logger.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package middleware
  2. import (
  3. "time"
  4. "github.com/gin-gonic/gin"
  5. "go.uber.org/zap"
  6. "go.uber.org/zap/zapcore"
  7. )
  8. // GinLoggerMiddleware Gin日志中间件
  9. func GinLoggerMiddleware() gin.HandlerFunc {
  10. return func(c *gin.Context) {
  11. // 记录请求开始时间
  12. start := time.Now()
  13. // 记录请求路径
  14. path := c.Request.URL.Path
  15. // 记录查询参数
  16. query := c.Request.URL.RawQuery
  17. // 处理请求
  18. c.Next()
  19. // 计算请求处理耗时
  20. latency := time.Since(start)
  21. // 获取响应状态码
  22. status := c.Writer.Status()
  23. // 获取客户端IP
  24. clientIP := c.ClientIP()
  25. // 获取请求方法
  26. method := c.Request.Method
  27. // 获取用户代理
  28. userAgent := c.Request.UserAgent()
  29. // 获取响应体大小
  30. bodySize := c.Writer.Size()
  31. // 获取错误信息(如果有)
  32. var errorMsg string
  33. if len(c.Errors) > 0 {
  34. errorMsg = c.Errors.String()
  35. }
  36. // 构建日志字段
  37. fields := []zapcore.Field{
  38. zap.Int("status", status), // 响应状态码
  39. zap.String("method", method), // 请求方法
  40. zap.String("path", path), // 请求路径
  41. zap.String("query", query), // 查询参数
  42. zap.String("ip", clientIP), // 客户端IP
  43. zap.String("user-agent", userAgent), // 用户代理
  44. zap.Duration("latency", latency), // 处理耗时
  45. zap.Int("body_size", bodySize), // 响应体大小
  46. zap.String("time", time.Now().Format("2006-01-02 15:04:05")), // 请求时间
  47. }
  48. // 如果存在错误,添加错误信息字段
  49. if errorMsg != "" {
  50. fields = append(fields, zap.String("error", errorMsg))
  51. }
  52. // 根据状态码级别记录日志
  53. switch {
  54. case status >= 500:
  55. // 服务器错误(5xx):使用Error级别
  56. zap.L().Error("服务器错误", fields...)
  57. case status >= 400:
  58. // 客户端错误(4xx):使用Warn级别
  59. zap.L().Warn("客户端错误", fields...)
  60. default:
  61. // 成功请求(2xx/3xx):使用Info级别
  62. zap.L().Info("请求完成", fields...)
  63. }
  64. }
  65. }
  66. // GinRecoveryMiddleware Gin恢复中间件(捕获panic)
  67. func GinRecoveryMiddleware() gin.HandlerFunc {
  68. return func(c *gin.Context) {
  69. defer func() {
  70. if err := recover(); err != nil {
  71. // 获取客户端IP
  72. clientIP := c.ClientIP()
  73. // 获取请求信息
  74. path := c.Request.URL.Path
  75. method := c.Request.Method
  76. // 记录panic详细信息
  77. zap.L().Error("请求发生panic",
  78. zap.Any("error", err), // panic错误
  79. zap.String("method", method), // 请求方法
  80. zap.String("path", path), // 请求路径
  81. zap.String("ip", clientIP), // 客户端IP
  82. zap.String("stack", string(zap.Stack("").String)), // 堆栈信息
  83. )
  84. // 返回500错误响应
  85. c.AbortWithStatusJSON(500, gin.H{
  86. "code": 500,
  87. "message": "服务器内部错误",
  88. })
  89. }
  90. }()
  91. c.Next()
  92. }
  93. }