我的数据源是Graphite。
我正在收集简单的指标:对我的应用程序的响应数量,按路由别名和响应代码分组,如下所示:
my_app.prod.count.api.*.*
因此,我可以将错误请求与 4xx 和 5xx 响应代码分组,如下所示:
my_app.prod.count.api.*.4*
my_app.prod.count.api.*.5*
问题是我不想将当前值与之前的值进行比较 - 应用程序流量在一天中发生变化,并且模式似乎每天都几乎相同(即使在周末)。 14天周期见附图:
因此,我希望“Ok”仪表能够将当前 1 小时值与一天中这一小时的值(过去一两周的平均值,以补偿错误部署或其他情况下的突然峰值)进行比较。当该值与平均值相差大约 3 倍标准偏差时,触发“不正常”状态。
我的问题是:查询大约是什么样子?
我见过类似的描述hereas
my_metric / avg_over_time(my_metric[1w])
my_metric / avg_over_time(my_metric[1w] offset 1w)
但不确定如何采用我的情况(正如评论中指出的,它是 Prometheus,而不是 Graphite),触发超过 3 倍的 std dev。
TL;DR: 我想出的办法看起来很糟糕,但似乎做得恰到好处:
aliasByNode(diffSeriesLists(aliasByNode(my_app.prod.count.newgs.api.*.4*, 5, 6), aliasByNode(scale(groupByNodes(timeStack(my_app.prod.count.newgs.api.*.4*, '1w', 0, 20), "stddev", 5, 6), 3), 0, 1)), 0, 1)
timeStack
: 获得过去 20 周(包括本周)的一系列偏移 1 周的系列
timeStack(my_app.prod.count.newgs.api.*.4*, '1w', 0, 20)
(这可以通过 1 天的偏移来完成;用
1w
以及要查看的任意天数替换 20
和 1d
)
然后我们计算每条路线的标准偏差和错误代码。节点命名为
my_app.prod.count.newgs.api.*.4*
,这意味着我们要按第 5 个和第 6 个节点进行分组(此处基于 0 的索引),并应用 stddev
聚合函数,使用 groupByNodes
:
groupByNodes(
timeStack(
my_app.prod.count.newgs.api.*.4*, '1w', 0, 20
), "stddev", 5, 6
)
由于我们想要将当前值与 3 个标准设备进行比较,因此我们应该使用
scale
将结果系列乘以常量(使用 multiplySeries
仅适用于系列,不适用于常量):
scale(
groupByNodes(
timeStack(
my_app.prod.count.newgs.api.*.4*, '1w', 0, 20
), "stddev", 5, 6
), 3
)
然后我们想知道当前值超过过去一段时间计算出的 stddev 多少,使用
diffSeriesLists
。
aliasByNode
应用于两个操作数,并将另一个操作数应用于外部以获得更好的命名:
aliasByNode(
diffSeriesLists(
aliasByNode(
my_app.prod.count.newgs.api.*.4*, 5, 6
),
aliasByNode(
scale(
groupByNodes(
timeStack(
my_app.prod.count.newgs.api.*.4*, '1w', 0, 20
), "stddev", 5, 6
), 3
), 0, 1
)
), 0, 1
)
注意:漂亮的格式仅用于演示目的,grafana 中的实际查询不允许在查询中使用换行符和良好的缩进