package middleware import ( "time" "github.com/gin-gonic/gin" "log/slog" ) // GinLogger 用结构化日志(slog,由 main 设为 JSON handler)记录每个请求, // 替代 gin 默认的 text logger,便于生产环境集中采集与检索。 func GinLogger() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() path := c.Request.URL.Path raw := c.Request.URL.RawQuery c.Next() // 跳过健康检查等高频噪声路径 if path == "/api/health" || path == "/api/v1/health" { return } latency := time.Since(start) status := c.Writer.Status() clientIP := c.ClientIP() method := c.Request.Method if raw != "" { path = path + "?" + raw } attrs := []slog.Attr{ slog.String("method", method), slog.String("path", path), slog.Int("status", status), slog.String("ip", clientIP), slog.Duration("latency", latency), } if len(c.Errors) > 0 { attrs = append(attrs, slog.String("error", c.Errors.ByType(gin.ErrorTypePrivate).String())) } switch { case status >= 500: slog.LogAttrs(c.Request.Context(), slog.LevelError, "request", attrs...) case status >= 400: slog.LogAttrs(c.Request.Context(), slog.LevelWarn, "request", attrs...) default: slog.LogAttrs(c.Request.Context(), slog.LevelInfo, "request", attrs...) } } }