blob: 49385f1cc5dd4ad647f1d11952ed416e21db52b9 [file] [log] [blame]
Zhuoyao Zhangc0190662024-10-03 22:03:47 +00001# Copyright 2024, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import argparse
16import logging
17import os
18import signal
19import sys
20import tempfile
21
22from edit_monitor import daemon_manager
23from edit_monitor import edit_monitor
24
25
26def create_arg_parser():
27 """Creates an instance of the default arg parser."""
28
29 parser = argparse.ArgumentParser(
30 description=(
31 'Monitors edits in Android source code and uploads the edit logs.'
32 ),
33 add_help=True,
34 formatter_class=argparse.RawDescriptionHelpFormatter,
35 )
36
37 parser.add_argument(
38 '--path',
39 type=str,
40 required=True,
41 help='Root path to monitor the edit events.',
42 )
43
44 parser.add_argument(
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +000045 '--dry_run',
46 action='store_true',
47 help='Dry run the edit monitor. This starts the edit monitor process without actually send the edit logs to clearcut.',
48 )
49
50 parser.add_argument(
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000051 '--force_cleanup',
52 action='store_true',
53 help=(
54 'Instead of start a new edit monitor, force stop all existing edit'
55 ' monitors in the system. This option is only used in emergent cases'
56 ' when we want to prevent user damage by the edit monitor.'
57 ),
58 )
59
Zhuoyao Zhang64ad75f2024-10-25 00:21:45 +000060 parser.add_argument(
61 '--verbose',
62 action='store_true',
63 help=(
64 'Log verbose info in the log file for debugging purpose.'
65 ),
66 )
67
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000068 return parser
69
70
Zhuoyao Zhang64ad75f2024-10-25 00:21:45 +000071def configure_logging(verbose=False):
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000072 root_logging_dir = tempfile.mkdtemp(prefix='edit_monitor_')
73 _, log_path = tempfile.mkstemp(dir=root_logging_dir, suffix='.log')
74
75 log_fmt = '%(asctime)s %(filename)s:%(lineno)s:%(levelname)s: %(message)s'
76 date_fmt = '%Y-%m-%d %H:%M:%S'
Zhuoyao Zhang64ad75f2024-10-25 00:21:45 +000077 log_level = logging.DEBUG if verbose else logging.INFO
78
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000079 logging.basicConfig(
Zhuoyao Zhang64ad75f2024-10-25 00:21:45 +000080 filename=log_path, level=log_level, format=log_fmt, datefmt=date_fmt
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000081 )
Zhuoyao Zhang0597a9d2024-10-04 21:11:18 +000082 # Filter out logs from inotify_buff to prevent log pollution.
83 logging.getLogger('watchdog.observers.inotify_buffer').addFilter(
84 lambda record: record.filename != 'inotify_buffer.py')
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000085 print(f'logging to file {log_path}')
86
87
88def term_signal_handler(_signal_number, _frame):
89 logging.info('Process %d received SIGTERM, Terminating...', os.getpid())
90 sys.exit(0)
91
92
93def main(argv: list[str]):
94 args = create_arg_parser().parse_args(argv[1:])
Zhuoyao Zhang64ad75f2024-10-25 00:21:45 +000095 configure_logging(args.verbose)
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +000096 if args.dry_run:
97 logging.info('This is a dry run.')
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000098 dm = daemon_manager.DaemonManager(
99 binary_path=argv[0],
100 daemon_target=edit_monitor.start,
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +0000101 daemon_args=(args.path, args.dry_run),
Zhuoyao Zhangc0190662024-10-03 22:03:47 +0000102 )
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +0000103
Zhuoyao Zhangc0190662024-10-03 22:03:47 +0000104 if args.force_cleanup:
105 dm.cleanup()
106
107 try:
108 dm.start()
109 dm.monitor_daemon()
110 except Exception:
111 logging.exception('Unexpected exception raised when run daemon.')
112 finally:
113 dm.stop()
114
115
116if __name__ == '__main__':
117 signal.signal(signal.SIGTERM, term_signal_handler)
Zhuoyao Zhangc0190662024-10-03 22:03:47 +0000118 main(sys.argv)