YouTubeDownloader v1.1.2
YouTube content downloader
Loading...
Searching...
No Matches
colored_log.py
Go to the documentation of this file.
1"""!
2********************************************************************************
3@file colored_log.py
4@brief Logging formatter for colored log in terminal.
5********************************************************************************
6"""
7
8import logging
9from logging import LogRecord
10from typing import Optional, Any
11from types import TracebackType
12from colorama import just_fix_windows_console
13just_fix_windows_console()
14
15# Possible Log Level:
16# CRITICAL = 50
17# FATAL = CRITICAL
18# ERROR = 40
19# WARNING = 30
20# WARN = WARNING
21# INFO = 20
22# DEBUG = 10
23# NOTSET = 0
24
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"
30
31
32def get_format(line_no: bool = False, threads: bool = False) -> str:
33 """!
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
38 """
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
47 else:
48 raise ValueError("No valid format found")
49 return msg_format
50
51
52def init_console_logging(level: int, threads: bool = False) -> None:
53 """!
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
58 """
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)
67
68
69class ColorFormatter(logging.Formatter):
70 """!
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
76 """
77 fg_grey = "\033[90m"
78 fg_yellow = "\033[33m"
79 fg_red = "\033[31m"
80 bg_red = "\033[41m"
81 reset = "\033[0m"
82
83 def __init__(self, fmt: Optional[str] = None, line_no: bool = True, threads: bool = False, data_format: Optional[str] = None, **kwargs: Any) -> None:
84 super().__init__(fmt, **kwargs)
85 msg_format = fmt if fmt else get_format(line_no=line_no, threads=threads)
86 self.d_formats = {
87 logging.DEBUG: self.fg_grey + msg_format + self.reset,
88 logging.INFO: self.reset + msg_format,
89 logging.WARNING: self.fg_yellow + msg_format + self.reset,
90 logging.ERROR: self.fg_red + msg_format + self.reset,
91 logging.CRITICAL: self.bg_red + msg_format + self.reset
92 }
93 self.data_format = data_format
94
95 def format(self, record: LogRecord) -> str:
96 """!
97 @brief Overwrite format method of logging.Formatter to use colors formatting
98 @param record : log record
99 @return formatted log record
100 """
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)
104
105 def formatException(self, ei: tuple[type[BaseException], BaseException, TracebackType | None] | tuple[None, None, None]) -> str:
106 """!
107 @brief Overwrite formatException method of logging. Formatter to use critical color formatting
108 @param ei : exception info
109 @return formatted exception log record
110 """
111 log_fmt = self.d_formats.get(logging.CRITICAL)
112 formatter = logging.Formatter(log_fmt, datefmt=self.data_format)
113 record = super().formatException(ei)
114 return formatter.format(record) # type: ignore
115
116
117if __name__ == "__main__":
118 log = logging.getLogger(__name__)
119 init_console_logging(logging.DEBUG)
120 log.debug("Debug")
121 log.info("Info")
122 log.warning("Warning")
123 log.error("Error")
124 log.critical("Critical")
Logging formatter that colors logging messages depending on their level.
None __init__(self, Optional[str] fmt=None, bool line_no=True, bool threads=False, Optional[str] data_format=None, **Any kwargs)
str format(self, LogRecord record)
Overwrite format method of logging.Formatter to use colors formatting.
str formatException(self, tuple[type[BaseException], BaseException, TracebackType|None]|tuple[None, None, None] ei)
Overwrite formatException method of logging.
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.