Prometheus之PromQL基础

一 PromQL简介

  • Prometheus基于指标名称(Metrics name)以及附属的标签集(labelset)唯一定义一条时间序列;
    • 指标名称代表着监控目标上某类可测量属性的基本特征标识;
    • 标签则是这个基本特征上再次细分的多个可测量维度;
  • 基于PromQL表达式,用户可以针对指定的特征及其细分的维度进行过滤、聚合、统计等运算从而产生期望的计算结果;
  • PromQL(Prometheus Query Language)是Prometheus Server内置数据查询语言;
    • PromQL使用表达式(expression)来表达查询需求;
    • 根据其使用的指标和标签,以及时间时间范围,表达式的查询请求可灵活地覆盖在一个或多个时间序列的一定范围内的样本之上,甚至是只包含单个时间序列的单个样本;

二 PromQL时间序列

2.1 时间序列

时间序列数据:按照时间顺序记录系统、设备状态变化的数据,每个数据称为一个样本;

  • 数据采集以特定的时间周期进行,因而,随着时间流逝,将这些样本数据记录下来,将生成一个离散的样本数据序列;
  • 改序列也称为向量。而将多个序列放在同一个坐标系内,将形成一个有数据点组成的矩阵;

2.2 数据类型

PromQL的表达式中支持4中数据类型:

  • 即时向量(Instant Vector):特定或全部的时间序列集合上,具有相同时间戳的一组样本值称为即时向量;
  • 范围向量(Range Vector):特定或全部的时间序列集合上,在指定的同一时间范围内的所有样本值;
  • 标量(Scalar):一个浮点型的数据值;
  • 字符串(String):支持使用单引号、双引号或反引号进行应用,但反引号中不会对转义字符进行转义;

2.3 指标

  • 指标名称和标签的特定组合代表着一个时间序列;
    • 指标名称相同,但标签不同的组合分布代表着不同的时间序列;
    • 不同的指标名称自然更是代表着不同的时间序列;
  • PromQL支持基于定义的指标维度进行过滤和聚合;
    • 更改任何标签值,包括添加或删除标签,都会创建一个新的时间序列;
    • 应该尽可能地保持标签的稳定性,否则,则很可能创建新的时间序列,更甚者会生成一个鼎泰的数据环境,并使得监控的数据源难以跟踪,从而导致建立在该指标之上的图形、告警及记录规则变得无效;

三 时间序列选择器

3.1 时间序列选择器介绍

  • PromQL的查询操作需要针对有限个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式最为关键的一步;
  • 用户可使用向量选择器表达式来挑选出给定指标名称下的所有时间序列或部分时间序列的及时样本值或至少过去某个时间范围内的样本值,前者称为即时向量选择器。后者称为范围向量选择器
    • 即时向量选择器(Instant Vector Selectors):返回0个、1个或多个时间序列上在给定时间戳上的各自的一个样本,改样本也可称为即时样本;
    • 范围向量选择器(Range Vector Selectors):返回0个、1个或多个时间序列上在给定时间范围内的各自的一组样本;

3.2 向量表达式使用要点

  • 表达式的返回值类型亦是即时向量、范围向量、标题或字符串4中数据类型的其中之一,但是有些使用场景要求表达式返回值必须满足特定的条件,例如
    • 需要将返回值绘制成图形时,仅支持即时向量类型的数据;
    • 对于诸如rate一类的速度函数来说,其要求使用的却又必须是范围向量型的数据;
  • 由于范围向量选择器的返回的是范围向量型数据,它不能用于表达式浏览器中图形绘制功能,否则,表达式浏览器会返回“Error executing query:invalid expression type "range vector" for range query,must be Scalar or instant Vector” 一类的错误
    • 事实上,范围向量选择几乎总是结合速率类的函数rate一同使用

3.3 匹配器

  • 匹配器用于定于标签过滤条件,目前支持如下4种匹配操作符;
    • =:选择与提供的字符串完全相同的标签。
    • !=:选择与提供的字符串不相同的标签。
    • =~:选择正则表达式与提供的字符串(或子字符串)相匹配的标签。
    • !~:选择正则表达式与提供的字符串(或子字符串)不匹配的标签。
  • 注意事项:
    • 匹配到空标签值的匹配器时,所有未定义标签的时间序列同样符合条件;
      • 例如:http_requests_total{env=""},则改指标名称上所有未使用改标签(env)的时间序列也符合条件,比如时间序列http_requests_total{method="get"};
    • 正则表达式将执行完全锚定机制,它需要匹配指定的标签的整个值;
    • 向量选择器知道要包含一个指标名称,或者至少有一个不会匹配到空字符串的匹配器;
      • 例如,{job=""}为非法的选择器;
    • 使用“__name__=”作为标签名称,还能够对指标名称进行过滤;
      • 例如,{__name__=~"http_requests_.*"}能够匹配所有以“http_requests_”为前缀的所有指标;
  • 匹配示例
    • node_load1{instance="192.168.174.100"}
    • node_load1{job="prometheus-node"}
    • node_load1{job="prometheus-node",instance="192.168.174.100"}
    • node_load1{job="prometheus-node",instance!="192.168.174.100"}

3.4 即时向量选择器

  • 即时向量选择器由两部分组成;
    • 指标名称:用于限定特定指标下的时间序列,即负责过滤指标;可选;
    • 匹配器(Matcher):或称为标签选择器,用于过滤时间序列上的标签;定义在{}之中;可选;
  • 即时向量选择器组合;
    • 仅给定指标名称,或在标签名称上使用了空值的匹配器:返回给定的指标下的所有时间序列各自的即时样本;
      • 例如,http_requests_total和http_requests_total{}的功能相同,都是用于返回http_requests_total指标下各时间序列的即时样本;
    • 仅给定匹配器:返回所有符合给定匹配器的所有时间序列上的即时样本;
      • 注意:这些时间序列可能会有着不用的指标名称;
      • 例如,{job=".*",method="get"}
    • 指标名称和匹配器的组合:返回给定的指标下的,且符合给定的标签过滤器的所有时间序列上的即时样本;
      • 例如:http_requests_total{method="get"}

3.5 范围向量选择器

  • 同即时向量选择器的唯一不同之处在于,范围向量选择器需要在表达式后紧跟一个方括号[]来表达需要在时间序列上返回的样本所处的时间范围;
    • 时间范围:以当前时间为基准时间点,指向过去一个特定的时间长度;例如[5m]便是值过去5分钟之内;
  • 时间格式:一个整数后紧跟一个时间单位。例如“5m”中的“m”即时时间单位;
    • 可用的时间单位有ms(毫秒)、s(秒)、m(分钟)、h(小时)、d(天)、w(周)和y(年);
    • 必须使用整数时间,且能够将多个不同级别的单位进行串联组合,以时间单位由大到小为顺序,例如1h30m,但不能使用1.5h;
  • 需要注意的是,范围向量选择器返回的是一定时间范围内的数据样本,虽然不同时间序列的数据抓取的时间点相同,但他们的时间戳并不会严格对齐;
    • 多个Target上的数据抓取需要分散在抓取时间点前后一定的时间范围内,以均衡Prometheus Server的负载;
    • 因而,Prometheus在趋势上准确,但并非绝对精确;

3.6 偏移量修改器

  • 默认情况下,即时向量选择器和范围向量选择器都已当前时间为基准时间点,而偏移量修改器能修改该基准;
  • 偏移量修改器的使用方法是紧跟在选择器表达式之后使用“offset”关键字指定;
    • “http_requests_total offset 5m”,标识获取以http_requests_total为指定名称的所有时间序列在过去5分钟之前的即时样本;
    • “http_requests_total[5m] offset 1d”,表示获取距此刻1天时间之前的5分钟之内的所有样本;

四 Prometheus指标类型

Prometheus Server并不使用类型信息,而是将所有数据展平为时间序列;

Prometheus有4个指标类型,它们主要由Prometheus的客户端使用;

4.1 Counter

  • Counter:计数器,单调递增,除非重置(例如服务器或进程重启);
  • 通常,Counter的总数并没有直接作用,而是需要借助于rate、topk、increase和irate等函数来生成样本数据的变化状况(增长率);
    • rate(http_requests_total[2h]),获取2小时内,该指标下各时间序列上的http总请求数的增长速率;
    • topk(3,http_requests_total),获取该指标下http请求总数排名前3的时间序列;
    • irate(http_requests_total[2h]),高灵敏度函数,用于计算指标的瞬时速率;
      • 基于样本范围内的最后两个样本进行计算,相较于rate函数来说,irate更适用于短期时间范围内的变化速率分析;

4.2 Gauge

Gauge用于存储其值可增可减的指标的样本数据,常用于进行求和、取平均值、最小值、最大值等聚合计算;也经常会结合PromQL的predict_linear和dalta函数使用;

  • predict_linear(v range-vector,t,scalar)函数可以预测时间序列v在t秒后的值,它通过线性回归的方式来预测样本数据的Ganuge变化趋势;
  • dalta(v range-vector)函数计算范围向量中每个时间序列元素的第一个值与最后一个值之差,从而展示不同时间点上的样本的差值;
    • dalta(cpu_temp_celsius{host="web01.wgs.com"}[2h]),返回服务器的CPU温度与2小时之前的差异;

4.3 Histogram

  • Histogram是一种对数据分布情况的图形表示,由一系列高度不等的长条图(bar)或线段表示,用于展示单个测度的值的分布;
    • 它一般用横轴表示某个指标维度的数据取值区间,用纵轴表示样本统计的频率或频数,从而能够以二维图的形式展现数值的分布状况;
    • 为了构建Histogram,首先需要将值的范围进行分段,即将所有值的整个可用范围分成一系列连续、相邻但不重叠的间隔,而后统计每个间隔中有多少值;
    • 从统计学的角度看,分位数不能被聚合,也不能进行算术运算;
  • 对于Prometheus来说,HIstogram会在一段时间范围内对数据进行采样(通常是请求持续时间或响应大小等),并将其计入可配置的bucket中;
    • Histogram事先将特定测度可能地取值范围分割成多个样本空间,并通过对落入bucket内的观测值进行计数以及求和操作;
    • 与常规方式略有不同的是,Prometheus取值间隔的划分采用的累积(Cumulative)区间间隔机制,即每个bucket中的样本均包含了其前面所有bucket中的样本,因而也称为累积直方图;
      • 可降低HIstogram的维护成本
      • 支持粗略计算样本值的分位数
      • 单独提供了_sum和_count指标,从而支持计算平均值
  • HIstogram类型的每个指标有一个基础指标名称<basename>,它会提供多个时间序列:
    • <basename>_bucket{le="<upper inclusive bound>"}:观测桶的上边界(upper inclusive bound),即样本统计区间,最大区间(包含所有样本)的名称为<basename>_bucket{le="+Inf"}
    • <basename>_sum:所有样本观测值的总和;
    • <basename>_count:总的观测次数,它自身本质上是一个Counter类型的指标;
  • 累积间隔机制生成的样本数据需要额外使用内置的histogram_quantile()函数即可根据Histogram指标来计算响应的分数位(quantile),即某个bucket的样本数在所有样本数中占据的比例;
    • histogram_quantile()函数在计算分位数时会假定每个区间内的样本满足线性分布状态,因而它的结果仅是一个预估值,并不完全准确;
    • 预估的准确度取决于bucket区间划分的粒度;粒度越大,准确度越低;

4.4 Summary

  • 指标类型是客户端库的特性,而Histogram在客户端仅是简单的桶划分和分桶计数,分位数计算由Prometheus Server基于样本数据进行估算,因而其结果未必准确,甚至不合理的bucket划分会导致较大的误差;
  • Summary是一种类似于Histogram的指标类型,但它在客户端于一段时间内(默认为10分钟)的每个采样点进行统计,计算并存储了分位数数值,Server端直接抓取响应值即可;
  • 但Summary不支持sum或avg一类的聚合运算,而且其分位数由客户端计算并生成,Server端无法获取客户端未定义的分位数,而Histogram可通过PromQL任意定义,有着较好的灵活性;
  • 对于每个指标,Summary以指标名称<basename>为前缀,生成如下几个指标序列;
    • <basename>{quantile="<>"}
    • <basename>_sum,抓取到的所有样本值之和;
    • <basename>_count,抓取到的所有样本总数;
posted @ 2021-11-16 20:55  小吉猫  阅读(643)  评论(0编辑  收藏  举报