4、PromQL基础使用

4、PromQL基础使用

TOC

PromQL基础使用

    Prometheus最关键之处也就是去操作Prometheus时间序列,对于Prometheus时间序列而言,咱们需要知道一个问题,也就是同一个Metrics不同的Label代表不同的时间序列,每个序列,我们也可以称之为一个向量,将多个序列放入同一个坐标系内,就形成一个矩阵了,那么对于PromQL,实际上它就上让我们能够从这样一个矩阵中去筛选出,我们需要的数据的,并在这个基础之上做一些运算,得到我们期望的结果的一种表达式;
    所以从某种意义上来说,指标名称代表着监控目标上某类可测量属性的基本特征表示,而标签则是这个基本特征上再次细分的多个可测量纬度,而基础PromQL表达式,用户可以针对指定的特征以及其细分的纬度,也就是标签进行过滤、聚合、统计等运算,从而产生期望的计算结果;
    PromQL是Prometheus的内置查询语言,它又内建的这样一个PromQL引擎,PromQL表达式来表达查询需求,根据其使用的指标和标签,以及时间范围,表达式可灵活地覆盖在一个或多个时间序列的一定范围内的样本之上,甚至是只包含单个时间序列单个样本;
Prometheus数据模型
    在Prometheus中,每个时间序列都由指标名称(Metric Name)和标签(Label)来唯一标识,格式为“<metric name>{<label name>=<label value>},...”;
    指标名称,通常用于描述系统上要测定的某个特征,例如http_request_total表示接收到的HTTP请求总数;
    标签,标签属于键值类型,附加在指标名称之上,从而让指标能够支持多维度特征,可选项,例如http_request_total{method=GET}和http_request_total{method=POST}代表着两个不同的时间序列,标签名称可使用字母、数字和下划线,且必须能匹配RE2规范的正则表达式,以"__"开头前缀的名称为Prometheus预留;
指标和标签注意事项
    指标名称和标签名称的组合代表着一个时间序列,指标名称相同,但是标签不同的组合分别代表着不同的时间序列,更改任意标签或标签值都会产生一个新的时间序列,所以应该尽可能的保持标签的稳定性,否则,很可能创建新的时间序列;
PromQL数据类型
    PromQL表达式中,支持四种数据类型,分别为,即时向量、范围向量、标量和字符串;
即时向量(Instant Vector):特定或全部的时间序列集合上,具有相同时间戳的一组样本值,称为即时向量;
范围向量(Range Vector):特定或全部的时间序列集合上,在指定的同一时间范围内的所有样本值;
标量(Scalar):一个浮点型的数据值;
字符串(String):支持使用单引号、双引号和反引号进行引用,但反引号不支持转义;
    PromQL的查询操作需要针对有限个时间序列上的样本数据进行,挑选出目标时间序列是构建表达式最为关键的一步,用户可使用向量选择器表达式来挑选出给定指标名称下的所有时间序列或部分时间序列的即时(当前)样本或过去某个时间范围内的样本值,前者称为即时向量选择器,后者称为范围向量选择器;
即时向量选择器(Instant Vector Selector):返回0个、1个或多个时间序列上在给定时间戳上的各自的一个样本,该样本也称之为即时样本;
范围向量选择器(Range Vector Selector):返回0个、1个或多个时间序列上在给定时间范围内的各自的一组样本;

    在绘图时,也只能绘制即时向量选择器的结果,因为范围向量无法成图,究其原因就是范围向量它的结果本来就是一个矩阵,所以无法利用矩阵来绘制一个矩阵;
    每一次返回一个值,就是即时向量选择器,如下图,使用node_disk_io_now得到的就是即时向量,之后通过下面的1h,拿到一个小时的所有即使向量结果(也就是范围向量)绘制成图,而如果我们使用node_disk_io_now[5m],则会抛出Error executing query: invalid expression type "range vector" for range query, must be Scalar or instant Vector结果,意思是对于范围向量,是没法绘图的;

    可以仔细分析下,node_disk_io_now[5m],意思是我们要挑选出指标node_disk_io_now在5分钟之内的值,然后下面又给定了一个1h,又要挑出一个小时之内的值,所以Prometheus无法绘制成图,抛出异常,所以,Prometheus的绘图要求就是即时向量,它自己会添加一个时间范围的;

向量表达式的使用要点
    表达式的返回值类型可以是即时向量、范围向量、标量和字符串四种类型,如果是标量,它可能是选择了单个时间序列的单个样本,如果是字符串可能返回的是字符串名称之类的,因为本身内部是没有字符串值的,它返回的值之内是上述四种之一,但是有些使用场景,它的返回值必须满足特定条件;
    比如要绘图,我们只能使用即时向量的这种结果,但是对于rate这样的速率函数来讲,它又要求必须是范围向量选择器,而它返回的结果,却是即时向量,比如,我们要返回5分钟之内的平均值;

    rate用来求平均值的,上图则是对node节点的CPU进行平均值计算,以每五分钟长度为单位,求过去一个小时内的每五分钟的平均值,进行绘图,所以说,对于rate这样的函数来讲,它是一定要给定一个范围向量,来求平均值的,但这个平均值的结果,却又是一个即时向量,事实上返回向量,机会总是结合平均值类的rate函数一起使用的,只要加范围向量,机会都会使用rate这样都函数;

即时向量选择器

    即时向量选择器由两部分组成,指标名称和匹配器,指标名称可选,匹配也可选,但不能两个都可选,至少给定一个;
指标名称:用于限定特定指标下的时间序列,即负责过滤指标;
匹配器(Metcher):或称为标签选择器,用于过滤时间序列上的标签,定义在{}之中;
匹配器(Matcher)
    对于Prometheus的匹配器来讲,主要用于过滤条件,对标签进行过滤,目前主要支持四种匹配操作符,这个匹配操作符,指的就是标签要满足某种条件,如下;
=:等值比较,相等为真;
~=:不等值比较,不等为真;
=~:模式匹配比较,此处将采取完全匹配模式,不能部分匹配,匹配为真;
!~:模式不匹配比较,此处将采取完全匹配模式,不能部分匹配,不匹配为真;
    此外,我们也可以使用__name__作为标签名,来对指标名称进行过滤,例如,{__name__=~"http_requests.*}能够匹配所有以"http_requests"为前缀的所有指标;

范围向量选择器

    范围向量选择器和即时向量选择器的不同之处在于,范围向量选择器需要在表达式后紧跟一个方括号[]来表达,需在时间序列上返回的样本所处的时间范围,一般都是结合rate或者irate类的函数来使用的,用来进行聚合计算;
    时间范围,以当前时间为基准时间点,指向过去一个特定的时间长度,例如[5m],指的就上过去五分钟之内,必须使用整数时间,且能够将多个不同级别的单位进行串联组合,以时间单位由大到小为顺序,例如1h30m,但不能使用1.5h;
    时间格式,一个整数后面紧跟一个时间单位,例如"5m"中的"m"即是时间单位,可用的时间单位有"ms"、"s"、"m"、"h"、"d"、"w"和"y";
    需要注意的是,范围向量选择器返回的是一定时间范围内的所有数据样本,虽然不同时间序列的数据抓取时间点相同,但他们时间戳并不会严格对齐,因而,Prometheus在趋势上是准确的,但并非绝对精准,因为抓取的时间点是分散开的,不可能每次才就的时间点都是一样;

偏移量修改器

    上面说过范围向量,它可以查看指定之间之内的指标数据样本,那么我们如果想查看指定时间之前的指标数据样本呢,此时我们就需要使用偏移量修改器,它可以让我们查看指定指标指定时间之前的数据样本,例如node_disk_io_now offset 5m代表查看node_disk_io_now指标,五分钟之前的数据样本,返回一个样本;
    当然,我们也可以这样使用node_disk_io_now[1h] offset 5m,它代表的意思是,从五分钟之前开始算起,取指标node_disk_io_now一个小时内的所有数据样本;

PromQL指标类型

    PromQL有四个指标类型,他们主要由Prometheus的客户端库使用,主要有Counter、Gauga、Histogram和Summary;
Counter:计数器,单调递增,数值一定数增长的,除非重置清零,这种数据一般不会直接展示,而是对特定时间范围内做rate或irate或avg等计算;
Gauga:仪盘表,可增可减的数据;
Histogram:直方图,把一个时间范围内的样本分成多段,每一段单独进行计算,比如,对每一段取出平均值或者求和,然后成图;
Summary:类似于Histogram,不同的是客户端会直接计算并上报分位数; 

Counter
    通常Counter的总数并没有直接作用,而是需要借助于rate、topk、increase和irate等函数来生成样本数据的情况(增长率);
rate(http_requests_total[2h]):获取两小时内,该指标下各时间序列上的http总请求书的增长速率;
topk(3,http_requests_total):获取该指标下所有时间序列的http请求总数排名前三的时间序列;
irate(http_requests_total[2h]):高灵敏度函数,用于计算指标的瞬时速率,它主要是基于样本范围内的最后两个样本进行计算,相较于rate函数来说,irate更适用于短期时间范围内的变化速率分析;
Gauge
    Gauge主要用于存储其值可增可减的指标样本数据,常用于进行求和、取平均值、最大值、最小值等聚合计算,也经常结合PromQL的predict_linear和delta函数使用;
predict_linear(v range-vector,t,scalar):函数可以预测时间序列v在t秒后的值,它通过线性回归的方式来预测样本数据的Gauge变化趋势;
delta(v range-vector):该函数计算范围向量中的每个时间序列元素的第一个值与最后一个值的差,从而展示不同时间点上的样本值差值,如delta(cpu_temp_celsius{host="web01.cce.com"}[2h]),返回该服务器上的CPU温度与2小时之前的差异;
Histogram
    Histogram,即直方图,我们可以从下图直接看出,位于某个时间点有多少,所以它比平均值要好很多,而且更重要的是,它给我们展示出来的结果,是以某个时间范围内的平均值或者中位数是多少,所以它是一种对数据分布情况进行图形展示的;
    Histogram是一种对数据分布情况的图形表示,由一系列高度不等的长条图或线段表示,用于展示单个测度的分布;
    它一般用横轴表示某个指标纬度的数据取值区间,用纵轴来表示样本统计的频率或频次,从而能够以二维图的形式展现数值的分布状况,为了构建Histogram,首先就将值的范围进行分段,换一句话说就说将所有值的整个可用范围进行分段,而后统计每个间隔中有多少个值;

    对于Prometheus来说,Histogram会在一段时间内,对数据进行采样,并将其计入可配置的存储桶中(一个范围就是一个桶),然后Histogram会将特定测度的取值范围分割为多个样本空间,并通过对落入桶内的数据样本进行计数以及求和操作,桶的概念其实就是一个柱状,如下图;

    需要注意的是,Prometheus的Histogram取值间隔划分采用的是累积区间,累积区间,所以,它是一个累积直方图,每一个桶的结果,都是当前的桶与前一个桶的和,所以叫累积,所以它一定是递增的,因为它是不断的往上增加的,如下图,灰色部分就是Histogram的直方图,所以说,累积直方图说不行的,我们需要想办法换算成绿色的,有波动的;
    Prometheus这样做的原因,主要有三点,第一,降低Histogram的维护成本,第二,使得其支持粗略计算样本值的分位数,第三,单独提供了_sum和_count指标,从而支持计算平均值,和除以计数也就是平均值;

    对于每一个Histogram类型的指标来讲,它会有N个时间序列,每个时间序列通过边界区分,比如第一个桶的边界是小于等于5,第二个桶的边界是小于等于10,第三个桶的边界是小于等于15,以此类推;
<metrics_name>_bucket{le="存储桶上边界"}:le即小于等于,表示该桶的指标值边界,一旦有这个le,就表示值小于等于多少,就属于这个桶,其中,最大边界包含所有样本,因为Histogram是累积直方图,数据会越来越大,所以最大边界表示为<metrics_name>_bucket{le="+Inf"}意思是比所有le都大的指标值,就属于这个桶;
<metrics_name>_sum:所有样本观测值的总和;
<metrics_name>_count:总的观测次数,它本身是一个Conter类型的指标,只增不减,累积值;

    因为Histogram是累积直方图,如果要知道一个桶的实际样本数,需要利用该桶的样本数减去前一个样本数,得到就是当前桶的实际样本数,Prometheus提供了一个histogram_quantile()函数,就可以直接计算,它可以直接根据Histogram指标来计算某个桶的样本数在所有样本数中占据的比例,但是它的预测结果只是一个预估值,并不完全准确,如果我们要想准确可以使用Summary;
Summary
    Summary和Histogram是一样的,它们之间唯一的区别就是Summary的数据是客户端算好了之后得来的,而不需要Prometheus  Server去计算了,反观Histogram,它的数据通过线性回归的方式估算出来的,并不准确,因此Summary是一种类似Histogram的指标类型;
    但是它是在客户端于一段时间内(默认10分钟)的每一个采样点进行统计,而不是一个采样点,计算并存储了分位数的数值,不过需要知道的是Summary是不支持sum或avg一类的聚合计算的,因为它的分为数是由客户端生成的,我们就没法算了,没法做二次聚合,所以从某种意义上来讲,Histogram有很好的灵活性,而Summary对服务端产生的压力较少;
<metrics_name>{quantile="<φ>"}:其中φ是分为点,其取值范围是(0<=φ<=1),属于计数器类型指标,比如,0、0.5、0.75和0.99几个分为点,他们是百分位点,所谓0.5指的就是百分之5,所谓0.75就是百分之75,大概意思就是百分之75的数据位于哪个区间内;
    拿请求时间为例,如果我们认为每一次请求响应,1秒钟是我们认为的合理范围,那么我们可以看下是不是百分之99的请求都在一秒钟得到响应了,换一句话说,只有1%的请求大于1秒,用百分数来说,就说只有百分之1的大于1秒,那么我们可以认为我们的网站响应正常的;
<metrics_name>_sum:所有样本观测值的总和;
<metrics_name>_count:总的观测次数,它本身是一个Conter类型的指标,只增不减,累积值;

发表评论