add monitoring
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
aovantsev
2025-10-05 09:58:13 +03:00
parent ebf4bdeede
commit 85221dfb1f
9 changed files with 223 additions and 25 deletions

137
metrics.go Normal file
View File

@@ -0,0 +1,137 @@
package main
import (
"log"
"net/http"
"strconv"
"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() {
log.Printf("📈 Metrics server starting on http://localhost:%s/metrics", port)
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.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 c.Request.URL.Path[:4] == "/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()
}