package middleware import ( "fmt" "net/http" "runtime/debug" "fotbal-club/internal/services" "fotbal-club/pkg/logger" "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(fmt.Sprintf( "Panic recovered: request_id=%s error=%v path=%s method=%s stack=%s", requestID, err, c.Request.URL.Path, c.Request.Method, stack, )) // 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(fmt.Sprintf( "Panic recovered: request_id=%s error=%v path=%s method=%s stack=%s", requestID, err, c.Request.URL.Path, c.Request.Method, stack, )) 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() } }