日志中间件在Iris中需手动控制执行流:必须用ctx.Next()前后打点记录耗时,提前返回后紧跟ctx.StopExecution(),避免重复日志或响应冲突;状态码应通过ctx.Recorded()和ctx.GetStatusCode()获取,而非ResponseWriter().Status()。

日志中间件在 Iris 中不会自动记录请求耗时、状态码或路径,必须手动调用 ctx.Next() 并在前后打点;漏掉 ctx.StopExecution() 或错误放置 ctx.Next() 会导致日志重复、缺失或 panic。
日志中间件必须手动控制执行流
Iris 不像 Gin 那样提供 Abort() 或自动中断语义,ctx.Next() 只是“继续”,不阻断后续代码。一旦你在中间件里写了响应(比如 ctx.StatusCode(401)),但没调 ctx.StopExecution(),后续中间件和 handler 仍会执行——日志就可能记两次,甚至写冲突响应。
- 正确结构:所有提前返回逻辑(如鉴权失败、参数校验)后必须紧跟
ctx.StopExecution() -
ctx.Next()必须放在所有条件分支之后,且不能被return、panic或未覆盖的if拦截 - 常见错误:JWT 中间件里
if token invalid { ctx.JSON(401); return }→ 忘了ctx.StopExecution(),导致日志中间件又执行一次,handler 也意外跑通
如何准确记录耗时与状态码
耗时必须用 time.Now() 打起点,ctx.Next() 后立刻取终点;状态码不能直接读 ctx.ResponseWriter().Status()(Iris 封装后不可靠),而应监听 ctx.StatusCode() 调用或改用 ctx.Recorded() 判断是否已写响应。
- 推荐方式:在
ctx.Next()前记开始时间,在ctx.Next()后立即检查ctx.Recorded(),若为true再调ctx.GetStatusCode() - 避免用
ctx.ResponseWriter().Status()—— Iris v12+ 中它可能返回 0 即使已写响应 - 如果 handler panic,
ctx.Recorded()仍为false,需配合defer/recover捕获并设默认状态码(如 500)
日志中间件注册顺序影响字段可见性
日志中间件若放在认证或解析中间件之后,才能拿到 ctx.User.Get() 或 ctx.Params().Get("id");但如果放得太靠后(比如在路由 handler 之后注册),它根本不会执行。
- 全局日志建议用
app.Use(),且放在所有功能性中间件(如 JWT、Session)之前,确保能捕获完整生命周期 - 若需记录用户 ID,必须保证日志中间件在
authMiddleware之后注册,否则ctx.User.Get()返回 nil - 别把日志中间件塞进某个
Party()分组里再期望它记录根路由——分组中间件只作用于该分组路径
别忽略 OPTIONS 请求的日志污染
前端跨域预检(OPTIONS)也会经过日志中间件,但这类请求通常无业务意义,高频刷屏日志,且状态码固定为 204,容易掩盖真实问题。
- 在日志中间件开头加判断:
if ctx.Method() == "OPTIONS" { ctx.Next(); return } - 或者更严格:只对
GET/POST/PUT/DELETE记录详细日志,其余方法仅记录路径和耗时 - 注意:不要在 OPTIONS 分支里调
ctx.StopExecution()后还写日志——那行日志就永远不会输出
最易被忽略的是:日志中间件里调用 ctx.StatusCode() 或 ctx.WriteString() 后,必须立刻 ctx.StopExecution(),否则 Iris 仍会继续执行后续中间件,造成日志错乱或 HTTP 响应头重复写入。这个细节没有报错,只有压测或线上出问题时才暴露。











