package metrics import ( "errors" "net/http" "net/http/httptest" "testing" "github.com/labstack/echo/v5" echoMiddleware "github.com/labstack/echo/v5/middleware" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/testutil" dto "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" ) func newEcho() *echo.Echo { e := echo.New() e.Use(Middleware()) e.Use(echoMiddleware.Recover()) e.GET("/items/:id", func(c *echo.Context) error { return c.String(http.StatusOK, "item") }) e.GET("/fail", func(c *echo.Context) error { return errors.New("broken") }) e.GET("/panic", func(c *echo.Context) error { panic("boom") }) return e } func serve(e *echo.Echo, method, target string) { e.ServeHTTP(httptest.NewRecorder(), httptest.NewRequest(method, target, nil)) } func requests(method, route, code string) float64 { return testutil.ToFloat64(httpRequests.WithLabelValues(method, route, code)) } func TestMiddlewareCountsRequestsByRoutePattern(t *testing.T) { e := newEcho() before := requests("GET", "/items/:id", "200") serve(e, http.MethodGet, "/items/1?x=secret") serve(e, http.MethodGet, "/items/2") assert.Equal(t, before+2, requests("GET", "/items/:id", "200")) assert.Equal(t, 0.0, requests("GET", "/items/1?x=secret", "200"), "the URL is never a label") assert.Equal(t, 0.0, requests("GET", "/items/1", "200")) } func TestMiddlewareRecordsErrorStatus(t *testing.T) { e := newEcho() failBefore := requests("GET", "/fail", "500") panicBefore := requests("GET", "/panic", "500") missingBefore := requests("GET", unmatchedRoute, "404") serve(e, http.MethodGet, "/fail") serve(e, http.MethodGet, "/panic") serve(e, http.MethodGet, "/no/such/page?q=1") assert.Equal(t, failBefore+1, requests("GET", "/fail", "500")) assert.Equal(t, panicBefore+1, requests("GET", "/panic", "500"), "Recover turns the panic into a 500") assert.Equal(t, missingBefore+1, requests("GET", unmatchedRoute, "404")) } func observations(method, route string) uint64 { m := &dto.Metric{} _ = httpDuration.WithLabelValues(method, route).(prometheus.Metric).Write(m) return m.GetHistogram().GetSampleCount() } func TestMiddlewareRecordsLatency(t *testing.T) { e := newEcho() before := observations("GET", "/items/:id") serve(e, http.MethodGet, "/items/1") assert.Equal(t, before+1, observations("GET", "/items/:id")) }