diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d8f2b87..20cacf5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/ ## [Unreleased](https://github.com/hynek/structlog/compare/24.1.0...HEAD) +### Changed + +- `structlog.processors.LogfmtRenderer` now escapes newlines. + [#592](https://github.com/hynek/structlog/pull/592) ## [24.1.0](https://github.com/hynek/structlog/compare/23.3.0...24.1.0) - 2024-01-08 diff --git a/src/structlog/processors.py b/src/structlog/processors.py index 3f25dfff..b7c78055 100644 --- a/src/structlog/processors.py +++ b/src/structlog/processors.py @@ -170,7 +170,7 @@ def __call__( continue value = "true" if value else "false" - value = f"{value}".replace('"', '\\"') + value = f"{value}".replace('"', '\\"').replace("\n", "\\n") if " " in value or "=" in value: value = f'"{value}"' diff --git a/tests/test_processors.py b/tests/test_processors.py index 04eb6a85..9fd16787 100644 --- a/tests/test_processors.py +++ b/tests/test_processors.py @@ -290,6 +290,16 @@ def test_invalid_key(self): with pytest.raises(ValueError, match='Invalid key: "invalid key"'): LogfmtRenderer()(None, None, event_dict) + def test_newline_in_value(self): + """ + Newlines in values are escaped. + """ + event_dict = {"with_newline": "some\nvalue"} + + rv = LogfmtRenderer()(None, None, event_dict) + + assert r"with_newline=some\nvalue" == rv + class TestJSONRenderer: def test_renders_json(self, event_dict):