104 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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()
 | ||
| 	}
 | ||
| }  |