symfonic.platform.observability¶
observability ¶
Observability the host owns, rather than the process.
Three open gaps say the same thing from three angles, and the middle one says it out loud.
PUB-5 names ConversationMetricsCollector: what makes a child's cost roll
up into its parent's totals. Without a public name, a generated app's
delegation costs vanish from the billing view.
PUB-6 names the metrics store's factory and its get/set module
globals. It is triaged "internalize store internals" while the scaffold's admin
dashboard and worker depend on exactly that seam, and the gap row states the
contradiction: the verdict and the shipped scaffold disagree; one of them has
to move.
PUB-7 names PostgresBudgetStore: without it two replicas each enforce
their own half of the limit.
One resolution answers all three, and it is the one the host already
established. These are process resources. The host owns them and hands
them over, which honours PUB-6's verdict rather than overturning it -- the
store internals stay internal, and what becomes public is a bundle a
composition root holds. It also removes the module globals, which a
multi-tenant host should never have had: set_metrics_store means the second
host built in a process overwrites the first, silently, and the first host's
dashboard then reads the second's numbers.
One collector, not one per agent. The roll-up is the sharing; there is no separate mechanism. A child reporting to its own collector would produce two correct ledgers and no total, which is why the collector belongs here and not to an agent.
ObservabilityServices
dataclass
¶
ObservabilityServices(collector: Any, metrics: Any = None, budget: Any = None, event_sinks: tuple[Any, ...] = ())
What a process needs to account for what its agents did.
Satisfies :class:~symfonic.platform.host.SharedResources structurally, so
a composition root hands this to the host it already builds rather than
installing it anywhere.
There is deliberately no setter. Ownership runs one way: the host holds these, and nothing installs them into a place other code discovers.
budget_is_shared
property
¶
Whether two replicas would enforce one limit or two halves of it.
Exposed because in-memory is a legitimate choice and a silent one is not: a deployment may accept per-replica budgets, but it may not be unable to tell that is what it has.
aclose
async
¶
Release what these own. Idempotent, because shutdown paths repeat.
Source code in src/symfonic/platform/observability.py
observability ¶
observability(*, metrics_identifier: str | None = None, postgres_session_factory: Any = None, mongo_database_factory: Any = None, mongo_retention_days: int = 90) -> ObservabilityServices
Build one process's observability resources.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metrics_identifier
|
str | None
|
which durable metrics store to build, if any. |
None
|
postgres_session_factory
|
Any
|
supplied when budget consumption must be
counted across replicas. Absent, the tracker is in-memory and each
replica enforces its own half of the limit -- which
:attr: |
None
|
mongo_database_factory
|
Any
|
the alternative durable metrics backend. |
None
|
mongo_retention_days
|
int
|
how long that backend keeps rows. |
90
|