Prometheus源码专题【左扬精讲】—— 监控系统 Prometheus 3.4.0 源码解析:recording rule
https://github.com/prometheus/prometheus/blob/main/rules/recording.go
在 Prometheus 监控体系中,查询性能和指标一致性是大规模监控场景下绕不开的核心需求。当你面对 Grafana 面板加载缓慢、复杂 PromQL 重复计算、跨团队指标口径混乱等问题时,"Recording Rule(记录规则)" 就是解决这些痛点的关键工具。今天我们就从基础到实践,彻底搞懂 Recording Rule。
一、什么是 Prometheus Recording Rule?
1.1、核心定义
Recording Rule 是 Prometheus 提供的一种预计算规则机制:它能将频繁执行的、复杂的 PromQL 查询结果,提前计算并存储为新的时间序列指标(新指标名由用户定义)。后续查询或仪表盘展示时,无需重复执行原复杂 PromQL,直接查询预计算的新指标即可。
让 AI 用一句话概括:Recording Rule 是 “复杂查询的缓存器”,也是 “指标定义的统一器”。
1.2、核心构成
从 Prometheus 源码(https://github.com/prometheus/prometheus/blob/main/rules/recording.go#L34)的 RecordingRule 结构体中,我们能看到其核心组成部分(无需深入源码,理解概念即可):
-
-
- name:新生成的指标名(对应配置中的 record 字段);
- vector:待预计算的 PromQL 查询表达式(对应配置中的 expr 字段);
- labels:附加到新指标上的标签(用于维度补充或覆盖,避免标签冲突);
- health:规则健康状态(HealthGood/HealthBad/HealthUnknown),用于监控规则本身是否正常。
-
二、Recording Rule 解决了哪些实际问题?
在没有 Recording Rule 的场景下,我们常会遇到以下痛点,而这正是 它的核心价值 所在:
2.1、避免复杂查询的重复计算,减少资源浪费
假设你有一个 Grafana 面板,10 个图表都依赖同一个复杂查询:
sum(rate(http_requests_total{status!~"5.."}[5m])) by (service, path)(含义:按服务、接口路径统计 5 分钟内的非 5xx 请求 QPS)
如果每个图表加载时都重新执行这个查询,Prometheus 需要重复解析、计算相同的指标数据 —— 尤其是当指标基数大(比如数百个 service+path 组合)时,会占用大量 CPU 和内存资源。
用 Recording Rule 解决:
将上述复杂查询预计算为新指标 api:http_requests:qps,所有图表直接查询这个新指标,计算逻辑只执行一次(按规则评估间隔执行),资源消耗大幅降低。
2.2、优化查询性能,提升仪表盘加载速度
实时执行复杂 PromQL(尤其是包含 rate/sum/by 等聚合操作)时,计算耗时会随指标基数增加而变长 —— 可能导致 Grafana 面板加载延迟 3-5 秒,甚至超时。
用 Recording Rule 解决:
会提前将计算结果存储为新的时间序列,后续查询本质是 “读取已存在的指标数据”,耗时从秒级降至毫秒级,仪表盘加载速度显著提升。
2.3、统一指标定义,减少跨团队口径混乱
在多团队协作的场景中,不同团队可能对同一指标的计算逻辑产生分歧:
-
-
- 团队 A 计算 QPS 用 rate(http_requests_total[5m]);
- 团队 B 计算 QPS 用 rate(http_requests_total[10m]);
-
这会导致监控数据“各说各话”,无法统一分析。
用 Recording Rule 解决:
由监控团队统一定义 Recording Rule,例如:
record: api:http_requests:qps expr: sum(rate(http_requests_total[5m])) by (service, path)
所有团队都基于 api:http_requests:qps 指标做分析,从源头统一指标口径。
2.4、支撑长期数据存储与分析
Prometheus 本地存储默认保留较短时间的原始指标(比如 15 天),但业务可能需要分析 “近 3 个月的接口 QPS 趋势”。如果直接存储原始指标,会占用大量磁盘空间。
用 Recording Rule 解决:
三、如何学习并使用 Recording Rule?
掌握 Recording Rule 无需复杂的前置知识,按 “基础准备 → 配置实践 → 验证监控 → 进阶优化” 的路径学习即可。
3.1、第一步:编写 Recording Rule 配置
Recording Rule 需定义在独立的规则文件中(如 rules/recording_rules.yml),配置格式遵循 Prometheus 规则规范,核心包含 "规则组(group)" 和 "规则(rule)"两层。
配置示例(最常用场景)
假设我们需要监控“用户服务的接口 QPS”和“支付服务的成功支付率”,配置如下:
# rules/recording_rules.yml groups:- name: user_service_metrics # 规则组名(自定义,建议按业务模块划分)interval: 1m # 规则评估间隔(默认继承Prometheus全局的evaluation_interval,可单独配置)rules:# 规则1:统计用户服务各接口的QPS(非5xx请求)- record: user_api:http_requests:qps # 新生成的指标名(建议用“业务:指标:维度”格式,如user_api:http_requests:qps)expr: sum(rate(http_requests_total{service="user-service", status!~"5.."}[5m])) by (path) # 预计算的PromQLlabels: # 附加标签(可选,用于补充维度或标记)monitor: "prometheus"env: "production"# 规则2:统计用户服务各接口的5xx错误率- record: user_api:http_requests:5xx_rateexpr: sum(rate(http_requests_total{service="user-service", status=~"5.."}[5m])) by (path) / sum(rate(http_requests_total{service="user-service"}[5m])) by (path)labels:monitor: "prometheus"- name: payment_service_metricsinterval: 2m # 支付服务指标变化较慢,评估间隔设为2m,减少计算压力rules:# 规则3:统计支付服务的成功支付率(status=200为成功)- record: payment:success_rateexpr: sum(rate(payment_total{status="200"}[10m])) / sum(rate(payment_total[10m]))labels:env: "production"
关键字段说明:
字段 | 作用 |
groups.name | 规则组名称,用于分类(如按业务模块、指标类型划分),避免规则混乱。 |
groups.interval | 规则评估间隔:每隔多久执行一次 expr 中的 PromQL 并更新新指标。默认继承 Prometheus 全局配置的 evaluation_interval(通常为 1m),可根据指标变化频率调整(变化慢的指标可设为 5m/10m)。 |
rules.record | 新生成的指标名,必须唯一,建议遵循 "业务域:指标名:维度" 的命名规范(如 user_api:http_requests:qps),便于识别和管理。 |
rules.expr | 核心:需要预计算的 PromQL 查询表达式,必须是返回 “向量(Vector)” 的查询(不能是标量或矩阵)。 |
rules.labels | 附加到新指标的标签:可用于补充环境(env)、监控来源(monitor)等维度,也可覆盖原指标的标签(需谨慎,避免维度混乱)。 |
3.2、第二步:在 prometheus 中引用规则文件
编写好规则文件后,需要在 Prometheus 主配置文件(如 prometheus.yml)中通过 rule_files 字段引用,让 Prometheus 加载规则:
# prometheus.yml global:scrape_interval: 15s # 指标采集间隔evaluation_interval: 1m # 全局规则评估间隔(未配置group.interval时生效)rule_files:- "rules/recording_rules.yml" # 引用Recording Rule文件(路径可相对/绝对)scrape_configs:# 此处省略指标采集配置(如采集user-service、payment-service的指标)- job_name: "user-service"static_configs:- targets: ["user-service:8080"]- job_name: "payment-service"static_configs:- targets: ["payment-service:8080"]
3.3、第三步:重启并验证配置正确性
在启动或重载 Prometheus 前,必须验证规则配置是否正确,避免因语法错误导致规则加载失败。
使用 Prometheus 自带的 promtool 工具验证:
# 语法:promtool check rules <规则文件路径> promtool check rules rules/recording_rules.yml
如果配置正确,会输出类似以下内容:
Checking rules/recording_rules.ymlSUCCESS: 3 rules found
若存在语法错误(如 expr 中 PromQL 写错、标签格式错误),工具会直接提示错误位置和原因,需修复后再部署。
重载/重启 prometheus server,步骤省略。
3.4、第四步:验证规则是否加载成功
访问 Prometheus Web UI(http://<prometheus-ip>:9090/rules),在规则列表中可看到已配置的 Recording Rule,且 "Health" 列显示为 "OK",说明规则正常运行。
3.5、第五步:使用预计算的指标
规则生效后,Prometheus 会按 interval 间隔预计算指标,你可以:
- 在 Prometheus Web UI 中查询:直接输入 user_api:http_requests:qps,即可看到预计算的 QPS 数据;
- 在 Grafana 中引用:将仪表盘图表的数据源查询从原复杂 PromQL 替换为预计算指标,提升加载速度;
- 用于 Alert Rule:若需基于 QPS 触发告警(如 QPS 超过 1000 告警),可直接用 user_api:http_requests:qps > 1000 作为告警条件,避免重复计算。
3.6、注意:监控 Recording Rule 本身
Recording Rule 也可能出现故障(如 expr 语法错误、评估超时),需通过 Prometheus 自带指标监控其状态:
指标名称 | 含义 |
prometheus_rule_health | 规则健康状态:1 = 健康(HealthGood),2 = 不健康(HealthBad),0 = 未知(HealthUnknown)。 |
prometheus_rule_evaluation_duration_seconds_sum | 规则评估总耗时,用于判断是否存在评估超时。 |
prometheus_rule_evaluation_failures_total | 规则评估失败次数,若持续增加,需检查 expr 或指标采集是否正常。 |
建议基于这些指标配置告警(如 prometheus_rule_health == 2 时触发告警),确保 Recording Rule 本身稳定运行。
-
-
- 避免标签冲突:若 expr 结果的标签与 rules.labels 中的标签重名,rules.labels 会覆盖原标签,需确保标签名不冲突(如原指标已有 env 标签,避免在 labels 中重复定义);
- 合理设置评估间隔:间隔太短(如 10s)会增加 Prometheus 计算压力,间隔太长(如 10m)会导致指标实时性不足,建议根据指标变化频率设置(如 QPS 指标设为 1m,日活指标设为 5m);
- 规则分组按业务划分:将同一业务模块的规则放在一个 group 中(如 user_service_metrics、payment_service_metrics),便于管理和排查问题;
- 避免过度聚合:Recording Rule 适合预计算 “高频使用的复杂聚合”,无需对所有简单查询都配置规则(如单指标查询 http_requests_total 无需预计算)。
-
四、学习资源推荐
如果想进一步深入 Recording Rule,推荐以下资源:
- 官方文档:Prometheus Recording Rules(https://prometheus.io/docs/prometheus/latest/configuration/recording_rules,最权威,涵盖所有配置细节);
- 源码参考:prometheus/rules/recording.go(https://github.com/prometheus/prometheus/blob/main/rules/recording.go,了解规则的底层实现逻辑,适合进阶学习者);
- 实践案例:Prometheus 最佳实践 - Recording Rules(https://grafana.com/search/?query=recording&type=post,Grafana 官方博客,包含真实场景案例)。
Recording Rule 看似简单,却是 Prometheus 从“基础监控”走向“大规模、高性能监控”的关键一步。它通过预计算解决了复杂查询的性能问题,通过统一配置解决了指标口径混乱问题,是每一个 Prometheus 使用者都必须掌握的核心能力。建议从实际业务场景出发,先编写 1-2 个简单规则(如统计接口 QPS),验证效果后再逐步扩展到复杂场景,相信你会很快感受到它带来的便利!