symfonic.core.observability.metrics_store¶
metrics_store ¶
Storage-agnostic durable metrics contracts, buffering, and factory.
The same sink persists billable model calls and metadata-only execution events.
BufferedMetricsSink ¶
BufferedMetricsSink(store: MetricsStore, *, batch_size: int = 25, flush_interval_s: float = 2.0, max_queue: int = 10000)
Hot-path buffer around any :class:MetricsStore.
record() is a synchronous O(1) enqueue so the collector fan-out in
on_llm_end never awaits DB I/O. A background task flushes the queue
every flush_interval_s or once batch_size rows are pending,
calling the wrapped store's record_calls once per batch. All read /
lifecycle methods delegate to the wrapped store, so get_metrics_store()
returns a single object serving both write and read.
Source code in symfonic/core/observability/metrics_store.py
loss_counts
property
¶
Losses by durable record family, safe for health reporting.
ensure_indexes ¶
Delegate to the wrapped store's index bootstrap, if it has one.
flush
async
¶
Drain the whole queue now (deterministic for tests / shutdown).
Source code in symfonic/core/observability/metrics_store.py
record ¶
Synchronous, non-blocking enqueue. Drops oldest on overflow.
Source code in symfonic/core/observability/metrics_store.py
record_event ¶
Enqueue one metadata-only execution event.
Source code in symfonic/core/observability/metrics_store.py
MetricsReader ¶
Bases: Protocol
Rich, tenant-scoped read side backing the admin dashboards.
conversation_detail
async
¶
Return snapshot-shaped rows for one conversation, oldest-first.
The shape MUST match ConversationMetricsCollector.snapshots() so
the scaffold's build_conversation_detail() is reused unchanged.
Source code in symfonic/core/observability/metrics_store.py
execution_detail
async
¶
Return metadata-only execution events, oldest-first.
list_conversations
async
¶
Return (rows, total) — per-conversation token rollup.
summary
async
¶
Return {conversations, total_llm_calls, total_cost_usd, total_tokens}.
token_usage
async
¶
Return DailyUsageRow / ModelUsageRow shaped dicts (group_by in {day, model}).
Source code in symfonic/core/observability/metrics_store.py
MetricsSink ¶
MetricsStore ¶
Bases: MetricsSink, MetricsReader, Protocol
A full metrics backend: durable writes + rich tenant-scoped reads.
get_metrics_store ¶
make_metrics_store ¶
make_metrics_store(identifier: str | None, *, postgres_session_factory: Any = None, mongo_database_factory: Any = None, mongo_retention_days: int = 90) -> MetricsStore | None
Resolve a METRICS_STORE identifier to a concrete backend.
none / "" → None (in-memory collector only, today's default).
postgres → :class:PostgresMetricsStore (needs postgres_session_factory
+ symfonic-core[postgres]). mongo → :class:MongoMetricsStore
(needs mongo_database_factory + symfonic-core[mongodb]). A dotted
path (my_pkg.mod:MyStore or my_pkg.mod.MyStore) → the adopter's
zero-arg-constructible MetricsStore.
Raises ValueError with a pip install hint on a missing extra and
on an unknown identifier, so misconfiguration fails loudly at startup.
Source code in symfonic/core/observability/metrics_store_factory.py
set_metrics_store ¶
Register the process-wide metrics store (or None to disable).