]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/helpers/logging.py
Policies have been adjusted for Android 11.
[waydroid.git] / tools / helpers / logging.py
1 # Copyright 2021 Oliver Smith
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 import logging
4 import os
5 import sys
6
7
8 class log_handler(logging.StreamHandler):
9 """
10 Write to stdout and to the already opened log file.
11 """
12 _args = None
13
14 def emit(self, record):
15 try:
16 msg = self.format(record)
17
18 # INFO or higher: Write to stdout
19 if (not self._args.details_to_stdout and
20 not self._args.quiet and
21 record.levelno >= logging.INFO):
22 stream = self.stream
23 stream.write(msg)
24 stream.write(self.terminator)
25 self.flush()
26
27 # Everything: Write to logfd
28 msg = "(" + str(os.getpid()).zfill(6) + ") " + msg
29 self._args.logfd.write(msg + "\n")
30 self._args.logfd.flush()
31
32 except (KeyboardInterrupt, SystemExit):
33 raise
34 except BaseException:
35 self.handleError(record)
36
37
38 def add_verbose_log_level():
39 """
40 Add a new log level "verbose", which is below "debug". Also monkeypatch
41 logging, so it can be used with logging.verbose().
42
43 This function is based on work by Voitek Zylinski and sleepycal:
44 https://stackoverflow.com/a/20602183
45 All stackoverflow user contributions are licensed as CC-BY-SA:
46 https://creativecommons.org/licenses/by-sa/3.0/
47 """
48 logging.VERBOSE = 5
49 logging.addLevelName(logging.VERBOSE, "VERBOSE")
50 logging.Logger.verbose = lambda inst, msg, * \
51 args, **kwargs: inst.log(logging.VERBOSE, msg, *args, **kwargs)
52 logging.verbose = lambda msg, *args, **kwargs: logging.log(logging.VERBOSE,
53 msg, *args,
54 **kwargs)
55
56
57 def init(args):
58 """
59 Set log format and add the log file descriptor to args.logfd, add the
60 verbose log level.
61 """
62 # Set log file descriptor (logfd)
63 if args.details_to_stdout:
64 setattr(args, "logfd", sys.stdout)
65 else:
66 # Require containing directory to exist (so we don't create the work
67 # folder and break the folder migration logic, which needs to set the
68 # version upon creation)
69 dir = os.path.dirname(args.log)
70 if os.path.exists(dir):
71 setattr(args, "logfd", open(args.log, "a+"))
72 else:
73 setattr(args, "logfd", open(os.devnull, "a+"))
74 if args.action != "init":
75 print("WARNING: Can't create log file in '" + dir + "', path"
76 " does not exist!")
77
78 # Set log format
79 root_logger = logging.getLogger()
80 root_logger.handlers = []
81 formatter = logging.Formatter("[%(asctime)s] %(message)s",
82 datefmt="%H:%M:%S")
83
84 # Set log level
85 add_verbose_log_level()
86 root_logger.setLevel(logging.DEBUG)
87 if args.verbose:
88 root_logger.setLevel(logging.VERBOSE)
89
90 # Add a custom log handler
91 handler = log_handler()
92 log_handler._args = args
93 handler.setFormatter(formatter)
94 root_logger.addHandler(handler)
95
96
97 def disable():
98 logger = logging.getLogger()
99 logger.disabled = True