fix: harden typed metrics review findings

This commit is contained in:
2026-08-14 13:50:04 +03:00
parent 996a5461de
commit b7face0e94
30 changed files with 722 additions and 382 deletions
+91 -3
View File
@@ -1,9 +1,11 @@
use std::collections::BTreeSet;
use crank_metrics::{
HTTP_ROUTE_DOMAIN, HttpRoute, MAX_LOGICAL_SERIES_PER_PROCESS, MAX_PRODUCT_LABELS_PER_FAMILY,
MAX_RENDERED_SERIES_PER_PROCESS, METRIC_SCHEMA_VERSION, metric_schema,
render_metric_schema_json, schema_budget, validate_budget,
HTTP_ROUTE_DOMAIN, HttpRoute, LabelClass, LabelDomain, MAX_LOGICAL_SERIES_PER_PROCESS,
MAX_PRODUCT_LABELS_PER_FAMILY, MAX_RENDERED_SERIES_PER_PROCESS, METRIC_SCHEMA_VERSION,
MetricDefinition, MetricKind, MetricProcess, MetricService, MetricUnit, metric_schema,
metric_schema_for_service, render_metric_schema_json, schema_budget, validate_budget,
validate_schema,
};
#[test]
@@ -98,3 +100,89 @@ fn exact_budget_math_counts_histogram_bucket_sum_and_count_series() {
);
}
}
#[test]
fn prometheus_reserved_and_digit_prefixed_label_names_are_rejected() {
static DOMAIN: LabelDomain = LabelDomain {
name: "valid",
class: LabelClass::ProductClosed,
values: &["value"],
};
for label in ["1invalid", "__reserved"] {
let mut domain = DOMAIN;
domain.name = label;
let definition = MetricDefinition {
name: "crank_test_total",
kind: MetricKind::Counter,
unit: MetricUnit::Count,
labels: Box::leak(vec![label].into_boxed_slice()),
label_domains: Box::leak(vec![domain].into_boxed_slice()),
buckets: &[],
processes: &[MetricProcess::AdminApi],
max_logical_series: 1,
max_rendered_series: 1,
description: "test metric",
};
assert!(validate_schema(&[definition]).is_err(), "accepted {label}");
}
}
#[test]
fn process_projection_excludes_mcp_only_metrics_from_admin() {
let admin = metric_schema_for_service(MetricService::AdminApi)
.map(|definition| definition.name)
.collect::<BTreeSet<_>>();
let mcp = metric_schema_for_service(MetricService::McpServer)
.map(|definition| definition.name)
.collect::<BTreeSet<_>>();
assert!(!admin.contains("crank_mcp_active_sessions"));
assert!(!admin.contains("crank_catalog_tools"));
assert!(mcp.contains("crank_mcp_active_sessions"));
assert!(admin.contains("crank_http_requests_total"));
assert!(mcp.contains("crank_http_requests_total"));
}
#[test]
fn registered_admin_and_mcp_routes_are_exactly_the_schema_domain() {
let admin_source = include_str!("../../../apps/admin-api/src/app.rs");
let mcp_source = include_str!("../../crank-community-mcp/src/app.rs");
let auth = ["/login", "/logout", "/session", "/profile", "/password"];
let admin_root = ["/capabilities", "/workspaces", "/workspaces/{workspace_id}"];
let mut actual = BTreeSet::from(["unmatched".to_owned()]);
for route in route_literals(admin_source) {
let canonical = if matches!(route.as_str(), "/health" | "/ready") {
route
} else if auth.contains(&route.as_str()) {
format!("/api/auth{route}")
} else if admin_root.contains(&route.as_str()) {
format!("/api/admin{route}")
} else {
format!("/api/admin/workspaces/{{workspace_id}}{route}")
};
actual.insert(canonical);
}
actual.extend(route_literals(mcp_source));
let expected = HTTP_ROUTE_DOMAIN
.iter()
.map(|route| (*route).to_owned())
.collect::<BTreeSet<_>>();
assert_eq!(actual, expected);
}
fn route_literals(source: &str) -> Vec<String> {
let mut routes = Vec::new();
let mut remaining = source;
while let Some(offset) = remaining.find(".route(") {
remaining = &remaining[offset + ".route(".len()..];
let Some(start) = remaining.find('"') else {
break;
};
let after_start = &remaining[start + 1..];
let Some(end) = after_start.find('"') else {
break;
};
routes.push(after_start[..end].to_owned());
remaining = &after_start[end + 1..];
}
routes
}