Вопрос или проблема
Некоторые из наших мониторингов Prometheus используют 10-недельные скользящие средние, которые были настроены пару месяцев назад, следующим образом:
round((sum(increase(metric_name[5m])))
/
(
(sum(increase(metric_name[5m] offset 1w)) +
sum(increase(metric_name[5m] offset 2w)) +
sum(increase(metric_name[5m] offset 3w)) +
sum(increase(metric_name[5m] offset 4w)) +
sum(increase(metric_name[5m] offset 5w)) +
sum(increase(metric_name[5m] offset 6w)) +
sum(increase(metric_name[5m] offset 7w)) +
sum(increase(metric_name[5m] offset 8w)) +
sum(increase(metric_name[5m] offset 9w)) +
sum(increase(metric_name[5m] offset 10w))
)
/10), 0.01)
Это работало отлично до тех пор, пока американское летнее время не “переключилось назад”, в этот момент сравнения, которые мы проводим, больше не сравниваются с одним и тем же часом суток. Теперь, после некоторых манипуляций, я понял, как сделать серию правил записи, которые выдают отрегулированное по DST количество часов для смещения следующим образом (заимствовано из https://github.com/abhishekjiitr/prometheus-timezone-rules):
# Определяет подходящее смещение времени (в часах) для 1 недели назад, учитывая американское летнее время для часового пояса America/New_York
(vector(168) and (Time:AmericaNewYork:Is1wAgoDuringDST == 1 and Time:AmericaNewYork:IsNowDuringDST == 1)) # Нормальное значение, когда время сравнения и текущее время оба находятся в DST
or
(vector(168) and (Time:AmericaNewYork:Is1wAgoDuringDST == 0 and Time:AmericaNewYork:IsNowDuringDST == 0)) # Нормальное значение, когда время сравнения и текущее время оба вне DST
or
(vector(167) and (Time:AmericaNewYork:Is1wAgoDuringDST == 0 and Time:AmericaNewYork:IsNowDuringDST == 1)) # Минус 1 час, когда время "переключилось вперед" между временем сравнения и текущим временем
or
(vector(169) and (Time:AmericaNewYork:Is1wAgoDuringDST == 1 and Time:AmericaNewYork:IsNowDuringDST == 0)) # Плюс 1 час, когда время "переключилось назад" между временем сравнения и текущим временем
Проблема в том, что я не могу найти способ фактически использовать это значение с модификатором смещения, как в первом кодовом блоке выше.
Кто-нибудь знает, возможно ли это? Я могу вернуться к созданию пользовательских правил записи для средних значений для каждой метрики, по которой мы делаем оповещения таким образом, но это, очевидно, много работы.
Ответ или решение
Динамические значения смещения PromQL для учета перехода на летнее/зимнее время
Вопрос, поднятый вами, касается корректного использования временных смещений в Prometheus (PromQL) с учетом перехода на летнее и зимнее время (DST). Вы правильно заметили, что стандартные фиксированные значения смещения не обеспечивают корректных результатов, когда часы меняются из-за перехода на летнее/зимнее время. Давайте глубже разберем это.
Проблема
Ваш текущий запрос для вычисления 10-недельного скользящего среднего использует фиксированные недельные смещения. В результате при переходе на зимнее время значения смещения перестали корректно соответствовать аналогичным временным интервалам. Это приводит к искажению анализируемых данных.
Решение
Вы предложили использовать правила записи для динамического вычисления смещения с учетом DST, что является правильным шагом. Однако, как вы отметили, вам необходимо внедрить рассчитанное смещение в ваш оригинальный запрос PromQL, для чего потребуется еще больше манипуляций.
Как интегрировать динамические значения смещения в PromQL
-
Создание записывающих правил: Судя по вашему коду, вы уже создали набор записывающих правил, которые определяют, насколько по времени будет отличаться смещение (1 час вперед или назад). Этот шаг является лишь предварительной частью решения.
-
Использование значений смещения в запросах PromQL: Основная задача — транслировать динамически вычисляемые смещения в запросы. К сожалению, прямого способа это сделать в PromQL нет, так как Prometheus не поддерживает динамические значения для спецификатора
offset
. Вместо этого можно использовать один из следующих подходов:-
Кастомные метрики: Создайте кастомные метрики, которые каждый раз будут содержать правильные временные значения в зависимости от сезона. Этот подход может потребовать значительных вычислительных ресурсов и времени на разработку.
-
Значения переключателя: Следующий вариант — создать метрику, которая возвращает правильные смещения в виде серии и использовать их в ваших прометеевых запросах. Например, если вы настроите метрики, называя их
offset_metric
, вы сможете делать запросы подобного рода:round( ( sum(increase(metric_name[5m])) ) / ( sum(increase(metric_name[5m] offset offset_metric) + ... [и так далее для всех 10 недель] ) / 10 ), 0.01)
В этом примере
offset_metric
будет возвращать нужные значения смещения в зависимости от времени года. Обратите внимание, что это также потребует соответствующей настройки и возможно, использования сторонних библиотеки для работы с временными зонами.
-
-
Подход с сохранением данных: В качестве альтернативы вы можете рассмотреть возможность сохранения предварительно вычисленных временных данных в другой базе данных или временном хранилище, где можно производить запросы без учета перехода на летнее/зимнее время, а затем просто интегрировать результаты в Prometheus при необходимости.
Заключение
Работы с временными метриками и переходами на летнее/зимнее время требуют комплексного подхода в настройке метрик и запросов. Полностью автоматизировать этот процесс в Prometheus возможно через написание кастомных правил и применение вспомогательных метрик.
Надеюсь, это поможет вам справиться с вашей задачей. Помните, что сильные стороны Prometheus заключаются в его гибкости и расширяемости, так что не стесняйтесь экспериментировать с различными подходами, чтобы достичь оптимальных результатов.