生产不能直接用 fiber.logger(),因其默认打印敏感头(authorization/cookie)、无采样、非结构化、无日志分级、不支持异步;应替换为 zerolog 或 zap 等结构化日志库,并手动实现中间件过滤敏感字段、分级打点、采样错误。

直接用 fiber.Logger() 上生产等于暴露敏感头和完整错误堆栈——它默认打印 Authorization、Cookie,且不采样、不结构化、不区分环境。
为什么不能直接用 fiber.Logger() 做生产日志
它不是“不够好”,而是设计上就面向开发调试:
• 默认输出完整请求头,含 Authorization 和 Cookie 字段,密钥/Token 一并打到 stdout;
• 不做采样,高并发下日志爆炸,IO 扛不住;
• 日志是纯字符串拼接,无法被 ELK 或 Loki 解析字段;
• 没有 error level 分级,panic 和 404 全混在 INFO 里;
• 不支持异步写入,阻塞请求处理链路。
生产该用什么替代 fiber.Logger()
必须换为结构化日志库,并手动注入中间件:
• 推荐 zerolog(轻量、零分配、JSON 原生)或 zap(性能极致,但稍重);
• 日志实例需全局复用,避免每请求新建 logger;
• 关键字段必须显式提取:method、status、path、latency、ip、user-agent;
• 敏感字段如 Authorization、X-API-Key 必须过滤,不能靠“不打印”——要从 c.Request().Header 中主动删;
• 开发环境可加 zerolog.ConsoleWriter,生产强制 JSON 输出。
一个安全可用的 zerolog 中间件示例
以下代码跳过敏感头、采样 1% 的 error 日志、只对非 2xx/3xx 响应打 ERROR 级别:
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/gofiber/fiber/v3"
)
func Logger() fiber.Handler {
// 全局 logger,带 request ID 字段
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
return func(c *fiber.Ctx) error {
start := time.Now()
// 过滤敏感 header(必须在 c.Next() 前做)
headers := c.GetReqHeaders()
delete(headers, "Authorization")
delete(headers, "Cookie")
delete(headers, "X-API-Key")
err := c.Next()
status := c.Response().StatusCode()
latency := time.Since(start)
event := logger.Info()
if status >= 400 {
event = logger.Error()
// 仅对 4xx/5xx 采样 1%,防刷
if rand.Float64() > 0.01 {
return err
}
}
event.
Str("method", c.Method()).
Str("path", c.Path()).
Int("status", status).
Dur("latency", latency).
Str("ip", c.IP()).
Str("ua", c.Get("User-Agent")).
Msg("http")
return err
}
}
然后挂载:app.Use(Logger()),而非 fiber.Logger()。
容易被忽略的三个细节
• c.GetReqHeaders() 返回的是引用,直接 delete() 会污染后续中间件——实际应复制 map 或只 log 前过滤;
• zerolog 的 ConsoleWriter 在容器里可能因 ANSI 转义符导致日志解析失败,生产务必关掉;
• 如果用了 Recover() 中间件,它的 panic 日志和你的结构化 logger 是两套系统,必须统一接管 zerolog.Global 或重写 Recover 的 error handler。











