3.scalar 标量 :一个简单的浮点值
4.string 字符串 :一个当前没有被使用的简单字符串操作符
使用PromQL除了能够方便的按照查询和过滤时间序列以外,PromQL还支持丰富的操作符,用户可以使用这些操作符对进一步的对事件序列进行二次加工。这些操作符包括:数学运算符,逻辑运算符,布尔运算符等等。
PromQL支持的所有数学运算符如下所示:+ (加法)
- (减法)
* (乘法)
/ (除法)
% (求余)
^ (幂运算)
举例说明↓↓↓
例如我们查询主机的内存大小,返回的是Bytes,如果我要把他转换成G可以使用一下表达式:node_memory_MemTotal_bytes / 1024 /1024 /1024返回的结果是一个瞬时向量。两个瞬时向量之间的数学计算例如:node_disk_written_bytes_total + node_disk_read_bytes_total 那么我们会发现是根据表达式的标签进行数学运算,分别算出vda、vdb的磁盘io。Prometheus支持以下布尔运算符如下:== (相等)!= (不相等)> (大于)< (小于)>= (大于等于)<= (小于等于)使用bool修饰符、返回匹配的查询结果↓↓↓例如:通过数学运算符我们可以很方便的计算出,当前所有主机节点的内存使用率:(node_memory_bytes_total - node_memory_free_bytes_total) / node_memory_bytes_total而在我们写告警规则的时候我们需要筛选出,内存使用率超过百分之95的主机、则可以使用布尔运算表达式:(node_memory_bytes_total - node_memory_free_bytes_total) / node_memory_bytes_total > 0.95Prometheus 支持以下集合运算符:
通过集合运算,可以在两个瞬时向量与瞬时向量之间进行相应的集合操作↓↓↓and (并且)
or (或者)
unless (排除)
vector1 and vector2 会产生一个由 vector1 的元素组成的新的向量。该向量包含 vector1 中完全匹配 vector2 中的元素组成。
vector1 or vector2 会产生一个新的向量,该向量包含 vector1 中所有的样本数据,以及 vector2 中没有与 vector1 匹配到的样本数据。
vector1 unless vector2 会产生一个新的向量,新向量中的元素由 vector1 中没有与 vector2 匹配的元素组成。
优先级 在 Prometheus 系统中,二元运算符优先级从高到低的顺序为:^*, /, %+, -==, !=, <=, <, >=, >and, unlessor具有相同优先级的运算符是满足结合律的(左结合)。例如,2 3 % 2 等价于 (2 3) % 2。运算符 ^ 例外,^ 满足的是右结合,例如,2 ^ 3 ^ 2 等价于 2 ^ (3 ^ 2)。聚合运算 Prometheus还提供了下列内置的聚合操作符,这些操作符作用于瞬时向量。可以将瞬时表达式返回的样本数据进行聚合,形成一个新的时间序列。
sum (求和) min (最小值) max (最大值) avg (平均值) stddev (标准差) stdvar (标准差异) count (计数) count_values (对value进行计数) bottomk (后n条时序) topk (前n条时序) quantile (分布统计)
使用聚合操作的语法如下:<aggr-op>([parameter,] <vector expression>) [without|by (<label list>)]其中只有count_values, quantile, topk, bottomk支持参数(parameter)。without用于从计算结果中移除列举的标签,而保留其它标签。by则正好相反,结果向量中只保留列出的标签,其余标签则移除。通过without和by可以按照样本的问题对数据进行聚合。sum(http_requests_total) without (instance)等于:sum(http_requests_t;otal) by (code,handler,job,method)如果只需要计算整个应用的HTTP请求总量,可以直接使用表达式:sum(http_requests_total)查询数据的平均值:avg(http_requests_total)查询最靠前的3个值:topk(3, http_requests_total)常用函数 Prometheus为不同的数据类型提供了非常多的计算函数,有个小技巧就是遇到counter数据类型,在做任何操作之前,先套上一个rate()或者increase()函数。下面介绍一些比较常用的函数帮助理解:increase()函数:该函数配合counter数据类型使用,获取区间向量中的第一个和最后一个样本并返回其增长量。如果除以一定时间就可以获取该时间内的平均增长率:
increase(node_cpu_seconds_total[2m]) / 120 #主机节点最近两分钟内的平均CPU使用率rate()函数:该函数配合counter类型数据使用,取counter在这个时间段中的平均每秒增量。
rate(node_cpu_seconds_total[2m]) #直接计算区间向量在时间窗口内平均增长速率sum()函数:在实际工作中CPU大多是多核的,而node_cpu会将每个核的数据都单独显示出来,我们其实不会关注每个核的单独情况,而是关心总的CPU情况。使用sum()函数进行求和后可以得出一条总的数据,但sum()是将所有机器的数据都进行了求和,所以还要再使用by (instance)或者by (cluster_name)就可以取出单个服务器或者一组服务器的CPU数据。上面的公式可以进化为:
sum( increase(node_cpu_seconds_total[1m]) ) #先找出每一个,然后再合并Topk()函数:该函数可以从大量数据中取出排行前N的数值,N可以自定义。比如监控了100台服务器的320个CPU,用这个函数就可以查看当前负载较高的那几个,用于报警:
topk(3, http_requests_total) #统计最靠前的3个值predict_linear()函数:对曲线变化速率进行计算,起到一定的预测作用。比如当前这1个小时的磁盘可用率急剧下降,这种情况可能导致磁盘很快被写满,这时可以使用该函数,用当前1小时的数据去预测未来几个小时的状态,实现提前告警:
predict_linear( node_filesystem_free_bytes{mountpoint="/"}[1h],4*3600 ) < 0 #如果未来4小时后磁盘使用率为负数就会报警CPU利用率表达式拆解 1.先把key找出来,比如是为了查看CPU的使用率,那么就应该使用:
node_cpu这个key2.在node_cpu这个key的基础上把idle的CPU时间和全部CPU时间过滤出来,使用{}做过滤:
node_cpu_seconds_total{ mode='idle' } #找出空闲CPU的值node_cpu_seconds_total #不写其他参数代表ALL3.使用increase()函数把1分钟的数据抓取出来,这个时候取出来的是每个CPU的数据:
increase(node_cpu_seconds_totalmode='idle'}[1m])4.使用sum()函数求和每个CPU的数据,得到单独一个数据:
sum( increase(node_cpu_seconds_total{mode='idle'}[1m]) )5.sum()函数虽然把每个CPU的数据进行了求和,但是还把每台服务器也进行了求和,所有服务器的CPU数据都相同了,还需要进行一次处理。这里又引出了一个新函数 by (instance)。它会把sum求和到一起的数值按照指定方式进行拆分,instance代表的是机器名。如果不写by (instance)的话就需要在{}中写明需要哪个实例的数据。
sum( increase(node_cpu_seconds_total{mode='idle'}[1m]) ) by (instance) #空闲CPU一分钟增量6.获取CPU空闲时间占比:
sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by(instance) /sum(increase(node_cpu_seconds_total[1m])) by(instance)7.CPU的利用率:
1-(sum(increase(node_cpu_seconds_total{mode="idle"}[1m])) by(instance) /sum(increase(node_cpu_seconds_total[1m])) by(instance)) * 100最终计算可能为负数,可能好多granafa模板都这样,当cpu处于多核、低负载的情况下,值的差异会被放大,从而导致出现负数的情况。
谁说运维是一块砖?提升运维工作价值一起学习《Devops之监控神器Prometheus》