怎么定义指标 · 命名、标签与基数红线
知道该测什么之后,怎么把它定义好?这一章给可执行的规则:命名规范(单位后缀是硬要求)、标签设计的取舍,以及那条必须守住的基数红线——含一个能让你立刻算出「这个指标要花多少钱」的公式。
怎么定义指标 · 命名、标签与基数红线
方法论告诉你该测什么,这一章讲怎么把它定义好。这是最“手艺活”的一章:规则不多,但每条都是血泪换来的——定义指标是个几乎不可逆的决定,一旦上线、被面板和告警依赖,改名字就是一场迁移。
命名规范
Prometheus 的命名约定不是风格问题,有些是硬要求:
格式:<命名空间>_<名词>_<单位>_<后缀>
http_requests_total ← counter 必须 _total
http_request_duration_seconds ← 单位必须写全:seconds 不是 ms
node_memory_usage_bytes ← bytes 不是 MB
process_cpu_seconds_total ← 累计 CPU 秒数
queue_depth ← gauge 不加 _total规则清单:
| 规则 | 为什么 |
|---|---|
counter 以 _total 结尾 | OpenMetrics 硬性规定,工具链依赖它 |
| 单位写在名字里,且用基本单位 | seconds 不用 milliseconds,bytes 不用 MB |
| 单位用复数 | _seconds、_bytes(约定) |
| 同名指标单位必须一致 | 否则聚合出来是垃圾 |
用 _ 不用驼峰 | 全生态约定 |
| 前缀用命名空间 | http_、node_、myapp_——避免撞名 |
“用基本单位”这条被低估了。 为什么不用毫秒?因为你会忘。三个月后你看到 http_request_duration = 250,这是 250 毫秒还是 250 秒?名字里带单位,读的人永远不用猜。而统一成秒(而非各处混用 ms/s/μs),让跨指标的运算永远正确——你可以直接把两个 _seconds 相加,不用转换。Grafana 会负责把 0.25 显示成 “250ms”,展示是展示的事,存储永远用基本单位。
一个真实的坑:改指标名的代价极高。 指标名一旦上线,就被写进了:面板、告警规则、recording rules、别人的看板、别人的告警、事故复盘文档、甚至某些自动化脚本。改名意味着所有这些都要同步改,而且历史数据不会跟着改名——你会得到一条在某个时间点断掉的曲线,以及一条从那时才开始的新曲线。
所以:第一次就想清楚。 上线前花十分钟对着这张表检查一遍,比日后迁移省一百倍力气。
标签设计:自由度与成本的交易
标签是提问的自由度,但每个标签都在放大 series 数。设计标签就是在做这笔交易。
三个问题,决定一个标签该不该加:
- 我会用它来筛选或聚合吗? —— 如果你想不出一个具体的查询会用到它,别加。“以后可能有用”是基数爆炸最常见的借口。
- 它的取值数量有上界吗? ——
status(约 10 种)、method(约 8 种)有界;user_id、url、error_message无界。无界的绝对不能加。 - 它和别的标签正交吗? —— 如果
region和datacenter一一对应,加两个是浪费(series 数不变但存储翻倍)。
一个好用的经验法则:如果你无法在心里数出这个标签有多少种取值,它就不该是标签。
基数红线:一个能立刻算出成本的公式
这是本章最实用的东西。
series 数 = 各标签取值数的乘积** × 实例数。这是乘法,不是加法——这就是它会爆炸的原因。**
举例,一个 HTTP 服务的 RED 指标:
http_request_duration_seconds_bucket{method, route, status, le, instance}
method: 5 (GET/POST/PUT/DELETE/PATCH)
route: 50 (50 个路由)
status: 8 (200/201/400/401/403/404/500/503)
le: 12 (11 个桶 + Inf) ← 别忘了 histogram 的桶也是标签!
instance: 20 (20 个 pod)
─────────────────────────────────────
series 数 = 5 × 50 × 8 × 12 × 20 = 480,000 条48 万条 series,一个指标。 而 Prometheus 的经验值是:每条活跃 series 大约吃 1~3 KB 内存(索引 + 标签 + 未落盘的 chunk)。
480,000 × 2KB ≈ 1 GB 内存 ← 就这一个指标现在看看加一个“无界”标签会怎样:
如果 route 用了原始 path(带订单 ID),假设一天 10 万个不同订单:
series 数 = 5 × 100,000 × 8 × 12 × 20 = 960,000,000 条
≈ 1.9 TB 内存 → Prometheus 当场 OOM这就是第 1 部分那个 scrape_series_added 持续 > 0 的后果。记住这个乘法公式,埋点前算一遍——它只需要 30 秒,能救你一次线上事故。
自己拖一下
光看公式没有手感。拖动下面的滑块,看这个乘法怎么把你送进 OOM:
单实例还扛得住,但该盯 head_series 了。
注意刻度是对数的——把 route 从 50 拖到 200,条子跳过大半个量程。这就是 「乘法,不是加法」的手感:直觉说「就多几个路由」,而现实是整体 ×4。
绝对不能进标签的东西
黑名单(记住它):
| ❌ 绝不 | 为什么 | 该放哪 |
|---|---|---|
user_id、session_id、request_id、trace_id | 无界 | 日志 / 追踪 |
| 原始 URL path(带 ID) | 无界 | 用路由模板 /orders/:id |
error_message、异常堆栈 | 无界 + 长 | 日志 |
| 时间戳、日期 | 无界 | 时间是 series 的维度,不是标签 |
| email、IP(客户端的) | 无界 | 日志 |
| 完整的 SQL 语句 | 无界 | 日志 / APM |
共同点:它们都是“标识符”或“自由文本”,不是“类别”。 一个可靠的判据:标签的取值应该是一个你能提前列举的、有限的“枚举”。status 是枚举,user_id 不是。
“时间戳当标签”这条值得特别提醒——听起来很蠢没人会犯,但它会伪装着出现:比如把 version="2026-07-15-build-1234" 当标签,每次发布就产生一批新 series;或者 batch_id、job_run_id 这类每次运行都变的东西。任何“每次都不一样”的值,都是时间戳的变体。
那些“确实需要高基数”的场景怎么办
如果你真的需要按 user_id 查询,答案是:别用指标。 这不是妥协,而是用对工具:
- 要按用户查 → 日志(Loki/ES)或追踪。它们为高基数而生:Loki 只索引少量标签,内容全文检索;追踪本来就是一条条独立的记录。
- 要看“最差的那些用户” → exemplar:指标里挂几个样例 trace_id,从曲线一键跳到那条具体请求。这是“聚合 + 样例”的混合模式,鱼和熊掌兼得的正确姿势。
- 要看 Top-N(如最慢的 10 个接口) → 这个可以用指标,因为接口数是有界的。但“最慢的 10 个用户”不行。
- 确实要高基数指标 → 这时该考虑的是专门的高基数后端(如某些商业 APM),而不是硬塞进 Prometheus。Prometheus 的整个设计(倒排索引、内存里的 Head)都建立在“series 数有界”这个假设上,你打破它就是在跟它的架构对抗。
一个 checklist
埋点前逐条过一遍,30 秒:
□ 名字符合规范?(_total 后缀、单位写全、基本单位、命名空间前缀)
□ 类型选对?(会减少的不是 counter;要看分布用 histogram 不用 summary)
□ 每个标签我都能说出一个会用到它的具体查询?
□ 每个标签的取值数我都能数出来?(数不出来 = 别加)
□ 算过乘法了?(各标签取值数 × 实例数 → 心里有数)
□ histogram 的桶数算进去了?(桶也是标签!)
□ 桶边界覆盖了我的 SLO 阈值?
□ 黑名单里的东西一个都没混进来?小结与下一章
命名:<命名空间>_<名词>_<单位>_<后缀>——counter 必须 _total、单位写进名字且用基本单位(seconds 不用 ms,因为你会忘;统一基本单位让跨指标运算永远正确,展示交给 Grafana);改名代价极高(面板/告警/规则/文档全要改,历史数据还不跟着改名),第一次就想清楚。标签设计问三个问题:会用它筛选吗、取值有上界吗、和别的标签正交吗——数不出取值数的东西不该是标签。基数红线:series 数 = 各标签取值数的乘积 × 实例数(是乘法!),每条活跃 series 约 1~3 KB 内存——一个普通 RED 指标就 48 万条 ≈ 1GB;换成原始 path 就是 9.6 亿条 ≈ 1.9TB 当场 OOM。黑名单:user_id / 原始 path / error_message / 时间戳及其变体(version、batch_id 等“每次都不一样”的值)一律不进标签。真需要高基数?别用指标——用日志 / 追踪 / exemplar。
规范有了,但还有个最实际的问题:多少算正常? 下一章给具体数字,收尾第 2 部分。👉 常见指标的合理范围。
参考资料
- [1] Prometheus 官方文档:Metric and label naming、Best practices — Instrumentation、Histograms and summaries。
- [2] OpenMetrics 规范(
_total后缀与单位约定)。 - [3] 关联数据模型、RED 埋点、relabeling 基数急救。