Fiber 内置 Logger 中间件通过 app.Use(logger.New()) 启用,支持模板化输出(如 ${method} ${path} ${status} ${latency} ${ip}),但默认不写文件、无结构化、不支持生产级日志功能;需自定义 Output 接入 zerolog/logrus 等结构化日志库。

怎么用 Fiber 内置的 Logger 中间件输出请求日志?
Fiber 自带的 Logger 中间件能快速打印 HTTP 请求基础信息(方法、路径、状态码、耗时),适合开发和简单调试。它默认写到 os.Stdout,不落地文件,也不支持结构化日志。
启用方式很简单:
app := fiber.New() app.Use(logger.New())
常见问题:日志里看不到客户端 IP?默认格式不包含 ip 字段。需要自定义 Format 参数:
-
Format是 Go 模板字符串,可用字段包括${status}、${method}、${path}、${latency}、${ip}、${ua}等 - 想加时间戳?用
${time}或${time_unix},注意${time}默认是 RFC3339 格式,中文环境可能显示 UTC 时间 - 如果启用了反向代理(如 Nginx),
${ip}取到的是代理 IP,得配合app.Config().ProxyHeader = "X-Forwarded-For"才能正确解析真实客户端 IP
为什么不能直接把 logger.New() 的输出重定向到文件?
因为 logger.New() 接收一个 logger.Config,其中 Output 字段类型是 io.Writer,理论上可以传 *os.File。但直接写文件有隐患:
立即学习“go语言免费学习笔记(深入)”;
- 并发写入会丢日志——Fiber 日志中间件本身不带锁,多个请求同时调
Write可能导致内容错乱 - 没做轮转,单文件会无限增长;也没错误恢复机制,磁盘满或文件被删后写入失败,日志就静默丢失
- 内置
Logger不支持 JSON 输出,无法对接 ELK 或 Loki 等日志系统
所以生产环境不建议硬塞 os.OpenFile,更稳妥的做法是用成熟日志库桥接。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
如何让 Fiber 日志对接 zerolog 或 logrus?
核心思路:把 Fiber 的 logger.New() 的 Output 指向一个自定义 io.Writer,该 Writer 把每行日志解析成结构体,再交由 zerolog 记录。例如用 zerolog 时:
import "github.com/rs/zerolog"
type ZerologWriter struct {
logger *zerolog.Logger
}
func (w *ZerologWriter) Write(p []byte) (n int, err error) {
line := strings.TrimSpace(string(p))
if line == "" {
return len(p), nil
}
w.logger.Info().Str("raw", line).Msg("http_access")
return len(p), nil
}
app.Use(logger.New(logger.Config{
Output: &ZerologWriter{logger: &yourZerologInstance},
}))
注意点:
- 别在
Write里做耗时操作(比如网络请求、磁盘 I/O),否则拖慢整个 HTTP 请求链路 -
zerolog默认不带时间字段,记得初始化时加zerolog.TimeFieldFormat = zerolog.TimeFormatUnix - 如果要用
logrus,原理一样,但要注意logrus.WithField()是非线程安全的,需确保每次调用都新建Entry
要不要在业务逻辑里也用 Fiber 的 Logger?
不要。Fiber 的 logger 中间件只负责请求生命周期日志,它没有 Debug/Error 级别区分,也没有上下文透传能力(比如 traceID)。你在 handler 里调 c.Locals 或 c.Context().Value 都拿不到它的实例。
真正该做的是:
- 全局用一个结构化日志实例(如
*zerolog.Logger)注入到fiber.App的Settings.ContextPool或自定义中间件中 - 在中间件里从
c.Context()提取 traceID、userAgent、requestID,用logger.With().Str(...).Logger()创建带上下文的子 logger,再传给 handler - handler 内部统一用这个子 logger 打印业务日志,确保每条日志都带 traceID,方便排查
内置 Logger 就老老实实当“访问日志开关”用,别让它越界管业务日志——边界模糊之后,查问题时你根本分不清哪条是接入层打的、哪条是服务逻辑打的。

















