blob: 6af421b1f354e088596d5722c15c62fc7be7d9aa [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
60 return parser
61
62
63def configure_logging():
64 root_logging_dir = tempfile.mkdtemp(prefix='edit_monitor_')
65 _, log_path = tempfile.mkstemp(dir=root_logging_dir, suffix='.log')
66
67 log_fmt = '%(asctime)s %(filename)s:%(lineno)s:%(levelname)s: %(message)s'
68 date_fmt = '%Y-%m-%d %H:%M:%S'
69 logging.basicConfig(
70 filename=log_path, level=logging.DEBUG, format=log_fmt, datefmt=date_fmt
71 )
Zhuoyao Zhang0597a9d2024-10-04 21:11:18 +000072 # Filter out logs from inotify_buff to prevent log pollution.
73 logging.getLogger('watchdog.observers.inotify_buffer').addFilter(
74 lambda record: record.filename != 'inotify_buffer.py')
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000075 print(f'logging to file {log_path}')
76
77
78def term_signal_handler(_signal_number, _frame):
79 logging.info('Process %d received SIGTERM, Terminating...', os.getpid())
80 sys.exit(0)
81
82
83def main(argv: list[str]):
84 args = create_arg_parser().parse_args(argv[1:])
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +000085 if args.dry_run:
86 logging.info('This is a dry run.')
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000087 dm = daemon_manager.DaemonManager(
88 binary_path=argv[0],
89 daemon_target=edit_monitor.start,
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +000090 daemon_args=(args.path, args.dry_run),
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000091 )
Zhuoyao Zhang7f22db82024-10-17 17:40:34 +000092
Zhuoyao Zhangc0190662024-10-03 22:03:47 +000093 if args.force_cleanup:
94 dm.cleanup()
95
96 try:
97 dm.start()
98 dm.monitor_daemon()
99 except Exception:
100 logging.exception('Unexpected exception raised when run daemon.')
101 finally:
102 dm.stop()
103
104
105if __name__ == '__main__':
106 signal.signal(signal.SIGTERM, term_signal_handler)
107 configure_logging()
108 main(sys.argv)