python-json-logger 4.1.0__py3-none-any.whl → 4.3.0.dev2__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-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/METADATA +2 -20
- {python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/RECORD +7 -7
- {python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/WHEEL +1 -1
- pythonjsonlogger/core.py +58 -28
- pythonjsonlogger/defaults.py +9 -1
- {python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/licenses/LICENSE +0 -0
- {python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-json-logger
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.3.0.dev2
|
|
4
4
|
Summary: JSON Log Formatter for the Python Logging Package
|
|
5
5
|
Author-email: Zakaria Zajac <zak@madzak.com>, Nicholas Hairs <info+python-json-logger@nicholashairs.com>
|
|
6
6
|
Maintainer-email: Nicholas Hairs <info+python-json-logger@nicholashairs.com>
|
|
@@ -16,30 +16,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.13
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
20
|
Classifier: Topic :: System :: Logging
|
|
20
21
|
Classifier: Typing :: Typed
|
|
21
22
|
Requires-Python: >=3.10
|
|
22
23
|
Description-Content-Type: text/markdown
|
|
23
24
|
License-File: LICENSE
|
|
24
|
-
Provides-Extra: dev
|
|
25
|
-
Requires-Dist: orjson; implementation_name != "pypy" and extra == "dev"
|
|
26
|
-
Requires-Dist: msgspec; implementation_name != "pypy" and extra == "dev"
|
|
27
|
-
Requires-Dist: validate-pyproject[all]; extra == "dev"
|
|
28
|
-
Requires-Dist: black; extra == "dev"
|
|
29
|
-
Requires-Dist: pylint; extra == "dev"
|
|
30
|
-
Requires-Dist: mypy; extra == "dev"
|
|
31
|
-
Requires-Dist: pytest; extra == "dev"
|
|
32
|
-
Requires-Dist: freezegun; extra == "dev"
|
|
33
|
-
Requires-Dist: tzdata; extra == "dev"
|
|
34
|
-
Requires-Dist: build; extra == "dev"
|
|
35
|
-
Requires-Dist: mkdocs; extra == "dev"
|
|
36
|
-
Requires-Dist: mkdocs-material>=8.5; extra == "dev"
|
|
37
|
-
Requires-Dist: mkdocs-awesome-pages-plugin; extra == "dev"
|
|
38
|
-
Requires-Dist: mdx_truly_sane_lists; extra == "dev"
|
|
39
|
-
Requires-Dist: mkdocstrings[python]; extra == "dev"
|
|
40
|
-
Requires-Dist: mkdocs-gen-files; extra == "dev"
|
|
41
|
-
Requires-Dist: mkdocs-literate-nav; extra == "dev"
|
|
42
|
-
Requires-Dist: mike; extra == "dev"
|
|
43
25
|
Dynamic: license-file
|
|
44
26
|
|
|
45
27
|
[](https://pypi.python.org/pypi/python-json-logger/)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
python_json_logger-4.
|
|
1
|
+
python_json_logger-4.3.0.dev2.dist-info/licenses/LICENSE,sha256=GOqVF546Xg4k62zhbED7--IxM8JQKTOi91-KPhoFW1Q,1329
|
|
2
2
|
pythonjsonlogger/__init__.py,sha256=2QcveuId10CyXff_BtJ_6kXIarHT5oq66XHHMFiaE8s,419
|
|
3
|
-
pythonjsonlogger/core.py,sha256=
|
|
4
|
-
pythonjsonlogger/defaults.py,sha256=
|
|
3
|
+
pythonjsonlogger/core.py,sha256=T02iURAubnMTk0PO0HUOckS93eMfAFapSZcFPXJqB64,17102
|
|
4
|
+
pythonjsonlogger/defaults.py,sha256=VR_Wl092yRjwS0mREjuNn_W4H4sAjtcZAIYFBMYNHe0,6770
|
|
5
5
|
pythonjsonlogger/exception.py,sha256=r3DXDk7TThscnMVNPpVRaRSFHTnY-ygea6nn-FgjwsI,804
|
|
6
6
|
pythonjsonlogger/json.py,sha256=6aJSqd2BeysAHkQkxb7dPgFpqsFRf4rvWYgaWF2MEC0,4064
|
|
7
7
|
pythonjsonlogger/jsonlogger.py,sha256=sfltkYGwRhRvqcpT-kxlPfcMuOc4ngEa4W4NVTiBpMI,417
|
|
@@ -9,7 +9,7 @@ pythonjsonlogger/msgspec.py,sha256=tdFes9rLrdns9I_C5ascK9a265iNc4UccLPzc8JbFDI,2
|
|
|
9
9
|
pythonjsonlogger/orjson.py,sha256=XWM-jyl6g_40Em8kt188EOspD872xHvYy8aS_CLlssw,2354
|
|
10
10
|
pythonjsonlogger/py.typed,sha256=4RLptUHQuSqzK6CDbigff8uvWQjwPPQMxikWPkV4OtA,80
|
|
11
11
|
pythonjsonlogger/utils.py,sha256=qr04nb61TkVw7cJTXAtLBfyH_NBvyYUlR_mehH76-RM,1126
|
|
12
|
-
python_json_logger-4.
|
|
13
|
-
python_json_logger-4.
|
|
14
|
-
python_json_logger-4.
|
|
15
|
-
python_json_logger-4.
|
|
12
|
+
python_json_logger-4.3.0.dev2.dist-info/METADATA,sha256=q4IajnR8q8pXVltRYOx5V3-7FPkoGkECHgo9XbSb9AI,2922
|
|
13
|
+
python_json_logger-4.3.0.dev2.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
|
|
14
|
+
python_json_logger-4.3.0.dev2.dist-info/top_level.txt,sha256=9G-OsTkbwPgM8t-bXKPmWDBRZv9cbzLIiEDE5EnGk2I,17
|
|
15
|
+
python_json_logger-4.3.0.dev2.dist-info/RECORD,,
|
pythonjsonlogger/core.py
CHANGED
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
from datetime import datetime, timezone
|
|
10
10
|
import logging
|
|
11
11
|
import re
|
|
12
|
+
import string
|
|
12
13
|
import sys
|
|
13
14
|
from typing import TypeAlias, Any
|
|
14
15
|
from collections.abc import Container, Sequence
|
|
@@ -61,9 +62,10 @@ if sys.version_info >= (3, 12):
|
|
|
61
62
|
RESERVED_ATTRS.sort()
|
|
62
63
|
|
|
63
64
|
|
|
64
|
-
STYLE_STRING_TEMPLATE_REGEX = re.compile(
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
STYLE_STRING_TEMPLATE_REGEX = re.compile(
|
|
66
|
+
r"\$(?:\$|\{(?P<braced>.+?)\}|(?P<named>[_a-z][_a-z0-9]*))", re.IGNORECASE
|
|
67
|
+
) # $ style
|
|
68
|
+
STYLE_PERCENT_REGEX = re.compile(r"%(?:%|\((?P<named>.+?)\))", re.IGNORECASE) # % style
|
|
67
69
|
|
|
68
70
|
## Type Aliases
|
|
69
71
|
## -----------------------------------------------------------------------------
|
|
@@ -111,10 +113,6 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
111
113
|
Must not be used directly.
|
|
112
114
|
|
|
113
115
|
*New in 3.1*
|
|
114
|
-
|
|
115
|
-
*Changed in 3.2*: `defaults` argument is no longer ignored.
|
|
116
|
-
|
|
117
|
-
*Added in 3.3*: `exc_info_as_array` and `stack_info_as_array` options are added.
|
|
118
116
|
"""
|
|
119
117
|
|
|
120
118
|
_style: logging.PercentStyle | str # type: ignore[assignment]
|
|
@@ -155,12 +153,14 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
155
153
|
rename_fields_keep_missing: When renaming fields, include missing fields in the output.
|
|
156
154
|
static_fields: an optional dict, used to add fields with static values to all logs
|
|
157
155
|
reserved_attrs: an optional list of fields that will be skipped when
|
|
158
|
-
outputting json log record.
|
|
156
|
+
outputting json log record. Pass a list or tuple, not a string.
|
|
157
|
+
Defaults to [all log record attributes][pythonjsonlogger.core.RESERVED_ATTRS].
|
|
159
158
|
timestamp: an optional string/boolean field to add a timestamp when
|
|
160
159
|
outputting the json log record. If string is passed, timestamp will be added
|
|
161
160
|
to log record using string as key. If True boolean is passed, timestamp key
|
|
162
161
|
will be "timestamp". Defaults to False/off.
|
|
163
|
-
exc_info_as_array: break the exc_info into a list of lines based on line breaks
|
|
162
|
+
exc_info_as_array: break the exc_info into a list of lines based on line breaks,
|
|
163
|
+
including cached exception text in records received over a transport.
|
|
164
164
|
stack_info_as_array: break the stack_info into a list of lines based on line breaks.
|
|
165
165
|
|
|
166
166
|
*Changed in 3.1*:
|
|
@@ -172,16 +172,19 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
172
172
|
missing fields. The original behaviour, missing fields have a value of `None`, is still
|
|
173
173
|
available by setting `rename_fields_keep_missing` to `True`.
|
|
174
174
|
|
|
175
|
+
*Changed in 3.2*: `defaults` argument is no longer ignored.
|
|
176
|
+
|
|
177
|
+
*Added in 3.3*: `exc_info_as_array` and `stack_info_as_array` options are added.
|
|
178
|
+
|
|
175
179
|
*Added in 4.0*:
|
|
176
180
|
|
|
177
|
-
- `fmt` now supports comma
|
|
181
|
+
- `fmt` now supports comma separated lists (`style=","`). Note that this style is specific
|
|
178
182
|
to `python-json-logger` and thus care should be taken to not to pass this format to other
|
|
179
183
|
logging Formatter implementations.
|
|
180
184
|
- `fmt` now supports sequences of strings (e.g. lists and tuples) of field names.
|
|
181
185
|
"""
|
|
182
186
|
## logging.Formatter compatibility
|
|
183
187
|
## ---------------------------------------------------------------------
|
|
184
|
-
# Note: validate added in python 3.8, defaults added in 3.10
|
|
185
188
|
if fmt is None or isinstance(fmt, str):
|
|
186
189
|
if style in logging._STYLES:
|
|
187
190
|
_style = logging._STYLES[style][0](fmt) # type: ignore[operator]
|
|
@@ -212,8 +215,9 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
212
215
|
## ---------------------------------------------------------------------
|
|
213
216
|
self.prefix = prefix
|
|
214
217
|
|
|
215
|
-
#
|
|
216
|
-
#
|
|
218
|
+
# Recreate these dicts so DictConfigurator `ext://` / `cfg://` prefixes
|
|
219
|
+
# are converted (ConvertingDict only converts on `__getitem__`) and so
|
|
220
|
+
# later mutation of the caller's dict cannot change formatter state.
|
|
217
221
|
# For more details see: https://github.com/nhairs/python-json-logger/pull/45
|
|
218
222
|
self.rename_fields = (
|
|
219
223
|
{key: rename_fields[key] for key in rename_fields} if rename_fields is not None else {}
|
|
@@ -221,29 +225,43 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
221
225
|
self.static_fields = (
|
|
222
226
|
{key: static_fields[key] for key in static_fields} if static_fields is not None else {}
|
|
223
227
|
)
|
|
228
|
+
self.defaults = {key: defaults[key] for key in defaults} if defaults is not None else {}
|
|
224
229
|
|
|
225
230
|
self.rename_fields_keep_missing = rename_fields_keep_missing
|
|
226
|
-
|
|
231
|
+
if reserved_attrs is None:
|
|
232
|
+
reserved_attrs = RESERVED_ATTRS
|
|
233
|
+
elif isinstance(reserved_attrs, str):
|
|
234
|
+
raise TypeError("reserved_attrs must be a sequence of field names, not a string")
|
|
235
|
+
self.reserved_attrs = set(reserved_attrs)
|
|
227
236
|
self.timestamp = timestamp
|
|
228
237
|
|
|
229
238
|
self._skip_fields = set(self._required_fields)
|
|
230
239
|
self._skip_fields.update(self.reserved_attrs)
|
|
231
|
-
self.defaults = defaults if defaults is not None else {}
|
|
232
240
|
self.exc_info_as_array = exc_info_as_array
|
|
233
241
|
self.stack_info_as_array = stack_info_as_array
|
|
234
242
|
return
|
|
235
243
|
|
|
244
|
+
def usesTime(self) -> bool:
|
|
245
|
+
"""Return whether the parsed format fields include `asctime`."""
|
|
246
|
+
return "asctime" in self._required_fields
|
|
247
|
+
|
|
236
248
|
def format(self, record: logging.LogRecord) -> str:
|
|
237
249
|
"""Formats a log record and serializes to json
|
|
238
250
|
|
|
251
|
+
When `record.msg` is a `dict`, adding `exc_info` and `stack_info` does not
|
|
252
|
+
modify the caller's dict.
|
|
253
|
+
|
|
239
254
|
Args:
|
|
240
255
|
record: the record to format
|
|
256
|
+
|
|
257
|
+
*Changed in 4.2.0*: a `dict` `record.msg` is copied instead of modified
|
|
258
|
+
in place.
|
|
241
259
|
"""
|
|
242
260
|
message_dict: dict[str, Any] = {}
|
|
243
261
|
# TODO: logging.LogRecord.msg and logging.LogRecord.message in typeshed
|
|
244
262
|
# are always type of str. We shouldn't need to override that.
|
|
245
263
|
if isinstance(record.msg, dict):
|
|
246
|
-
message_dict = record.msg
|
|
264
|
+
message_dict = record.msg.copy()
|
|
247
265
|
record.message = ""
|
|
248
266
|
else:
|
|
249
267
|
record.message = record.getMessage()
|
|
@@ -257,7 +275,9 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
257
275
|
if record.exc_info and not message_dict.get("exc_info"):
|
|
258
276
|
message_dict["exc_info"] = self.formatException(record.exc_info)
|
|
259
277
|
if not message_dict.get("exc_info") and record.exc_text:
|
|
260
|
-
message_dict["exc_info"] =
|
|
278
|
+
message_dict["exc_info"] = (
|
|
279
|
+
record.exc_text.splitlines() if self.exc_info_as_array else record.exc_text
|
|
280
|
+
)
|
|
261
281
|
|
|
262
282
|
# Display formatted record of stack frames
|
|
263
283
|
# default format is a string returned from :func:`traceback.print_stack`
|
|
@@ -296,20 +316,30 @@ class BaseJsonFormatter(logging.Formatter):
|
|
|
296
316
|
raise ValueError(f"Style {self._style!r} is not supported")
|
|
297
317
|
|
|
298
318
|
if isinstance(self._style, logging.StringTemplateStyle):
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
319
|
+
# String templates support both ${name} and $name, and $$ is an escaped literal
|
|
320
|
+
return [
|
|
321
|
+
match.group("braced") or match.group("named")
|
|
322
|
+
for match in STYLE_STRING_TEMPLATE_REGEX.finditer(self._fmt)
|
|
323
|
+
if match.group("braced") or match.group("named")
|
|
324
|
+
]
|
|
325
|
+
|
|
326
|
+
if isinstance(self._style, logging.StrFormatStyle):
|
|
327
|
+
return [
|
|
328
|
+
field_name
|
|
329
|
+
for _, field_name, _, _ in string.Formatter().parse(self._fmt)
|
|
330
|
+
if field_name
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
if isinstance(self._style, logging.PercentStyle):
|
|
305
334
|
# PercentStyle is parent class of StringTemplateStyle and StrFormatStyle
|
|
306
335
|
# so it must be checked last.
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
336
|
+
return [
|
|
337
|
+
match.group("named")
|
|
338
|
+
for match in STYLE_PERCENT_REGEX.finditer(self._fmt)
|
|
339
|
+
if match.group("named")
|
|
340
|
+
]
|
|
311
341
|
|
|
312
|
-
|
|
342
|
+
raise ValueError(f"Style {self._style!r} is not supported")
|
|
313
343
|
|
|
314
344
|
def serialize_log_record(self, log_data: LogData) -> str:
|
|
315
345
|
"""Returns the final representation of the data to be logged
|
pythonjsonlogger/defaults.py
CHANGED
|
@@ -152,10 +152,18 @@ def use_exception_default(obj: Any) -> TypeGuard[BaseException]:
|
|
|
152
152
|
def exception_default(obj: BaseException) -> str:
|
|
153
153
|
"""Default function for exception instances
|
|
154
154
|
|
|
155
|
+
Includes the exception's own notes, if present. Exception groups retain
|
|
156
|
+
their summary without recursively formatting their children.
|
|
157
|
+
|
|
155
158
|
Args:
|
|
156
159
|
obj: object to handle
|
|
160
|
+
|
|
161
|
+
*Changed in 4.3*: Includes exception notes if available.
|
|
157
162
|
"""
|
|
158
|
-
|
|
163
|
+
result = f"{obj.__class__.__name__}: {obj}"
|
|
164
|
+
if hasattr(obj, "__notes__"):
|
|
165
|
+
return "\n".join([result, *obj.__notes__])
|
|
166
|
+
return result
|
|
159
167
|
|
|
160
168
|
|
|
161
169
|
def use_traceback_default(obj: Any) -> TypeGuard[TracebackType]:
|
{python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
{python_json_logger-4.1.0.dist-info → python_json_logger-4.3.0.dev2.dist-info}/top_level.txt
RENAMED
|
File without changes
|