Files
tyapi-server/internal/shared/middleware/panic_recovery.go
2025-07-28 15:21:37 +08:00

104 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
}
}