-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathlogger.py
More file actions
110 lines (88 loc) · 3.5 KB
/
Copy pathlogger.py
File metadata and controls
110 lines (88 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import logging
from termcolor import colored
from functools import partial, partialmethod
class ColorfulFormatter(logging.Formatter):
COLORS = {
"DEBUG": {"color": "black", "attrs": []},
"INFO": {"color": "blue", "attrs": []},
"WARNING": {"color": "yellow", "attrs": []},
"ERROR": {"color": "red", "attrs": []},
"CRITICAL": {"color": "red", "attrs": []},
"SUCCESS": {"color": "green", "attrs": []},
}
def format(self, record):
log_level = record.levelname
msg = super().format(record)
return colored(
msg,
self.COLORS.get(log_level)["color"],
attrs=self.COLORS.get(log_level)["attrs"],
)
def add_logging_level(level_name, level_num, method_name=None):
"""
Comprehensively adds a new logging level to the `logging` module and the
currently configured logging class.
`level_name` becomes an attribute of the `logging` module with the value
`level_num`.
`methodName` becomes a convenience method for both `logging` itself
and the class returned by `logging.getLoggerClass()` (usually just
`logging.Logger`).
If `methodName` is not specified, `levelName.lower()` is used.
To avoid accidental clobberings of existing attributes, this method will
raise an `AttributeError` if the level name is already an attribute of the
`logging` module or if the method name is already present
Example
-------
>>> add_logging_level('TRACE', logging.DEBUG - 5)
>>> logging.getLogger(__name__).setLevel('TRACE')
>>> logging.getLogger(__name__).trace('that worked')
>>> logging.trace('so did this')
>>> logging.TRACE
5
"""
if not method_name:
method_name = level_name.lower()
if hasattr(logging, level_name):
raise AttributeError(f"{level_name} already defined in logging module")
if hasattr(logging, method_name):
raise AttributeError(
f"{method_name} already defined in logging module"
)
if hasattr(logging.getLoggerClass(), method_name):
raise AttributeError(f"{method_name} already defined in logger class")
# This method was inspired by the answers to Stack Overflow post
# http://stackoverflow.com/q/2183233/2988730, especially
# https://stackoverflow.com/a/35804945
# https://stackoverflow.com/a/55276759
logging.addLevelName(level_num, level_name)
setattr(logging, level_name, level_num)
setattr(
logging.getLoggerClass(),
method_name,
partialmethod(logging.getLoggerClass().log, level_num),
)
setattr(logging, method_name, partial(logging.log, level_num))
def setup_logger(name=__name__):
logging.getLogger().setLevel(logging.CRITICAL)
logger = logging.getLogger(name)
logger.setLevel(logging.CRITICAL)
if logger.hasHandlers():
logger.handlers.clear()
try:
add_logging_level("SUCCESS", 25)
except AttributeError as e:
logger.debug(e)
# Create console handler
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# Create formatter and add it to the handlers
format_str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
formatter = ColorfulFormatter(format_str, datefmt="%Y-%m-%d %H:%M:%S")
ch.setFormatter(formatter)
# Add the handlers to the logger
logger.addHandler(ch)
# prevent propagation of log messages to parent logger
logger.propagate = False
# disable root logger
logging.getLogger().handlers = []
return logger