app.services.strategy_observability_service module¶
Observability aggregation service.
Reads from the same strategyexecutionlog table the engine writes
via DslExecutionObserver and shapes it into the metrics view
the dashboard renders for a single strategy, plus the A/B comparison
endpoint that runs the same aggregation against two ids and computes
deltas.
The repository already does the heavy lifting (SUM/COUNT/GROUP BY in the DB); this service is responsible for:
Combining 5 narrow queries into one response - the dashboard fetches once per page load.
Computing percentiles + histograms in Python from a bounded sample, because SQLite (used in tests) doesn’t have
percentile_contand PostgreSQL’s window-function variant is expensive on tables with millions of rows.Tenant scoping: callers pass the strategy id, we resolve it via
StrategyDefinitionService.get_strategywhich 404s on cross-realm probes, so this service is implicitly tenant-aware.
- class app.services.strategy_observability_service.StrategyObservabilityService(execution_log_repository, strategy_definition_service)[source]¶
Bases:
objectSingle entrypoint for the dashboard view + A/B view.
- Parameters:
execution_log_repository (StrategyExecutionLogRepository)
strategy_definition_service (StrategyDefinitionService)
- async get_metrics(*, id, realmId, sinceDt=None, untilDt=None)[source]¶
Build the per-strategy metrics card.
Resolves the strategy first so the response includes name + version + status - and so cross-realm probes 404 before we spend a query on the execution log.
- Parameters:
id (str)
realmId (str | None)
sinceDt (datetime | None)
untilDt (datetime | None)
- Return type:
StrategyMetricsResponse
- async compare(*, idA, idB, realmId, sinceDt=None, untilDt=None)[source]¶
Run the metrics aggregation twice in parallel-ish (awaited sequentially since each takes ~5 narrow queries) and compute deltas server-side. Both ids are validated through the same get_strategy path so neither can leak from a foreign realm.
- Parameters:
idA (str)
idB (str)
realmId (str | None)
sinceDt (datetime | None)
untilDt (datetime | None)
- Return type:
StrategyComparisonResponse