Promethues(五)查询-PromQL 语言-保证易懂好学

一、介绍

普罗米修斯提供了一种称为PromQL(普罗米修斯查询语言)的函数式查询语言,允许用户实时选择和聚合时间序列数据。

表达式的结果可以显示为图形,在 Prometheus 的表达式浏览器中显示为表格数据,也可以通过 HTTP API 由外部系统使用。

通常初学者可以在浏览器总,通过 Prometheus 的查询框输入查询语句,从而获取到查询结果。
在这里插入图片描述

二、PromQL 数据类型

在普罗米修斯的表达语言中,表达式或子表达式计算结果可以是如下四种类型之:

  • Instant vector 即时矢量 一组按照当前时间戳获取的监控指标时间序列数据样本,例如当前服务器内存可以大小,当前服务器的CPU使用率等。
    示例:
    假设目前监控了 3 台服务器,现在我希望获取 3 台服务器此刻每台服务器的内存剩余可用容量。可以输入语句:

    node_memory_MemAvailable_bytes

    应该返回如下样式的数据:
    在这里插入图片描述

上图中每一行都是一个服务器的数据样本,后面是具体的数据,单位: 字节。

  • Range vector 范围矢量 一组按照指定时间范围获取到的监控指标时间序列数据,包含了在这个时间范围内,随着时间变化而变化的数据样本,例如最近 15 秒内的内存剩余可用数据。
    可以输出查询语句: node_memory_MemAvailable_bytes[15s]
    获取到如下结果
    在这里插入图片描述

从上图可以看到,每个服务器都有 3 组数据,这是因为在 prometheus.yml 配置中的 scrape_interval 的值是 5s, 表示每 5 秒中 Prometheus会查询一次数据并保存到自己的数据库中。所以这里查询最近 15 秒的数据,就会返回 3 组数据。
17051344896 @1694497278.45517051344896 是具体的数值,@1694497278.455 表示一个时间戳,这个时间戳就是从Unix 元年开始到现在的秒数。

  • Scalar 标量 - 一个简单的数字浮点值;通常是通过查询表达式计算出来的结果。例如,内存使用率=内存可用容量 / 内存总容量=0.23
  • String 字符串 - 一个简单的字符串值;当前未使用

三、常量

1 字符串

字符串可以指定为单引号、双引号或反引号中的字面。

PromQL遵循与Go相同的转义规则。在单引号或双引号中,反斜杠开始一个转义序列,后面可能有a、b、f、n、r、t、v或\。可以使用八进制(\nnn)或十六进制(\xnn、\unnnn和\Unnnnnnnn)提供特定字符。

在反引号中不会处理转义符号

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

2 浮点

标量(Scalar)浮点值可以写成该格式中的文字整数或浮点数(只包括空白以提高可读性)

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

示例:

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

四、时间序列选择器 Time series Selectors

1 即时矢量(Instant vector)选择器

Instant vector 选择器允许在给定的时间戳(即时)为每个时间序列选择一组时间戳和一个样本值:在最简单的形式中,只指定一个度量名称。这将产生一个Instant vector,其中包含具有此度量名称的所有时间序列的元素。

此示例选择具有 up 指标名称的所有时间序列:

up

在这里插入图片描述

在一个简单的指标名称后面添加大括号({}),并在大括号中附件用逗号分隔的标签匹配器,可以实现对查询结果的过滤,这有点像是 SQL 中的 where 条件语句。
PromQL:

up{instance="10.10.40.200:9111"}

转化成 SQL:

select * from up where instance="10.10.40.200:9111"

此示例表示查询标签 instance 的值是 10.10.40.200:9111 的 up 指标数据

存在以下标签匹配运算符:

  • = 选择与提供的字符串完全相等的标签。
  • != 选择不等于提供的字符串的标签。
  • =~ 选择与正则表达式匹配的标签。
  • !~ 选择与正则表达式不匹配的标签。

注意:正则表达式匹配完全锚定。env=~"foo" 的匹配被视为 env=~"^foo$"

如下示例:返回标签 instance 的值以 10.10.40 开头,后面跟着 2 个任意组合的数字,以及标签 job的值以是 beijing 的。

up{instance=~"10.10.40.[0-9]{2}:9111", job="beijing"}

与空标签值匹配的标签匹配器还将包含所有没有设置此指定标签的时间序列。

同一标签名称可能有多个匹配器。

矢量选择器必须指定一个名称或至少含有一个非空字符串的标签匹配器。以下表达方式是非法的:

{job=~".*"} # 错误!

错误的原因: 这个可以匹配到一个空字符串(注意这里空字符串并不是空格)的标签,比如 {job=~""}, 这种情况下,它还没有指定一个具体的指标名称

相比之下,这些表达式是有效的,因为它们都至少有一个非空的标签的选择器。

{job=~".+"}              # Good!, 这个正测表示一个以及一个以上的字符(包含空格,虽然实际上并没有任何意义))。
{job=~".*",method="get"} # Good!

以上两个表达式,虽然都没有指定一个具体的指标名称,但是他们都不会匹配到一个空标签。空标签就是 {job=""}

通过与内部__name__标签进行匹配,标签匹配器也可以应用于指标名称。例如,表达式http_requests_total 等效于{__name__="http_requists_toltal"}。也可以使用除=之外的匹配项(!=,=~,!~)。以下表达式选择名称以 job 开头的所有度量:

{__name__=~"job:.*"}

指标名称不得是关键字 boolonignoringgroup_leftgroup_right 之一。以下表达方式是非法的:

on{} # Bad!

此限制的变通办法是使用__name__标签:

{__name__="on"} # Good!

2 范围矢量选择器

范围矢量的工作原理与即时矢量一样,只是它们从当前实例中选择指定时间范围内的一系列样本。

从语法上讲,时间长度附加在方括号([])中,在矢量选择器的末尾,以指定每个结果范围向量元素应获取多远的时间值。

在本例中,我们选择过去5分钟内为所有时间序列记录的所有值,这些值的指标名称为 node_filesystem_avail_bytes ,且标签 mountpoing 是 / , 标签 fstype 是 ext 开头或者是 xfs的:

node_filesystem_avail_bytes{fstype=~"ext.*|xfs",mountpoint ="/"}[5m]

2.1 时间长度

时间长度指定为数字,紧接着是以下单位之一:

  • ms 毫秒
  • s
  • m 分钟
  • h 小时
  • d 天 - 假设一天总是24小时
  • w 周 - 假设一周总是7d
  • y 年 - 假设一年总是365d

时间长度可以通过串联来组合。单位必须从最长到最短给定。给定的单位在一段时间内只能出现一次。

以下是一些有效时间长度的示例:

5h
1h30m
5m
10s

2.2 偏移修饰符

不常用

offset修饰符允许更改查询中单个即时矢量和范围矢量的时间偏移量。

例如,以下表达式返回 5 分钟之前 node_memory_MemAvailable_bytes 即时矢量的值:

node_memory_MemAvailable_bytes offset 5m

请注意,offset修饰符总是需要立即跟随选择器,即以下内容是正确的:

sum(node_memory_MemAvailable_bytes offset 5m) // GOOD.

sum 是一个计算总和的函数,后续会介绍
显然以下情况不正确:

sum(node_memory_MemAvailable_bytes) offset 5m // INVALID.

范围向量也是如此。这返回了node_memory_MemAvailable_bytes 一周前的5分钟数据:

node_memory_MemAvailable_bytes[5m] offset 1w

2.3 @ 修饰符

不常用

@ 修饰符允许对单个即时和范围矢量的具体时间进行指定。提供给@修饰符的时间是unix时间戳,并用 Float 文字描述。
说白了就是可以指定某个时间点

例如,以下表达式在 2023-09-12 12:30 返回 node_memory_MemAvailable_bytes 的值:

node_memory_MemAvailable_bytes @1694493000

时间转换: date -d “2023-09-12 12:30” +%s

请注意,同样 @修饰符总是需要立即跟随选择器。

范围向量也是如此。

@ 修饰符支持上述在int64范围内的所有浮点文字表示。它也可以与 offset 修饰符一起使用,其中 offset 相对于@修饰符时间应用,无论先写入哪个修饰符,这2个查询将产生相同的结果。
指定时间 1694493000 的 5 m之前 的数据

# offset after @
node_memory_MemAvailable_bytes @1694493000 offset 5m
# offset before @
node_memory_MemAvailable_bytes offset 5m  @1694493000

3 避免慢速查询和过载

如果查询需要对大量数据进行操作,则绘制查询可能会超时或使服务器或浏览器过载。

因此,在对未知数据构建查询时,请始终在普罗米修斯表达式浏览器的表格视图中开始构建查询,直到结果集看起来合理(最多是数百个,而不是数千个时间序列)。

只有在充分筛选或汇总数据后,才能切换到图形模式。如果表达式仍然需要很长时间来进行特别绘图,请通过记录规则 (recording rules ) 对其进行预记录。

这与普罗米修斯的查询语言尤其相关,在普罗米修斯中,像 api_http_requests_total 这样的裸度量名称选择器可以扩展到数千个具有不同标签的时间序列。还要记住,即使输出只是少量的时间序列,在许多时间序列上聚合的表达式也会在服务器上产生负载。这类似于对关系数据库中一列的所有值求和的速度很慢,即使输出值只有一个数字。

五、子查询

子查询允许您针对给定的范围和分辨率进行即时查询(instant query)。

子查询的结果是一个范围向量。

语法:<instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]

<resolution>是可选的。默认值是全局评估间隔。

返回过去30分钟 promhttp_metric_handler_requests_total 指标的5分钟速率,分辨率为1分钟。

rate(promhttp_metric_handler_requests_total[5m])[30m:1m]

prometheus_http_requests_total[5m]) 返回了每5分钟

六、操作符 Operators

Prometheus支持许多二进制和聚合运算符。

1 二进制运算符

普罗米修斯的查询语言支持基本的逻辑和算术运算符。对于两个即时矢量之间的操作,可以修改主题匹配行为。

算术运算符

普罗米修斯中存在以下二进制算术运算符:

  • + 加法
  • - 减法
  • * 乘法
  • / 除法
  • % 取模运算
  • ^ 幂运算

2 比较运算符:

  • == 等于
  • != 不等于
  • > 大于
  • < 小于
  • >= 大于等于
  • <= 小于等于

3 集合运算符

and 逻辑与
unless 排除某个
or 逻辑或

vector1 unless vector2
vector1 返回的结果中排除 vector2 返回的结果。
示例:

up{instance=~"10.10.40.*:9111"} unless up{instance="10.10.40.61:9111"}

从查询的结果集中排除 instance 的值为 10.10.40.61:9111 的数据

排除之前:
在这里插入图片描述
排除之后:
在这里插入图片描述

3 矢量匹配 Vector matching

矢量之间的运算试图在右侧矢量中为左侧的每个条目找到匹配元素。有两种基本类型的匹配行为:

  • 一对一
  • 多对一 或 一对多

3.1 矢量匹配关键字

这些矢量匹配关键字允许在具有不同标签集的系列之间进行匹配。
可以使用:

  • on
  • ignoring

提供给匹配关键字的标签列表将决定向量的组合方式。
具体用法见下面章节 3.3 一对一 矢量匹配 One-to-one vector matches

3.2 组修饰符

这些组修饰符可以实现 多对一/一对多 矢量匹配:

  • group_left
  • group_right

标签列表可以提供给组修饰符,其中包含要包含在结果度量中的“one”侧的标签。

多对一和一对多匹配是高级用例,应该仔细考虑。通常,正确使用 ignoring(<labels>) 可以提供所需的结果。

分组修饰符只能用于比较运算符和算术运算符。操作为 and, unlessor 操作默认情况下与右向量中的所有可能条目匹配。
具体用法见下面章节3.4 多对一 和 一对多 矢量匹配 Many-to-one and one-to-many vector matches

3.3 一对一 矢量匹配 One-to-one vector matches

一对一从操作的每一侧查找一对唯一的条目。

在默认情况下,这是一个遵循 vector1<operator>vector2格式的操作。

如果两个条目具有完全相同的标签集和相应的值,则它们匹配。

  • ignoring 关键字允许在匹配时忽略某些标签,就是在匹配的时候不需要考虑的标签
  • on 关键字允许将所需要匹配的标签集限定在所提供的列表中,就是在匹配的时候仅限于 on 所指定的这些标签。

语法:

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

<vector expr> 是 PromQL 查询表达式
<bin-op> 就是二进制操作符
<label list> 就是 标签列表

假设有如下数据

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"} 21method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120

查询示例:

method_code:http_errors:rate5m{code="500"} / ignoring(code) method:http_requests:rate5m

这将返回一个结果向量,其中包含在过去5分钟内测量到的每个 HTTP 请求方法的响应状态代码为500的HTTP请求占对应的HTTP请求方法的多少。
如果不忽略(code),就不会有匹配,因为度量不共享同一组标签。方法为put和del的条目不匹配,不会显示在结果中:

{method="get"}  0.04            //  24 / 600
{method="post"} 0.05            //   6 / 120

3.4 多对一 和 一对多 矢量匹配 Many-to-one and one-to-many vector matches

多对一和一对多匹配指的是“一”侧的每个表达式查询到的每条数据可以与“多”侧的多条数据匹配的情况。这必须使用group_leftgroup_right 修饰符来明确请求,其中 left/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>

示例数据:

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"} 21method:http_requests:rate5m{method="get"}  600
method:http_requests:rate5m{method="del"}  34
method:http_requests:rate5m{method="post"} 120

查询目的:
当前希望查询 每个请求方法(get,post,put)的响应码(500,404,501)在每个请求方法总数中的占比。
例如, get 方法中响应码为 500 的数据占 get 请求总数的占比, 手工计算: 24 / 600

可使用查询示例:

method_code:http_errors:rate5m / ignoring(code) group_left method:http_requests:rate5m

在这种情况下,左侧表达式中每个 method 标签值包含了多个条目(比如 get 就有 2 条)。因此,我们使用 group_left 来表示这一点,可以认为是以左侧表达式进行分组。右侧表达式中的元素现在与左侧表达式具有相同 method 标签的多个元素匹配:

{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

put 和 del 没有同时在两侧出现,所以无法匹配成功,结果中不包含 put 和 del 方法的条目。

4 聚合运算

Prometheus支持以下内置聚合运算符,这些运算符可用于聚合单个即时向量的数据,从而产生具有聚合值的更少数据的新矢量:

  • sum(计算总和)

  • min(选择最小值)

  • max(选择最大值)

  • avg(计算平均值)

  • group(将结果集中的值都设置为 1)
    在这里插入图片描述

  • stddev(计算维度上的总体标准偏差)

  • stdvar(计算维度上的总体标准方差)

  • count(计算向量中的元素数量,就是有多少条数据)
    统计目前监控了多少台服务器

     count(up)
    
  • count_values(计算具有相同值的元素数量,并需要传递一个字符串的参数,这个参数会作为一个新的 key 给返回值使用,这个有点像 SQL 语句中的 group by
    分别统计当前在线和非在线服务器的数量,并且打上新的标签 count

    count_values("server_st", up)
    

    在这里插入图片描述

  • bottomk(按样本值划分的最小k元素,就是找到所有数据的值最小的前几个)

  • topk(按样本值划分的最大的k种元素,就是找到所有数据的值最大的前几个)

     topk(5,node_memory_MemAvailable_bytes)
    
  • quantile(计算φ-quantile(0 ≤ φ ≤ 1) 取当前数据的中位数,取值范围0-1

     quantile(0.5, http_request_total)
    

这些运算符可用于聚合所有标签维度,也可以通过包含一个 withoutby 子句来保留不同的维度。
withoutby 可以在表达式之前或之后使用, 放在之前和之后两者起到的做优。
语法:

<aggr-op> [without|by (<label list>)] ([parameter,] <vector expression>)

<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]

标签列表是未引用标签的列表,其可以包括尾随逗号,即 (label1, label2)(label1, label2,) 都是有效语法。

without 从聚合结果向量中删除列出的标签,而所有其他标签都保留在输出中。
by 执行相反的操作,并删除未在 by 子句中列出的标签,即使它们的标签值在所有表达式的所有数据之间相同。

parameter 参数仅对 count_values, quantile, topk and bottomk 是必须的。

示例1 从返回的数据中添加 group 标签
使用 by 之前,统计所有被监控的服务器总数:
在这里插入图片描述
使用 by 之后,以 group 标签的值进行分组统计:
在这里插入图片描述

七、函数

八、Comments

支持以 # 开头作为注释

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/107961.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux HTTP协议

目录 1.浏览器与服务器通信过程2.HTTP请求报头&#xff08;1&#xff09;HTTP的请求报头结构&#xff08;2&#xff09;HTTP的请求方法 3.HTTP应答报头&#xff08;1&#xff09;HTTP的应答报头结构&#xff08;2&#xff09; HTTP的应答状态 1.浏览器与服务器通信过程 浏览器…

PaddleOCR学习笔记1-初步尝试

尝试使用PaddleOCR方法&#xff0c;如何使用自定义的模型方法&#xff0c;参数怎么配置&#xff0c;图片识别尝试简单提高识别率方法。 目前仅仅只是初步学习下如何使用PaddleOCR的方法。 一&#xff0c;测试识别图片&#xff1a; 1.png : 正确文本内容为“哲学可以帮助辩别现…

领域驱动设计:领域模型与代码模型的一致性

文章目录 领域对象的整理从领域模型到微服务的设计领域层的领域对象应用层的领域对象 领域对象与微服务代码对象的映射典型的领域模型非典型领域模型 DDD 强调先构建领域模型然后设计微服务&#xff0c;以保证领域模型和微服务的一体性&#xff0c;因此我们不能脱离领域模型来谈…

HarmonyOS Codelab 优秀样例——溪村小镇(ArkTS)

一、介绍 溪村小镇是一款展示溪流背坡村园区风貌的应用&#xff0c;包括园区内的导航功能&#xff0c;小火车行车状态查看&#xff0c;以及各区域的风景展览介绍&#xff0c;主要用于展示HarmonyOS的ArkUI能力和动画效果。具体包括如下功能&#xff1a; 打开应用时进入启动页&a…

EasyPHP-Devserver-17安装和配置mantisBT

文章目录 1、准备工作2、安装easyphp2.1 http://127.0.0.1 无法访问 3、安装mantisBT和phpMyAdmin3.1 配置浏览器的访问url和端口号&#xff08;配置局域网内可访问&#xff09;3.2 安装mantis 4、Administrator 注册新用户时设置登录密码5、附件上传6、邮件配置 文章参考自&am…

IntelliJ IDEA远程调试:使用IDEA Remote Debug进行高效调试的指南

引言 在开发分布式系统时&#xff0c;调试是一个重要但复杂的环节。开发者通常需要跨越多个服务、模块和线程来追踪和解决问题。在没有远程调试的情况下&#xff0c;许多开发者会在代码中添加各种日志语句&#xff0c;然后重新部署和上线来调试。这种方法不仅费时&#xff0c;…

Redis——其他数据类型介绍

概要介绍 Redis中有10种不同的数据类型。之前的blog中介绍了Redis中常见的五大数据类型&#xff1a;String&#xff0c;List&#xff0c;Hash&#xff0c;Set&#xff0c;ZSet。而Redis中还有许多其他的数据类型&#xff0c;一般在特定的场景中使用 Stream 首先介绍一下什么…

bootstrap-datepicker实现只能选择每一年的某一个月份

1、问题描述 最近碰到一个需求&#xff0c;要求日期控件选择的时候&#xff0c;只能选择某一年的1月份。 2、解决方法 使用setStartDate()和setEndDate()函数对日期选择框进行范围限制。 3、我的代码 【免费】bootstrap-datepicker实现只能选择每一年的某一个月份资源-CSDN文库…

从零开始的PICO教程(1)Pico游戏开发项目配置

从零开始的PICO教程&#xff08;1&#xff09;Pico游戏开发项目配置 文章目录 从零开始的PICO教程&#xff08;1&#xff09;Pico游戏开发项目配置一、前言1、大纲 二、成为Pico开发者1、注册 PICO 开发者帐号2、创建组织3、创建应用 三、导入PICO的SDK1、PICO设备开启 “开发者…

睿思BI制作数据分析报告并导出到word中

数据分析报告是一种常用的分析应用文体&#xff0c;它是数据分析项目的目的、方法、过程、结论以及可行性建议等内容的完整展示&#xff0c;是数据背后真实的业务水平的客观体现&#xff0c;是管理者做出科学、严谨决策的依据。睿思BI在数据报表中配置数据分析报告&#xff0c;…

【LeetCode: 1462. 课程表 IV:拓扑排序+图+广度优先搜索】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Mobileye CEO来华:只有能控制住成本的公司,才能活下来

‍作者|德新 编辑|王博 上午9点近一刻&#xff0c;Mobileye CEO Amnon Shuashua步入酒店的会议室。由于Amnon本人是以色列希伯来大学的计算机科学教授&#xff0c;大部分人更习惯称他为「教授」。 时近以色列的新年&#xff0c;这趟教授的中国之行安排十分紧凑。 他率领了一…