]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/helpers/logging.py
hardware_manager: Validate upgrade zips against the saved ota channel
[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 try:
73 os.chmod(args.log, 0o666)
74 except PermissionError:
75 pass
76 else:
77 setattr(args, "logfd", open(os.devnull, "a+"))
78 if args.action != "init":
79 print("WARNING: Can't create log file in '" + dir + "', path"
80 " does not exist!")
81
82 # Set log format
83 root_logger = logging.getLogger()
84 root_logger.handlers = []
85 formatter = logging.Formatter("[%(asctime)s] %(message)s",
86 datefmt="%H:%M:%S")
87
88 # Set log level
89 add_verbose_log_level()
90 root_logger.setLevel(logging.DEBUG)
91 if args.verbose:
92 root_logger.setLevel(logging.VERBOSE)
93
94 # Add a custom log handler
95 handler = log_handler()
96 log_handler._args = args
97 handler.setFormatter(formatter)
98 root_logger.addHandler(handler)
99
100
101 def disable():
102 logger = logging.getLogger()
103 logger.disabled = True