fiber.Logger()不能直接用于生产环境,因其仅输出时间、状态码、路径、耗时等基础字段,缺失IP、User-Agent、Query、请求/响应体等关键调试信息;格式为固定纯文本,无法对接Loki/ELK;且会明文打印Authorization头导致token泄露,高并发下I/O拖垮QPS。

fiber.Logger() 为什么不能直接用在生产环境
它默认输出的字段太少,只有时间、状态码、路径和耗时,没有 IP、User-Agent、Query、请求体或响应体;格式固定为纯文本,没法对接 Loki 或 ELK 这类结构化日志系统。更关键的是,它会在每条日志里打印完整 Authorization 头,上线后等于把 token 批量泄露到文件里。
常见错误现象:fiber.Default() 自带这个中间件,上线不换 fiber.New() 就直接用,TTFB 会多出 0.3–0.8ms,高并发下 I/O 拖垮 QPS。
- 开发阶段可用
fiber.Default()快速验证 - 上线前必须切到
fiber.New(),再按需手动加日志逻辑 - 真要记日志,只对
POST/PUT或/api/路由启用完整记录 - 敏感字段(如
password、token)必须脱敏,例如用正则替换"password=([^&]*)&?"为"password=[REDACTED]&"
自定义中间件捕获完整请求/响应体的关键操作
HTTP body 只能读一次,c.Body() 和 c.Request().Body() 都会消耗原始流,后续 handler 会报 http: read on closed response body。必须提前拷贝并重置。
- 读请求体前,先调
c.Request().ForceRequestBodyRead() - 用
io.ReadFull(c.Request().Body(), buf)替代io.ReadAll(),防 OOM - 拷贝后用
c.Request().SetBodyStream(bytes.NewReader(copiedBytes), len(copiedBytes))恢复 body - 响应体捕获需包装
fiber.Response,重写Write()方法并缓存内容 - 别在中间件里调
c.SendString()或c.JSON(),否则提前 commit response,后续 handler panic
ctx.QueryParam、ctx.Params、ctx.FormValue 到底该用哪个
三者来源完全不同,混用必空,不是框架 bug,是读错了地方。
-
c.QueryParam("q")只读 URL query string,比如/search?q=go中的q -
c.Params("id")只读路由占位符,比如app.Get("/user/:id", )匹配/user/123后的123 -
c.FormValue("name")是给application/x-www-form-urlencoded准备的;JSON body 必须用c.Body()+json.Unmarshal或c.Struct(&v)
查不到值?先确认请求发的是什么类型、路径是否匹配、参数名拼写是否一致——90% 的问题出在这三处。
调试时怎么定位中间件执行卡在哪一环
别靠猜,用最朴素但有效的方式:在每个中间件开头加 log.Printf("[debug] in %s middleware", "auth"),看输出断在哪一行。Fiber 的执行顺序就是 app.Use() 的注册顺序,先注册的先执行,没例外。
- 权限中间件里写了
c.Status(401).Send()还跟c.Next(),后续 handler 就不会进 - 拒绝请求就直接
return,放行才调c.Next() - 全局中间件一定比路由组中间件先执行,但
app.Get("/x", h, mw)这种路由级中间件,在全局之后、handler 之前运行 - 协程日志建议嵌入 fiber ID,比如
[fiber:%d],方便区分不同请求上下文
最容易被忽略的是:不同环境(dev/staging/prod)该启用的日志粒度完全不同,dev 可以全开,prod 必须采样+截断+异步,否则日志本身就成了性能瓶颈。


















