diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index 6c8bac4..41104d6 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/gorilla/mux" "github.com/prometheus/client_golang/prometheus" ) @@ -45,21 +46,36 @@ func NewPrometheusMiddleware() *PrometheusMiddleware { } } -func (i *PrometheusMiddleware) Handler(next http.Handler) http.Handler { +func (p *PrometheusMiddleware) Handler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { begin := time.Now() interceptor := &interceptor{ResponseWriter: w, statusCode: http.StatusOK} - path := urlToLabel(r.URL.Path) + path := p.getRouteName(r) next.ServeHTTP(interceptor, r) var ( status = strconv.Itoa(interceptor.statusCode) took = time.Since(begin) ) - i.Histogram.WithLabelValues(r.Method, path, status).Observe(took.Seconds()) - i.Counter.WithLabelValues(status).Inc() + p.Histogram.WithLabelValues(r.Method, path, status).Observe(took.Seconds()) + p.Counter.WithLabelValues(status).Inc() }) } +// converts gorilla mux routes from '/api/delay/{wait}' to 'api_delay_wait' +func (p *PrometheusMiddleware) getRouteName(r *http.Request) string { + if mux.CurrentRoute(r) != nil { + if name := mux.CurrentRoute(r).GetName(); len(name) > 0 { + return urlToLabel(name) + } + if path, err := mux.CurrentRoute(r).GetPathTemplate(); err == nil { + if len(path) > 0 { + return urlToLabel(path) + } + } + } + return urlToLabel(r.RequestURI) +} + var invalidChars = regexp.MustCompile(`[^a-zA-Z0-9]+`) // converts a URL path to a string compatible with Prometheus label value. diff --git a/pkg/api/server.go b/pkg/api/server.go index 8a47333..b1199a1 100644 --- a/pkg/api/server.go +++ b/pkg/api/server.go @@ -61,16 +61,16 @@ func (s *Server) registerHandlers() { s.router.HandleFunc("/", s.infoHandler).Methods("GET") s.router.HandleFunc("/version", s.versionHandler).Methods("GET") s.router.HandleFunc("/echo", s.echoHandler).Methods("POST") - s.router.HandleFunc("/headers", s.echoHeadersHandler).Methods("GET") - s.router.HandleFunc("/delay/{wait:[0-9]+}", s.delayHandler).Methods("GET") + s.router.HandleFunc("/headers", s.echoHeadersHandler).Methods("GET", "POST") + s.router.HandleFunc("/delay/{wait:[0-9]+}", s.delayHandler).Methods("GET").Name("delay") s.router.HandleFunc("/healthz", s.healthzHandler).Methods("GET") s.router.HandleFunc("/readyz", s.readyzHandler).Methods("GET") s.router.HandleFunc("/readyz/enable", s.enableReadyHandler).Methods("POST") s.router.HandleFunc("/readyz/disable", s.disableReadyHandler).Methods("POST") s.router.HandleFunc("/panic", s.panicHandler).Methods("GET") - s.router.HandleFunc("/status/{code:[0-9]+}", s.statusHandler).Methods("GET", "POST", "PUT") + s.router.HandleFunc("/status/{code:[0-9]+}", s.statusHandler).Methods("GET", "POST", "PUT").Name("status") s.router.HandleFunc("/store", s.storeWriteHandler).Methods("POST") - s.router.HandleFunc("/store/{hash}", s.storeReadHandler).Methods("GET") + s.router.HandleFunc("/store/{hash}", s.storeReadHandler).Methods("GET").Name("store") s.router.HandleFunc("/configs", s.configReadHandler).Methods("GET") s.router.HandleFunc("/api/info", s.infoHandler).Methods("GET") s.router.HandleFunc("/api/echo", s.echoHandler).Methods("POST")