前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解 PromQL

深入理解 PromQL

作者头像
haohongfan
发布2022-12-16 15:44:31
1.8K0
发布2022-12-16 15:44:31
举报
文章被收录于专栏:HHFCodeRvHHFCodeRv

Prometheus 监控系统是云原生环境下主流的监控系统,在各大厂都有比较广泛的应用。

Prometheus 开创性地提出了 PromQL 查询语法,大大简化了监控面板的配置门槛,使得应用开发者可以自由地配置、组合监控面板。

PromQL 功能非常强大,大部分应用开发者只需要了解最简单的函数(如 rate、delta、histogram_quantile)就可以实现绝大部分需求。另一方面,这也导致很多人对 PromQL 并没有很深入的理解,无法掌握一些高级查询功能,遇到一些报错的时候不明所以。

比如:

1、案例1:offset位置不对报错,必须在 selector 或者 subquery 后面

2、案例2:ranges只能接在 vector selectors 后面

本文试图阐述 PromQL 的组成部分,帮助大家深入的理解 PromQL 语句的含义,以及能够根据所想写出合适的 PromQL 语句。

PromQL 解析

四则混合运算,可以拆分成 数字、操作符和括号,掌握了运算规则,再长的算式都变得很好理解。PromQL 也是如此。

Prometheus的指标(Metric)包括 Counter、Gauge、Histogram、Summary 四种基本类型,部分 PromQL的函数确实也有要求指定的类型,但这里的细节不在本文的讨论范围内。

PromQL 主要包含以下几个组成部分(下列组成部分的划分是我个人根据自身的经验和理解做出的,如有不同意见欢迎探讨)

  • Scalar(标量)
  • Vectors
    • Instant Vector
    • Range Vector
  • Selectors
    • Instant Query Selector
    • Range Query Selector
  • Operators
    • Arithmetic (算数操作符)
    • Trigonometric(三角函数操作符)
    • Comparison(比较操作符)
    • Logical(逻辑操作符)
    • Binary Operators
    • Aggregation Operators
  • Functions
  • SubQuery
  • Modifiers

一个 PromQL 表达式,即是由上述各部分组成的,理解了每个部分的含义,复杂的 PromQL 就很好理解了。更进一步也可以按自己的心意写出复杂的 PromQL 语句。

本文并不致力于详尽的讲解每一个组成部分,只想澄清最关键的一些概念。一些组成部分的细节(如具体的函数)可以去查阅官方文档。以上各个部分其实在官方文档上都有提及,但是散落在不同的页面,不是很好理解其中的关系。

Vectors

Vector是什么

Vector直接翻译是向量的意思,PromQL 中的 Vector 也可以理解为向量。

以一个时间序列(TimeSeries)为例

代码语言:javascript
复制
counter{a="b", c="d"}

等价于

代码语言:javascript
复制
{a="b", c="d", __name__="counter"}
  • 每一个标签(label)都是一个维度(dimension ),这是一个包含三个维度(dimension)的向量(vector)
  • 具有相同 dimension 的 vector 可以认为有相同的秩(线性代数的概念),可以进行匹配等操作。
  • 每个 dimension 都有一个标签值,所有unique的标签&&标签值的组合都是一个独立的时间序列(TimeSeries)
  • 使用 selector(下面会讲到)查询出的可以认为是全维度(full-dimension)的vector。当执行某些运算或函数的时候,可能出现维度丢失。例如
    • sum by (a) (counter{a="b", c="d"}) 聚合后的 vector 就只剩下了 a 这一个 dimension
    • 官网未提及 irate(counter{a="b", c="d"}[2m]) 这样的函数,运算完之后,实际上__name__ 已经消失了
  • 通过 vector() 函数也可以创建 vector,是一个零维度的 vector
Instant Vector && Range Vector

刚刚讲的 dimension 可以理解为 向量的方向,向量还有一个元素就是向量值,在 Prometheus中,向量值都是浮点型的数字。

在一个时刻有一个向量值的,就叫做 instant vector

在一个时刻,不仅包含当前时刻的值,还包含前向一段时间范围的 向量值(确切的说是时刻=>值的键值对)的,就叫做 range vector

对于 instant vector,加上时间维度后,可以很容易地画出图像,横坐标是时间戳,纵坐标是向量值。

对于 range vector,每一个时刻,都包含一组键值对信息,例如

以 example_metric{job="C"} 为例,可以看到 1@1(value@timestamp) 这个点,出现在了上述所有时刻的 ran ge里。

在做运算的时候,可能会用到部分或全部这些信息。例如

  • rate、irate 函数,计算变化率,既需要知道 value 的变化,也需要知道 时间的变化。区别是 rate 会取一个 range 的首和尾来计算,irate 会取一个 range 的最新的两个点来计算。这也是为什么 irate 要比 rate 的图像变化波动更大。
  • max_over_time 函数,只需要知道一段 range 里的 value就行了,并不关心时间戳
Vector扩展——相关注意点
  • 指标在收集的过程中,可能会丢失某些时刻的sample,一个 range 里也就会丢失部分数据点。丢失数据点后的range在计算过程中,Prometheus会进行一定的兼容处理(如根据一定算法推测缺失的点)。
  • 指标在采集的时候,经常是固定时间间隔采集一次(例如15s、30s、1m等),相同 dimension 的指标,在采集时可能会有时间差(前后错开几秒)。Prometheus 内部会有时间戳对齐机制,将相应有偏差的采集点对齐后,再做计算。

上述两点,是想说明 Prometheus 适合用于趋势类监控,并不能做到十分精确。在某一项指标的具体一小段时间,尤其是 irate 这样的函数结果并不能精确的反应真实情况。不要用 Prometheus 做时间灵敏度、精确度高的监控手段。

另外,基于采样的监控,采样间隔期间出现的瞬时峰值也是无法监控到的。

Selectors

Selector是什么

Selector——选择器——是一个基于标签匹配来获取符合条件的timeseries的PromQL对象

Selector 可以定义一组label及其对应的匹配规则,一共有四种:

  • = literally match
  • != literally not match
  • =~ regularly match
  • !~ regularly not match

标签的匹配和存储是基于倒排索引来实现的。

指标名称也是标签,是一个特殊的标签__name__

Prometheus的正则匹配是对 label 值的完全匹配,不支持部分匹配。正则匹配支持的规则也有一定限制(与go官方的regex库支持范围一致),如无法支持“look behind”等。

Selector和Vector的关系

相同点

  • Selector查询出来的其实是TimeSeries,也是包含了这个TimeSeries所有维度的 “full-dimensional” vector
  • Selector 和 Vector 都有 Instant 和 Range 两类。Instant Query Selector 可以得到 Instant Vector,Range Query Selector 可以得到 Range Vector

不同点

  • Instant Query Selector 后面加上 [range:resolution] 就变成了 Range Query Selector,其中 冒号和resolution 可以省略 Instant Vector 后面加上 [range:resolution] 就变成了 Range Vector(也叫做 SubQuery),其中resolution可以省略,但是冒号不能省略(后文有详细说明)

SubQuery

SubQuery 本质上是 range vector,是 instant vector 附加上 [range:resolution] 之后得到的。

在 PromQL 支持的函数中,如果涉及到 instant vector 和 range vector 之间的转换,几乎部分都是从 range vector 转换到 instant vector。这也不难理解,因为 range vector 所包含的信息更多,这些函数,本质上都是接受较多信息作为入参,计算出一维的结果进行返回。

例如 irate 函数,可以计算一个 counter 指标的变化率

代码语言:javascript
复制
irate(counter{a="b", c="d"}[5m])

如果我想计算近5分钟变化率的最大值,该怎么办?这里就用到了 SubQuery

代码语言:javascript
复制
max_over_time(irate(counter{a="b", c="d"}[5m])[5m:1m])

irate 返回的结果是一个 instant vector,拼接上 [range:resolution] 之后,就成为了一个 subquery,也就是一个 range vector,可以被用于 max_over_time 函数的入参。

为什么resolution是必须的

根据官方文档, SubQuery 的标准定义为

代码语言:javascript
复制
Syntax: <instant_query> '[' <range> ':' [<resolution>] ']' [ @ <float_literal> ] [ offset <duration> ]

<resolution> is optional. Default is the global evaluation interval.

官方文档这里描述的有点坑,比如既然 resolution 是可选的,为什么还会报下面的错误?

答案是 虽然 resolution 是可选的,但是冒号不能丢,可以写成这样:

代码语言:javascript
复制
max_over_time(irate(vector(5)[5m:1m])[5m:])

此时,默认的 resolution,等于 prometheus 配置中的 global evaluation interval,也就是来自官网配置文档中的下面这项配置:

为什么 SubQuery 中 resolution 是必要的?按照我的理解,这是因为很多函数计算严格依赖 resolution。例如

代码语言:javascript
复制
sum_over_time(vector(5)[5m:1m]) ==> 25
sum_over_time(vector(5)[5m:2m]) ==> 10

resolution 在上面的表达式里,直接决定了range内有几个点参与计算。

与之对比,在 selector 层面,range query selector 中的时间范围可以不加 resolution。这是因为对于一个具体的 timeseries,其自身天然包含 resolution信息(等于指标采集时的间隔)。但是对于SubQuery,必须需要一个resolution,来确定range内的点的粒度和个数。

各组件关系转换图

总结

PromQL 本质上是针对一系列 vector 的操作:selector 是 TimeSeries 转换为 Vector 的桥梁,查出来的结果是 full-dimensional vector。然后,再通过一系列函数、操作符,针对 vector 的粒度,来进行运算。

本文试图将 PromQL 解析为基本的组成部分,并对其中的关键点、易混淆的概念进行了解析。略去的 Operators、Functions等,读者可以自行去官网查看详细的使用说明。相信有了本文作为基础,理解官方文档也会更加快速、更加透彻。

作者介绍

兰孟然,某大厂资深研发工程师,擅长高性能分布式服务端开发,对 prometheus 有深入理解,当前从事 presto、spark 引擎的开发&维护工作。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HHFCodeRv 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PromQL 解析
    • Vectors
      • Vector是什么
      • Instant Vector && Range Vector
      • Vector扩展——相关注意点
    • Selectors
      • Selector是什么
      • Selector和Vector的关系
    • SubQuery
      • 为什么resolution是必须的
      • 作者介绍
  • 各组件关系转换图
  • 总结
相关产品与服务
Prometheus 监控服务
Prometheus 监控服务(TencentCloud Managed Service for Prometheus,TMP)是基于开源 Prometheus 构建的高可用、全托管的服务,与腾讯云容器服务(TKE)高度集成,兼容开源生态丰富多样的应用组件,结合腾讯云可观测平台-告警管理和 Prometheus Alertmanager 能力,为您提供免搭建的高效运维能力,减少开发及运维成本。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档