package middleware import ( "net/http" "runtime/debug" "time" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // PanicRecoveryMiddleware Panic恢复中间件 type PanicRecoveryMiddleware struct { logger *zap.Logger } // NewPanicRecoveryMiddleware 创建Panic恢复中间件 func NewPanicRecoveryMiddleware(logger *zap.Logger) *PanicRecoveryMiddleware { return &PanicRecoveryMiddleware{ logger: logger, } } // GetName 返回中间件名称 func (m *PanicRecoveryMiddleware) GetName() string { return "panic_recovery" } // GetPriority 返回中间件优先级 func (m *PanicRecoveryMiddleware) GetPriority() int { return 100 // 最高优先级,第一个执行 } // Handle 返回中间件处理函数 func (m *PanicRecoveryMiddleware) Handle() gin.HandlerFunc { return gin.RecoveryWithWriter(&panicLogger{logger: m.logger}) } // IsGlobal 是否为全局中间件 func (m *PanicRecoveryMiddleware) IsGlobal() bool { return true } // panicLogger 实现io.Writer接口,用于记录panic信息 type panicLogger struct { logger *zap.Logger } // Write 实现io.Writer接口 func (pl *panicLogger) Write(p []byte) (n int, err error) { pl.logger.Error("系统发生严重错误", zap.String("error_type", "panic"), zap.String("stack_trace", string(p)), zap.String("timestamp", time.Now().Format("2006-01-02 15:04:05")), ) return len(p), nil } // CustomPanicRecovery 自定义panic恢复中间件 func (m *PanicRecoveryMiddleware) CustomPanicRecovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err != nil { // 获取请求信息 requestID := c.GetString("request_id") traceID := c.GetString("trace_id") userID := c.GetString("user_id") clientIP := c.ClientIP() method := c.Request.Method path := c.Request.URL.Path userAgent := c.Request.UserAgent() // 记录详细的panic信息 m.logger.Error("系统发生严重错误", zap.Any("panic_error", err), zap.String("error_type", "panic"), zap.String("request_id", requestID), zap.String("trace_id", traceID), zap.String("user_id", userID), zap.String("client_ip", clientIP), zap.String("method", method), zap.String("path", path), zap.String("user_agent", userAgent), zap.String("stack_trace", string(debug.Stack())), zap.String("timestamp", time.Now().Format("2006-01-02 15:04:05")), ) // 返回500错误响应 c.JSON(http.StatusInternalServerError, gin.H{ "success": false, "message": "服务器内部错误", "error_code": "INTERNAL_SERVER_ERROR", "request_id": requestID, "timestamp": time.Now().Unix(), }) // 中止请求处理 c.Abort() } }() c.Next() } }