Chapter 03

PromQL 查询语言

PromQL 是 Prometheus 的灵魂。掌握向量类型、选择器、rate、聚合与函数,你就能从海量序列里问出任何答案。

3.1 四种表达式类型

Instant Vector 即时向量
一组序列在同一时刻各有一个样本。http_requests_total 就返回即时向量。
Range Vector 区间向量
一组序列在一段时间窗口内的多个样本。用 [5m] 语法得到,如 http_requests_total[5m],只能喂给 rate 类函数。
Scalar 标量
单个浮点数,如 3.14,或 scalar() 的结果。
String 字符串
仅少数函数使用,实际查询中很少直接返回。

3.2 选择器与匹配

# 精确匹配
http_requests_total{job="api", status="500"}

# 正则匹配 =~ ,取反 != / !~
http_requests_total{status=~"5.."}          # 所有 5xx
http_requests_total{handler!="/health"}      # 排除健康检查
http_requests_total{env=~"prod|staging"}    # 多值

# 区间向量 + 偏移
http_requests_total[5m]                       # 最近 5 分钟
http_requests_total offset 1h              # 1 小时前的即时值

3.3 rate / irate / increase

Counter 只增不减,直接看没意义。rate 计算区间内的每秒平均增长率,是 PromQL 里最常用的函数。

# 每秒请求数(QPS),5 分钟窗口平滑
rate(http_requests_total[5m])

# irate:只用窗口内最后两个点,反应更灵敏但更抖,适合快变化
irate(http_requests_total[1m])

# increase:区间内的总增量(= rate * 窗口秒数)
increase(http_requests_total[1h])   # 过去 1 小时总请求数
rate 的窗口要 ≥ 4×抓取间隔

rate 至少需要窗口内有两个样本才能算。若 scrape_interval 是 15s,窗口至少给 [1m](含约 4 个点),否则可能出现空结果或抖动。rate 还会自动处理 counter reset(重启归零)。

3.4 聚合算子

聚合算子把多条序列压成更少的序列。核心是 by(保留哪些 label)和 without(去掉哪些 label)。

# 全站总 QPS(去掉所有维度,聚合成一条)
sum(rate(http_requests_total[5m]))

# 按状态码分组的 QPS
sum by (status) (rate(http_requests_total[5m]))

# 每个实例的内存使用,保留 instance
avg by (instance) (node_memory_used_bytes)

# Top 3 最忙的接口
topk(3, sum by (handler) (rate(http_requests_total[5m])))

常用聚合算子:sum / avg / min / max / count / count_values / stddev / topk / bottomk / quantile

3.5 常用函数

函数作用
histogram_quantile(0.95, ...)从 _bucket 序列估算 P95 分位数
rate() / irate() / increase()Counter 速率与增量
delta() / deriv()Gauge 的变化量 / 导数
predict_linear(v[1h], 3600)线性预测未来值(如磁盘几时写满)
avg_over_time(v[5m])区间内时间加权平均(同类还有 max/min/sum_over_time)
label_replace() / label_join()动态改写 / 拼接标签
clamp_max() / round()数值裁剪与取整

算 P95 延迟

histogram_quantile(
  0.95,
  sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)

注意:先对 _bucketrate + sum by (le)(跨实例聚合),再喂给 histogram_quantile——这正是 Histogram 能跨实例聚合的原因。

3.6 二元算子与向量匹配

# 算术:错误率(5xx 占比)
sum(rate(http_requests_total{status=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

# 比较 + bool:延迟是否超标(返回 0/1)
node_filesystem_avail_bytes / node_filesystem_size_bytes < 0.1

# on/ignoring 控制向量匹配的 label 维度
rate(errors_total[5m]) / on(instance) rate(requests_total[5m])
向量匹配 on / ignoring / group_left

两个向量做运算时,Prometheus 按 label 集合配对。用 on(labels) 指定按哪些 label 匹配,ignoring(labels) 反向;一对多用 group_left/group_right——这是 PromQL 最难的部分,常见于 info 指标 join。

3.7 常见查询模式速查

CPU 使用率(node_exporter)
100 - avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100
内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
目标存活数
sum by(job)(up)——某 job 有几个目标在线。
磁盘几小时写满
predict_linear(node_filesystem_avail_bytes[6h], 4*3600) < 0
QPS by 接口
sum by(handler)(rate(http_requests_total[5m]))
P99 延迟
histogram_quantile(0.99, sum by(le)(rate(request_duration_seconds_bucket[5m])))

3.8 小结与下一步