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:

语法:

<vector expr> <bin-op> <vector expr>
or
<vector expr> <bin-op> ignoring(<label list>) <vector expr>
or
<vector expr> <bin-op> on(<label list>) <vector expr>

说明:
两边的时间序列根据相同的标签来进行匹配。可以通过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来确定哪一个向量具有更高的基数(充当“多”的角色)。

语法如下:

<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>

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/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Protobuf是一种高效的序列化协议,可以用于数据交换和数据存储。它的主要优势是大小小,速度快,可扩展性强。下面是使用Protobuf的一些小记: 1. 定义消息格式 首先,需要定义消息格式,以便Protobuf可以将数据序列化和反序列化。消息格式定义在.proto文件中,使用protobuf语言编写。例如,下面是一个简单的消息格式定义: ``` syntax = "proto3"; message Person { string name = 1; int32 age = 2; } ``` 这个消息格式定义了一个名为Person的消息,包含两个字段:name和age。 2. 生成代码 一旦消息格式定义好,就可以使用Protobuf编译器生成代码。编译器将根据消息格式定义生成相应的代码,包括消息类、序列化和反序列化方法等。可以使用以下命令生成代码: ``` protoc --java_out=. message.proto ``` 这将生成一个名为message.pb.java的Java类,该类包含Person消息的定义以及相关方法。 3. 序列化和反序列化 一旦生成了代码,就可以使用Protobuf序列化和反序列化数据。例如,下面是一个示例代码,将一个Person对象序列化为字节数组,并将其反序列化为另一个Person对象: ``` Person person = Person.newBuilder() .setName("Alice") .setAge(25) .build(); byte[] bytes = person.toByteArray(); Person deserializedPerson = Person.parseFrom(bytes); ``` 这个示例代码创建了一个Person对象,将其序列化为字节数组,然后将其反序列化为另一个Person对象。在这个过程中,Protobuf使用生成的代码执行序列化和反序列化操作。 以上是使用Protobuf的一些基本步骤和注意事项,希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值