feat(logging): structured JSON logs, uvicorn access log included
Hold Slayer's logs are shipped to Loki by the host's Alloy agent, which reads container stdout. Text lines arrive there as an opaque blob: filtering on a status code meant regex over a formatted string. This adds LOG_FORMAT=json (default "text", so local dev stays readable) rendering one JSON object per line. Two parts were less obvious than a format= argument would suggest, and both are why this is a module rather than a basicConfig tweak: Uvicorn attaches its own handlers to `uvicorn` and `uvicorn.access` with propagate=False, so configuring only the root logger would have left the access log — the highest-volume, most useful stream — as colourised text next to our JSON. configure_logging clears those handlers and re-enables propagation, and is called both at import (for startup config checks) and in lifespan (uvicorn configures itself after importing the app). The __main__ path passes log_config=None so uvicorn never applies its own. The access record's payload lives in record.args as a 5-tuple, not in the message. Formatting it would throw the structure away and force Loki to parse it back out, so the tuple is unpacked into real fields and status_code is emitted as a number for range filtering. Also drops uvicorn's `color_message` extra, an ANSI-coloured duplicate of the message that generic extra-promotion would otherwise copy into every startup line — the same unreadable-in-Grafana problem recently fixed for the lab's Asterisk logs. Verified against a real uvicorn server: 39/39 lines valid JSON, zero ANSI escapes, no duplicates, access lines structured with correct status codes; text mode unchanged. Thread name is included off the main thread, since "which execution context logged this" is the first question when debugging across the asyncio/Sippy/PJSUA2 boundary. SecretStr extras stay masked. README Phase 4 item ticked; LOG_FORMAT and the previously-undocumented LOG_LEVEL added to the config table and .env.example. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -100,6 +100,9 @@ HOST=0.0.0.0
|
||||
PORT=8000
|
||||
DEBUG=false
|
||||
LOG_LEVEL=info
|
||||
# Log rendering: "text" (human-readable) or "json" (one object per line, for
|
||||
# Loki/Alloy). The Docker image sets json; text is the default for local dev.
|
||||
LOG_FORMAT=text
|
||||
|
||||
# --- Safety ---
|
||||
# Max simultaneous calls the gateway will place (REST + MCP)
|
||||
|
||||
Reference in New Issue
Block a user