Iris 集成 Prometheus 的关键是手动注册包级指标并显式挂载 /metrics 路由:使用 iris.FromStd(promhttp.Handler()) 注册,避免重复注册 panic;自定义 Counter/Gauge 需声明为包级变量并在 init/main 中注册一次,controller 中调用 Inc()/Dec();异步更新需确保 goroutine 安全。

Iris 框架本身不内置 MVC 结构(它更倾向“路由+Handler”风格),但如果你在 Iris 中模拟 MVC 分层(比如 controller 包、service 包、model 包),集成 Prometheus 监控指标的关键不是“MVC 架构”,而是「如何在 HTTP 请求生命周期中暴露和更新指标」。直接结论:用 iris.Prometheus 插件 + 手动注册自定义指标即可,无需改架构。
为什么 iris.Prometheus 插件不能直接用默认配置?
Iris 的 iris.Prometheus 是一个开箱即用的中间件插件,但它只暴露基础指标(HTTP 状态码、请求耗时、QPS),且默认路径是 /metrics。问题在于:
- 它不会自动采集 JVM 或 Go 运行时指标(Iris 是 Go 写的,没 JVM)
- 它不支持标签(label)动态注入,比如按 controller 名或用户 ID 打标
- 若你已在全局用了
promhttp.Handler()(比如自己注册了/metrics),再启用该插件会导致重复注册 panic
怎么正确注册自定义 Counter/Gauge 并避免 panic?
Go 的 Prometheus 客户端对重复注册极其敏感:prometheus.MustRegister() 遇到同名指标会直接 crash。常见错误是把 prometheus.NewCounter() 写在 handler 函数里,每次请求都新建+注册。
- 所有指标必须声明为包级变量,例如:
var orderCreatedCounter = prometheus.NewCounterVec(prometheus.CounterOpts{Name: "order_created_total"}, []string{"status"}) - 注册只在
init()或main()启动阶段做一次:prometheus.MustRegister(orderCreatedCounter) - 在 controller 逻辑中调用:
orderCreatedCounter.WithLabelValues("success").Inc(),不要 new、不要重复 Register - 若需按请求路径打标,建议提取
c.Request().URL.Path后截取一级路径(如/api/orders),避免 label 值爆炸
如何让 /metrics 端点生效且不和 Iris 路由冲突?
Iris 默认不接管 /metrics,必须显式挂载。很多人 curl /metrics 返回 404 或空内容,根本原因是没注册 Handler。
- 别依赖
iris.Prometheus插件自动挂载;手动在启动前加:app.Get("/metrics", iris.FromStd(promhttp.Handler())) - 确保路径和 Prometheus server 的
scrape_configs.metrics_path完全一致(默认就是/metrics) - 如果用了其他中间件(如 JWT 鉴权),要放行
/metrics,否则返回 401 —— Iris 不会自动跳过监控路径 - 本地调试时返回空?检查指标变量是否被 GC:确认包级变量有被引用(比如至少在某个 handler 里调用了
.Inc()),否则 Go 编译器可能优化掉
最易忽略的一点:Iris 的 Context 生命周期和 goroutine 不完全对齐。如果你在异步 goroutine(比如发消息后记录日志)里更新 Gauge,务必确保该 goroutine 退出前调用 .Dec(),否则活跃连接数类指标会持续上涨失真。


















