feat: freeze typed metrics registry and bounded exemplars
This commit is contained in:
+26
-7
@@ -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.
|
||||
|
||||
## Распределённые трассы
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"budget": {"logical_series": 4513, "rendered_series": 14338, "max_logical_series": 5000, "max_rendered_series": 15000},
|
||||
"global_labels": [
|
||||
{"name": "service", "class": "process_constant", "domain": ["admin-api", "mcp-server"]},
|
||||
{"name": "version", "class": "process_constant", "domain": ["validated_release_identity"]},
|
||||
{"name": "environment", "class": "process_constant", "domain": ["validated_startup_value"]}
|
||||
],
|
||||
"metrics": [
|
||||
{"name": "crank_http_requests_total", "kind": "counter", "unit": "count", "help": "Total HTTP requests.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "route", "class": "product_closed", "domain": ["unmatched", "/health", "/ready", "/api/auth/login", "/api/auth/logout", "/api/auth/session", "/api/auth/profile", "/api/auth/password", "/api/admin/capabilities", "/api/admin/workspaces", "/api/admin/workspaces/{workspace_id}", "/api/admin/workspaces/{workspace_id}/operations", "/api/admin/workspaces/{workspace_id}/imports/openapi/preview", "/api/admin/workspaces/{workspace_id}/imports/openapi/{job_id}/create", "/api/admin/workspaces/{workspace_id}/operations/analyze-quality", "/api/admin/workspaces/{workspace_id}/operations/import", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions/{version}", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/publish", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/archive", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/test-runs", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/input-json", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/output-json", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/drafts/generate", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/export", "/api/admin/workspaces/{workspace_id}/agents", "/api/admin/workspaces/{workspace_id}/agents/tool-search/preview", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/versions/{version}", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/publish", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/unpublish", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/archive", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}/revoke", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}", "/api/admin/workspaces/{workspace_id}/auth-profiles", "/api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}", "/api/admin/workspaces/{workspace_id}/upstreams", "/api/admin/workspaces/{workspace_id}/upstreams/{upstream_id}", "/api/admin/workspaces/{workspace_id}/secrets", "/api/admin/workspaces/{workspace_id}/secrets/{secret_id}", "/api/admin/workspaces/{workspace_id}/secrets/{secret_id}/rotate", "/api/admin/workspaces/{workspace_id}/export", "/api/admin/workspaces/{workspace_id}/logs", "/api/admin/workspaces/{workspace_id}/logs/{log_id}", "/api/admin/workspaces/{workspace_id}/approvals", "/api/admin/workspaces/{workspace_id}/approvals/{approval_id}", "/api/admin/workspaces/{workspace_id}/usage", "/api/admin/workspaces/{workspace_id}/usage/operations/{operation_id}", "/api/admin/workspaces/{workspace_id}/usage/agents/{agent_id}", "/v1/{workspace_slug}/{agent_slug}", "/v1/{workspace_slug}/{agent_slug}/approvals", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}/approve", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}/deny"]},{"name": "method", "class": "product_closed", "domain": ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "CONNECT", "TRACE", "OTHER"]},{"name": "status_class", "class": "product_closed", "domain": ["1xx", "2xx", "3xx", "4xx", "5xx", "other"]}], "buckets_seconds": [], "max_logical_series": 3420, "max_rendered_series": 3420},
|
||||
{"name": "crank_http_request_duration_seconds", "kind": "histogram", "unit": "seconds", "help": "HTTP request duration in seconds.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "route", "class": "product_closed", "domain": ["unmatched", "/health", "/ready", "/api/auth/login", "/api/auth/logout", "/api/auth/session", "/api/auth/profile", "/api/auth/password", "/api/admin/capabilities", "/api/admin/workspaces", "/api/admin/workspaces/{workspace_id}", "/api/admin/workspaces/{workspace_id}/operations", "/api/admin/workspaces/{workspace_id}/imports/openapi/preview", "/api/admin/workspaces/{workspace_id}/imports/openapi/{job_id}/create", "/api/admin/workspaces/{workspace_id}/operations/analyze-quality", "/api/admin/workspaces/{workspace_id}/operations/import", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/versions/{version}", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/publish", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/archive", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/test-runs", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/input-json", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/samples/output-json", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/drafts/generate", "/api/admin/workspaces/{workspace_id}/operations/{operation_id}/export", "/api/admin/workspaces/{workspace_id}/agents", "/api/admin/workspaces/{workspace_id}/agents/tool-search/preview", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/versions/{version}", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/bindings", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/publish", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/unpublish", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/archive", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}/revoke", "/api/admin/workspaces/{workspace_id}/agents/{agent_id}/platform-api-keys/{key_id}", "/api/admin/workspaces/{workspace_id}/auth-profiles", "/api/admin/workspaces/{workspace_id}/auth-profiles/{auth_profile_id}", "/api/admin/workspaces/{workspace_id}/upstreams", "/api/admin/workspaces/{workspace_id}/upstreams/{upstream_id}", "/api/admin/workspaces/{workspace_id}/secrets", "/api/admin/workspaces/{workspace_id}/secrets/{secret_id}", "/api/admin/workspaces/{workspace_id}/secrets/{secret_id}/rotate", "/api/admin/workspaces/{workspace_id}/export", "/api/admin/workspaces/{workspace_id}/logs", "/api/admin/workspaces/{workspace_id}/logs/{log_id}", "/api/admin/workspaces/{workspace_id}/approvals", "/api/admin/workspaces/{workspace_id}/approvals/{approval_id}", "/api/admin/workspaces/{workspace_id}/usage", "/api/admin/workspaces/{workspace_id}/usage/operations/{operation_id}", "/api/admin/workspaces/{workspace_id}/usage/agents/{agent_id}", "/v1/{workspace_slug}/{agent_slug}", "/v1/{workspace_slug}/{agent_slug}/approvals", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}/approve", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}", "/v1/{workspace_slug}/{agent_slug}/approvals/{approval_id}/deny"]},{"name": "method", "class": "product_closed", "domain": ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "CONNECT", "TRACE", "OTHER"]}], "buckets_seconds": [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60], "max_logical_series": 570, "max_rendered_series": 9120},
|
||||
{"name": "crank_http_inflight", "kind": "gauge", "unit": "count", "help": "HTTP requests currently being processed.", "processes": ["admin_api", "mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_mcp_requests_total", "kind": "counter", "unit": "count", "help": "Total MCP JSON-RPC requests.", "processes": ["mcp_server"], "labels": [{"name": "method", "class": "product_closed", "domain": ["initialize", "initialized", "ping", "tools_list", "tools_call", "notification", "unsupported", "response", "invalid"]},{"name": "response_mode", "class": "product_closed", "domain": ["json", "sse", "unknown"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "client_error", "server_error", "jsonrpc_error", "tool_error", "aborted", "other"]}], "buckets_seconds": [], "max_logical_series": 189, "max_rendered_series": 189},
|
||||
{"name": "crank_mcp_request_duration_seconds", "kind": "histogram", "unit": "seconds", "help": "MCP JSON-RPC request duration in seconds.", "processes": ["mcp_server"], "labels": [{"name": "method", "class": "product_closed", "domain": ["initialize", "initialized", "ping", "tools_list", "tools_call", "notification", "unsupported", "response", "invalid"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "client_error", "server_error", "jsonrpc_error", "tool_error", "aborted", "other"]}], "buckets_seconds": [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60], "max_logical_series": 63, "max_rendered_series": 1008},
|
||||
{"name": "crank_mcp_active_sessions", "kind": "gauge", "unit": "count", "help": "Active persisted MCP transport sessions.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_mcp_session_metrics_fresh", "kind": "gauge", "unit": "count", "help": "Whether the active-session gauge was refreshed successfully.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_mcp_active_streams", "kind": "gauge", "unit": "count", "help": "MCP event streams currently being served.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_tool_invocations_total", "kind": "counter", "unit": "count", "help": "Total tool invocations.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "source", "class": "product_closed", "domain": ["internal", "admin_test_run", "agent_tool_call"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "error", "aborted"]},{"name": "error_kind", "class": "product_closed", "domain": ["none", "schema", "mapping", "rest_adapter", "protocol_adapter", "unsupported_protocol", "unsupported_execution_mode", "concurrency_limit", "invalid_prepared_request", "confirmation_required", "invalid_confirmation_token", "confirmation_store", "idempotency_store", "idempotency_in_progress", "idempotency_conflict", "idempotency_outcome_unknown", "missing_auth_profile", "missing_secret", "missing_secret_version", "invalid_auth_secret", "secret_crypto", "aborted"]}], "buckets_seconds": [], "max_logical_series": 198, "max_rendered_series": 198},
|
||||
{"name": "crank_tool_invocation_duration_seconds", "kind": "histogram", "unit": "seconds", "help": "Tool invocation duration in seconds.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "source", "class": "product_closed", "domain": ["internal", "admin_test_run", "agent_tool_call"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "error", "aborted"]}], "buckets_seconds": [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60], "max_logical_series": 9, "max_rendered_series": 144},
|
||||
{"name": "crank_upstream_requests_total", "kind": "counter", "unit": "count", "help": "Total upstream requests.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "operation_kind", "class": "product_closed", "domain": ["rest"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "client_error", "server_error", "unexpected_status", "timeout", "transport_error", "response_too_large", "rejected", "window_expired", "invalid_response", "invalid_request", "configuration", "aborted"]}], "buckets_seconds": [], "max_logical_series": 13, "max_rendered_series": 13},
|
||||
{"name": "crank_upstream_request_duration_seconds", "kind": "histogram", "unit": "seconds", "help": "Upstream request duration in seconds.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "operation_kind", "class": "product_closed", "domain": ["rest"]},{"name": "outcome", "class": "product_closed", "domain": ["success", "client_error", "server_error", "unexpected_status", "timeout", "transport_error", "response_too_large", "rejected", "window_expired", "invalid_response", "invalid_request", "configuration", "aborted"]}], "buckets_seconds": [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60], "max_logical_series": 13, "max_rendered_series": 208},
|
||||
{"name": "crank_runtime_inflight", "kind": "gauge", "unit": "count", "help": "Runtime executions currently in progress.", "processes": ["admin_api", "mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_runtime_limit_rejections_total", "kind": "counter", "unit": "count", "help": "Runtime executions rejected by a bounded limit.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "stage", "class": "product_closed", "domain": ["concurrency", "rate_limit", "mcp_stream"]}], "buckets_seconds": [], "max_logical_series": 3, "max_rendered_series": 3},
|
||||
{"name": "crank_runtime_cache_total", "kind": "counter", "unit": "count", "help": "Runtime response cache outcomes.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "outcome", "class": "product_closed", "domain": ["hit", "miss", "read_error", "decode_error", "evict_error", "stored", "write_error"]}], "buckets_seconds": [], "max_logical_series": 7, "max_rendered_series": 7},
|
||||
{"name": "crank_idempotency_total", "kind": "counter", "unit": "count", "help": "Runtime idempotency outcomes.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "outcome", "class": "product_closed", "domain": ["execute", "replay", "completed", "conflict", "in_progress", "outcome_unknown", "store_unavailable", "error"]}], "buckets_seconds": [], "max_logical_series": 8, "max_rendered_series": 8},
|
||||
{"name": "crank_confirmation_total", "kind": "counter", "unit": "count", "help": "Runtime confirmation outcomes.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "outcome", "class": "product_closed", "domain": ["approved", "required", "invalid_token", "store_unavailable", "error"]}], "buckets_seconds": [], "max_logical_series": 5, "max_rendered_series": 5},
|
||||
{"name": "crank_db_pool_connections", "kind": "gauge", "unit": "count", "help": "PostgreSQL pool connections by state.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "state", "class": "product_closed", "domain": ["idle", "used"]}], "buckets_seconds": [], "max_logical_series": 2, "max_rendered_series": 2},
|
||||
{"name": "crank_catalog_tools", "kind": "gauge", "unit": "count", "help": "Tools in the current published catalog.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_catalog_estimated_context_tokens", "kind": "gauge", "unit": "count", "help": "Estimated context tokens in the current published catalog.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_catalog_warnings", "kind": "gauge", "unit": "count", "help": "Warnings in the current published catalog.", "processes": ["mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_invocation_history_lost_total", "kind": "counter", "unit": "count", "help": "Invocation history records lost after an action completed.", "processes": ["admin_api", "mcp_server"], "labels": [], "buckets_seconds": [], "max_logical_series": 1, "max_rendered_series": 1},
|
||||
{"name": "crank_telemetry_export_failures_total", "kind": "counter", "unit": "count", "help": "Telemetry export failures.", "processes": ["admin_api", "mcp_server"], "labels": [{"name": "signal_type", "class": "product_closed", "domain": ["trace", "invocation_history"]},{"name": "exporter", "class": "product_closed", "domain": ["otlp", "postgres"]}], "buckets_seconds": [], "max_logical_series": 4, "max_rendered_series": 4}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user