4. 指标定义规范:Metric命名规则、标签设计原则、指标类型选择

指标定义是Exporter开发的核心环节。一个规范的指标定义,需要同时满足三个维度:命名可读、标签可查、类型可用。本章从这三个维度出发,给出可落地的标准化规范。

4.1 Metric命名规则

Prometheus官方推荐使用 snake_case 命名法,Exporter指标命名必须遵循以下层级结构:

<namespace>_<subsystem>_<unit>[_<suffix>]
层级 说明 示例
namespace 应用或领域名称,单数小写 node、redis、kafka
subsystem 模块或组件名称,可选 network、memory、disk
unit 指标描述的核心实体 bytes、requests、errors
suffix 单位后缀,如 _total、_seconds、_bytes _total、_count、_bucket
命名避坑清单:
  • 禁止使用大写字母(如 Redis_Memory)
  • 禁止使用连字符(如 redis-memory)
  • 禁止以数字开头(如 1st_request)
  • 禁止使用Prometheus保留后缀以外的自定义后缀
  • 单位后缀必须与指标实际单位一致,_bytes 不能用于计数

4.2 标签设计原则

标签是Prometheus多维数据模型的基石。设计不当的标签会导致基数爆炸、查询缓慢、存储膨胀。以下原则必须遵守:

原则 说明 正确示例 错误示例
有限基数 标签值数量应控制在100以内 status="200" user_id="u_12345"
可枚举 标签值应来自预定义集合 method="GET" ip="192.168.1.1"
不包含时间戳 时间信息应放在时间戳字段 (不添加时间标签) timestamp="2025-01-01"
不包含随机值 随机ID、UUID、Session等禁止作为标签 region="us-east" session_id="abc123"
标签名语义化 使用有业务含义的短名称 db_name attr1
标签基数爆炸典型案例: 某团队在 http_requests_total 上添加了 path 标签,包含所有RESTful路径(如 /api/v1/users/12345/profile),导致一周内标签基数从50增长到50万,Prometheus OOM。解决方案:只保留 endpoint 标签(如 /api/v1/users/:id/profile),路径参数通过日志链路追踪。

4.3 指标类型选择

Prometheus提供四种核心指标类型。选择错误会导致查询语义混乱、聚合结果失真。以下给出选择决策树和对比表:

指标类型选择决策树 指标值可增减? 是(可增可减) 否(只增不减) Gauge(仪表盘) Counter(计数器) 需要分位数? 是 否 Summary(摘要) Histogram(直方图) 选择建议 • 内存/温度/连接数 → Gauge • 请求总数/错误总数 → Counter • 延迟分位数(已知分位)→ Summary / 未知分位 → Histogram

4.4 四种指标类型对比

类型 适用场景 可聚合 分位数 典型后缀
Counter 只增不减的累计值:请求数、错误数、写入字节数 支持 rate() / increase() 不支持 _total
Gauge 可增可减的瞬时值:内存使用率、连接数、温度 支持 avg() / max() 不支持 无固定后缀
Histogram 需要自定义分位数或计算SLA:请求延迟、响应大小 支持 histogram_quantile() 服务端计算 _bucket、_count、_sum
Summary 已知分位数且客户端计算:延迟百分位、评分分布 不支持跨进程聚合 客户端计算 _count、_sum、_created
实战选择口诀:
“计数用Counter,快照用Gauge;分位未知Histogram,分位已知Summary;聚合查询选Histogram,精确分位选Summary。”

4.5 指标定义完整示例

以下是一个符合规范的Redis Exporter指标定义片段:

// 命名:redis_memory_used_bytes
// 类型:Gauge
// 标签:db, role
redis_memory_used_bytes{db="0", role="master"} 1048576

// 命名:redis_commands_total
// 类型:Counter
// 标签:command, result
redis_commands_total{command="get", result="success"} 1024

// 命名:redis_request_duration_seconds
// 类型:Histogram
// 标签:command
// Bucket:{0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1, +Inf}
redis_request_duration_seconds_bucket{command="get", le="0.01"} 500
redis_request_duration_seconds_bucket{command="get", le="+Inf"} 1024
redis_request_duration_seconds_count{command="get"} 1024
redis_request_duration_seconds_sum{command="get"} 12.345
代码审查清单: 每次提交Exporter代码前,对照以下问题检查指标定义:
1. 命名是否包含 namespace 和 unit?
2. 标签基数是否可控?
3. 类型选择是否与指标语义一致?
4. Histogram 的 bucket 边界是否覆盖业务分布?
5. 是否遗漏了 _count 和 _sum(对于 Histogram/Summary)?

4.6 标签设计实战案例

以“数据库查询延迟”指标为例,展示标签设计从坏到好的演进过程:

标签设计演进:从坏到好 ❌ 坏设计:基数爆炸 db_query_duration_seconds{query_id="q_abc123", user_id="u_98765", sql_hash="0xdeadbeef", timestamp="2025-01-01T12:00:00Z"} → 标签基数:无限(query_id、user_id 每天新增百万级) ✅ 好设计:有限基数 db_query_duration_seconds{db_name="orders", query_type="select", table="users", status="success"} → 标签基数:db_name(5) × query_type(4) × table(20) × status(2) = 800(可控) ⭐ 最佳设计:有限基数 + 业务语义 db_query_duration_seconds{db_name="orders", query_type="select", table="users", status="success"} + 慢查询详情通过日志链路 ID 关联(不放在指标标签中) → 指标用于告警和趋势,日志用于根因分析,各司其职
核心原则: 指标标签只承载“用于分组聚合的有限维度”,不承载“用于追踪的无限维度”。无限维度请走日志链路。