go服务不触发告警,仅需准确暴露带标签的指标;promhttp.handler()只输出指标文本,告警由prometheus抓取后按规则计算;须用histogram而非counter监控延迟,合理设buckets并正确打标。

Go服务本身不触发告警,告警由Prometheus服务端根据规则计算后推送给Alertmanager;你在Go里要做的,只是把指标暴露得准确、带对标签、用对类型。
为什么promhttp.Handler()不能直接触发告警
它只负责把当前时刻的指标值以文本格式输出(比如http_requests_total{method="GET",status="200"} 12345),不参与任何阈值判断或状态跟踪。告警逻辑完全在Prometheus服务端执行:它定期抓取/metrics,运行expr表达式,比对结果是否持续满足条件。
常见错误现象:
- 在Go代码里写
if latency > 500 { sendAlert() }—— 这是手动告警,绕过了Prometheus的去重、抑制、静默等关键能力 - 暴露的指标没加
labels,导致PromQL无法按服务/实例/路径切分,告警规则一配就全量命中
Counter和Histogram选错会导致告警失效
比如监控HTTP延迟,必须用Histogram(或Summary),不能用Counter。因为告警需要的是“分布”或“分位数”,而Counter只给累计值。
正确做法:
- 用
prometheus.NewHistogram()定义延迟指标,设置合理的Buckets(如[]float64{0.1, 0.2, 0.5, 1, 2, 5},单位秒) - 在HTTP handler末尾调用
histogram.WithLabelValues(method, path).Observe(latency.Seconds()) - PromQL写
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 2,而不是试图从Counter里算平均值
性能影响:Buckets太多(如50个)会显著增加内存和存储开销;太少(如只有3个)会让P95失去意义。
告警规则里的for持续时间不是“等待时间”
它表示:Prometheus必须连续n秒都看到表达式为true,才真正触发告警。这期间如果任意一次抓取结果为false(比如延迟回落到400ms),计时器就重置。
容易踩的坑:
-
for: 1m配在5秒抓取间隔下,实际需要至少12次连续true —— 如果你的服务偶发抖动,很容易漏报 - 和Go服务自身的指标更新频率无关:即使你每100ms更新一次
Histogram,Prometheus仍按scrape_interval(通常15s或30s)来拉取 - 不要盲目缩短
for,否则可能引发告警风暴;建议先设for: 2m,再根据真实抖动频率调整
标签(Labels)漏传或拼错,告警就查不到数据
比如定义了api_requests_total{endpoint="/user", method="POST"},但告警规则写成sum by (path) (rate(api_requests_total{method="POST"}[5m])),其中path根本不存在,结果永远是空集合。
实操建议:
- 所有自定义指标注册前,先用
prometheus.MustRegister(),避免静默失败 - 在
/metrics页面手动curl一把,确认标签名和值拼写完全一致(注意大小写、下划线) - 告警规则中用
label_values(api_requests_total, endpoint)在Prometheus Web UI的Graph页验证可用标签值
最常被忽略的一点:Go服务重启后,Counter类指标会归零,但Prometheus默认能自动处理counter重置(靠rate()函数),所以别在Go里做“启动时恢复旧值”这种事——它反而会破坏PromQL的计算逻辑。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











