package logger import ( "time" "github.com/break/junhong_cmp_fiber/pkg/constants" "github.com/gofiber/fiber/v2" "go.uber.org/zap" ) const ( // MaxBodyLogSize 限制记录的请求/响应 body 大小为 50KB MaxBodyLogSize = 50 * 1024 ) // truncateBody 截断 body 到指定大小 func truncateBody(body []byte, maxSize int) string { if len(body) == 0 { return "" } if len(body) <= maxSize { return string(body) } // 超过限制,截断并添加提示 return string(body[:maxSize]) + "... (truncated)" } // Middleware 创建 Fiber 日志中间件 // 记录所有 HTTP 请求到访问日志(包括请求和响应 body) func Middleware() fiber.Handler { return func(c *fiber.Ctx) error { // 记录请求开始时间 startTime := time.Now() c.Locals(constants.ContextKeyStartTime, startTime) // 获取请求 body(在 c.Next() 之前读取) requestBody := truncateBody(c.Body(), MaxBodyLogSize) // 获取 query 参数 queryParams := string(c.Request().URI().QueryString()) // 处理请求 err := c.Next() // 计算请求持续时间 duration := time.Since(startTime) // 获取请求 ID(由 requestid 中间件设置) requestID := "" if rid := c.Locals(constants.ContextKeyRequestID); rid != nil { requestID = rid.(string) } // 获取用户 ID(由 auth 中间件设置) userID := "" if uid := c.Locals(constants.ContextKeyUserID); uid != nil { userID = uid.(string) } // 获取响应 body responseBody := truncateBody(c.Response().Body(), MaxBodyLogSize) // 记录访问日志 accessLogger := GetAccessLogger() accessLogger.Info("", zap.String("method", c.Method()), zap.String("path", c.Path()), zap.String("query", queryParams), zap.Int("status", c.Response().StatusCode()), zap.Float64("duration_ms", float64(duration.Microseconds())/1000.0), zap.String("request_id", requestID), zap.String("ip", c.IP()), zap.String("user_agent", c.Get("User-Agent")), zap.String(constants.ContextKeyUserID, userID), zap.String("request_body", requestBody), zap.String("response_body", responseBody), ) return err } }