METRICS_STORE identifier -> a concrete backend.
The resolution table only: none, postgres, mongo, or an
adopter's dotted path. It is separated from
:mod:symfonic.core.observability.metrics_store -- which owns the protocols,
the buffered sink, and the process-wide hook -- because this is the one part
that grows a branch per backend, and the optional-extra import guards belong
next to the branch that needs them.
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 src/symfonic/core/observability/metrics_store_factory.py
| def 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.
"""
raw = (identifier or "").strip()
if raw == "" or raw.lower() == "none":
return None
low = raw.lower()
if low == "postgres":
if postgres_session_factory is None:
raise ValueError(
"METRICS_STORE=postgres requires a postgres_session_factory",
)
try:
from symfonic.core.observability.postgres_metrics_store import ( # noqa: PLC0415
PostgresMetricsStore,
)
except ImportError as exc: # pragma: no cover - exercised via extra
raise ValueError(
"METRICS_STORE=postgres requires SQLAlchemy: "
"pip install 'symfonic-core[postgres]'",
) from exc
return PostgresMetricsStore(postgres_session_factory)
if low in ("mongo", "mongodb"):
if mongo_database_factory is None:
raise ValueError(
"METRICS_STORE=mongo requires a mongo_database_factory",
)
try:
from symfonic.core.observability.mongo_metrics_store import ( # noqa: PLC0415
MongoMetricsStore,
)
except ImportError as exc: # pragma: no cover - exercised via extra
raise ValueError(
"METRICS_STORE=mongo requires motor: "
"pip install 'symfonic-core[mongodb]'",
) from exc
return MongoMetricsStore(
mongo_database_factory, retention_days=mongo_retention_days,
)
if ":" in raw or "." in raw:
cls = _import_dotted(raw)
return cls()
raise ValueError(
f"unknown METRICS_STORE {raw!r}; expected 'none', 'postgres', "
"'mongo', or a dotted path 'pkg.module:Class'",
)
|