Prometheus强大的地方就在于可以使用很多计算公式去获取自己需要的数据。正因为涉及到了计算公式,这也是它的难点所在,比如在Zabbix中要获取CPU使用率是一件很简单的事情,而在Prometheus中却需要使用计算公式来完成。

比如要统计CPU使用率:node_exporter会抓取CPU常用的8种状态的累计工作时间,然后再用(所有非空闲状态的CPU时间总和)/(所有状态的CPU时间总和)= CPU使用率。而如果想要获取中间某一分钟的CPU平均时间还需要用到Counter数据类型。由于Counter的数据一直是增量,所以需要截取其中一段增量值,然后再拿这个数值去套用公式进行计算。


Prometheus为不同的数据类型提供了非常多的计算函数,有个小技巧就是遇到counter数据类型,在做任何操作之前,先套上一个rate()或者increase()函数。下面介绍一些比较常用的函数帮助理解:

rate()函数:这是一个非常重要的函数,专门配合counter类型数据,取counter在这个时间段中的平均每秒增量。比如监控网络接受字节数的情况,在9:10到9:20期间累计量增加了1000bytes,加入rate([1m])函数后就会使用1000除以60秒,计算出数据大约为16bytes。

1rate(  node_network_receive_bytes[1m] )  #获取1分钟内每秒的增量


increase函数:和rate()函数一样也是配合Counter使用。区别就是它是取其中一段时间的增量而不是平均值,比如

1increase(node_cpu[1m])  #获取CPU总使用时间1分钟的增量


sum函数:在实际工作中CPU大多是多核的,而node_cpu会将每个核的数据都单独显示出来,我们其实不会关注每个核的单独情况,而是关心总的CPU情况。使用sum()函数进行求和后可以得出一条总的数据,但sum()是将所有机器的数据都进行了求和,所以还要再使用by (instance)或者by (cluster_name)就可以取出单个服务器或者一组服务器的CPU数据。上面的公式可以进化为:

1sum( increase(node_cpu[1m]) )


count函数:该函数用于进行一些模糊判断,比如有100台服务器在监控,想实现当CPU使用率大于80%的机器达到N台就进行报警就可以使用它

1count(count_netstat_wait_connections > 200)


topk函数:该函数可以从大量数据中取出排行前N的数值,N可以自定义。比如监控了100台服务器的320个CPU,用这个函数就可以查看当前负载较高的那几个,用于报警

1topk(3,count_netstat_wait_connections)  #Gauge类型


2topk(3,,rate(node_network_receive_bytes[20m]))  #Counter类型


absent()

absent(v instant-vector) 如果传递给它的向量具有任何元素,则返回空向量;如果传递给它的向量没有元素,则返回值为1的1元素向量。

这对于在给定度量标准名称和标签组合不存在时间序列时发出警报非常有用。

absent(nonexistent{job="myjob"})
# => {job="myjob"}
absent(nonexistent{job="myjob",instance=~".*"})
# => {job="myjob"}
absent(sum(nonexistent{job="myjob"}))
# => {}

在第二个示例中,absent()尝试从输入向量中导出1元素输出向量的标签。

delta()函数

delta(v range-vector)计算范围向量v中每个时间系列元素的第一个和最后一个值之间的差值,返回具有给定增量和等效标签的即时向量。 delta被外推以覆盖范围向量选择器中指定的全时间范围,因此即使样本值都是整数,也可以获得非整数结果。

以下示例表达式返回现在和2小时之前CPU温度的差异:

delta(cpu_temp_celsius{host="zeus"}[2h])

delta应仅用于仪表。


changes()函数

changes(v range-vector) 输入一个区间向量, 返回这个区间向量内每个样本数据值变化的次数(瞬时向量)。例如

# 如果样本数据值没有发生变化,则返回结果为 1changes(node_load5{instance="192.168.1.75:9100"}[1m]) # 结果为 1



predict_linear函数:对曲线变化速率进行计算,起到一定的预测作用。比如当前这1个小时的磁盘可用率急剧下降,这种情况可能导致磁盘很快被写满,这时可以使用该函数,用当前1小时的数据去预测未来几个小时的状态,实现提前告警

1predict_linear( node_filesystem_free_bytes{mountpoint="/"}[1h],4*3600 ) < 0   #如果未来4小时后磁盘使用率为负数就会报警



了解清楚流程之后进行一个CPU使用率的拆分解析:

1、先把key找出来,比如是为了查看CPU的使用率,那么就应该使用node_cpu这个key

2、在node_cpu这个key的基础上把idle的CPU时间和全部CPU时间过滤出来,使用{}做过滤,如下:

1node_cpu{ mode='idle' }  #找出空闲CPU的值
2node_cpu  #不写其他参数代表ALL


3、使用increase()函数把1分钟的数据抓取出来,这个时候取出来的是每个CPU的数据

1increase(node_cpu{mode='idle'}[1m])


4、使用sum()函数求和每个CPU的数据,得到单独一个数据

1sum( increase(node_cpu{mode='idle'}[1m]) )


5、sum()函数虽然把每个CPU的数据进行了求和,但是还把每台服务器也进行了求和,所有服务器的CPU数据都相同了,还需要进行一次处理。这里又引出了一个新函数 by (instance)。它会把sum求和到一起的数值按照指定方式进行拆分,instance代表的是机器名。如果不写by (instance)的话就需要在{}中写明需要哪个实例的数据。

1sum( increase(node_cpu{mode='idle'}[1m]) ) by (instance)  #空闲CPU一分钟增量


6、最终计算出CPU使用率

11-( sum( increase(node_cpu{mode='idle'}[1m]) ) by (instance) / sum(increase(node_cpu[1m])) by (instance) ) *100



附上三个常用的计算公式:

查看源码打印?

1#CPU使用率
2100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) by (instance) * 100)
3#内存使用率
4(node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100
5#空闲内存剩余率
6100 - (node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes) / node_memory_MemTotal_bytes * 100
7#磁盘使用率
8100 - (node_filesystem_free_bytes{mountpoint="/",fstype=~"ext4|xfs"} / node_filesystem_size_bytes{mountpoint="/",fstype=~"ext4|xfs"} * 100)