# Триггеры и префильтры

# Префильтр

# Поддерживаемые операторы

Оператор Описание Пример использования
and И _labels.type == 'Prometheus' and _stream.id == 10
or ИЛИ _stream.id == 10 or _stream.id == 11
not НЕ _stream.type == 'Prometheus' and not _stream.id == 10
== Эквивалентно _stream.type == 'Prometheus'
~= Не эквивалентно _stream.type ~= 'Prometheus'
> Больше _stream.id > 10
< Меньше _stream.id < 10
>= Больше равно _stream.id >= 10
<= Меньше равно _stream.id <= 10
in(field, {args}) В списке in(_stream.id, {10, 11, 15})
regexIsMatch(field, "(pattern)") Регулярное выражение regexIsMatch(source.@timestamp, "(\\d{4}-\\d{2}-\\d{2}T\\[0][0-9]:\\d{2}:\\d{2}\\.\\d+Z)") - возвращает true если время в @timestamp с 00 до 09 часов

Допускается группировка частей выражения с помощью ()

Операторы сравнения не учитывают регистр

Объекты типа string должны быть заключены в одинарные кавычки

Экранирование происходит через \.

# Общие поля

Данные поля могут использоваться для фильтрации любых событий

Поле Тип Описание
_stream.id long ID потока, являющегося источником события
_stream.name string Название потока, являющегося источником события
_labels.type string Тип потока, являющегося источником события
_aggregatedAt DateTime Время получения события
source.@timestamp DateTime Время генерации события, указанное в сообщении

# Шаблоны префильтров

# SystemZabbixHost

_labels.type == 'Zabbix' AND _stream.id == <ID потока данных> AND source.host.id == <ID узла сети Zabbix>

# SystemZabbixTrigger

_labels.type == 'Zabbix' AND _stream.id == <ID потока данных> AND source.trigger.id == '<ID триггера Zabbix>'

# SystemSCOM

_labels.type == 'SCOM' AND _stream.id == <ID потока данных> and source.objectId == '<ID объекта источника>'

Для получения ID объекта источника, используйте команду Get-SCOMMonitoringObject -Name "<имя>"| select id (см. подробнее (opens new window)).

# SystemPrometheusStandart

_labels.type == 'Prometheus' AND _stream.id == <ID потока данных> AND source.labels.controller_pod == '<Controller pod>' AND source.labels.alertname == '<Alert name>'

# Правило

# Служебные переменные

Переменная Класс Описание
trigger SyntheticTrigger Синтетические триггер.
_stream Stream Поток данных, являющийся источником обрабатываемого события.
source Any Первичное событие, полученное из источника.
_labels Any Набор меток, добавленных в событие препроцессором потока.
По умолчанию содержит поле type: string – обозначение типа потока.

# Служебные методы

Метод Параметры Тип возвращаемого значения Описание
print message: any void Вывести значение параметра метода
setTriggerStatus newStatus: string, labels: any (optional) LuaResult<bool> Изменить статус триггера

# Служебные классы

# SyntheticTrigger

Поле Тип Описание
id number Id синтетического триггера
name string Имя синтетического триггера
description string Описание синтетического триггера
status string Текущий статус синтетического триггера
# Stream
Поле Тип Описание
id number ID интеграции
name string Название интеграции
type string Тип интеграции MONQ ПЕРЕНЕСЕНО В _LABELS.TYPE В MONQ 5.0

# Any

Таблица с произвольным набором полей.

# LuaResult

Поле Тип Описание
data type Данные, которые вернул метод. type может быть любым из раздела "Типы данных"
err LuaCustomException Поле содержит объект с описанием ошибки, которую вернул метод. Если ошибки нет, то поле будет в статусе nil.

# LuaCustomException

Поле Тип Описание
message string Сообщение об ошибке

# Шаблоны правил

# SystemZabbixTrigger

function convertTriggerStatus(value, priority)
  if (value == 0) then
    return 'Ok'
  elseif (priority == 2) then
    return 'Problem4'
  elseif (priority == 3) then
    return 'Problem3'
  elseif (priority == 4) then
    return 'Problem2'
  elseif (priority == 5) then
    return 'Problem1'
  end
end

function generateLabels(newStatus)
  return 
  {
    eventName = source.host.name .. ': ' .. source.trigger.revealedDescription,
    changeStatus = trigger.status .. ' → ' .. newStatus,
    zTriggerName = source.trigger.revealedDescription,
    zHostName = source.host.name,
    zHostgroupName = source.group.name
  }
end

local triggerStatus = convertTriggerStatus(source.trigger.value, source.trigger.priority) 
if (triggerStatus ~= nil and trigger.status ~= triggerStatus) then
  local labels = generateLabels(triggerStatus)
  setTriggerStatus(triggerStatus, labels)
end

# SystemSCOM

function convertSeverity(value)
  local severityEnum = 
  {
    ["Information"] = 0,
    ["Warning"] = 1,
    ["Error"] = 2
  }
  return severityEnum[value]
end

function convertPriority(value)
  local priorityEnum = 
  {
    ["Low"] = 0,
    ["Medium"] = 1,
    ["High"] = 2
  }
  return priorityEnum[value]
end

function convertTriggerStatus(severity, priority)
  local scomPriority = convertPriority(priority) * 3 + convertSeverity(severity) + 1
  if (scomPriority == 2 or scomPriority == 3) then
    return 'Problem4'
  elseif (scomPriority == 4 or scomPriority == 5) then
    return 'Problem3'
  elseif (scomPriority == 6 or scomPriority == 7) then
    return 'Problem2'
  elseif (scomPriority == 8 or scomPriority == 9) then
    return 'Problem1'
  else
    return 'Ok'
  end
end

local triggerStatus = convertTriggerStatus(source.severity, source.priority)
if (triggerStatus ~= nil and trigger.status ~= triggerStatus) then
  setTriggerStatus(triggerStatus)
end

# Примеры синтетических триггеров

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

# nagios

  • Конвертация статусов 1-в-1.

  • state: Unknown игнорируется.

  • Пример префильтра для мониторинга сервиса: connector.id == 1 AND source.hostName == 'test host' AND source.serviceDescription == 'test service' AND source.objecttypeId == 2

  • Пример префильтра для мониторинга хоста: connector.id == 1 AND source.hostName == 'test host' AND source.objecttypeId == 1

    function convertEventStatus(value)
    if (value == 0) then
       return 'Ok'
    elseif (value == 1) then
       return 'Problem1'
    elseif (value == 2) then
       return 'Problem2'
    end
    end
    
    
    local newStatus = convertEventStatus(source.state)
    if (trigger.status ~= newStatus and source.state ~= 3) then
    setTriggerStatus(newStatus)
    end
    

# prometheusUniversalWithGrouping

Универсальный триггер Prometheus. Подходит для случая, когда настроена группировка в alertmanager.
Запоминает активные проблемы и выставляет максимальный приоритет.

-- Функция для ковертирования времни в timestamp
function toTimeStamp(dateString)
	local inYear, inMonth, inDay, inHour, inMinute, inSecond, inMsec, inZone =
  string.match(dateString, '^(%d%d%d%d)-(%d%d)-(%d%d)T(%d%d):(%d%d):(%d%d)%.(%d-)([%+%-].-)$')
	local zHours, zMinutes = string.match(inZone, '^(.-):(%d%d)$')
	local returnTime = os.time({year=inYear, month=inMonth, day=inDay, hour=inHour, min=inMinute, sec=inSecond, isdst=false})
	if zHours then
		returnTime = returnTime - ((tonumber(zHours)*3600) + (tonumber(zMinutes)*60))
	end
	return returnTime
end

-- Функция для установки статуса триггера по числовому значению
function setTrigger(numstat)
  if (numstat == 0) then
    setTriggerStatus('Ok')
  elseif (numstat == 1) then
    setTriggerStatus('Problem4')
  elseif (numstat == 2) then
    setTriggerStatus('Problem3')
  elseif (numstat == 3) then
    setTriggerStatus('Problem2')
  elseif (numstat == 4) then
    setTriggerStatus('Problem1')
  end
end

-- Функция преобразования приоритета события в числовое значение
function convertEventSeverity(severity)
  local eventSeverity =
  { ["disaster"] = 4, ["high"] = 3, ["warning"] = 2, ["info"] = 1 }
  return eventSeverity[severity]
end

-- Функция преобразования статуса триггера СМ в числовое значение
function convertTriggerStatus(status)
  local triggerStatus =
  { ["Ok"] = 0, ["Problem4"] = 1, ["Problem3"] = 2, ["Problem2"] = 3, ["Problem1"] = 4 }
  return triggerStatus[status]
end

-- Функция поиска ключа по value в таблице
function findEvent(table,element)
  for k,v in pairs(table) do
    if (deepcompare(json.decode(v), element)) then
      return k
    end
  end
end

-- Функция разделения строки
function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

-- Функция сравнения таблиц
function deepcompare(t1,t2,ignore_mt)
   local ty1 = type(t1)
   local ty2 = type(t2)
   if ty1 ~= ty2 then return false end
   if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
   local mt = getmetatable(t1)
   if not ignore_mt and mt and mt.__eq then return t1 == t2 end
   for k1,v1 in pairs(t1) do
      local v2 = t2[k1]
      if v2 == nil or not deepcompare(v1,v2) then return false end
   end
   for k2,v2 in pairs(t2) do
      local v1 = t1[k2]
      if v1 == nil or not deepcompare(v1,v2) then return false end
   end
   return true
end

-- Вычисление числового значения триггера и полученного события
local oldSeverity = convertTriggerStatus(trigger.status)
local newSeverity = convertEventSeverity(source.labels.severity)

-- Смена статуса Ok -> Problem
if (trigger.status == 'Ok' and source.status == 'firing') then
  setTrigger(newSeverity)
  alerts = {json.encode({time=toTimeStamp(source.startsAt), alertname=source.labels.alertname, severity=source.labels.severity})}
  _G["alerts"] = table.concat(alerts,";")
-- Смена статуса Problem -> Problem
elseif (trigger.status ~= 'Ok' and source.status == 'firing') then
  if (newSeverity > oldSeverity) then
    setTrigger(newSeverity)
  end
  alerts = split(_G["alerts"],";")
  table.insert(alerts, json.encode({time=toTimeStamp(source.startsAt), alertname=source.labels.alertname, severity=source.labels.severity}))
  _G["alerts"] = table.concat(alerts,";")
-- Смена статуса Problem -> Ok
elseif (trigger.status ~= 'Ok' and source.status == 'resolved') then
  alerts = split(_G["alerts"],";")
  local alertKey = findEvent(alerts,{time=toTimeStamp(source.startsAt), alertname=source.labels.alertname, severity=source.labels.severity})
  if (alertKey ~= nil) then
    table.remove(alerts,alertKey)
    if (#alerts == 0) then
      setTriggerStatus('Ok')
      _G["alerts"] = ""
    else
      -- Поиск максимального severity среди активных событий
      local newSeverity = convertEventSeverity(json.decode(alerts[1])['severity'])
      for k,v in pairs(alerts) do
        local vnewSeverity = convertEventSeverity(json.decode(v)['severity'])
        if vnewSeverity > newSeverity then
          newSeverity = vnewSeverity
        end
      end
      -- Установка триггера с максимальным severity
      setTrigger(newSeverity)
      _G["alerts"] = table.concat(alerts,";")
    end
  end
end

# prometheusWithoutGrouping

Универсальный триггер Prometheus. Подходит для случая, когда не настроена группировка в alertmanager.
Запоминает активные проблемы и выставляет максимальный приоритет.

-- Функция ковертирования времни в timestamp
function toTimeStamp(dateString)
	local inYear, inMonth, inDay, inHour, inMinute, inSecond, inMsec, inZone =
  string.match(dateString, '^(%d%d%d%d)-(%d%d)-(%d%d)T(%d%d):(%d%d):(%d%d)%.(%d-)([%+%-].-)$')

	local zHours, zMinutes = string.match(inZone, '^(.-):(%d%d)$')

	local returnTime = os.time({year=inYear, month=inMonth, day=inDay, hour=inHour, min=inMinute, sec=inSecond, isdst=false})

	if zHours then
		returnTime = returnTime - ((tonumber(zHours)*3600) + (tonumber(zMinutes)*60))
	end

	return returnTime
end

-- Функция установки статуса триггера по числовому значению
function setTrigger(numstat)
  if (numstat == 0) then
    setTriggerStatus('Ok')
  elseif (numstat == 1) then
    setTriggerStatus('Problem4')
  elseif (numstat == 2) then
    setTriggerStatus('Problem3')
  elseif (numstat == 3) then
    setTriggerStatus('Problem2')
  elseif (numstat == 4) then
    setTriggerStatus('Problem1')
  end
end

-- Функция преобразования приоритета события в числовое значение
function convertEventSeverity(severity)
  local eventSeverity =
  {
    ["disaster"] = 4,
    ["high"] = 3,
    ["warning"] = 2,
    ["info"] = 1
  }
  return eventSeverity[severity]
end

-- Функция преобразования статуса триггера в числовое значение
function convertTriggerStatus(status)
  local triggerStatus =
  {
    ["Ok"] = 0,
    ["Problem4"] = 1,
    ["Problem3"] = 2,
    ["Problem2"] = 3,
    ["Problem1"] = 4
  }
  return triggerStatus[status]
end

-- Вычисление числового значения триггера и пришедшего события
local oldSeverity = convertTriggerStatus(trigger.status)
local newSeverity = convertEventSeverity(source.labels.severity)

if (source.status == 'firing' and trigger.status == 'Ok') then
  setTrigger(newSeverity)
  _G["eventTime"] = toTimeStamp(source.startsAt)
  _G["newStatus"] = 1
elseif (source.status == 'firing' and trigger.status ~= 'Ok') then
  local newEventTime = toTimeStamp(source.startsAt)
  print(source.startsAt)
  if (_G["newStatus"] == 0) then
    setTrigger(newSeverity)
    _G["newStatus"] = 1
    _G["eventTime"] = newEventTime
  else
    if newSeverity > oldSeverity then
      setTrigger(newSeverity)
      _G["eventTime"] = newEventTime
    elseif (newSeverity == oldSeverity and _G["eventTime"] < newEventTime) then
      _G["eventTime"] = toTimeStamp(source.startsAt)
    end
  end

elseif (source.status == 'resolved' and trigger.status ~= 'Ok') then
  if (toTimeStamp(source.startsAt) == _G["eventTime"] and newSeverity == oldSeverity) then
    if (_G["newStatus"] == 0) then
      setTrigger(0)
      _G["newStatus"] = 0
    else
      _G["newStatus"] = 0
    end
  end
end

# SystemZabbixTrigger-5

Стандартный шаблон триггера Zabbix, учитывающий статус information.

function convertTriggerStatus(value, priority)
  if (value == 0) then
    return 'Ok'
  elseif (priority == 1) then
    return 'Problem4'
  elseif (priority == 2) then
    return 'Problem4'
  elseif (priority == 3) then
    return 'Problem3'
  elseif (priority == 4) then
    return 'Problem2'
  elseif (priority == 5) then
    return 'Problem1'
  end
end

function generateLabels(newStatus)
  return 
  {
    eventName = source.host.name .. ': ' .. source.trigger.revealedDescription,
    changeStatus = trigger.status .. ' → ' .. newStatus,
    zTriggerName = source.trigger.revealedDescription,
    zHostName = source.host.name,
    zHostgroupName = source.group.name
  }
end

local triggerStatus = convertTriggerStatus(source.trigger.value, source.trigger.priority)
if (triggerStatus ~= nil and trigger.status ~= triggerStatus) then
  local labels = generateLabels(triggerStatus)
  setTriggerStatus(triggerStatus, labels)
end

# vrops

Шаблон триггера для обработки событий из VMware vRealize Operations через промежуточный shim. Пример префильтра: _stream.id = 2 and source.resourceName = 'test-server'

-- Функция конвертации приоритетов (возвращает буквенную и цифровую версию)
function convertSeverity(severity)
  if (severity == "ALERT_CRITICALITY_LEVEL_INFO" or severity == "Problem4") then
    return {char="Problem4", num=4}
  elseif (severity == "ALERT_CRITICALITY_LEVEL_WARNING" or severity == "Problem3") then
    return {char="Problem3", num=3}
  elseif (severity == "ALERT_CRITICALITY_LEVEL_IMMEDIATE" or severity == "Problem2") then
    return {char="Problem2", num=2}
  elseif (severity == "ALERT_CRITICALITY_LEVEL_CRITICAL" or severity == "Problem1") then
    return {char="Problem1", num=1}
  else
    return {char="Ok", num=5}
  end
end

-- Функция установки лейблов
function generateLabels(alert)
  return {eventName = alert.AlertName}
end

local priority = convertSeverity(source.criticality)
local labels = generateLabels(source)

-- OK -> Problem
if (source.status == 'ACTIVE' and trigger.status == 'Ok') then
  setTriggerStatus(priority.char, labels)
  local problems = {}
  problems[source.alertId] = {priority = priority, labels = labels}
  _G["problems"] = json.encode(problems)
  _G["active"] = source.alertId

-- Problem -> Problem
elseif (source.status == 'ACTIVE' and trigger.status ~= 'Ok') then
  local oldPriority = convertSeverity(trigger.status)
  if (priority.num < oldPriority.num) then
    setTriggerStatus(priority.char, labels)
    _G["active"] = source.alertId
  end
  local problems = json.decode(_G["problems"])
  problems[source.alertId] = {priority = priority, labels = labels}
  _G["problems"] = json.encode(problems)

-- Problem -> Ok
elseif (source.status == 'CANCELED' and trigger.status ~= 'Ok') then
  local problems = json.decode(_G["problems"])
  problems[source.alertId] = nil
  if (source.alertId == _G["active"]) then
    local candidate={priority={num=5, char="Ok"}}
    for k,v in pairs(problems) do
      if (v.priority.num < candidate.priority.num) then
        candidate = v
        _G["active"] = k
      end
    end
    setTriggerStatus(candidate.priority.char, candidate.labels)
  end
  _G["problems"] = json.encode(problems)
end

# zabbixAccumulateWithDelay

  • Устанавливает максимальный приоритет проблемы из попавших в него триггеров.
  • Запоминает активные проблемы.
  • По мере закрытия проблем, устанавливается максимальный приоритет из активных проблем.
  • Закрывается только после истечения timeout, после закрытия последней проблемы.
-- Функция преобразования приоритета события в статус триггера
function convertTriggerStatus(value, priority)
  if (value == 0) then
    return 'Ok'
  elseif (priority == 2) then
    return 'Problem4'
  elseif (priority == 3) then
    return 'Problem3'
  elseif (priority == 4) then
    return 'Problem2'
  elseif (priority == 5) then
    return 'Problem1'
  end
end

-- Функция поиска ключа по eventId
function findEvent(table,element)
  for k,v in pairs(table) do
    if (json.decode(v)['id'] == element) then
      return k
    end
  end
end

-- Функция преобразования статуса триггера в приоритет события
function convertTriggerPriority(value)
  if (value == 'Problem1') then
    return 5
  elseif (value == 'Problem2') then
    return 4
  elseif (value == 'Problem3') then
    return 3
  else
    return 2
  end
end
function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

-- Установка таймаута очистки
local timeout = 300
-- Проверка запуска расчета scheduler и условий для закрытия
if (isScheduled == true) then
  if (_G["clear"] == true and (os.time()-_G["clearTime"]) >= timeout and trigger.status ~= 'Ok') then
    print("clear")
    setTriggerStatus('Ok')
  end
else
  -- Вычисление нового значения триггера
  local newSeverity = convertTriggerStatus(source.trigger.value, source.trigger.priority)
  if (trigger.status == 'Ok' and newSeverity ~= 'Ok') then
    setTriggerStatus(newSeverity)
    triggers = {json.encode({id = source.trigger.id, priority = source.trigger.priority})}
    _G["triggers"] = table.concat(triggers,";")
    _G["clear"] = false
  elseif (trigger.status ~= 'Ok' and newSeverity ~= 'Ok') then
    if (convertTriggerPriority(trigger.status) < source.trigger.priority) then
      setTriggerStatus(newSeverity)
    end
    if (#_G["triggers"] > 0) then
      triggers = split(_G["triggers"],";")
      table.insert(triggers, json.encode({id = source.trigger.id, priority = source.trigger.priority }))
    else
      triggers = {json.encode({id = source.trigger.id, priority = source.trigger.priority})}
    end
    _G["triggers"] = table.concat(triggers,";")
    _G["clear"] = false
  elseif (trigger.status ~= 'Ok' and newSeverity == 'Ok') then
    triggers = split(_G["triggers"],";")
    local triggerKey = findEvent(triggers,source.trigger.id)
    if (triggerKey ~= nil) then
      table.remove(triggers, triggerKey)
      if (#triggers == 0) then
        _G["clear"] = true
        _G["clearTime"] = os.time()
        _G["triggers"] = ""
        scheduler:executeAfter(timeout)
      else
        if (convertTriggerPriority(trigger.status) == source.trigger.priority) then
          local newPriority = json.decode(triggers[1])['priority']
          for k,v in pairs(triggers) do
            if (json.decode(v)['priority'] > newPriority) then
              newPriority = json.decode(v)['priority']
            end
          end
          setTriggerStatus(convertTriggerStatus(1,newPriority))
        end
        _G["triggers"] = table.concat(triggers,";")
      end
    end
  end
end

# zabbixAccumulateWithDelayPeakSeverity

  • Устанавливает максимальный приоритет проблемы из попавших в него триггеров.
  • Запоминает активные проблемы.
  • По мере закрытия проблем, устанавливается максимальный из возникших приоритет и не снижается.
  • Закрывается только после истечения timeout, после закрытия последней проблемы.
-- Функция преобразования приоритета события в статус триггера
function convertTriggerStatus(value, priority)
  if (value == 0) then
    return 'Ok'
  elseif (priority == 2) then
    return 'Problem4'
  elseif (priority == 3) then
    return 'Problem3'
  elseif (priority == 4) then
    return 'Problem2'
  elseif (priority == 5) then
    return 'Problem1'
  end
end

-- Функция поиска ключа по eventId
function findEvent(table,element)
  for k,v in pairs(table) do
    if (v == element) then
      return k
    end
  end
end

-- Функция преобразования статуса триггера в приоритет события
function convertTriggerPriority(value)
  if (value == 'Problem1') then
    return 5
  elseif (value == 'Problem2') then
    return 4
  elseif (value == 'Problem3') then
    return 3
  else
    return 2
  end
end
function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

-- Установка таймаута очистки
local timeout = 900
-- Проверка запуска расчета scheduler и условий для закрытия
if (isScheduled == true) then
  if (_G["clear"] == true and (os.time()-_G["clearTime"]) >= timeout and trigger.status ~= 'Ok') then
    setTriggerStatus('Ok')
  end
else
  -- Вычисление нового значения триггера
  local newSeverity = convertTriggerStatus(source.trigger.value, source.trigger.priority)
  if (trigger.status == 'Ok' and newSeverity ~= 'Ok') then
    setTriggerStatus(newSeverity)
    _G["triggers"] = table.concat({source.trigger.id},";")
    _G["clear"] = false
  elseif (trigger.status ~= 'Ok' and newSeverity ~= 'Ok') then
    if (convertTriggerPriority(trigger.status) < source.trigger.priority) then
      setTriggerStatus(newSeverity)
    end
    if (#_G["triggers"] > 0) then
      triggers = split(_G["triggers"],";")
      table.insert(triggers, source.trigger.id)
    else
      triggers = {source.trigger.id}
    end
    _G["triggers"] = table.concat(triggers,";")
    _G["clear"] = false
  elseif (trigger.status ~= 'Ok' and newSeverity == 'Ok') then
    triggers = split(_G["triggers"],";")
    local triggerKey = findEvent(triggers,source.trigger.id)
    if (triggerKey ~= nil) then
      table.remove(triggers, triggerKey)
      if (#triggers == 0) then
        _G["clear"] = true
        _G["clearTime"] = os.time()
        _G["triggers"] = ""
        scheduler:executeAfter(timeout)
      else
        _G["triggers"] = table.concat(triggers,";")
      end
    end
  end
end

# zabbixByWeight

  • Устанавливает свой статус исходя из суммы весов попавших в него проблем.
  • Вес проблемы определяется согласно приоритету (1-5).
  • Трешхолды устанавливаются в функции setTriggerStatusByWeight.
-- Функция расчета и установки статуса триггера
function setTriggerStatusByWeight(weight)
  if (weight == 0) then
    setTriggerStatus('Ok')
  elseif (weight > 0 and weight <= 5) then
    setTriggerStatus('Problem4')
  elseif (weight > 5 and weight <= 10) then
    setTriggerStatus('Problem3')
  elseif (weight > 10 and weight <= 15) then
    setTriggerStatus('Problem2')
  elseif (weight > 15) then
    setTriggerStatus('Problem1')
  end
  _G['weight'] = weight
end

-- Инициализация глобальной переменной "Веса" триггера
if (trigger.status == 'Ok') then
  _G['weight']=0
end

-- Проверка приоритета проблемы больше 1 (Предупреждение и выше)
if (source.trigger.priority > 1) then
  if (source.trigger.value == 1) then
    setTriggerStatusByWeight(_G['weight']+source.trigger.priority)
  else
    if (source.trigger.priority >= _G['weight']) then
      setTriggerStatusByWeight(0)
    else
      setTriggerStatusByWeight(_G['weight']-source.trigger.priority)
    end
  end
end