应使用 ctx.responsewriter().status() 获取最终状态码且耗时统计必须放在 ctx.next() 之后,因 ctx.getstatuscode() 返回的是未定稿的中间状态,而时间起点设于开头、计算置于 ctx.next() 后才能准确同步状态码与耗时。

为什么不能用 ctx.GetStatusCode() 获取最终状态码
中间件里调用 ctx.GetStatusCode() 返回的只是当前写入缓冲区的状态,可能还没定稿——比如后续某个中间件或 handler 调用了 ctx.StatusCode(500),但你已经记了 200。真正可靠的是 ctx.ResponseWriter().Status(),它在 ctx.Next() 执行完后才返回最终值。
耗时统计必须放在 ctx.Next() 之后
时间起点要设在中间件开头,但耗时计算必须等整个请求链执行完毕才能准确。常见错误是把 time.Since(start) 放在 ctx.Next() 前,结果只测了中间件自身开销。
- 正确顺序:记录 start →
ctx.Next()→ 调用ctx.ResponseWriter().Status()和time.Since(start) - 别用
ctx.Values().Set("start", time.Now())存时间戳——其他中间件可能覆盖这个 key - 避免在中间件里读
ctx.Request().Body,会破坏流,导致后续 handler 读不到数据
推荐的日志字段组合和结构化写法
Iris 自带的 iris.Logger() 不打请求日志,得自己用结构化日志库(如 zerolog)或直接调 iris.Logger().Infof。关键字段建议包含:
-
{Method}:ctx.Request().Method -
{Path}:ctx.Request().URL.Path(不是ctx.Path(),后者可能被重写) -
{StatusCode}:ctx.ResponseWriter().Status() -
{ElapsedMs}:int64(time.Since(start).Milliseconds()) -
{TraceID}(可选):ctx.GetHeader("X-Request-ID")或用 middleware 注入
示例:
logger.Infof("REQ %s %s %s - %d in %dms", traceID, method, path, status, elapsedMs)
全局注册 vs 路由组注册的差异
用 app.Use() 是全局生效,所有路由都会走;用 app.Party("/v1").Use() 则只影响该分组。如果 v1 和 v2 版本对耗时统计字段要求不同(比如 v2 要加 {Version} 字段),就得拆成两个中间件,分别挂到对应 Party 下。
容易踩的坑:Party 创建后忘了调 .Use(),结果那组路由完全没统计——日志里根本看不到请求记录,排查时容易误判为请求没进来。
复杂点在于:耗时本身不难算,难的是确保它和状态码、路径、上下文信息严格同步;一旦中间件顺序错位或提前写响应,Status() 和耗时就都不可信了。











