Prometheus查询

半兽人 发表于: 2019-07-23   最后更新时间: 2020-10-22 10:46:38  
{{totalSubscript}} 订阅, 5,706 游览

Prometheus提供一个函数式的表达式语言,可以使用户实时地查找和聚合时间序列数据。表达式计算结果可以在图表中展示,也可以在Prometheus表达式浏览器中以表格形式展示,或者作为数据源,以HTTP API的方式提供给外部系统使用。

例子

本文仅供参考, 这里先举几个容易上手的例子。

表达式语言数据类型

在Prometheus的表达式语言中,任何表达式或者子表达式都可以归为四种类型:

  • instant vector 瞬时向量 - 它是指在同一时刻,抓取的所有度量指标数据。这些度量指标数据的key都是相同的,也即相同的时间戳。
  • range vector 范围向量 - 它是指在任何一个时间范围内,抓取的所有度量指标数据。
  • scalar 标量 - 一个简单的数字浮点值
  • string 字符串 - 一个简单的字符串值;目前未使用

依赖于使用场景(例如:图表 vs. 表格),根据用户所写的表达式,仅仅只有一部分类型才适用这种表达式。例如:瞬时向量类型是唯一可以直接在图表中使用的。

Literals

字符串

字符串可以用单引号双引号或者反引号表示。

PromQL遵循与Go相同的转义规则。在单引号,双引号中,反斜杠成为了转义字符,后面可以跟着a,b,f,n,r,t,v或者\。 可以使用八进制(\nnn)或者十六进制(\xnn, \unnnn\Unnnnnnnn)提供特定字符。

在反引号内不处理转义字符。与Go不同,Prom不会丢弃反引号中的换行符。例如:

"this is a string"
'these are unescaped: \n \\ \t'
`these are not unescaped: \n ' " \t`

浮点数

Scalar float值可以被写成整数或浮点数的格式(为了更好的阅读性,只包含空格)。

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

Examples:

23
-2.43
3.4e-9
0x8f
-Inf
NaN

时间序列选择器 (Time series Selectors)

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

瞬时向量选择器可以对一组时间序列数据进行筛选,并给出结果中的每个结果键值对(时间戳-样本值): 最简单的是,只有一个度量名称被指定。在一个瞬时向量中这个结果包含有这个度量指标名称的所有样本数据键值对。

下面这个例子选择所有时间序列度量名称为http_requests_total的样本数据:

http_requests_total

通过在度量指标后面增加{}一组标签可以进一步地过滤这些时间序列数据。

下面这个例子选择了度量指标名称为http_requests_total,且一组标签为job=prometheus, group=canary:

http_requests_total{job="prometheus",group="canary"}

可以采用不匹配的标签值,或者用正则表达式,操作如下所示:

  • =: 精确地匹配标签给定的值
  • !=: 不等于给定的标签值
  • =~: 正则表达匹配给定的标签值
  • !~: 给定的标签值不符合正则表达式

例如:度量指标名称为http_requests_total,正则表达式匹配标签environmentstaging, testing, development的值,且http请求方法不等于GET

http_requests_total{environment=~"staging|testing|development", method!="GET"}

匹配空标签值的标签匹配器也可以选择没有设置任何标签的所有时间序列数据。正则表达式完全匹配。

向量选择器必须指定一个度量指标名称或者至少不能为空字符串的标签值。以下表达式是非法的:

{job=~".*"} #Bad!

上面这个例子既没有度量指标名称,标签选择器也可以正则匹配空标签值,所以不符合向量选择器的条件

相反地,下面这些表达式是有效的,第一个一定有一个字符。第二个有一个有用的标签method

{job=~".+"}  # Good!
{job=~".*", method="get"} # Good!

标签匹配器能够被应用到度量指标名称,使用内部的__name__标签筛选度量指标名称。例如:表达式http_requests_total等价于{__name__="http_requests_total"}。其他的匹配器,如:= ( !=, =~, !~)都可以使用。下面的表达式选择了度量指标名称以job:开头的时间序列数据:

{__name__=~"^job:.*"}

度量标准名称不得为关键字 bool, on, ignoring, group_leftgroup_right.。 以下表达式是非法的:

on{} # Bad!

此限制的解决方法是使用__name__标签:

{__name__="on"} # Good!

范围向量选择器 (Range Vector Selectors)

范围向量类似瞬时向量, 不同在于,它们从当前实例选择样本范围区间。在语法上,时间长度被追加在向量选择器尾部的方括号[]中,用以指定对于每个样本范围区间中的每个元素应该抓取的时间范围样本区间。

时间长度有一个数值决定,后面可以跟下面的单位:

  • ms - milliseconds
  • s - seconds
  • m - minutes
  • h - hours
  • d - days
  • w - weeks
  • y - years

在下面这个例子中, 选择过去5分钟内,度量指标名称为http_requests_total, 标签为job="prometheus"的时间序列数据:

http_requests_total{job="prometheus"}[5m]

偏移修饰符 (Offset modifier)

这个offset偏移修饰符允许在查询中改变单个瞬时向量和范围向量中的时间偏移

例如,下面的表达式返回相对于当前时间的前5分钟时的时刻, 度量指标名称为http_requests_total的时间序列数据:

http_requests_total offset 5m

注意:offset偏移修饰符必须直接跟在选择器后面,例如:

sum(http_requests_total{method="GET"} offset 5m) // GOOD.

然而,下面这种情况是不正确的

sum(http_requests_total{method="GET"}) offset 5m // INVALID.

offset在范围向量上和瞬时向量用法一样的。下面这个返回了相对于当前时间的前一周时,过去5分钟的度量指标名称为http_requests_total的速率:

rate(http_requests_total[5m] offset 1w)

操作符

Prometheus支持二元和聚合操作符。详见表达式语言操作符

函数

Prometheus提供了一些函数列表操作时间序列数据。详见表达式语言函数

陷阱

插值和陈旧

当运行查询后,独立于当前时刻被选中的时间序列数据所对应的时间戳,这个时间戳主要用来进行聚合操作,包括sum, avg等,大多数聚合的时间序列数据所对应的时间戳没有对齐。由于它们的独立性,我们需要在这些时间戳中选择一个时间戳,并已这个时间戳为基准,获取小于且最接近这个时间戳的时间序列数据。

如果5分钟内,没有获取到任何的时间序列数据,则这个时间戳不会存在。那么在图表中看到的数据都是在当前时刻5分钟前的数据。

注意:差值和陈旧处理可能会发生变化。详见https://github.com/prometheus/prometheus/issues/398https://github.com/prometheus/prometheus/issues/581

避免慢查询和高负载

如果一个查询需要操作非常大的数据量,图表绘制很可能会超时,或者服务器负载过高。因此,在对未知数据构建查询时,始终需要在Prometheus表达式浏览器的表格视图中构建查询,直到结果是看起来合理的(最多为数百个,而不是数千个)。只有当你已经充分过滤或者聚合数据时,才切换到图表模式。如果表达式的查询结果仍然需要很长时间才能绘制出来,则需要通过记录规则重新清洗数据。

api_http_requests_total这样简单的度量指标名称选择器,可以扩展到具有不同标签的数千个时间序列中,这对于Prometheus的查询语言是非常重要的。还要记住,聚合操作即使输出的结果集非常少,但是它会在服务器上产生负载。这类似于关系型数据库查询可一个字段的总和,总是非常缓慢。

更新于 2020-10-22

查看Prometheus更多相关的文章或提一个关于Prometheus的问题,也可以与我们一起分享文章