package obs import ( "net/http" "net/http/httptest" "strings" "testing" "github.com/go-chi/chi/v5" ) func TestMiddlewareRecordsMetrics(t *testing.T) { reg := NewRegistry() r := chi.NewRouter() r.Use(reg.Middleware) r.Get("/x/{id}", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusNoContent) }) r.Handle("/metrics", reg.Handler()) // One 2xx (204) request through the instrumented route. w := httptest.NewRecorder() r.ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/x/123", nil)) if w.Code != http.StatusNoContent { t.Fatalf("route status: got %d", w.Code) } // Scrape metrics. The scrape itself is recorded only after it returns, so its body reflects just the // prior /x request. mw := httptest.NewRecorder() r.ServeHTTP(mw, httptest.NewRequest(http.MethodGet, "/metrics", nil)) body := mw.Body.String() for _, want := range []string{ `mm_http_requests_total{class="2xx"} 1`, "mm_http_request_duration_seconds_count 1", "mm_http_request_duration_seconds_bucket", // in flight reads 1 here: the scrape itself is the in flight request, so assert presence not value. "mm_http_in_flight_requests ", } { if !strings.Contains(body, want) { t.Errorf("metrics output missing %q\n---\n%s", want, body) } } } func TestPoolStatsGauges(t *testing.T) { reg := NewRegistry() reg.SetPoolStats(func() map[string]float64 { return map[string]float64{"app_total": 3} }) w := httptest.NewRecorder() reg.Handler().ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/metrics", nil)) if !strings.Contains(w.Body.String(), `mm_db_pool{stat="app_total"} 3`) { t.Errorf("pool gauge missing:\n%s", w.Body.String()) } }