5月27日 17:39
PromQL 常用函数怎么选?一文讲透用法与避坑
PromQL 是 Prometheus 的核心查询语言,掌握常用函数是写出高效监控告警规则的基础。本文按实际使用场景分类梳理 PromQL 函数,并标注每种函数的适用指标类型和常见陷阱。
变化率与增量函数
变化率类函数是 PromQL 中使用频率最高的函数,但也是最容易用错的一类。
- rate(v range-vector):计算 Counter 类型指标在时间窗口内的平均每秒增长率。适合绘制趋势图和配置告警规则,结果会被平滑处理。例如
rate(http_requests_total[5m])计算过去 5 分钟内 HTTP 请求的每秒平均增长率。 - irate(v range-vector):计算 Counter 的瞬时增长率,仅使用时间窗口内最后两个数据点。适合绘制细粒度波动图,但不适合告警(抖动太大)。例如
irate(http_requests_total[5m])。 - increase(v range-vector):计算 Counter 在时间窗口内的总增量,等价于
rate() * 窗口秒数。返回值是整数趋势但实际可能是小数(外推导致)。例如increase(http_requests_total[1h])表示过去 1 小时新增了多少请求。 - delta(v range-vector):计算 Gauge 类型指标的差值,仅用于 Gauge。例如
delta(cpu_temp_celsius[1h])表示温度变化量。
关键区别:rate 和 irate 只能用于 Counter,delta 用于 Gauge。increase 虽然概念上返回整数,但由于外推机制,结果可能非整数。如果需要精确整数,用 floor(increase(...))。
时间窗口选择:窗口太短会导致数据稀疏时出现 NaN,太长会掩盖波动。一般建议窗口至少是采集间隔的 4 倍。
聚合函数
聚合函数用于将多个时间序列合并为更少的结果序列,是构建大盘面板的基础。
- sum():求和。最常用的聚合,例如
sum(rate(http_requests_total[5m]))计算总 QPS。 - avg():求平均值。注意平均值容易受极端值影响,监控延迟场景更推荐用分位数。
- max() / min():最大值和最小值。适合找出峰值或谷值。
- count():计数。统计时间序列的数量,例如
count(up == 0)统计宕机实例数。 - count_values():按值分组计数。例如
count_values("status", http_requests_total)统计各状态码出现次数。 - topk(k, ...):返回值最大的 k 个时间序列。适合找出负载最高的实例,例如
topk(5, rate(http_requests_total[5m]))。 - bottomk(k, ...):返回值最小的 k 个时间序列。
- quantile(φ, ...):计算分位数。例如
quantile(0.95, rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))估算 P95 延迟。
分组聚合:使用 by 子句按标签分组,例如 sum(rate(http_requests_total[5m])) by (method) 按请求方法分组求和。使用 without 排除指定标签,sum(...) without (instance) 按 instance 维度聚合。
时间窗口聚合函数(_over_time 系列)
这类函数对时间窗口内每个时间序列的数据点做聚合,与上面聚合函数的区别是:聚合函数跨序列合并,_over_time 系列在单个序列的时间维度上聚合。
- avg_over_time(x[5m]):5 分钟内平均值,适合平滑 Gauge 指标。
- max_over_time(x[5m]):5 分钟内最大值,常用于找出峰值。
- min_over_time(x[5m]):5 分钟内最小值。
- sum_over_time(x[5m]):5 分钟内求和。
- count_over_time(x[5m]):5 分钟内数据点数量,可用于检测数据缺失。
- quantile_over_time(0.9, x[5m]):5 分钟内分位数计算。
- stddev_over_time(x[5m]):5 分钟内标准差,衡量波动程度。
- stdvar_over_time(x[5m]):5 分钟内方差。
典型用法:max_over_time(node_load15[1h]) 找出过去 1 小时最大负载。
数学与取整函数
- abs(v):绝对值。
- ceil(v):向上取整,例如
ceil(cpu_usage)将 72.3 变为 73。 - floor(v):向下取整。
- round(v, nearest):四舍五入到最近的整数或指定精度。
round(3.14159, 0.01)结果为 3.14。 - sqrt(v):平方根。
- exp(v):指数函数 e^v。
- ln(v) / log2(v) / log10(v):自然对数、以 2 为底和以 10 为底的对数。
- clamp(v, min, max):将值限制在指定范围内。
clamp(cpu_percent, 0, 100)确保百分比不超出 0-100。 - clamp_max(v, max) / clamp_min(v, min):单侧限制。
预测与统计函数
- predict_linear(v range-vector, t):基于 2 小时(默认)的线性回归预测 t 秒后的值。常用于磁盘空间预警:
predict_linear(node_filesystem_avail_bytes[1h], 3600*24) < 0预测 24 小时后磁盘是否耗尽。 - deriv(v range-vector):计算 Gauge 指标的瞬时导数(变化率),适合 Gauge 趋势分析。
- holt_winters(v range-vector, sf, tf):基于 Holt-Winters 双指数平滑进行平滑和预测。sf 是平滑因子(0-1),tf 是趋势因子(0-1)。适合有周期性波动的指标。
标签操作函数
- label_replace(v, dst_label, replacement, src_label, regex):基于正则从源标签提取值写入目标标签。例如
label_replace(up, "host", "$1", "instance", "(.*):.*")从 instance 标签提取主机名写入 host 标签。 - label_join(v, dst_label, separator, src_label_1, src_label_2, ...):将多个源标签拼接后写入目标标签。例如
label_join(up, "endpoint", "-", "job", "instance")将 job 和 instance 用短横线拼接。
其他实用函数
- changes(v range-vector):计算时间窗口内值变化的次数。适合检测配置变更或重启次数:
changes(process_start_time_seconds[1d])检测一天内重启次数。 - absent(v):如果传入的向量没有数据点则返回 1,有数据则返回空。常用于检测指标消失:
absent(up{job="myapp"})在 myapp 完全无数据时触发告警。 - time():返回当前 Unix 时间戳。常用于相对时间计算。
- timestamp(v):返回向量中每个样本的时间戳。
- sort(v) / sort_desc(v):升序/降序排列。
- histogram_quantile(φ, v):从直方图桶中计算分位数,是延迟监控的核心函数。例如
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))计算 P99 延迟。注意by (le)不可省略,le 是桶边界标签。
实战示例
计算 QPS 并按服务分组:
promqlsum(rate(http_requests_total[5m])) by (service)
计算内存使用率百分比:
promqlsum(container_memory_usage_bytes) by (container) / sum(container_spec_memory_limit_bytes) by (container) * 100
计算 P95 请求延迟:
promqlhistogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, method) )
预测 24 小时后磁盘是否耗尽:
promqlpredict_linear(node_filesystem_avail_bytes{mountpoint="/"}[1h], 3600*24) < 0
检测服务重启:
promqlchanges(process_start_time_seconds[1d]) > 0
检测指标缺失:
promqlabsent(up{job="critical-service"})
常见陷阱
- 对 Gauge 用 rate:rate/irate/increase 只适用于 Counter(只增不减的累计值)。Gauge 用 delta 或 deriv。
- 窗口过短:采集间隔 15 秒却用
[30s]窗口,容易得到 NaN。窗口建议至少 4 倍采集间隔。 - increase 结果非整数:由于外推机制,increase 可能返回小数。需要精确整数时加
floor()。 - histogram_quantile 忘记 by(le):le 标签是分位数计算必需的,省略会导致结果错误。
- topk 不稳定:topk 结果随数据波动变化大,不适合直接用于告警。
- absent 的触发条件:absent 返回 1 表示无数据,告警规则应写
absent(...) == 1而非absent(...) > 0。