Context
Follow-up to #77. PR #80 added a static `_RESERVED_LOG_RECORD_KEYS` frozenset enumerating the stdlib `LogRecord` attribute names that, if present in user-supplied `extra`, would cause `KeyError` inside `logging.Logger._log`.
The static list works today but carries a maintenance risk: future Python versions may add new `LogRecord` attributes, and the static set will silently drift. CPython has historically added fields (e.g. `taskName` in 3.12).
Tasks
- Replace (or supplement) the static set with a runtime-derived one:
```python
_RESERVED_LOG_RECORD_KEYS = frozenset(logging.makeLogRecord({}).dict) | {"message", "asctime"}
```
Rationale: `message` is computed in `LogRecord.getMessage()` and `asctime` by formatters, so neither appears in `dict` of a freshly created `LogRecord`.
- Keep the existing explicit regression tests (reserved keys `message`, `args`, `levelname`, `name`, `msg`) to lock the contract regardless of derivation strategy.
- Add a test that asserts `taskName` (Python 3.12+) is recognized on supported interpreters, gated by `sys.version_info`.
Out of Scope
- Behavior change of `sanitize_extra` itself (still prefixes collisions with `extra`).
- Public API change.
Priority
P2 — defensive refactor, not a bug. Target: v0.6.0 or later.
Context
Follow-up to #77. PR #80 added a static `_RESERVED_LOG_RECORD_KEYS` frozenset enumerating the stdlib `LogRecord` attribute names that, if present in user-supplied `extra`, would cause `KeyError` inside `logging.Logger._log`.
The static list works today but carries a maintenance risk: future Python versions may add new `LogRecord` attributes, and the static set will silently drift. CPython has historically added fields (e.g. `taskName` in 3.12).
Tasks
```python
_RESERVED_LOG_RECORD_KEYS = frozenset(logging.makeLogRecord({}).dict) | {"message", "asctime"}
```
Rationale: `message` is computed in `LogRecord.getMessage()` and `asctime` by formatters, so neither appears in `dict` of a freshly created `LogRecord`.
Out of Scope
Priority
P2 — defensive refactor, not a bug. Target: v0.6.0 or later.