常规数据运维,经常要用到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_left 或 group_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"}