2844 lines
131 KiB
Markdown
2844 lines
131 KiB
Markdown
# Prometheus 知识学习手册 · 第 2 篇:PromQL 与查询
|
||
|
||
> 基于 [prometheus.io 官方文档](https://prometheus.io/docs/prometheus/latest/querying/basics/) 整理
|
||
> 文档版本: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-章-promql-基础)
|
||
- [1.1 查询语言总览](#11-查询语言总览)
|
||
- [1.2 样本与 flavor](#12-样本与-flavor)
|
||
- [1.3 表达式语言数据类型](#13-表达式语言数据类型)
|
||
- [1.4 字面量与时间表达式](#14-字面量与时间表达式)
|
||
- [1.5 时间序列选择器](#15-时间序列选择器)
|
||
- [1.6 时间修饰:offset、@ modifier 与子查询](#16-时间修饰offset-modifier-与子查询)
|
||
- [1.7 Lookback 与 staleness](#17-lookback-与-staleness)
|
||
- [1.8 正则表达式](#18-正则表达式)
|
||
- [1.9 UTF-8 引用语法提点](#19-utf-8-引用语法提点)
|
||
- [1.10 注释与慢查询规避](#110-注释与慢查询规避)
|
||
- [第 2 章 运算符](#第-2-章-运算符)
|
||
- [2.1 一元运算符](#21-一元运算符)
|
||
- [2.2 算术运算符](#22-算术运算符)
|
||
- [2.3 三角函数运算符](#23-三角函数运算符)
|
||
- [2.4 直方图裁剪运算符](#24-直方图裁剪运算符)
|
||
- [2.5 比较运算符](#25-比较运算符)
|
||
- [2.6 逻辑/集合运算符](#26-逻辑集合运算符)
|
||
- [2.7 向量匹配](#27-向量匹配)
|
||
- [2.8 聚合运算符](#28-聚合运算符)
|
||
- [2.9 二元运算符优先级](#29-二元运算符优先级)
|
||
- [2.10 实验特性:fill modifiers](#210-实验特性fill-modifiers)
|
||
- [第 3 章 函数全表](#第-3-章-函数全表)
|
||
- [3.1 通用约定](#31-通用约定)
|
||
- [3.2 缺失检测类](#32-缺失检测类)
|
||
- [3.3 取整与数值钳制类](#33-取整与数值钳制类)
|
||
- [3.4 数学函数](#34-数学函数)
|
||
- [3.5 时间与日期类](#35-时间与日期类)
|
||
- [3.6 范围向量(趋势/变化/速率)类](#36-范围向量趋势变化速率类)
|
||
- [3.7 直方图专用函数](#37-直方图专用函数)
|
||
- [3.8 标签操作类](#38-标签操作类)
|
||
- [3.9 排序与向量构造类](#39-排序与向量构造类)
|
||
- [3.10 over_time 聚合系列](#310-over_time-聚合系列)
|
||
- [3.11 三角函数](#311-三角函数)
|
||
- [3.12 函数速查总表](#312-函数速查总表)
|
||
- [第 4 章 查询示例集](#第-4-章-查询示例集)
|
||
- [4.1 简单时序选择](#41-简单时序选择)
|
||
- [4.2 子查询示例](#42-子查询示例)
|
||
- [4.3 函数与运算符实战](#43-函数与运算符实战)
|
||
- [第 5 章 HTTP API](#第-5-章-http-api)
|
||
- [5.1 通用格式与响应信封](#51-通用格式与响应信封)
|
||
- [5.2 表达式查询端点](#52-表达式查询端点)
|
||
- [5.3 元数据查询端点](#53-元数据查询端点)
|
||
- [5.4 目标与抓取池端点](#54-目标与抓取池端点)
|
||
- [5.5 规则与告警端点](#55-规则与告警端点)
|
||
- [5.6 指标元数据端点](#56-指标元数据端点)
|
||
- [5.7 Alertmanager 与状态端点](#57-alertmanager-与状态端点)
|
||
- [5.8 TSDB 管理 API](#58-tsdb-管理-api)
|
||
- [5.9 写入/读取接收端](#59-写入读取接收端)
|
||
- [5.10 通知与特性端点](#510-通知与特性端点)
|
||
- [5.11 Remote Read API](#511-remote-read-api)
|
||
- [第 6 章 查询调试](#第-6-章-查询调试)
|
||
- [第 7 章 直方图与分位数](#第-7-章-直方图与分位数)
|
||
- [第 8 章 UTF-8 指标名](#第-8-章-utf-8-指标名)
|
||
- [附录 本篇覆盖清单](#附录-本篇覆盖清单)
|
||
|
||
---
|
||
|
||
## 第 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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/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 **不丢弃**反引号内的换行。
|
||
|
||
```promql
|
||
"this is a string"
|
||
'these are unescaped: \n \\ \t'
|
||
`these are not unescaped: \n ' " \t`
|
||
```
|
||
|
||
#### 1.4.2 Float literals
|
||
|
||
标量浮点值可写为整数或浮点字面量,格式(空白仅为可读性):
|
||
|
||
```text
|
||
[-+]?(
|
||
[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** 中:
|
||
|
||
```promql
|
||
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](https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||
|
||
### 1.5 时间序列选择器
|
||
|
||
#### 1.5.1 Instant vector selectors(瞬时向量选择器)
|
||
|
||
允许选择一组时间序列及其在给定时点的单个样本值。最简形式只指定 metric name,返回包含所有该名字时间序列的 instant vector。
|
||
|
||
返回值是**查询评估时间戳(instant query)或查询中当前 step(range query)之前或等于该时刻的最新样本**。`@` modifier 可覆盖选择所依据的时间戳。仅当其最新样本在 lookback period 之内时序列才被返回(见 1.7)。
|
||
|
||
```promql
|
||
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]`。
|
||
|
||
- **区间为左开右闭**:时间戳与左边界重合的样本被**排除**,与右边界重合的被**包含**。
|
||
|
||
```promql
|
||
http_requests_total{job="prometheus"}[5m]
|
||
```
|
||
|
||
> 引自:[Querying basics](https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||
|
||
### 1.6 时间修饰:offset、@ modifier 与子查询
|
||
|
||
#### 1.6.1 Offset modifier
|
||
|
||
允许为查询中单个 instant 与 range vector 改变时间偏移。**`offset` 必须紧跟 selector**。
|
||
|
||
```promql
|
||
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**。
|
||
|
||
```promql
|
||
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 相对于 `@` 时间施加,**结果与两者顺序无关**:
|
||
|
||
```promql
|
||
http_requests_total @ 1609746000 offset 5m
|
||
http_requests_total offset 5m @ 1609746000
|
||
```
|
||
|
||
- `start()` 与 `end()` 可作为 `@` 的特殊值:对 range query 分别解析为 range query 的起点与终点,且对所有 step 保持不变;对 instant query 两者都解析为求值时间。
|
||
|
||
```promql
|
||
http_requests_total @ start()
|
||
rate(http_requests_total[5m] @ end())
|
||
```
|
||
|
||
**注意**:`@` modifier 允许查询前瞻其评估时间。
|
||
|
||
#### 1.6.3 Subquery(子查询)
|
||
|
||
Subquery 允许对给定 range 与 resolution 运行 instant query,结果是一个 **range vector**。
|
||
|
||
语法:
|
||
|
||
```text
|
||
<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <float_literal> ]
|
||
```
|
||
|
||
- `<resolution>` 可选,**默认为全局 evaluation interval**。
|
||
|
||
> 引自:[Querying basics](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||
|
||
### 1.8 正则表达式
|
||
|
||
Prometheus 中所有正则表达式使用 **RE2 syntax**。Regex 匹配**始终完全锚定**。
|
||
|
||
> 引自:[Querying basics](https://prometheus.io/docs/prometheus/latest/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](https://prometheus.io/docs/guides/utf8/)
|
||
|
||
### 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](https://prometheus.io/docs/prometheus/latest/querying/basics/)
|
||
|
||
> 💡 补充:本手册第 6 章「查询调试」给出了 query log 的开启方式与性能排查思路,可与本节配合使用。
|
||
|
||
---
|
||
|
||
## 第 2 章 运算符
|
||
|
||
PromQL 支持 **unary(一元)**、**binary(二元)** 与 **aggregation(聚合)** 三类运算符。
|
||
|
||
> 引自:[Operators](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/operators/)
|
||
|
||
### 2.3 三角函数运算符
|
||
|
||
存在以下三角函数**二元**运算符,以**弧度**工作:
|
||
|
||
| 运算符 | 含义 |
|
||
|:-------|:-----|
|
||
| `atan2` | 基于 <https://pkg.go.dev/math#Atan2> |
|
||
|
||
三角函数运算符允许借助 vector matching 对两个向量执行三角函数,这是普通函数所不具备的。其行为方式与算术运算符相同,**仅作用于 float samples**;涉及 histogram samples 的运算导致对应向量元素移出输出向量并标记 **info-level annotation**。
|
||
|
||
> 引自:[Operators](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/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` 允许将考虑标签集缩减为所给列表。
|
||
|
||
```text
|
||
<vector expr> <bin-op> ignoring(<label list>) <vector expr>
|
||
<vector expr> <bin-op> on(<label list>) <vector expr>
|
||
```
|
||
|
||
**示例输入**:
|
||
|
||
```text
|
||
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
|
||
```
|
||
|
||
**示例查询**:
|
||
|
||
```promql
|
||
method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
|
||
```
|
||
|
||
返回结果向量包含各 method 在过去 5 分钟状态码 500 的 HTTP 请求占比。没有 `ignoring(code)` 就不会有匹配,因为两个指标不共享相同标签集。`put` 与 `del` 方法无匹配,不出现在结果中:
|
||
|
||
```text
|
||
{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 决定哪个向量基数更高:
|
||
|
||
```text
|
||
<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`,**一个标签只能出现在其中一个列表中**。
|
||
- **结果向量的每条时间序列必须唯一可识别。**
|
||
|
||
**示例查询**:
|
||
|
||
```promql
|
||
method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
|
||
```
|
||
|
||
此处左侧向量每个 `method` 标签值有多个条目,用 `group_left` 表示。右侧元素现在与左侧相同 `method` 标签的多个元素匹配:
|
||
|
||
```text
|
||
{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](https://prometheus.io/docs/prometheus/latest/querying/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` 子句保留不同维度;子句**可置于表达式之前或之后**:
|
||
|
||
```text
|
||
<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**。
|
||
|
||
```promql
|
||
# 若 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 不应用排序。**
|
||
|
||
```promql
|
||
topk(5, memory_consumption_bytes) # 跨所有实例内存消耗最高的 5 个实例
|
||
```
|
||
|
||
**`limitk(k, v)`**(experimental):返回 `k` 个输入样本的子集,结果向量含原始标签。子集以**确定性伪随机**方式选取,与样本类型无关,因此对 float samples 与 histogram samples 都适用。
|
||
|
||
```promql
|
||
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 值的紧凑字符串表示作为标签值。
|
||
|
||
```promql
|
||
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](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/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` 填充任一侧缺失序列):
|
||
|
||
```promql
|
||
method_code:http_errors:rate5m{status="500"} / ignoring(code) fill(0) method:http_requests:rate5m
|
||
```
|
||
|
||
返回各 method 状态码 500 请求占比。`put` 与 `del` 条目因在另一侧无匹配序列,现以填充默认值 `0` 纳入结果:
|
||
|
||
```text
|
||
{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](https://prometheus.io/docs/prometheus/latest/querying/operators/)
|
||
|
||
---
|
||
|
||
## 第 3 章 函数全表
|
||
|
||
> 引自:[Query functions](https://prometheus.io/docs/prometheus/latest/querying/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 组合完全不存在时间序列」的场景做告警 |
|
||
|
||
它会尝试从输入向量**智能推导**输出标签:
|
||
|
||
```promql
|
||
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` |
|
||
| 用途 | 对「某组合在**一段时间内**都不存在序列」做告警 |
|
||
|
||
```promql
|
||
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 样本被忽略、不出现在结果中。
|
||
|
||
```promql
|
||
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 样本被忽略。
|
||
|
||
```promql
|
||
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()` 指定时间窗口。
|
||
|
||
**示例**:
|
||
|
||
```promql
|
||
# 经典直方图
|
||
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()` 相同。
|
||
- 第二个字符串参数指定用于在结果中区分不同分位数的**标签名**。
|
||
|
||
```promql
|
||
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 样本行为一致。
|
||
|
||
```promql
|
||
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 行为一致。
|
||
|
||
```promql
|
||
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 写法**:
|
||
|
||
```promql
|
||
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` 简化:
|
||
|
||
```promql
|
||
info(rate(http_server_request_duration_seconds_count[2m]), {k8s_cluster_name=~".+"})
|
||
```
|
||
|
||
省略第二参数即加**全部** data 标签:
|
||
|
||
```promql
|
||
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](https://prometheus.io/docs/prometheus/latest/querying/functions/)
|
||
|
||
---
|
||
|
||
## 第 4 章 查询示例集
|
||
|
||
> 引自:[Query examples](https://prometheus.io/docs/prometheus/latest/querying/examples/)
|
||
|
||
本章完整收录官方 examples 页面的全部场景,每条示例配解释。
|
||
|
||
### 4.1 简单时序选择
|
||
|
||
#### 4.1.1 按指标名选择
|
||
|
||
```promql
|
||
http_requests_total
|
||
```
|
||
|
||
返回所有 metric 为 `http_requests_total` 的时间序列。
|
||
|
||
> 💡 补充:这是一条**裸 metric name selector**。在生产环境中它可能展开为数千条不同标签的时间序列——这正是 1.10 节强调「先在表格视图构建查询」的典型场景。
|
||
|
||
#### 4.1.2 按多个标签过滤
|
||
|
||
```promql
|
||
http_requests_total{job="apiserver", handler="/api/comments"}
|
||
```
|
||
|
||
返回带给定 `job` 与 `handler` 标签的所有 `http_requests_total` 时间序列。
|
||
|
||
#### 4.1.3 取一段时间范围(range vector)
|
||
|
||
```promql
|
||
http_requests_total{job="apiserver", handler="/api/comments"}[5m]
|
||
```
|
||
|
||
为同一向量返回一整段时间范围(此处为截至查询时间的 5 分钟),使其成为 **range vector**。
|
||
|
||
**注意**:结果为 range vector 的表达式**不能直接绘图**,需在 expression browser 的表格("Console")视图中查看。
|
||
|
||
#### 4.1.4 正则匹配 job
|
||
|
||
```promql
|
||
http_requests_total{job=~".*server"}
|
||
```
|
||
|
||
用正则表达式仅选择 name 匹配某模式的 jobs(此处为所有以 `server` 结尾的 jobs)。
|
||
|
||
#### 4.1.5 反向正则排除状态码
|
||
|
||
```promql
|
||
http_requests_total{status!~"4.."}
|
||
```
|
||
|
||
选择除 4xx 外的所有 HTTP 状态码。
|
||
|
||
### 4.2 子查询示例
|
||
|
||
#### 4.2.1 5 分钟 rate 的 30 分钟序列
|
||
|
||
```promql
|
||
rate(http_requests_total[5m])[30m:1m]
|
||
```
|
||
|
||
返回 `http_requests_total` 过去 30 分钟的 5-minute rate,分辨率 1 分钟。
|
||
|
||
#### 4.2.2 嵌套子查询
|
||
|
||
```promql
|
||
max_over_time(deriv(rate(distance_covered_total[5s])[30s:5s])[10m:])
|
||
```
|
||
|
||
嵌套 subquery 示例。`deriv` 函数的 subquery 使用**默认 resolution**。注意不必要地使用 subqueries 是**不明智**的。
|
||
|
||
> 引自:[Query examples](https://prometheus.io/docs/prometheus/latest/querying/examples/)
|
||
|
||
### 4.3 函数与运算符实战
|
||
|
||
#### 4.3.1 每秒请求速率
|
||
|
||
```promql
|
||
rate(http_requests_total[5m])
|
||
```
|
||
|
||
返回所有 `http_requests_total` 时间序列在过去 5 分钟测得的每秒速率。
|
||
|
||
#### 4.3.2 按 job 聚合减少序列数
|
||
|
||
假设所有 `http_requests_total` 时间序列都有 `job`(按 job 名 fanout)与 `instance`(按 job 实例 fanout)标签,可对全部实例的 rate 求和以减少输出序列数但保留 `job` 维度:
|
||
|
||
```promql
|
||
sum by (job) (
|
||
rate(http_requests_total[5m])
|
||
)
|
||
```
|
||
|
||
#### 4.3.3 二元运算:未使用内存
|
||
|
||
若有两个具相同维度标签的不同指标,可对其施加二元运算符,两侧标签集相同的元素会匹配并传播到输出。例如返回(虚构 cluster scheduler 暴露的指标下)每个实例的未使用内存(MiB):
|
||
|
||
```promql
|
||
(instance_memory_limit_bytes - instance_memory_usage_bytes) / 1024 / 1024
|
||
```
|
||
|
||
同一表达式按 application 求和可写为:
|
||
|
||
```promql
|
||
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"` 标签):
|
||
|
||
```promql
|
||
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 统计运行实例数:
|
||
|
||
```promql
|
||
count by (app) (instance_cpu_time_ns)
|
||
```
|
||
|
||
#### 4.3.6 limitk:探查指标的标签
|
||
|
||
若为探查某指标以获得其标签(例如便于随后对其中一些聚合),可使用:
|
||
|
||
```promql
|
||
limitk(10, app_foo_metric_bar)
|
||
```
|
||
|
||
#### 4.3.7 limit_ratio:均匀采样约 10%
|
||
|
||
若希望返回的时间序列采样更均匀,可用以下方式获取约 10%:
|
||
|
||
```promql
|
||
limit_ratio(0.1, app_foo_metric_bar)
|
||
```
|
||
|
||
> 💡 补充:`limitk` 与 `limit_ratio` 均为实验性聚合运算符,须 `--enable-feature=promql-experimental-functions` 启用(见 2.8 节)。二者都以**确定性伪随机**方式选取子集,与样本类型无关。
|
||
|
||
> 引自:[Query examples](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/prometheus/latest/querying/api/)
|
||
|
||
当前稳定 HTTP API 挂在 Prometheus 服务器的 `/api/v1`,非破坏性新增都加在该前缀下。
|
||
|
||
### 5.1 通用格式与响应信封
|
||
|
||
#### 5.1.1 OpenAPI 规范
|
||
|
||
```text
|
||
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 瞬时查询
|
||
|
||
```text
|
||
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>}`。
|
||
|
||
**示例**:
|
||
|
||
```bash
|
||
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 范围查询
|
||
|
||
```text
|
||
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`**。
|
||
|
||
**示例**:
|
||
|
||
```bash
|
||
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 格式化表达式
|
||
|
||
```text
|
||
GET /api/v1/format_query
|
||
POST /api/v1/format_query
|
||
```
|
||
|
||
- 参数仅 `query=<string>`。
|
||
- data 为格式化后的字符串,**注释会被移除**。
|
||
|
||
**示例**:`query=foo/bar` → `"foo / bar"`。
|
||
|
||
#### 5.2.5 解析表达式为 AST(实验性)
|
||
|
||
```text
|
||
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)**:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"metric": {},
|
||
"values": [[<unix_time>, "<sample_value>"], ...],
|
||
"histograms": [[<unix_time>, <histogram>], ...]
|
||
}
|
||
]
|
||
```
|
||
|
||
- 每条序列可有 `values`、`histograms` 或两者;同一时间戳只会有一个 float 或 histogram 样本。
|
||
- 序列按 `metric` 排序,`sort`/`sort_by_label` 对范围向量无效。
|
||
|
||
**Instant vectors(vector)**:
|
||
|
||
```json
|
||
[
|
||
{
|
||
"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>`**:
|
||
|
||
```json
|
||
{
|
||
"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 按标签匹配器查序列
|
||
|
||
```text
|
||
GET /api/v1/series
|
||
POST /api/v1/series
|
||
```
|
||
|
||
| 参数 | 说明 |
|
||
|:-----|:-----|
|
||
| `match[]=<series_selector>` | **可重复,至少一个** |
|
||
| `start`、`end` | 时间范围 |
|
||
| `limit` | 可选,`0` 禁用 |
|
||
|
||
data 为对象数组,每项是标识序列的标签名/值对。`start`/`end` 只是**近似**,结果可能含区间内无样本的序列。
|
||
|
||
**示例**:
|
||
|
||
```bash
|
||
curl 'http://localhost:9090/api/v1/series' --data-urlencode 'match[]=up' --data-urlencode 'match[]=process_start_time_seconds{job="prometheus"}'
|
||
```
|
||
|
||
#### 5.3.2 标签名列表
|
||
|
||
```text
|
||
GET /api/v1/labels
|
||
POST /api/v1/labels
|
||
```
|
||
|
||
参数:`start`、`end`、`match[]`(均可选)、`limit`。data 为字符串标签名数组(示例含 `__name__`、`job`、`instance`、`le`、`quantile` 等)。
|
||
|
||
#### 5.3.3 标签值列表
|
||
|
||
```text
|
||
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 名与值(实验性,流式)
|
||
|
||
```text
|
||
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(实验性)
|
||
|
||
```text
|
||
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 抓取池列表
|
||
|
||
```text
|
||
GET /api/v1/scrape_pools
|
||
```
|
||
|
||
data 为 `{"scrapePools": ["prometheus", "node_exporter", "blackbox"]}`。*v2.42 新增*
|
||
|
||
#### 5.4.2 抓取池配置(实验性,仅 Web UI 用)
|
||
|
||
```text
|
||
GET /api/v1/scrape_pools/config?scrapePool=<scrape_pool_name>
|
||
```
|
||
|
||
- `scrapePool` **必填**。
|
||
- 返回该池生效配置(含 `scrape_config_files` 加载的内容),**凭证与密钥被脱敏**。
|
||
- data 为 `{"yaml": "..."}`。
|
||
|
||
#### 5.4.3 目标总览
|
||
|
||
```text
|
||
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 用)
|
||
|
||
```text
|
||
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 规则列表
|
||
|
||
```text
|
||
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 活跃告警
|
||
|
||
```text
|
||
GET /api/v1/alerts
|
||
```
|
||
|
||
data.alerts[] 每项含 `activeAt`、`annotations`、`labels`、`state`、`value`。稳定性保证同样**弱于** API v1。
|
||
|
||
### 5.6 指标元数据端点
|
||
|
||
#### 5.6.1 目标指标元数据(实验性)
|
||
|
||
```text
|
||
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 指标元数据(实验性)
|
||
|
||
```text
|
||
GET /api/v1/metadata
|
||
```
|
||
|
||
参数:`limit`、`limit_per_metric`、`metric`。data 为对象,键为指标名、值为该指标跨所有目标的唯一元数据对象列表(同一指标可能存在多个不同 `help` 的条目)。
|
||
|
||
### 5.7 Alertmanager 与状态端点
|
||
|
||
#### 5.7.1 Alertmanager 发现
|
||
|
||
```text
|
||
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
|
||
|
||
```text
|
||
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
|
||
|
||
```text
|
||
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
|
||
|
||
```text
|
||
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
|
||
|
||
```text
|
||
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](https://prometheus.io/docs/prometheus/latest/querying/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](https://prometheus.io/docs/guides/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`:
|
||
|
||
```yaml
|
||
global:
|
||
scrape_interval: 15s
|
||
evaluation_interval: 15s
|
||
query_log_file: /prometheus/query.log
|
||
scrape_configs:
|
||
- job_name: 'prometheus'
|
||
static_configs:
|
||
- targets: ['localhost:9090']
|
||
```
|
||
|
||
reload:
|
||
|
||
```bash
|
||
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:
|
||
|
||
```text
|
||
# 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 查询字段概览
|
||
|
||
```json
|
||
{
|
||
"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:
|
||
|
||
```json
|
||
{
|
||
"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 名):
|
||
|
||
```json
|
||
{
|
||
"ruleGroup": {
|
||
"file": "rules.yml",
|
||
"name": "partners"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 6.4 日志轮转注意事项
|
||
|
||
- **Prometheus 自身不会轮转 query log**,需用**外部工具**,如 `logrotate`(多数 Linux 发行版默认启用)。
|
||
- 示例 `/etc/logrotate.d/prometheus`:
|
||
|
||
```text
|
||
/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](https://prometheus.io/docs/practices/histograms/)
|
||
|
||
### 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 中暴露为:
|
||
|
||
```json
|
||
{
|
||
"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`:
|
||
|
||
```promql
|
||
histogram_sum(rate(http_request_duration_seconds[5m]))
|
||
/
|
||
histogram_count(rate(http_request_duration_seconds[5m]))
|
||
```
|
||
|
||
等价短写法:
|
||
|
||
```promql
|
||
histogram_avg(rate(http_request_duration_seconds[5m]))
|
||
```
|
||
|
||
#### 7.3.2 summary / classic
|
||
|
||
用 `_sum` / `_count` 序列:
|
||
|
||
```promql
|
||
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 之后、相除之前**聚合(与底层类型无关):
|
||
|
||
```promql
|
||
# 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 计算落在某区间的比例
|
||
|
||
```promql
|
||
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 的表达式截然不同
|
||
|
||
```promql
|
||
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)**:
|
||
|
||
```promql
|
||
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**(**必须**在精确边界有桶,因累积桶表达式不同):
|
||
|
||
```promql
|
||
(
|
||
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 的分位数几乎无意义,取平均统计上荒谬:
|
||
|
||
```promql
|
||
avg(http_request_duration_seconds{quantile="0.95"}) // BAD!
|
||
```
|
||
|
||
histogram 则可聚合:
|
||
|
||
```promql
|
||
# 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` 再求和**:
|
||
|
||
```promql
|
||
# 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](https://prometheus.io/docs/guides/utf8/)
|
||
|
||
### 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 字符集的名称。
|
||
|
||
**全局设置**:
|
||
|
||
```yaml
|
||
global:
|
||
metric_name_validation_scheme: legacy
|
||
```
|
||
|
||
**按 scrape config 设置**:
|
||
|
||
```yaml
|
||
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` 段更改:
|
||
|
||
```text
|
||
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 一致。凡标 `> 💡 补充:` 的段落为结合上下文的经验性说明,非官方原文。
|
||
|