feat: structured JSON output mode (output="json")
add a selectable output format to setup_logging: text (default, human,
local time) stays unchanged; output="json" emits one-JSON-object-per-line
(JSON Lines) for the Grafana/Loki path. json fields are time (UTC ISO-8601
with Z), level, module, message, plus any extra={...} keys surfaced as
top-level fields and a rendered exc_info traceback on error records. both
file and console use the chosen format; the live-file name is unchanged so
the Promtail glob and tail command don't break across text/json. an unknown
output falls back to text and warns, never crashes. stdlib json only, zero
new deps. minor bump to v0.2.0.
Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -13,7 +13,7 @@ and emit; their records flow into the handlers `log_setup` wired.
|
||||
## Install
|
||||
|
||||
```
|
||||
log_setup @ git+ssh://git@git.rethinkstudios.io/rethink-public/log_setup.git@v0.1.0
|
||||
log_setup @ git+ssh://git@git.rethinkstudios.io/rethink-public/log_setup.git@v0.2.0
|
||||
```
|
||||
|
||||
No dependencies — stdlib only.
|
||||
@@ -52,6 +52,37 @@ emits; the records land in the configured root.
|
||||
- **console=True** (off by default) also logs to stdout in the same format — opt in when
|
||||
you want live terminal output alongside the file.
|
||||
|
||||
## Output format (`output=`)
|
||||
|
||||
Two formats, two needs. Default is `"text"`; the live-file name is the same either way
|
||||
(`run.log`, never auto-renamed), so a service can switch text↔json without breaking the
|
||||
Promtail glob, bind-mount path, or your `tail` command.
|
||||
|
||||
- **`output="text"`** (default) — human-readable
|
||||
`2026-06-27 19:55:05 | module.name | INFO | message`, **local time**. The
|
||||
single-machine `tail -f` path. `fmt`/`datefmt` override it. Unchanged from v0.1.x.
|
||||
- **`output="json"`** — structured **one JSON object per line** (JSON Lines) for the
|
||||
Grafana/Loki pipeline (Promtail → Loki → Grafana); Loki parses JSON fields into labels
|
||||
natively, no regex.
|
||||
|
||||
```python
|
||||
setup_logging(name="run", output="json")
|
||||
logging.getLogger("bot.core").info("ready", extra={"monitor": "heartbeat"})
|
||||
# -> {"time": "2026-06-28T14:03:11Z", "level": "INFO", "module": "bot.core",
|
||||
# "message": "ready", "monitor": "heartbeat"}
|
||||
```
|
||||
|
||||
- **Fields:** `time`, `level`, `module`, `message` always; any `extra={...}` keys land
|
||||
as **top-level** fields (stamp `monitor`/`service`/request-id for Loki labels — the lib
|
||||
stays domain-agnostic); error records carry the traceback in `exc_info` (never dropped).
|
||||
- **Time is UTC ISO-8601 with a `Z`** (`2026-06-28T14:03:11Z`), not local. json is the
|
||||
aggregation path — logs from many servers/containers sort unambiguously only in UTC;
|
||||
Grafana converts to local for display. (Text mode stays local — that's a human on one
|
||||
box.)
|
||||
- Both file and console use the chosen format. `fmt`/`datefmt` apply to text only (json
|
||||
builds fields, not a format string). An unknown `output` falls back to text + warns,
|
||||
never crashes. **Zero new deps** — stdlib `json` only.
|
||||
|
||||
## Signature
|
||||
|
||||
```python
|
||||
@@ -65,8 +96,9 @@ setup_logging(
|
||||
compress=True, # gzip rolled files
|
||||
console=False, # also log to stdout (off by default; opt in)
|
||||
queue=False, # route through a background QueueListener (async-friendly)
|
||||
fmt=None, # override the format string
|
||||
datefmt=None, # override the date format
|
||||
output="text", # "text" (human, local time) | "json" (structured, UTC)
|
||||
fmt=None, # override the text format string (text mode only)
|
||||
datefmt=None, # override the text date format (text mode only)
|
||||
) -> logging.Logger # returns the configured root logger
|
||||
```
|
||||
|
||||
@@ -97,8 +129,9 @@ handlers. Getting files to a backend is a separate concern (e.g. Promtail tails
|
||||
backend can change without touching any app, and the consistent format here is what
|
||||
makes downstream parsing and alerting easy.
|
||||
|
||||
Also out of v0.1.0 (possible later additions): structured/JSON logging, color
|
||||
formatting, per-logger filters, remote handlers.
|
||||
Structured/JSON output is **in** as of v0.2.0 (`output="json"`) — text and json only.
|
||||
Still deliberately out: logfmt or other formats, a format DSL, per-handler formats,
|
||||
color formatting, per-logger filters, remote handlers.
|
||||
|
||||
## Versioning
|
||||
|
||||
|
||||
Reference in New Issue
Block a user