package metrics import ( "net/http" "strconv" "time" "github.com/gin-gonic/gin" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" ) // MetricsService interface defines the contract for metrics operations type MetricsService interface { RecordHTTPRequest(method, path string, statusCode int, duration time.Duration) RecordDBOperation(operation, table string) RecordAuthAttempt(action, result string) StartMetricsServer(port string) MetricsMiddleware() gin.HandlerFunc } // PrometheusMetricsService implements MetricsService using Prometheus type PrometheusMetricsService struct { httpRequestsTotal *prometheus.CounterVec httpRequestDuration *prometheus.HistogramVec dbOperationsTotal *prometheus.CounterVec authAttemptsTotal *prometheus.CounterVec } // NewPrometheusMetricsService creates a new Prometheus metrics service func NewPrometheusMetricsService() MetricsService { return &PrometheusMetricsService{ httpRequestsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total number of HTTP requests", }, []string{"method", "path", "status"}, ), httpRequestDuration: promauto.NewHistogramVec( prometheus.HistogramOpts{ Name: "http_request_duration_seconds", Help: "HTTP request duration in seconds", Buckets: prometheus.DefBuckets, }, []string{"method", "path"}, ), dbOperationsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "db_operations_total", Help: "Total number of database operations", }, []string{"operation", "table"}, ), authAttemptsTotal: promauto.NewCounterVec( prometheus.CounterOpts{ Name: "auth_attempts_total", Help: "Total number of authentication attempts", }, []string{"action", "result"}, ), } } // RecordHTTPRequest records an HTTP request func (m *PrometheusMetricsService) RecordHTTPRequest(method, path string, statusCode int, duration time.Duration) { status := strconv.Itoa(statusCode) m.httpRequestsTotal.WithLabelValues(method, path, status).Inc() m.httpRequestDuration.WithLabelValues(method, path).Observe(duration.Seconds()) } // RecordDBOperation records a database operation func (m *PrometheusMetricsService) RecordDBOperation(operation, table string) { m.dbOperationsTotal.WithLabelValues(operation, table).Inc() } // RecordAuthAttempt records an authentication attempt func (m *PrometheusMetricsService) RecordAuthAttempt(action, result string) { m.authAttemptsTotal.WithLabelValues(action, result).Inc() } // StartMetricsServer starts the Prometheus metrics server func (m *PrometheusMetricsService) StartMetricsServer(port string) { http.Handle("/metrics", promhttp.Handler()) go func() { if err := http.ListenAndServe(":"+port, nil); err != nil { // Log error but don't fail the application } }() } // MetricsMiddleware creates a Gin middleware for HTTP metrics func (m *PrometheusMetricsService) MetricsMiddleware() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Next() duration := time.Since(start) m.RecordHTTPRequest(c.Request.Method, c.FullPath(), c.Writer.Status(), duration) } }