package middleware import ( "fmt" "net/http" "runtime/debug" "fotbal-club/pkg/logger" "fotbal-club/internal/services" "github.com/gin-gonic/gin" ) // CustomRecovery returns a middleware that recovers from panics and logs them func CustomRecovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err != nil { // Get stack trace stack := string(debug.Stack()) // Log the panic requestID := GetRequestID(c) logger.Error("Panic recovered", "request_id", requestID, "error", fmt.Sprintf("%v", err), "stack", stack, "path", c.Request.URL.Path, "method", c.Request.Method, ) // Return error response c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal server error", "request_id": requestID, }) c.Abort() } }() c.Next() } } func CustomRecoveryWithReporter(reporter *services.ErrorReporter) gin.HandlerFunc { if reporter == nil { return CustomRecovery() } return func(c *gin.Context) { defer func() { if err := recover(); err != nil { stack := string(debug.Stack()) requestID := GetRequestID(c) logger.Error("Panic recovered", "request_id", requestID, "error", fmt.Sprintf("%v", err), "stack", stack, "path", c.Request.URL.Path, "method", c.Request.Method, ) reporter.Report(c.Request.Context(), &services.ErrorEvent{ Origin: "backend", Language: "go", Severity: "fatal", Message: fmt.Sprintf("%v", err), Stack: stack, URL: c.Request.URL.Path, Method: c.Request.Method, RequestID: requestID, }) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal server error", "request_id": requestID, }) c.Abort() } }() c.Next() } }