-
Notifications
You must be signed in to change notification settings - Fork 19
/
logging.py
97 lines (78 loc) · 2.75 KB
/
logging.py
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
import logging
from .notifier import Notifier
from .global_notifier import get_global_notifier
def _log_record_attrs():
record = logging.LogRecord("", logging.ERROR, "", 0, "", None, None)
attrs = set()
for k in vars(record).keys():
attrs.add(k)
attrs.add("message") # set by Formatter
return attrs
_LOG_RECORD_ATTRS = _log_record_attrs()
_LOG_RECORD_ATTRS_TO_COPY = [
"created",
"msecs",
"process",
"processName",
"relativeCreated",
"thread",
"threadName",
]
class LoggingHandler(logging.Handler):
def __init__(self, notifier=None, level=logging.ERROR, **kwargs):
logging.Handler.__init__(self, level=level)
if notifier is None:
notifier = get_global_notifier() or Notifier(**kwargs)
self._notifier = notifier
def emit(self, record):
try:
notice = self.build_notice(record)
self._notifier.send_notice(notice)
except Exception: # pylint: disable=broad-except
self.handleError(record)
def build_notice(self, record):
notice = self._notifier.build_notice(None)
notice["errors"].append(self._build_error(record))
self._update_context(notice["context"], record)
self._update_params(notice["params"], record)
return notice
def _build_error(self, record):
if record.exc_info:
return self._build_error_from_exc_info(record.exc_info)
error = dict(
type=record.name,
message=record.msg,
backtrace=self._build_backtrace(record),
)
return error
def _build_error_from_exc_info(self, exc_info):
cls, err, tb = exc_info
backtrace = self._notifier._build_backtrace_tb(tb)
error = dict(type=cls.__name__, message=str(err), backtrace=backtrace)
return error
def _build_backtrace(self, record):
frame = self._notifier._frame_with_code(
record.pathname, record.funcName, record.lineno
)
backtrace = [frame]
return backtrace
def _update_context(self, context, record):
context["severity"] = record.levelname
context["component"] = record.module
def _update_params(self, params, record):
extra = self._build_extra(record)
if extra is not None:
params["extra"] = extra
for attr in _LOG_RECORD_ATTRS_TO_COPY:
v = getattr(record, attr)
if v is not None:
params[attr] = v
def _build_extra(self, record):
extra = None
for k, v in vars(record).items():
if k not in _LOG_RECORD_ATTRS:
if extra is None:
extra = {k: v}
else:
extra[k] = v
return extra