Как получить согласованные значения с неотрицательной производной influxdb?
используя grafana с influxdb, я пытаюсь показать скорость в секунду некоторого значения, которое является счетчиком. Если я использую non_negative_derivative(1s)
функция, значение скорости, кажется, резко меняется в зависимости от временной ширины представления grafana. Я использую last
селектор (но также может использовать max
который является тем же значением, поскольку он является счетчиком).
в частности, я использую:
SELECT non_negative_derivative(last("my_counter"), 1s) FROM ...
по словам документы influxdb неотрицательная производная:
InfluxDB вычисляет разницу между значениями хронологического поля и преобразует эти результаты в скорость изменения на единицу.
поэтому для меня это означает, что значение в данной точке не должно сильно меняться при расширении представления времени, так как значение должно быть скорость изменения на единицу (1s в моем примере запроса выше).
в графите, они имеют специфическое perSecond
функция, которая работает намного лучше:
perSecond(consolidateBy(my_counter, 'max'))
любые идеи о том, что я делаю неправильно С выше запроса приток?
2 ответов
если вы хотите в секунду результаты, которые не меняются, вы хотите, чтобы 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
то, что мы просим, это то, что и
0s-2s → 2s-4s
2*(5-1)/2 → 2*(11-5)/2
4 → 6
то, что мы просим здесь, это то, что
@Michael-Desa дает отличное объяснение.
я хотел бы дополнить этот ответ решением довольно распространенной метрики, в которой заинтересована наша компания: "Что такое максимум значение "операция в секунду" на конкретном поле измерения?".
я буду использовать реальный пример из нашей компании.
Сценарий Фон
мы отправляем много данных из СУБД в Рэдис. При передаче этого данные, мы отслеживаем 5 счетчиков:
-
TipTrgUp
-> обновления бизнес-триггером (хранимая процедура) -
TipTrgRm
-> удаляет бизнес-триггер (хранимая процедура) -
TipRprUp
-> обновления автоматической авторемонтных пакетной обработки -
TipRprRm
-> удаляет пакетным процессом автоматического ремонта -
TipDmpUp
-> обновления с помощью процесса массового сброса
мы сделали сборщик метрик, который отправляет текущее состояние этих счетчиков для InfluxDB с интервалом в 1 секунду (настраивается).
график Grafana 1: низкое разрешение, не правда максимум ОПС
вот запрос grafana, который полезен, но не показывает истинный max ops при уменьшении масштаба (мы знаем, что он будет идти около 500 ops в обычный рабочий день, когда никаких специальных дампов или обслуживания не происходит-в противном случае он идет в тысячи):
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 для downsample для политик хранения с большей продолжительностью. Также обратите внимание на 1s
как производный параметр: это необходимо, так как значение по умолчанию отличается при использовании GROUP BY. Это можно легко упустить из виду в документации InfluxDB.
график, увиденный 24 часами выглядит так:
если мы просто используем разрешение 1s (как предложено @Michael-Desa), an огромное количество данных передается от influxdb клиенту. Это работает достаточно хорошо (около 10 секунд), но слишком медленно для нас.
график Графана 2: низкое и высокое разрешение, true max ops, медленная производительность
однако мы можем использовать подзапросы чтобы добавить true 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)
график Графана 3: низкое и высокое разрешение, истинный Макс ОПС, высокая эффективность, пре-высчитывает КК
наше окончательное решение для такого рода метрик (но только тогда, когда нам нужен живой вид, подход подзапроса отлично работает для графиков 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
отсюда, это тривиально использовать эти измерения maxops в grafana. Когда downsampling к 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)
при увеличении до точности 1s вы можете видеть, что графики становятся идентичными:
надеюсь, это поможет, TW