2. PromQL 基础回顾:数据类型与核心概念

在编写告警表达式之前,必须牢固掌握 PromQL 的四种数据类型以及 Metric 与 Label 的底层逻辑。告警规则的误报、漏报、表达式计算失败,绝大多数源于对这些基础概念的误解。本节将逐一拆解,并建立后续收敛规则所需的知识基座。

2.1 四种数据类型

PromQL 表达式求值后返回的结果只能是以下四种类型之一。理解它们的区别,是正确使用聚合、运算和函数的前提。

类型 英文名 含义 典型示例 告警场景注意点
瞬时向量 Instant Vector 一组时间序列,每个序列包含一个最新采样值 node_cpu_seconds_total 告警表达式最常用类型,直接比较当前值
区间向量 Range Vector 一组时间序列,每个序列包含一段时间窗口内的多个采样值 node_cpu_seconds_total[5m] 用于趋势计算、速率、预测,必须搭配时间范围
标量 Scalar 一个单一的浮点数值,没有时间序列维度 1.0、100 常用于阈值比较、数学运算的右操作数
字符串 String 一个简单的字符串值,在 PromQL 中极少使用 "warning" 告警表达式几乎不涉及,仅在某些标签操作中出现
关键区分: 瞬时向量是“当前快照”,区间向量是“历史窗口”。在告警规则中,rate()、increase()、avg_over_time() 等函数必须接收区间向量作为参数,如果误传瞬时向量,PromQL 会直接报错。

2.2 Metric 与 Label 概念

Metric(指标名)和 Label(标签)共同构成了 Prometheus 时间序列的标识体系。一个完整的时间序列由 metric_name{label1="value1", label2="value2", ...} 唯一确定。

  • Metric(指标名): 描述被监控对象“是什么”。例如 http_requests_total 表示 HTTP 请求总数,node_memory_MemAvailable_bytes 表示可用内存字节数。指标名必须符合正则 [a-zA-Z_:][a-zA-Z0-9_:]*。
  • Label(标签): 描述指标的“维度”或“属性”。例如 method="GET"、status="200"、instance="10.0.0.1:9090"。标签用于区分同一指标下的不同子集,是聚合、分组、过滤的核心工具。
工程实践建议: 在告警表达式中,合理利用 Label 可以精确控制告警范围。例如 node_load1{instance=~"web.*"} 只匹配实例名以 "web" 开头的主机,避免非核心节点触发告警。

2.3 数据类型与 Label 的关系图示

下图展示了瞬时向量、区间向量与 Metric/Label 体系之间的映射关系,以及它们在 PromQL 计算中的角色。

PromQL 数据类型与 Metric/Label 关系 时间序列标识 Metric: http_requests_total Label: method="POST" Label: status="500" 瞬时向量 当前最新值: 1024 时间戳: T 区间向量 [T-5m, T] 多个采样值 标量(Scalar) 单一数值,无 Metric 无 Label。例如:阈值 0.8、聚合结果 count 在告警表达式中常作为比较右值:node_load1 > 0.8 字符串(String):极少用于告警表达式,仅在 label_replace 等函数中作为参数出现

2.4 数据类型转换与告警表达式陷阱

在编写告警规则时,PromQL 引擎会自动进行类型推断,但以下场景需要显式注意:

  • 区间向量不能直接与标量比较: rate(http_requests_total[5m]) > 100 是正确的,因为 rate() 返回瞬时向量。但 http_requests_total[5m] > 100 会报错,因为区间向量不能直接参与比较运算。
  • 标量运算需要显式转换: 某些函数如 count()、sum() 返回瞬时向量,而非标量。如果需要标量结果,必须使用 scalar() 函数显式转换,但 scalar() 要求输入向量只有一个元素,否则返回 NaN。
  • 字符串类型在告警中几乎无用: 告警表达式最终必须返回一个布尔值或瞬时向量,字符串类型无法直接参与条件判断。
常见错误: 在告警规则中直接使用 http_requests_total[5m] 作为表达式。这返回的是区间向量,Prometheus 告警引擎无法评估其真假。必须配合 rate()、increase() 或 avg_over_time() 等函数将其转换为瞬时向量。

2.5 Label 在告警收敛中的基础作用

Label 不仅是标识维度,更是告警收敛的核心操作对象。后续章节的收敛规则(如聚合、分组、抑制)都建立在 Label 的匹配与操作之上。

Label 操作 PromQL 函数/语法 告警收敛用途
过滤 {label="value"}、{label=~"regex"} 缩小告警范围,只关注特定维度
聚合分组 sum by (label)、avg by (label) 将多个时间序列合并为一个,减少告警数量
标签重写 label_replace()、label_join() 标准化标签值,便于后续分组和抑制匹配
标签移除 告警配置中的 keep_labels / drop_labels 减少告警通知中的冗余信息,聚焦关键维度

下图展示了 Label 如何影响告警收敛中的分组与聚合流程。

Label 在告警收敛中的分组与聚合 原始序列 cpu{host="web1",core="0"} cpu{host="web1",core="1"} cpu{host="web2",core="0"} cpu{host="web2",core="1"} 聚合操作 avg by (host) sum by (host) count by (host) 收敛后序列 cpu{host="web1"} cpu{host="web2"} 告警收敛效果 4 条原始序列 → 2 条聚合序列,告警数量减少 50%,同时保留 host 维度用于后续通知路由

2.6 本节要点总结

  • 瞬时向量 是告警表达式的主力类型,代表当前状态快照。
  • 区间向量 必须配合时间窗口使用,是速率、趋势、预测类函数的输入前提。
  • 标量 作为阈值和运算常数,在比较表达式中不可或缺。
  • Metric + Label 唯一标识一个时间序列,Label 是告警收敛中分组、过滤、抑制的核心操作维度。
  • 告警表达式必须返回瞬时向量或布尔值,区间向量和字符串不能直接用于告警条件判断。