2 Выражение триггера

Обзор

Используемые в триггерах выражения являются очень гибкими. Вы можете использовать их для создания сложных логических тестов с учетом статистики по мониторингу.

Простое выражение использует функцию, которая применяется к элементу данных с некоторыми параметрами. Функция возвращает результат, который сравнивается с порогом, используя оператор и константу.

Синтаксис простого полезного выражения: функция(/узел сети/ключ,параметр)<оператор><константа>.

Например:

min(/Zabbix server/net.if.in[eth0,bytes],5m)>100K

сработает, если количество полученных байт за последние пять минут всегда превышает 100 килобайт.

С функциональной точки зрения существует два типа выражений триггеров, хоть они и имеют абсолютно одинаковый синтаксис:

  • выражение проблемы — задает условия проблемы
  • выражение восстановления (опционально) — задает дополнительные условия решения проблемы

Когда задается только выражение проблемы, это выражение будет использоваться в качестве порога как проблемы, так и восстановления проблемы. Как только выражение проблемы вычисляется в значение ИСТИНА, возникает проблема. Как только выражение проблемы вычисляется в значение ЛОЖЬ, проблема считается решённой.

Если задаются оба выражения, как проблемы, так и дополнительного выражения восстановления, решение проблемы становится более сложным: не только выражение проблемы должно стать ЛОЖЬ, но также и выражение восстановления должно стать ИСТИНА. Такой подход полезен для создания гистерезиса и помогает избежать частых переключений триггера (из / в состояние ПРОБЛЕМЫ и обратно).

Использовать макрос {TRIGGER.VALUE} в выражении восстановления непродуктивно, поскольку это выражение вычисляется только тогда, когда триггер находится в состоянии «Проблема». Следовательно, при вычислении выражения {TRIGGER.VALUE} всегда будет разрешаться в «1» (что указывает на состояние «Проблема»).

Функции

Функции позволяют обсчитывать собранные значения (вычислять среднее, минимальное, максимальное, сумму), искать строки, ссылаться на текущее время, принимать во внимание и другие факторы.

Имеется полный список поддерживаемых функций.

Обычно функции возвращают числовые значения для последующего сравнения. При возвращении строк можно выполнять сравнения при помощи операторов = и <> (смотрите пример).

Параметры функций

Параметры функций позволяют указать:

  • узел сети и ключ элемента данных (только функции, которые ссылаются на историю элемента данных узла сети)
  • параметры, специфичные для функции
  • другие выражения (недоступно для функций, которые ссылаются на историю элемента данных узла сети, смотрите другие выражения для ознакомления с примерами)

Узел сети и ключ элемента данных можно указать в виде /узел сети/ключ. Элемент данных, на который ссылается функция, должен быть в поддерживаемом состоянии (за исключением функции nodata(), которая вычисляется также по неподдерживаемым элементам данных).

В то время как в триггерах другие выражения триггеров в качестве параметров функции ограничены функциями, не связанными с историей, это ограничение не применяется к вычисляемым элементам данных.

Параметры, зависящие от функции

Параметры, которые зависят от используемой функции, помещаются после ключа элемента данных и отделяются от него запятой. Смотрите полный список этих параметров по поддерживаемым функциям.

Большинство числовых функций принимают время в качестве параметра. Чтобы указать время, вы можете использовать секунды или суффиксы времени. Параметр, которому предшествует символ решётки, имеет другое значение:

Выражение Описание
sum(/узел сети/ключ,10m) Сумма значений за последние 10 минут.
sum(/узел сети/ключ,#10) Сумма последних десяти значений.

В случае с функцией last параметры с символом решётки имеют другой смысл - они обозначают N-ое предыдущее значение, таким образом, с учетом заданных значений 3, 7, 2, 6, 5 (от самого последнего к наименее последнему значению):

  • last(/узел сети/ключ,#2) вернёт '7'
  • last(/узел сети/ключ,#5) вернёт '5'
Сдвиг времени

В качестве параметра функции поддерживается опциональный сдвиг времени со временем или количеством значений. Этот параметр позволяет ссылаться на данные из периода времени в прошлом.

Сдвиг времени начинается с now - указывает текущее время, за которым следует +N<единица времени> или -N<единица времени> - для добавления или вычитания N-го количества единиц времени.

Например, avg(/узел сети/ключ,1h:now-1d) вернет среднее значение за час днем ранее.

Сдвиг времени, указанный в месяцах (M) и годах (y), поддерживается только для функций динамики изменений. Остальные функции поддерживают секунды (s), минуты (m), часы (h), дни (d) и недели (w).

Сдвиг времени с абсолютными периодами времени

Абсолютные периоды времени поддерживаются в параметре сдвига времени, например, с полуночи до полуночи для дня, понедельник-воскресенье для недели, первый - последний день месяца для месяца.

Сдвиг времени по абсолютным периодам времени начинается с now - указывает текущее время, за которым следует любое количество временных операций: /<единица времени> - определяет начало и конец единицы времени, например, с полуночи до полуночи для дня, +N<единица времени> или -N<единица времени> - для добавления или вычитания N-го количества единиц времени.

Обратите внимание, что значение сдвига времени может быть больше или равно 0, тогда как минимальный период времени равен значению 1.

Параметр Описание
1d:now/d Вчера
1d:now/d+1d Сегодня
2d:now/d+1d Последние 2 дня
1w:now/w Последняя неделя
1w:now/w+1w Текущая неделя
Другие выражения

Параметры функций могут содержать другие выражения в соответствии со следующим синтаксисом:

min(min(/узел сети/ключ,1h),min(/узел сети2/ключ2,1h)*10)

Обратите внимание, что другие выражения нельзя использовать, если функция ссылается на историю элемента данных. Например, следующий синтаксис не разрешён:

min(/узел сети/ключ,#5*10)

Операторы

Следующие операторы поддерживаются триггерами (представлены по убыванию приоритета выполнения):

Приоритет Оператор Определение Заметки по неизвестным значениям Принудительное преобразование операнда в дробное число 1
1 - Унарный минус -Неизвестно → Неизвестно Да
2 not Логическое НЕ not Неизвестно → Неизвестно Да
3 * Умножение 0 * Неизвестно → Неизвестно
(да, Неизвестно, не 0 - чтобы не потерять
Неизвестно в арифметических операциях)
1.2 * Неизвестно → Неизвестно
Да
/ Деление Неизвестно / 0 → ошибка
Неизвестно / 1.2 → Неизвестно
0.0 / Неизвестно → Неизвестно
Да
4 + Арифметический плюс 1.2 + Неизвестно → Неизвестно Да
- Арифметический минус 1.2 - Неизвестно → Неизвестно Да
5 < Меньше чем. Этот оператор можно представить в виде:

A<B ⇔ (A<B-0.000001)
1.2 < Неизвестно → Неизвестно Да
<= Меньше чем или равно. Этот оператор можно представить в виде:

A<=B ⇔ (A≤B+0.000001)
Неизвестно <= Неизвестно → Неизвестно Да
> Больше чем. Этот оператор можно представить в виде:

A>B ⇔ (A>B+0.000001)
Да
>= Больше чем или равно. Этот оператор можно представить в виде:

A>=B ⇔ (A≥B-0.000001)
Да
6 = Равно. Этот оператор можно представить в виде:

A=B ⇔ (A≥B-0.000001) и (A≤B+0.000001)
Нет 1
<> Не равно. Этот оператор можно представить в виде:

A<>B ⇔ (A<B-0.000001) или (A>B+0.000001)
Нет 1
7 and Логическое И 0 and Неизвестно → 0
1 and Неизвестно → Неизвестно
Неизвестно and Неизвестно → Неизвестно
Да
8 or Логическое ИЛИ 1 or Неизвестно → 1
0 or Неизвестно → Неизвестно
Неизвестно or Неизвестно → Неизвестно
Да

1 Строковый операнд по прежнему приводится к числовому значению, если:

  • другой операнд числовой
  • над операндом используется оператор, отличный от = или <>

(Если приведение завершается с ошибкой - числовой операнд приводится к строковому операнду и оба операнда сравниваются как строковые значения.)

Операторы not, and and or зависят от регистра и должны быть в нижнем регистре. Они также должны быть окружены символами пробелов или круглыми скобками.

Все операторы, кроме унарных - и not, имеют ассоциативность слева направо. Унарные - и not не ассоциативны (имеется в виду, что нужно использовать -(-1) и not (not 1) вместо --1 и not not 1).

Результат вычисления:

  • Операторы <, <=, >, >=, =, <> должны возвращать '1' в выражении триггера, если указанное соотношение правдиво, и '0', если оно ложно. Если по крайней мере один операнд Неизвестен, то и результат будет Неизвестно;
  • and по известным операндам должен возвращать '1', если оба из этих операндов сравнения не равны '0'; в противном случае, будет давать '0'; для неизвестных операндов and вернет '0' только, если один из операндов сравнения равен '0'; в противном случае, он вернет 'Неизвестно';
  • or по известным операндам должен возвращать '1', если какой-либо из этих операндов сравнения не равен '0'; в противном случае, будет возвращать '0'; для неизвестных операндов or вернет '1' только, если один из операндов сравнения не равен '0'; в противном случае, он вернет 'Неизвестно';
  • Результат логического операнда отрицания not для известного операнда равен '0', если значение этого операнда сравнения не равно '0'; '1', если значение его операнда сравнения равно '0'. Для неизвестных операндов not вернет 'Неизвестно'.

Кэширование значений

Значения, которые необходимы для вычисления триггеров, кэшируются Zabbix сервером. По этой причине такое вычисление триггеров приводит к более высокой нагрузке на базу данных на некоторое время после перезапуска сервера. Кэш значений не очищается, когда значения истории элементов данных удаляются (либо вручную, либо при помощи автоматической очистки истории), поэтому сервер будет использовать кэшированные значения пока они не станут старше, чем периоды времени, заданные в функциях триггеров, либо пока сервер не будет перезапущен.

Примеры триггеров

Пример 1

Высокая загрузка процессора на сервере Zabbix.

last(/Zabbix server/system.cpu.load[all,avg1])>5

Используя функцию 'last()', мы ссылаемся на самое последнее значение. '/Zabbix server/system.cpu.load[all,avg1]' представляет короткое имя наблюдаемого параметра. Эта строка указывает, что сервер - 'Zabbix server' и наблюдаемый ключ - 'system.cpu.load[all,avg1]'. И, наконец, '>5' означает, что триггер будет переходить в состояние ПРОБЛЕМА всякий раз, когда самое последнее измерение загрузки процессора на сервере Zabbix server будет превышать 5.

Пример 2

www.example.com перегружен

last(/www.example.com/system.cpu.load[all,avg1])>5 or min(/www.example.com/system.cpu.load[all,avg1],10m)>2

Это выражение будет истинным, когда либо текущая загрузка процессора станет более 5, либо загрузка процессора больше значения 2 в течение последних 10 минут.

Пример 3

/etc/passwd был изменён.

last(/www.example.com/vfs.file.cksum[/etc/passwd],#1)<>last(/www.example.com/vfs.file.cksum[/etc/passwd],#2)

Это выражение будет истинным, когда предыдущее значение контрольной суммы файла /etc/passwd отличается от самого нового значения.

Аналогичные выражения могут быть полезны для мониторинга изменений в важных файлах, таких как /etc/passwd, /etc/inetd.conf, /kernel и других.

Пример 4

Кто-то в данный момент скачивает большой файл из Интернет

Используется функция min:

min(/www.example.com/net.if.in[eth0,bytes],5m)>100K

Это выражение будет истинным, когда количество полученных байт на eth0 превышает 100 КБ за последних 5 минут.

Пример 5

Оба узла кластера SMTP серверов недоступны

Обратите внимание на то, что в выражении используются два разных узла сети:

last(/smtp1.example.com/net.tcp.service[smtp])=0 and last(/smtp2.example.com/net.tcp.service[smtp])=0

Это выражение будет истинным, когда оба SMTP сервера недоступны - и на smtp1.example.com, и на smtp2.example.com.

Пример 6

Zabbix агент нуждается в обновлении

Используется функция find():

find(/example.example.com/agent.version,,"like","beta8")=1

Это выражение будет истинным, когда версия Zabbix агента содержит в себе 'beta8'.

Пример 7

Сервер недоступен

count(/example.example.com/icmpping,30m,,"0")>5

Это выражение будет истинным, если узел сети "example.example.com" недоступен более 5 раз за последние 30 минут.

Пример 8

Нет данных за последние 3 минуты

Используется функцию nodata():

nodata(/example.example.com/tick,3m)=1

Для того, чтобы этот триггер заработал, элемент данных ‘tick’ должен быть определён как элемент данных с типом Zabbix траппер. Узел сети должен периодически отправлять данные этому элементу данных, используя zabbix_sender. Если никаких данных не было получено за последние 180 секунд, значение триггера станет ПРОБЛЕМА.

Обратите внимание, что 'nodata' можно использовать с любым типом элементов данных.

Пример 9

Активность CPU в ночное время

Используется функция time():

min(/Zabbix server/system.cpu.load[all,avg1],5m)>2 and time()<060000

Триггер может изменить свое состояние в ПРОБЛЕМА только в ночное время (00:00 - 06:00).

Пример 10

Активность CPU в любое время с исключением.

Используется функция time() и оператор not:

min(/zabbix/system.cpu.load[all,avg1],5m)>2
       and not (dayofweek()=7 and time()>230000)
       and not (dayofweek()=1 and time()<010000)

Триггер может изменить свое состояние на Проблема в любое время, за исключением интервала в 2 часа при изменении недели (воскресенье, 23:00 - понедельник, 01:00).

Пример 11

Проверка синхронизации времени на клиенте со временем на Zabbix сервере

Используется функция fuzzytime():

fuzzytime(/MySQL_DB/system.localtime,10s)=0

Триггер изменит состояние на проблему тогда, когда локальное время на сервере MySQL_DB и Zabbix сервере будут различаться более чем на 10 секунд. Обратите внимание, что 'system.localtime' должен быть настроен как пассивная проверка.

Пример 12

Сравнение средней загрузки сегодня со средним значением загрузки за это же время вчера (использование сдвига времени в виде now-1d).

avg(/server/system.cpu.load,1h)/avg(/server/system.cpu.load,1h:now-1d)>2

Этот триггер сработает, если средняя загрузка за последний час более чем вдвое превысит среднюю загрузку за тот же час вчера.

Пример 13

Использование значения другого элемента данных в качестве порогового значения триггера:

last(/Template PfSense/hrStorageFree[{#SNMPVALUE}])<last(/Template PfSense/hrStorageSize[{#SNMPVALUE}])*0.1

Триггер изменит свое состояние на проблему, если количество свободного пространства на диске упадёт ниже 10 процентов.

Пример 14

Использование результата вычисления для получения количества триггеров больше порога:

(last(/server1/system.cpu.load[all,avg1])>5) + (last(/server2/system.cpu.load[all,avg1])>5) + (last(/server3/system.cpu.load[all,avg1])>5)>=2

Этот триггер сработает, если по крайней мере два триггера в выражении будут в состоянии ПРОБЛЕМА.

Пример 15

Сравнение строковых значений двух элементов данных: операнды здесь - это функции, которые возвращают строки.

Проблема: создание оповещения, если версия Ubuntu отличается от версии на другом узле сети

last(/NY Zabbix server/vfs.file.contents[/etc/os-release])<>last(/LA Zabbix server/vfs.file.contents[/etc/os-release])
Пример 16

Сравнение двух строковых значений - операнды здесь:

  • функция, которая возвращает строку
  • комбинация макросов и строк

Проблема: обнаружение изменений в DNS запросе

Ключ элемента данных:

net.dns.record[8.8.8.8,{$WEBSITE_NAME},{$DNS_RESOURCE_RECORD_TYPE},2,1]

с макросами, заданными как

{$WEBSITE_NAME} = example.com
       {$DNS_RESOURCE_RECORD_TYPE} = MX

который обычно возвращает:

example.com           MX       0 mail.example.com

Итак, наше выражение триггера определяет, если результат DNS запроса отклоняется от ожидаемого значения:

last(/Zabbix server/net.dns.record[8.8.8.8,{$WEBSITE_NAME},{$DNS_RESOURCE_RECORD_TYPE},2,1])<>"{$WEBSITE_NAME}           {$DNS_RESOURCE_RECORD_TYPE}       0 mail.{$WEBSITE_NAME}"

Обратите внимание на кавычки вокруг второго операнда.

Пример 17

Сравнение двух строковых значений - операнды здесь:

  • функция, которая возврашает строку
  • строковая константа со специальными символами \ и "

Проблема: определить идентично ли содержимое файла /tmp/hello следующим данным:

\" //hello ?\"

Опция 1) указать строку напрямую

last(/Zabbix server/vfs.file.contents[/tmp/hello])="\\\" //hello ?\\\""

Обратите внимание на то как экранируются символы \ и " при сравнении строки напрямую.

Опция 2) использование макроса

{$HELLO_MACRO} = \" //hello ?\"

в выражении:

last(/Zabbix server/vfs.file.contents[/tmp/hello])={$HELLO_MACRO}
Пример 18

Сравнение длительных периодов.

Проблема: Загрузка Exchange сервера увеличилась более чем на 10% за последний месяц

trendavg(/Exchange/system.cpu.load,1M:now/M)>1.1*trendavg(/Exchange/system.cpu.load,1M:now/M-1M)

Вы можете также использовать поле Имени события в настройках триггера, чтобы создать осмысленное сообщение оповещения, например, для получения примерно следующего

"Load of Exchange server increased by 24% in July (0.69) comparing to June (0.56)"

имя события должно быть определено следующим образом:

Load of {HOST.HOST} server increased by {{?100*trendavg(//system.cpu.load,1M:now/M)/trendavg(//system.cpu.load,1M:now/M-1M)}.fmtnum(0)}% in {{TIME}.fmttime(%B,-1M)} ({{?trendavg(//system.cpu.load,1M:now/M)}.fmtnum(2)}) comparing to {{TIME}.fmttime(%B,-2M)} ({{?trendavg(//system.cpu.load,1M:now/M-1M)}.fmtnum(2)})

Также для подобных проблем полезно было бы разрешить закрывать триггер вручную в настройках самого триггера.

Гистерезис

Порой нам необходим некоторый интервал между состояниями ОК и Проблема, а не просто порог. Например, если мы хотим задать триггер, который переходит в состояние Проблема, когда температура в серверной комнате становится больше 20°C, и мы хотим, чтобы он оставался в этом состоянии, пока температура не опустится ниже 15°C, то просто порога в 20°C для триггера будет недостаточно.

Вместо этого нам нужно сначала задать выражение триггера для события проблемы (температура выше 20°C). Затем нам нужно задать дополнительное условие восстановления (температура ниже 15°C). Это можно сделать, задавая дополнительный параметр Выражение восстановления в настройках триггера.

В этом случае восстановление проблемы будет проходить в два этапа:

  • Во-первых, выражение проблемы (температура выше 20°C) должно быть вычислено значением ЛОЖЬ
  • Во-вторых, выражение восстановления (температура ниже 15°C) должно быть вычислено значением ИСТИНА

Выражение восстановления будет вычислено только, когда сначала будет решено событие о проблеме.

Выражение восстановления, которое в состоянии ИСТИНА, не решает проблему, если выражение проблемы по-прежнему равно ИСТИНА!

Пример 1

Температура в серверной комнате слишком высокая.

Выражение проблемы:

last(/server/temp)>20

Выражение восстановления:

last(/server/temp)<=15
Пример 2

Очень мало свободного места на диске.

Выражение проблемы: если меньше 10ГБ за последние 5 минут

max(/server/vfs.fs.size[/,free],5m)<10G

Выражение восстановления: если больше 40ГБ за последние 10 минут

min(/server/vfs.fs.size[/,free],10m)>40G

Выражения с неизвестными операндами

В большинстве случаев, неизвестный операнд (такой как неподдерживаемый элемент данных) в выражении незамедлительно изменит значение триггера на Неизвестно.

Однако, в некоторых случаях неизвестные операнды (неподдерживаемые элементы данных, ошибки функций) допустимы при вычисления выражений:

  • Функция nodata() вычисляется независимо от того, поддерживается элемент данных, на который она ссылается, или же не поддерживается.
  • Логические выражения с ИЛИ и И могут быть вычислены в известные значения независимо от неизвестных операндов в двух случаях:
    • Случай 1: "1 or некая_функция(неподдерживаемый_элемент_данных1) or некая_функция(неподдерживаемый_элемент_данных2) or ..." может быть вычислено с известным результатом ('1' или "Проблема"),
    • Случай 2: "0 and некая_функция(неподдерживаемый_элемент_данных1) and некая_функция(неподдерживаемый_элемент_данных2) and ..." может быть вычислено с известнвм результатом ('0' или "OK").
      Zabbix пытается вычислить такие логические выражения, принимая неподдерживаемые элементы данных как Неизвестные значения. В двух случаях, упомянутых выше, будет производиться известное значение; в остальных случаях значением триггера будет Неизвестно.
  • Если вычисление функции по поддерживаемому элементу данных приведет к ошибке, значением функции будет Неизвестно и оно будет частью дальнейшего вычисления выражения как неизвестный операнд.

Обратите внимание на то, что неизвестные операнды могут "исчезать" только в логических выражениях, описанных выше. В арифметических выражениях неизвестные значения всегда приводят к Неизвестному результату (за исключением деления на 0).

Выражение, приводящее к Неизвестно, не меняет состояние триггера ("Проблема/OK"). Таком образом, если он был в состоянии "Проблема" (смотри Случай 1), то остаётся в том же проблемном состоянии даже если известная часть разрешается ('1' становится '0'), потому что выражение теперь вычисляется в Неизвестно, а это не меняет состояние триггера.

Если выражение триггера с несколькими неподдерживаемыми элементами данных вычисляется как Неизвестное, сообщение об ошибке в веб-интерфейсе ссылается на последний вычисленный неподдерживаемый элемент данных.