python-json-logger 2.0.7__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_json_logger-2.0.7.dist-info → python_json_logger-3.0.0.dist-info}/LICENSE +1 -1
- {python_json_logger-2.0.7.dist-info → python_json_logger-3.0.0.dist-info}/METADATA +61 -37
- python_json_logger-3.0.0.dist-info/RECORD +8 -0
- {python_json_logger-2.0.7.dist-info → python_json_logger-3.0.0.dist-info}/WHEEL +1 -1
- pythonjsonlogger/jsonlogger.py +132 -74
- python_json_logger-2.0.7.dist-info/RECORD +0 -8
- {python_json_logger-2.0.7.dist-info → python_json_logger-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2011, Zakaria Zajac
|
|
1
|
+
Copyright (c) 2011, Zakaria Zajac and the python-json-logger Contributors
|
|
2
2
|
All rights reserved.
|
|
3
3
|
|
|
4
4
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
@@ -1,58 +1,78 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-json-logger
|
|
3
|
-
Version:
|
|
4
|
-
Summary:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: JSON Log Formatter for the Python Logging Package
|
|
5
|
+
Author-email: Zakaria Zajac <zak@madzak.com>
|
|
6
|
+
Maintainer-email: Nicholas Hairs <info+python-json-logger@nicholashairs.com>
|
|
7
|
+
License: BSD-2-Clause License
|
|
8
|
+
Project-URL: GitHub, https://github.com/nhairs/python-json-logger
|
|
9
9
|
Classifier: Development Status :: 6 - Mature
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: BSD License
|
|
12
12
|
Classifier: Operating System :: OS Independent
|
|
13
|
-
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.7
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.8
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.9
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
20
|
Classifier: Topic :: System :: Logging
|
|
22
|
-
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
License-File: LICENSE
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
Provides-Extra: lint
|
|
26
|
+
Requires-Dist: validate-pyproject[all] ; extra == 'lint'
|
|
27
|
+
Requires-Dist: black ; extra == 'lint'
|
|
28
|
+
Requires-Dist: pylint ; extra == 'lint'
|
|
29
|
+
Requires-Dist: mypy ; extra == 'lint'
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: pytest ; extra == 'test'
|
|
32
|
+
|
|
33
|
+

|
|
27
34
|
[](https://pypi.python.org/pypi/python-json-logger/)
|
|
28
35
|
[](https://pypi.python.org/pypi/python-json-logger/)
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
# Python JSON Logger
|
|
38
|
+
|
|
32
39
|
This library is provided to allow standard python logging to output log data as json objects. With JSON we can make our logs more readable by machines and we can stop writing custom parsers for syslog type records.
|
|
33
40
|
|
|
34
|
-
News
|
|
35
|
-
=======
|
|
36
|
-
Hi, I see this package is quiet alive and I am sorry for ignoring it so long. I will be stepping up my maintenance of this package so please allow me a week to get things back in order (and most likely a new minor version) and I'll post and update here once I am caught up.
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
### 🚨 Important 🚨
|
|
43
|
+
|
|
44
|
+
This repository is a maintained fork of [madzak/python-json-logger](https://github.com/madzak/python-json-logger) pending [a PEP 541 request](https://github.com/pypi/support/issues/3607) for the PyPI package. The future direction of the project is being discussed [here](https://github.com/nhairs/python-json-logger/issues/1).
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
### Install via pip / PyPI
|
|
49
|
+
|
|
50
|
+
Until the PEP 541 request is complete you will need to use one of the alternative methods below.
|
|
51
|
+
|
|
52
|
+
### Install from GitHub
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
```shell
|
|
55
|
+
pip install 'python-json-logger@git+https://github.com/nhairs/python-json-logger.git'
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
To install a specific version:
|
|
43
59
|
|
|
44
|
-
|
|
60
|
+
```shell
|
|
61
|
+
pip install 'python-json-logger@git+https://github.com/nhairs/python-json-logger.git@v2.0.7'
|
|
62
|
+
```
|
|
45
63
|
|
|
46
|
-
https://pypi.python.org/pypi/python-json-logger
|
|
47
64
|
|
|
48
|
-
|
|
65
|
+
### Install from Source
|
|
49
66
|
|
|
50
|
-
|
|
67
|
+
```shell
|
|
68
|
+
git clone https://github.com/nhairs/python-json-logger.git
|
|
69
|
+
cd python-json-logger
|
|
70
|
+
pip install -e .
|
|
71
|
+
```
|
|
51
72
|
|
|
52
|
-
Usage
|
|
53
|
-
=====
|
|
73
|
+
## Usage
|
|
54
74
|
|
|
55
|
-
|
|
75
|
+
### Integrating with Python's logging framework
|
|
56
76
|
|
|
57
77
|
Json outputs are provided by the JsonFormatter logging formatter. You can add the custom formatter like below:
|
|
58
78
|
|
|
@@ -70,7 +90,7 @@ Json outputs are provided by the JsonFormatter logging formatter. You can add th
|
|
|
70
90
|
logger.addHandler(logHandler)
|
|
71
91
|
```
|
|
72
92
|
|
|
73
|
-
|
|
93
|
+
### Customizing fields
|
|
74
94
|
|
|
75
95
|
The fmt parser can also be overidden if you want to have required fields that differ from the default of just `message`.
|
|
76
96
|
|
|
@@ -112,7 +132,7 @@ formatter = CustomJsonFormatter('%(timestamp)s %(level)s %(name)s %(message)s')
|
|
|
112
132
|
|
|
113
133
|
Items added to the log record will be included in *every* log message, no matter what the format requires.
|
|
114
134
|
|
|
115
|
-
|
|
135
|
+
### Adding custom object serialization
|
|
116
136
|
|
|
117
137
|
For custom handling of object serialization you can specify default json object translator or provide a custom encoder
|
|
118
138
|
|
|
@@ -129,7 +149,7 @@ logger.info({"special": "value", "run": 12})
|
|
|
129
149
|
logger.info("classic message", extra={"special": "value", "run": 12})
|
|
130
150
|
```
|
|
131
151
|
|
|
132
|
-
|
|
152
|
+
### Using a Config File
|
|
133
153
|
|
|
134
154
|
To use the module with a config file using the [`fileConfig` function](https://docs.python.org/3/library/logging.config.html#logging.config.fileConfig), use the class `pythonjsonlogger.jsonlogger.JsonFormatter`. Here is a sample config file.
|
|
135
155
|
|
|
@@ -162,8 +182,7 @@ format = %(message)s
|
|
|
162
182
|
class = pythonjsonlogger.jsonlogger.JsonFormatter
|
|
163
183
|
```
|
|
164
184
|
|
|
165
|
-
Example Output
|
|
166
|
-
==============
|
|
185
|
+
## Example Output
|
|
167
186
|
|
|
168
187
|
Sample JSON with a full formatter (basically the log message from the unit test). Every log message will appear on 1 line like a typical logger.
|
|
169
188
|
|
|
@@ -191,9 +210,14 @@ Sample JSON with a full formatter (basically the log message from the unit test)
|
|
|
191
210
|
}
|
|
192
211
|
```
|
|
193
212
|
|
|
194
|
-
|
|
195
|
-
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
This project is licensed under the BSD 2 Clause License - see [`LICENSE`](https://github.com/nhairs/python-json-logger/blob/main/LICENSE)
|
|
216
|
+
|
|
217
|
+
## Authors and Maintainers
|
|
218
|
+
|
|
219
|
+
This project was originally authored by [Zakaria Zajac](https://github.com/madzak) and our wonderful [contributors](https://github.com/nhairs/python-json-logger/graphs/contributors)
|
|
196
220
|
|
|
197
|
-
|
|
221
|
+
It is currently maintained by:
|
|
198
222
|
|
|
199
|
-
- [
|
|
223
|
+
- [Nicholas Hairs](https://github.com/nhairs) - [nicholashairs.com](https://www.nicholashairs.com)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
pythonjsonlogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pythonjsonlogger/jsonlogger.py,sha256=dIKseexAUbEyJDQVjVrYY-gcJWn_T9sIzEFkaptHhmE,11255
|
|
3
|
+
pythonjsonlogger/py.typed,sha256=4RLptUHQuSqzK6CDbigff8uvWQjwPPQMxikWPkV4OtA,80
|
|
4
|
+
python_json_logger-3.0.0.dist-info/LICENSE,sha256=GOqVF546Xg4k62zhbED7--IxM8JQKTOi91-KPhoFW1Q,1329
|
|
5
|
+
python_json_logger-3.0.0.dist-info/METADATA,sha256=3tNA-gXRR5EooajrvPCV1Q2fg8VPkQsC-g2Y9sZY634,7508
|
|
6
|
+
python_json_logger-3.0.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
7
|
+
python_json_logger-3.0.0.dist-info/top_level.txt,sha256=9G-OsTkbwPgM8t-bXKPmWDBRZv9cbzLIiEDE5EnGk2I,17
|
|
8
|
+
python_json_logger-3.0.0.dist-info/RECORD,,
|
pythonjsonlogger/jsonlogger.py
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
"""
|
|
2
2
|
This library is provided to allow standard python logging
|
|
3
3
|
to output log data as JSON formatted strings
|
|
4
|
-
|
|
4
|
+
"""
|
|
5
|
+
|
|
5
6
|
import logging
|
|
6
7
|
import json
|
|
7
8
|
import re
|
|
8
|
-
from datetime import date, datetime, time, timezone
|
|
9
9
|
import traceback
|
|
10
10
|
import importlib
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
from datetime import date, datetime, time, timezone
|
|
12
|
+
import sys
|
|
13
|
+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
|
13
14
|
|
|
14
15
|
from inspect import istraceback
|
|
15
16
|
|
|
@@ -17,19 +18,45 @@ from collections import OrderedDict
|
|
|
17
18
|
|
|
18
19
|
# skip natural LogRecord attributes
|
|
19
20
|
# http://docs.python.org/library/logging.html#logrecord-attributes
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
# Changed in 3.0.0, is now list[str] instead of tuple[str, ...]
|
|
22
|
+
RESERVED_ATTRS: List[str] = [
|
|
23
|
+
"args",
|
|
24
|
+
"asctime",
|
|
25
|
+
"created",
|
|
26
|
+
"exc_info",
|
|
27
|
+
"exc_text",
|
|
28
|
+
"filename",
|
|
29
|
+
"funcName",
|
|
30
|
+
"levelname",
|
|
31
|
+
"levelno",
|
|
32
|
+
"lineno",
|
|
33
|
+
"module",
|
|
34
|
+
"msecs",
|
|
35
|
+
"message",
|
|
36
|
+
"msg",
|
|
37
|
+
"name",
|
|
38
|
+
"pathname",
|
|
39
|
+
"process",
|
|
40
|
+
"processName",
|
|
41
|
+
"relativeCreated",
|
|
42
|
+
"stack_info",
|
|
43
|
+
"thread",
|
|
44
|
+
"threadName",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
if sys.version_info >= (3, 12):
|
|
48
|
+
# taskName added in python 3.12
|
|
49
|
+
RESERVED_ATTRS.append("taskName")
|
|
50
|
+
RESERVED_ATTRS.sort()
|
|
51
|
+
|
|
52
|
+
OptionalCallableOrStr = Optional[Union[Callable, str]]
|
|
26
53
|
|
|
27
54
|
|
|
28
55
|
def merge_record_extra(
|
|
29
56
|
record: logging.LogRecord,
|
|
30
57
|
target: Dict,
|
|
31
58
|
reserved: Union[Dict, List],
|
|
32
|
-
rename_fields: Optional[Dict[str,str]] = None,
|
|
59
|
+
rename_fields: Optional[Dict[str, str]] = None,
|
|
33
60
|
) -> Dict:
|
|
34
61
|
"""
|
|
35
62
|
Merges extra attributes from LogRecord object into target dictionary
|
|
@@ -44,10 +71,8 @@ def merge_record_extra(
|
|
|
44
71
|
rename_fields = {}
|
|
45
72
|
for key, value in record.__dict__.items():
|
|
46
73
|
# this allows to have numeric keys
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
and key.startswith('_'))):
|
|
50
|
-
target[rename_fields.get(key,key)] = value
|
|
74
|
+
if key not in reserved and not (hasattr(key, "startswith") and key.startswith("_")):
|
|
75
|
+
target[rename_fields.get(key, key)] = value
|
|
51
76
|
return target
|
|
52
77
|
|
|
53
78
|
|
|
@@ -56,30 +81,34 @@ class JsonEncoder(json.JSONEncoder):
|
|
|
56
81
|
A custom encoder extending the default JSONEncoder
|
|
57
82
|
"""
|
|
58
83
|
|
|
59
|
-
def default(self,
|
|
60
|
-
if isinstance(
|
|
61
|
-
return self.format_datetime_obj(
|
|
84
|
+
def default(self, o: Any) -> Any:
|
|
85
|
+
if isinstance(o, (date, datetime, time)):
|
|
86
|
+
return self.format_datetime_obj(o)
|
|
62
87
|
|
|
63
|
-
|
|
64
|
-
return
|
|
88
|
+
if istraceback(o):
|
|
89
|
+
return "".join(traceback.format_tb(o)).strip()
|
|
65
90
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return str(obj)
|
|
91
|
+
# pylint: disable=unidiomatic-typecheck
|
|
92
|
+
if type(o) == Exception or isinstance(o, Exception) or type(o) == type:
|
|
93
|
+
return str(o)
|
|
70
94
|
|
|
71
95
|
try:
|
|
72
|
-
return super(
|
|
96
|
+
return super().default(o)
|
|
73
97
|
|
|
74
98
|
except TypeError:
|
|
75
99
|
try:
|
|
76
|
-
return str(
|
|
100
|
+
return str(o)
|
|
77
101
|
|
|
78
|
-
except Exception:
|
|
102
|
+
except Exception: # pylint: disable=broad-exception-caught
|
|
79
103
|
return None
|
|
80
104
|
|
|
81
|
-
def format_datetime_obj(self,
|
|
82
|
-
|
|
105
|
+
def format_datetime_obj(self, o):
|
|
106
|
+
"""Format datetime objects found in self.default
|
|
107
|
+
|
|
108
|
+
This allows subclasses to change the datetime format without understanding the
|
|
109
|
+
internals of the default method.
|
|
110
|
+
"""
|
|
111
|
+
return o.isoformat()
|
|
83
112
|
|
|
84
113
|
|
|
85
114
|
class JsonFormatter(logging.Formatter):
|
|
@@ -89,22 +118,35 @@ class JsonFormatter(logging.Formatter):
|
|
|
89
118
|
json default encoder
|
|
90
119
|
"""
|
|
91
120
|
|
|
92
|
-
|
|
121
|
+
# pylint: disable=too-many-arguments
|
|
122
|
+
def __init__(
|
|
123
|
+
self,
|
|
124
|
+
*args: Any,
|
|
125
|
+
json_default: OptionalCallableOrStr = None,
|
|
126
|
+
json_encoder: OptionalCallableOrStr = None,
|
|
127
|
+
json_serialiser: Union[Callable, str] = json.dumps,
|
|
128
|
+
json_indent: Optional[Union[int, str]] = None,
|
|
129
|
+
json_ensure_ascii: bool = True,
|
|
130
|
+
prefix: str = "",
|
|
131
|
+
rename_fields: Optional[dict] = None,
|
|
132
|
+
static_fields: Optional[dict] = None,
|
|
133
|
+
reserved_attrs: Union[Tuple[str, ...], List[str], None] = None,
|
|
134
|
+
timestamp: Union[bool, str] = False,
|
|
135
|
+
**kwargs: Any,
|
|
136
|
+
) -> None:
|
|
93
137
|
"""
|
|
94
138
|
:param json_default: a function for encoding non-standard objects
|
|
95
139
|
as outlined in https://docs.python.org/3/library/json.html
|
|
96
140
|
:param json_encoder: optional custom encoder
|
|
97
141
|
:param json_serializer: a :meth:`json.dumps`-compatible callable
|
|
98
142
|
that will be used to serialize the log record.
|
|
99
|
-
:param json_indent:
|
|
100
|
-
|
|
143
|
+
:param json_indent: indent parameter for json.dumps
|
|
144
|
+
:param json_ensure_ascii: ensure_ascii parameter for json.dumps
|
|
101
145
|
:param prefix: an optional string prefix added at the beginning of
|
|
102
146
|
the formatted string
|
|
103
147
|
:param rename_fields: an optional dict, used to rename field names in the output.
|
|
104
148
|
Rename message to @message: {'message': '@message'}
|
|
105
149
|
:param static_fields: an optional dict, used to add fields with static values to all logs
|
|
106
|
-
:param json_indent: indent parameter for json.dumps
|
|
107
|
-
:param json_ensure_ascii: ensure_ascii parameter for json.dumps
|
|
108
150
|
:param reserved_attrs: an optional list of fields that will be skipped when
|
|
109
151
|
outputting json log record. Defaults to all log record attributes:
|
|
110
152
|
http://docs.python.org/library/logging.html#logrecord-attributes
|
|
@@ -113,17 +155,18 @@ class JsonFormatter(logging.Formatter):
|
|
|
113
155
|
to log record using string as key. If True boolean is passed, timestamp key
|
|
114
156
|
will be "timestamp". Defaults to False/off.
|
|
115
157
|
"""
|
|
116
|
-
self.json_default = self._str_to_fn(
|
|
117
|
-
self.json_encoder = self._str_to_fn(
|
|
118
|
-
self.json_serializer = self._str_to_fn(
|
|
119
|
-
self.json_indent =
|
|
120
|
-
self.json_ensure_ascii =
|
|
121
|
-
self.prefix =
|
|
122
|
-
self.rename_fields =
|
|
123
|
-
self.static_fields =
|
|
124
|
-
reserved_attrs
|
|
158
|
+
self.json_default = self._str_to_fn(json_default)
|
|
159
|
+
self.json_encoder = self._str_to_fn(json_encoder)
|
|
160
|
+
self.json_serializer = self._str_to_fn(json_serialiser)
|
|
161
|
+
self.json_indent = json_indent
|
|
162
|
+
self.json_ensure_ascii = json_ensure_ascii
|
|
163
|
+
self.prefix = prefix
|
|
164
|
+
self.rename_fields = rename_fields or {}
|
|
165
|
+
self.static_fields = static_fields or {}
|
|
166
|
+
if reserved_attrs is None:
|
|
167
|
+
reserved_attrs = RESERVED_ATTRS
|
|
125
168
|
self.reserved_attrs = dict(zip(reserved_attrs, reserved_attrs))
|
|
126
|
-
self.timestamp =
|
|
169
|
+
self.timestamp = timestamp
|
|
127
170
|
|
|
128
171
|
# super(JsonFormatter, self).__init__(*args, **kwargs)
|
|
129
172
|
logging.Formatter.__init__(self, *args, **kwargs)
|
|
@@ -131,9 +174,9 @@ class JsonFormatter(logging.Formatter):
|
|
|
131
174
|
self.json_encoder = JsonEncoder
|
|
132
175
|
|
|
133
176
|
self._required_fields = self.parse()
|
|
134
|
-
self._skip_fields = dict(zip(self._required_fields,
|
|
135
|
-
self._required_fields))
|
|
177
|
+
self._skip_fields = dict(zip(self._required_fields, self._required_fields))
|
|
136
178
|
self._skip_fields.update(self.reserved_attrs)
|
|
179
|
+
return
|
|
137
180
|
|
|
138
181
|
def _str_to_fn(self, fn_as_str):
|
|
139
182
|
"""
|
|
@@ -146,7 +189,7 @@ class JsonFormatter(logging.Formatter):
|
|
|
146
189
|
if not isinstance(fn_as_str, str):
|
|
147
190
|
return fn_as_str
|
|
148
191
|
|
|
149
|
-
path, _, function = fn_as_str.rpartition(
|
|
192
|
+
path, _, function = fn_as_str.rpartition(".")
|
|
150
193
|
module = importlib.import_module(path)
|
|
151
194
|
return getattr(module, function)
|
|
152
195
|
|
|
@@ -158,22 +201,26 @@ class JsonFormatter(logging.Formatter):
|
|
|
158
201
|
to include in all log messages.
|
|
159
202
|
"""
|
|
160
203
|
if isinstance(self._style, logging.StringTemplateStyle):
|
|
161
|
-
formatter_style_pattern = re.compile(r
|
|
204
|
+
formatter_style_pattern = re.compile(r"\$\{(.+?)\}", re.IGNORECASE)
|
|
162
205
|
elif isinstance(self._style, logging.StrFormatStyle):
|
|
163
|
-
formatter_style_pattern = re.compile(r
|
|
206
|
+
formatter_style_pattern = re.compile(r"\{(.+?)\}", re.IGNORECASE)
|
|
164
207
|
# PercentStyle is parent class of StringTemplateStyle and StrFormatStyle so
|
|
165
208
|
# it needs to be checked last.
|
|
166
209
|
elif isinstance(self._style, logging.PercentStyle):
|
|
167
|
-
formatter_style_pattern = re.compile(r
|
|
210
|
+
formatter_style_pattern = re.compile(r"%\((.+?)\)", re.IGNORECASE)
|
|
168
211
|
else:
|
|
169
|
-
raise ValueError(
|
|
212
|
+
raise ValueError(f"Invalid format: {self._fmt!r}")
|
|
170
213
|
|
|
171
214
|
if self._fmt:
|
|
172
215
|
return formatter_style_pattern.findall(self._fmt)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
216
|
+
return []
|
|
217
|
+
|
|
218
|
+
def add_fields(
|
|
219
|
+
self,
|
|
220
|
+
log_record: Dict[str, Any],
|
|
221
|
+
record: logging.LogRecord,
|
|
222
|
+
message_dict: Dict[str, Any],
|
|
223
|
+
) -> None:
|
|
177
224
|
"""
|
|
178
225
|
Override this method to implement custom logic for adding fields.
|
|
179
226
|
"""
|
|
@@ -182,42 +229,53 @@ class JsonFormatter(logging.Formatter):
|
|
|
182
229
|
|
|
183
230
|
log_record.update(self.static_fields)
|
|
184
231
|
log_record.update(message_dict)
|
|
185
|
-
merge_record_extra(
|
|
232
|
+
merge_record_extra(
|
|
233
|
+
record,
|
|
234
|
+
log_record,
|
|
235
|
+
reserved=self._skip_fields,
|
|
236
|
+
rename_fields=self.rename_fields,
|
|
237
|
+
)
|
|
186
238
|
|
|
187
239
|
if self.timestamp:
|
|
188
|
-
|
|
240
|
+
# TODO: Can this use isinstance instead?
|
|
241
|
+
# pylint: disable=unidiomatic-typecheck
|
|
242
|
+
key = self.timestamp if type(self.timestamp) == str else "timestamp"
|
|
189
243
|
log_record[key] = datetime.fromtimestamp(record.created, tz=timezone.utc)
|
|
190
244
|
|
|
191
245
|
self._perform_rename_log_fields(log_record)
|
|
246
|
+
return
|
|
192
247
|
|
|
193
|
-
def _perform_rename_log_fields(self, log_record):
|
|
248
|
+
def _perform_rename_log_fields(self, log_record: Dict[str, Any]) -> None:
|
|
194
249
|
for old_field_name, new_field_name in self.rename_fields.items():
|
|
195
250
|
log_record[new_field_name] = log_record[old_field_name]
|
|
196
251
|
del log_record[old_field_name]
|
|
252
|
+
return
|
|
197
253
|
|
|
198
|
-
def process_log_record(self, log_record):
|
|
254
|
+
def process_log_record(self, log_record: Dict[str, Any]) -> Dict[str, Any]:
|
|
199
255
|
"""
|
|
200
256
|
Override this method to implement custom logic
|
|
201
257
|
on the possibly ordered dictionary.
|
|
202
258
|
"""
|
|
203
259
|
return log_record
|
|
204
260
|
|
|
205
|
-
def jsonify_log_record(self, log_record):
|
|
261
|
+
def jsonify_log_record(self, log_record: Dict[str, Any]) -> str:
|
|
206
262
|
"""Returns a json string of the log record."""
|
|
207
|
-
return self.json_serializer(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
263
|
+
return self.json_serializer(
|
|
264
|
+
log_record,
|
|
265
|
+
default=self.json_default,
|
|
266
|
+
cls=self.json_encoder,
|
|
267
|
+
indent=self.json_indent,
|
|
268
|
+
ensure_ascii=self.json_ensure_ascii,
|
|
269
|
+
)
|
|
212
270
|
|
|
213
271
|
def serialize_log_record(self, log_record: Dict[str, Any]) -> str:
|
|
214
272
|
"""Returns the final representation of the log record."""
|
|
215
|
-
return
|
|
273
|
+
return self.prefix + self.jsonify_log_record(log_record)
|
|
216
274
|
|
|
217
275
|
def format(self, record: logging.LogRecord) -> str:
|
|
218
276
|
"""Formats a log record and serializes to json"""
|
|
219
277
|
message_dict: Dict[str, Any] = {}
|
|
220
|
-
#
|
|
278
|
+
# TODO: logging.LogRecord.msg and logging.LogRecord.message in typeshed
|
|
221
279
|
# are always type of str. We shouldn't need to override that.
|
|
222
280
|
if isinstance(record.msg, dict):
|
|
223
281
|
message_dict = record.msg
|
|
@@ -230,14 +288,14 @@ class JsonFormatter(logging.Formatter):
|
|
|
230
288
|
|
|
231
289
|
# Display formatted exception, but allow overriding it in the
|
|
232
290
|
# user-supplied dict.
|
|
233
|
-
if record.exc_info and not message_dict.get(
|
|
234
|
-
message_dict[
|
|
235
|
-
if not message_dict.get(
|
|
236
|
-
message_dict[
|
|
291
|
+
if record.exc_info and not message_dict.get("exc_info"):
|
|
292
|
+
message_dict["exc_info"] = self.formatException(record.exc_info)
|
|
293
|
+
if not message_dict.get("exc_info") and record.exc_text:
|
|
294
|
+
message_dict["exc_info"] = record.exc_text
|
|
237
295
|
# Display formatted record of stack frames
|
|
238
296
|
# default format is a string returned from :func:`traceback.print_stack`
|
|
239
|
-
if record.stack_info and not message_dict.get(
|
|
240
|
-
message_dict[
|
|
297
|
+
if record.stack_info and not message_dict.get("stack_info"):
|
|
298
|
+
message_dict["stack_info"] = self.formatStack(record.stack_info)
|
|
241
299
|
|
|
242
300
|
log_record: Dict[str, Any] = OrderedDict()
|
|
243
301
|
self.add_fields(log_record, record, message_dict)
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
pythonjsonlogger/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
pythonjsonlogger/jsonlogger.py,sha256=R_eb9uR7t9q06gykfWZ3LhZMIEVYMOXDXx7iz0i06X0,10274
|
|
3
|
-
pythonjsonlogger/py.typed,sha256=4RLptUHQuSqzK6CDbigff8uvWQjwPPQMxikWPkV4OtA,80
|
|
4
|
-
python_json_logger-2.0.7.dist-info/LICENSE,sha256=wVvJlIz5ho1mHqGh4PckLVZ8D4NXa_9LoQH5jeBweus,1290
|
|
5
|
-
python_json_logger-2.0.7.dist-info/METADATA,sha256=G8GNdTilEbOa3kQiOALmbsSu997Lt5iylpT4Ej2tCbc,6484
|
|
6
|
-
python_json_logger-2.0.7.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
|
7
|
-
python_json_logger-2.0.7.dist-info/top_level.txt,sha256=9G-OsTkbwPgM8t-bXKPmWDBRZv9cbzLIiEDE5EnGk2I,17
|
|
8
|
-
python_json_logger-2.0.7.dist-info/RECORD,,
|
|
File without changes
|