Skip to content

Commit ebbd70a

Browse files
committed
[core] Add support for comma format
Fixes #15
1 parent 0428e2b commit ebbd70a

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

docs/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99
### Added
1010
- Support `DictConfigurator` prefixes for `rename_fields` and `static_fields`. [#45](https://github.com/nhairs/python-json-logger/pull/45)
1111
- Allows using values like `ext://sys.stderr` in `fileConfig`/`dictConfig` value fields.
12+
- Support comma seperated lists for Formatter `fmt` (`style=","`) e.g. `"asctime,message,levelname"` [#15](https://github.com/nhairs/python-json-logger/issues/15)
13+
- Note that this style is specific to `python-json-logger` and thus care should be taken not to pass this format to other logging Formatter implementations.
1214

1315
### Changed
1416
- Rename `pythonjsonlogger.core.LogRecord` and `log_record` arguments to avoid confusion / overlapping with `logging.LogRecord`. [#38](https://github.com/nhairs/python-json-logger/issues/38)

src/pythonjsonlogger/core.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ def __init__(
175175
- Renaming fields now preserves the order that fields were added in and avoids adding
176176
missing fields. The original behaviour, missing fields have a value of `None`, is still
177177
available by setting `rename_fields_keep_missing` to `True`.
178+
179+
*Added in 4.0*:
180+
181+
- `fmt` now supports comma seperated lists (`style=","`). Note that this style is specific
182+
to `python-json-logger` and thus care should be taken to not to pass this format to other
183+
logging Formatter implementations.
178184
"""
179185
## logging.Formatter compatibility
180186
## ---------------------------------------------------------------------
@@ -186,7 +192,7 @@ def __init__(
186192
self._style = _style
187193
self._fmt = _style._fmt
188194

189-
elif not validate:
195+
elif style == "," or not validate:
190196
self._style = style
191197
self._fmt = fmt
192198

@@ -271,6 +277,18 @@ def parse(self) -> List[str]:
271277
Returns:
272278
list of fields to be extracted and serialized
273279
"""
280+
if self._fmt is None:
281+
# TODO: does it matter that we do this before checking if the style is valid?
282+
# (we already (mostly) check for valid style names in __init__
283+
return []
284+
285+
if isinstance(self._style, str) and self._style == ",":
286+
# TODO: should we check that there are no empty fields?
287+
# If yes we should do this in __init__ where we validate other styles?
288+
# Do we drop empty fields?
289+
# etc
290+
return [field.strip() for field in self._fmt.split(",") if field.strip()]
291+
274292
if isinstance(self._style, logging.StringTemplateStyle):
275293
formatter_style_pattern = STYLE_STRING_TEMPLATE_REGEX
276294

@@ -285,10 +303,7 @@ def parse(self) -> List[str]:
285303
else:
286304
raise ValueError(f"Style {self._style!r} is not supported")
287305

288-
if self._fmt:
289-
return formatter_style_pattern.findall(self._fmt)
290-
291-
return []
306+
return formatter_style_pattern.findall(self._fmt)
292307

293308
def serialize_log_record(self, log_data: LogData) -> str:
294309
"""Returns the final representation of the data to be logged

tests/test_formatters.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,21 @@ def test_default_format(env: LoggingEnvironment, class_: type[BaseJsonFormatter]
158158

159159
@pytest.mark.parametrize("class_", ALL_FORMATTERS)
160160
def test_percentage_format(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
161-
env.set_formatter(
162-
class_(
163-
# All kind of different styles to check the regex
164-
"[%(levelname)8s] %(message)s %(filename)s:%(lineno)d %(asctime)"
165-
)
166-
)
161+
# Note: All kind of different %s styles to check the regex
162+
env.set_formatter(class_("[%(levelname)8s] %(message)s %(filename)s:%(lineno)d %(asctime)"))
163+
164+
msg = "testing logging format"
165+
env.logger.info(msg)
166+
log_json = env.load_json()
167+
168+
assert log_json["message"] == msg
169+
assert log_json.keys() == {"levelname", "message", "filename", "lineno", "asctime"}
170+
return
171+
172+
173+
@pytest.mark.parametrize("class_", ALL_FORMATTERS)
174+
def test_comma_format(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
175+
env.set_formatter(class_("levelname,message,filename,lineno,asctime", style=","))
167176

168177
msg = "testing logging format"
169178
env.logger.info(msg)

0 commit comments

Comments
 (0)