Files
wiki/监控/Prometheus/Prometheus-学习手册-02-PromQL与查询篇.md
T
2026-10-08 15:05:32 +08:00

131 KiB
Raw Blame History

Prometheus 知识学习手册 · 第 2 篇:PromQL 与查询

基于 prometheus.io 官方文档 整理 文档版本:Prometheus v3.15.0(最新稳定版,2026-10 发布)| 抓取日期:2026-10-08 数据来源:prometheus/prometheus@v3.15.0、prometheus/alertmanager、prometheus/docs 官方仓库源文件(与官网 latest 内容一致)

全册结构(共 4 篇)

  • 第 1 篇:入门与架构
  • 第 2 篇:PromQL 与查询 ← 本篇
  • 第 3 篇:配置与运维
  • 第 4 篇:Alertmanager 与生态(告警、插桩、可视化、规范)

目录


第 1 章 PromQL 基础

1.1 查询语言总览

Prometheus 提供函数式查询语言 PromQL(Prometheus Query Language),用于实时选择与聚合时间序列数据。

查询请求分为两类:

类型 含义 UI 对应
instant query(瞬时查询) 在单一时点上对表达式求值 expression browser 的 "Table" 标签页
range query(范围查询) 在 start 与 end 之间以等间隔 step 上求值 expression browser 的 "Graph" 标签页

PromQL 在两种情况下行为完全一致——range query 相当于在多个不同时间戳上重复执行 instant query。其他程序可通过 HTTP API 获取 PromQL 表达式结果(见第 5 章)。

引自:Querying basics

1.2 样本与 flavor

1.2.1 样本值类型

  • float sample:简单的浮点数值。
  • native histogram sample:包含完整直方图,即 count、sum 与 buckets。

术语说明(重要,避免混淆):

  • 术语 "histogram sample" 始终指 native histogram。
  • classic histogram 指由带 _bucket、_count、_sum 后缀的 float 样本序列共同描述的直方图。从 PromQL 视角看它们只是 float samples,不存在 "classic histogram samples"。

1.2.2 counter/gauge flavor

float sample 与 histogram sample 都具有 counter 或 gauge 的 flavor:

类型 命名 是否存储 flavor
counter float sample "counters" 否(float samples 不存储 flavor)
gauge float sample "gauges" 否
counter histogram "counter histograms" 是(histogram sample "知道" 自己的 flavor)
gauge histogram "gauge histograms" 是

因为 float samples 不存储 flavor,需用户自行在写 PromQL 时考虑(约定:float counter 的时间序列名以 _total 结尾以便区分)。而 histogram samples 知道自己属于 counter 还是 gauge,因此可对不匹配的操作给出可靠警告:

  • 对 gauge floats 应用 rate 函数很可能产生荒谬结果,但查询会被无抱怨地处理。
  • 若应用于 gauge histograms,查询结果会被标注 warning。

引自:Querying basics

1.3 表达式语言数据类型

表达式或子表达式可求值为以下四种类型之一:

类型 英文 说明
瞬时向量 Instant vector 一组时间序列,每条序列含单个样本,全部共享同一时间戳
区间向量 Range vector 一组时间序列,每条序列含一段时间范围内的多个数据点
标量 Scalar 简单数值浮点值
字符串 String 简单字符串值;目前未使用

哪些类型可作表达式根?

  • 对 instant queries:以上任意类型均可作为表达式根。
  • 对 range queries:仅支持 scalar 类型与 instant-vector 类型的表达式。

向量与时间序列均可混合包含 float samples 与 histogram samples。

1.3.1 Native histogram bucket layout 的 reconciliation

  • Native histograms 可有不同 bucket layouts,但通常可转换为兼容版本以施加二元与聚合运算。作用于 range vectors 且适用于 native histograms 的函数也执行此类 reconciliation。
  • 二元运算中 reconciliation **成对(pairwise)**执行;聚合运算与函数中所有 histogram samples 被统一 reconcile 到一种兼容 bucket layout。
  • 并非所有 bucket layout 都可 reconcile;若运算遇到不兼容直方图,对应输出向量元素会从结果中移除,并标记 warn-level annotation。详见 native histogram specification。

引自:Querying basics

1.4 字面量与时间表达式

1.4.1 String literals(字符串字面量)

不存在 "histogram literal"。 String literals 由单引号、双引号或反引号界定,遵循与 Go 相同的 escaping rules:

  • 单/双引号内反斜杠开始转义序列,后可跟 a、b、f、n、r、t、v 或 \;特定字符可用八进制(\nnn)或十六进制(\xnn、\unnnn、\Unnnnnnnn)表示。
  • 反引号界定的字符串中不解析转义字符;且与 Go 不同,Prometheus 不丢弃反引号内的换行。
"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`

1.4.2 Float literals

标量浮点值可写为整数或浮点字面量,格式(空白仅为可读性):

[-+]?(
      [0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?
    | 0[xX][0-9a-fA-F]+
    | [nN][aA][nN]
    | [iI][nN][fF]
)

示例:23、-2.43、3.4e-9、0x8f、-Inf、NaN。可在十进制或十六进制数字之间使用下划线 _ 提升可读性,如 1_000_000、.123_456_789、0x_53_AB_F3_82。

1.4.3 时间持续(duration)

Float literals 也用于以秒为单位指定时长。十进制整数可组合以下时间单位:

单位 含义 等价关系
ms milliseconds —
s seconds 1s equals 1000ms
m minutes 1m equals 60s(忽略 leap seconds)
h hours 1h equals 60m
d days 1d equals 24h(忽略 daylight saving time)
w weeks 1w equals 7d
y years 1y equals 365d(忽略 leap days)

给十进制整数加上述单位后缀,等价于以裸 float literal 表示的相同秒数:

写法 等价裸值
1s 1.
2m 120.
1ms 0.001.
-2h -7200.

以下示例不工作:

  • 0xABm(十六进制数不可加后缀)
  • 1.5h(时间单位不能与浮点数组合)
  • +Infd(±Inf 或 NaN 不可加后缀)

多个单位可通过拼接带后缀整数组合,单位必须从最长到最短排序,且每个单位在一个 float literal 中只能出现一次:

写法 等价
1h30m 5400s 即 5400.
12h34m56s 45296s 即 45296.
54s321ms 54.321

1.4.4 Duration expressions(时长表达式)

凡期望时间持续之处均可使用算术表达式,即 range vector selectors 与 offset durations 中:

rate(http_requests_total[5m * 2])     # 10 minute range
rate(http_requests_total[(5+2) * 1m]) # 7 minute range
http_requests_total offset (1h / 2)       # 30 minute offset
http_requests_total offset ((2 ^ 3) * 1m) # 8 minute offset

使用 offset 配合 duration expression 时必须用括号包裹表达式;无括号时 offset 计算只采用第一个 duration 值。支持的运算符(按通常优先级):+ 加法、- 减法、* 乘法、/ 除法、% 取模、^ 幂。

duration expressions 内可用函数:

函数 解析结果 instant query 下
step() range query 的 step width 0s
range() range query 的完整范围(end time − start time) 0s
min_of(<duration>, <duration>) 两者中较小者(用于把时长封顶到最大值) —
max_of(<duration>, <duration>) 两者中较大者(用于强制最小值) —

range() 特别适合配合 @ end() 回顾整个查询范围,如 max_over_time(metric[range()] @ end())。

例如 max_of(step(), 5s) 保证时长不短于 5s,min_of(range(), 1h) 把时长封顶为 1h。注意:@ modifier 中不支持 duration expressions。

等价时长示例:

表达式 等价于
5m * 2 10m 或 600s
10m - 1m 9m 或 540s
(5+2) * 1m 7m 或 420s
1h / 2 30m 或 1800s
4h % 3h 1h 或 3600s
(2 ^ 3) * 1m 8m 或 480s
step() + 1 查询 step width 增加 1s
max_of(step(), 5s) 查询 step 与 5s 中较大者
min_of(2 * step() + 5s, 5m) 两倍 step 加 5s 与 5m 中较小者

引自:Querying basics

1.5 时间序列选择器

1.5.1 Instant vector selectors(瞬时向量选择器)

允许选择一组时间序列及其在给定时点的单个样本值。最简形式只指定 metric name,返回包含所有该名字时间序列的 instant vector。

返回值是查询评估时间戳(instant query)或查询中当前 step(range query)之前或等于该时刻的最新样本。@ modifier 可覆盖选择所依据的时间戳。仅当其最新样本在 lookback period 之内时序列才被返回(见 1.7)。

http_requests_total
http_requests_total{job="prometheus",group="canary"}
http_requests_total{environment=~"staging|testing|development",method!="GET"}

1.5.2 标签匹配运算符

运算符 含义
= 选择标签值精确等于所给字符串
!= 选择标签值不等于所给字符串
=~ 选择标签值正则匹配所给字符串
!~ 选择标签值不正则匹配所给字符串

关键规则:

  • Regex 匹配完全锚定:env=~"foo" 视为 env=~"^foo$"。
  • 匹配空标签值的 matcher 也会选中所有根本没有设置该标签的时间序列。
  • 同一标签名可有多个 matcher,所有 matcher 都通过才返回。

空标签匹配示例:给定数据集 http_requests_total、http_requests_total{replica="rep-a"}、http_requests_total{replica="rep-b"}、http_requests_total{environment="development"}:

  • 查询 http_requests_total{environment=""} 返回前三条,排除 environment="development" 那条。
  • 查询 http_requests_total{replica!="rep-a",replica=~"rep.*"} 匹配 http_requests_total{replica="rep-b"}。

合法性要求:Vector selectors 必须指定 name 或至少一个不匹配空字符串的 label matcher:

写法 是否合法
{job=~".*"} # Bad! ❌ 非法(正则匹配空串)
{job=~".+"} # Good! ✅ 合法
{job=~".*",method="get"} # Good! ✅ 合法(有一个不匹配空串)

1.5.3 通过 __name__ 匹配指标名

Label matchers 也可通过匹配内部 __name__ 标签施加于 metric name:

  • http_requests_total 等价于 {__name__="http_requests_total"}。
  • 除 = 外还可用 !=、=~、!~。
  • {__name__=~"job:.*"} 选择所有名字以 job: 开头的指标。

metric name 不得为关键字 bool、on、ignoring、group_left、group_right,例如 on{} # Bad! 非法;变通方法是使用 __name__ 标签:{__name__="on"} # Good!。

1.5.4 Range Vector Selectors(区间向量选择器)

行为类似 instant vector literals,但选择从当前时刻回溯的一段样本范围。语法上在 vector selector 末尾用方括号 [] 追加一个 float literal,指定每条 range vector 元素向前回溯多少秒取值,常用带时间单位的写法如 [5m]。

  • 区间为左开右闭:时间戳与左边界重合的样本被排除,与右边界重合的被包含。
http_requests_total{job="prometheus"}[5m]

引自:Querying basics

1.6 时间修饰:offset、@ modifier 与子查询

1.6.1 Offset modifier

允许为查询中单个 instant 与 range vector 改变时间偏移。offset 必须紧跟 selector。

http_requests_total offset 5m
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
rate(http_requests_total[5m] offset 1w)
rate(http_requests_total[5m] offset -1w)
  • 查询过去的样本用正 offset。
  • 负 offset 可实现向未来方向的时间比较,允许查询前瞻其评估时间。

1.6.2 @ modifier

允许为查询中单个 instant 与 range vector 改变求值时间。@ 接受 Unix timestamp,用 float literal 描述。@ 必须紧跟 selector。

http_requests_total @ 1609746000
sum(http_requests_total{method="GET"} @ 1609746000) // GOOD.
sum(http_requests_total{method="GET"}) @ 1609746000 // INVALID.
rate(http_requests_total[5m] @ 1609746000)
  • 它支持上述所有数值字面量表示形式。
  • 可与 offset 共用,offset 相对于 @ 时间施加,结果与两者顺序无关:
http_requests_total @ 1609746000 offset 5m
http_requests_total offset 5m @ 1609746000
  • start() 与 end() 可作为 @ 的特殊值:对 range query 分别解析为 range query 的起点与终点,且对所有 step 保持不变;对 instant query 两者都解析为求值时间。
http_requests_total @ start()
rate(http_requests_total[5m] @ end())

注意:@ modifier 允许查询前瞻其评估时间。

1.6.3 Subquery(子查询)

Subquery 允许对给定 range 与 resolution 运行 instant query,结果是一个 range vector。

语法:

<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <float_literal> ]
  • <resolution> 可选,默认为全局 evaluation interval。

引自:Querying basics

1.7 Lookback 与 staleness

1.7.1 为什么需要 lookback

查询期间采样数据的时间戳独立于实际现存的时间序列数据而选择,主要为支持 sum、avg 等聚合场景(多条被聚合序列在时间上并不精确对齐)。因此 Prometheus 需为每个相关时间序列在这些时间戳赋值,方式是取不超过 lookback period 之前的最新样本。

1.7.2 lookback period

项 值
默认值 5 分钟
全局配置 --query.lookback-delta flag
单次查询覆盖 lookback_delta 参数(HTTP API,见第 5 章)

1.7.3 Staleness(陈旧标记)

  • 若 target scrape 或 rule evaluation 不再返回某条先前存在的时间序列的样本,该序列被标记为 stale。
  • 若 target 被移除,先前抓取的序列会在移除后不久被标记 stale。
  • 若查询在某序列被标记 stale 之后的采样时间戳求值,则该序列不返回值;若后续有新样本摄入,则按预期返回。
  • 序列在其不再被导出或 target 不存在时变 stale,会消失在图中(在最后一次采集样本处),并在标记 stale 后不再被查询返回。
  • 某些自行给样本打时间戳的 exporters 行为不同:停止导出的序列会在(默认)5 分钟内保留最后一个值再消失;track_timestamps_staleness 设置可改变该行为。

引自:Querying basics

1.8 正则表达式

Prometheus 中所有正则表达式使用 RE2 syntax。Regex 匹配始终完全锚定。

引自:Querying basics

1.9 UTF-8 引用语法提点

从 Prometheus 3.0 起,任意 UTF-8 字符串都是合法的 metric/label 名(详见第 8 章)。在 PromQL 中查询这类名称需要略不同的语法:

  • classic 查询语法对 legacy-compatible 名称仍有效:my_metric{}。
  • UTF-8 名称必须加引号并移入花括号内:{"my.metric"}。
  • label 名若含 legacy-incompatible 字符也必须加引号:{"metric.name", "my.label.name"="bar"}。
  • metric 名可出现在花括号内任意位置,但风格上偏好放在首个位置。

引自:UTF-8 in Prometheus

1.10 注释与慢查询规避

1.10.1 注释

PromQL 支持以 # 开头的行注释,例如 # This is a comment。

1.10.2 Avoiding slow queries and overloads

若查询需处理大量数据,绘图可能超时或拖垮服务器/浏览器。因此:

  • 在未知数据上构建查询时,应始终先在 expression browser 的表格视图中构建,直到结果集合理(最多数百条而非数千条时间序列)。
  • 只有充分过滤或聚合后才切到 graph 模式。
  • 若临时绘图仍太慢,通过 recording rule 预先记录。

此点对 PromQL 尤其相关:

  • 裸 metric name selector 如 api_http_requests_total 可能展开为数千条不同标签的时间序列;
  • 即便输出仅少量序列,对众多序列聚合的表达式也会给服务器带来负载,类似关系数据库中求整列之和即便输出单值也会很慢。

引自:Querying basics

💡 补充:本手册第 6 章「查询调试」给出了 query log 的开启方式与性能排查思路,可与本节配合使用。


第 2 章 运算符

PromQL 支持 unary(一元)、binary(二元) 与 aggregation(聚合) 三类运算符。

引自:Operators

2.1 一元运算符

PromQL 中唯一的 unary 运算符是 -(unary minus),可作用于 scalar 或 instant vector:

  • 作用于 scalar 时返回符号取反的 scalar;
  • 作用于 instant vector 时返回每个元素符号取反的 instant vector;
  • histogram sample 的符号通过反转所有 bucket populations 及观测的 count 与 sum 的符号来反转,结果 histogram sample 总被视为 gauge histogram。

Note

:含任何负 bucket population 或负观测 count 的 histogram 只应作为中间结果使用。若这种负直方图是 recording rule 的最终结果,rule evaluation 会失败。负直方图无法被任何交换格式(exposition、remote-write、OTLP)表示,因此无法以任何方式摄入 Prometheus,只能由 PromQL 表达式创建。

引自:Operators

2.2 算术运算符

2.2.1 运算符清单

运算符 含义
+ addition(加法)
- subtraction(减法)
* multiplication(乘法)
/ division(除法)
% modulo(取模)
^ power / exponentiation(幂)

定义为 scalar/scalar、vector/scalar、vector/vector 值对之间的运算,遵循通常的 IEEE 754 浮点算术,包括对 NaN、+Inf、-Inf 等特殊值的处理。

2.2.2 scalar 之间

直接求值为对两个操作数施加运算符后的另一个 scalar。

2.2.3 instant vector 与 scalar 之间

运算符施加于 vector 中每个数据样本的值。

  • 若样本是 float,则在该 float 与 scalar 间执行运算(例如 float samples 的 instant vector 乘 2,结果是每个样本值都乘以 2 的 float samples 向量)。
  • 对 histogram sample 的向量元素:
    • *:将所有 bucket populations 及观测 count 与 sum 乘以 scalar(scalar 为负则结果视为 gauge histogram,否则保留输入的 counter vs. gauge flavor)。
    • /:要求 histogram sample 在左侧(LHS)、scalar 在右侧(RHS),将 bucket populations 及 count 与 sum 除以 scalar。除以零结果为无 regular buckets 的直方图,zero bucket population 与 count、sum 依输入值(正、负、零/NaN)分别设为 +Inf、-Inf 或 NaN(scalar 为负则结果为 gauge histogram,否则保留输入 flavor)。
    • scalar 在 LHS、histogram 在 RHS 的 /,以及所有其他 scalar 与 histogram 组合的算术二元运算符,无结果且对应元素从结果向量中移除,并以 info-level annotation 标记。

2.2.4 两个 instant vectors 之间

运算符施加于 LHS 向量每个条目及其在 RHS 中的 matching element,结果传播到结果向量且 grouping labels 成为输出标签集。默认情况下,在对面向量找不到匹配条目的序列不进入结果,该行为可用 fill modifiers 调整(见 2.10)。

样本类型匹配规则:

LHS / RHS 行为
float / float 对两个输入值施加算术运算符
float / histogram 遵循 scalar 与 histogram 间的同一逻辑(* 与 / 后者要求 histogram 在 LHS 有效,其余导致元素移除)
histogram / histogram 只有 + 与 - 有效,各将匹配的 bucket populations 及 count 与 sum 相加或相减;其余运算导致元素移出输出向量并标记 info-level annotation

关于 histogram 的加减:

  • + 与 - 一般只应作用于 gauge histograms,但 PromQL 也允许用于 counter histograms 以覆盖特定用例,此时需特别留意 counter resets 不对齐问题(PromQL 能检测某些 counter reset 不兼容并标记 warn-level annotation)。
  • 两个 counter histograms 相加结果为 counter histogram;所有其他操作数组合及所有减法结果为 gauge histogram。
  • 任何涉及向量的算术二元运算都会丢弃 metric name,即便在 on 中显式提到 __name__ 也如此(参见 issue 16631)。
  • 对任何可能产生负直方图的算术二元运算,须注意 2.1 节 unary operator 的相关 note。

引自:Operators

2.3 三角函数运算符

存在以下三角函数二元运算符,以弧度工作:

运算符 含义
atan2 基于 https://pkg.go.dev/math#Atan2

三角函数运算符允许借助 vector matching 对两个向量执行三角函数,这是普通函数所不具备的。其行为方式与算术运算符相同,仅作用于 float samples;涉及 histogram samples 的运算导致对应向量元素移出输出向量并标记 info-level annotation。

引自:Operators

2.4 直方图裁剪运算符

存在以下二元 histogram trim 运算符:

运算符 含义
</ trim upper:移除所有高于阈值的观测
>/ trim lower:移除所有低于阈值的观测

定义为 vector/scalar 与 vector/vector 值对之间的运算,左侧为 native histogram(exponential 或 NHCB),右侧为 float 阈值。

  • 若阈值未与直方图某 bucket 边界对齐,则采用线性插值(对 NHCB 与 exponential histogram 的 zero buckets)或指数插值(对 exponential histogram 的非零 bucket)计算阈值所在 bucket 中剩余观测的估计数量。
  • 当有观测被 trim 时,新的观测值之和基于剩余观测(近似)重新计算。

引自:Operators

2.5 比较运算符

2.5.1 运算符清单

运算符 含义
== equal(等于)
!= not-equal(不等于)
> greater-than(大于)
< less-than(小于)
>= greater-or-equal(大于等于)
<= less-or-equal(小于等于)

定义为 scalar/scalar、vector/scalar、vector/vector 值对之间。默认过滤(filter),行为可通过在运算符后提供 bool 修改,bool 会返回值 0 或 1 而非过滤。

2.5.2 各类组合的详细行为

组合 行为
两个 scalars 必须提供 bool modifier,结果为另一个 scalar,依比较结果为 0(false)或 1(true)
instant vector 与 scalar 施加于 vector 中每个数据样本值,比较结果为 false 的向量元素从结果向量中丢弃。仅适用于 float samples;对 histogram samples,对应元素从结果向量移除并标记 info-level annotation
两个 instant vectors 默认作为 filter 施加于匹配条目。表达式不为真或在另一侧找不到匹配的向量元素从结果中丢弃,其余传播到结果向量且 grouping labels 成为输出标签集

向量间样本类型:

  • 两个 float samples 匹配照常工作;
  • float sample 与 histogram sample 匹配非法,对应元素移除并标记 info-level annotation;
  • 两个 histogram samples 之间 == 与 != 照常工作,其余比较二元运算均非法。

2.5.3 bool modifier 与 metric name

  • 涉及向量的比较二元运算中提供 bool modifier 会改变行为:在另一侧找到匹配但表达式为假的向量元素值为 0,找到匹配且表达式为真的值为 1(注意无匹配或涉及 histogram samples 的非法运算仍返回无结果而非 0);且 metric name 被丢弃。
  • 若未提供 bool modifier,则保留左侧的 metric name,但有例外:
    • 使用 on 时 metric name 被丢弃;
    • 使用 group_right 时保留右侧 metric name 以避免冲突。

引自:Operators

2.6 逻辑/集合运算符

以下 logical/set 二元运算符仅在 instant vectors 之间定义:

运算符 含义
and intersection(交集)
or union(并集)
unless complement(补集)

语义:

  • vector1 and vector2:结果为 vector1 中那些在 vector2 存在标签集完全匹配元素的元素,其他元素丢弃;metric name 与值从左侧向量带过来。
  • vector1 or vector2:结果为包含 vector1 全部原始元素(标签集 + 值),外加 vector2 中在 vector1 无匹配标签集的全部元素。
  • vector1 unless vector2:结果为 vector1 中那些在 vector2 不存在标签集完全匹配元素的元素;两向量中所有匹配元素都被丢弃。

由于这些 logical/set 运算符不与样本值交互,对 float samples 与 histogram samples 行为相同。

引自:Operators

2.7 向量匹配

向量间运算为 LHS 每个条目尝试在 RHS 向量中找到匹配元素。有两种基本匹配行为:One-to-one 与 many-to-one / one-to-many。

2.7.1 匹配关键字

Vector matching keywords(允许在不同标签集的序列间匹配):

关键字 含义
on(<label list>) 仅在所给标签上匹配
ignoring(<label list>) 匹配时忽略所给标签

提供给匹配关键字的标签列表决定向量如何组合。

Group modifiers(启用 many-to-one / one-to-many 匹配):

modifier 含义
group_left 允许 many-to-one 匹配,左侧向量基数更高
group_right 允许 one-to-many 匹配,右侧向量基数更高

可为 group modifier 提供标签列表,包含 "one" 侧的标签以纳入结果指标。

重要提示:Many-to-one 与 one-to-many 匹配是高级用例,应谨慎考虑;通常正确使用 ignoring(<labels>) 即可得到期望结果。Grouping modifiers 只能用于 comparison、arithmetic 与 trigonometric 运算符;set 运算符默认与任一侧所有可能条目匹配。

2.7.2 One-to-one vector matches

找到运算两侧唯一的一对条目。默认情形即 vector1 <operator> vector2 形式;两个条目标签集与对应值完全相同则匹配。

  • ignoring 允许匹配时忽略某些标签;
  • on 允许将考虑标签集缩减为所给列表。
<vector expr> <bin-op> ignoring(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) <vector expr>

示例输入:

method_code:http_errors:rate5m{method="get", code="500"}  24
method_code:http_errors:rate5m{method="get", code="404"}  30
method_code:http_errors:rate5m{method="put", code="501"}  3
method_code:http_errors:rate5m{method="post", code="500"} 6
method_code:http_errors:rate5m{method="post", code="404"} 21

method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120

示例查询:

method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m

返回结果向量包含各 method 在过去 5 分钟状态码 500 的 HTTP 请求占比。没有 ignoring(code) 就不会有匹配,因为两个指标不共享相同标签集。put 与 del 方法无匹配,不出现在结果中:

{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

2.7.3 Many-to-one 与 one-to-many vector matches

指 "one" 侧每个向量元素可匹配 "many" 侧多个元素的情形,必须用 group_left 或 group_right modifiers 显式请求,left/right 决定哪个向量基数更高:

<vector expr> <bin-op> ignoring(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> ignoring(<label list>) group_right(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_left(<label list>) <vector expr>
<vector expr> <bin-op> on(<label list>) group_right(<label list>) <vector expr>
  • group modifier 提供的标签列表包含来自 "one" 侧的额外标签以纳入结果指标。
  • 对 on,一个标签只能出现在其中一个列表中。
  • 结果向量的每条时间序列必须唯一可识别。

示例查询:

method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m

此处左侧向量每个 method 标签值有多个条目,用 group_left 表示。右侧元素现在与左侧相同 method 标签的多个元素匹配:

{method="get", code="500"}  0.04            //  24 / 600
{method="get", code="404"}  0.05            //  30 / 600
{method="post", code="500"} 0.05            //   6 / 120
{method="post", code="404"} 0.175           //  21 / 120

2.7.4 on/ignoring 与 group modifier 规则详表

组合写法 匹配语义 结果标签
v1 <op> v2 one-to-one,全标签集须完全相同 两向量标签集交集
v1 <op> ignoring(<L>) v2 one-to-one,忽略标签 L 后匹配 同上(忽略 L)
v1 <op> on(<L>) v2 one-to-one,仅按 L 匹配 仅保留 L
v1 <op> ignoring(<L>) group_left(<M>) v2 many-to-one,左多右一 左标签 + M(取自 "one" 侧右向量)
v1 <op> ... group_right(<M>) ... v2 one-to-many,右多左一 右标签 + M(取自 "one" 侧左向量)
v1 <op> on(<L>) group_left(<M>) v2 many-to-one,按 L 匹配 L + M,L 与 M 不得重叠

引自:Operators

2.8 聚合运算符

2.8.1 运算符清单

内置聚合运算符用于对单个 instant vector 的元素聚合,产生元素更少、值为聚合值的新向量:

运算符 含义
sum(v) calculate sum over dimensions
avg(v) calculate the arithmetic average over dimensions
min(v) select minimum over dimensions
max(v) select maximum over dimensions
bottomk(k, v) 按样本值取最小的 k 个元素
topk(k, v) 按样本值取最大的 k 个元素
limitk(k, v) 采样 k 个元素,experimental
limit_ratio(r, v) 采样伪随机比例 r 的元素,experimental
group(v) 结果向量中所有值均为 1
count(v) 向量中元素个数
count_values(l, v) 统计具有相同值的元素个数
stddev(v) 总体标准差(population standard deviation)
stdvar(v) 总体方差(population variance)
quantile(φ, v) 计算 φ-quantile(0 ≤ φ ≤ 1)

limitk 与 limit_ratio 须用 --enable-feature=promql-experimental-functions 启用。

2.8.2 by / without 子句

这些运算符既可对所有标签维度聚合,也可通过 without 或 by 子句保留不同维度;子句可置于表达式之前或之后:

<aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)
<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]
  • label list 为不带引号的标签列表,允许尾随逗号,即 (label1, label2) 与 (label1, label2,) 均为合法语法。
  • without 从结果向量中移除所列标签而保留其他标签;
  • by 相反,丢弃未列入 by 的标签,即便这些标签值在向量所有元素间完全相同。

2.8.3 各聚合运算符详解

sum(v):以与 + 二元运算符相同的方式累加 v 中样本值。聚合到同一结果向量元素的所有样本值必须同为 float samples 或 histogram samples;混合聚合非法,对应向量元素从输出移除并标记 warn-level annotation。

# 若 memory_consumption_bytes 按 application、instance、group 标签 fanout:
sum without (instance) (memory_consumption_bytes)   # 等价于 sum by (application, group) (...)
sum(memory_consumption_bytes)                       # 所有 application 的总内存消耗

avg(v):以与 / 二元运算符相同的方式用 v 之和除以被聚合样本数。同样要求聚合到同一结果元素的所有样本同为 float 或 histogram,混合非法 → 元素移除并标记 warn-level annotation。

min(v) 与 max(v):分别返回 v 中最小/最大值。仅作用于 float samples,遵循 IEEE 754 浮点算术,尤其意味着 NaN 只有在所有被聚合值均为 NaN 时才被视为最小/最大值。输入向量中的 histogram samples 被忽略并标记 info-level annotation。

topk(k, v) 与 bottomk(k, v):与其他聚合器不同,返回输入样本中 k 个值的子集(含原始标签)到结果向量。by 与 without 仅用于对输入向量分桶。

  • 与 min/max 类似仅作用于 float samples,将 NaN 视为距最高/最低最远;输入向量中 histogram samples 被忽略并标记 info-level annotation。
  • 若用于 instant query,topk 与 bottomk 分别按值降序/升序返回序列;
  • 若配合 by 或 without,则各桶内序列按值排序且同桶序列连续返回,但不保证各桶按特定顺序返回。
  • range queries 不应用排序。
topk(5, memory_consumption_bytes)   # 跨所有实例内存消耗最高的 5 个实例

limitk(k, v)(experimental):返回 k 个输入样本的子集,结果向量含原始标签。子集以确定性伪随机方式选取,与样本类型无关,因此对 float samples 与 histogram samples 都适用。

limitk(10, memory_consumption_bytes)

limit_ratio(r, v)(experimental):返回输入样本的子集,结果向量含原始标签,同样为确定性伪随机选取,与样本类型无关因而适用于两种样本。

  • r 可取 +1 与 -1 之间;r 的绝对值用作选择比例,但负 r 时选择顺序反转,可用于选取补集。
  • limit_ratio(0.1, ...) 返回约 10% 输入样本的确定性集合,而 limit_ratio(-0.9, ...) 精确返回 limit_ratio(0.1, ...) 未返回的其余约 90% 样本。

group(v):对每个在该时间戳含任意值的组返回 1。值可为 float 或 histogram sample。

count(v):返回该时间戳的值的个数,若该时间戳无值则完全不返回值。值可为 float 或 histogram sample。

count_values(l, v):对 v 中每个唯一样本值输出一条时间序列,每条序列带一个由 l 给出的附加标签,标签值为该唯一样本值,每条序列的值是该样本值出现的次数。对 float samples 与 histogram samples 都工作;对后者,使用 histogram sample 值的紧凑字符串表示作为标签值。

count_values("version", build_version)   # 统计各构建版本运行的二进制数

stddev(v) / stdvar(v):分别返回 v 的标准差 / 方差。仅适用于 float samples,遵循 IEEE 754 浮点算术;输入向量中 histogram samples 被忽略并标记 info-level annotation。

quantile(φ, v):计算 φ-quantile,即在所聚合维度的 N 个指标值中排名第 φ*N 的值。仅适用于 float samples;输入向量中 histogram samples 被忽略并标记 info-level annotation。NaN 被视为可能的最小值。

  • quantile(0.5, ...) 计算中位数,quantile(0.95, ...) 计算 95 分位。
  • 特殊情况:φ = NaN 时返回 NaN;φ < 0 时返回 -Inf;φ > 1 时返回 +Inf。

引自:Operators

2.9 二元运算符优先级

二元运算符优先级从高到低:

优先级 运算符
1(最高) ^
2 *, /, %, atan2
3 +, -
4 ==, !=, <=, <, >=, >
5 and, unless
6(最低) or
  • 同级运算符左结合,例如 2 * 3 % 2 等价于 (2 * 3) % 2。
  • 但 ^ 是右结合,故 2 ^ 3 ^ 2 等价于 2 ^ (3 ^ 2)。

引自:Operators

2.10 实验特性:fill modifiers

Fill modifiers 为 experimental,必须用 --enable-feature=promql-binop-fill-modifiers 启用。

默认在二元运算另一侧找不到匹配的向量元素不进入结果向量;fill modifiers 允许用所给默认样本值填充任一侧缺失序列:

modifier 含义
fill(<value>) 用 value 填充任一侧缺失匹配
fill_left(<value>) 用 value 填充左侧缺失匹配
fill_right(<value>) 用 value 填充右侧缺失匹配

约束:

  • value 必须是表示 float sample 的数值字面量;不支持 histogram samples。
  • 这些 modifier 只能填充运算某一侧缺失的序列;若序列在两侧都缺失则无法由此创建。
  • 允许的组合:fill(<default>);fill_left(<default>);fill_right(<default>);fill_left(<default>) fill_right(<default>);fill_right(<default>) fill_left(<default>)。
  • 若使用 bool、on、ignoring、group_left、group_right 等其他二元运算符 modifier,fill modifiers 必须置于最后。

与 group_left/group_right 组合时:

  • 若 fill modifier 用于匹配的 "many" 侧,则只为每个匹配组的 "many" 侧填充单条序列,以该组的 matching labels 作为序列标识;
  • 若用于 "one" 侧且 grouping modifier 指定了要纳入的 "one" 侧标签名(如 left_vector * on(instance, job) group_left(info_label) fill_right(1) right_vector),则这些标签不会为缺失序列填充,因为其值无来源。

Fill modifiers 不支持 set 运算符(and、or、unless),因为这些运算符的目的就是基于另一向量中的存在与否过滤序列。

示例查询(用 0 填充任一侧缺失序列):

method_code:http_errors:rate5m{status="500"} / ignoring(code) fill(0) method:http_requests:rate5m

返回各 method 状态码 500 请求占比。put 与 del 条目因在另一侧无匹配序列,现以填充默认值 0 纳入结果:

{method="get"}  0.04            #  24 / 600
{method="put"}  +Inf            #   3 /   0 (missing right side filled in)
{method="del"}  0               #   0 /  34 (missing left side filled in)
{method="post"} 0.05            #   6 / 120

引自:Operators


第 3 章 函数全表

引自:Query functions

本章按功能分类,完整收录官方文档中的全部查询函数(共 90 个,含实验性函数)。

3.1 通用约定

3.1.1 默认参数

有些函数带默认参数,例如 year(v=vector(time()) instant-vector):当唯一参数 v 未提供时,默认取表达式 vector(time()) 的值。

3.1.2 两类样本语义

  • float samples:普通浮点样本。
  • histogram samples:原生直方图(native histogram)样本。

3.1.3 处理 histogram 的三种措辞(最重要的横向规律)

大量函数对 histogram 样本的处理方式只有三种:

措辞 含义
ignored silently 静默忽略
omitted + warn-level annotation 整条从结果剔除并给 warn 级注解
仅用 float 部分 + info-level annotation 只取 float 样本并给 info 级注解

3.1.4 feature flag

标注 feature flag 的函数必须通过 --enable-feature=promql-experimental-functions 开启,属实验特性。

3.2 缺失检测类

3.2.1 absent()

项 内容
签名 absent(v instant-vector)
参数 v:instant vector
行为 若输入向量有任何元素(float 或 histogram 样本)返回空向量;若无任何元素,返回一个只含 1 的单元素向量
用途 对「某 metric + label 组合完全不存在时间序列」的场景做告警

它会尝试从输入向量智能推导输出标签:

absent(nonexistent{job="myjob"})
# => {job="myjob"}

absent(nonexistent{job="myjob",instance=~".*"})
# => {job="myjob"}

absent(sum(nonexistent{job="myjob"}))
# => {}

3.2.2 absent_over_time()

项 内容
签名 absent_over_time(v range-vector)
参数 v:range vector
行为 语义与 absent 相同,但作用在 range-vector 上——区间内有任何元素返回空,无元素返回单元素 1
用途 对「某组合在一段时间内都不存在序列」做告警
absent_over_time(nonexistent{job="myjob"}[1h])
# => {job="myjob"}

absent_over_time(nonexistent{job="myjob",instance=~".*"}[1h])
# => {job="myjob"}

absent_over_time(sum(nonexistent{job="myjob"})[1h:])
# => {}

同样会智能推导标签。

3.3 取整与数值钳制类

3.3.1 ceil()

  • 签名:ceil(v instant-vector)
  • 行为:把 float 样本向上取整到「≥ 原值的最小整数」;histogram 样本静默忽略。
  • 特例:ceil(+Inf)=+Inf、ceil(±0)=±0、ceil(1.49)=2.0、ceil(1.78)=2.0。

3.3.2 floor()

  • 签名:floor(v instant-vector)
  • 行为:向下取整到「≤ 原值的最大整数」;histogram 静默忽略。
  • 特例:floor(+Inf)=+Inf、floor(±0)=±0、floor(1.49)=1.0、floor(1.78)=1.0。

3.3.3 round()

  • 签名:round(v instant-vector, to_nearest=1 scalar)
  • 参数:to_nearest(可选,默认 1):指定「就近的倍数」,可以是小数(分数)。
  • 行为:把所有样本四舍五入到最近整数,平局向上取整;histogram 静默忽略。

3.3.4 clamp()

  • 签名:clamp(v instant-vector, min scalar, max scalar)
  • 行为:把 v 中 float 样本钳制到 [min, max];histogram 静默忽略。
  • 特例:
    • min > max 时返回空向量;
    • min 或 max 为 NaN 时返回 NaN;
    • min=-Inf 且 max=+Inf 时样本不变。

3.3.5 clamp_max()

  • 签名:clamp_max(v instant-vector, max scalar)
  • 行为:只设上限 max;histogram 静默忽略。
  • 特例:max=NaN 返回 NaN;max=+Inf 不变;max=-Inf 时所有 float 样本置为 -Inf。

3.3.6 clamp_min()

  • 签名:clamp_min(v instant-vector, min scalar)
  • 行为:只设下限 min;histogram 静默忽略。
  • 特例:min=NaN 返回 NaN;min=-Inf 不变;min=+Inf 时所有 float 样本置为 +Inf。

3.4 数学函数

函数 签名 行为 特例
exp exp(v instant-vector) 求所有 float 样本的指数函数;histogram 静默忽略 Exp(+Inf)=+Inf、Exp(NaN)=NaN
ln ln(v instant-vector) 自然对数;histogram 静默忽略 ln(+Inf)=+Inf、ln(0)=-Inf、ln(x<0)=NaN、ln(NaN)=NaN
log2 log2(v instant-vector) 二进制对数;histogram 静默忽略 与 ln 等价
log10 log10(v instant-vector) 十进制对数;histogram 静默忽略 与 ln 等价
sqrt sqrt(v instant-vector) 平方根;histogram 静默忽略 —
sgn sgn(v instant-vector) 取符号:正数→1,负数→-1,零→0;histogram 静默忽略 —
abs abs(v instant-vector) 取绝对值;输入中的 histogram 样本被静默忽略(明确写在 abs 描述里) —

3.5 时间与日期类

以下函数把 float 样本解释为时间戳(自 1970-01-01 UTC 起的秒数),全部以 UTC 计算,且都静默忽略 histogram 样本。

3.5.1 常用日期时间函数

函数 签名 返回值范围
day_of_month day_of_month(v=vector(time()) instant-vector) 当月第几天,1–31
day_of_week day_of_week(v=vector(time()) instant-vector) 星期几,0–6,0 表示周日
day_of_year day_of_year(v=vector(time()) instant-vector) 当年第几天,平年 1–365、闰年 1–366
days_in_month days_in_month(v=vector(time()) instant-vector) 当月天数,28–31
hour hour(v=vector(time()) instant-vector) 小时,0–23
minute minute(v=vector(time()) instant-vector) 分钟,0–59
month month(v=vector(time()) instant-vector) 月份,1–12,1 表示一月
year year(v=vector(time()) instant-vector) 年份(UTC)

3.5.2 当前时间与样本时间戳

time()

  • 返回自 1970-01-01 UTC 起的秒数。
  • 关键注意事项:返回的不是真实当前时间,而是该表达式被求值的时刻。

timestamp(v instant-vector)

  • 返回给定向量中每个样本的时间戳(秒,UTC);对 float 与 histogram 样本行为一致。

start_timestamp(v instant-vector)

  • 返回给定向量每个样本的起始时间戳(秒,UTC),对 float 与 histogram 行为一致。
  • 限制:只有直接作用于 instant vector 且启用 use-start-timestamps feature flag 时才有效;若作用于表达式或该 flag 未开启,返回空结果。

3.5.3 实验性:查询区间信息与标量比较

以下函数均需 feature flag --enable-feature=promql-experimental-functions:

函数 签名 行为
start start() 返回当前查询区间求值的起始时间戳(秒,UTC)。instant query 时等于求值时间戳
end end() 返回当前查询区间求值的结束时间戳(秒,UTC)。instant query 时等于求值时间戳
step step() 返回查询分辨率步长(秒)。instant query 返回 0
range range() 返回当前查询区间时长(秒),等价于 end() - start();instant query 返回 0
max_of max_of(a scalar, b scalar) 返回两个标量中较大者
min_of min_of(a scalar, b scalar) 返回两个标量中较小者

3.6 范围向量(趋势/变化/速率)类

3.6.1 函数总览

函数 签名 适用类型 样本支持
delta delta(v range-vector) gauge(float 与 histogram 皆然) float + histogram
deriv deriv(v range-vector) gauge 仅 float
predict_linear predict_linear(v range-vector, t scalar) gauge 仅 float
double_exponential_smoothing double_exponential_smoothing(v range-vector, sf scalar, tf scalar) gauge(实验性) 仅 float
rate rate(v range-vector) counter(float 与 histogram) float + histogram
irate irate(v range-vector) counter float + histogram
increase increase(v range-vector) counter float + histogram
changes changes(v range-vector) 通用 float + histogram
resets resets(v range-vector) counter float + histogram
idelta idelta(v range-vector) gauge(float 与 histogram 皆然) float + histogram

3.6.2 delta()

  • 计算区间内首末样本值之差,返回带等价标签的 instant vector。
  • 差值会外推到整个区间,因此即使样本值全为整数也可能得到非整数结果。
  • 示例:delta(cpu_temp_celsius{host="zeus"}[2h]) 返回「现在与 2 小时前」的 CPU 温度差。
  • 对 histogram 的处理:计算一个新的 histogram,其每个分量(观测 sum、count、buckets)为首末原生直方图对应分量之差;区间内混有 float 与 histogram 样本的元素会被剔除并打 warn 级注解。
  • 仅应用于 gauge(float 与 histogram 皆然)。

3.6.3 deriv()

  • 用简单线性回归计算每个 float 时间序列的每秒导数。
  • 区间至少需 2 个 float 样本;区间内出现 +Inf/-Inf 时斜率与截距都为 NaN。
  • 仅用于 gauge,且只支持 float:只含 histogram 的元素被完全忽略;混含的元素只取 float 输入并打 info 级注解。

3.6.4 predict_linear()

  • 基于区间 v 用简单线性回归预测从此刻起 t 秒后的值。
  • 区间至少需 2 个 float 样本;含 ±Inf 时预测值为 NaN。
  • 仅用于 gauge,只支持 float;处理规则同 deriv(纯 histogram 元素忽略,混含只取 float 并打 info 注解)。

3.6.5 double_exponential_smoothing()(实验性)

  • 签名:double_exponential_smoothing(v range-vector, sf scalar, tf scalar)
  • 对区间内每个 float 时间序列产生平滑值。
  • sf(平滑因子)越小,越看重旧数据;tf(趋势因子)越大,越多考虑趋势。sf 与 tf 都必须在 0–1 之间。
  • Prometheus V2 中此函数名为 holt_winters,官方说明改名原因:Holt-Winters 通常指三次指数平滑,而此处实现的是二次("Holt Linear"),原名易致混淆。
  • 仅用于 gauge,只支持 float;纯 histogram 元素完全忽略,混含只取 float 并打 info 注解。

3.6.6 rate()

  • 计算区间内时间序列的每秒平均增长率。
  • 自动处理单调性中断(如 target 重启导致的 counter reset);并外推到区间两端,以容忍漏抓取或抓取周期与区间未对齐。
  • 示例:rate(http_requests_total{job="api-server"}[5m])。
  • 对原生直方图:生成新直方图,各分量(sum、count、buckets)为首末原生直方图对应分量的增长率;区间内混含 float 与原生直方图样本的元素被剔除并打 warn 注解。
  • 仅用于 counter(float 与 histogram 皆然),最适合告警与缓慢变化 counter 的绘图。
  • 重要:与聚合算子(如 sum())或任何以 _over_time 结尾的聚合函数组合时,必须先用 rate() 再聚合,否则 target 重启时无法检测 counter reset。

3.6.7 irate()

  • 基于最后两个数据点计算每秒瞬时增长率,自动处理单调性中断。
  • 最后两个样本必须同为 float 或同为 histogram,否则该元素被剔除并打 warn 注解。
  • 仅用于 counter(float 与 histogram)。示例:irate(http_requests_total{job="api-server"}[5m])。
  • 仅建议用于绘图「易变、快速变化」的 counter;告警与缓慢 counter 用 rate,因为速率短暂变化会重置 FOR 子句,且全为孤立尖峰的图难以阅读。
  • 同样:与聚合算子或 _over_time 组合时必须先 irate() 后聚合,否则无法在 target 重启时识别 counter reset。

3.6.8 increase()

  • 计算区间内时间序列的增量,自动修正单调性中断,并外推到整个区间(因此即使 counter 仅按整数增长也可能得到非整数结果)。
  • 示例:increase(http_requests_total{job="api-server"}[5m])。
  • 对 histogram:生成新直方图,各分量为首末原生直方图对应分量的增量;混含 float 与 histogram 的元素被剔除并打 warn 注解。
  • 仅用于 counter(float 与 histogram)。
  • 它本质是 rate(v) 乘以区间秒数的语法糖,主要用于人类可读性;在 recording rules 中应使用 rate,以便按秒一致地追踪增量。

3.6.9 changes()

  • 对每个输入时间序列,返回区间内值发生变化的次数(instant vector)。
  • float 样本后跟 histogram 样本(或反之)计作一次变化;counter histogram 后跟一个数值完全相同的 gauge histogram(或反之)不计为变化。

3.6.10 resets()

  • 对每个序列返回区间内 counter reset 次数。
  • float 上任何相邻两点间的下降都算一次 reset。
  • 原生直方图的 reset 判定更复杂:任一 bucket(含 zero bucket)或观测计数的下降算 reset;此前有值的 bucket 消失、zero-bucket 宽度减小、以及任何非「兼容的降分辨率」的 schema 变更也都算 reset。
  • 仅用于 counter(float 与 histogram)。
  • float 与 histogram 相邻互计为 reset;counter histogram 与 gauge histogram 相邻也计为 reset(但注意 resets 本就不该用于 gauge)。

3.6.11 idelta()

  • 计算区间 v 中最后两个样本之差,返回 instant vector。
  • 两个样本必须同为 float 或同为 histogram;若最后两个一为 float 一为 histogram,则该元素被剔除并打 warn 注解。
  • 仅用于 gauge(float 与 histogram 皆然)。

3.7 直方图专用函数

函数 签名 说明
histogram_avg histogram_avg(v instant-vector) 原生直方图观测值的算术平均
histogram_count histogram_count(v instant-vector) 原生直方图储存的观测计数
histogram_sum histogram_sum(v instant-vector) 原生直方图观测值之和
histogram_fraction histogram_fraction(lower scalar, upper scalar, b instant-vector) 区间内观测的估算占比
histogram_quantile histogram_quantile(φ scalar, b instant-vector) φ-分位数
histogram_quantiles histogram_quantiles(v instant-vector, quantile_label string, φ_1, φ_2, ...) 一次算多个分位数(实验性)
histogram_stddev histogram_stddev(v instant-vector) 估计标准差
histogram_stdvar histogram_stdvar(v instant-vector) 估计方差

3.7.1 histogram_avg()

返回 v 中每个原生直方图样本观测值的算术平均;float 样本被忽略、不出现在结果中。

histogram_avg(rate(http_request_duration_seconds[5m]))

等价于 histogram_sum(rate(...)) / histogram_count(rate(...))。

3.7.2 histogram_count() 与 histogram_sum()

  • histogram_count(v instant-vector):返回每个原生直方图样本中储存的观测计数;float 样本被忽略。
  • histogram_sum(v instant-vector):返回每个原生直方图样本中观测值之和;float 样本被忽略。
histogram_count(rate(http_request_duration_seconds[10m]))   # 每秒请求数

3.7.3 histogram_fraction()

  • 返回 b 中每个经典或原生直方图在 [lower, upper] 之间观测值的估算占比。
  • b 中的 float 样本被视为「一个或多个经典直方图各 bucket 的计数」,而原生直方图样本各自独立当作一个直方图处理,逻辑与 histogram_quantile() 相同。
  • 若给定边界不与 bucket 边界重合,结果为估算值,使用与 histogram_quantile() 相同的插值法;经典直方图下极易选到远离任何 bucket 边界的上下界,导致误差很大,此时官方建议直接对 bucket 序列运算(参考 Apdex 计算)。
  • 示例:histogram_fraction(0, 0.2, rate(http_request_duration_seconds[1h])) 表示过去一小时耗时 ≤200ms 的请求占比。
  • +Inf/-Inf 是合法边界(若要含所有 ≤0.2 的观测含负值,下界应用 -Inf 而非 0)。
  • 边界开闭仅在恰好对齐 bucket 边界时才有意义,此时行为取决于直方图 schema 定义(标准指数 schema 对正值是「上界含、下界不含」,负值相反);未对齐时用插值,开闭无关紧要。
  • 原生标准指数桶特例:NaN 观测被视为落在所有 bucket 之外,histogram_fraction(-Inf, +Inf, b) 实际返回非 NaN 观测占比,可能小于 1。

3.7.4 histogram_quantile()

从经典直方图或原生直方图计算 φ-分位数(0 ≤ φ ≤ 1)。

输入解释:

  • b 的 float 样本被视为「一个或多个经典直方图各 bucket 的计数」,每个 float 样本必须带 le 标签表示该 bucket 的含上界;不带此标签的 float 样本被静默忽略;其余标签与 metric 名用于识别各 bucket 归属哪个经典直方图(histogram 类型自动生成带 _bucket 后缀的时间序列)。
  • b 中的原生直方图样本各自独立计算分位数。
  • 只要不产生命名冲突,b 可混含经典与原生直方图。
  • 用 rate() 指定时间窗口。

示例:

# 经典直方图
histogram_quantile(0.9, rate(http_request_duration_seconds_bucket[10m]))

# 原生直方图
histogram_quantile(0.9, rate(http_request_duration_seconds[10m]))

# 聚合(经典,需把 le 放进 by)
histogram_quantile(0.9, sum by (job, le) (rate(http_request_duration_seconds_bucket[10m])))

# 聚合(原生,简化为 sum by (job))
histogram_quantile(0.9, sum by (job) (rate(http_request_duration_seconds[10m])))

# 经典全聚合需只保留 le
histogram_quantile(0.9, sum by (le) (rate(http_request_duration_seconds_bucket[10m])))

# 原生全聚合无需 by
histogram_quantile(0.9, sum(rate(http_request_duration_seconds[10m])))

插值方式:

  • 经典直方图、原生自定义边界直方图、以及原生的 zero bucket 使用线性插值(假设桶内均匀分布);
  • 原生标准指数 schema 的非零桶使用指数插值(假设样本在更高分辨率的假设直方图中均匀填充各桶)。

返回值特例:

条件 返回
b 有 0 个观测 NaN
φ < 0 -Inf
φ > 1 +Inf
φ = NaN NaN

经典直方图特例:

  • bucket 少于 2 个返回 NaN;
  • 最高 bucket 上界必须是 +Inf(否则返回 NaN);
  • 分位数落在最高桶时返回次高桶上界;
  • 最低桶上界 > 0 时假定其下界为 0 并做线性插值,否则(上界 ≤ 0)落在最低桶的分位数直接返回该桶上界。

原生直方图特例:

  • 标准指数桶含 NaN 观测且分位数落在已有指数桶内时,因 NaN 被当作 +Inf,结果会偏高,打 info 注解;
  • 若分位数高于所有已有指数桶则返回 NaN,也打 info 注解;
  • 有限宽 zero bucket 在「有正桶观测但无负桶观测」时被假定不含负观测,反之亦然。

极值估计:

  • histogram_quantile(0, v) 可得估计最小值;
  • histogram_quantile(1, v) 可得估计最大值。

累积性假设与修正(经典直方图):

  • bucket 计数应单调不减,相邻两桶上界之间无观测时两桶计数应相等。
  • 浮点精度问题(如 sum(rate(...)) 引入的小偏差)或非法数据会违反该假设导致结果无意义。
  • 缓解措施:把相邻桶的极小相对差异(阈值为两桶之和的万亿分之一,1e-12)视为浮点误差而忽略;若调整后仍非单调,则把计数抬升到前一桶的值以强制单调。
  • 此情形会打 info 级注解 input to histogram_quantile needed to be fixed for monotonicity,遇到该注解应找出并移除非法数据源。

3.7.5 histogram_quantiles()(实验性)

  • 签名:histogram_quantiles(v instant-vector, quantile_label string, φ_1 scalar, φ_2 scalar, ...)
  • 从经典或原生直方图一次性计算多个(1 到 10 个) φ-分位数,计算方式与 histogram_quantile() 相同。
  • 第二个字符串参数指定用于在结果中区分不同分位数的标签名。
histogram_quantiles(sum(rate(foo[1m])), "quantile", 0.9, 0.99)
# => {quantile="0.9"} 123
#    {quantile="0.99"} 128

3.7.6 histogram_stddev() 与 histogram_stdvar()

  • histogram_stddev(v instant-vector):返回每个原生直方图样本观测值的估计标准差。估计时假定每个桶内所有观测都取该桶边界的均值:zero bucket 与自定义边界桶用算术平均,标准指数桶用几何平均。float 样本被忽略。
  • histogram_stdvar(v instant-vector):返回每个原生直方图样本观测值的估计方差,其余同 histogram_stddev。

3.8 标签操作类

3.8.1 label_join()

  • 签名:label_join(v instant-vector, dst_label string, separator string, src_label_1 string, src_label_2 string, ...)
  • 对 v 中每个时间序列,用 separator 拼接所有 src_labels 的值,返回把这些值写入 dst_label 后的序列。src_labels 数量不限。
  • 对 float 与 histogram 样本行为一致。
label_join(up{job="api-server",src1="a",src2="b",src3="c"}, "foo", ",", "src1", "src2", "src3")
# 给每条序列加上 foo="a,b,c"

3.8.2 label_replace()

  • 签名:label_replace(v instant-vector, dst_label string, replacement string, src_label string, regex string)
  • 用 regex 匹配 src_label 的值,匹配成功则把 dst_label 设为 replacement 的展开结果(保留原有标签);反向引用可写 $1、$2…,命名捕获组可写 $name;正则不匹配则序列原样返回。
  • 对 float 与 histogram 行为一致。
label_replace(up{job="api-server",service="a:c"}, "foo", "$1", "service", "(.*):.*")
# 返回 service="a:c"、foo="a"

# 等价写法:命名组
label_replace(up{job="api-server",service="a:c"}, "foo", "$name", "service", "(?P<name>.*):(?P<version>.*)")

3.8.3 info()(实验性)

文档明确警告:未来版本行为可能变化,甚至从 PromQL 移除。须 --enable-feature=promql-experimental-functions 启用。

  • 签名:info(v instant-vector, [data-label-selector instant-vector])
  • 为 v 中每条序列找到所有「identifying 标签匹配」的 info 序列,并把它们的 data(非 identifying)标签做并集加到该序列上。
  • 第二参数可选,不是真正的 instant vector,只用其语法子集,必须以 { ... } 起止且只能包含标签匹配器,用于约束「考虑哪些 info 序列」与「加入哪些 data 标签」。
  • 若某时刻找不到匹配 info 序列(如 info 序列已 stale):
    • 若 data-label-selector 含任何不匹配空串的匹配器(如 {data=~".+"}),该序列在该时间戳被丢弃(所需增强不可得);
    • 若所有匹配器都匹配空串(如 {data=~".*"})或未提供第二参数,则序列在无增强的情况下被返回。

概念说明:info 序列的 identifying 标签是唯一标识该序列的标签子集,其余为 data 标签。Prometheus 的时间序列身份概念始终包含全部标签,而 info 函数在「逻辑上」另定义了一套 info 序列身份。identifying 标签用于与普通(非 info)序列 join;data 标签承载元数据键值对。这意味着传统视角下 data 标签变化 = 一条 info 序列结束、另一条开始,而 info 的逻辑视角视为同一 info 序列延续、只是 data 不同。

对比传统 join 写法:

rate(http_server_request_duration_seconds_count[2m])
* on (job, instance) group_left (k8s_cluster_name)
target_info

冗长且不直观,还可能有「身份危机」——若旧 target_info 未正确标记为 stale,会在最多 5m(lookback delta)内报错,因为同时匹配到新旧两版。

用 info 简化:

info(rate(http_server_request_duration_seconds_count[2m]), {k8s_cluster_name=~".+"})

省略第二参数即加全部 data 标签:

info(rate(http_server_request_duration_seconds_count[2m]))

可用 __name__ 匹配器限定 info 序列,如 {__name__="target_info"}。

注意:若 v 中某些序列本身匹配 data-label-selector(或未指定时的默认 target_info),它们会被当作 info 序列并原样返回。

Limitations:

  • 当前版本 info 默认只考虑名为 target_info 的 info 序列,并假定 identifying 标签为 instance 与 job。
  • 通过 __name__ 匹配器可支持其他 info 序列名,如 {__name__=~"(target|build)_info"} 同时考虑两者,但 identifying 标签必须始终是 instance 和 job。
  • 当只提供否定式 __name__ 匹配器(如 {__name__!="target_info"})时,info 会先考虑所有匹配 .+_info 的 metric 再做否定过滤,因为单靠否定匹配器无法正向确定要纳入哪些 info metric。
  • identifying 标签的存在性是按输入序列逐条判定的:只含 job、只含 instance、或两者都有的输入都能从对应 info 序列组获得 data 标签;缺失的 identifying 标签不会被当作通配符。
  • 文档承认这些限制部分削弱了 info 的初衷,当前仍是实验,最终版本会考虑所有匹配的 info 序列及其恰当的 identifying 标签。

3.9 排序与向量构造类

3.9.1 sort() 与 sort_desc()

  • sort(v instant-vector):按 float 样本值升序排序;histogram 静默忽略。
  • sort_desc(v instant-vector):同 sort,但降序。
  • 注意:sort 只影响 instant query 的结果,range query 结果始终有固定输出顺序。

3.9.2 sort_by_label() 与 sort_by_label_desc()(实验性)

  • sort_by_label(v instant-vector, label string, ...):按给定标签值升序排序;标签值相等时按完整标签集排序。对 float 与 histogram 行为一致。
  • sort_by_label_desc(v instant-vector, label string, ...):同 sort_by_label,但降序。
  • 只影响 instant query 结果(同 sort)。使用自然排序(natural sort order)。

3.9.3 scalar() 与 vector()

  • scalar(v instant-vector):若输入向量恰好只有一个 float 样本元素,返回其样本值作为 scalar;否则返回 NaN。histogram 样本被静默忽略。
  • vector(s scalar):把标量 s 转为一个 float 样本,返回无标签的单元素 instant vector。

3.10 over_time 聚合系列

对给定 range vector 的每条序列做区间聚合,返回带「逐序列聚合结果」的 instant vector。

3.10.1 标准函数

函数 签名 说明
avg_over_time avg_over_time(range-vector) 区间内所有 float 或 histogram 样本的平均值
min_over_time min_over_time(range-vector) 区间内所有 float 样本的最小值
max_over_time max_over_time(range-vector) 区间内所有 float 样本的最大值
sum_over_time sum_over_time(range-vector) 区间内所有 float 或 histogram 样本之和
count_over_time count_over_time(range-vector) 区间内所有样本的计数
quantile_over_time quantile_over_time(scalar, range-vector) 区间内所有 float 样本的 φ-分位数(0 ≤ φ ≤ 1)
stddev_over_time stddev_over_time(range-vector) 区间内所有 float 样本的总体标准差
stdvar_over_time stdvar_over_time(range-vector) 区间内所有 float 样本的总体方差
last_over_time last_over_time(range-vector) 区间内最新样本
first_over_time first_over_time(range-vector) 区间内最旧样本
present_over_time present_over_time(range-vector) 区间内任何序列都返回值 1

3.10.2 实验性附加函数(需 feature flag)

函数 签名 说明
mad_over_time mad_over_time(range-vector) 区间内所有 float 样本的中位数绝对偏差
ts_of_min_over_time ts_of_min_over_time(range-vector) 区间内取到最小值的那(最后)个 float 样本的时间戳
ts_of_max_over_time ts_of_max_over_time(range-vector) 区间内取到最大值的那(最后)个 float 样本的时间戳
ts_of_last_over_time ts_of_last_over_time(range-vector) 区间内最后一个样本的时间戳
ts_of_first_over_time ts_of_first_over_time(range-vector) 区间内最早一个样本的时间戳

3.10.3 权重与 histogram 处理

权重说明:区间内所有值在聚合中权重相同,即使它们在区间内分布不均。

对 histogram 的处理:

  • count_over_time、first_over_time、last_over_time、present_over_time() 对 float 与 histogram 样本行为一致。
  • avg_over_time() 与 sum_over_time() 对 histogram 样本的处理等同于对应的聚合算子;若某序列区间内混含 float 与 histogram 样本,该结果会被整体移除并打 warn 级注解。
  • 其余函数忽略 histogram 的方式为:只含 histogram 的区间被静默移除;混含 float 与 histogram 的区间只处理 float 样本,忽略 histogram 的部分打 info 级注解。

补充对比:first_over_time(m[1m]) 与 m offset 1m 不同——前者选取 1m 区间之内的第一个样本,而 m offset 1m 选取的是 lookback 区间内、位于 1m 偏移之外且之前的最近样本。这在 range query 中用 first_over_time(m[step()]) 可确保所选样本落在区间步长之内。

3.11 三角函数

三角函数以弧度为单位,且忽略输入向量中的 histogram 样本。

3.11.1 反三角与双曲函数

函数 签名 对应 Go
acos acos(v instant-vector) 反余弦(math#Acos)
acosh acosh(v instant-vector) 反双曲余弦(math#Acosh)
asin asin(v instant-vector) 反正弦(math#Asin)
asinh asinh(v instant-vector) 反双曲正弦(math#Asinh)
atan atan(v instant-vector) 反正切(math#Atan)
atanh atanh(v instant-vector) 反双曲正切(math#Atanh)
cos cos(v instant-vector) 余弦(math#Cos)
cosh cosh(v instant-vector) 双曲余弦(math#Cosh)
sin sin(v instant-vector) 正弦(math#Sin)
sinh sinh(v instant-vector) 双曲正弦(math#Sinh)
tan tan(v instant-vector) 正切(math#Tan)
tanh tanh(v instant-vector) 双曲正切(math#Tanh)

3.11.2 角度/弧度转换

函数 签名 说明
deg deg(v instant-vector) 弧度 → 角度
pi pi() 返回 pi
rad rad(v instant-vector) 角度 → 弧度

3.12 函数速查总表

下表按字母序汇总全部 90 个函数及其分类与实验性标记。

# 函数 分类 实验性 备注
1 abs 数学 histogram 静默忽略
2 absent 缺失检测
3 absent_over_time 缺失检测
4 acos 三角函数
5 acosh 三角函数
6 asin 三角函数
7 asinh 三角函数
8 atan 三角函数
9 atanh 三角函数
10 avg_over_time over_time 支持 histogram
11 ceil 取整/钳制
12 changes 范围向量 支持 histogram
13 clamp 取整/钳制
14 clamp_max 取整/钳制
15 clamp_min 取整/钳制
16 cos 三角函数
17 cosh 三角函数
18 count_over_time over_time 支持 histogram
19 day_of_month 时间/日期
20 day_of_week 时间/日期 0 = 周日
21 day_of_year 时间/日期
22 days_in_month 时间/日期
23 deg 三角函数
24 delta 范围向量 gauge;支持 histogram
25 deriv 范围向量 gauge;仅 float
26 double_exponential_smoothing 范围向量 ✅ 原 holt_winters
27 end 时间/日期 ✅
28 exp 数学
29 first_over_time over_time 支持 histogram
30 floor 取整/钳制
31 histogram_avg 直方图
32 histogram_count 直方图
33 histogram_fraction 直方图
34 histogram_quantile 直方图
35 histogram_quantiles 直方图 ✅
36 histogram_stddev 直方图
37 histogram_stdvar 直方图
38 histogram_sum 直方图
39 hour 时间/日期
40 idelta 范围向量 gauge;支持 histogram
41 increase 范围向量 counter;支持 histogram
42 info 标签操作 ✅ 可能被移除
43 irate 范围向量 counter;支持 histogram
44 label_join 标签操作
45 label_replace 标签操作
46 last_over_time over_time 支持 histogram
47 ln 数学
48 log10 数学
49 log2 数学
50 mad_over_time over_time ✅
51 max_of 时间/日期 ✅
52 max_over_time over_time 仅 float
53 min_of 时间/日期 ✅
54 min_over_time over_time 仅 float
55 minute 时间/日期
56 month 时间/日期 1 = 一月
57 pi 三角函数
58 predict_linear 范围向量 gauge;仅 float
59 present_over_time over_time 支持 histogram
60 quantile_over_time over_time 仅 float
61 rad 三角函数
62 range 时间/日期 ✅
63 rate 范围向量 counter;支持 histogram
64 resets 范围向量 counter;支持 histogram
65 round 取整/钳制
66 scalar 排序/构造
67 sgn 数学
68 sin 三角函数
69 sinh 三角函数
70 sort 排序/构造
71 sort_by_label 排序/构造 ✅
72 sort_by_label_desc 排序/构造 ✅
73 sort_desc 排序/构造
74 sqrt 数学
75 start 时间/日期 ✅
76 start_timestamp 时间/日期 需 use-start-timestamps
77 stddev_over_time over_time 仅 float
78 stdvar_over_time over_time 仅 float
79 step 时间/日期 ✅
80 sum_over_time over_time 支持 histogram
81 tan 三角函数
82 tanh 三角函数
83 time 时间/日期
84 timestamp 时间/日期 支持 histogram
85 ts_of_first_over_time over_time ✅
86 ts_of_last_over_time over_time ✅
87 ts_of_max_over_time over_time ✅
88 ts_of_min_over_time over_time ✅
89 vector 排序/构造
90 year 时间/日期

统计:共 90 个函数。其中需 --enable-feature=promql-experimental-functions 开启的实验性函数共 16 个:double_exponential_smoothing、end、histogram_quantiles、info、mad_over_time、max_of、min_of、range、sort_by_label、sort_by_label_desc、start、step、ts_of_first_over_time、ts_of_last_over_time、ts_of_max_over_time、ts_of_min_over_time。另有 start_timestamp 依赖 use-start-timestamps 特性开关,info/histogram_quantiles 的未来版本可能发生不兼容变化。

引自:Query functions


第 4 章 查询示例集

引自:Query examples

本章完整收录官方 examples 页面的全部场景,每条示例配解释。

4.1 简单时序选择

4.1.1 按指标名选择

http_requests_total

返回所有 metric 为 http_requests_total 的时间序列。

💡 补充:这是一条裸 metric name selector。在生产环境中它可能展开为数千条不同标签的时间序列——这正是 1.10 节强调「先在表格视图构建查询」的典型场景。

4.1.2 按多个标签过滤

http_requests_total{job="apiserver", handler="/api/comments"}

返回带给定 job 与 handler 标签的所有 http_requests_total 时间序列。

4.1.3 取一段时间范围(range vector)

http_requests_total{job="apiserver", handler="/api/comments"}[5m]

为同一向量返回一整段时间范围(此处为截至查询时间的 5 分钟),使其成为 range vector。

注意:结果为 range vector 的表达式不能直接绘图,需在 expression browser 的表格("Console")视图中查看。

4.1.4 正则匹配 job

http_requests_total{job=~".*server"}

用正则表达式仅选择 name 匹配某模式的 jobs(此处为所有以 server 结尾的 jobs)。

4.1.5 反向正则排除状态码

http_requests_total{status!~"4.."}

选择除 4xx 外的所有 HTTP 状态码。

4.2 子查询示例

4.2.1 5 分钟 rate 的 30 分钟序列

rate(http_requests_total[5m])[30m:1m]

返回 http_requests_total 过去 30 分钟的 5-minute rate,分辨率 1 分钟。

4.2.2 嵌套子查询

max_over_time(deriv(rate(distance_covered_total[5s])[30s:5s])[10m:])

嵌套 subquery 示例。deriv 函数的 subquery 使用默认 resolution。注意不必要地使用 subqueries 是不明智的。

引自:Query examples

4.3 函数与运算符实战

4.3.1 每秒请求速率

rate(http_requests_total[5m])

返回所有 http_requests_total 时间序列在过去 5 分钟测得的每秒速率。

4.3.2 按 job 聚合减少序列数

假设所有 http_requests_total 时间序列都有 job(按 job 名 fanout)与 instance(按 job 实例 fanout)标签,可对全部实例的 rate 求和以减少输出序列数但保留 job 维度:

sum by (job) (
  rate(http_requests_total[5m])
)

4.3.3 二元运算:未使用内存

若有两个具相同维度标签的不同指标,可对其施加二元运算符,两侧标签集相同的元素会匹配并传播到输出。例如返回(虚构 cluster scheduler 暴露的指标下)每个实例的未使用内存(MiB):

(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024

同一表达式按 application 求和可写为:

sum by (app, proc) (
  instance_memory_limit_bytes - instance_memory_usage_bytes
) / 1024 / 1024

4.3.4 topk:按应用与进程类型取 CPU 使用 top 3

给定如下形式的每实例 CPU 使用指标(示例含 app 为 lion/elephant/turtle/fox,proc 为 web/worker/api/widget,另有 rev、env、job="cluster-manager" 标签):

topk(3, sum by (app, proc) (rate(instance_cpu_time_ns[5m])))

可按 application(app)与 process type(proc)分组取 CPU 使用 top 3。

4.3.5 count:统计运行实例数

假设该指标每个运行实例一条时间序列,可按 application 统计运行实例数:

count by (app) (instance_cpu_time_ns)

4.3.6 limitk:探查指标的标签

若为探查某指标以获得其标签(例如便于随后对其中一些聚合),可使用:

limitk(10, app_foo_metric_bar)

4.3.7 limit_ratio:均匀采样约 10%

若希望返回的时间序列采样更均匀,可用以下方式获取约 10%:

limit_ratio(0.1, app_foo_metric_bar)

💡 补充:limitk 与 limit_ratio 均为实验性聚合运算符,须 --enable-feature=promql-experimental-functions 启用(见 2.8 节)。二者都以确定性伪随机方式选取子集,与样本类型无关。

引自:Query examples

4.3.8 查询章节索引页说明

官方 querying/index.md(https://prometheus.io/docs/prometheus/latest/querying/)为查询章节的索引/落地页,仅有 frontmatter(title: Querying、sort_rank: 4),本身不承载内容要点,具体内容分布在其子页面(basics、examples、operators、functions 等)中。

💡 补充:本页 URL 与同目录 examples.md 的 sort_rank 相同(均为 4),存在 sort_rank 重复(属官方文档细节,不影响内容)。


第 5 章 HTTP API

引自:HTTP API

当前稳定 HTTP API 挂在 Prometheus 服务器的 /api/v1,非破坏性新增都加在该前缀下。

5.1 通用格式与响应信封

5.1.1 OpenAPI 规范

GET /api/v1/openapi.yaml
  • 机器可读规范,默认返回 OpenAPI 3.1;加 ?openapi_version=3.2 返回 OpenAPI 3.2(含 /api/v1/notifications/live 等端点)。
  • 可用于生成客户端、校验请求/响应、生成交互式文档。

5.1.2 响应信封与状态码

响应体为 JSON,成功一律 2xx。

状态码 含义
400 Bad Request 参数缺失/错误
422 Unprocessable Entity 表达式无法执行(RFC4918)
503 Service Unavailable 查询超时/中止

端点之前发生的错误可能返回其他非 2xx。

信封字段:

字段 说明
status "success" 或 "error"
data 数据体
errorType 仅出错时含
error 仅出错时含
warnings 可选,字符串数组,不影响执行
infos 可选,info 级注解

出错时 data 仍可能含已成功收集的数据。

5.1.3 占位符与参数约定

占位符 说明
<rfc3339 | unix_timestamp> 输入支持 RFC3339 或 Unix 秒(可带小数);输出时间戳始终为 Unix 秒
<series_selector> 需 URL 编码,如 http_requests_total{method=~"(GET|POST)"}
<duration> 如 5m
<bool> true / false

时间格式说明:输入时间既可用 RFC3339(如 2015-07-01T20:10:51.781Z)也可用 Unix 时间戳(秒,可带小数);输出时间戳始终为 Unix 秒。可重复的查询参数名以 [] 结尾。

5.2 表达式查询端点

5.2.1 瞬时查询

GET  /api/v1/query
POST /api/v1/query
参数 类型 说明
query string 必填,PromQL 表达式
time <rfc3339 | unix_timestamp> 可选,缺省用服务器当前时间
timeout <duration> 可选,默认且受 -query.timeout 上限约束
limit number 可选,最大返回序列数,0 表示禁用,不影响 scalar/string,仅截断 matrix/vector
lookback_delta <duration|float> 可选,覆盖 lookback 期
stats string 可选,true 基础统计、all 含逐步统计;其他非空值已废弃,会加 warning 并在下个大版本拒绝
  • POST 时用 Content-Type: application/x-www-form-urlencoded 把参数放请求体,规避 URL 长度限制。
  • data 结构:{"resultType": "matrix"|"vector"|"scalar"|"string", "result": <value>}。

示例:

curl 'http://localhost:9090/api/v1/query?query=up&time=2015-07-01T20:10:51.781Z'

返回 vector,元素为 {"metric": {...}, "value": [1435781451.781, "1"]}。

5.2.2 范围查询

GET  /api/v1/query_range
POST /api/v1/query_range
参数 类型 说明
query string 必填
start <rfc3339 | unix_timestamp> 必填,含
end <rfc3339 | unix_timestamp> 必填,含
step <duration | float> 分辨率步长,两种格式均可
timeout <duration> 语义同瞬时查询
limit number 语义同瞬时查询
lookback_delta <duration|float> 语义同瞬时查询
stats string 语义同瞬时查询

data 的 resultType 恒为 matrix。

示例:

curl 'http://localhost:9090/api/v1/query_range?query=up&start=2015-07-01T20:10:30.781Z&end=2015-07-01T20:11:00.781Z&step=15s'

结果元素含 values: [[<unix_time>, "<sample_value>"], ...]。

5.2.3 查询统计(stats)

stats 被设置时,data 内附 stats 对象:

字段 说明
timings 各阶段耗时秒,如 evalTotalTime、execQueueTime
samples.totalQueryableSamples 载入样本总数,范围向量函数每步计入完整窗口
samples.totalQueryableSamplesPerStep 仅 stats=all 且启用逐步统计
samples.samplesRead 读取/I/O 样本数,范围查询的范围向量函数仅计每步新增点,其他查询等于 totalQueryableSamples
samples.samplesReadPerStep 逐步读取数
samples.peakSamples 内存峰值

另暴露指标 prometheus_engine_query_samples_total、prometheus_engine_query_samples_read_total;逐步统计受 promql-per-step-stats feature flag 控制。

5.2.4 格式化表达式

GET  /api/v1/format_query
POST /api/v1/format_query
  • 参数仅 query=<string>。
  • data 为格式化后的字符串,注释会被移除。

示例:query=foo/bar → "foo / bar"。

5.2.5 解析表达式为 AST(实验性)

GET  /api/v1/parse_query
POST /api/v1/parse_query
  • 参数 query。
  • 端点名与返回结构可能随版本变化,仅供 Prometheus 自带 Web UI 使用。
  • data 为 AST 字符串(示例给出 binaryExpr/vectorSelector/matchers 等字段)。

5.2.6 表达式查询结果格式

<sample_value> 为数值;因 JSON 不支持 NaN/Inf/-Inf,样本值以带引号字符串传输。histogram/histograms 键仅在存在原生直方图时出现。

Range vectors(matrix):

[
  {
    "metric": {},
    "values": [[<unix_time>, "<sample_value>"], ...],
    "histograms": [[<unix_time>, <histogram>], ...]
  }
]
  • 每条序列可有 values、histograms 或两者;同一时间戳只会有一个 float 或 histogram 样本。
  • 序列按 metric 排序,sort/sort_by_label 对范围向量无效。

Instant vectors(vector):

[
  {
    "metric": {},
    "value": [<unix_time>, "<sample_value>"],
    "histogram": [<unix_time>, <histogram>]
  }
]
  • value 与 histogram 二者不同时出现。无函数时顺序不保证。

Scalars(scalar):[ <unix_time>, "<scalar_value>" ] Strings(string):[ <unix_time>, "<string_value>" ]

Native histograms 的 <histogram>:

{
  "count": "<count_of_observations>",
  "sum": "<sum_of_observations>",
  "buckets": [[<boundary_rule>, "<left_boundary>", "<right_boundary>", "<count_in_bucket>"], ...]
}

boundary_rule 取 0–3:

值 含义
0 open left
1 open right
2 open both
3 closed both

当前实现中正桶为 open left、负桶为 open right、零桶为 closed both(左边界负、右边界正)。

5.3 元数据查询端点

注意:这些端点可能返回在所选时间范围内无样本、或已被删除 API 标记删除的序列的元数据;额外返回范围属实现细节,可能变化。

5.3.1 按标签匹配器查序列

GET  /api/v1/series
POST /api/v1/series
参数 说明
match[]=<series_selector> 可重复,至少一个
start、end 时间范围
limit 可选,0 禁用

data 为对象数组,每项是标识序列的标签名/值对。start/end 只是近似,结果可能含区间内无样本的序列。

示例:

curl 'http://localhost:9090/api/v1/series' --data-urlencode 'match[]=up' --data-urlencode 'match[]=process_start_time_seconds{job="prometheus"}'

5.3.2 标签名列表

GET  /api/v1/labels
POST /api/v1/labels

参数:start、end、match[](均可选)、limit。data 为字符串标签名数组(示例含 __name__、job、instance、le、quantile 等)。

5.3.3 标签值列表

GET /api/v1/label/<label_name>/values

(仅 GET)。参数:start、end、match[]、limit。data 为字符串标签值数组。

Values Escaping(标签名转义):标签名含 / 等字符时须转义——

  • 前缀 U__;
  • 字母/数字/冒号原样;
  • 单下划线变双下划线;
  • 其他字符用 _<UTF-8编码点十六进制>_(空格→_20_,.→_2e_)。

示例:http.status_code → /api/v1/label/U__http_2e_status_code/values。

5.3.4 搜索 metric/label 名与值(实验性,流式)

GET|POST /api/v1/search/metric_names
GET|POST /api/v1/search/label_names
GET|POST /api/v1/search/label_values
  • 须启用 --enable-feature=search-api。
  • 返回 NDJSON(application/x-ndjson):0+ 条 batch 行(含 results 数组、可选 warnings),然后以 trailer 行(status、has_more、可选 warnings)或 error 行(status、errorType、error)结尾。
  • 流开始前出错返回常规 JSON 错误 + 4xx/5xx,开始后出错以 NDJSON error 行替代 trailer。
  • 客户端须容忍无 trailer 的突然 EOF,并忽略未知字段。
  • has_more 仅信息性,本版无分页游标(需更多结果就提高 limit,受 --web.search.max-limit 限制,或用 match[] 收窄)。

公共参数:

参数 说明
match[] 标签匹配器
search[] 多值 OR
fuzz_threshold 0–100
fuzz_alg subsequence | jarowinkler,默认 subsequence
case_sensitive 大小写敏感
sort_by 排序字段
sort_dir asc | dsc,仅当 sort_by=alpha
include_score 是否含分数
start、end 时间范围
limit 默认 100
batch_size 默认 100

专属参数:

  • metric_names 加 include_metadata、sort_by=alpha|score;
  • label_names 加 sort_by=alpha|score;
  • label_values 加 label=<label_name>(必填)、sort_by=alpha|score。

数据按固定大小 block(通常每块 2 小时)存储,结果可能含窗口略外的活跃序列值。

5.3.5 查询 exemplars(实验性)

GET  /api/v1/query_exemplars
POST /api/v1/query_exemplars

参数:query、start、end。data 为数组,元素含 seriesLabels 与 exemplars(每项 labels、value 字符串、timestamp 浮点秒)。

💡 补充:exemplar 是「样本之外挂载的追踪 ID 等元数据」,需 scrape/exposition 侧支持 OpenMetrics 的 exemplar 才会被采集。

5.4 目标与抓取池端点

5.4.1 抓取池列表

GET /api/v1/scrape_pools

data 为 {"scrapePools": ["prometheus", "node_exporter", "blackbox"]}。v2.42 新增

5.4.2 抓取池配置(实验性,仅 Web UI 用)

GET /api/v1/scrape_pools/config?scrapePool=<scrape_pool_name>
  • scrapePool 必填。
  • 返回该池生效配置(含 scrape_config_files 加载的内容),凭证与密钥被脱敏。
  • data 为 {"yaml": "..."}。

5.4.3 目标总览

GET /api/v1/targets
  • 默认同时返回 active 与 dropped targets;dropped 受 keep_dropped_targets 限制。
  • labels 是 relabel 后的标签集,discoveredLabels 是服务发现阶段未修改的标签。
  • activeTargets 每项含 discoveredLabels、labels、scrapePool、scrapeUrl、globalUrl、lastError、lastScrape、lastScrapeDuration、health、scrapeInterval、scrapeTimeout。

参数:

参数 说明
state active | dropped | any,过滤后被排除的仍返回空数组,其他值忽略
scrapePool 按抓取池名过滤

💡 补充:文档示例中 lastScrapeDuration 出现两种口径(0.050688943 秒与 50688943 纳秒),官方未说明,疑为文档笔误/版本差异。使用时建议以实际返回为准。

5.4.4 Relabel 步骤(实验性,仅 Web UI 用)

GET /api/v1/targets/relabel_steps

参数:scrapePool=<string>(必填)、labels=<string>(必填,relabel 前的标签集 JSON)。data.steps 每步含 keep、output、rule(action/regex/replacement/separator/target_label/source_labels)。

5.5 规则与告警端点

5.5.1 规则列表

GET /api/v1/rules

返回已加载的 alerting 与 recording 规则,以及各告警规则当前触发的活跃告警。该端点比 API v1 整体稳定性保证弱。

参数 说明
type alert | record
rule_name[] 按规则名过滤
rule_group[] 按规则组过滤
file[] 按文件过滤
exclude_alerts <bool>
match[] <label_selector>,匹配规则定义中的标签,非模板展开后的值
group_limit <number>,超出则响应含 groupNextToken
group_next_token 须与 group_limit 同时使用;若分页中对应规则组被删则返回 400

分页期间规则组被修改时不保证一致性。

  • data.groups[].rules[] 中 alerting 规则含 alerts(activeAt、annotations、labels、state、value)、annotations、duration、health、labels、name、query、type;
  • 组含 file、interval、limit、name。

5.5.2 活跃告警

GET /api/v1/alerts

data.alerts[] 每项含 activeAt、annotations、labels、state、value。稳定性保证同样弱于 API v1。

5.6 指标元数据端点

5.6.1 目标指标元数据(实验性)

GET /api/v1/targets/metadata
参数 说明
match_target <label_selectors>,留空选全部目标
metric <string>,留空取全部
limit number

仅返回直接从目标抓取的元数据,经 Remote-Write 或 OTLP 送入的不含在内。data 为对象数组,含 target、metric、type、help、unit。

5.6.2 指标元数据(实验性)

GET /api/v1/metadata

参数:limit、limit_per_metric、metric。data 为对象,键为指标名、值为该指标跨所有目标的唯一元数据对象列表(同一指标可能存在多个不同 help 的条目)。

5.7 Alertmanager 与状态端点

5.7.1 Alertmanager 发现

GET /api/v1/alertmanagers

data 含 activeAlertmanagers 与 droppedAlertmanagers,每项为 {"url": "..."}。

5.7.2 状态端点

端点 说明 新增版本
GET /api/v1/status/config 返回已加载配置的 dump YAML,YAML 注释不保留。data 为 {"yaml": "..."} —
GET /api/v1/status/flags 返回所有 flag 值,全部为 string 类型(如 query.lookback-delta、query.max-concurrency) v2.2
GET /api/v1/status/runtimeinfo 运行时属性(startTime、CWD、hostname、serverTime、reloadConfigSuccess、lastConfigTime、timeSeriesCount、corruptionCount、goroutineCount、GOMAXPROCS、GOGC、GODEBUG、storageRetention),类型不一,且可能随版本无预警变化 v2.14
GET /api/v1/status/buildinfo 构建信息(version、revision、branch、buildUser、buildDate、goVersion),全部 string,且可能随版本无预警变化 v2.14
GET /api/v1/status/tsdb TSDB 基数统计,参数 limit(每类统计返回条数,默认 10,最大 10000) v3.6.0
GET /api/v1/status/tsdb/blocks 当前加载的 TSDB block 及元数据(ulid、minTime/maxTime 毫秒、stats{numSeries/numSamples/numChunks}、compaction{level/sources}、version)。实验性,格式可能变化 v2.15
GET /api/v1/status/walreplay WAL 回放信息。该端点在服务器标记 ready 前即可用并实时更新 v2.28
GET /api/v1/status/self_metrics 实验性。以结构化 JSON(ProtoJSON 编码的 io.prometheus.client.MetricFamily)返回自身插桩指标(与 /metrics 同源),参数 metric_name_pattern=<string>(完全锚定的正则,可选) —

/api/v1/status/tsdb 的 data 字段:

  • headStats(numSeries、chunkCount、minTime、maxTime,毫秒);
  • seriesCountByMetricName、labelValueCountByLabelName、memoryInBytesByLabelName、seriesCountByLabelValuePair。

💡 补充:官方文档正文列出的键名为 seriesCountByLabelPair,而示例中为 seriesCountByLabelValuePair,文档自相矛盾。

/api/v1/status/walreplay 的字段:返回示例字段为 min/max/current/state,而正文描述为 read/total/progress/state(waiting | in progress | done)。描述与示例键名不一致。

/api/v1/status/self_metrics 每个 family 含 name、help、type(COUNTER/GAUGE/SUMMARY/HISTOGRAM/UNTYPED)、可选 unit、metric 列表(含 label 及类型专用数据)。

5.8 TSDB 管理 API

未设置 --web.enable-admin-api 时这些端点不启用。

5.8.1 Snapshot

POST|PUT /api/v1/admin/tsdb/snapshot
  • 把当前数据快照到 TSDB 数据目录下 snapshots/<datetime>-<rand>。
  • 参数 skip_head=<bool>(可选,跳过仅在 head block、尚未 compact 到磁盘的数据)。
  • data 为 {"name": "<快照目录名>"}。
  • v2.1 新增,v2.9 起支持 PUT

5.8.2 Delete Series

POST|PUT /api/v1/admin/tsdb/delete_series
  • 参数:match[](可重复,至少一个)、start(可选,默认最早)、end(可选,默认最晚);start/end 都不给会清除匹配序列的全部数据。
  • 成功返回 204。
  • 实际数据仍在磁盘,待后续 compaction 清理或调用 clean_tombstones。
  • 注意:该端点只是把样本标记删除,不保证元数据查询中不再返回该区间序列元数据。
  • v2.1 新增,v2.9 起支持 PUT

5.8.3 Clean Tombstones

POST|PUT /api/v1/admin/tsdb/clean_tombstones
  • 无参数无 body,成功返回 204。
  • v2.1 新增,v2.9 起支持 PUT

5.9 写入/读取接收端

5.9.1 Remote Write Receiver

--web.enable-remote-write-receiver 启用后端点 /api/v1/write。不视为高效摄入方式,仅适合特定低量场景,不可替代抓取。v2.33 新增

5.9.2 Remote Read

POST /api/v1/read

供外部系统(如 Thanos)读取 TSDB,详见 5.11 节与本手册独立 Remote Read API 说明。

5.9.3 OTLP Receiver

--web.enable-otlp-receiver 启用后端点 /api/v1/otlp/v1/metrics。v2.47 新增。启用 --enable-feature=otlp-deltatocumulative(用 OTel Collector 的 deltatocumulative)可把 delta 时序转为 cumulative 等价形式。v3.2 新增

5.10 通知与特性端点

端点 说明 新增版本
GET /api/v1/notifications 实验性,返回当前所有活跃通知(text、date、active) v3.0
GET /api/v1/notifications/live 实验性,以 Server-Sent Events 流式推送实时通知;删除的通知以 active: false 发送,连接时会先发活跃通知。订阅者达上限时返回 204 No Content,上限由 --web.max-notifications-subscribers(默认 16)控制 v3.0
GET /api/v1/features 返回服务器已启用/禁用的特性,按类别组织 v3.8

/api/v1/features 的类别:api、promql、promql_functions、promql_operators、rules、scrape、service_discovery、templating、tsdb、otlp_receiver、prometheus 等。data 为「类别 → 特性名 → 布尔」映射。

注意:feature 名一律 snake_case;值为 false 的可能被省略,客户端应把缺失视为 false;须忽略未知特性名与类别。

5.11 Remote Read API

引自:Remote Read API

5.11.1 稳定性声明

该 API 当前不属于稳定 API,即使在 Prometheus 的非主版本(non-major)发布之间也可能发生变化。

5.11.2 功能与端点

  • 提供从 Prometheus 读取数据的能力。接口要求 snappy 压缩。
  • API 定义位于 github.com/prometheus/prometheus 仓库的 prompb/remote.proto;Protobuf 定义也可在 buf.build 上查看(prometheus.ReadRequest)。
  • 端点:请求发往 /api/v1/read。

5.11.3 External labels 与 remote read(双向影响)

global 中的 external_labels 设置会双向影响 remote read:

方向 行为
对外提供 remote read(服务端侧) Prometheus 会把 external_labels 追加到经 /api/v1/read 返回的每一条时间序列上。这些标签不存储在 TSDB 中,而是在响应时添加。对于与某个 external label 匹配的入站等值匹配器(equality matchers),会被改写为匹配空字符串,以便 TSDB 能完成查询
使用 remote read(客户端侧) 发起查询的 Prometheus 会把自身的 external_labels 作为额外的等值匹配器放进请求,随后再从响应中把它们剥离

风险提示:若查询方 Prometheus 的 external_labels 与远端服务器不同或缺失,查询可能返回空结果,因为匹配器对不上。应确保查询方所有 external_labels 与远端实际存在的标签保持一致。

5.11.4 Samples 与 Streamed Chunks

  • Samples:返回的消息包含与请求查询匹配的原始样本列表。
  • Streamed Chunks:流式 chunk 使用受 [Gorilla 论文] 启发的 XOR 算法编码,但提供毫秒级分辨率(而非秒级)。

第 6 章 查询调试

引自:Using the Prometheus query log

6.1 是什么 / 为什么

  • 自 2.16.0 起,Prometheus 能够把所有引擎执行的查询记录到日志文件。
  • query log 可在运行时切换开关,因此适合在排查 Prometheus 实例变慢或高负载时启用。
  • 用途:定位「哪条 PromQL 在拖慢服务器」——通常来自仪表盘或临时调试查询。

6.2 怎么用:开启与关闭

启用/禁用两步:① 修改配置以添加/移除 query log 配置;② reload Prometheus server 配置。

6.2.1 开启

记录所有查询到 /prometheus/query.log(假设 /prometheus 是数据目录且 Prometheus 有写权限)。修改 prometheus.yml:

global:
  scrape_interval:     15s
  evaluation_interval: 15s
  query_log_file: /prometheus/query.log
scrape_configs:
- job_name: 'prometheus'
  static_configs:
  - targets: ['localhost:9090']

reload:

curl -X POST http://127.0.0.1:9090/-/reload

💡 补充:若 Prometheus 启动时未带 --web.enable-lifecycle,且非 Windows 环境,可向 Prometheus 进程发送 SIGHUP 触发 reload。

💡 补充:命令行参数 --query.log-file 等价于配置中的 query_log_file;两者其一即可,生产上更推荐配置方式以便配合 reload 动态切换。

6.2.2 关闭

重复上述操作并从配置中移除 query_log_file,然后 reload。

6.2.3 验证是否启用

两个 metrics:

# HELP prometheus_engine_query_log_enabled State of the query log.
# TYPE prometheus_engine_query_log_enabled gauge
prometheus_engine_query_log_enabled 0
# HELP prometheus_engine_query_log_failures_total The number of query log failures.
# TYPE prometheus_engine_query_log_failures_total counter
prometheus_engine_query_log_failures_total 0
  • prometheus_engine_query_log_enabled:启用时为 1,否则为 0。
  • prometheus_engine_query_log_failures_total:表示无法记录的查询数。

6.3 日志格式与字段解读

query log 为 JSON 格式(每行一条 JSON)。

6.3.1 查询字段概览

{
    "params": {
        "end": "2020-02-08T14:59:50.368Z",
        "query": "up == 0",
        "start": "2020-02-08T13:59:50.368Z",
        "step": 5
    },
    "stats": {
        "timings": {
            "evalTotalTime": 0.000447452,
            "execQueueTime": 7.599e-06,
            "execTotalTime": 0.000461232,
            "innerEvalTime": 0.000427033,
            "queryPreparationTime": 1.4177e-05,
            "resultSortTime": 6.48e-07
        }
    },
    "ts": "2020-02-08T14:59:50.387Z"
}
字段 含义
params 查询:start/end 时间戳、step 与实际查询语句 query
stats 统计(当前含内部引擎计时器)
ts 查询结束时间戳

stats.timings 各计时器:

计时器 含义
queryPreparationTime 查询准备(解析、构造执行计划)耗时
execQueueTime 在执行队列中等待的耗时
innerEvalTime 引擎实际求值耗时
evalTotalTime 求值总耗时
execTotalTime 执行总耗时
resultSortTime 结果排序耗时

💡 补充:视触发请求来源不同,JSON 行还会含额外字段。

6.3.2 API 查询与 consoles

HTTP 请求含客户端 IP、method、path:

{
    "httpRequest": {
        "clientIP": "127.0.0.1",
        "method": "GET",
        "path": "/api/v1/query_range"
    }
}
  • path 在设置了 web prefix 时会包含前缀,也可能指向 console。
  • client IP 是网络 IP 地址,不考虑 X-Forwarded-For 等 header;若想记录代理后的原始调用方,需在代理本身记录。

6.3.3 Recording rules 与 alerts

含 ruleGroup 元素(文件路径与 group 名):

{
    "ruleGroup": {
        "file": "rules.yml",
        "name": "partners"
    }
}

6.4 日志轮转注意事项

  • Prometheus 自身不会轮转 query log,需用外部工具,如 logrotate(多数 Linux 发行版默认启用)。
  • 示例 /etc/logrotate.d/prometheus:
/prometheus/query.log {
    daily
    rotate 7
    compress
    delaycompress
    postrotate
        killall -HUP prometheus
    endscript
}
  • 该配置每日轮转并保留一周历史。

💡 补充:postrotate 里的 killall -HUP prometheus 与 6.2.1 的 reload 机制一致——Prometheus 收到 SIGHUP 会重新打开日志文件句柄,从而切换到新的 query log 文件,避免继续写入已被 logrotate 改名的旧文件。

6.5 性能排查思路

💡 补充:以下为结合官方 query log / stats 的排查方法,非文档原文。

  1. 先开 query log,再复现问题:在实例变慢时才启用(运行时切换),避免长期开启带来的 I/O 开销。
  2. 按 stats.timings 排序定位瓶颈:
    • execQueueTime 高 → 并发查询排队,考虑 --query.max-concurrency 与客户端并发;
    • innerEvalTime 高 → 单条表达式本身昂贵,需优化 PromQL(加过滤、先聚合、用 recording rule);
    • resultSortTime 高 → 返回序列数过多,用 limit 或更强聚合收窄。
  3. 看 params.query 与 httpRequest.path:
    • 若来自 /api/v1/query_range 且 step 很小、时间范围很大,通常是仪表盘在拉大图;
    • 若是 query_exemplars/series 等元数据类端点,往往是**查询构建器(如 Grafana 的指标浏览器)**在探测。
  4. 结合 HTTP API 的 stats 参数(见 5.2.3):用 stats=all 获取 totalQueryableSamples、samplesRead、peakSamples,判断是载入样本多还是内存峰值高。
  5. 落地优化:对高频昂贵查询建立 recording rule 预计算;对仪表盘收紧时间范围与 step;必要时调整 --query.timeout、--query.max-concurrency。

第 7 章 直方图与分位数

引自:Histograms and summaries

7.1 总纲与两种表示法

总纲:histogram 因历史原因分 classic 与 native 两种变体(后者还有子变体)。能用的前提下优先用 native histograms,优于 classic histograms 和 summaries。 仅在①存量指标是 classic/summary、②所用库不支持 native、③少数特定场景时退而求其次。OTel 接入时提示「prefer the latter(NHCB)」。

表示分布的两条路:

方式 机制 优点 缺点
summary 程序对预配置时间窗口预计算若干分位数并作为额外指标暴露 分位通常很精确 (a) 计算有资源开销;(b) 之后无法换窗口/百分位重算;(c) 分位数无法聚合(无法算多副本服务的整体 P90)
histogram 以 digest(bucket 计数)表示分布 之后可对任意窗口算任意分位数;分布可互相聚合 分位是估算(受桶/分辨率限制)

两者都额外采集 count 与 sum;都需每样本采集一堆数值,称 composite types。

classic 与 native 的映射差异:

  • classic 映射:把多值拆成多条序列,按特定 label 区分——summary 每个分位数、histogram 每个 bucket、及 count/sum 各一条。
  • native:单个样本内含 count、sum 与动态 bucket(计数+边界),TSDB 中一个 histogram 只对应一条样本序列。

7.1.1 库支持

  • summary:几乎都支持(部分只给 count/sum,即 quantile-less summary,仍合法);
  • classic histogram:广泛;
  • native histogram:仍罕见,需 protobuf 格式(Java、Go),文本格式支持正作为 OpenMetrics v2 推进。

只暴露 classic 时,可让 Prometheus 摄入为 NHCB(自定义桶边界的 native histogram)——比标准指数桶有局限,但存储效率远高于 classic,PromQL 处理同 native,日后迁移容易。

7.1.2 OTel 接入

普通 OTel histogram 可转 classic 或 NHCB(优选 NHCB);OTel exponential histograms 总转成标准 native histogram。

7.2 Histogram 数据结构

7.2.1 classic histogram 的序列构成

一个 classic histogram 指标(如 http_request_duration_seconds)在 TSDB 中映射为多条 float 序列:

序列 含义
http_request_duration_seconds_bucket{le="..."} 每个桶的累积计数,le = less or equal,值为累积桶上界(闭区间)
http_request_duration_seconds_sum 观测值总和
http_request_duration_seconds_count 观测次数

关键:classic 摄入时每个配置桶都生成一条 _bucket 序列(无论是否被填充)。

7.2.2 native histogram 的样本结构

单个样本内含 count、sum 与动态 bucket(计数 + 边界),TSDB 中一个 histogram 只对应一条样本序列。HTTP API 中暴露为:

{
  "count": "<count_of_observations>",
  "sum": "<sum_of_observations>",
  "buckets": [[<boundary_rule>, "<left_boundary>", "<right_boundary>", "<count_in_bucket>"], ...]
}

7.3 count 与 sum:算平均值

思路:先取 rate,再「sum 的 rate」除以「count 的 rate」。

7.3.1 native(含 NHCB)

用 histogram_sum / histogram_count:

  histogram_sum(rate(http_request_duration_seconds[5m]))
/
  histogram_count(rate(http_request_duration_seconds[5m]))

等价短写法:

histogram_avg(rate(http_request_duration_seconds[5m]))

7.3.2 summary / classic

用 _sum / _count 序列:

  rate(http_request_duration_seconds_sum[5m])
/
  rate(http_request_duration_seconds_count[5m])
  • 分母即每秒请求数;..._count 行为等价于请求计数器(若无该 histogram/summary 你会命名 http_requests_total)。

7.3.3 负值观测的特殊问题

  • 混入负值时 sum 可能下降,被 rate(..._sum[5m]) 误判为 counter reset。
  • 只影响 summary 与 classic;native(含 NHCB)整体做 rate,能正确检测 reset。
  • 万不得已时用两个 summary/histogram(正值、取反负值)再合并。

7.3.4 聚合

sum/count 可加,应在 rate 之后、相除之前聚合(与底层类型无关):

# native histograms
  sum by (job) (histogram_sum(rate(http_request_duration_seconds[5m])))
/
  sum by (job) (histogram_count(rate(http_request_duration_seconds[5m])))

# summaries / classic histograms
  sum by (job) (rate(http_request_duration_seconds_sum[5m]))
/
  sum by (job) (rate(http_request_duration_seconds_count[5m]))

7.4 Bucketing:桶选择

7.4.1 classic

  • 埋点配固定桶边界;classic 摄入时每个配置桶都生成一条 _bucket 序列。
  • 桶越多精度越高,但「每桶一序列」代价显著。
  • 难点:事先挑对桶困难,事后改桶扰动大。

7.4.2 NHCB

  • 未填充桶代价可忽略,已填充也更高效(单条复合序列)。

7.4.3 native

  • 不选边界,配分辨率,按指数分桶动态创建,覆盖 -Inf 到 +Inf。
  • 分辨率越高资源越大,但同资源下可达远高于 classic 的分辨率;库还提供限桶策略(偶发重置、自适应降分辨率)。

7.4.4 计算落在某区间的比例

histogram_fraction(0, 0.3, sum by (job) (rate(http_request_duration_seconds[5m])))

即每个 job 最近 5m 落在 0–300ms 的比例(300ms 写 0.3,始终用基础单位)。

  • sum 通过求和相应桶聚合;桶布局不同会先 reconcile——标准指数桶平滑回退到最低公共分辨率,5m 内跨时间的布局差异同样处理。
  • NHCB 下效果重度依赖具体布局,可能只剩一个含全部观测的桶,需 reconcile 时结果带 info 级 annotation。

7.4.5 精度

  • 恰有桶边界在 0.3 才精确;否则用插值返回估算比例,分辨率越高越准。
  • 已知 SLO(如 95% 请求 300ms 内)可用 classic 固定边界求精确,但改 SLO 后改桶很繁琐;native 动态桶虽不落在 0.3 但插值仍较准,换来随时改区间边界的自由(利于 SLO 变更)。

7.4.6 纯 classic 的表达式截然不同

  sum by (job) (rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
/
  sum by (job) (rate(http_request_duration_seconds_count[5m]))
  • le = less or equal,值为累积桶上界(闭区间)。
  • 严格要求存在 0.3 桶边界:无则不做插值、直接无结果;只有部分 histogram 有时返回不完整结果且无警告(很糟糕,应避免纯 classic)。

7.4.7 Apdex score

目标 300ms、可容忍 1.2s(通常 4 倍目标)。按 job 求最近 5m:

native(含 NHCB):

  histogram_fraction(0, 0.3, sum by (job) (rate(http_request_duration_seconds[5m])))
+
  histogram_fraction(0.3, 1.2, sum by (job) (rate(http_request_duration_seconds[5m]))) / 2

纯 classic(必须在精确边界有桶,因累积桶表达式不同):

    (
        sum by (job) (rate(http_request_duration_seconds_bucket{le="0.3"}[5m]))
      +
        sum by (job) (rate(http_request_duration_seconds_bucket{le="1.2"}[5m]))
    )
  /
    2
/
  sum by (job) (rate(http_request_duration_seconds_count[5m]))

💡 补充:原文注——为简便未显式排除失败请求,严格正确的 Apdex 需排除。

7.5 Quantiles:分位数

φ-quantile(0 ≤ φ ≤ 1)是 N 个观测中排第 φ*N 位的观测值;0.5 = 中位数,0.95 = P95。

7.5.1 本质区别

  • summary:在程序内流式算出并直接暴露;
  • histogram:暴露分桶计数,由服务端 histogram_quantile() 计算。

7.5.2 三类实现对比

维度 native classic summary
埋点配置 选分辨率 / 限桶策略 选适合的桶 选 φ 与窗口(之后不可再算别的)
埋点成本 便宜(仅自增计数) 便宜 较贵(流式计算)
查询性能 需服务端计算(太慢可用 recording rules) 需服务端计算 快
序列数 一条复合样本 _sum+_count+每桶 _sum+_count+每分位
分位误差 受分辨率限 受桶宽限 可配、通常很低
φ 与窗口 PromQL ad-hoc 指定 PromQL ad-hoc 指定 埋点期预配
聚合 可行 可行(需桶边界不变) 不可聚合

NHCB:埋点侧与 classic 完全相同(NHCB 仅服务端生成);查询性能与序列数同 native,分位误差同对应 classic;改桶布局比 classic 略优雅但仍 problematic(至少以 annotation 标出)。

7.5.3 多副本聚合

多副本想算整体 P95 时,聚合 summary 的分位数几乎无意义,取平均统计上荒谬:

avg(http_request_duration_seconds{quantile="0.95"}) // BAD!

histogram 则可聚合:

# native(含 NHCB)
histogram_quantile(0.95, sum(rate(http_request_duration_seconds[5m]))) // GOOD.

# classic
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m]))) // GOOD.

7.5.4 SLO 变化时的取值

SLO 变化(改看 P90、或改看 10m)时只改表达式,无需重配埋点。取值示例:

  • summary 配 0.95 分位 + 5m 衰减;
  • native 配合适分辨率(Go 库可用 NativeHistogramBucketFactor=1.1);
  • classic 配 {le="0.1"}、{le="0.2"}、{le="0.3"}、{le="0.45"}。

7.6 histogram_quantile 计算原理(线性插值)

histogram_quantile(φ, b) 的关键逻辑(函数详细签名见 3.7.4):

  1. 识别桶归属:classic 的 float 样本必须带 le 标签,其余标签与 metric 名用于识别各 bucket 属于哪个经典直方图。
  2. 定位落点桶:找到分位数落在哪个 bucket(累积计数首次达到 φ*count 的桶)。
  3. 桶内插值:
    • 经典直方图、原生自定义边界直方图、原生 zero bucket → 线性插值(假设桶内均匀分布);
    • 原生标准指数 schema 的非零桶 → 指数插值(假设样本在更高分辨率的假设直方图中均匀填充各桶)。
  4. 特例处理:见 3.7.4 的返回值特例、经典特例、原生特例。
  5. 单调性修正:classic bucket 计数应单调不减;浮点误差(阈值 1e-12)被忽略,非单调则抬升到前一桶值并打 info 注解 input to histogram_quantile needed to be fixed for monotonicity。

聚合注意事项(务必记住):用 rate() 指定时间窗口后,先把 le 放进 by 再求和:

# classic:必须有 le
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))

# native:直接 sum,无需 by
histogram_quantile(0.95, sum(rate(http_request_duration_seconds[5m])))

💡 补充:顺序必须是 rate → sum → histogram_quantile。若先 sum 后 rate,会因 counter reset 无法跨实例正确检测而出错(同 3.6.6 的通用规则)。

7.7 分位数估算误差

  • 分位数无论程序内还是服务端算,都是估算。

例 1(native,NativeHistogramBucketFactor=1.1,请求全约 220ms):

  • 尖峰所在桶约 0.210–0.229;设全在此桶,histogram_quantile 插值估 P95 = 228ms,真值在 210–229ms 之间,最坏情况也相当准。
  • 同例 classic({le="0.3"},即 200–300ms):插值估 295ms,真值 200–300ms——误差界大得多且离真值远;SLO=300ms 时会误以为快要违约。

例 2(再加 100ms 后端延迟,尖峰 320ms):

  • native 相关桶 297–324ms,估 323ms(几乎完美);
  • classic 观测几乎全在 300–450ms 桶,估 443ms,远离正确的约 320ms。

例 3(150ms 尖峰占 90%,另 10% 均匀铺在 150–450ms 长尾):此时 P95 恰为 SLO 300ms;

  • classic 在此例准确(P95 恰与某桶边界重合;桶内均匀正是 classic 插值的假设)。

summary 的误差按 φ 维度配置,如 0.95±0.01 → 结果落在 P94–P96 之间;上例 P94=270ms、P96=330ms,报告值可能在 270–330ms,横跨「明显在 SLO 内」与「明显超 SLO」。

结论:

  • summary 掌握 φ 维度的误差;
  • histogram 掌握观测值维度的误差(classic 靠选桶布局、难;native 靠选分辨率、易)。
  • 分布越宽,φ 微变引起观测值大幅偏差;分布越尖,观测值的小区间覆盖很大的 φ 区间。

7.7.1 三条经验法则

  1. 能用 native histograms 就用,分辨率匹配精度要求,兼顾精度、可聚合与 ad-hoc 改参数(百分位、滑动窗口);
  2. 不能 native 但需聚合则用 classic,须设合适桶边界并在桶成本与所需精度间取平衡;
  3. 仅当不需聚合才考虑 summary(φ 维度很准、总成本较低,但须在埋点期选定分位数与窗口是严重缺点)。

7.8 Summary 的对比与取舍

取舍点 summary histogram
分位精度 φ 维度可配,通常很高 受桶宽/分辨率限制,是估算
可聚合性 不可聚合 可聚合
φ 与窗口灵活性 埋点期固定,事后不可改 查询期任意指定
埋点开销 较高(流式计算) 较低(自增计数)
查询开销 低 需服务端计算
序列数 _sum+_count+每分位 _sum+_count+每桶(classic)或一条(native)

7.9 可视化

  • summary 分位数可像普通浮点序列可视化;
  • histogram 更复杂:
    • UI 的 Table 视图显示单个样本的图形表示;
    • Graph 视图对 classic 分别画每条成分序列、对 native 只画 sum。
  • 随时间变化的最佳可视化是 heatmap;Prometheus UI 尚不支持(issue #15346),Perses、Grafana 可渲染。
  • classic 分辨率通常不足以做好热力图,native 的高分辨率可支持非常精细的热力图。

7.10 Native histograms 简要提点

  • 单一复合样本:一个 histogram 对应一条序列(对比 classic 的「每桶一序列」),存储与基数双重友好。
  • 动态指数分桶:只需配分辨率,覆盖 -Inf 到 +Inf,无需预先选桶边界。
  • 可聚合:sum / rate 后可直接 histogram_quantile,无需 by (le)。
  • 负值友好:整体做 rate,能正确检测 counter reset(classic/summary 不能)。
  • NHCB:由 classic 摄入生成,PromQL 处理同 native,便于日后迁移。
  • OTel 的 exponential histogram 总转成标准 native histogram。
  • 规范详见第 4 篇「Native Histograms 规范」章节。

第 8 章 UTF-8 指标名

引自:UTF-8 in Prometheus

8.1 背景

  • 3.0 之前的 Prometheus 要求 metric 与 label 名遵守严格字符集;
  • Prometheus 3.0 起所有 UTF-8 字符串都是合法名称,但生态其他部分引入任意 UTF-8 字符名称还需一些手动改动。
  • 也可能有用户想强制 legacy 字符集(例如为兼容旧 Prometheus 或尚不支持 UTF-8 的其他 scraper)。本章讲解 UTF-8 过渡细节。

8.1.1 Go Instrumentation

  • 官方 client_golang 创建的 metrics 默认接受 UTF-8 名称。
  • 此前文档建议用户覆盖 model.NameValidationScheme 值以选择 legacy 校验;该 boolean 现已 deprecated,应始终设为 UTF8Validation。
  • 若需强制 legacy 校验,应由各实现调用相应 validation APIs 完成,而不再是库特性。

8.1.2 其他语言

其他 client libraries 可能尚不支持 UTF-8,可能需要特殊处理或配置,请查阅所用库文档。

8.2 配置项:metric_name_validation_scheme

Prometheus 3.0 默认接受所有 UTF-8 字符串为合法 metric/label 名;可覆盖此行为以拒绝不符合 legacy 字符集的名称。

全局设置:

global:
  metric_name_validation_scheme: legacy

按 scrape config 设置:

scrape_configs:
  - job_name: prometheus
    metric_name_validation_scheme: legacy
  • scrape config 设置覆盖全局设置。
  • 若设置了 scrape config 的 validation 但未设置 escaping scheme,则 escaping scheme 会从 validation scheme 推断——因此可只设 metric_name_validation_scheme 而无需同时指定 metric_name_escaping_scheme。

8.3 Scrape Content Negotiation for UTF-8 escaping

  • 抓取时,抓取系统必须在 Accept header 传 escaping=allow-utf-8 才会被提供 UTF-8 名称;
  • 若 scrape target 未见该 header,会自动用 underscore replacement 把 UTF-8 名称转换为 legacy-compatible。

Prometheus 及兼容抓取系统也可通过把 escaping header 设为不同值来请求特定 escaping 方法:

escaping 值 行为
underscores 默认;把 legacy-invalid 字符转为下划线
dots 类似 UnderscoreEscaping,但点转为 _dot_,且既有下划线转为 __。允许含点的简单 metric 名往返(round-trip)
values 名称前置 U__,把所有非法字符替换为 unicode 值(两侧加下划线),单个下划线替换为双下划线。允许与 legacy Prometheus 之间完整往返 UTF-8 名称

要点:在 content negotiation 中声明 UTF-8 支持表示 Prometheus 能够接收 UTF-8 字符,但不要求 metric 名包含此前不支持的字符;Accept header 声明支持 UTF-8 也不要求 metrics 生产者禁用其侧的名称转换。确切名称转换策略由 metrics 生产者决定。要求是:当 Prometheus 请求 allow-utf-8 之外的 escaping scheme 时,生产者必须按请求方式转换名称。

8.4 Remote Write 2.0

在 Prometheus 3.0 中自动接受所有 UTF-8 名称;无法在 Remote Write 2.0 中强制 legacy 字符集校验。

8.5 OTLP Metrics

Prometheus 3.0 的 OTLP receiver 默认仍把所有名称规范化为 Prometheus 格式。可在配置的 otlp 段更改:

otlp:
  # Ingest OTLP data keeping UTF-8 characters in metric/label names.
  translation_strategy: NoTranslation

注意:当不追加 type 与 unit 后缀时,若存在两个同名但 type 或 unit 不同的 metrics,它们在 Prometheus 中会冲突(collide)。等 Prometheus 原生支持 type 与 unit metadata 后该问题将消失。详见 OpenTelemetry guide。

8.6 引用语法

查询 UTF-8 名称的 metrics 在 PromQL 中需略不同的语法:

  • classic 查询语法对 legacy-compatible 名称仍有效:my_metric{};
  • 但 UTF-8 名称必须加引号并移入花括号内:{"my.metric"};
  • label 名若含 legacy-incompatible 字符也必须加引号:{"metric.name", "my.label.name"="bar"};
  • metric 名可出现在花括号内任意位置,但风格上偏好放在首个位置。

8.7 注意事项汇总

事项 结论
默认校验 3.0 起默认接受全部 UTF-8 名称
强制 legacy 用 metric_name_validation_scheme: legacy(全局或 scrape config,后者优先)
escaping scheme 推断 只设 validation 即可,escaping 会据此推断
抓取协商 必须 escaping=allow-utf-8,否则自动 underscore 转换
Remote Write 2.0 无法强制 legacy
OTLP 默认规范化;translation_strategy: NoTranslation 保留 UTF-8;注意 type/unit 冲突
PromQL 引用 {"metric.name"}、{"metric.name", "label.name"="v"}

附录 本篇覆盖清单

本篇对应的官网 URL → 手册章节对照表。覆盖依据见《Prometheus-覆盖映射表.md》。

# 官网页面 URL 归属章节
19 https://prometheus.io/docs/prometheus/latest/querying/basics/ 第 1 章 PromQL 基础
20 https://prometheus.io/docs/prometheus/latest/querying/examples/ 第 4 章 查询示例集
21 https://prometheus.io/docs/prometheus/latest/querying/index/ 第 1 章(导航页,见 4.3.8 说明)
22 https://prometheus.io/docs/prometheus/latest/querying/operators/ 第 2 章 运算符
23 https://prometheus.io/docs/prometheus/latest/querying/functions/ 第 3 章 函数全表
24 https://prometheus.io/docs/prometheus/latest/querying/remote_read_api/ 第 5.11 节 Remote Read API
25 https://prometheus.io/docs/prometheus/latest/querying/api/ 第 5 章 HTTP API
37 https://prometheus.io/docs/prometheus/latest/management_api/ 第 5.8 节 TSDB 管理 API
70 https://prometheus.io/docs/guides/query-log/ 第 6 章 查询调试
72 https://prometheus.io/docs/guides/utf8/ 第 8 章 UTF-8 指标名
92 https://prometheus.io/docs/practices/histograms/ 第 7 章 直方图与分位数

本篇收录统计:

  • 章节:8 章 + 附录;
  • 函数:90 个(其中实验性 16 个);
  • 运算符:一元 1 个、算术 6 个、三角 1 个、直方图裁剪 2 个、比较 6 个、逻辑/集合 3 个、聚合 14 个、fill modifiers 3 个;
  • HTTP API 端点:40+ 个(含实验性与需 flag 启用的端点);
  • 查询示例:官方 examples 全部 15 条场景 + 索引页说明。

💡 补充:本篇所有内容均取自 prometheus/docs 官方仓库源文件(raw/core/querying/*、raw/docs/guides/query-log.md、raw/docs/guides/utf8.md、raw/docs/practices/histograms.md),与官网 latest 一致。凡标 > 💡 补充: 的段落为结合上下文的经验性说明,非官方原文。