Prometheus提供了一种称为PromQL(Prometheus查询语言)的功能查询语言,使用户可以实时选择和汇总时间序列数据。 表达式的结果既可以图形显示,也可以在Prometheus的表达式浏览器中显示为表格数据,也可以由外部系统通过HTTP API使用。
Examples
本文档仅供参考。 对于学习而言,从几个示例开始可能会更容易。
Expression language data types 表达式语言的数据类型
在 prometheus 表达式语言中,表达式或子表达式可以转化为下面 4 种类型之一
* Instant vector 瞬时向量 - 一组时间序列,每个时间序列包含一个样本,所有样本共享相同的时间戳
* Range vector 范围向量 - 一组时间序列,其中包含每个时间序列随时间的一系列数据点
* Scalar 标量 - 一个简单的数字浮点值
* String - 一个简单的字符串值; 目前未使用
根据用例(例如在绘制图形或显示表达式的输出时),由于用户指定的表达式的结果,其中只有某些类型是合法的。 例如,返回瞬时向量的表达式是唯一可以直接绘制图形的类型。
Literals 文字
String literals 字符串文字
可以在单引号,双引号或反引号中将字符串指定为文字。
PromQL遵循与Go相同的转义规则。 在单引号或双引号中,反斜杠开始一个转义序列,其后可以跟a,b,f,n,r,t,v或\。 可以使用八进制(\ nnn)或十六进制(\ xnn,\ unnnn和\ Unnnnnnnn)提供特定字符。
反引号内不会处理任何转义。 与Go不同,Prometheus不会在反引号内丢弃换行符。
Example:
```txt
"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`
```
Float literals
标量浮点值可以从字前面上写为[-](数字)[.(数字)]形式的数字。
```sql
-2.43
```
Time series Selectors 时间序列选择
Instant vector selectors 瞬时向量选择器
瞬时向量选择器允许在给定的时间戳(瞬时)下选择一组时间序列和每个样本的单个样本值:以最简单的形式,仅指定度量名称。 这将让一个即时向量,包含具有该度量名称的所有时间序列的元素。
本示例选择所有具有http_requests_total指标名称的时间序列:
```sql
http_requests_total
```
可以通过在大括号({})中附加一组匹配的标签来进一步过滤这些时间序列。
本示例仅选择那些具有http_requests_total度量标准名称的时间序列,这些时间序列还将其工作标签设置为prometheus,其组标签设置为canary:
```sql
http_requests_total{job="prometheus",group="canary"}
```
也可以否定地匹配标签值,或将标签值与正则表达式匹配。 存在以下标签匹配运算符:
* = : 选择与提供的字符串完全相同的标签。
* != : 选择与提供的字符串不同的标签。
* =~ : 选择与提供的字符串进行正则表达式匹配的标签。
* !~ : 选择不与提供的字符串进行正则表达式匹配的标签。
例如,这将选择所有http_requests_total时间序列用于暂存,测试和开发环境以及除GET之外的HTTP方法。
```sql
http_requests_total{environment=~"staging|testing|development",method!="GET"}
```
匹配空标签值的标签匹配器还会选择所有根本没有设置特定标签的时间序列。 正则表达式匹配完全锚定。 同一标签名称可能有多个匹配器。
向量选择器必须指定一个名称或至少一个与空字符串不匹配的标签匹配器。 以下表达式是非法的:
```sql
{job=~".*"} # Bad!
```
相反,这些表达式都是有效的,因为它们都具有与空标签值不匹配的选择器。
```sql
{job=~".+"} # Good!
{job=~".*",method="get"} # Good!
```
通过与内部__name__标签进行匹配,标签匹配器也可以应用于度量标准名称。 例如,表达式http_requests_total等效于{__name __ =“ http_requests_total”}。 也可以使用除=(!=,=〜,!〜)以外的匹配器。 以下表达式选择名称以 job: 开头的所有度量:
```sql
{__name__=~"job:.*"} # 以 job: 开头
``
Prometheus中的所有正则表达式都使用RE2语法[https://github.com/google/re2/wiki/Syntax]。
Range Vector Selectors
范围向量文字的工作方式与瞬时向量文字相同,不同之处在于它们从当前即时选择回采样范围。 语法上,将范围持续时间附加在向量选择器末尾的方括号([])中,以指定应为每个结果范围向量元素提取多远的时间值。
持续时间以数字指定,后面紧跟以下单位之一:
* s - seconds
* m - minutes
* h - hours
* d - days
* w - weeks
* y - years
在此示例中,我们选择所有时间序列在最近5分钟内记录的所有值,这些值的度量标准名称为http_requests_total且作业标签设置为prometheus:
```sql
http_requests_total{job="prometheus"}[5m]
```
Offset modifier
offset修饰符允许更改查询中各个瞬时矢量和范围矢量的时间偏移。
例如,以下表达式返回相对于当前查询评估时间过去5分钟的http_requests_total值:
```sql
http_requests_total offset 5m
```
请注意,offset修饰符始终需要立即跟随选择器,即以下内容将是正确的:
```sql
sum(http_requests_total{method="GET"} offset 5m) // GOOD.
```
尽管以下内容将不正确:
```sql
sum(http_requests_total{method="GET"}) offset 5m // INVALID.
```
范围向量的工作原理相同。 这将返回http_requests_total一周前的5分钟比率:
```sql
rate(http_requests_total[5m] offset 1w)
```
Subquery
子查询允许您针对给定的范围和分辨率运行瞬时查询。 子查询的结果是范围向量。
Syntax: <instant_query> '[' <range> ':' [<resolution>] ']' [ offset <duration> ]
* <resolution> is optional. Default is the global evaluation interval.
Operators
Prometheus支持许多二进制和聚合运算符。 这些在表达式语言运算符页面中进行了详细描述。[https://prometheus.io/docs/prometheus/latest/querying/operators/]
Functions
Prometheus支持多种对数据进行操作的功能。 这些在表达语言功能页面中进行了详细描述。
Comments
PromQL支持以#开头的行注释。 例:
```sql
# This is a comment
```
Gotchas 缺陷
Staleness 陈旧的
运行查询时,将选择采样数据的时间戳,而不依赖于实际的当前时间序列数据。 这主要是为了支持诸如聚合(sum, avg 等)的情况,其中多个聚合时间序列未在时间上精确对齐。 由于它们的独立性,Prometheus需要为每个相关时间序列在那些时间戳上分配一个值。 只需在此时间戳之前获取最新样本即可。
如果目标刮擦或规则评估不再返回先前存在的时间序列的样本,则该时间序列将被标记为陈旧。 如果删除了目标,则其先前返回的时间序列将在不久后标记为陈旧。
如果在某个时间序列标记为陈旧后以采样时间戳评估查询,则该时间序列不会返回任何值。 如果随后在该时间序列中摄取了新样本,则它们将照常返回。
如果在采样时间戳记之前5分钟未找到样本(默认情况下),则该时间序列在此时间点不会返回任何值。 这实际上意味着,在最新采集的样本超过5分钟或标记为陈旧之后,时间序列会从图表中“消失”。
对于在刮擦中包含时间戳的时间序列,不会标记为陈旧。 在这种情况下,仅会应用5分钟的阈值。
Avoiding slow queries and overloads 避免慢查询和重载
如果查询需要处理大量数据,则对其进行图形化处理可能会超时或使服务器或浏览器超载。 因此,在对未知数据构建查询时,请始终开始在Prometheus表达式浏览器的表格视图中构建查询,直到结果集看起来合理为止(最多数百个而不是数千个时间序列)。 仅当您充分过滤或汇总了数据后,才切换到图形模式。 如果该表达式仍无法花费很长时间来绘制即席图形,请通过记录规则将其预先记录。
这对于Prometheus的查询语言尤其重要,在该语言中,像api_http_requests_total这样的裸指标名称选择器可以扩展到成千上万个具有不同标签的时间序列。 还请记住,即使输出只是少量时间序列,在多个时间序列上聚合的表达式也会在服务器上产生负载。 这类似于将关系数据库中的列的所有值相加会很慢,即使输出值只是一个数字也是如此。