package trace import ( "time" "github.com/gin-gonic/gin" ) // GinLogger 记录每个 HTTP 请求的 method/path/status/latency func GinLogger() 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).Milliseconds() status := c.Writer.Status() log := FromContext(c.Request.Context()) fields := []interface{}{ "method", c.Request.Method, "path", path, "status", status, "latency_ms", latency, "client_ip", c.ClientIP(), } if query != "" { fields = append(fields, "query", query) } if errStr := c.Errors.String(); errStr != "" { fields = append(fields, "errors", errStr) } switch { case status >= 500: log.Errorw("request completed", fields...) case status >= 400: log.Warnw("request completed", fields...) default: log.Infow("request completed", fields...) } } } // GinRecovery 自定义 panic 恢复中间件,使用 zap 记录 func GinRecovery() gin.HandlerFunc { return func(c *gin.Context) { defer func() { if err := recover(); err != nil { log := FromContext(c.Request.Context()) log.Errorw("panic recovered", "error", err, "path", c.Request.URL.Path, "method", c.Request.Method, "client_ip", c.ClientIP()) c.AbortWithStatus(500) } }() c.Next() } }