日志记事件,指标看趋势。QPS 掉没掉、P99 涨没涨、错误率超没超,靠指标曲线一眼看出,比翻日志快。这一篇用 Prometheus 客户端埋点,暴露 /metrics,配 Grafana 看板。
1. 为什么埋指标
出了问题先看曲线定范围(哪段时间、哪类请求),再拿 trace_id 下钻日志。指标是监控的第一道岗,报警也基于它。
2. 定义指标
import "github.com/prometheus/client_golang/prometheus" var reqCount = prometheus.NewCounterVec( prometheus.CounterOpts{Name: "http_requests_total", Help: "请求总数"}, []string{"method", "path", "code"}, ) var reqDuration = prometheus.NewHistogramVec( prometheus.HistogramOpts{Name: "http_request_seconds", Buckets: []float64{.005, .01, .05, .1, .5, 1}}, []string{"method", "path"}, ) func init() { prometheus.MustRegister(reqCount, reqDuration) }
3. 中间件记录
func Metrics() gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Next() reqCount.WithLabelValues(c.Request.Method, c.FullPath(), fmt.Sprint(c.Writer.Status())).Inc() reqDuration.WithLabelValues(c.Request.Method, c.FullPath()).Observe(time.Since(start).Seconds()) } }
c.FullPath() 取路由模板(/articles/:id)而不是具体 id,否则标签基数爆炸。
4. 暴露 /metrics
import "github.com/prometheus/client_golang/prometheus/promhttp" r.GET("/metrics", gin.WrapH(promhttp.Handler()))
Prometheus 定时来拉这个端点。别对 /metrics 限流,否则拉取失败丢数据。
5. 三类核心看板
Grafana 里最该盯的三条:
- QPS:
rate(http_requests_total[1m]),看流量走势。 - P99 延迟:
histogram_quantile(0.99, rate(http_request_seconds_bucket[5m])),比平均值更能反映长尾用户体验。 - 错误率:
rate(http_requests_total{code=~"5.."}[1m]) / rate(http_requests_total[1m]),超阈值报警。
6. 报警规则
- alert: HighErrorRate expr: rate(http_requests_total{code=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.05 for: 5m labels: { severity: page }
错误率连续 5 分钟超 5% 就呼叫。阈值按业务定,误报多了没人看。
7. 上线清单
指标标签基数控制,path 用路由模板不用具体值。计数器用 Counter、延迟用 Histogram,别用 Gauge 记次数。把 /metrics 排除在鉴权和限流外。P99 比平均值重要,长尾延迟最伤体验。报警接人,没人的报警等于没有。
六篇走完,进阶系列从 GraphQL、限流、熔断、多租户到集成测试、指标监控,把一套能扛流量的生产级 Gin 服务要的补全都补齐了。