常规数据运维,经常要用到prometheus的语句,这里备忘下

📊 一、数据类型

类型 说明 示例
Counter 只增不减的计数器(可重置) http_requests_total, node_cpu_seconds_total
Gauge 可增可减的仪表盘 node_memory_MemAvailable_bytes, temperature
Histogram 直方图,观察值分布 http_request_duration_seconds_bucket
Summary 摘要,客户端计算分位数 rpc_duration_seconds

🔍 二、选择器和过滤器

基本选择器

# 精确匹配
http_requests_total{method="GET"}

# 不等于
http_requests_total{method!="GET"}

# 正则匹配
http_requests_total{endpoint=~"/api/.*"}

# 正则不匹配
http_requests_total{status!~"5.."}

# 多条件
http_requests_total{method="GET", status="200"}

时间范围选择器

# 瞬时向量(instant vector)
http_requests_total

# 范围向量(range vector)
http_requests_total[5m]    # 最近 5 分钟
http_requests_total[1h]    # 最近 1 小时
http_requests_total[1d]    # 最近 1 天

# 时间偏移
http_requests_total offset 1h        # 1 小时前的值
http_requests_total[5m] offset 1d    # 1 天前的 5 分钟范围

时间单位

ms  - 毫秒
s   - 秒
m   - 分钟
h   - 小时
d   - 天
w   - 周
y   - 年

🔢 三、聚合操作符

常用聚合函数

函数 说明 示例
sum 求和 sum(http_requests_total)
avg 平均值 avg(node_cpu_usage)
max 最大值 max(response_time)
min 最小值 min(response_time)
count 计数 count(up == 1)
stddev 标准差 stddev(response_time)
stdvar 方差 stdvar(response_time)
topk 前 K 个最大值 topk(5, http_requests_total)
bottomk 前 K 个最小值 bottomk(5, http_requests_total)
quantile 分位数 quantile(0.95, response_time)

分组语法

# 按指定标签分组
sum by (instance, job) (http_requests_total)

# 保留所有标签除了指定的
sum without (instance) (http_requests_total)

# 不分组(全局聚合)
sum(http_requests_total)

⚡ 四、核心函数速查

Counter 专用函数

# rate - 每秒平均增长率(常用)
rate(http_requests_total[5m])

# irate - 瞬时增长率(敏感)
irate(http_requests_total[5m])

# increase - 时间窗口内的总增长量
increase(http_requests_total[5m])

# resets - Counter 重置次数
resets(http_requests_total[5m])

关键区别:

  • rate() = 平滑平均,适合告警和图表
  • irate() = 瞬时值,适合实时监控
  • increase()rate() × 时间窗口秒数

Histogram 专用函数

# 计算分位数(P95, P99 等)
histogram_quantile(0.95, 
  sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)

时间和日期函数

time()                    # 当前时间戳
minute()                  # 当前分钟 (0-59)
hour()                    # 当前小时 (0-23)
day_of_week()            # 星期几 (0-6, 0=周日)
day_of_month()           # 当月第几天 (1-31)
days_in_month()          # 当月天数
month()                  # 月份 (1-12)
year()                   # 年份

数学函数

abs(metric)              # 绝对值
ceil(metric)             # 向上取整
floor(metric)            # 向下取整
round(metric, 0.1)       # 四舍五入到指定精度
sqrt(metric)             # 平方根
exp(metric)              # e^x
ln(metric)               # 自然对数
log2(metric)             # log2
log10(metric)            # log10

变化率函数

# 预测未来值(线性回归)
predict_linear(metric[1h], 3600)    # 预测 1 小时后的值

# 变化趋势(导数)
deriv(metric[5m])

# 变化量
delta(metric[5m])        # Gauge 用
idelta(metric[5m])       # 最后两个点的差值

排序和限制

sort(metric)             # 升序排序
sort_desc(metric)        # 降序排序
topk(5, metric)          # 前 5 大
bottomk(5, metric)       # 前 5 小

时间函数

# 时间戳转换
timestamp(metric)        # 获取样本时间戳

# 最近一次值(去除陈旧数据)
last_over_time(metric[5m])

缺失值处理

# 无数据时返回默认值
metric or vector(0)

# 标签不存在时返回默认值
label_replace(metric, "new_label", "default", "old_label", "")

🧮 五、操作符

算术操作符

+  加法
-  减法
*  乘法
/  除法
%  取模
^  幂运算

# 示例
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100

比较操作符

==  等于
!=  不等于
>   大于
<   小于
>=  大于等于
<=  小于等于

# 作为过滤器(默认)
http_requests_total > 100

# 返回 0/1(添加 bool)
http_requests_total > bool 100

逻辑操作符

and  交集
or   并集
unless  差集

# 示例:找出高 CPU 但低内存的节点
(cpu_usage > 80) and (memory_usage < 20)

向量匹配

# 一对一匹配(默认)
method:http_requests:rate5m / method:http_requests:count

# 多对一匹配
metric_a / on(instance) group_left metric_b

# 一对多匹配
metric_a / on(instance) group_right metric_b

# 忽略某些标签
metric_a / ignoring(le) metric_b

📋 六、常用查询模式

1. CPU 使用率

# 按节点
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 全局平均
100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 按 CPU 核心
100 - (rate(node_cpu_seconds_total{mode="idle"}[5m]) * 100)

2. 内存使用率

# 可用内存百分比
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100

# 使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 平均使用率
avg((1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100)

3. 磁盘使用率

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

# 剩余空间 (GB)
node_filesystem_avail_bytes / 1024 / 1024 / 1024

4. 网络流量

# 入站流量 (Mbps)
rate(node_network_receive_bytes_total[5m]) * 8 / 1000 / 1000

# 出站流量 (Mbps)
rate(node_network_transmit_bytes_total[5m]) * 8 / 1000 / 1000

# 总流量
sum(rate(node_network_receive_bytes_total[5m])) + sum(rate(node_network_transmit_bytes_total[5m]))

5. HTTP 请求监控

# QPS (每秒请求数)
sum(rate(http_requests_total[5m]))

# 按接口 QPS
sum by (endpoint) (rate(http_requests_total[5m]))

# 错误率 (%)
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100

# 成功率 (%)
sum(rate(http_requests_total{status=~"2.."}[5m])) / sum(rate(http_requests_total[5m])) * 100

# 请求延迟 P95
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

# 请求延迟 P99
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

6. 服务可用性

# 在线节点数
count(up == 1)

# 可用率
count(up == 1) / count(up) * 100

# 按 job 统计
count by (job) (up == 1)

7. 流量对比

# 当前 vs 1 小时前
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1h))

# 当前 vs 昨天同时段
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1d))

# 环比增长率 (%)
(sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1h)) - 1) * 100

8. TopK 查询

# CPU 使用最高的 5 个节点
topk(5, 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100))

# 流量最大的 5 个接口
topk(5, sum by (endpoint) (rate(http_requests_total[5m])))

# 最慢的 5 个接口
topk(5, histogram_quantile(0.95, sum by (le, endpoint) (rate(http_request_duration_seconds_bucket[5m]))))

9. 告警条件

# CPU 高于 80%
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80

# 内存低于 10%
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10

# 磁盘使用率高于 90%
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 > 90

# 服务不可用
up == 0

# 错误率高于 5%
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 > 5

# QPS 突降 50%
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 5m)) < 0.5

10. 计算趋势

# 预测 1 小时后磁盘使用率
predict_linear(node_filesystem_avail_bytes[1h], 3600)

# 计算 5 分钟内 CPU 使用率的变化趋势
deriv(node_cpu_seconds_total{mode="idle"}[5m])

⚠️ 七、重要注意事项

1. Counter 类型必须用 rate/increase

# ❌ 错误:直接使用 Counter
http_requests_total

# ✅ 正确:使用 rate
rate(http_requests_total[5m])

2. Histogram 必须保留 le 标签

# ❌ 错误:没有 le 标签
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])))

# ✅ 正确:保留 le 标签
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

3. 时间窗口选择

# 太短:数据点少,不稳定
rate(metric[30s])

# 推荐:5m-15m
rate(metric[5m])

# 太长:响应慢,不敏感
rate(metric[1h])

经验法则: 时间窗口应至少是采集间隔的 4 倍

4. rate vs irate

# ✅ 适合 rate:告警、仪表盘、长期监控
rate(http_requests_total[5m])

# ✅ 适合 irate:实时监控、瞬时尖峰检测
irate(http_requests_total[5m])

5. 避免笛卡尔积

# ❌ 危险:可能产生大量时间序列
metric_a * metric_b

# ✅ 指定匹配标签
metric_a * on(instance) metric_b

6. 标签基数问题

# ❌ 避免高基数标签:用户 ID、请求 ID、时间戳
http_requests_total{user_id="12345"}

# ✅ 使用低基数标签:状态、方法、路径模式
http_requests_total{status="200", method="GET", endpoint="/api/users"}

7. 聚合顺序优化

# ❌ 效率低:先聚合再过滤
sum(rate(http_requests_total[5m])){status="200"}

# ✅ 效率高:先过滤再聚合
sum(rate(http_requests_total{status="200"}[5m]))

8. 除法运算注意除零

# ❌ 可能除零
metric_a / metric_b

# ✅ 处理除零
metric_a / (metric_b != 0)

# 或使用默认值
(metric_a / metric_b) or vector(0)

🎯 八、性能优化建议

1. 减少查询时间范围

# ❌ 慢:查询大范围
rate(metric[1h])

# ✅ 快:查询适当范围
rate(metric[5m])

2. 使用 Recording Rules 预计算

# prometheus.yml
groups:
  - name: example
    interval: 30s
    rules:
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))

然后直接查询:

job:http_requests:rate5m

3. 限制返回结果数量

# 使用 topk/bottomk
topk(10, metric)

# 使用过滤器
metric{instance=~"prod-.*"}

🔧 九、调试技巧

1. 检查时间序列数量

count(http_requests_total)

2. 查看所有标签值

# 查看所有 instance
group by (instance) (up)

# 统计每个标签的基数
count by (instance) (http_requests_total)

3. 检查数据是否存在

# 是否有数据
count(metric) > 0

# 最近一次采集时间
time() - timestamp(metric)

4. 查看原始样本

在 Prometheus UI 的 Table 视图中查看原始数据,而不是 Graph 视图。


📚 十、命名规范(最佳实践)

Metric 命名

<namespace>_<subsystem>_<name>_<unit>

例如:
- http_requests_total
- node_cpu_seconds_total
- api_response_duration_seconds
- database_connections_active

Recording Rule 命名

<level>:<metric>:<operations>

例如:
- job:http_requests:rate5m
- instance:node_cpu:avg_rate5m

🎓 十一、学习资源

快速测试查询

在 Prometheus Web UI:http://localhost:9090/graph

常用指标查看

# 查看所有指标
{__name__=~".+"}

# 查看特定前缀的指标
{__name__=~"http.*"}

# 查看某个 job 的所有指标
{job="node-exporter"}

💡 十二、常见错误和解决方案

错误信息 原因 解决方案
parse error 语法错误 检查括号、引号是否匹配
vector cannot be matched 标签不匹配 使用 on()ignoring()
many-to-many matching 向量匹配问题 使用 group_leftgroup_right
no datapoints found 无数据 检查时间范围、标签过滤器

这份速查表涵盖了 Prometheus PromQL 的核心知识点,建议收藏备用!🚀

# 精确匹配
http_requests_total{method="GET"}

# 不等于
http_requests_total{method!="GET"}

# 正则匹配
http_requests_total{endpoint=~"/api/.*"}

# 正则不匹配
http_requests_total{status!~"5.."}

# 多条件
http_requests_total{method="GET", status="200"}
# 瞬时向量(instant vector)
http_requests_total

# 范围向量(range vector)
http_requests_total[5m]    # 最近 5 分钟
http_requests_total[1h]    # 最近 1 小时
http_requests_total[1d]    # 最近 1 天

# 时间偏移
http_requests_total offset 1h        # 1 小时前的值
http_requests_total[5m] offset 1d    # 1 天前的 5 分钟范围
ms  - 毫秒
s   - 秒
m   - 分钟
h   - 小时
d   - 天
w   - 周
y   - 年
# 按指定标签分组
sum by (instance, job) (http_requests_total)

# 保留所有标签除了指定的
sum without (instance) (http_requests_total)

# 不分组(全局聚合)
sum(http_requests_total)
# rate - 每秒平均增长率(常用)
rate(http_requests_total[5m])

# irate - 瞬时增长率(敏感)
irate(http_requests_total[5m])

# increase - 时间窗口内的总增长量
increase(http_requests_total[5m])

# resets - Counter 重置次数
resets(http_requests_total[5m])
# 计算分位数(P95, P99 等)
histogram_quantile(0.95, 
  sum by (le) (rate(http_request_duration_seconds_bucket[5m]))
)
time()                    # 当前时间戳
minute()                  # 当前分钟 (0-59)
hour()                    # 当前小时 (0-23)
day_of_week()            # 星期几 (0-6, 0=周日)
day_of_month()           # 当月第几天 (1-31)
days_in_month()          # 当月天数
month()                  # 月份 (1-12)
year()                   # 年份
abs(metric)              # 绝对值
ceil(metric)             # 向上取整
floor(metric)            # 向下取整
round(metric, 0.1)       # 四舍五入到指定精度
sqrt(metric)             # 平方根
exp(metric)              # e^x
ln(metric)               # 自然对数
log2(metric)             # log2
log10(metric)            # log10
# 预测未来值(线性回归)
predict_linear(metric[1h], 3600)    # 预测 1 小时后的值

# 变化趋势(导数)
deriv(metric[5m])

# 变化量
delta(metric[5m])        # Gauge 用
idelta(metric[5m])       # 最后两个点的差值
sort(metric)             # 升序排序
sort_desc(metric)        # 降序排序
topk(5, metric)          # 前 5 大
bottomk(5, metric)       # 前 5 小
# 时间戳转换
timestamp(metric)        # 获取样本时间戳

# 最近一次值(去除陈旧数据)
last_over_time(metric[5m])
# 无数据时返回默认值
metric or vector(0)

# 标签不存在时返回默认值
label_replace(metric, "new_label", "default", "old_label", "")
+  加法
-  减法
*  乘法
/  除法
%  取模
^  幂运算

# 示例
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100
==  等于
!=  不等于
>   大于
<   小于
>=  大于等于
<=  小于等于

# 作为过滤器(默认)
http_requests_total > 100

# 返回 0/1(添加 bool)
http_requests_total > bool 100
and  交集
or   并集
unless  差集

# 示例:找出高 CPU 但低内存的节点
(cpu_usage > 80) and (memory_usage < 20)
# 一对一匹配(默认)
method:http_requests:rate5m / method:http_requests:count

# 多对一匹配
metric_a / on(instance) group_left metric_b

# 一对多匹配
metric_a / on(instance) group_right metric_b

# 忽略某些标签
metric_a / ignoring(le) metric_b
# 按节点
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 全局平均
100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 按 CPU 核心
100 - (rate(node_cpu_seconds_total{mode="idle"}[5m]) * 100)
# 可用内存百分比
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100

# 使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 平均使用率
avg((1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100)
# 使用率
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100

# 剩余空间 (GB)
node_filesystem_avail_bytes / 1024 / 1024 / 1024
# 入站流量 (Mbps)
rate(node_network_receive_bytes_total[5m]) * 8 / 1000 / 1000

# 出站流量 (Mbps)
rate(node_network_transmit_bytes_total[5m]) * 8 / 1000 / 1000

# 总流量
sum(rate(node_network_receive_bytes_total[5m])) + sum(rate(node_network_transmit_bytes_total[5m]))
# QPS (每秒请求数)
sum(rate(http_requests_total[5m]))

# 按接口 QPS
sum by (endpoint) (rate(http_requests_total[5m]))

# 错误率 (%)
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100

# 成功率 (%)
sum(rate(http_requests_total{status=~"2.."}[5m])) / sum(rate(http_requests_total[5m])) * 100

# 请求延迟 P95
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

# 请求延迟 P99
histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
# 在线节点数
count(up == 1)

# 可用率
count(up == 1) / count(up) * 100

# 按 job 统计
count by (job) (up == 1)
# 当前 vs 1 小时前
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1h))

# 当前 vs 昨天同时段
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1d))

# 环比增长率 (%)
(sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 1h)) - 1) * 100
# CPU 使用最高的 5 个节点
topk(5, 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100))

# 流量最大的 5 个接口
topk(5, sum by (endpoint) (rate(http_requests_total[5m])))

# 最慢的 5 个接口
topk(5, histogram_quantile(0.95, sum by (le, endpoint) (rate(http_request_duration_seconds_bucket[5m]))))
# CPU 高于 80%
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80

# 内存低于 10%
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 10

# 磁盘使用率高于 90%
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 > 90

# 服务不可用
up == 0

# 错误率高于 5%
sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100 > 5

# QPS 突降 50%
sum(rate(http_requests_total[5m])) / sum(rate(http_requests_total[5m] offset 5m)) < 0.5
# 预测 1 小时后磁盘使用率
predict_linear(node_filesystem_avail_bytes[1h], 3600)

# 计算 5 分钟内 CPU 使用率的变化趋势
deriv(node_cpu_seconds_total{mode="idle"}[5m])
# ❌ 错误:直接使用 Counter
http_requests_total

# ✅ 正确:使用 rate
rate(http_requests_total[5m])
# ❌ 错误:没有 le 标签
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])))

# ✅ 正确:保留 le 标签
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))
# 太短:数据点少,不稳定
rate(metric[30s])

# 推荐:5m-15m
rate(metric[5m])

# 太长:响应慢,不敏感
rate(metric[1h])
# ✅ 适合 rate:告警、仪表盘、长期监控
rate(http_requests_total[5m])

# ✅ 适合 irate:实时监控、瞬时尖峰检测
irate(http_requests_total[5m])
# ❌ 危险:可能产生大量时间序列
metric_a * metric_b

# ✅ 指定匹配标签
metric_a * on(instance) metric_b
# ❌ 避免高基数标签:用户 ID、请求 ID、时间戳
http_requests_total{user_id="12345"}

# ✅ 使用低基数标签:状态、方法、路径模式
http_requests_total{status="200", method="GET", endpoint="/api/users"}
# ❌ 效率低:先聚合再过滤
sum(rate(http_requests_total[5m])){status="200"}

# ✅ 效率高:先过滤再聚合
sum(rate(http_requests_total{status="200"}[5m]))
# ❌ 可能除零
metric_a / metric_b

# ✅ 处理除零
metric_a / (metric_b != 0)

# 或使用默认值
(metric_a / metric_b) or vector(0)
# ❌ 慢:查询大范围
rate(metric[1h])

# ✅ 快:查询适当范围
rate(metric[5m])
# prometheus.yml
groups:
  - name: example
    interval: 30s
    rules:
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))
job:http_requests:rate5m
# 使用 topk/bottomk
topk(10, metric)

# 使用过滤器
metric{instance=~"prod-.*"}
count(http_requests_total)
# 查看所有 instance
group by (instance) (up)

# 统计每个标签的基数
count by (instance) (http_requests_total)
# 是否有数据
count(metric) > 0

# 最近一次采集时间
time() - timestamp(metric)
<namespace>_<subsystem>_<name>_<unit>

例如:
- http_requests_total
- node_cpu_seconds_total
- api_response_duration_seconds
- database_connections_active
<level>:<metric>:<operations>

例如:
- job:http_requests:rate5m
- instance:node_cpu:avg_rate5m
# 查看所有指标
{__name__=~".+"}

# 查看特定前缀的指标
{__name__=~"http.*"}

# 查看某个 job 的所有指标
{job="node-exporter"}