Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- `pythonjsonlogger.[ORJSON,MSGSPEC]_AVAILABLE` no longer imports the respective package when determining availability.
- `pythonjsonlogger.[orjson,msgspec]` now throws a `pythonjsonlogger.exception.MissingPackageError` when required libraries are not available. These contain more information about what is missing whilst still being an `ImportError`.
- `defaults` parameter is no longer ignored and now conforms to the standard library. Setting a defaults dictionary will add the specified keys if the those keys do not exist in a record or weren't passed by the `extra` parameter when logging a message.

## [3.1.0](https://github.com/nhairs/python-json-logger/compare/v3.0.1...v3.1.0) - 2023-05-28

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 = "3.1.0"
version = "3.2.0"
description = "JSON Log Formatter for the Python Logging Package"
authors = [
{name = "Zakaria Zajac", email = "zak@madzak.com"},
Expand Down
9 changes: 8 additions & 1 deletion src/pythonjsonlogger/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ def __init__(
style: how to extract log fields from `fmt`
validate: validate `fmt` against style, if implementing a custom `style` you
must set this to `False`.
defaults: ignored - kept for compatibility with python 3.10+
defaults: a dictionary containing default values for unspecified
extras. {"key": 1234} will add the key to the json if
unspecified in the extras while logging a message.
These fields are added prior to renaming.
prefix: an optional string prefix added at the beginning of
the formatted string
rename_fields: an optional dict, used to rename field names in the output.
Expand Down Expand Up @@ -215,6 +218,7 @@ def __init__(
self._required_fields = self.parse()
self._skip_fields = set(self._required_fields)
self._skip_fields.update(self.reserved_attrs)
self.defaults = defaults if defaults is not None else {}
return

def format(self, record: logging.LogRecord) -> str:
Expand Down Expand Up @@ -310,6 +314,9 @@ def add_fields(
message_dict: dictionary that was logged instead of a message. e.g
`logger.info({"is_this_message_dict": True})`
"""
for field in self.defaults:
log_record[self._get_rename(field)] = self.defaults[field]

for field in self._required_fields:
log_record[self._get_rename(field)] = record.__dict__.get(field)

Expand Down
38 changes: 38 additions & 0 deletions tests/test_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,18 @@ def test_percentage_format(env: LoggingEnvironment, class_: type[BaseJsonFormatt
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_defaults_field(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_(defaults={"first": 1, "second": 2}))

env.logger.info("testing defaults field", extra={"first": 1234})
log_json = env.load_json()

assert log_json["first"] == 1234
assert log_json["second"] == 2
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_rename_base_field(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_(rename_fields={"message": "@message"}))
Expand All @@ -186,6 +198,19 @@ def test_rename_base_field(env: LoggingEnvironment, class_: type[BaseJsonFormatt
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_rename_with_defaults(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
"""Make sure that the default fields are also renamed."""
env.set_formatter(class_(rename_fields={"custom": "@custom"}, defaults={"custom": 1234}))

msg = "testing rename with defaults"
env.logger.info(msg)
log_json = env.load_json()

assert log_json["@custom"] == 1234
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_rename_missing(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_(rename_fields={"missing_field": "new_field"}))
Expand Down Expand Up @@ -321,6 +346,19 @@ def test_log_dict(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
return


@pytest.mark.parametrize("class_", ALL_FORMATTERS)
def test_log_dict_defaults(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
env.set_formatter(class_(defaults={"d1": 1234, "d2": "hello"}))

msg = {"d2": "world"}
env.logger.info(msg)
log_json = env.load_json()

assert log_json["d1"] == 1234
assert log_json["d2"] == "world"
return


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