首页 PromQL
文章
取消

PromQL

一.PromQL

1.1.基本查询

匹配查询

PromQL的查询现在只要支持两种查询模式:完全匹配和正则匹配。

  1. 完全匹配

支持使用 = 和 != 的两种完全匹配模式

通过label=xxx和label!=xxx的两种模式进行完全匹配。

  1. 正则匹配

使用格式label=~regx表示选择符合正则表达式的,label=!~regx则表示排除

1.2.范围查询

直接使用时间序列的指标名进行查询的时候查询出来的东西一个瞬时向量值, 也就是查询出来的只是当前的这个时间序列的最新的一个值,如果需要查询这个时间序列指标的一个时间范围内的数据的话。就需要使用到区间向量表达式

瞬时向量表达式与区间向量表达式的区别就在于区间向量表达式需要指定一个时间区间,时间范围通过选择器 []进行定义

1
serierTimeMetrics{label=xxx}[5m] //表示查询这个指标5分钟的向量值

区间向量表达式中的PromQL的时间范围选择器支持的时间单位有:s, m, h, d, w, y

1.2.1.位移查询

前面说的瞬时向量查询和区间向量查询都是基于当前的时间为准的,如果我要查询5分钟以前的瞬时向量值的话就需要用到位移操作。

PromQL中的位移操作关键字是offerset。

1
serierTimeMetrics{label=xxx}[5m] offset 1d //表示查询这个指标一天前这个时候5分钟的向量区间指标值集合

1.2.2.聚合查询

一般来说在特征标签并非唯一的时候会返回多个满足条件的时间序列的值,PromQL支持通过聚合的操作将这些时间序列聚合成一个新的时间序列值。

聚合可以通过一些函数和 by 关键字做聚合操作。

1.3.表达式合法性

PromQL语法的基本要求是:至少指定一个时间序列名或者有一个不会匹配到空的标签选择器。

同时,除了使用<metric name>{label=value}的形式以外,我们还可以使用内置的__name__标签来指定监控指标名称。

http_request_total # 合法
http_request_total{} # 合法
{method="get"} # 合法

{label=".*"}  #非法,可匹配空标签

{__name__=~"http_request_total"} # 合法
{__name__=~"node_disk_bytes_read|node_disk_bytes_written"} # 合法

1.4.标量与字符串

上面说这些带有时间性质的都称之为向量。没有事件性质就称之为标量。查询出来的向量指标的值如果想转换成标量指标值的话可以通过函数scalar()将向量转成一个标量。

字符串就是直接用一个双引号括起来的字符串查询,返回的就是一个字符串。

1.5.操作符

PromQL支持的操作符包括,数学运算符,逻辑操作符, 布尔运算符。

1.5.1.数学运算

PromQL支持的数学运算符包括:

  • + 加
  • - 减
  • * 乘
  • / 除
  • % 求余
  • ^ 幂

PromQL中的数学运算主要有两种。向量与标量运算。向量与向量的运算

  1. 向量与标量做运算

向量与标量做运算的时候,会先求出一组向量数据, 然后这个标量依次与向量数据做运算得出一组新的向量数据。

此时的向量数据的 时间序列名与标签不变。

  1. 向量与向量做运算

向量与向量做运算的过程相对复杂点。主要有三个步骤:

  1. 对运算表达式两边的向量元素完全匹配的时间序列做运算得出一个新的值
  2. 如果两边的表达式有一边没匹配上的直接丢弃,不参与运算
  3. 运算结果的新的时间序列将不包含指标名称,只有{label=xxx label2=xxx},也就是内置的__name__在向量运算过后将会被丢弃。
1
2
3
4
5
6
表达式:
node_disk_bytes_written + node_disk_bytes_read

结果:
{device="sda",instance="localhost:9100",job="node_exporter"}=>1634967552@1518146427.807 + 864551424@1518146427.807
{device="sdb",instance="localhost:9100",job="node_exporter"}=>0@1518146427.807 + 1744384@1518146427.807

1.5.2.布尔运算

目前,Prometheus支持以下布尔运算符如下:

  • == (相等)
  • != (不相等)
  • > (大于)
  • < (小于)
  • >= (大于等于)
  • <= (小于等于)

向量与标量运算

与数学运算类似,true保留, false丢弃

向量与向量运算

与数学运算类似, true保留,false丢弃, 没匹配上的也丢弃。

使用bool修饰符改变布尔运算的行为

前面说了, PromQL中的布尔运算的默认行为为, true暴露样本指标, false丢弃该指标。

那么如果是需要,如果是true返回1, false返回0

1
2
3
4
5
http_requests_total > bool 1000 #http_requests_total是否大于 1000,大于返回1,小于返回0。

结果:
http_requests_total{code="200",handler="query",instance="localhost:9090",job="prometheus",method="get"}  1
http_requests_total{code="200",handler="query_range",instance="localhost:9090",job="prometheus",method="get"}  0

注意标量之间的表达式必须使用bool修饰符。

集合运算符

目前,Prometheus支持以下集合运算符:

  • and (并且)
  • or (或者)
  • unless (排除)

vector1 and vector2 会产生一个由vector1的元素组成的新的向量。该向量包含vector1中完全匹配vector2中的元素组成。

vector1 or vector2 会产生一个新的向量,该向量包含vector1中所有的样本数据,以及vector2中没有与vector1匹配到的样本数据。

vector1 unless vector2 会产生一个新的向量,新向量中的元素由vector1中没有与vector2匹配的元素组成。

在PromQL操作符中优先级由高到低依次为:

  1. ^
  2. *, /, %
  3. +, -
  4. ==, !=, <=, <, >=, >
  5. and, unless
  6. or

###向量与向量运算的匹配模式详解**

当向量与向量做运算的时候, 运算规则为:

依次找到与左边的元素完全匹配的右边的元素,如果没匹配到则直接丢弃此时间序列元素。

匹配模式就需要区分, 是1对1还是1对多,还是多对1。

####一对一**

默认情况下就是进行一对一的匹配操作,右边完全匹配左边(包括标签的个数与key-value),匹配到的就运算。

在两边有的标签不需要匹配或者只需要匹配某些标签的时候可以通过 on(label list) 或者 ignore(label list) 的语法进行限定label的匹配行为。

1
2
向量匹配表达式 操作符 ignore(label list) 向量匹配表达式
向量匹配表达式 操作符 on(label list) 向量匹配表达式

###多对一与一对多**

多对一与一对多都是指 “一” 侧的每一个向量可以与 另一侧的多个元素匹配的情况。在这种情况下,必须使用group_left和group_right来确定哪一边具有更多的角色。

1
2
3
4
<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>

##聚合操作**

PromQL内置的聚合函数包括:

  • sum (求和)
  • min (最小值)
  • max (最大值)
  • avg (平均值)
  • stddev (标准差)
  • stdvar (标准方差)
  • count (计数)
  • count_values (对value进行计数)
  • bottomk (后n条时序)
  • topk (前n条时序)
  • quantile (分位数)

聚合操作语法:

1
<聚合操作符>([parameter,] <向量表达式>) [without|by (<label list>)]

其中只有count_values, quantile, topk, bottomk支持参数(parameter)。

##内置函数**

###increase(vertor range)**

计算一个counter指标的增长量。获取此区间的第一个向量值与最后一个向量值相减

rate(vertor range)

计算一个时间窗口内的每秒增长速率,此区间的第一个向量值与最后一个向量值相减,除以对应的时间

缺点:存在“长尾反应”也就是在这个时间窗口内的

###irate(vertor range)**

类似rate,但是是使用区间向量中最后的两个样本数据来计算向量的增长速率,除以时间。

分位数

什么是分位数?

prometheus中百分位数成为quantile, 百分位数指的是小于某个特定数值的采样达到的百分比。假设0.9-quantile值为100,则表示小于100的样本数据达到了90%。

统计方式

prometheus分别支持两种方式统计分位数,一个是summary,一个是histogram

summary是在客户端进行统计,histogram是在服务端进行统计

summary

summary是在客户端就已经指定了统计的分位数 http_request_duration_millisecond_count

http_request_duration_millisecond_sum

http_request_duration_millisecond{quanile=}

http_request_duration_millisecond{quanile=}

http_request_duration_millisecond{quanile=}

并且不支持对多个实例做quantile的聚合计算,例如A实例的0.8-quantile是50,B实例的0.9-quantile是90,总体的0.9-quantile如果单纯的(50+90)/2=70,是错误的。对多个实例做分位数的聚合计算只能用histogram。

###histogram**

histogram在客户端指定的是样本统计的区间

http_request_duration_millisecond_count

http_request_duration_millisecond_sum

http_request_duration_millisecond{le=}

http_request_duration_millisecond{le=}

http_request_duration_millisecond{le=}

histogram统计出来的bucket,后面一个bucket的样本值是包含前面的bucket样本值的,计算quantile使用的是histogram_quantile函数,计算一段时间的分位数可以使用histogram_quantile(0.9, rate(vertor)[timerange]).

histogram的分位数肯定是在某一个区间内, 如果这个区间的范围很大,那计算出来的这个数据很可能就会出现反直觉的现象,就是分位数比最大值还大。

afa上的交易时间bucket的精度是,白毫秒内的误差为10毫秒,千毫秒内的误差为100毫秒,万毫秒内的误差为1000毫秒。

也就是上面的出现反直觉的现象的时候的误差值不会超过这个值

histogram统计分位数是根据线性插值法进行判定分位的bucket区间的,例如 样本总数是 x, 0.9的样本数为0.9x, 则需要找到小于0.9x的最近的bucket,(下个bucket le) - (当前bucket le) * 0.9 + 当前bucket le = 分位数

例如

agree_afa_engine_svc_executedtime_bucket{le=100} 1516

agree_afa_engine_svc_executedtime_bucket{le=500} 7814

agree_afa_engine_svc_executedtime_bucket{le=1000} 15634.0

agree_afa_engine_svc_executedtime_bucket{le=5000} 15650.0

agree_afa_engine_svc_executedtime_bucket{le=10000} 15650.0

agree_afa_engine_svc_executedtime_bucket{le=30000} 15650.0

agree_afa_engine_svc_executedtime_bucket{le=60000} 15650.0

agree_afa_engine_svc_executedtime_count{le=60000} 15650.0

agree_afa_engine_svc_executedtime_sum{le=60000} 7869694.0

15650 * 0.9 = 14085

1000-500 * 0.9 + 500 =

参考:https://zhuanlan.zhihu.com/p/76904793

标准差与方差

统计意义:统计一组数据的的离散程度,偏离度。

计算方法:给定一组数据(a,b,c,d), 总共有n个数据, 这组数据平均数为$\mu$

\[方差 = \frac{(a-\mu)^2+(b-\mu)^2+(c-\mu)^2}{n}\] \[标准差\sigma = \sqrt{方差}\]

经典案例:3月2日 9点30-9点40,longsleep偏离度

prometheus中提供stddev(标准差)与stdvar(方差)进行计算。

stddev(向量表达式) [bywithout (labellist)]

向量表达式与 label确立计算标准差的数据有多少组,每一组数据出一个标准差,上面的表达式是取一个时间节点,计算的时候的样本会以时间为x跨度轴进行扩展统计的数据组有多少。

本文由作者按照 CC BY 4.0 进行授权

设计模式

TSDB part(1) - The Head Block