使用grafana和Influxdb,我试图显示某个值的计数器的每秒速率。如果我使用non_negative_derivative(1s)
函数,则速率值似乎会根据grafana视图的时间宽度发生显着变化。我正在使用last
选择器(但也可以使用max
,这是一个相同的值,因为它是一个计数器)。
具体来说,我正在使用:
SELECT non_negative_derivative(last("my_counter"), 1s) FROM ...
根据influxdb docs non-negative-derivative:
InfluxDB计算按时间顺序的字段值之间的差异,并将这些结果转换为每单位的变化率。
所以对我来说,这意味着在扩展时间视图时,给定点的值不应该改变那么多,因为值应该是每单位的变化率(在我的示例查询中为1s)上文)。
在石墨中,它们具有特定的perSecond
功能,效果更好:
perSecond(consolidateBy(my_counter, 'max'))
关于上面的涌入查询我做错了什么想法?
答案 0 :(得分:17)
如果您希望每秒的结果不变,则需要GROUP BY time(1s)
。这将为您提供准确的perSecond
结果。
考虑以下示例:
假设每秒计数器的值都这样改变
0s → 1s → 2s → 3s → 4s
1 → 2 → 5 → 8 → 11
根据我们对上述序列进行分组的方式,我们会看到不同的结果。
考虑我们将事物分组到2s
桶中的情况。
0s-2s → 2s-4s
(5-1)/2 → (11-5)/2
2 → 3
与1s
水桶相比
0s-1s → 1s-2s → 2s-3s → 3s-4s
(2-1)/1 → (5-2)/1 → (8-5)/1 → (11-8)/1
1 → 3 → 3 → 3
寻址
所以对我来说,这意味着,扩展的时间视图当在给定点处的值应该变化不大,因为该值应为每单位变化率(在上述我的示例查询1S)。
rate of change per unit
是一个归一化因子,与GROUP BY
时间单位无关。当我们将导数区间更改为2s
时,解释我们之前的示例可能会提供一些见解。
确切的等式是
∆y/(∆x/tu)
考虑我们将事物分组到1s
桶中的情况,其中派生间隔为2s
。我们应该看到的结果是
0s-1s → 1s-2s → 2s-3s → 3s-4s
2*(2-1)/1 → 2*(5-2)/1 → 2*(8-5)/1 → (11-8)/1
2 → 6 → 6 → 6
这看起来有点奇怪,但是如果你考虑一下它说的话应该有意义。当我们指定2s
的派生间隔时,我们要求的是2s
1s
桶的GROUP BY
更改率。
如果我们对导数间隔为2s
的{{1}}存储桶的情况应用类似的推理,那么
2s
我们在此要求的是 0s-2s → 2s-4s
2*(5-1)/2 → 2*(11-5)/2
4 → 6
2s
桶的2s
变化率,在第一个时间间隔内GROUP BY
变化率为2s
,第二个时间间隔4
的变化率为2s
。
答案 1 :(得分:6)
@ Michael-Desa给出了一个很好的解释。
我希望通过解决我们公司感兴趣的一个非常常见的指标来增加答案:" 最大"每秒操作次数&#34 34;特定测量领域的价值?"。
我将使用我们公司的真实案例。
我们将大量数据从RDBMS发送到redis。传输数据时,我们会跟踪5个计数器:
TipTrgUp
- >业务触发器(存储过程)的更新TipTrgRm
- >通过业务触发器(存储过程)删除TipRprUp
- >通过无人参与的自动修复批处理进行更新TipRprRm
- >通过无人参与的自动修复批处理删除TipDmpUp
- >批量转储过程的更新我们制作了一个度量收集器,将这些计数器的当前状态发送到InfluxDB,间隔为1秒(可配置)。
这是有用的grafana查询,但在缩小时不会显示真正的最大操作数(我们知道在正常工作日它将会发生大约500次操作,当时没有发生特殊转储或维护 - 否则它进入成千上万):
SELECT
non_negative_derivative(max(TipTrgUp),1s) AS "update/TipTrgUp"
,non_negative_derivative(max(TipTrgRm),1s) AS "remove/TipTrgRm"
,non_negative_derivative(max(TipRprUp),1s) AS "autorepair-up/TipRprUp"
,non_negative_derivative(max(TipRprRm),1s) AS "autorepair-rm/TipRprRm"
,non_negative_derivative(max(TipDmpUp),1s) AS "dump/TipDmpUp"
FROM "$rp"."redis_flux_-transid-d-s"
WHERE
host =~ /$server$/
AND $timeFilter
GROUP BY time($interval),* fill(null)
旁注:$rp
是保留政策的名称,在grafana中模板化。我们使用CQ来缩减采样到具有更长持续时间的保留策略。另请注意1s
作为派生参数:它是必需的,因为使用GROUP BY时默认值不同。这可以在InfluxDB文档中轻易忽略。
如果我们只使用1s的分辨率(如@ Michael-Desa所建议的那样),则会将大量数据从Influxdb传输到客户端。它工作得相当好(大约10秒),但对我们来说太慢了。
然而,我们可以使用子查询将真实的maxops添加到此图表中,这是一个小小的改进。将更少的数据传输到客户端,但InfluxDB服务器必须进行大量的数字运算。 B系列(别名前加maxops
):
SELECT
max(subTipTrgUp) AS maxopsTipTrgUp
,max(subTipTrgRm) AS maxopsTipTrgRm
,max(subTipRprUp) AS maxopsRprUp
,max(subTipRprRm) AS maxopsTipRprRm
,max(subTipDmpUp) AS maxopsTipDmpUp
FROM (
SELECT
non_negative_derivative(max(TipTrgUp),1s) AS subTipTrgUp
,non_negative_derivative(max(TipTrgRm),1s) AS subTipTrgRm
,non_negative_derivative(max(TipRprUp),1s) AS subTipRprUp
,non_negative_derivative(max(TipRprRm),1s) AS subTipRprRm
,non_negative_derivative(max(TipDmpUp),1s) AS subTipDmpUp
FROM "$rp"."redis_flux_-transid-d-s"
WHERE
host =~ /$server$/
AND $timeFilter
GROUP BY time(1s),* fill(null)
)
WHERE $timeFilter
GROUP BY time($interval),* fill(null)
我们对这些指标的最终解决方案(但仅当我们需要实时视图时,子查询方法适用于ad-hoc图表)是:使用连续查询预先计算真实的maxops。我们生成这样的CQ:
CREATE CONTINUOUS QUERY "redis_flux_-transid-d-s.maxops.1s"
ON telegraf
BEGIN
SELECT
non_negative_derivative(max(TipTrgUp),1s) AS TipTrgUp
,non_negative_derivative(max(TipTrgRm),1s) AS TipTrgRm
,non_negative_derivative(max(TipRprUp),1s) AS TipRprUp
,non_negative_derivative(max(TipRprRm),1s) AS TipRprRm
,non_negative_derivative(max(TipDmpUp),1s) AS TipDmpUp
INTO telegraf.A."redis_flux_-transid-d-s.maxops"
FROM telegraf.A."redis_flux_-transid-d-s"
GROUP BY time(1s),*
END
从现在开始,在grafana中使用这些maxops测量是微不足道的。下采样到保留时间较长的RP时,我们再次使用max()
作为选择器函数。
系列B(别名中附加.maxops
)
SELECT
max(TipTrgUp) AS "update/TipTrgUp.maxops"
,max(TipTrgRm) AS "remove/TipTrgRm.maxops"
,max(TipRprUp) as "autorepair-up/TipRprUp.maxops"
,max(TipRprRm) as "autorepair-rm/TipRprRm.maxops"
,max(TipDmpUp) as "dump/TipDmpUp.maxops"
FROM "$rp"."redis_flux_-transid-d-s.maxops"
WHERE
host =~ /$server$/
AND $timeFilter
GROUP BY time($interval),* fill(null)
希望这有帮助,TW
答案 2 :(得分:0)
这里的问题是$__interval
的宽度根据您在Grafana中查看的时间范围而变化。
获得一致结果的方法是从每个间隔(mean()
,median()
或max()
均能正常工作)中取样,然后按{{1} }。这样,您的导数将随着放大/缩小而与间隔长度匹配。
因此,您的查询可能类似于:
derivative($__interval)