Привет, дорогой читатель!
Если ты когда‑нибудь писал триггеры в Zabbix и ловил себя на мысли «ну вроде работает, а вроде и хер поймёшь почему», — добро пожаловать.
Сегодня поговорим про одну из самых часто криво реализуемых логик: «N последних значений подряд должны быть плохими».
Спойлер: last(#2) — это почти всегда хрень. Сейчас объясню, почему.
Задача из реальной жизни
Есть некая метрика. Неважно какая: ответ API, здоровье сервиса, время реакции, температура утюга или задницы.
Ты хочешь:
триггерить только если проблема держится стабильно, а не из‑за одного скачка.
Не «один раз дернулось»
Не «что‑то было минуту назад»
А подряд N измерений — всё плохо
Как делают неправильно (и почему это боль)
Очень часто встречается такая логика:
last(/SomeTemplate/some.health.metric,#2) > {$THRESHOLD}
Что тут реально происходит:
#2— это второе значение с конца- проверяется ОДНА точка
- ни о какой стабильности речи нет
То есть ситуация:
[ OK ] [ ПЛОХО ] [ OK ]
И триггер может сработать.
Поздравляю, ты только что настроил рандом‑алерт‑генератор.
Канонический способ: min() + #N
Если тебе нужно:
N последних значений подряд ≥ порога
Правильная формула выглядит так:
min(/SomeTemplate/some.health.metric,#3) >= {$THRESHOLD}
Что это означает по‑взрослому:
- берутся ровно 3 последних значения
- считается минимум
- если минимум ≥ порога → все три значения плохие
Логика тут железобетонная:
[ ПЛОХО ] [ ПЛОХО ] [ ПЛОХО ] => триггер
[ ПЛОХО ] [ OK ] [ ПЛОХО ] => нет триггера
Никакой магии. Только математика.
А почему не max() / avg() / last()?
Коротко:
last()— проверяет одну точку, нестабильноavg()— сглаживает и прячет реальные пикиmax()— реагирует на один выброс
min() — единственный вариант, который гарантирует:
«ВСЁ окно было плохим»
Окно по количеству (#N) или по времени (Nm)?
Есть два подхода:
1. По количеству значений
min(item,#5) >= threshold
Плюсы:
- чётко: 5 подряд значений
- не зависит от времени
Минусы:
- если поменяется интервал сбора — логика ломается
2. По времени
min(item,5m) >= threshold
Плюсы:
- логика «5 минут подряд плохо»
- неважно, раз в 30с или раз в 1м метрика приходит
Минусы:
- количество точек в окне не фиксировано
Выбор простой:
- хочешь подряд N измерений →
#N - хочешь устойчивость по времени →
Nm
Когда триггеров становится до хрена
А теперь реальность.
У тебя:
- 20 сервисов
- 20 айтемов
- 20 одинаковых триггеров
- везде
#3
И вот однажды ты понимаешь, что надо не 3, а 5.
И начинается веселье: «открыть → поправить → сохранить → не забыть → не про%бать».
Логичный вопрос
«А можно вынести
#3в макрос?»
Интуитивно хочется так:
min(item,#{$POINTS}) >= {$THRESHOLD}
Ответ неприятный
Нельзя.
Zabbix не умеет подставлять пользовательские макросы в #N.
Парсер ожидает число, а не макрос.
Результат — ошибка и испорченное настроение.
Как делают нормальные люди
Используют временное окно + макрос.
Например:
{$HEALTH_WINDOW} = 3m
И триггер:
min(item,{$HEALTH_WINDOW}) >= {$THRESHOLD}
Теперь:
- хочешь 3 минуты →
3m - хочешь 5 минут →
5m - хочешь 30 секунд →
30s
И все 20 триггеров меняются сразу.
Да, это не «ровно 3 значения».
Зато:
- масштабируется
- читаемо
- поддерживаемо
- не превращается в ад при росте проекта
А что в итоге?
Запомни раз и навсегда, дорогой мой читатель:
last(#2)— почти всегда ошибкаmin(#N)— если нужен подряд N значенийmin(Nm)+ макрос — если триггеров много- макросы в
#N— не работают - макросы во времени — работают идеально
Если триггер можно описать словами
«всё было плохо некоторое время»
— ты на правильном пути.
Если он описывается как
«вторая точка с конца была плохая»
— выкинь и перепиши.
Себя потом поблагодаришь.
