Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [4.2.0](https://github.com/nhairs/python-json-logger/compare/v4.1.0...v4.2.0) - UNRELEASED

### Fixed
- Logging a `dict` no longer modifies it. `exc_info` and `stack_info` were previously added to the caller's `dict`. [#66](https://github.com/nhairs/python-json-logger/pull/66)

Thanks @gaoflow

Comment thread
nhairs marked this conversation as resolved.
## [4.1.0](https://github.com/nhairs/python-json-logger/compare/v4.0.0...v4.1.0) - 2026-03-29

### Added
Expand Down
3 changes: 3 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ logger.info({
!!! warning
Be aware that if you log using a `dict`, other formatters may not be able to handle it.

!!! note
Your `dict` is not modified when the formatter adds fields such as `exc_info`.

You can also add additional message fields using the `extra` argument.

```python
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "python-json-logger"
version = "4.1.0"
version = "4.2.0.dev1"
description = "JSON Log Formatter for the Python Logging Package"
authors = [
{name = "Zakaria Zajac", email = "zak@madzak.com"},
Expand Down
8 changes: 7 additions & 1 deletion src/pythonjsonlogger/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,14 +236,20 @@ def __init__(
def format(self, record: logging.LogRecord) -> str:
"""Formats a log record and serializes to json

When `record.msg` is a `dict`, adding `exc_info` and `stack_info` does not
modify the caller's dict.

Args:
record: the record to format

*Changed in 4.2.0*: a `dict` `record.msg` is copied instead of modified
in place.
"""
message_dict: dict[str, Any] = {}
# TODO: logging.LogRecord.msg and logging.LogRecord.message in typeshed
# are always type of str. We shouldn't need to override that.
if isinstance(record.msg, dict):
message_dict = record.msg
message_dict = record.msg.copy()
record.message = ""
else:
record.message = record.getMessage()
Expand Down
17 changes: 17 additions & 0 deletions tests/test_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,23 @@ def test_log_dict_defaults(env: LoggingEnvironment, class_: type[BaseJsonFormatt
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_log_dict_not_modified(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_())

msg = {"text": "testing logging", "nested": {"more": "data"}}
try:
raise ValueError("test")
except ValueError:
env.logger.exception(msg, stack_info=True)
log_json = env.load_json()

assert log_json["exc_info"]
assert log_json["stack_info"]
assert msg == {"text": "testing logging", "nested": {"more": "data"}}
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_log_extra(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_())
Expand Down
Loading