- 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.
111 lines
2.6 KiB
Go
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)
|
|
}
|
|
}
|