package observability import ( "net/http" "time" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" ) // Metrics contains the Prometheus metrics for the application. type Metrics struct { RequestsTotal *prometheus.CounterVec RequestDuration *prometheus.HistogramVec DBQueriesTotal *prometheus.CounterVec DBQueryDuration *prometheus.HistogramVec } // NewMetrics creates and registers the Prometheus metrics. func NewMetrics(reg prometheus.Registerer) *Metrics { return &Metrics{ RequestsTotal: promauto.With(reg).NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests.", }, []string{"method", "path", "status"}, ), RequestDuration: promauto.With(reg).NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "Duration of HTTP requests.", Buckets: prometheus.DefBuckets, }, []string{"method", "path"}, ), DBQueriesTotal: promauto.With(reg).NewCounterVec( prometheus.CounterOpts{ Name: "db_queries_total", Help: "Total number of database queries.", }, []string{"operation", "status"}, ), DBQueryDuration: promauto.With(reg).NewHistogramVec( prometheus.HistogramOpts{ Name: "db_query_duration_seconds", Help: "Duration of database queries.", Buckets: prometheus.DefBuckets, }, []string{"operation", "status"}, ), } } // PrometheusMiddleware returns an HTTP middleware that records Prometheus metrics. func (m *Metrics) PrometheusMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() rw := &responseWriter{ResponseWriter: w} next.ServeHTTP(rw, r) duration := time.Since(start).Seconds() m.RequestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(duration) m.RequestsTotal.WithLabelValues(r.Method, r.URL.Path, http.StatusText(rw.statusCode)).Inc() }) } // PrometheusHandler returns an HTTP handler for serving Prometheus metrics. func PrometheusHandler(reg prometheus.Gatherer) http.Handler { return promhttp.HandlerFor(reg, promhttp.HandlerOpts{}) }