backend-service/internal/middleware/monitoring.go
ats-tech25 ddfa2de49e feat(app): Implement comprehensive application lifecycle management
- Add new `app` package to manage application initialization and lifecycle
- Refactor `main.go` to use new application management approach
- Implement graceful shutdown with context timeout and signal handling
- Add dependency injection container initialization
- Enhance logging with configurable log levels and structured logging
- Update configuration loading and server initialization process
- Modify Jitsi configuration in `.env` for custom deployment
- Improve error handling and logging throughout application startup
- Centralize application startup and shutdown logic in single package
Introduces a more robust and flexible application management system with improved initialization, logging, and shutdown capabilities.
2025-11-07 19:22:26 +00:00

111 lines
2.6 KiB
Go

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)
}
}