Fiber默认logger不够用,因仅输出时间、状态码等基础字段,缺失请求体、响应体、IP、User-Agent等关键调试信息,且格式固定无法对接Loki/ELK;需自定义中间件,在handler前后复制并重置body、捕获IP/User-Agent/Query、脱敏敏感字段,并通过异步、截断、环境配置优化性能。

为什么默认中间件的 fiber.Logger 不够用
它只输出基础字段(时间、状态码、路径、耗时),没包含请求体、响应体、IP、User-Agent 等调试关键信息;而且日志格式固定,无法对接结构化日志系统(如 Loki、ELK)。真正线上排障时,你得自己补全上下文。
怎么自定义中间件记录完整请求/响应
核心是用 fiber.Next() 控制流程,在 handler 前后分别读取并保存原始数据。注意:HTTP body 只能读一次,必须用 c.Request().Body() 提前拷贝,再用 bytes.NewReader() 重置给后续 handler 使用。
- 用
c.IP()和c.Get("User-Agent")获取客户端信息 - 用
c.Request().URI().QueryString()拿 query string - 响应体捕获需包装
fiber.Response,重写Write()方法并缓存内容 - 敏感字段(如密码、token)必须在日志前做脱敏,例如用正则替换
"password=([^&]*)&?"为"password=[REDACTED]&"
如何避免日志中间件拖慢接口性能
结构化日志本身不重,但序列化、IO 写入、尤其是记录请求/响应体时,会显著增加内存和 CPU 开销。别在所有路由上无差别启用。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 只对
/api/或特定 method(如POST、PUT)启用完整日志 - 限制记录长度:用
body[:min(len(body), 1024)]截断过长内容 - 异步写日志:把日志结构体发到
chan logEntry,由单独 goroutine 落盘或发 Kafka - 跳过文件上传(
c.MultipartForm())和大文件下载(Content-Disposition: attachment)的 body 记录
常见错误:日志里全是空 body 或 panic
典型现象是 c.Body() 返回空字符串,或调用 c.Request().Body() 后后续 handler 报 http: read on closed response body —— 这是因为 Fiber 默认复用底层 fasthttp.RequestCtx 的 buffer,且不自动 reset。
立即学习“go语言免费学习笔记(深入)”;
- 读 body 前先调用
c.Request().ForceRequestBodyRead() - 用
io.ReadFull(c.Request().Body(), buf)替代io.ReadAll()防止超大 body OOM - 恢复 body 必须用
c.Request().SetBodyStream()+bytes.NewReader(copiedBytes),不能直接赋值 - 别在中间件里调用
c.SendString()或c.JSON(),否则会提前 commit response,导致后续 handler panic

















