-
Notifications
You must be signed in to change notification settings - Fork 0
fix: integrate Uvicorn access logging with structlog and add access.log sink #560
Description
Summary
Uvicorn's default access logger (uvicorn.access) writes unstructured INFO: 172.18.0.4:35196 - "GET /api/v1/health HTTP/1.1" 200 OK lines to stdout, completely bypassing the structlog pipeline. Meanwhile, RequestLoggingMiddleware already logs the same requests as structured events (api.request.started/api.request.completed with method, path, status_code, duration_ms, request_id). This creates duplicate logging -- every HTTP request appears twice.
Scope
-
Disable Uvicorn's access log: Pass
access_log=Falsetouvicorn.run()inserver.py. The structlogRequestLoggingMiddlewarealready covers the same data with richer fields. -
Route Uvicorn's own messages through structlog: Pass
log_config=Nonetouvicorn.run()to disable Uvicorn's default logging dict config. Then configureuvicornanduvicorn.errorstdlib loggers to propagate through the structlog handler chain (so Uvicorn startup/shutdown messages get structured formatting). -
Add
access.logsink: New 8th sink inDEFAULT_SINKS-- DEBUG level, JSON format, routessynthorg.api.logger prefix. Provides a dedicated HTTP access log file separate from the catch-all logs. -
Update
_SINK_ROUTINGinsinks.pyto include"access.log": ("synthorg.api.",).
Dependencies
- Depends on bootstrap_logging being wired in (the logging bootstrap issue)
Acceptance Criteria
- No more duplicate
INFO: ... "GET ... HTTP/1.1" 200 OKlines in logs - Uvicorn startup/shutdown messages (
Started server process,Application startup complete) flow through structlog with structured formatting -
access.logfile receives allsynthorg.api.*events -
RequestLoggingMiddlewareremains the single source of truth for HTTP access logging - Docker CMD does not need to change (uvicorn args are set in
server.py/create_app)