Add gauge/counter semantics to metric declarations (ticket 097)

Metrics previously only declared a data type (String/Number/...), so
rate() could be applied to a point-in-time gauge reading and sum()/avg()
could be applied directly to a cumulative counter reading with no guard
against either. Adds a MetricSemantics enum (Gauge, default; Counter)
threaded through DeclareMetricRequest, the engine's MetricDeclaration
data value, profile persistence, the API/MCP declaration routes, and the
Metrics panel's declaration form, then uses it in evaluate_promql to
reject rate() on a declared gauge and bare sum()/avg() on a declared
counter (suggesting rate() first). The guard only applies to metrics
with a captured value_param — bare occurrence-count metrics are always
safe under both operations, so existing dashboards are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TeyhRfMYjMditek6geDRoQ
This commit is contained in:
Hugh Kaznowski
2026-09-07 12:30:06 +01:00
co-authored by Claude Sonnet 5
parent c3108677ce
commit 4a0fe92ce8
12 changed files with 299 additions and 55 deletions
+2
View File
@@ -486,6 +486,7 @@ async fn declare_metric(
value_param: request.value_param,
matched_labels: request.matched_labels,
unmatched_labels: request.unmatched_labels,
semantics: request.semantics,
};
(StatusCode::CREATED, Json(dto)).into_response()
}
@@ -526,6 +527,7 @@ async fn update_metric(
value_param: request.value_param,
matched_labels: request.matched_labels,
unmatched_labels: request.unmatched_labels,
semantics: request.semantics,
};
(StatusCode::OK, Json(dto)).into_response()
}