fiber.Logger()不适合生产环境,因其每请求同步写日志到stdout,无缓冲、不支持异步和结构化,实测TTFB增加0.3–0.8ms,QPS过万时I/O成瓶颈,且泄露敏感信息、重复输出panic堆栈。

别用 fiber.Logger() 上线,它会让 TTFB 增加 0.3–0.8ms,压测到 2 万 QPS 时直接拖垮 I/O。
为什么 fiber.Logger() 不适合生产环境
它每请求打一条日志到 os.Stdout,不支持异步、无缓冲、无法对接结构化日志系统。实测在 4 核 8G 环境下,单条日志写入平均耗时 0.15ms,QPS 过万后 stdout 成瓶颈,还会干扰 pprof 和健康检查路径的响应节奏。
- 它自动注入
X-Request-ID,但你可能根本不需要——很多服务已由 Nginx 或 Service Mesh 注入 - 它默认记录完整请求体和响应体,敏感字段(如密码、token)会裸漏在日志里
- 它和
fiber.Recover()叠加使用时,panic 日志会重复输出两次堆栈
怎么写一个轻量可控的日志中间件
核心是:只记录必要字段、绕过 stdout、支持结构化、不阻塞主流程。推荐用 zerolog + io.Discard 或文件 writer:
- 用
c.Response().StatusCode()替代c.Status()获取真实状态码(后者可能被后续中间件覆盖) - 用
c.GetReqHeaders()["User-Agent"]而非c.Get("User-Agent"),避免 header key 大小写问题 - 记录耗时必须用
c.Context().Time()起始时间戳,而不是time.Now(),防止中间件执行间隙引入误差 - 别在中间件里调
log.Info().Str("path", c.Path()).Send()—— 这会触发一次同步写,改用logger.Info().Str("path", c.Path()).Timestamp().Caller().Send()并确保 logger 已配置zerolog.New(os.Stderr).With().Timestamp().Logger()
示例片段:
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
app.Use(func(c *fiber.Ctx) error {
start := time.Now()
err := c.Next()
status := c.Response().StatusCode()
duration := time.Since(start).Microseconds()
logger.Info().
Int("status", status).
Int64("duration_us", duration).
Str("method", c.Method()).
Str("path", c.Path()).
Str("ip", c.IP()).
Send()
return err
})
哪些路径该跳过日志记录
不是所有请求都值得记日志。高频、低业务价值的路径建议静默处理,否则日志量爆炸且掩盖关键信号:
-
/health、/metrics、/favicon.ico—— 这些是监控探针或浏览器自动请求,记了也白记 -
/assets/开头的静态资源路径 —— 应由 CDN 或 Nginx 承担,Fiber 层不该参与 - 返回
304 Not Modified的请求 —— ETag 或 Last-Modified 匹配成功,无实际内容传输 - 状态码为
404且路径含.php、.asp、wp-admin等扫描特征 —— 属于恶意探测,可聚合统计而非逐条落盘
日志字段顺序和采样控制很关键
字段顺序影响解析效率(尤其用 Filebeat 或 Loki 采集时),采样则决定磁盘和网络成本:
- 固定前缀字段放前面:
level、time、status、duration_us;业务字段放后面:user_id、order_id - 高 QPS 接口启用采样:
if rand.Intn(100) > 1 { return err }(1% 采样),避免日志写满磁盘 - 错误日志(
status >= 400)必须 100% 记录,但可压缩堆栈深度:zerolog.ErrorStackMarshaler = func(err error) interface{} { return err.Error() } - 别把
c.Locals全部序列化进日志 —— 它可能含未清理的临时数据或闭包引用,导致内存泄漏
真正上线前,一定要用 ab 或 hey 对比开/关日志中间件的 P99 延迟变化。差值超过 0.2ms 就得重新评估——这不是微优化,是稳定性底线。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










