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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# Copyright 2018 ke liang <lokyse@163.com>.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
from .markerFormatter import MarkerFormatter
from .utils import is_above_python_2_7, is_above_python_3_2
class MDCFormatter(MarkerFormatter):
"""
A custom MDC formatter to prepare Mapped Diagnostic Context
to enrich log message.
"""
def __init__(self, fmt=None, mdcfmt=None,
datefmt=None, colorfmt=None, style="%"):
"""
:param fmt: build-in format string contains standard
Python %-style mapping keys
:param mdcFmt: mdc format with '{}'-style mapping keys
:param datefmt: Date format to use
:param colorfmt: colored output with ANSI escape code on terminal
:param style: style mapping keys in python3
"""
if is_above_python_3_2():
super(MDCFormatter, self).__init__(fmt=fmt,
datefmt=datefmt,
colorfmt=colorfmt,
style=style)
elif is_above_python_2_7():
super(MDCFormatter, self).__init__(fmt=fmt,
datefmt=datefmt,
colorfmt=colorfmt)
else:
MarkerFormatter.__init__(self, fmt, datefmt, colorfmt)
self._mdc_tag = "%(mdc)s"
if self.style == "{":
self._mdc_tag = "{mdc}"
elif self.style == "$":
self._mdc_tag = "${mdc}"
if mdcfmt:
self._mdcFmt = mdcfmt
else:
self._mdcFmt = '{reqeustID}'
def _mdcfmtKey(self):
"""
maximum barce match algorithm to find the mdc key
:return: key in brace and key not in brace,such as ({key}, key)
"""
left = '{'
right = '}'
target = self._mdcFmt
st = []
keys = []
for index, v in enumerate(target):
if v == left:
st.append(index)
elif v == right:
if len(st) == 0:
continue
elif len(st) == 1:
start = st.pop()
end = index
keys.append(target[start:end + 1])
elif len(st) > 0:
st.pop()
keys = list(filter(lambda x: x[1:-1].strip('\n \t ') != "", keys))
words = None
if keys:
words = map(lambda x: x[1:-1], keys)
return keys, words
def _replaceStr(self, keys):
fmt = self._mdcFmt
for i in keys:
fmt = fmt.replace(i, i[1:-1] + "=" + i)
return fmt
def format(self, record):
"""
Find mdcs in log record extra field, if key form mdcFmt dosen't
contains mdcs, the values will be empty.
:param record: the logging record instance
:return: string
for example:
the mdcs dict in logging record is
{'key1':'value1','key2':'value2'}
the mdcFmt is" '{key1} {key3}'
the output of mdc message: 'key1=value1 key3='
"""
mdcIndex = self._fmt.find(self._mdc_tag)
if mdcIndex == -1:
if is_above_python_2_7():
return super(MDCFormatter, self).format(record)
else:
return MarkerFormatter.format(self, record)
mdcFmtkeys, mdcFmtWords = self._mdcfmtKey()
if mdcFmtWords is None:
self._fmt = self._fmt.replace(self._mdc_tag, "")
if is_above_python_3_2():
self._style = logging._STYLES[self.style][0](self._fmt)
if is_above_python_2_7():
return super(MDCFormatter, self).format(record)
else:
return MarkerFormatter.format(self, record)
mdc = record.__dict__.get('mdc', None)
res = {}
for i in mdcFmtWords:
if mdc and i in mdc:
res[i] = mdc[i]
else:
res[i] = ""
del mdc
try:
mdcstr = self._replaceStr(keys=mdcFmtkeys).format(**res)
self._fmt = self._fmt.replace(self._mdc_tag, mdcstr)
if is_above_python_3_2():
self._style = logging._STYLES[self.style][0](self._fmt)
if is_above_python_2_7():
return super(MDCFormatter, self).format(record)
else:
return MarkerFormatter.format(self, record)
except KeyError as e:
print("The mdc key %s format is wrong" % str(e))
except Exception:
raise
|