metrics: emit default quality-gate counters when file missing

This commit is contained in:
Brad Stein 2026-04-09 02:08:55 -03:00
parent af2d94a53b
commit fba6c2c940
2 changed files with 35 additions and 0 deletions

View File

@ -180,10 +180,12 @@ func appendQualityGateMetrics(dst *strings.Builder) {
} }
raw, err := os.ReadFile(path) raw, err := os.ReadFile(path)
if err != nil { if err != nil {
appendDefaultQualityGateMetrics(dst)
return return
} }
text := strings.TrimSpace(string(raw)) text := strings.TrimSpace(string(raw))
if text == "" { if text == "" {
appendDefaultQualityGateMetrics(dst)
return return
} }
if dst.Len() > 0 { if dst.Len() > 0 {
@ -195,6 +197,20 @@ func appendQualityGateMetrics(dst *strings.Builder) {
} }
} }
// appendDefaultQualityGateMetrics runs one orchestration or CLI step.
// Signature: appendDefaultQualityGateMetrics(dst *strings.Builder).
// Why: Grafana should always have baseline Ananke quality-gate series so
// overview panels never show "no data" before the first host-side gate run.
func appendDefaultQualityGateMetrics(dst *strings.Builder) {
if dst.Len() > 0 {
dst.WriteString("\n")
}
dst.WriteString("# HELP ananke_quality_gate_runs_total Total Ananke quality gate runs by status.\n")
dst.WriteString("# TYPE ananke_quality_gate_runs_total counter\n")
dst.WriteString("ananke_quality_gate_runs_total{suite=\"ananke\",status=\"ok\"} 0\n")
dst.WriteString("ananke_quality_gate_runs_total{suite=\"ananke\",status=\"failed\"} 0\n")
}
// boolNum runs one orchestration or CLI step. // boolNum runs one orchestration or CLI step.
// Signature: boolNum(v bool) int. // Signature: boolNum(v bool) int.
// Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve. // Why: keeps behavior explicit so startup/shutdown workflows remain maintainable as services evolve.

View File

@ -84,3 +84,22 @@ func TestExporterAppendsQualityGateMetrics(t *testing.T) {
t.Fatalf("expected quality gate metrics appended to exporter output, got:\n%s", body) t.Fatalf("expected quality gate metrics appended to exporter output, got:\n%s", body)
} }
} }
// TestExporterDefaultsQualityGateMetrics runs one orchestration or CLI step.
// Signature: TestExporterDefaultsQualityGateMetrics(t *testing.T).
// Why: ensures Grafana panels see zero-value quality-gate series instead of
// "no data" before host-side quality-gate files exist.
func TestExporterDefaultsQualityGateMetrics(t *testing.T) {
t.Setenv("ANANKE_QUALITY_METRICS_FILE", filepath.Join(t.TempDir(), "missing.prom"))
e := New()
req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
rr := httptest.NewRecorder()
e.Handler("/metrics").ServeHTTP(rr, req)
body := rr.Body.String()
if !strings.Contains(body, `ananke_quality_gate_runs_total{suite="ananke",status="ok"} 0`) {
t.Fatalf("expected default ok=0 quality gate metric, got:\n%s", body)
}
if !strings.Contains(body, `ananke_quality_gate_runs_total{suite="ananke",status="failed"} 0`) {
t.Fatalf("expected default failed=0 quality gate metric, got:\n%s", body)
}
}