ATLAS Offline Software
Loading...
Searching...
No Matches
logger.py
Go to the documentation of this file.
1# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2
3import os
4import logging
5from contextlib import contextmanager
6
7
8VERBOSE_LEVEL = 15
9logging.addLevelName(VERBOSE_LEVEL, "VERBOSE")
10
11# Rename critical to FATAL.
12logging.addLevelName(logging.CRITICAL, "FATAL")
13
14# The background is set with 40 plus the number of the color, and the foreground with 30
15RED, YELLOW, BLUE, WHITE = 1, 3, 4, 7
16
17# These are the sequences need to get colored ouput
18RESET_SEQ = "\033[0m"
19COLOR_SEQ = "\033[1;%dm"
20BOLD_SEQ = "\033[1m"
21
22def insert_seqs(message):
23 return message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ)
24
25COLORS = {
26 'DEBUG' : BLUE,
27 'VERBOSE' : WHITE,
28 'INFO' : YELLOW,
29 'WARNING' : YELLOW,
30 'ERROR' : RED,
31 'FATAL' : RED,
32}
33
34
35class ColoredFormatter(logging.Formatter):
36 def __init__(self, msg, use_color=True):
37 logging.Formatter.__init__(self, msg)
38 self.use_color = use_color
39
40 def format(self, record):
41 levelname = record.levelname
42 if self.use_color and levelname in COLORS:
43 color_seq = COLOR_SEQ % (30 + COLORS[levelname])
44 record.levelname = color_seq + levelname + RESET_SEQ
45 return logging.Formatter.format(self, record)
46
47
48LoggerClass = logging.getLoggerClass()
49@logging.setLoggerClass
50class ExtendedLogger(LoggerClass):
51 def __init__(self, *args, **kwargs):
52 LoggerClass.__init__(self, *args, **kwargs)
53 if hasattr (logging, '_levelNames'):
54 self.__dict__.update(logging._levelNames)
55 if hasattr (logging, '_nameToLevel'):
56 self.__dict__.update(logging._nameToLevel)
57 if hasattr (logging, '_levelToName'):
58 self.__dict__.update(logging._levelToName)
59
60 def verbose(self, *args):
61 self.log(VERBOSE_LEVEL, *args)
62
63 def fatal(self, *args):
64 self.critical(*args)
65
66
67def get_log_handler(singleton={}):
68 """
69 Return the STDOUT handler singleton used for all logging.
70 """
71 if "value" in singleton:
72 return singleton["value"]
73
74 handler = logging.StreamHandler()
75 if os.isatty(handler.stream.fileno()):
76 FORMAT = "[%(asctime)s][$BOLD%(name)-20s$RESET][%(levelname)-18s] %(message)s"
77 handler.setFormatter(ColoredFormatter(insert_seqs(FORMAT)))
78
79 # Make the top level logger and make it as verbose as possible.
80 # The log messages which make it to the screen are controlled by the handler
81 log = logging.getLogger()
82 log.addHandler(handler)
83 log.setLevel(logging.DEBUG)
84
85 singleton["value"] = handler
86 return handler
87
88@contextmanager
89def log_level(level):
90 """
91 A log level context manager. Changes the log level for the duration.
92 """
93 handler = get_log_handler()
94 old_level = handler.level
95 try:
96 handler.setLevel(level)
97 yield
98 finally:
99 handler.setLevel(old_level)
100
101def get_level_for_opts(verbose, quiet):
102 if quiet:
103 log_level = logging.WARNING
104 elif not verbose:
105 log_level = logging.INFO
106 elif verbose == 1:
107 log_level = VERBOSE_LEVEL
108 elif verbose > 1:
109 log_level = logging.DEBUG
110
111 return log_level
112
113def init_logger(verbose=False, quiet=False):
114 """
115 This function should be called only by programs (not by libraries)
116 """
117 handler = get_log_handler()
118 handler.setLevel(get_level_for_opts(verbose, quiet))
__init__(self, msg, use_color=True)
Definition logger.py:36
__init__(self, *args, **kwargs)
Definition logger.py:51
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310
bool verbose
Definition hcg.cxx:73
get_level_for_opts(verbose, quiet)
Definition logger.py:101
insert_seqs(message)
Definition logger.py:22
get_log_handler(singleton={})
Definition logger.py:67
log_level(level)
Definition logger.py:89
init_logger(verbose=False, quiet=False)
Definition logger.py:113