Iris中间件必须为func(ctx iris.Context)签名且调用ctx.Next(),否则阻断请求;耗时需用ctx.RecordStartTime()和ctx.GetDuration()获取,StatusCode须在ctx.Next()后读取。

中间件函数签名必须返回 iris.Handler
Iris 的中间件本质是 iris.Handler 类型的函数,签名固定为 func(ctx iris.Context)。如果写成普通函数或漏掉 ctx.Next(),日志会记录不全甚至阻断请求链。
- 错误写法:
func logMiddleware() { ... }(无参数、不接收ctx) - 正确写法:
func logMiddleware(ctx iris.Context) { ...; ctx.Next(); } - 必须调用
ctx.Next(),否则后续 handler 不执行,接口直接卡住 - 若想在响应后记录耗时或状态码,
ctx.Next()必须放在日志逻辑之前(即“前置记录时间 → 执行链 → 后置读取状态”)
用 ctx.RecordStartTime() 和 ctx.GetDuration() 获取准确耗时
Iris 提供了内置计时支持,比手动 time.Now() 更可靠——它能自动处理中间件嵌套、重定向、panic 恢复等场景下的时间偏差。
- 在中间件开头调用
ctx.RecordStartTime() - 在
ctx.Next()之后用ctx.GetDuration("handler")获取总耗时(单位 ns) - 避免自己用
time.Since():若 handler 中发生 panic 且被Recover捕获,手算时间可能早于实际结束时刻 - 示例片段:
ctx.RecordStartTime() ctx.Next() dur := ctx.GetDuration("handler") log.Printf("[%s] %s %s %d %v", ctx.RemoteAddr(), ctx.Method(), ctx.Path(), ctx.StatusCode(), dur)
注意 ctx.StatusCode() 在 ctx.Next() 前始终为 0
这是最容易踩的坑:很多新手在 ctx.Next() 前读 ctx.StatusCode(),结果日志里全是 0。Iris 的状态码只在写响应头后才真正确定,而写响应头发生在 handler 执行过程中。
- 只有
ctx.Next()返回后,ctx.StatusCode()才反映真实值 - 如果 handler 内部调用了
ctx.Redirect()或ctx.JSON()等方法,状态码才被设置 - 若需记录失败原因(如 validator 错误),应结合
ctx.IsStopped()和自定义上下文键(ctx.Values().Set())在 handler 中主动标记
日志输出到文件时别忘了配置 os.File 的 Sync 行为
直接用 log.SetOutput(file) 写文件,若不显式 file.Sync(),进程崩溃或突然退出会导致最后几条日志丢失。
- 推荐用
lumberjack.Logger(第三方轮转日志库)替代裸*os.File - 若坚持用
*os.File,可在每次写完后加file.Sync(),但会影响性能;更稳妥的是启用log.Lshortfile并配合系统级日志收集(如 systemd-journald) - Iris 自身不接管日志落盘策略,所有
log.Printf或fmt.Fprintln都依赖你传入的io.Writer实现
实际部署时,ctx.Path() 和 ctx.URL() 的差异、查询参数是否脱敏、敏感 header(如 Authorization)是否过滤,这些都得在中间件里手工判断——Iris 日志中间件不自动做任何内容过滤。











