monitor.server¶
MonitorServer — FastAPI web server for the otto monitoring dashboard.
Endpoints¶
GET / Serves the React dashboard’s built index.html (web/, via make web)
GET /static/… Serves the built dist/ assets (JS/CSS bundles, etc.)
GET /api/mode JSON {"mode": "live"|"review", "source": str|None}
GET /api/monitor_sessions The format:1 payload: the loaded archive in
review mode, or a snapshot of the running session in live mode (a live
session is just one whose end is still open). Both modes hydrate
through this one endpoint.
GET /api/stream SSE stream — pushes metric updates and events in real time
POST /api/event Record a manual event from the dashboard UI
GET /api/export/json Download the current data as a format:1 document
-
class otto.monitor.server.SuppressASGIWarning(name=
'')¶ Bases:
Filterlogging.Filterthat drops the uvicorn ASGI callable warning on shutdown.
-
class otto.monitor.server.MonitorServer(collector: MetricCollector, host: str =
'0.0.0.0', port: int =0, *, mode: 'live' | 'review' ='live', document: MonitorExport | None =None, source_name: str | None =None, frame: SessionFrame | None =None, lab: LabSnapshot | None =None)¶ Bases:
objectWraps a FastAPI/uvicorn server for the monitoring dashboard.
Two modes, chosen by the CLI at construction time:
mode="live"(default) — serves a runningMetricCollector.frameandlabmust both be supplied so/api/monitor_sessions//api/export/jsoncan build a snapshot document on demand.mode="review"— serves a pre-builtdocument(aformat:1MonitorExport, e.g. read back from a--dbsession archive).source_nameis the human-facing origin (a file path) reported by/api/mode.
Call
await serve()from an async context to run the server. Callstop()from any thread to trigger a graceful shutdown, orforce_stop()to abort open SSE connections immediately instead of waiting for them to drain.- force_stop() None¶
Shut down without waiting for open connections to drain (thread-safe).
SSE dashboards hold /api/stream open indefinitely, so a graceful shutdown can wait forever. This sets uvicorn’s
force_exit(skip the drain) and aborts open connection transports on the server’s own loop (h11 never closes a mid-stream transport, so clients would otherwise not see the connection die). Used by test harnesses and Ctrl+C paths; preferstop()when clients should finish cleanly.The listening sockets are closed first so no new connection is accepted, then open transports are aborted. A single abort pass is not enough: uvicorn registers a connection in its protocol’s
connection_made, which asyncio defers onto the loop viacall_soon. So a socket already accepted at the OS level when the listeners close can finish registering a live transport after the abort pass — and an un-aborted mid-stream h11 SSE keeps the server task alive (asyncio.Server.wait_closed()waits on it on 3.12+), hanging shutdown indefinitely (issue #109). Because the listeners are closed, the set of still-pending registrations is bounded, so we re-abort across a few consecutive loop turns (_FORCE_STOP_ABORT_PASSES) until they have all run and been aborted.