2********************************************************************************
4@brief Logging formatter for colored log in terminal.
5********************************************************************************
9from logging
import LogRecord
10from typing
import Optional, Any
11from types
import TracebackType
12from colorama
import just_fix_windows_console
13just_fix_windows_console()
25S_LOG_MSG_FORMAT_WO_LINENO_WO_THREADS =
"%(asctime)s [%(name)s][%(levelname)s] %(message)s"
26S_LOG_MSG_FORMAT_WO_LINENO_W_THREADS =
"%(asctime)s [%(name)s][%(threadName)s][%(levelname)s] %(message)s"
27S_LOG_MSG_FORMAT_W_LINENO_WO_THREADS =
"%(asctime)s [%(name)s:%(lineno)d][%(levelname)s] %(message)s"
28S_LOG_MSG_FORMAT_W_LINENO_W_THREADS =
"%(asctime)s [%(name)s:%(lineno)d][%(threadName)s][%(levelname)s] %(message)s"
29S_LOG_DATE_FORMAT =
"%Y-%m-%d %H:%M:%S"
32def get_format(line_no: bool =
False, threads: bool =
False) -> str:
34 @brief Get the configurable log format string
35 @param line_no : include line number in log string
36 @param threads : include thread name in log string
37 @return log format string
39 if not line_no
and not threads:
40 msg_format = S_LOG_MSG_FORMAT_WO_LINENO_WO_THREADS
41 elif not line_no
and threads:
42 msg_format = S_LOG_MSG_FORMAT_WO_LINENO_W_THREADS
43 elif line_no
and not threads:
44 msg_format = S_LOG_MSG_FORMAT_W_LINENO_WO_THREADS
45 elif line_no
and threads:
46 msg_format = S_LOG_MSG_FORMAT_W_LINENO_W_THREADS
48 raise ValueError(
"No valid format found")
54 @brief Initializes logging for console output.
55 Line numbers are active in DEBUG level or lower.
56 @param level : root log level
57 @param threads : include thread names in log strings
59 root_logger = logging.getLogger()
60 root_logger.setLevel(level)
61 stream_handler = logging.StreamHandler()
62 line_no = bool(level == logging.DEBUG)
63 date_format = S_LOG_DATE_FORMAT
if (level != logging.DEBUG)
else None
64 stream_handler.setFormatter(
ColorFormatter(line_no=line_no, threads=threads, data_format=date_format))
65 root_logger.handlers.clear()
66 root_logger.addHandler(stream_handler)
71 @brief Logging formatter that colors logging messages depending on their level
72 @param fmt : [optional] overwrite format with a complete custom log format -> ignores all other parameters
73 @param line_no : [optional] include line number in log format string
74 @param threads : [optional] include thread names in log format string
75 @param data_format : [optional] date format
78 fg_yellow =
"\033[33m"
83 def __init__(self, fmt: Optional[str] =
None, line_no: bool =
True, threads: bool =
False, data_format: Optional[str] =
None, **kwargs: Any) ->
None:
85 msg_format = fmt
if fmt
else get_format(line_no=line_no, threads=threads)
88 logging.INFO: self.
reset + msg_format,
90 logging.ERROR: self.
fg_red + msg_format + self.
reset,
91 logging.CRITICAL: self.
bg_red + msg_format + self.
reset
95 def format(self, record: LogRecord) -> str:
97 @brief Overwrite format method of logging.Formatter to use colors formatting
98 @param record : log record
99 @return formatted log record
101 log_fmt = self.
d_formats.get(record.levelno)
102 formatter = logging.Formatter(fmt=log_fmt, datefmt=self.
data_format)
103 return formatter.format(record)
105 def formatException(self, ei: tuple[type[BaseException], BaseException, TracebackType |
None] | tuple[
None,
None,
None]) -> str:
107 @brief Overwrite formatException method of logging. Formatter to use critical color formatting
108 @param ei : exception info
109 @return formatted exception log record
111 log_fmt = self.
d_formats.get(logging.CRITICAL)
112 formatter = logging.Formatter(log_fmt, datefmt=self.
data_format)
114 return formatter.format(record)
117if __name__ ==
"__main__":
118 log = logging.getLogger(__name__)
119 init_console_logging(logging.DEBUG)
122 log.warning(
"Warning")
124 log.critical(
"Critical")
None init_console_logging(int level, bool threads=False)
Initializes logging for console output.
str get_format(bool line_no=False, bool threads=False)
Get the configurable log format string.