You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func scrape(t *testing.T, m *Metrics) string {
|
||||
t.Helper()
|
||||
rec := httptest.NewRecorder()
|
||||
req := httptest.NewRequest("GET", "/metrics", nil)
|
||||
m.Handler().ServeHTTP(rec, req)
|
||||
if rec.Code != 200 {
|
||||
t.Fatalf("metrics handler status = %d, want 200", rec.Code)
|
||||
}
|
||||
body, _ := io.ReadAll(rec.Result().Body)
|
||||
return string(body)
|
||||
}
|
||||
|
||||
func TestNewRegistersAllCollectors(t *testing.T) {
|
||||
m := New(func() float64 { return 3 }, func() float64 { return 12.5 })
|
||||
// CounterVecs emit no series until a label set is observed; touch each once
|
||||
// so the metric family name surfaces in the scrape.
|
||||
m.RecordSessionExit("exited")
|
||||
m.RecordPermissionDecision("auto")
|
||||
m.RecordDeadLetter("webhook.deliver")
|
||||
body := scrape(t, m)
|
||||
|
||||
for _, name := range []string{
|
||||
"acp_sessions_active",
|
||||
"acp_session_exit_total",
|
||||
"acp_permission_decisions_total",
|
||||
"jobs_dead_letter_total",
|
||||
"llm_cost_usd_total",
|
||||
} {
|
||||
if !strings.Contains(body, name) {
|
||||
t.Errorf("metrics output missing %q\n%s", name, body)
|
||||
}
|
||||
}
|
||||
// GaugeFunc values surface immediately even without any Record* call.
|
||||
if !strings.Contains(body, "acp_sessions_active 3") {
|
||||
t.Errorf("acp_sessions_active gauge not reporting func value; body:\n%s", body)
|
||||
}
|
||||
if !strings.Contains(body, "llm_cost_usd_total 12.5") {
|
||||
t.Errorf("llm_cost_usd_total gauge not reporting func value; body:\n%s", body)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecordHelpersIncrementWithLabels(t *testing.T) {
|
||||
m := New(nil, nil)
|
||||
m.RecordSessionExit("crashed")
|
||||
m.RecordSessionExit("crashed")
|
||||
m.RecordSessionExit("exited")
|
||||
m.RecordPermissionDecision("approved")
|
||||
m.RecordPermissionDecision("denied")
|
||||
m.RecordPermissionDecision("expired")
|
||||
m.RecordDeadLetter("webhook.deliver")
|
||||
|
||||
body := scrape(t, m)
|
||||
wants := []string{
|
||||
`acp_session_exit_total{status="crashed"} 2`,
|
||||
`acp_session_exit_total{status="exited"} 1`,
|
||||
`acp_permission_decisions_total{outcome="approved"} 1`,
|
||||
`acp_permission_decisions_total{outcome="denied"} 1`,
|
||||
`acp_permission_decisions_total{outcome="expired"} 1`,
|
||||
`jobs_dead_letter_total{type="webhook.deliver"} 1`,
|
||||
}
|
||||
for _, w := range wants {
|
||||
if !strings.Contains(body, w) {
|
||||
t.Errorf("metrics output missing %q\n%s", w, body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryIsolatedNotGlobalDefault(t *testing.T) {
|
||||
// Two independent Metrics must not collide (would panic if both used the
|
||||
// global default registry).
|
||||
_ = New(nil, nil)
|
||||
_ = New(nil, nil)
|
||||
}
|
||||
|
||||
func TestNilReceiverRecordSafe(t *testing.T) {
|
||||
var m *Metrics
|
||||
// Must not panic — callers may hold a nil *Metrics when metrics disabled.
|
||||
m.RecordSessionExit("exited")
|
||||
m.RecordPermissionDecision("auto")
|
||||
m.RecordDeadLetter("x")
|
||||
}
|
||||
Reference in New Issue
Block a user