Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_cli / py / pw_cli / log.py
1 # Copyright 2020 The Pigweed Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 # use this file except in compliance with the License. You may obtain a copy of
5 # the License at
6 #
7 #     https://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, WITHOUT
11 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 # License for the specific language governing permissions and limitations under
13 # the License.
14 """Configure the system logger for the default pw command log format."""
15
16 import logging
17 from pathlib import Path
18 from typing import NamedTuple, Union
19
20 import pw_cli.color
21 import pw_cli.env
22 import pw_cli.plugins
23
24 # Log level used for captured output of a subprocess run through pw.
25 LOGLEVEL_STDOUT = 21
26
27
28 class LogLevel(NamedTuple):
29     level: int
30     color: str
31     ascii: str
32     emoji: str
33
34
35 # Shorten all the log levels to 3 characters for column-aligned logs.
36 # Color the logs using ANSI codes.
37 _LOG_LEVELS = (
38     LogLevel(logging.CRITICAL, 'bold_red', 'CRT', '☠️ '),
39     LogLevel(logging.ERROR,    'red',      'ERR', '❌'),
40     LogLevel(logging.WARNING,  'yellow',   'WRN', '⚠️ '),
41     LogLevel(logging.INFO,     'magenta',  'INF', 'ℹ️ '),
42     LogLevel(LOGLEVEL_STDOUT,  'cyan',     'OUT', '💬'),
43     LogLevel(logging.DEBUG,    'blue',     'DBG', '👾'),
44 )  # yapf: disable
45
46 _LOG = logging.getLogger(__name__)
47 _STDERR_HANDLER = logging.StreamHandler()
48
49
50 def main() -> None:
51     """Show how logs look at various levels."""
52
53     # Force the log level to make sure all logs are shown.
54     _LOG.setLevel(logging.DEBUG)
55
56     # Log one message for every log level.
57     _LOG.critical('Something terrible has happened!')
58     _LOG.error('There was an error on our last operation')
59     _LOG.warning('Looks like something is amiss; consider investigating')
60     _LOG.info('The operation went as expected')
61     _LOG.log(LOGLEVEL_STDOUT, 'Standard output of subprocess')
62     _LOG.debug('Adding 1 to i')
63
64
65 def install(level: int = logging.INFO,
66             use_color: bool = None,
67             hide_timestamp: bool = False,
68             log_file: Union[str, Path] = None) -> None:
69     """Configure the system logger for the default pw command log format."""
70
71     colors = pw_cli.color.colors(use_color)
72
73     env = pw_cli.env.pigweed_environment()
74     if env.PW_SUBPROCESS or hide_timestamp:
75         # If the logger is being run in the context of a pw subprocess, the
76         # time and date are omitted (since pw_cli.process will provide them).
77         timestamp_fmt = ''
78     else:
79         # This applies a gray background to the time to make the log lines
80         # distinct from other input, in a way that's easier to see than plain
81         # colored text.
82         timestamp_fmt = colors.black_on_white('%(asctime)s') + ' '
83
84     # Set log level on root logger to debug, otherwise any higher levels
85     # elsewhere are ignored.
86     root = logging.getLogger()
87     root.setLevel(logging.DEBUG)
88
89     handler = logging.FileHandler(log_file) if log_file else _STDERR_HANDLER
90     handler.setLevel(level)
91     handler.setFormatter(
92         logging.Formatter(timestamp_fmt + '%(levelname)s %(message)s',
93                           '%Y%m%d %H:%M:%S'))
94     root.addHandler(handler)
95
96     if env.PW_EMOJI:
97         name_attr = 'emoji'
98         colorize = lambda ll: str
99     else:
100         name_attr = 'ascii'
101         colorize = lambda ll: getattr(colors, ll.color)
102
103     for log_level in _LOG_LEVELS:
104         name = getattr(log_level, name_attr)
105         logging.addLevelName(log_level.level, colorize(log_level)(name))
106
107
108 def set_level(log_level: int):
109     """Sets the log level for logs to stderr."""
110     _STDERR_HANDLER.setLevel(log_level)
111
112
113 if __name__ == '__main__':
114     install()
115     main()