promQL 小记

表达式数据类型

在prometheus 表达式中,可操作的数据类型可归结为以下4类:

  1. Instant vector

    一组时间戳相同的时间序列。eg:

    promQL: http_requests_total
    ---
    element                               value
    http_requests_total{instance=xxx}       1
    http_requests_total{instance=aaa}       2
    http_requests_total{instance=ccc}       3
    
  2. Rage vector

    某个时段的时间序列的值的集合。eg:

    promQL: http_requests_total[1m]
    ---
    element                               value
    http_requests_total{instance=xxx}	40668
                                        @1562816358.478
                                        40669
                                        @1562816373.478
                                        40670
                                        @1562816388.478
                                        40671
                                        @1562816403.478
    
  3. Scalar

    一个简单的浮点数, eg:

    promQL: 1+1
    ---
    element         value
    scalar            2
    
  4. String

    一个字符串,暂未用到

时间序列选择器

prometheus 采集的metrics都已时间序列的方式存储。PromQL 是时间序列查询语法。由上数据类型可知,查询结果共有四种数据类型。以下为各数据类型查询语法介绍。

Instant Vector selector

Instant vector 表示同一时间戳下具有相同特征的时间序列。以node_exporter采集的metrics node_memory_MemAvailable 为例。

获取全部的node_memory_MemAvailable metric 时间序列:

promQL: node_memory_MemAvailable
---
element                                                                                     value
node_memory_MemAvailable{instance="192.168.1.1:9100",job="node_exporter",service="web"}	  1537667072
node_memory_MemAvailable{instance="192.168.1.2:9100",job="node_exporter",service="web"}	  15886266368
node_memory_MemAvailable{instance="192.168.1.3:9100",job="node_exporter",service="db"}	  16204136448
node_memory_MemAvailable{instance="192.168.1.3:9100",job="node_exporter",service="mq"}	  16204136448

即不加任何过滤条件。如果只看web 服务的时间序列,查询语句如下:

promQL: node_memory_MemAvailable{service="web"}
---
element                                                                                     value
node_memory_MemAvailable{instance="192.168.1.1:9100",job="node_exporter",service="web"}	  1537667072
node_memory_MemAvailable{instance="192.168.1.2:9100",job="node_exporter",service="web"}	  15886266368

标签支持以下几种操作符:

  • = : 完全匹配
  • != : 完全不匹配
  • =~ : 部分匹配(可接正则表达式)
  • !~ : 部分不匹配(可接正则表达式)

例如过滤除service=web 外的其他时间序列,可通过:

promQL: node_memory_MemAvailable{service!~"web.*"}
or
promQL: node_memory_MemAvailable{service!="web"}
or
promQL: node_memory_MemAvailable{service=~"mq|db"}

Range Vector selector

Instant Vector selector 不同的是,range vector 需要带上时间间隔。

比如展示service=db 5分钟内的内存可用量:

promQL: node_memory_MemAvailable{service="db"}[5m]
---
element                                                                                     value
node_memory_MemAvailable{instance="192.168.1.3:9100",job="node_exporter",service="db"}	  16489734144 @1562826039.824
                                                                                          16489734144 @1562826039.824
                                                                                          16489394176 @1562826054.824
                                                                                          16487358464 @1562826069.825
                                                                                          16484458496 @1562826084.824
                                                                                          ...

可选择的时间单位如下:

  • s: seconds
  • m: minutes
  • h: hours
  • d: days
  • w: weeks
  • y: years

假设当前时间为12:00pm, 如果想看前一天12.00pm的时间序列,可以采用offset。写法如下:

promQL:  node_memory_MemAvailable{service="db"} offset 1d

当然如果想看过去某个时间段内的时间序列也是ok的:

promQL: node_memory_MemAvailable{service="db"}[5m] offset 1d

支持的运算操作

  • 二元运算
  • 匹配运算
  • 聚合运算

二元运算

promQL 支持以下二元运算:

  • 算数运算
  • 逻辑运算
  • 比较运算

算数运算

运算符:+, -, *, /, %, ^

分别对应加法,减法,乘法,除法,取余,指数运算

可用于scalar/scalar, vector/scalar, vector/vector

scalar/scalar

promQL: 2 * 2

vector/scalar:

node_memory_MemFree_bytes/(1024*1024)

将内存单位换算为MB

vector/vector:

promQL: node_filesystem_size{instance="192.168.1.1:9100",device="/dev/sda1"} - node_filesystem_free{instance="192.168.1.1:9100",device="/dev/sda1"}

计算某块磁盘的使用量。

比较运算

运算符:==, !=, >, <, >=, <=

可用于scalar/scalar, vector/scalar, vector/vector

scalar/scalar:

promQL: 1 >= bool 2
---
element                 value
scalar                    0

0 表示 False, 1 表示 True

vector/scalar:

promQL: rate(http_requests_total{instance='192.168.1.1:9100'}[5m]) >=  bool 100
---
element                                            value
{instance='192.168.1.1',job="node_exporter"}         0

统计最近5分钟内,并发请求数是否大于100。

如果不带bool 修饰符,则返回为5分钟内实际并发数(如果满足并发数大于100)或者空(并发数小于100)

vector/vector

(node_memory_bytes_total - node_memory_free_bytes_total) / node_memory_bytes_total * 100 > bool 95

判断当前内存使用率是否超过95%

逻辑/集合运算

只能用于 instant vector 之间。

运算符:

  • and (交集)
  • or (并集)
  • unless (补集)

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

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

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

暂时没想到例子,待补充。

匹配运算

作用于vector1/vector2

用于匹配出现在vector2vector1 中的时间序列。用伪代码可这样表示:

def match(vector1, vector2):
    new_vector = set()
    for item in vector1:
        if item in vector2:
            new_vector.add(item)
    return new_vector

有两种匹配行为:一对一,一对多/多对一

这里参考官网示例来加以说明,假设有如下时间序列:

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

one-to-one 可认为左右集合中的条目数量相等。

one-to-many 可认为左侧集合中一个条目对应右侧多个条目

many-to-one 同理

one-to-one:

语法:

  
or
  ignoring(

说明:
两边的时间序列根据相同的标签来进行匹配。可以通过ignoring 来忽略某些标签。on则用于将匹配条件限定在特定标签中。

promQL: method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m
---
element         value
{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

该表达式会返回在过去5分钟内,HTTP请求状态码为500的在所有请求中的比例。如果没有使用ignoring(code),操作符两边表达式返回的瞬时向量中将找不到任何一个标签完全相同的匹配项。

在上面例子中,左侧表达式返回的时间序列集为:

promQL: method_code:http_errors:rate5m{code="500"}
---
element                                                    value
method_code:http_errors:rate5m{method="get", code="500"}    24
method_code:http_errors:rate5m{method="post", code="500"}    6

由于使用了ignore 忽略了对code 标签的匹配,所以从右侧表达式匹配到的时间序列为:

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

然后对结果集做/ 除法操作,得到上面结果。

one-to-many/many-to-one:

多对一和一对多两种匹配模式指的是“一”侧的每一个向量元素可以与"多"侧的多个元素匹配的情况。在这种情况下,必须使用group修饰符:group_left或者group_right来确定哪一个向量具有更高的基数(充当“多”的角色)。

语法如下:

  ignoring(

eg:

promQL: method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m
---
element                    value
{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

分析:

左侧表达式对应集合:

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

由于使用了group_left, 因此左侧集合代表的一侧。
由于右侧集合中,没有code 标签,所以需要通过ignore 来忽略。

聚合操作

聚合操作,顾名思义就是将多组序列聚合为一组。通过promQL的内置函数来实现。

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

sum:

统计机器上存储容量

promQL: sum(node_filesystem_size{instance=~"192.168.1.1.+",device=~"/dev/sd.*"} )
---
element         value
{}              520794112

to be continue

参考文档

https://yunlzheng.gitbook.io/prometheus-book/parti-prometheus-ji-chu/promql/prometheus-aggr-ops

https://prometheus.io/docs/prometheus/latest/querying/operators/

你可能感兴趣的:(prometheus)