生产环境禁用fiber.logger(),因其默认全量记录含authorization头的请求、无采样、阻塞i/o,导致ttfb增加0.5ms+;应改用zerolog等结构化日志库对接fiber.new()实例。

别用 fiber.Logger() 上生产——它默认打全量请求(含 Authorization 头)、不采样、阻塞 I/O,QPS 高时 TTFB 直接涨 0.5ms+。真正可用的日志中间件得自己写,或用结构化日志库对接 fiber.New() 实例。
为什么 fiber.Logger() 不适合生产环境
fiber.Logger() 是开发快捷工具,不是生产日志方案。它在 fiber.Default() 中默认启用,但问题一堆:
- 每条请求都输出完整
ctx.Request().Header.String(),密钥、token、cookie 全进日志文件 - 无采样机制,高并发下磁盘 I/O 成瓶颈,
fmt.Fprintf()同步写导致协程阻塞 - 无法过滤路径(比如跳过
/health、/metrics),静态资源也照打 - 时间戳格式固定、无 traceID 关联、不支持 JSON 输出,和 ELK / Loki 对接困难
手写轻量级请求日志中间件(推荐)
用 time.Now() + ctx.Method() + ctx.Path() + ctx.Response().StatusCode() 就够了,关键要控制输出时机和内容边界:
- 只在
c.Next()后读取状态码,避免未处理完就记日志 - 用
ctx.Locals或自定义字段存开始时间,别依赖闭包变量(goroutine 复用会错乱) - 敏感路径如
/login、/api/v1/user要脱敏ctx.Body()和ctx.Query("token") - 错误日志单独走
zerolog.Error().Str("path", ...).Int("status", ...).Err(err),和访问日志分离
func AccessLog() fiber.Handler {
return func(c *fiber.Ctx) error {
start := time.Now()
c.Locals("start_time", start)
err := c.Next()
status := c.Response().StatusCode()
duration := time.Since(start)
if status >= 400 {
zerolog.Error().
Str("method", c.Method()).
Str("path", c.Path()).
Int("status", status).
Dur("duration", duration).
Err(err)
} else {
zerolog.Info().
Str("method", c.Method()).
Str("path", c.Path()).
Int("status", status).
Dur("duration", duration).
Msg("http_access")
}
return err
}
}
用 zerolog + fiber.New() 接入结构化日志
这才是生产级做法:禁用所有默认中间件,手动挂载带上下文的 zerolog.Logger 实例:
- 初始化时传入
&fiber.Config{DisableStartupMessage: true},关掉 banner 干扰日志 - 用
zerolog.New(os.Stdout).With().Timestamp().Logger()构建 root logger - 中间件里用
c.Context().Value()或c.Locals("logger")注入 request-scoped logger,加req_id字段 - 别在中间件里调
log.Printf或fmt.Println—— 它们不走 zerolog pipeline,无法统一格式/采样/输出目标
常见漏点:ctx.IP() 在反向代理后可能拿到的是 Nginx 内网 IP,得配 fiber.Config{ProxyHeader: fiber.HeaderXForwardedFor} 并确保 Nginx 透传 X-Forwarded-For。











