// Package metrics provides Prometheus metrics collection and instrumentation. package metrics import ( "net/http" "time" "github.com/gin-gonic/gin" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" ) // Metrics holds all Prometheus metrics. type Metrics struct { httpRequestDuration *prometheus.HistogramVec httpRequestTotal *prometheus.CounterVec httpErrorsTotal *prometheus.CounterVec registry *prometheus.Registry } // NewMetrics creates a new metrics registry with all metrics. func NewMetrics() *Metrics { registry := prometheus.NewRegistry() m := &Metrics{ registry: registry, httpRequestDuration: prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request duration in seconds", Buckets: prometheus.DefBuckets, }, []string{"method", "path", "status"}, ), httpRequestTotal: prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "path", "status"}, ), httpErrorsTotal: prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_errors_total", Help: "Total number of HTTP errors", }, []string{"method", "path", "status"}, ), } // Register all metrics registry.MustRegister(m.httpRequestDuration) registry.MustRegister(m.httpRequestTotal) registry.MustRegister(m.httpErrorsTotal) return m } // HTTPMiddleware returns a Gin middleware for collecting HTTP metrics. func (m *Metrics) HTTPMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() // Process request c.Next() // Calculate duration duration := time.Since(start).Seconds() // Get request details method := c.Request.Method path := c.FullPath() if path == "" { path = c.Request.URL.Path } status := c.Writer.Status() // Record metrics m.httpRequestDuration.WithLabelValues(method, path, http.StatusText(status)).Observe(duration) m.httpRequestTotal.WithLabelValues(method, path, http.StatusText(status)).Inc() // Record errors (4xx and 5xx) if status >= 400 { m.httpErrorsTotal.WithLabelValues(method, path, http.StatusText(status)).Inc() } } } // Handler returns an HTTP handler for the /metrics endpoint. func (m *Metrics) Handler() http.Handler { return promhttp.HandlerFor(m.registry, promhttp.HandlerOpts{}) } // Registry returns the Prometheus registry. func (m *Metrics) Registry() *prometheus.Registry { return m.registry }