iris 默认不记录http请求日志,需自定义中间件实现;推荐用ctx.responsewriter().status()获取最终状态码,time.since(start)计算耗时,并结合zerolog结构化定制字段。

怎么用 Iris 的 Logger 记请求日志
Iris 自带的 Logger 默认不记录 HTTP 请求(比如 method、path、status、耗时),它只打启动、错误、自定义日志。要记请求日志,得自己加中间件——不是配置开关就能开的。
最直接的做法是用 iris.Logger().Infof 在 ctx.Next() 前后手动记,但更推荐用 iris.Logger().Info + ctx.ResponseWriter().Status() 组合,因为 Status() 能拿到最终状态码(中间件里调用才有效)。
- 别在
ctx.Next()前读ctx.Request().Body,会破坏流,后续 handler 读不到 - 别用
ctx.GetStatusCode(),它返回的是当前写入缓冲区的状态,可能还没定稿;ctx.ResponseWriter().Status()才是最终值 - 耗时建议用
time.Since(start),start 记在中间件开头,别依赖ctx.Values().Get()存时间戳,容易被其他中间件覆盖
如何定制 Logger 输出格式和字段
Iris 的 Logger 底层是 zerolog,所以支持结构化日志,但默认输出是纯文本。想加 trace_id、client_ip、user_agent,得自己封装一层 zerolog.Logger 并替换掉框架默认实例。
关键点:调用 app.Logger().Output(...) 只能改输出目标(比如写到文件),不能改字段;真正控制字段得在初始化 logger 时传入 zerolog.ConsoleWriter 或自定义 zerolog.LevelWriter,再通过 With().Caller().Timestamp().Stack() 等链式方法加字段。
- client_ip 推荐从
ctx.RemoteAddr()或ctx.GetHeader("X-Forwarded-For")提取,注意代理场景下后者可能被伪造 - 不要在
Logger().With().Str("path", ctx.Path())里直接塞ctx.Path(),它可能为空(比如路由未匹配);先判断ctx.HandlerName() != ""更稳妥 - 如果用了
app.Use(iris.Recover),错误日志会重复:一次是 recover 中间件打的 panic 日志,一次是你自己写的请求日志里的 500;可加 flag 过滤或统一收口到一个 error handler
iris.Logger() 和自定义 zerolog.Logger 混用要注意什么
直接 new 一个 zerolog.Logger 并赋给全局变量没问题,但千万别用 iris.New().Logger().Output(...) 后又自己 new 一个同名 logger——Iris 不会自动同步两者配置,iris.Logger() 仍走默认输出,你新造的 logger 完全独立。
常见误操作:在 main.go 初始化了一个带 file writer 的 zerolog.Logger,然后在中间件里调 app.Logger().Infof(...),结果日志还在 console,没进文件。原因就是没把自定义 logger 注入到 Iris 实例中。
- 正确做法是:创建好自定义
zerolog.Logger后,调app.Logger().Output(yourZerologWriter)替换输出目标 - 如果要用
zerolog.With().Str("req_id", ...)动态加字段,必须每次在中间件里 new 一个子 logger:logger := app.Logger().With().Str("req_id", uuid).Logger(),否则字段会污染全局 logger - log level 是全局的,
app.Logger().Level(zerolog.DebugLevel)会影响所有输出,包括 recover、startup 日志;如需分级,得用不同 logger 实例,而不是改 level
为什么不用 iris.Logger().RequestLogger
这个方法确实存在,但它只是个空壳:源码里它返回 nil,文档也没说明用途,实际无法启用。别被名字误导,Iris 官方目前没提供开箱即用的请求日志中间件。
社区有人基于 iris.Logger().Infof 封装了简易版,但字段固定(method/path/status/duration),不支持扩展字段或结构化输出。如果你需要 JSON 格式、对接 ELK、或加 span_id,还是得自己写中间件+zerolog。
最轻量的可行方案就三行:
app.Use(func(ctx iris.Context) {
start := time.Now()
ctx.Next()
app.Logger().Infof("%s %s %d %v", ctx.Method(), ctx.Path(), ctx.ResponseWriter().Status(), time.Since(start))
})
复杂点的需求,比如按 status 分文件、采样日志、异步写入,就得深入 zerolog 的 LevelWriter 或用 channel 做缓冲——这些不是 Iris 的责任,而是日志系统本身的边界。











