package metrics import ( "net/http" "strconv" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" ) var ( requestsTotal = promauto.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "path", "status"}, ) requestDuration = promauto.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "Duration of HTTP requests", Buckets: prometheus.DefBuckets, }, []string{"method", "path"}, ) requestsInFlight = promauto.NewGauge(prometheus.GaugeOpts{ Name: "http_requests_in_flight", Help: "Number of HTTP requests currently in flight", }) ) func Handler() http.Handler { return promhttp.Handler() } type recorder struct { http.ResponseWriter status int } func (r *recorder) WriteHeader(code int) { r.status = code r.ResponseWriter.WriteHeader(code) } func Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { requestsInFlight.Inc() defer requestsInFlight.Dec() start := time.Now() rec := &recorder{ResponseWriter: w, status: http.StatusOK} next.ServeHTTP(rec, r) status := strconv.Itoa(rec.status) requestsTotal.WithLabelValues(r.Method, r.URL.Path, status).Inc() requestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(time.Since(start).Seconds()) }) }