feat: one structured log for every process, with a request id
A deployment printed four different log formats and none of them could be joined up: uvicorn's log_config.json for the API, a hand-rolled StreamHandler in main.py for anything not started by uvicorn, logging.basicConfig() in the worker and in the download child (no timestamp at all), and alembic's fileConfig. app/logs.py replaces all four with one JSON line per event (OpenTelemetry's log data model, no SDK): ts, level, severity, source, logger, event code, message, attributes, plus the correlation the context carries — request id, account, download job. Redaction is applied at the HANDLER, not at the call sites: every message, every attribute and every traceback is scrubbed on the way out, so a secret cannot leak by being forgotten at one of ~125 call sites. Passwords, tokens, cookies, secret config values and email addresses never reach a line. The access log is ours now (`http.request`): the route template instead of the concrete path, the status, the duration and the account — and never the query string, which uvicorn's access log printed on every single request (`?account=`, `?source=`, the `?token=` of a share link). A well-formed client request id is accepted and echoed in X-Request-Id, so a browser line and a server line join up. The account comes from `request.state`, filled by the auth dependency: the middleware is the outermost one, so it runs outside SessionMiddleware and in a different task context. `log_level` becomes an admin knob (sysconfig), applied without a restart and re-applied at startup — best-effort on purpose, since a logging knob must never be what stops the app from booting. Every compose service gets bounded json-file logs (3×50 MB): Docker keeps every line forever by default, and the API now writes one line per request. Verified on the localdev stack: JSON everywhere including alembic and the worker, the query strings gone, a supplied X-Request-Id echoed and logged, and three /healthz hits of which only the one made while the level was DEBUG produced a line.
This commit is contained in:
@@ -15,7 +15,8 @@
|
||||
"downloads": "Downloads",
|
||||
"plex": "Plex",
|
||||
"tmdb": "TMDB",
|
||||
"audit": "Audit log"
|
||||
"audit": "Audit log",
|
||||
"diagnostics": "Diagnostics"
|
||||
},
|
||||
"fields": {
|
||||
"smtp_host": {
|
||||
@@ -154,6 +155,10 @@
|
||||
"label": "Retention (days)",
|
||||
"hint": "How long admin audit-log entries are kept before the audit-log cleanup job prunes them. 0 = keep forever. Default 180."
|
||||
},
|
||||
"log_level": {
|
||||
"label": "Log level",
|
||||
"hint": "How much the server writes to its log. INFO is the normal setting; DEBUG and TRACE are for reproducing a problem and are far more detailed. Takes effect immediately, no restart."
|
||||
},
|
||||
"plex_enabled": {
|
||||
"label": "Enable Plex",
|
||||
"hint": "Expose the Plex library as a Feed source with a rich player. Requires the Plex server to be reachable from this host and its media on a local mount (see the path map)."
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
"downloads": "Letöltések",
|
||||
"plex": "Plex",
|
||||
"tmdb": "TMDB",
|
||||
"audit": "Naplózás"
|
||||
"audit": "Naplózás",
|
||||
"diagnostics": "Diagnosztika"
|
||||
},
|
||||
"fields": {
|
||||
"smtp_host": {
|
||||
@@ -154,6 +155,10 @@
|
||||
"label": "Megőrzés (nap)",
|
||||
"hint": "Meddig maradnak meg az admin-naplóbejegyzések, mielőtt a napló-karbantartó feladat törli őket. 0 = örökre. Alapérték 180."
|
||||
},
|
||||
"log_level": {
|
||||
"label": "Naplózási szint",
|
||||
"hint": "Mennyit naplózzon a szerver. Az INFO a szokásos; a DEBUG és a TRACE hibakereséshez való, sokkal részletesebb. Azonnal érvénybe lép, újraindítás nélkül."
|
||||
},
|
||||
"plex_enabled": {
|
||||
"label": "Plex engedélyezése",
|
||||
"hint": "A Plex-könyvtár megjelenítése forrásként, gazdag lejátszóval. Ehhez a Plex-szervernek elérhetőnek kell lennie erről a gépről, a média pedig helyi mounton (lásd az útvonal-leképezést)."
|
||||
|
||||
Reference in New Issue
Block a user