开发者学堂课程【3天吃透 Prometheus:PromQL 进阶】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1244/detail/18448
PromQL 进阶
接下来我们需要求出每一个路径下各类响应码的速率增长之和,因为它的每一类响应码是不是都有增长,各类响应码的数据增长之和。我们该怎么求,稍微麻烦一点,因为这里表达的不完整。我们依然是使用rate(http_requests_total│[5m]),但是这次我们要计算各类序时间序列的不只是status的code等于5XX?这就表示各个时间序列,各类响应码下,各个路径下,它各自的增长率是这么多高,但是对于每一类,我们还要干什么?求和每一类路径要求和,这样才能对路径下的响应码进行做比例计算,因此我们要把它生成结果当一个独立的时间序列做聚合计算,怎么聚合?sum by pass,我们以路径只要是同一路径下的所有的增长率,加一个和包括5XX,2XX,3XX求和,这是聚合运算和函数运算结合起来,去求它是不是大于0.乘它才对。这才是我们所要期望得出来的逻辑。
知道我们的聚合运算,它的聚合运算的优先级,二元运算符,因而已经很高就不用考虑,因而这应该会先做聚合计算,乘以0.1,计算5XX响应码的增长率在对应的增长率下是不是大于0.1。很显然,对时间序列来讲,后面生成的时间序列要看它的标签是什么,我们还要对标签做一些简单的修正。对于后面时间序列来讲,它的标签是什么?我们是计算的各类响应码下,我们又以pass进行聚合,它标签跟前面是不是都是一样?也就意味着前面十分序列应该有两个标签,后面应该也是有两个标签。
举个例子,刚才我做简单的测试,我们的prometheus自己正好有一个类似的指标叫做Prometheus http request total,它的标签会更多,我们假设统计每类URL下不管它叫handler之下,其响应码为400的占比是多少,各位来看,是不是只有这一个handler有code等于400的响应码?因此其实相当于我们就算这一种。而对这一个URL来讲,能看200的响应码的有一个增长,有应该有一个采样值,400是不是有个采样值?正常情况下,我们应该分别算出来200的增长率,400的增长率,再用400的增长率除以400加200的增长率,才是我们所希望的结果。比如我们有红橙黄绿青蓝紫集合,告诉你红的个现在是一个,请问黑的比例在整体中占的比例是多大?很显然,你得对整体有多少个先取和,再用黑的取个和对它进行比较。
因此我们这里的计算方法就应该跟他类似。比如我们使用prometheus request对他5分钟之内的范围向量求速率计算。我们只期望算一下响对应的响应码400所占的比例是多大,各自400的比例占的是多大?首先计算出来这一半,它结果是0,这就很难有什么占比。
这是5分,最近5分钟,没有什么出现什么错误。最近5小时,5个小时还有一点。我就按6个小时计算大概占比是这么大,它的增长率是这么大,这是第一点。先记住表达式,我们还要算出来所有响应码下增长率之和,意味着我们还要把code删除,我先把复制出来,等下我还要使用它,现在去掉,这样计算,这就意味着是所有时间序列增长之和,现在我要把那些pass路径相同的给它加起,当然只有它的pass路径这里是有相同,其它是不是都不同?我们要对它以路径作聚合,要使用sum by handler做聚合,后面要当成一个序列,序列要用括号括起,大家知道在聚合计算中,所以这计算结果各个handler到底是多少?
其中APIquery其中就包含400+200的和,我现在要比较什么?比较刚才400的结果是不是要大于0.1乘以它,意思就是400的所占的比例增长率是不是比所有的增长率的比例之和大于它的10%,超过10%,如果为空,不大于10%,没有大于10%,这对我们来讲是最理想的状态。可能得一个结果出来,比例太小,可能比例实在是太小。
我们再重复一遍,看左右两侧,我们来看左右两侧,他们的标签是不是一样。两种计算出来的结果,你看标签是不是都保留着,这是左侧的,再看右侧的标签是不是一样。如果不一样,你的取值一定不会有结果。
所以我们还要想办法使用哪个标签来进行计算。这个为值来进行计算,因为它俩的标签不一样,不一样能比较出来结果?不能。我们接下来还要干什么?指明基于哪个标签进行计算。因此在这里使用0.1相乘的时候还要在这表达式上指定位置。我们要忽略或者只针对哪个标签进行计算,只针对handler一个标签进行计算。进行做比较,进行做聚合,这又少个括号,好叫onhandler。这次我们比较的时候才能比较出结果,不然双方的标签很难一致。这是我们整个计算中的问题,所以我们事例当中所表达的过于简陋,因为我们没法事先没法假设它有多少个标签,不知道它到底真正的计算意义是什么,我回头把它修改。这个问题我觉得我来讲应该能解决。
但是看我们写的表达式,看起来是不是有点投影眼花的感觉?但是你要记住这一点,像表达式你可以记录下来报警,你别忘这是报警条件。如果说我这里可能写的有点过于夸张,正常情况下,我们认为它要大于5%,就开始报警,因为出错太多。经常有这么多404,我们的换成404,假设你正常网站有些响应码是404的,但是我们算一算过去6个小时平均的增长率,404的响应居然在总体增长率当中大于5%。这就意味着有5%的用户在请求你的网站时,得到的页面都是404,难道还不报警吗?你不知道你网站出什么问题吗?这就是一个报警条件。一旦满足这个条件,我就向用户发邮件或者发微信或者发短信来进行报警。而只有写出来这样的表达式才能触发报警。不知道你触发什么报警网站有人请求就报警吗?肯定不对。
我们再来看多对多。多和一对多的区别在于,sorry。一对多和多对一的区别在于我们要指定谁是多方,谁是一方,它不支持多对多,所以一定有一方是一,一方是多。多指的是1这一侧的每个元素可以与多侧的多个元素进行匹配,而不像刚才我只能左侧是一个,右侧也只能出现一个,多一个都不行。究竟左侧是多还是右侧是多?使用groupleft或者groupright来明确指定哪侧为多侧就行。注意我们指的是哪一侧为多的一侧。所以它就有这样4个表达式,或者叫4个语法格式。
首先第一种表示左侧是多的侧,右侧是一侧,右侧为多侧,左侧为一侧。但我们要指明在比较时忽略哪些标签,同时也可以指明在连接时使用哪个标签。所以他这种组合方式主要是他们的变化。
就这样的组合,看一个示例应该容易理解。看这个示例首先。
Method_code:http_errors:rate 5m/ignoring(code)group_left method:http_requests:rate5m
与ignoring code仍然把code给它忽略,grouplight注意左侧为多,这表示左侧为多侧。右侧一侧是什么?method request rate
五分钟其实它指的是在实例的基础之上,你仍然是有这些数据。和这些数据。在这些数据的基础之上,我们要分析他们是怎么连接,左侧是谁?是method code,意味着有什么响应包含响应码,右侧是只有method,就不包含响应码。所以左侧可能会有多项在标签比较的时候能匹配到右侧上来。而且我们的ignored code于是结果就是method get ,code等于500的时候匹配到右侧。Method =get右侧method应该我们刚刚说过,右侧一共有3个值,分别是660和21。分别对应三个方法get,dial和post三个方法。
对于左侧而言,methd get ,code有method get code404有一组,还有200有一组得到的结果。所以method等于get,我们有忽略code就意味着双方都是get时,右侧是200,600,左侧是24是一个。响应码是500的,响应码是404的,30是一个。所以左侧有这两种变化,Method都是get,而右侧method get只有一种。因而左侧两个时间序列与右侧一个时间序列建立连接。这就表示它能分别计算,不同响应码在同一种方法当中所占据的比例。这就叫多对1的匹配。只要一对一能理解,多对一,一对多应该也没什么难理的地方,只是多的一侧能出现多个与右侧的1的一侧唯一匹配的例子。来,我们就实现这样的连接就行。
我现在不看它,回过头我们自己让你把它换成多对1的表达式,看你能不能想通,直接看到这里的实例,所得的1指的是method各是一个,而对左侧,对上面来讲,识别序列来讲,各能看到get这个方法是不是出现有两个时间序列?pose这个方法是不是有两个时间序列put只有一个?
所以如果不考虑code的情况下,上下两个时间序列连接的时候会有什么问题?
我认为上面是多侧,下面这个是一侧,就意味着我们24是不是可以跟600连接?24跟600能够对应起?你只做什么计算,你自己下操作符就行。30是不是可以跟600也能对应起来?而后三跟谁对应有没有就删除,不显示不连接。6跟谁对应120,所以6连接120,后面21还是120没问题,在右侧,30岁没用不出现。大家有没有发,这好像求的是一种交集,但这种交集过程当中不是1对1,直接交集的是这样子,而是多对1的。所以出现就这样几种结果。
相反如果让一对多会有什么情况,会不会出现这里能不能一对多?上面当一方,下面当多方。好像不行,因为多方这里每一种是不是就只出现一个?所以你要能作为多方的,能作为一方的其实大体上我们判断一下标签能不能判断出来多方,一定是标签有更多更复杂的组合,它能包含一方的组合,这就是所谓要多对1的匹配示例。
一对多反过来是一样,只不过多的一侧发生变化。我就不再花时间介绍。
四、promQL 的解析过程
我们来看promql的解析过程,promQL现在各位知道,像包括我们刚才写的那么绕的,它也只是一段文本而已,这是我们迄今为止写的最复杂的表达式之一,它只是一段文本而已,这段文本将会被我们的prometheus的promql引擎加载以后所解析,怎么解析?首先我们要计算是不是一个instant叫即时向量,如果是怎么办?如果不是集成量,看评估一下是不是范围向量,如果不是怎么办?接着看是不是标量,如果是怎么办?如果不是怎么办?接着再看是不是一个vector evaluation,有没有必要向量评估等,所以我们说叫请求数据时。Step,这叫interval,它设定相邻两个点的间隔,promql,每次evaluation都是针对某个确定的时间点和statement表达式来进行计算的,会得到一个时间戳相同的向量,,我们不必要纠结它.这就是prmql的基本使用逻辑,应该没有什么更复杂的语法,但是我们接下来要补充一个,刚才我PPT当中没有写进去的,我们prometheus的函数,刚刚我们看到聚合函数,但是你发现rate包括我们曾用到的这些都不是聚合函数,它就是内置的函数,能够在你的对应的时间序列上做计算,所我们可以理解为它们就是我们的prometheus的函数,这些函数就没有聚合函数的约束或者限制。他们各自所适用的时间序列类型可能会略有不同。来看它函数的哪,这里functions,这里列出来我们prometheus的目前的2.23版本,注意版本,因为这是最新的所支持的函数。
常见函数有这么多个,我们大体上给各位简单说明我们过去使用过的函数。比如我们曾经用过rate,我们以rate为例来说明,这里rate它告诉我们rate的语法格式,rate我们要带的是一个range vector,意思我们要传参数,注意它们用逗号隔开,就表示一个参数。参数必须是一个范围向量,意思就是对范围向量对应的范围内的数据做增长率计算,这叫rate。因而我们这必须给一个范围向量。rate这里告诉我们应该仅用于计数器上,因为对于GAG类型的数,你做rate计算没有任何意义,因为GAG本身就代表随时间变化的量,而counter没能直接表达随时间变化的结果,所以我们要采使用rate进行计算的。而rate的计算结果还可以求和。When combining rate with aggregation operatore,意思就是我们把rate函数和sum函数联合起来计算或者或聚合函数sum结合起来计算时,你要先算rate后求和,这就是强调这个意思。
接着再说比如像ABS英语得什么意思?求绝对值,absent就判断它是否为空的为returns empty vector if
The vector passed to it has elements and one element vector.
意思就是判断我们要传一个及时向量,我们对及时向量求它的结果,看看它的内容是不是或者内部是不是不包含任何样本。这叫absent,叫不存在样本,只是这意思。
irate跟rate意义是一样,它也是做增长率计算的,但是它的增长率计算比较独特,只使用should only be used when graphing volatile fast moving counters,意思就是那种计数器变化速度非常快的,而且我们在短时间内求它的增长率。我们也使用irate,因为它不像rate,是在你的时间范围内的所有增长率都取出来求平均值。而irate只是把最后两个数的差拿来当速率,而不是求平均值的,所以它的计算方式与rate不同。它的灵敏度更高,但是它只适用于短时间内的速率,不适合长时间样本用中的速率计算,我们还可以使用label join label replace,手动的人为的在指定的向量上去修改他们的标签,比如让标签连接起来去替换标签等,直接使用这两个函数也能做到,我们不必要非得去使用标签重写机制,这是这两个函数。
可能我们偶尔会用到的一个叫做叫predict linear。我们说过这叫predict,叫预算预估,linear叫线性意思,所以它利用线性回归的方式来评估你所给定的这个范围向量,在未来的某个时间之后,这是个标量,大概它的值、样本值会变化到多少,因而我们经常拿它去做一个预测。比如我预测一下某个层磁盘,比如我们有个指标,它统计我们的磁盘空间的剩余量剩余比例或者叫做某一个挂载点的文件系统的剩余空间的剩余比例,我们根据现在的采样结果比例的采样结果可以评估比如未来12个小时后,剩余的比例是不是会小于5%,它能帮你预算出来,用这个能预算出来后,还是那句话,它不小于5%最好。
如果小于5%就该报警,因而这是一个常用的基于回归分析做预测的报警,让我们提前能够预知问题的一个内介函数,所以在我们的报警当中经常会用到the predict linear,注意它的语法格式,我们要传递一个范围向量,给一个时间标量,这表示我们要预测多久以后,对于这样一个范围,下面讲它的样本值大概会增加到哪个阶段或者哪个值上,我可以利用值给我们的阈值进行比较,阈值就是我们认为接受的上限或者下限,这是我们还剩一个话题,叫做函数prometjeus的内介函数,有些函数在聚合函数中也会出现,像sum,AVG,我们都会有聚合计算的表操作符和函数操作符,它的表达格式可能会有所不同,各位要注意。