package middleware import ( "strconv" "time" "attune-heart-therapy/internal/errors" "attune-heart-therapy/internal/logger" "attune-heart-therapy/internal/monitoring" "github.com/gin-gonic/gin" ) // MonitoringMiddleware provides comprehensive request monitoring func MonitoringMiddleware() gin.HandlerFunc { monitor := monitoring.GetGlobalMonitor() log := logger.New("monitoring_middleware") return func(c *gin.Context) { start := time.Now() // Increment active requests monitor.MetricsCollector.IncrementActiveRequests() defer monitor.MetricsCollector.DecrementActiveRequests() // Process request c.Next() // Calculate duration duration := time.Since(start) // Get response status status := c.Writer.Status() // Record metrics monitor.MetricsCollector.RecordRequest( c.FullPath(), c.Request.Method, status, duration, ) // Track errors if any occurred if len(c.Errors) > 0 { err := c.Errors.Last() if appErr := errors.GetAppError(err.Err); appErr != nil { userID := "" if uid, exists := c.Get("user_id"); exists { if uidStr, ok := uid.(string); ok { userID = uidStr } else if uidUint, ok := uid.(uint); ok { userID = strconv.FormatUint(uint64(uidUint), 10) } } monitor.ErrorTracker.TrackError( c.Request.Context(), appErr, userID, c.FullPath(), ) } } // Log request completion fields := map[string]interface{}{ "method": c.Request.Method, "path": c.Request.URL.Path, "status": status, "duration_ms": duration.Milliseconds(), "client_ip": c.ClientIP(), "user_agent": c.Request.UserAgent(), } // Add user ID if available if userID, exists := c.Get("user_id"); exists { fields["user_id"] = userID } // Add trace ID if available if traceID, exists := c.Get("trace_id"); exists { fields["trace_id"] = traceID } // Log based on status and duration if status >= 500 { log.Error("Request completed with server error", nil, fields) } else if status >= 400 { log.Warn("Request completed with client error", fields) } else if duration > 5*time.Second { log.Warn("Slow request completed", fields) } else { log.Debug("Request completed", fields) } } } // HealthCheckMiddleware provides health check monitoring func HealthCheckMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Skip monitoring for health check endpoints to avoid noise if c.Request.URL.Path == "/health" || c.Request.URL.Path == "/health/detailed" { c.Next() return } // Apply monitoring for all other endpoints MonitoringMiddleware()(c) } }