alibek Posted September 22, 2022 Posted September 22, 2022 Есть Zabbix 5.4.2, в котором настроено оповещение в Телеграм. Для оповещалки используется штатный js-скрипт. Неудобством является то, что из оповещений Телеграма сложно понять, какие аварии все еще активны. Хочу сделать так, чтобы все активные аварии автоматически прикреплялись, а при закрытии аварии откреплялись. С закреплением проблем нет, в js-скрипте я после строчки response = request.post(url, data); добавлю еще вызов метода pinChatMessage и передам в нем response.message_id. Но вот как потом откреплять — пока не придумал. По идее, при возникновении аварии мне нужно где-то запоминать EVENT.ID и сопоставленный с ним идентификатор сообщения Телеграма. А при закрытии аварии нужно по EVENT.ID находить идентификатор ранее отправленного сообщения Телеграм. Но вот где хранить сопоставленный идентифиватор сообщения Телеграм — хороших идей нет. Лучше всего было бы хранить прямо в самом событии Заббикса (EVENT), но из js-скрипта к нему доступа нет. А изобретать костыли бы не хотелось. Вставить ник Quote
Ser Posted September 22, 2022 Posted September 22, 2022 А мне бы для монтажников нужно в чате телеграмм писать только Recent Alarm. Если данный список изменился, то удалять все записи в чате и писать новый обновленный список аварий. Есть идеи как это можно реализовать? Вставить ник Quote
alibek Posted September 22, 2022 Author Posted September 22, 2022 Запоминать при публикации message_id. При изменениях в составе аварий редактировать сообщение. Если аварий нет, то удалять сообщение и забывать message_id. Но это все будет каким-то сторонним решением. А я бы хотел без костылей, использовать штатный механизм заббикса. Вставить ник Quote
alibek Posted September 22, 2022 Author Posted September 22, 2022 Хотя я тут немного покопался, можно по быстрому и почти штатно. Нужно добавить способ оповещения с типом "скрипт", в параметрах скрипта прописать {EVENT.ID}, настроить скрипт на возникновение проблемы и восстановление проблемы. Затем в /usr/lib/zabbix/alertscripts создать скрипт с указанным именем. Заббикс будет вызывать скрипт, передавая в него идентификатор события. Но в принципе, идентификатор события особо не нужен. Скрипт с помощью метода problem.get будет получать список текущих проблем, формировать текст и с помощью editMessageText обновлять текст сообщения. А идентификатор сообщения можно просто прописать прямо в скрипте. Вставить ник Quote
alibek Posted September 23, 2022 Author Posted September 23, 2022 А вот и скрипт. <?php print "Подключение к NMS Zabbix\n"; if (!$zb = new Zabbix (null)) { print "! Сбой инициализации NMS Zabbix\n"; exit; } elseif ($zb->error()) { print "! Сбой подключения NMS Zabbix: " . $zb->error() . "\n"; exit; } file_put_contents("/tmp/{$script}_buffer.tmp", getmypid() . "\n", FILE_APPEND); print "Запрос действующих проблем из Zabbix...\n"; $tmp = $zb->request("problem.get", ["output"=>"extend", "recent"=>false, "severities"=>[4,5], "groupids"=>[19,20,21,22], "sortfield"=>["eventid"], "sortorder"=>"DESC"]); if (!$tmp) { print "! Ошибка получения списка проблем из Zabbix\n"; exit; } if (isset($tmp['error'])) { print "! Ошибка получения списка проблем из Zabbix: {$response['error']}\n"; exit; } $tmp = $tmp['result']; print "Запрос списка проблем из Zabbix выполнен, строк: " . count($tmp) . "\n"; $lst = []; foreach ($tmp as $rec) $lst[$rec['eventid']] = ['id'=>$rec['eventid'], 'clock'=>$rec['clock'], 'problem'=>$rec['name'], 'level'=>$rec['severity']]; print "Запрос деталей проблем из Zabbix...\n"; $tmp = $zb->request("event.get", ["output"=>"extend", "eventids"=>array_keys($lst), "selectHosts"=>"extend"]); if (!$tmp) { print "! Ошибка получения деталей проблем из Zabbix\n"; exit; } if (isset($tmp['error'])) { print "! Ошибка получения деталей проблем из Zabbix: {$response['error']}\n"; exit; } $tmp = $tmp['result']; foreach ($tmp as $rec) { if (!isset($lst[$rec['eventid']])) continue; if (!$rec['value']) continue; if (isset($rec['hosts'], $rec['hosts'][0])) { if ($rec['hosts'][0]['status']) continue; $lst[$rec['eventid']]['host'] = $rec['hosts'][0]['host']; $lst[$rec['eventid']]['title'] = $rec['hosts'][0]['name']; $lst[$rec['eventid']]['date'] = date("Y-m-d H:i", $rec['clock']); $lst[$rec['eventid']]['time'] = time() - $rec['clock']; } } $lst = array_filter($lst, function($rec) { return isset($rec['host']);}); $ids = array_keys($lst); sort($ids); $ids = implode(",", $ids); $ref = null; $old = ""; if (file_exists("/tmp/{$script}_telegram.tmp")) { $tmp = file_get_contents("/tmp/{$script}_telegram.tmp"); if (($tmp !== false) && $tmp) { $ref = trim(strtok($tmp, ":")); $old = trim(strtok(":")); } } print "Буфферизация отправки команд..."; sleep(2); if (!file_exists("/tmp/{$script}_buffer.tmp")) exit; $tmp = file_get_contents("/tmp/{$script}_buffer.tmp"); if (!$tmp) exit; $tmp = explode("\n", trim($tmp)); $tmp = end($tmp); if ($tmp != getmypid()) exit; unlink("/tmp/{$script}_buffer.tmp"); $tlg = new Telegram(); $rcpt = '...'; if ($ids) { print "# Есть аварии\n"; if ($ids == $old) { print "# Состав аварий не изменился, ничего не делать\n"; null; } else { print "# Состав аварий изменился\n"; $tlg->build(); $tlg->build("Список действующих аварий:\n"); foreach ($lst as $rec) { $tlg->build("- {$rec['title']} (с " . date("Y-m-d H:i", $rec['clock']) . ")\n"); } $tlg->build("\nИнформация обновлена: " . date("Y-m-d H:i:s")); if ($ref) { print "# Если есть закрепленное сообщение, то обновить его\n"; $tlg->editMessageText($rcpt, $ref); file_put_contents("/tmp/{$script}_telegram.tmp", "{$ref}: {$ids}"); } else { print "# Если закрепленного сообщения нет, то создать его и сохранить кеш\n"; if ($tmp = $tlg->sendMessage($rcpt)) { $ref = $tmp['message_id']; $tlg->pinChatMessage($rcpt, $ref); file_put_contents("/tmp/{$script}_telegram.tmp", "{$ref}: {$ids}"); } } } } else { print "# Нет аварий\n"; if ($ref) { print "# Если есть закрепленное сообщение, то закрыть его и удалить кеш\n"; $tlg->build(); $tlg->build("Активные аварии отсутствуют.\n"); $tlg->build("\nИнформация обновлена: " . date("Y-m-d H:i:s")); $tlg->editMessageText($rcpt, $ref); $tlg->unpinChatMessage($rcpt, $ref); unlink("/tmp/{$script}_telegram.tmp"); } } Обертки Zabbix и Telegram нужно подставить свои, но в принципе скрипт полный и рабочий. Вставить ник Quote
Ser Posted September 26, 2022 Posted September 26, 2022 Спасибо. Попробую разобраться. Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.