mirror of
https://github.com/nais/wonderwall.git
synced 2026-05-08 09:27:12 +00:00
82 lines
2.5 KiB
Go
82 lines
2.5 KiB
Go
// This code was originally written by Rene Zbinden and modified by Vladimir Konovalov.
|
|
// Copied from https://github.com/766b/chi-prometheus and further adapted.
|
|
|
|
package middleware
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
|
|
chi_middleware "github.com/go-chi/chi/v5/middleware"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
|
|
"github.com/nais/wonderwall/pkg/metrics"
|
|
)
|
|
|
|
var defaultBuckets = []float64{.001, .01, .05, .1, .5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
|
|
|
|
const (
|
|
serviceName = "wonderwall"
|
|
reqsName = "requests_total"
|
|
latencyName = "request_duration_seconds"
|
|
)
|
|
|
|
// PrometheusMiddleware is a handler that exposes prometheus metrics for the number of requests,
|
|
// the latency and the response size, partitioned by status code, method and HTTP path.
|
|
type PrometheusMiddleware struct {
|
|
reqs *prometheus.CounterVec
|
|
latency *prometheus.HistogramVec
|
|
}
|
|
|
|
// Prometheus returns a new PrometheusMiddleware handler.
|
|
func Prometheus(provider string, buckets ...float64) *PrometheusMiddleware {
|
|
var m PrometheusMiddleware
|
|
m.reqs = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: reqsName,
|
|
Help: "How many HTTP requests processed, partitioned by status code, method and HTTP path.",
|
|
ConstLabels: prometheus.Labels{"service": serviceName, metrics.LabelProvider: provider},
|
|
},
|
|
[]string{"code", "method", "path", "host"},
|
|
)
|
|
|
|
if len(buckets) == 0 {
|
|
buckets = defaultBuckets
|
|
}
|
|
m.latency = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
|
Name: latencyName,
|
|
Help: "How long it took to process the request, partitioned by status code, method and HTTP path.",
|
|
ConstLabels: prometheus.Labels{"service": serviceName, metrics.LabelProvider: provider},
|
|
Buckets: buckets,
|
|
},
|
|
[]string{"code", "method", "path", "host"},
|
|
)
|
|
|
|
prometheus.Register(m.reqs)
|
|
prometheus.Register(m.latency)
|
|
|
|
return &m
|
|
}
|
|
|
|
func (m *PrometheusMiddleware) Initialize(path, method string, code int) {
|
|
m.reqs.WithLabelValues(
|
|
strconv.Itoa(code),
|
|
method,
|
|
path,
|
|
)
|
|
}
|
|
|
|
func (m *PrometheusMiddleware) Handler(next http.Handler) http.Handler {
|
|
fn := func(w http.ResponseWriter, r *http.Request) {
|
|
start := time.Now()
|
|
ww := chi_middleware.NewWrapResponseWriter(w, r.ProtoMajor)
|
|
next.ServeHTTP(ww, r)
|
|
statusCode := strconv.Itoa(ww.Status())
|
|
duration := time.Since(start)
|
|
m.reqs.WithLabelValues(statusCode, r.Method, r.URL.Path, r.Host).Inc()
|
|
m.latency.WithLabelValues(statusCode, r.Method, r.URL.Path, r.Host).Observe(duration.Seconds())
|
|
}
|
|
return http.HandlerFunc(fn)
|
|
}
|