强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

05 - PromQL 基础

05 - PromQL 基础

5.1 PromQL 概述

PromQL(Prometheus Query Language)是 Prometheus 内置的查询语言,用于查询和聚合时间序列数据。它功能强大,支持即时查询、范围查询、聚合运算、多维过滤等操作。

查询类型

类型API 端点说明
即时查询(Instant Query)/api/v1/query返回当前时刻的值
范围查询(Range Query)/api/v1/query_range返回一段时间内的值
# 即时查询
curl 'http://localhost:9090/api/v1/query?query=up'

# 范围查询
curl 'http://localhost:9090/api/v1/query_range?query=up&start=2024-01-01T00:00:00Z&end=2024-01-01T01:00:00Z&step=15s'

5.2 时间序列数据模型

数据类型

PromQL 中有四种数据类型(表达式类型):

类型说明示例
即时向量(Instant Vector)每个时间序列一个数据点http_requests_total
范围向量(Range Vector)每个时间序列多个数据点http_requests_total[5m]
标量(Scalar)单个浮点数1 + 1
字符串(String)单个字符串"hello"

即时向量 vs 范围向量

即时向量: 每个序列返回 1 个数据点(当前时刻)
┌────────────────────┐
│ series1: value@T   │
│ series2: value@T   │
│ series3: value@T   │
└────────────────────┘

范围向量: 每个序列返回 N 个数据点(时间范围)
┌────────────────────────────────────────────┐
│ series1: [value@T-4m, value@T-3m, ..., @T] │
│ series2: [value@T-4m, value@T-3m, ..., @T] │
│ series3: [value@T-4m, value@T-3m, ..., @T] │
└────────────────────────────────────────────┘

5.3 选择器(Selectors)

选择器用于过滤和匹配时间序列。

标签匹配器

匹配器符号说明示例
等于=精确匹配job="api"
不等于!=排除匹配job!="api"
正则匹配=~正则表达式匹配status=~"2.."
正则排除!~正则表达式排除status!~"2.."

基础选择器

# 1. 精确匹配指标名称
http_requests_total

# 2. 精确匹配标签
http_requests_total{job="api-server"}

# 3. 多标签匹配(AND 逻辑)
http_requests_total{job="api-server", method="GET"}

# 4. 不等于
http_requests_total{status!="200"}

# 5. 正则匹配
http_requests_total{status=~"2.."}

# 6. 正则排除
http_requests_total{status!~"2.."}

# 7. 复杂正则
http_requests_total{path=~"/api/(users|orders).*", method=~"GET|POST"}

指标名称正则匹配

# 匹配多个指标名称
{__name__=~"http_requests.*"}

# 匹配所有 http 开头的 Counter
{__name__=~"http_.*_total"}

# 匹配特定 job 的所有指标
{job="api-server"}

范围向量选择器

# 过去 5 分钟的数据
http_requests_total[5m]

# 过去 1 小时的数据
http_requests_total[1h]

# 使用不同的时间单位
http_requests_total[30s]   # 秒
http_requests_total[5m]    # 分钟
http_requests_total[2h]    # 小时
http_requests_total[7d]    # 天
http_requests_total[1w]    # 周
http_requests_total[1y]    # 年

Offset 修饰符

# 当前时刻的值
http_requests_total

# 1 小时前的值
http_requests_total offset 1h

# 1 天前的值
http_requests_total offset 1d

# 计算过去 1 小时的增长率 vs 前 1 小时的增长率
rate(http_requests_total[5m])
/
rate(http_requests_total[5m] offset 1h)

# 一周同期对比
http_requests_total offset 1w

@ 修饰符

# 查询特定时间点的值
http_requests_total @ 1609459200

# 配合 offset
http_requests_total @ 1609459200 offset 1h

# 查询当前时间(start() 和 end() 用于范围查询)
http_requests_total @ start()
http_requests_total @ end()

5.4 运算符(Operators)

算术运算符

运算符说明示例
+加法a + b
-减法a - b
*乘法a * b
/除法a / b
%取模a % b
^幂运算a ^ 2
# 内存使用率(百分比)
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100

# 磁盘使用率
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100

# 单位转换:字节转 GB
node_memory_MemTotal_bytes / 1024 / 1024 / 1024

# 请求错误率(百分比)
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

比较运算符

运算符说明示例
==等于a == b
!=不等于a != b
>大于a > b
<小于a < b
>=大于等于a >= b
<=小于等于a <= b
# 过滤出使用率超过 90% 的文件系统
(node_filesystem_avail_bytes / node_filesystem_size_bytes) < 0.1

# 使用 bool 修饰符返回 0 或 1
(node_filesystem_avail_bytes / node_filesystem_size_bytes) < bool 0.1

逻辑运算符(集合运算符)

运算符说明说明
and交集两边都存在的序列
or并集任一边存在的序列
unless差集左边存在但右边不存在的序列
# 获取同时有 HTTP 和 gRPC 指标的实例
http_requests_total and grpc_requests_total

# 获取有 HTTP 指标或 gRPC 指标的实例
http_requests_total or grpc_requests_total

# 获取有 HTTP 指标但没有 gRPC 指标的实例
http_requests_total unless grpc_requests_total

向量匹配

当两个向量进行运算时,需要匹配对应的标签。

一对一匹配(One-to-one)

# 默认按所有标签匹配
http_requests_success / http_requests_total

# 使用 on() 指定匹配标签
http_requests_success / on(instance, job) http_requests_total

# 使用 ignoring() 排除某些标签
http_requests_success / ignoring(status) http_requests_total

多对一/一对多匹配

# group_left: 左边有多条序列,右边只有一条
http_requests_total * on(instance) group_left(node_name) node_info

# group_right: 右边有多条序列,左边只有一条
node_info * on(instance) group_right() http_requests_total

5.5 聚合函数

PromQL 提供了丰富的聚合函数,用于对多个时间序列进行聚合。

聚合函数列表

函数说明
sum()求和
min()最小值
max()最大值
avg()平均值
count()计数
stddev()标准差
stdvar()方差
topk(k, v)前 k 个最大值
bottomk(k, v)前 k 个最小值
quantile(q, v)分位数
count_values("label", v)按值计数
group(v)返回值为 1 的序列

使用 by 和 without

# by: 按指定标签分组聚合
sum by (job) (rate(http_requests_total[5m]))

# without: 排除指定标签,按其余标签分组
sum without(instance) (rate(http_requests_total[5m]))

# 每个 job 的请求速率
sum by (job) (rate(http_requests_total[5m]))

# 每个 instance 的总 CPU 使用率
avg by (instance) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))

# 每个 job 的 P99 延迟
histogram_quantile(0.99, sum by (job, le) (rate(http_request_duration_seconds_bucket[5m])))

实用聚合示例

# 1. 每个服务的请求速率 (QPS)
sum by (job) (rate(http_requests_total[5m]))

# 2. 错误率(按状态码分类)
sum by (status) (rate(http_requests_total[5m]))

# 3. 每台机器的内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 4. CPU 使用率(排除 idle)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 5. 磁盘使用率(根分区)
(1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100

# 6. 网络流量速率(MB/s)
rate(node_network_receive_bytes_total[5m]) / 1024 / 1024

# 7. Top 5 CPU 使用率最高的实例
topk(5, 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100))

# 8. 统计各状态码的数量
count_values("status_code", http_requests_total)

5.6 内置函数

速率函数

函数适用类型说明
rate(v)Counter每秒平均速率(基于范围向量)
increase(v)Counter范围内的增量
irate(v)Counter瞬时速率(基于最后两个点)
irate(v)Counter瞬时速率(更敏感,适合图表)
# rate: 平滑的每秒速率(推荐用于告警和录制规则)
rate(http_requests_total[5m])

# increase: 过去 1 小时的增量
increase(http_requests_total[1h])

# irate: 瞬时速率(更敏感,适合实时图表)
irate(http_requests_total[5m])
rate vs irate 区别:
───────────────────

rate:   使用范围内所有点计算平均斜率
        ───────  ───────  ───────  ───────
        点1       点2      点3      点4
              ↓              ↓
        计算所有点的平均斜率 → 平滑曲线

irate:  只使用最后两个点计算斜率
        ───────  ───────  ───────  ───────
        点1       点2      点3      点4
                                  ↓↓
                            只看最后两点 → 敏感波动

最佳实践:告警规则用 rate()(平滑),实时图表用 irate()(灵敏)。时间窗口建议为采集间隔的 4 倍(如 15s 间隔用 1m)。

时间函数

函数说明示例
time()当前 Unix 时间戳time()
timestamp(v)返回序列的时间戳timestamp(up)
day_of_week()星期几(0=Sunday)day_of_week()
day_of_month()每月第几天day_of_month()
hour()小时(0-23)hour()

数学函数

函数说明
abs(v)绝对值
ceil(v)向上取整
floor(v)向下取整
round(v, to_nearest)四舍五入
clamp(v, min, max)限制在范围
clamp_min(v, min)最小值限制
clamp_max(v, max)最大值限制
sort(v)升序排列
sort_desc(v)降序排列

字符串函数

函数说明
label_replace(v, dst, src, regex, replacement)标签替换
label_join(v, dst, separator, src1, src2, ...)标签合并
# 从 instance 标签提取主机名
label_replace(up, "hostname", "$1", "instance", "(.*):.*")

# 合并标签
label_join(up, "host_port", ":", "instance", "port")

5.7 经典查询示例

RED 方法(微服务监控)

# Rate: 每秒请求数
sum by (job) (rate(http_requests_total[5m]))

# Error: 错误率
sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total[5m]))

# Duration: P99 延迟
histogram_quantile(0.99,
  sum by (job, le) (rate(http_request_duration_seconds_bucket[5m]))
)

USE 方法(基础设施监控)

# Utilization: CPU 使用率
100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100

# Saturation: 系统负载 (1分钟)
node_load1

# Saturation: 内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# Error: 磁盘 IO 错误
rate(node_disk_io_errors_total[5m])

告警条件示例

# 实例宕机
up == 0

# CPU 使用率超过 80%
(100 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80

# 磁盘空间不足(剩余 < 10%)
(node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1

# 内存使用率超过 90%
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) > 0.9

# 请求错误率超过 5%
sum by (job) (rate(http_requests_total{status=~"5.."}[5m]))
/ sum by (job) (rate(http_requests_total[5m])) > 0.05

5.8 本章小结

概念说明
选择器{label="value"}, =~, !~
即时向量当前时刻的数据点集合
范围向量时间范围内的数据点集合
运算符算术、比较、逻辑、向量匹配
聚合sum, avg, max, topk + by/without
核心函数rate(), increase(), histogram_quantile()

扩展阅读


上一章04 - 指标类型 下一章06 - PromQL 进阶