服务端阅读 05月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 维度聚合。时间窗口聚合函数(overtime 系列)这类函数对时间窗口内每个时间序列的数据点做聚合,与上面聚合函数的区别是:聚合函数跨序列合并,overtime 系列在单个序列的时间维度上聚合。avgovertime(x[5m]):5 分钟内平均值,适合平滑 Gauge 指标。maxovertime(x[5m]):5 分钟内最大值,常用于找出峰值。minovertime(x[5m]):5 分钟内最小值。sumovertime(x[5m]):5 分钟内求和。countovertime(x[5m]):5 分钟内数据点数量,可用于检测数据缺失。quantileovertime(0.9, x[5m]):5 分钟内分位数计算。stddevovertime(x[5m]):5 分钟内标准差,衡量波动程度。stdvarovertime(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。clampmax(v, max) / clampmin(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)。适合有周期性波动的指标。标签操作函数labelreplace(v, dstlabel, replacement, src_label, regex):基于正则从源标签提取值写入目标标签。例如 label_replace(up, "host", "$1", "instance", "(.*):.*") 从 instance 标签提取主机名写入 host 标签。labeljoin(v, dstlabel, separator, srclabel1, srclabel2, …):将多个源标签拼接后写入目标标签。例如 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 并按服务分组:sum(rate(http_requests_total[5m])) by (service)计算内存使用率百分比:sum(container_memory_usage_bytes) by (container) / sum(container_spec_memory_limit_bytes) by (container) * 100计算 P95 请求延迟:histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, method))预测 24 小时后磁盘是否耗尽:predict_linear(node_filesystem_avail_bytes{mountpoint="/"}[1h], 3600*24) < 0检测服务重启:changes(process_start_time_seconds[1d]) > 0检测指标缺失:absent(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。