fix: JSON extra cannot clobber canonical time/level/module fields (v0.3.1)
guard the extra-merge loop with the formatter's own output keys (time/level/module/
message). stdlib LogRecord rejects extra keys colliding with real attribute names, but
time/level are NOT LogRecord attrs, so a caller's extra={"time":...}/{"level":...}
previously overwrote the UTC timestamp / levelname — the two fields Loki/Grafana alert
on. now those keys are reserved and a colliding extra is dropped.
Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
parent
73007fe900
commit
ad62993bb3
@ -13,7 +13,7 @@ and emit; their records flow into the handlers `log_setup` wired.
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
```
|
```
|
||||||
log_setup @ git+ssh://git@git.rethinkstudios.io/rethink-public/log_setup.git@v0.3.0
|
log_setup @ git+ssh://git@git.rethinkstudios.io/rethink-public/log_setup.git@v0.3.1
|
||||||
```
|
```
|
||||||
|
|
||||||
No dependencies — stdlib only.
|
No dependencies — stdlib only.
|
||||||
|
|||||||
@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "log_setup"
|
name = "log_setup"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
description = "stdlib app-entry-point logging setup: live run.log, rotation, gzip, retention, consistent format"
|
description = "stdlib app-entry-point logging setup: live run.log, rotation, gzip, retention, consistent format"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = []
|
dependencies = []
|
||||||
|
|||||||
@ -19,4 +19,4 @@ from .setup import setup_logging
|
|||||||
|
|
||||||
__all__ = ["setup_logging"]
|
__all__ = ["setup_logging"]
|
||||||
|
|
||||||
__version__ = "0.3.0"
|
__version__ = "0.3.1"
|
||||||
|
|||||||
@ -15,6 +15,11 @@ DEFAULT_FORMAT = "%(asctime)s | %(name)s | %(levelname)s | %(message)s"
|
|||||||
DEFAULT_DATEFMT = "%Y-%m-%d %H:%M:%S"
|
DEFAULT_DATEFMT = "%Y-%m-%d %H:%M:%S"
|
||||||
|
|
||||||
_RESERVED = frozenset(vars(logging.makeLogRecord({})).keys()) | {"message", "asctime"}
|
_RESERVED = frozenset(vars(logging.makeLogRecord({})).keys()) | {"message", "asctime"}
|
||||||
|
# this formatter's own canonical output keys — stdlib's LogRecord rejects `extra` keys
|
||||||
|
# colliding with real attribute names (e.g. `module`), but `time`/`level` are NOT
|
||||||
|
# LogRecord attrs, so a caller's extra={"time":...}/{"level":...} would otherwise
|
||||||
|
# overwrite the UTC timestamp / levelname. guard them explicitly
|
||||||
|
_OUTPUT_KEYS = frozenset({"time", "level", "module", "message"})
|
||||||
|
|
||||||
|
|
||||||
class JsonLinesFormatter(logging.Formatter):
|
class JsonLinesFormatter(logging.Formatter):
|
||||||
@ -38,7 +43,7 @@ class JsonLinesFormatter(logging.Formatter):
|
|||||||
"message": record.getMessage(),
|
"message": record.getMessage(),
|
||||||
}
|
}
|
||||||
for key, value in record.__dict__.items():
|
for key, value in record.__dict__.items():
|
||||||
if key not in _RESERVED and not key.startswith("_"):
|
if key not in _RESERVED and key not in _OUTPUT_KEYS and not key.startswith("_"):
|
||||||
payload[key] = value
|
payload[key] = value
|
||||||
if record.exc_info:
|
if record.exc_info:
|
||||||
payload["exc_info"] = self.formatException(record.exc_info)
|
payload["exc_info"] = self.formatException(record.exc_info)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user