| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package middleware
- import (
- "time"
- "github.com/gin-gonic/gin"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
- )
- // GinLoggerMiddleware Gin日志中间件
- func GinLoggerMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- // 记录请求开始时间
- start := time.Now()
- // 记录请求路径
- path := c.Request.URL.Path
- // 记录查询参数
- query := c.Request.URL.RawQuery
- // 处理请求
- c.Next()
- // 计算请求处理耗时
- latency := time.Since(start)
- // 获取响应状态码
- status := c.Writer.Status()
- // 获取客户端IP
- clientIP := c.ClientIP()
- // 获取请求方法
- method := c.Request.Method
- // 获取用户代理
- userAgent := c.Request.UserAgent()
- // 获取响应体大小
- bodySize := c.Writer.Size()
- // 获取错误信息(如果有)
- var errorMsg string
- if len(c.Errors) > 0 {
- errorMsg = c.Errors.String()
- }
- // 构建日志字段
- fields := []zapcore.Field{
- zap.Int("status", status), // 响应状态码
- zap.String("method", method), // 请求方法
- zap.String("path", path), // 请求路径
- zap.String("query", query), // 查询参数
- zap.String("ip", clientIP), // 客户端IP
- zap.String("user-agent", userAgent), // 用户代理
- zap.Duration("latency", latency), // 处理耗时
- zap.Int("body_size", bodySize), // 响应体大小
- zap.String("time", time.Now().Format("2006-01-02 15:04:05")), // 请求时间
- }
- // 如果存在错误,添加错误信息字段
- if errorMsg != "" {
- fields = append(fields, zap.String("error", errorMsg))
- }
- // 根据状态码级别记录日志
- switch {
- case status >= 500:
- // 服务器错误(5xx):使用Error级别
- zap.L().Error("服务器错误", fields...)
- case status >= 400:
- // 客户端错误(4xx):使用Warn级别
- zap.L().Warn("客户端错误", fields...)
- default:
- // 成功请求(2xx/3xx):使用Info级别
- zap.L().Info("请求完成", fields...)
- }
- }
- }
- // GinRecoveryMiddleware Gin恢复中间件(捕获panic)
- func GinRecoveryMiddleware() gin.HandlerFunc {
- return func(c *gin.Context) {
- defer func() {
- if err := recover(); err != nil {
- // 获取客户端IP
- clientIP := c.ClientIP()
- // 获取请求信息
- path := c.Request.URL.Path
- method := c.Request.Method
- // 记录panic详细信息
- zap.L().Error("请求发生panic",
- zap.Any("error", err), // panic错误
- zap.String("method", method), // 请求方法
- zap.String("path", path), // 请求路径
- zap.String("ip", clientIP), // 客户端IP
- zap.String("stack", string(zap.Stack("").String)), // 堆栈信息
- )
- // 返回500错误响应
- c.AbortWithStatusJSON(500, gin.H{
- "code": 500,
- "message": "服务器内部错误",
- })
- }
- }()
- c.Next()
- }
- }
|