feat: freeze typed metrics registry and bounded exemplars

This commit is contained in:
2026-08-14 11:52:00 +03:00
parent 17c8e3a8f0
commit 8e709acea9
29 changed files with 1690 additions and 103 deletions
+26 -7
View File
@@ -171,7 +171,8 @@ scrape_configs:
- `crank_http_requests_total`, `crank_http_request_duration_seconds`,
`crank_http_inflight`;
- `crank_mcp_requests_total`, `crank_mcp_active_sessions`,
- `crank_mcp_requests_total`, `crank_mcp_request_duration_seconds`,
`crank_mcp_active_sessions`, `crank_mcp_session_metrics_fresh`,
`crank_mcp_active_streams`;
- `crank_tool_invocations_total`, `crank_tool_invocation_duration_seconds`;
- `crank_upstream_requests_total`,
@@ -187,8 +188,12 @@ scrape_configs:
Recorder добавляет к рядам проверенные статические labels `service`,
`version`, `environment`. Остальные labels имеют закрытый набор значений.
Имена, типы и допустимые значения labels определены в независимом нижнем
crate `crank-metrics`. Product-код вызывает только его типизированный фасад;
Эти три labels классифицированы как `process_constant`: они валидируются один
раз при запуске и образуют ровно одну tuple на процесс. Имена, типы, help,
process ownership, допустимые значения product labels и buckets определены в
независимом нижнем crate `crank-metrics`. Его deterministic machine snapshot —
[`schemas/metrics-registry-v1.json`](schemas/metrics-registry-v1.json).
Product-код вызывает только типизированный фасад;
прямая production-зависимость от `metrics` вне `crank-metrics` и
`crank-observability` запрещена архитектурной проверкой Cargo metadata.
Запрещено использовать workspace, идентификаторы агента, операции или
@@ -198,7 +203,10 @@ HTTP route берётся только из шаблона Axum; неизвес
`crank_mcp_active_sessions` отражает число ещё не истёкших транспортных
сессий в общем хранилище, а `crank_mcp_active_streams` — число открытых в
этом экземпляре SSE-потоков. Прикладные ошибки JSON-RPC и
этом экземпляре SSE-потоков. `crank_mcp_session_metrics_fresh=0` означает,
что последнее bounded чтение session store завершилось ошибкой/timeout и
значение active sessions нельзя считать свежим; успешное чтение возвращает
freshness в `1`. Прикладные ошибки JSON-RPC и
`tools/call.result.isError=true` учитываются отдельно от успешного HTTP 200.
Счётчики cache, idempotency и confirmation описывают переходы
соответствующих стадий: hit/miss и ошибки хранилища, execute/replay/conflict
@@ -208,9 +216,20 @@ HTTP route берётся только из шаблона Axum; неизвес
Buckets длительности фиксированы кодом:
`0.005`, `0.01`, `0.025`, `0.05`, `0.1`, `0.25`, `0.5`, `1`, `2.5`, `5`,
`10`, `30`, `60` секунд. Это пока техническая шкала, а не SLO. Фактические
series и расход памяти измеряются в истории 1.8; произвольный численный
бюджет до замеров не назначается.
`10`, `30`, `60` секунд. Это пока техническая шкала, а не SLO. Registry v1
содержит 23 family и для всего lifetime одного процесса ограничен 5 000
logical labelsets и 15 000 Prometheus sample series; текущий worst case —
4 513 и 14 338 соответственно. Histogram budget включает finite buckets,
`+Inf`, `_sum` и `_count`; изменение domain или buckets требует обновления
versioned snapshot и evidence.
Обычный scrape сохраняет Prometheus text 0.0.4. Клиент с
`Accept: application/openmetrics-text` получает OpenMetrics 1.0 и `# EOF`.
Validated 32-hex Trace ID может присутствовать только как latest bounded
histogram exemplar; он никогда не является label и не меняет aggregate.
Отсутствующий, invalid или unsampled Trace ID просто не создаёт exemplar.
Размер готового exposition ограничен 8 MiB; превышение возвращает статический
`503` без частично усечённого тела и не влияет на product listener.
## Распределённые трассы