2、监控指标设计:Counter、Gauge、Histogram、Summary 四种核心指标类型详解与选型

监控指标选型这事儿,我见过太多团队踩坑了。有人把所有数据都塞进 Counter,结果算平均值算到怀疑人生。也有人非要用 Histogram 统计个在线人数,白白浪费存储空间。说白了,选错指标类型,就像拿菜刀拧螺丝——不是不能用,但你会很痛苦。

今天咱们就把 Prometheus 这四种核心指标类型掰开揉碎讲清楚。我会结合自己踩过的坑,告诉你什么场景该用谁。

2.1 Counter:只增不减的计数器

Counter 是最直观的指标类型。它只支持两种操作:初始化、加一。嗯,你没看错,不能减。

典型场景:

  • HTTP 请求总数
  • 错误发生次数
  • 任务执行次数
  • CPU 时间片累计

代码示例:

// 记录 API 调用次数
api_requests_total{method="GET", endpoint="/users"} 1024

// 记录错误次数
errors_total{service="auth", type="timeout"} 57

核心要点:Counter 只能算速率,不能算均值。比如「每秒请求数」用 rate() 函数算,「累计请求数」直接查值就行。

我的经验:我习惯把 Counter 的指标名以 _total 结尾。这是 Prometheus 的命名规范,但更重要的是——看到这个名字我就知道它是累加的,不会傻乎乎去求平均值。

2.2 Gauge:可增可减的仪表盘

Gauge 就像汽车仪表盘上的速度表。它能上能下,反映的是某个时刻的瞬时值。

典型场景:

  • 当前内存使用量
  • 在线用户数
  • 队列长度
  • CPU 温度

代码示例:

// 当前内存使用量(字节)
memory_usage_bytes{host="web-01"} 8589934592

// 当前在线用户数
active_users{service="chat"} 1423

注意:Gauge 的值会随时间波动。如果你用 Gauge 记录「累计请求数」,那每次重启服务都会归零。我曾经见过有人用 Gauge 记录请求总数,结果每次部署后数据都断崖式下跌——排查了半天才发现是类型选错了。

什么时候用 Gauge?

  • 数据可以上升也可以下降
  • 你关心的是当前值,不是变化速率
  • 数据会随着系统状态自然波动

2.3 Histogram:分布统计的利器

Histogram 是我个人最喜欢的指标类型。它不仅能记录数值,还能告诉你这些数值是怎么分布的。

举个例子:你记录了 1000 次 API 请求的延迟。平均值是 200ms,但这里面可能有 900 次是 10ms,100 次是 2s。平均值完全掩盖了真相。Histogram 就能告诉你:90% 的请求在 50ms 以内,99% 在 500ms 以内。

核心概念:

  • Bucket(桶):预先定义好的数值区间,比如 ≤10ms、≤50ms、≤100ms、≤500ms
  • Count:落在每个桶里的样本数量
  • Sum:所有样本值的总和

代码示例:

// 定义 Histogram 指标
http_request_duration_seconds_bucket{le="0.1"} 240
http_request_duration_seconds_bucket{le="0.5"} 890
http_request_duration_seconds_bucket{le="1.0"} 950
http_request_duration_seconds_bucket{le="+Inf"} 1000
http_request_duration_seconds_count 1000
http_request_duration_seconds_sum 157.3

选桶技巧:桶的分布要符合你的业务特征。我一般会先跑一周数据,看看 P50、P90、P99 大概在什么范围,然后围绕这些值设置桶。桶太少会丢失精度,桶太多会浪费存储。

典型场景:

  • 请求延迟分布
  • 响应体大小分布
  • 数据库查询耗时分布

2.4 Summary:预计算的分位数

Summary 和 Histogram 很像,都能算分位数。但区别在于:Summary 在客户端就完成了分位数计算,Histogram 是在服务端算的。

代码示例:

// Summary 指标
rpc_duration_seconds{quantile="0.5"} 0.052
rpc_duration_seconds{quantile="0.9"} 0.210
rpc_duration_seconds{quantile="0.99"} 0.850
rpc_duration_seconds_count 1000
rpc_duration_seconds_sum 157.3

重要提醒:Summary 的分位数是预定义的,你不能在查询时动态调整。比如你只定义了 P50、P90、P99,那就没法算 P95。而 Histogram 可以在查询时用 histogram_quantile() 函数算任意分位数。

什么时候用 Summary?

  • 你明确知道需要哪些分位数
  • 客户端计算能减轻服务端压力
  • 指标数量少,且分位数固定不变

2.5 选型决策指南

说了这么多,到底该怎么选?我整理了一个简单的决策流程:

你的需求 推荐类型 原因
只关心总量或速率 Counter 简单高效,存储成本低
关心当前瞬时值 Gauge 可增可减,反映实时状态
需要分析数据分布 Histogram 灵活查询任意分位数
分位数固定且客户端计算 Summary 减少服务端计算压力

避坑指南:我曾经在一个高并发系统里用 Summary 记录请求延迟,结果发现客户端计算分位数时内存暴涨。后来换成 Histogram,把计算压力转移到服务端,问题就解决了。所以——如果你的客户端资源紧张,优先考虑 Histogram。

2.6 实战中的组合使用

实际项目中,很少只用一种指标类型。我通常的做法是:

  1. 基础监控用 Counter:请求数、错误数、任务执行次数
  2. 资源监控用 Gauge:CPU、内存、磁盘、连接数
  3. 性能监控用 Histogram:延迟、响应大小、查询耗时
  4. 特定场景用 Summary:比如 SLA 报告中只需要 P99 和 P999

举个例子,一个完整的 HTTP 服务监控指标集可能是这样的:

# Counter:请求总量和错误量
http_requests_total{method="GET", status="200"}
http_errors_total{method="GET", status="500"}

# Gauge:当前连接数和队列长度
http_active_connections
http_queue_length

# Histogram:请求延迟分布
http_request_duration_seconds_bucket{le="0.05"}
http_request_duration_seconds_bucket{le="0.1"}
http_request_duration_seconds_bucket{le="0.5"}
http_request_duration_seconds_bucket{le="1.0"}

你看,每种指标各司其职。Counter 告诉你「发生了多少」,Gauge 告诉你「现在怎么样」,Histogram 告诉你「到底有多慢」。三者配合,才能看清系统的全貌。

最后说一句:指标类型选型没有绝对的对错,但有明显的优劣。我的建议是——先搞清楚你要回答什么问题,再选合适的指标类型。别为了用 Histogram 而用 Histogram,也别因为偷懒把所有数据都塞进 Gauge。

下一章我们会聊「标签设计:如何避免高基数陷阱」。嗯,这个话题我也有不少血泪史,到时候慢慢讲。