138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
)
|
|
|
|
var (
|
|
// HTTP request metrics
|
|
httpRequestsTotal = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "http_requests_total",
|
|
Help: "Total number of HTTP requests",
|
|
},
|
|
[]string{"method", "endpoint", "status_code"},
|
|
)
|
|
|
|
// HTTP request duration metrics
|
|
httpRequestDuration = prometheus.NewHistogramVec(
|
|
prometheus.HistogramOpts{
|
|
Name: "http_request_duration_seconds",
|
|
Help: "HTTP request duration in seconds",
|
|
Buckets: prometheus.DefBuckets,
|
|
},
|
|
[]string{"method", "endpoint"},
|
|
)
|
|
|
|
// API endpoint specific metrics
|
|
apiRequestsTotal = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "api_requests_total",
|
|
Help: "Total number of API requests by endpoint",
|
|
},
|
|
[]string{"endpoint", "method"},
|
|
)
|
|
|
|
// Database operation metrics
|
|
dbOperationsTotal = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "db_operations_total",
|
|
Help: "Total number of database operations",
|
|
},
|
|
[]string{"operation", "table"},
|
|
)
|
|
|
|
// Authentication metrics
|
|
authAttemptsTotal = prometheus.NewCounterVec(
|
|
prometheus.CounterOpts{
|
|
Name: "auth_attempts_total",
|
|
Help: "Total number of authentication attempts",
|
|
},
|
|
[]string{"type", "status"},
|
|
)
|
|
)
|
|
|
|
// InitMetrics initializes Prometheus metrics
|
|
func InitMetrics() {
|
|
// Register all metrics
|
|
prometheus.MustRegister(httpRequestsTotal)
|
|
prometheus.MustRegister(httpRequestDuration)
|
|
prometheus.MustRegister(apiRequestsTotal)
|
|
prometheus.MustRegister(dbOperationsTotal)
|
|
prometheus.MustRegister(authAttemptsTotal)
|
|
}
|
|
|
|
// StartMetricsServer starts the metrics server on a separate port
|
|
func StartMetricsServer(port string) {
|
|
// Create a new HTTP server for metrics
|
|
metricsMux := http.NewServeMux()
|
|
metricsMux.Handle("/metrics", promhttp.Handler())
|
|
|
|
// Add health check for metrics server
|
|
metricsMux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("Metrics server is healthy"))
|
|
})
|
|
|
|
server := &http.Server{
|
|
Addr: "localhost:" + port,
|
|
Handler: metricsMux,
|
|
ReadTimeout: 5 * time.Second,
|
|
WriteTimeout: 10 * time.Second,
|
|
}
|
|
|
|
go func() {
|
|
Logger.Printf("📈 Metrics server starting on http://localhost:%s/metrics", port)
|
|
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
Logger.Printf("❌ Metrics server failed to start: %v", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
// MetricsMiddleware is a Gin middleware to collect HTTP metrics
|
|
func MetricsMiddleware() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
start := time.Now()
|
|
path := c.FullPath()
|
|
method := c.Request.Method
|
|
|
|
// Process request
|
|
c.Next()
|
|
|
|
// Calculate duration
|
|
duration := time.Since(start).Seconds()
|
|
statusCode := strconv.Itoa(c.Writer.Status())
|
|
|
|
// Record metrics
|
|
httpRequestsTotal.WithLabelValues(method, path, statusCode).Inc()
|
|
httpRequestDuration.WithLabelValues(method, path).Observe(duration)
|
|
|
|
// Record API-specific metrics for API routes
|
|
if strings.HasPrefix(c.Request.URL.Path, "/api") {
|
|
apiRequestsTotal.WithLabelValues(path, method).Inc()
|
|
}
|
|
}
|
|
}
|
|
|
|
// RecordAPICall records a specific API endpoint call
|
|
func RecordAPICall(endpoint, method string) {
|
|
apiRequestsTotal.WithLabelValues(endpoint, method).Inc()
|
|
}
|
|
|
|
// RecordDBOperation records a database operation
|
|
func RecordDBOperation(operation, table string) {
|
|
dbOperationsTotal.WithLabelValues(operation, table).Inc()
|
|
}
|
|
|
|
// RecordAuthAttempt records an authentication attempt
|
|
func RecordAuthAttempt(authType, status string) {
|
|
authAttemptsTotal.WithLabelValues(authType, status).Inc()
|
|
}
|