Files
story/internal/httpapi/metrics.go
T

67 lines
2.2 KiB
Go

package httpapi
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 (
httpRequests = promauto.NewCounterVec(prometheus.CounterOpts{
Namespace: "voice_platform", Subsystem: "http", Name: "requests_total",
Help: "Total HTTP requests by service, method, route and status.",
}, []string{"service", "method", "route", "status"})
httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Namespace: "voice_platform", Subsystem: "http", Name: "request_duration_seconds",
Help: "HTTP request duration by service, method and route.",
Buckets: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5},
}, []string{"service", "method", "route"})
httpInflight = promauto.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "voice_platform", Subsystem: "http", Name: "inflight_requests",
Help: "Current in-flight HTTP requests by service.",
}, []string{"service"})
)
func MetricsHandler() http.Handler { return promhttp.Handler() }
func metricsMiddleware(serviceName string, next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
startedAt := time.Now()
httpInflight.WithLabelValues(serviceName).Inc()
defer httpInflight.WithLabelValues(serviceName).Dec()
recorder := &statusRecorder{ResponseWriter: writer, status: http.StatusOK}
defer func() {
route := request.Pattern
if route == "" {
route = "unmatched"
}
httpRequests.WithLabelValues(serviceName, request.Method, route, strconv.Itoa(recorder.status)).Inc()
httpDuration.WithLabelValues(serviceName, request.Method, route).Observe(time.Since(startedAt).Seconds())
}()
next.ServeHTTP(recorder, request)
})
}
type statusRecorder struct {
http.ResponseWriter
status int
bytes int
}
func (r *statusRecorder) WriteHeader(status int) {
r.status = status
r.ResponseWriter.WriteHeader(status)
}
func (r *statusRecorder) Write(body []byte) (int, error) {
written, err := r.ResponseWriter.Write(body)
r.bytes += written
return written, err
}
func (r *statusRecorder) Unwrap() http.ResponseWriter { return r.ResponseWriter }