Fiber未内置/metrics或Monitor中间件,因Go生态无此抽象,需手动集成可观测性能力;暴露/metrics需用adaptor.HTTPHandler适配promhttp.Handler并注册;统计HTTP耗时与状态码须包装ResponseWriter并在defer中记录,指标变量须包级定义且路径/状态码label需规范化。

为什么 Fiber 没有内置 /metrics 或 Monitor 中间件
Fiber 本身不提供 /metrics 端点,也没有叫 Monitor 的中间件——这个词是 SpringBoot 生态的术语,Go 生态里没有对应抽象。Fiber 的设计原则是轻量、显式、可组合,所有可观测性能力(指标、日志、追踪)都需手动集成。你看到的 “Fiber + Monitor” 示例,大概率是误用了 Java 概念,或引用了非官方、零散封装的社区包(如 fiber-prometheus),它们不在官方支持范围内。
怎么暴露 /metrics 端点并让 Prometheus 能抓到
必须显式注册 promhttp.Handler() 到 Fiber 路由中,否则访问 /metrics 会返回 404 或空响应。Fiber 的 app.Get() 接收的是 func(*fiber.Ctx),而 promhttp.Handler() 返回的是 http.Handler,不能直接传入。
正确做法是用 adaptor.HTTPHandler() 做适配:
- 引入
github.com/gofiber/fiber/v2/utils/adaptor - 调用
app.Use("/metrics", adaptor.HTTPHandler(promhttp.Handler())) - 确保监听地址可被 Prometheus 访问:别只绑
:8080,它默认只监听 localhost;生产环境建议用0.0.0.0:8080
如果用 curl http://localhost:8080/metrics 返回空,先检查是否漏掉 MustRegister();再确认是否在 init() 或 main() 开头注册了指标,而不是在 handler 里重复新建+注册。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
怎么统计 HTTP 请求耗时和状态码(不漏 WriteHeader)
直接在中间件里写 start := time.Now() + ctx.Next() + time.Since(start) 是错的:它只覆盖到 ctx.Next() 返回的时间,不包括 WriteHeader 和响应体真正 flush 到连接的时间。
正确方式是包装 ctx.Response().Writer,实现自定义 ResponseWriter:
- 在中间件开头创建一个带状态码记录的 wrapper 结构体
- 重写
WriteHeader(statusCode int)方法,保存statusCode - 重写
Write(p []byte) (int, error)方法(可选,用于捕获首次写入) - 用
ctx.Response().SetBodyStreamWriter()或直接替换底层 writer(需小心并发)
然后在 defer 中调用 httpRequestDuration.WithLabelValues(method, path).Observe(time.Since(start).Seconds()),确保 observe 一定被执行。
自定义 CounterVec 和 HistogramVec 容易踩的坑
指标变量必须是包级变量,注册只做一次,否则启动 panic 报 duplicate metrics collector registration:
- 写成
var httpReqCounter = prometheus.NewCounterVec(...),不要放在 handler 函数里 -
func init() { prometheus.MustRegister(httpReqCounter) },或者在main()开头注册 - 路径 label 不能直接用
ctx.Path()(比如/user/123),要映射为模板形式(如/user/{id}),否则 cardinality 爆炸 - 状态码 label 值必须收敛:用
switch statusCode { case 200: return "200"; case 404: return "404"; default: return "5xx" },别直接填strconv.Itoa(statusCode) - 延迟 histogram 的
Buckets别用prometheus.DefBuckets:对毫秒级 API 太粗,建议用prometheus.ExponentialBuckets(0.005, 2, 10)(5ms 起,覆盖到 ~2.5s)
最常被忽略的一点:http.Request 对象里的 ctx 不包含路由模板信息,Fiber 的 ctx.Route().Path 才是注册时的原始路径(如 /api/users/:id),这才是 label 的安全来源。

















