我用几个例子一步一步拆解一些常用的写法和指标。
例子一
这里我有一个需求是计算我的程序,每处理 1Gb 数据需要使用多少 CPU 时间。
(increase(container_cpu_usage_seconds_total{cluster="$cluster", namespace="$namespace"}[5m]) / on(pod, container, namespace) increase(enrich_event_bytes_total{cluster="$cluster", namespace="$namespace"}[5m])) * (1024 * 1024 * 1024)
increase/rate:
我们除了 increase 还经常使用 rate.
在Prometheus中,rate
和increase
函数都是用来处理计数器类型的时间序列数据。计数器是一种只增不减的指标,它常用来表示累积值,例如累计使用的CPU时间。然而,rate
和increase
在它们处理和计算这些数据方面存在一些关键的区别:
-
rate():
rate()
函数计算在给定时间范围内的平均增长率。
- 它是一个瞬时的概念,通常用来了解“每秒”这样的速率。
rate()
会处理计数器重置(例如,由于容器重启)和抓取间隔的影响,尝试提供一个平滑的估计。
- 适用于计算指标的瞬时变化,如每秒请求数。
-
increase():
increase()
函数计算在给定时间范围内计数器增加的总量。
- 它会考虑整个时间范围,并给出开始和结束时刻之间的增量值。
- 和
rate()
一样,increase()
也会处理计数器的重置情况。
- 通常用于计算在某个具体时间范围内的总变化量,如在过去5分钟内接收到的总数据字节数。
简单理解,一个是算平均值的,一个是算总值的。在这里因为我最终要做一个除法,所以我打算获取一个增量的值,
[1m]/[5m]/[10m]:
在Prometheus查询语言中,[5m]
是一个时间范围选择器,它指定了查询应该考虑的历史时间窗口大小。在这个上下文中,increase(enrich_event_bytes_total[5m])
的意思是计算指标enrich_event_bytes_total
在过去5分钟内的增加量。
这是如何工作的:
enrich_event_bytes_total
是一个计数器,它不断增加,每次处理事件时都会增加表示该事件大小的值。
- 当您对这个指标应用
increase()
函数时,Prometheus会查看5分钟前该计数器的值和现在的值。
- 然后,它计算两个值之间的差异,这就是在5分钟内的“增加量”。
- 如果在这5分钟内有任何计数器重置(例如,由于容器重启),Prometheus也会正确处理这种情况,确保提供一个准确的增加量。
时间范围选择器[5m]
是可配置的,您可以根据需要设置不同的时间长度,比如[1h]
表示1小时,[10s]
表示10秒等。选择合适的时间范围对于准确反映指标的实际变化非常关键。
总的来说这个可以帮我们划定一个区间数据,以让我们得到这个量。比如这里我使用 5m,5分钟。我只需要同样获取 5m 内增量的 cpu 使用时间 / 5m 内增量的 数据处理总量,理论上就可以计算出 处理 1单位数据(默认单位数据是 1kb,取决于你的上报单位) 需要的 CPU 时间。
On (pod, container, namespace):
这个可以理解为一个 SQL join 操作上的 on,他可以作为拼接条件帮助我们处理的数据。
在Prometheus中,当您尝试对两个指标进行操作时,如果这两个指标的标签集不匹配,那么在进行除法操作时可能会得到空结果。这是因为Prometheus在执行二元操作符(如除法/
)时,默认执行的是标签的精确匹配(也称为内部连接)。
这意味着,只有当两个指标拥有完全相同的标签和相对应的值时,操作才会产生结果。
所以手动指定正确的条件,可以帮助我们计算拥有同样条件的数据。
同样的我们还可以指定别的条件,获取选择忽略一些条件。
-
忽略不匹配的标签: 使用ignore
关键字来忽略不需要的标签,这样可以在执行操作时排除这些标签:
increase(container_cpu_usage_seconds_total{cluster="$cluster", namespace="$namespace"}[5m]) / ignoring(cluster, namespace) increase(enrich_event_bytes_total[5m])
-
使用on
关键字: 指定哪些标签必须匹配,这通常是两个指标共有的一组标签,例如pod
或container
:
increase(container_cpu_usage_seconds_total{cluster="$cluster", namespace="$namespace"}[5m]) / on(pod, container) increase(enrich_event_bytes_total[5m])
请根据实际情况替换pod
和container
为您的指标实际有的共同标签。
-
添加缺失的标签: 如果enrich_event_bytes_total
指标确实应该有cluster
和namespace
这些标签,您可能需要调整收集这些指标的配置,确保标签的一致性。
-
使用group_left
或group_right
: 这些操作允许您在操作不同的向量时保留一个向量的所有标签。这在您希望保持其中一个指标的标签集时非常有用:
increase(container_cpu_usage_seconds_total{cluster="$cluster", namespace="$namespace"}[5m]) / on() group_left increase(enrich_event_bytes_total[5m])
group_left
表示保持左侧指标的标签,group_right
则相反。
例子二
sum(rate(enrich_event_bytes_total{}[$__interval])) by (namespace)
这个Prometheus查询是用来计算每个命名空间(namespace)的enrich_event_bytes_total
指标的速率,并将结果按命名空间聚合。让我们逐一解释这个表达式的组成部分:
-
enrich_event_bytes_total{}:
- 这是一个计数器类型的指标,用于跟踪处理的事件字节数。
- 空的大括号
{}
表示没有应用任何过滤条件,所以它将选择所有的enrich_event_bytes_total
时间序列。
-
rate(...[$__interval]):
rate
函数计算指标在给定时间范围内的平均速率,即单位时间内指标增加的量。
$__interval
是一个变量,通常由Grafana提供,代表一个合适的查询间隔,这个间隔是动态计算的,基于Grafana面板的时间范围或是用户界面上的选择。
-
sum(...):
-
by (namespace):
by
子句指示Prometheus在求和之后要按照namespace
标签进行分组。
- 这意味着它将为每个不同的
namespace
值计算一个总和。
这个按命名空间聚合可以理解成 group by (namespace),所以我们遇到需要将同一个 namespace 下,不同机器上的 metric 都聚合起来。我们可以直接使用这种写法将他们汇总。
相当于这里我们先用 rate(enrich_event_bytes_total{}[$__interval]) 求了个每个 pod 的平均值,然后再加起来 group by 了 namespace ,获得根据 namespace 聚合的总和。
在这里记录一下。