feat(multiplayer): export queryable API latency histograms

This commit is contained in:
Josh Creek
2026-09-01 17:21:13 +01:00
parent 20f376f713
commit 0bf33e7fe8
3 changed files with 52 additions and 8 deletions
+21
View File
@@ -18,7 +18,28 @@ func TestMetricsNormalizesOperationsAndExportsBoundedLabels(t *testing.T) {
if !strings.Contains(text, `operation="queue",status="2xx"`) || !strings.Contains(text, `operation="other",status="5xx"`) {
t.Fatalf("metrics output = %s", text)
}
if !strings.Contains(text, "# TYPE cosmic_clash_api_latency_seconds histogram") ||
!strings.Contains(text, `cosmic_clash_api_latency_seconds_bucket{operation="queue",status="2xx",le="0.25"} 1`) ||
!strings.Contains(text, `cosmic_clash_api_latency_seconds_bucket{operation="queue",status="2xx",le="+Inf"} 1`) {
t.Fatalf("latency histogram missing expected buckets: %s", text)
}
if strings.Contains(text, "crafted") || strings.Contains(text, "secret") {
t.Fatalf("unbounded operation label leaked: %s", text)
}
}
func TestMetricsHistogramUsesCumulativeBoundarySemantics(t *testing.T) {
m := NewMetrics()
m.ObserveAPI("queue", 200, 250*time.Millisecond)
var output strings.Builder
if err := m.WritePrometheus(&output); err != nil {
t.Fatal(err)
}
text := output.String()
if !strings.Contains(text, `le="0.25"} 1`) || !strings.Contains(text, `le="0.5"} 1`) {
t.Fatalf("boundary observation was not cumulative: %s", text)
}
if strings.Contains(text, `le="0.1"} 1`) {
t.Fatalf("250ms observation entered an earlier bucket: %s", text)
}
}