PromQL:检测一个指标何时更改,而另一个指标不更改

PromQL: Detect when one metric changes while another does not

提问人:elbino 提问时间:11/16/2023 最后编辑:elbino 更新时间:11/16/2023 访问量:117

问:

我有两个指标:和 .我想检测何时更改,而几分钟没有。作为伪代码,你可以说:my_bytes_inmy_bytes_outmy_bytes_inmy_bytes_out

IF my_bytes_in changed over the last five minutes while my_bytes_out did not 
THEN return 1 
ELSE return 0

在 PromQL 中,我构建了以下查询:

((vector(1) and on() (sum(my_bytes_in{project="$Project", stage="$Stage", myname=~"$My_Name"}) - sum(my_bytes_in{project="$Project", stage="$Stage", myname=~"$My_Name"} offset 5m)) != 0 and (sum(my_bytes_out{project="$Project", stage="$Stage", myname=~"$My_Name"}) - sum(my_bytes_out{project="$Project", stage="$Stage", myname=~"$My_Name"} offset 5m)) == 0) or on() vector(0))

无论如何,您可以使用 rate() 而不是使用该 offset 方法。这仅适用于一个变量组合:

Grafana 截图

一旦我对变量进行多选,我仍然只得到一个图形。另外,由于使用了标签,所以也许我需要一种非常不同的方法?$My_Namevector()

是否可以获得一个指标作为 PromQL 结果,用于执行此异常检测并支持变量输入的多选?目前我不知道如何实现这一目标。

Prometheus Grafana 指标 PromQL

评论

0赞 markalex 11/16/2023
如果条件为 false,您需要 0 吗?
0赞 markalex 11/16/2023
您希望在结果中具有哪些标签?全部存在于源指标中,还是仅存在于选择器中使用的指标中?
0赞 elbino 11/16/2023
@markalex 我希望具有源指标中的标签,至少是查询中提到的三个标签,并用于变量。如果条件为假,则为 0 会很好,但也许我可以没有它。

答:

0赞 star67 11/16/2023 #1

不确定我是否理解一切,但我会尝试=)

changes() 函数

changes() 函数显示其值在提供的时间范围内更改的次数。

例如,过去 5 分钟内指标的变化量(为简单起见省略标签):my_bytes_in

changes(my_bytes_in{}[5m])

布尔值

Bool 运算符可用于将过滤条件转换为 和 (我们稍后将使用它们进行乘法)10

如果在过去 5 分钟内有变化,则显示指标,如果没有变化,则显示:1my_bytes_in0

changes(my_bytes_in{}[5m]) > bool 0

如果在过去 5 分钟内没有变化,则显示指标,显示有一些变化:1my_bytes_in1

changes(my_bytes_out{}[5m]) != bool 0

向量匹配

由于您按标签 、 、 进行筛选,我想您希望通过所有其他标签匹配结果。projectstagemyname

让我们一起结合:

(changes(my_bytes_in{project="$Project", stage="$Stage", myname=~"$My_Name"}[5m]) > bool 0) 
  * ignoring (project, stage, myname)
(changes(my_bytes_out{project="$Project", stage="$Stage", myname=~"$My_Name"}[5m]) != bool 0)

因此,生成的查询仅返回两个条件都返回 (*=) 的时间序列,否则返回。111110

评论

0赞 elbino 11/16/2023
这是行不通的。虽然目前没有 5 分钟的间隔my_bytes_in改变而my_bytes_out没有改变,但我得到了一个从 0 跳到 1 然后回来的上下图。另外:如果我从仪表板的下拉列表中多选 myname,我会得到:“execution: found duplicate series for the match group {} on the right hand-side of the operation: [{my_name=”5100_test“}, {my_name=”5200_test“}];不允许多对多匹配:匹配标签的一侧必须是唯一的”
0赞 elbino 11/16/2023
但你让我进入了正确的方向!--> (sum by(stage, myname) (changes(my_bytes_in{project=“$Project”, stage=“$Stage”, myname=~“$My_Name”}[5m])) != 0 and sum by(stage, myname) (changes(my_bytes_out{project=“$Project”, stage=“$Stage”, myname=~“$My_Name”}[5m])) == 0) --- 这确实如我所愿。我只需要将找到的任何值转换为 1,如果没有找到任何值,那么它应该是 0。
0赞 star67 11/16/2023
@elbino考虑为此使用运算符bool
0赞 elbino 11/16/2023
谢谢,看起来现在这似乎有效。:)
0赞 star67 11/17/2023
@elbino随时改进我的答案,使其对其他 SO 用户有用