fiber框架需通过自定义中间件实现精确接口耗时统计:在c.next()前用time.now().unixnano()打点,defer中计算差值并存入c.locals;避免闭包捕获错误变量,确保panic时仍能记录。

Fiber 框架本身不内置响应时间监控能力,但它的中间件机制足够轻量且灵活,可以低成本实现接口耗时统计。核心思路是:在请求进入时打点,响应发出前计算差值,再写入日志或指标系统。
用 fiber.Logger 中间件快速看耗时(适合开发/测试)
fiber.Logger 是 Fiber 官方提供的日志中间件,它默认会打印状态码、路径、方法和耗时(latency 字段),但默认格式里不显式标注单位,容易误读成毫秒(实际是 time.Duration,输出如 12.345ms 或 250.123µs)。
实操建议:
- 启用时确认日志输出是否包含
latency字段(默认开启) - 不要依赖它做告警或聚合分析——字段不可编程提取,格式随 locale 可能变化
- 仅用于快速验证单次请求是否明显变慢,比如本地调试或 CI 环境的 smoke test
自定义中间件记录精确耗时(推荐生产使用)
真正可控的方式是自己写一个中间件,在 c.Next() 前后记录 time.Now(),手动计算差值。
常见错误现象:
- 用
time.Since()但传入了错误的起始时间变量(比如在c.Next()后才声明 start) - 把耗时直接塞进
c.Locals但没在后续中间件或 handler 里消费,导致“记了却没用” - 在 panic 恢复逻辑外漏掉耗时记录(比如 handler panic 了,
after部分没执行)
实操建议:
- 起始时间必须在
c.Next()前获取,且建议用time.Now().UnixNano()避免浮点误差 - 结束时间放在
defer里,确保即使 panic 也能记录 - 把耗时写入
c.Locals("duration_ns"),后续可由日志中间件或 metrics 中间件统一读取
示例代码片段:
app.Use(func(c *fiber.Ctx) error {
start := time.Now().UnixNano()
defer func() {
duration := time.Now().UnixNano() - start
c.Locals("duration_ns", duration)
}()
return c.Next()
})
对接 Prometheus 暴露 HTTP 耗时指标(需要可观测基建)
Fiber 没有原生 Micrometer 支持,但可通过 promhttp + 自定义指标注册实现类似 Spring Boot 的 http_server_request_duration_seconds。
关键点:
- 必须用
prometheus.NewHistogramVec按method、status、path多维打点,否则聚合无意义 - 耗时单位必须转为秒(
float64(ns) / 1e9),Prometheus histogram 只接受秒级 float - 不能在每个请求里重复注册指标,要提前在
init()或main()开头注册一次
性能影响很小,但要注意 histogram 的 bucket 设置——太密(如每 10ms 一个 bucket)会导致指标膨胀;太粗(如只设 0.1, 0.2, 0.5, 1.0, 2.0)会丢失 P95/P99 细节。推荐从 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5 开始。
为什么不用第三方 APM(如 DataDog、New Relic)自动埋点?
Fiber 的中间件链极简,没有像 Spring MVC 那样标准的 Controller/HandlerMapping 分层,多数 APM SDK 依赖反射扫描或字节码注入,对 Fiber 支持有限或需手动 patch。
目前稳定可用的只有:
- OpenTelemetry Go SDK:需手动在每个路由 handler 入口调用
tracer.Start(),侵入性强 - DataDog 的
dd-trace-go对 Fiber 有实验性支持,但要求你用fiber.Router接口而非*fiber.App,且版本兼容卡得紧(v2.50+ 才较稳)
结论:除非团队已统一使用某套 OpenTelemetry Collector,否则优先走自定义中间件 + Prometheus 路线更可控。最易被忽略的是 panic 场景下的耗时记录完整性——别只测 happy path。











