iris框架需通过userouter中间件记录http请求日志,用ctx.next()后获取状态码与耗时并调用app.logger().info()输出;捕获panic须自定义userecovery回调,调用app.logger().error().err().stack()记录;输出到文件需clone底层zerolog实例并重置output,log level须初始化时用zerolog.setgloballevel设置。

如何用 iris.Logger() 记录 HTTP 请求日志
iris.Logger() 默认只输出到终端,不自动写入文件,也不区分访问日志和错误日志。它本质是 zerolog.Logger 的封装,但 Iris 没有暴露底层日志实例的直接配置入口,所以不能靠“替换 logger”一劳永逸地接管所有日志。
真正记录请求日志,推荐用中间件 + iris.Application.UseRouter() 配合手动打点:
- 用
ctx.Record()捕获响应状态码、耗时、路径,再调用app.Logger().Info()输出结构化日志 - 避免在
Use()中记录,否则会重复触发(比如重定向、静态文件);必须用UseRouter()确保仅对路由匹配的请求生效 - 注意:Iris 的
ctx.Values().Get()无法跨中间件传递自定义字段(如 requestID),需用ctx.Set() / ctx.Get()
app.UseRouter(func(ctx iris.Context) {
start := time.Now()
ctx.Next()
status := ctx.GetStatusCode()
duration := time.Since(start)
app.Logger().Info().
Str("path", ctx.Request().URL.Path).
Int("status", status).
Dur("duration", duration).
Msg("http request")
})
怎样捕获并记录未处理的 panic 和系统错误
Iris 不会自动 recover panic,一旦路由 handler panic,连接直接断开,且默认不打印堆栈。必须显式注册 app.OnAnyErrorCode() 和 app.UseRecovery() 两层防护。
-
app.UseRecovery()是基础 panic 捕获中间件,但它只打印到标准错误,不走app.Logger()—— 所以你要自己重写它的回调函数 -
app.OnAnyErrorCode(500)只捕获已返回 500 响应的请求,对 panic 后未返回响应的情况无效 - 真正可靠的方案:在
UseRecovery()回调里调用app.Logger().Error().Err(err).Stack().Msg("panic recovered")
app.UseRecovery(func(ctx iris.Context, err interface{}) {
app.Logger().Error().
Err(fmt.Errorf("%v", err)).
Stack().
Msg("panic recovered")
ctx.StatusCode(500)
ctx.WriteString("Internal Server Error")
})
iris.Logger() 能否输出到文件?怎么配 log level?
可以,但 Iris 没提供 SetOutput() 或 SetLevel() 这类快捷方法。它底层用的是 zerolog,所以得通过 app.Logger().Clone() 获取原始 *zerolog.Logger 实例再操作。
- 输出到文件:先用
os.OpenFile()创建带os.O_APPEND | os.O_CREATE标志的文件句柄,再传给zerolog.New(),最后用app.Logger().Update(func(l *zerolog.Logger) { ... })替换 - log level 控制:Iris 的
app.Logger().Level()是只读的;必须在初始化 logger 时就设好,例如zerolog.SetGlobalLevel(zerolog.WarnLevel) - 注意:
app.Logger().Output()返回的是io.Writer,不是*zerolog.Logger,不能链式调用Level()
为什么自定义 error handler 里拿不到完整错误上下文?
因为 app.OnErrorCode() 的回调函数只传入 ctx iris.Context,不带 error 对象。你看到的 “error handler 不执行” 或 “日志里没堆栈”,往往是因为你误以为它能捕获 panic —— 它不能。
- 它只响应
ctx.StatusCode(500)显式设置后的响应,比如你在 handler 里if err != nil { ctx.StatusCode(500); return } - 若想在此处记录 error,必须提前把 error 存进
ctx.Values().Set("error", err),然后在OnErrorCode里取 - 更稳妥的做法是:所有业务错误统一包装为自定义 error 类型(如
AppError),并在中间件中集中判断、记录、响应
真正难调试的,是那些没被 UseRecovery 捕获的 goroutine panic,比如异步任务或定时器里的错误——这些 Iris 完全不感知,得靠全局 recover 或第三方监控工具补位。











