Уведомления в реальном времени в GLPI со Smart Notify

В стандартном GLPI уведомление - это асинхронный e-mail, за которым никто не следит. Бесплатный модуль Smart Notify добавляет в панель навигации колокольчик, который опрашивает базу (режим delta ~93 байта) и собирает шестнадцать источников событий ITIL. Как работает опрос, SQL для диагностики, матрица событий, которые стоит оставить включёнными, и ловушки из практики - от автовоспроизведения в Chrome до ошибки 1064 в MySQL 8.

В этой статьеРазделов: 7

В стандартном GLPI уведомление - это асинхронный e-mail: он попадает в спам, специалист не живёт в веб-почте, и комментарий часами остаётся без ответа. Smart Notify заменяет эту модель колокольчиком в панели самого GLPI, который опрашивает базу и собирает более дюжины событий ITIL почти в реальном времени. При сопровождении клиентских парков мы поняли, что сложно не включить колокольчик, а откалибровать то, что он показывает, чтобы он не превратился в шум. Это руководство показывает, как устроен опрос, SQL для диагностики, матрицу событий, которые стоит оставить включёнными, и ловушки, чаще всего ломающие установку.

Почему встроенный e-mail не решает задачу операционных уведомлений

Встроенные уведомления GLPI зависят от очереди queuednotification и шаблонов писем. Это асинхронная модель вне инструмента: специалисту приходится переключаться между GLPI и почтовым ящиком, транзакционные письма попадают в корпоративный спам, и никто не следит за веб-почтой в реальном времени. Классический результат в эксплуатации - согласование, стоящее часами, и назначенная задача, которую никто не заметил.

Колокольчик решает это для тех, кто вошёл в GLPI. Но обратите внимание на первую ловушку: колокольчик не заменяет e-mail для инициатора. Он уведомляет специалиста, находящегося в сессии, а не клиента, создавшего заявку через self-service. Типичная ошибка - отключить уведомления по e-mail в расчёте на то, что колокольчик охватывает всех, - и инициатор перестаёт получать оповещения. Колокольчик и e-mail - взаимодополняющие слои, а не взаимоисключающие.

Как колокольчик устроен изнутри (polling + delta)

JavaScript колокольчика выполняет опрос каждые 30 секунд (refresh_interval по умолчанию) к AJAX-эндпоинту. В каждом цикле бэкенд перебирает до шестнадцати источников событий, формирует список, применяет срок хранения (retention_days, по умолчанию 90 дней), обрезает до max_notifications (по умолчанию 50) и сортирует по убыванию даты. Каждое уведомление получает стабильный хеш (sha1(tipo_id_timestamp)) - именно он помечает элемент как прочитанный, не требуя нового поля в заявке.

Момент, который замечают только те, кто эксплуатирует систему, - стоимость такого опроса каждые 30 с для каждого вошедшего специалиста. Поэтому эндпоинт использует режим delta: клиент передаёт хеш последнего состояния (state=); если ничего не изменилось, ответ уменьшается примерно с 18 КБ до ~93 байт. А проверка прочтения стала одним пакетным SELECT - раньше это был отдельный SELECT на каждое уведомление, до ~700 за опрос у пользователей с большим бэклогом. GET также сразу вызывает session_write_close(), чтобы не удерживать блокировку сессии PHP, пока идёт обход базы.

# O sino faz polling a cada 30s neste endpoint (roteado pelo module_ajax):
GET /plugins/nextool/ajax/module_ajax.php?module=smartnotify&file=notifications.php&action=get&state=${HASH}

# Sem novidade desde o ultimo poll, a resposta e um delta de ~93 bytes:
{ "success": true, "unchanged": true, "state": "...md5...", "unread_count": 4 }

# So quando algo muda vem o payload completo (~18KB) com o array notifications[].

Источники событий и что оставить включённым

Глобальная конфигурация предоставляет шестнадцать триггеров, и каждый специалист дополнительно настраивает свои в модальном окне предпочтений (оно открывается прямо из выпадающего меню колокольчика). Важны два правила таргетинга: комментарий, который написали вы, вас не уведомляет (запрос фильтрует users_id != usuário), а уведомление приходит при прямом участии или через группу специалистов (notify_group_involvement), всегда с учётом активных организаций сессии.

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

Семейство событийТриггер (config)По умолчаниюЗаметка из практики
Комментарии (заявка, проблема, изменение)notify_*_followupВключеноБольше всего двигает бэклог; оставьте
Согласования и ответы на согласованияnotify_*_validation(_response)ВключеноЗастрявшее согласование - тихое узкое место
Назначенные задачиnotify_*_taskВключеноЭто рабочая очередь специалиста
Зарегистрированные решенияnotify_solutionВключеноЗамыкает цикл для тех, кто следит
Прикреплённые документыnotify_documentВыключеноШумно там, где много вложений
Новые заявкиnotify_new_ticketВключеноСигнал входа в очередь
Новые проблемы / измененияnotify_new_problem / _changeВыключеноРеже встречаются; включайте по профилю
Ручные объявления (broadcast)notify_manualВключеноОбслуживание, изменение процесса

Диагностика через SQL: кто что отключил

Когда клиент жалуется, что «колокольчик не оповещает», проблема почти всегда в индивидуальных предпочтениях или неверной организации, а не в баге. Эти три запроса решают сортировку прямо в базе (реальные таблицы модуля):

-- 1. Quantos tecnicos silenciaram cada tipo de evento (acha ruido/fadiga):
SELECT
  SUM(ticket_followups = 0) AS mudo_followup_ticket,
  SUM(solutions = 0)        AS mudo_solucao,
  SUM(documents = 0)        AS mudo_documento,
  SUM(sound_enabled = 0)    AS som_desligado
FROM glpi_plugin_nextool_smartnotify_preferences;

-- 2. Registros de leitura por usuario (backlog e ultima atividade):
SELECT users_id, COUNT(*) AS lidas_registradas, MAX(date_read) AS ultima_leitura
FROM glpi_plugin_nextool_smartnotify_read
GROUP BY users_id
ORDER BY ultima_leitura DESC;

-- 3. Broadcasts manuais ativos e seu alvo (all/user/group/entity):
SELECT id, title, priority, target_type, target_id, entities_id, date_creation
FROM glpi_plugin_nextool_smartnotify_manual
WHERE is_active = 1
ORDER BY date_creation DESC;

Звуки по приоритету и ловушка автовоспроизведения

Уведомления воспроизводят звук через Web Audio API, с четырьмя тембрами, сопоставленными приоритетам. Специалист ещё до взгляда на экран слышит, рутина пришла или срочное:

ПриоритетЗвукТембр (прибл.)
НизкийsubtleКороткий и низкий (440 Гц)
ОбычныйdefaultСтандартный (523 Гц)
ВысокийalertСредний (659 Гц)
СрочныйalarmДлинный и высокий (880 Гц)

Ловушка здесь не в модуле, а в браузере: политика автовоспроизведения Chrome позволяет создать AudioContext только после первого действия пользователя. На практике первый звук сессии раздаётся только после первого клика по странице. Каждый месяц кто-то создаёт заявку «звук не работает» - ответ: один раз кликнуть по странице. Это не баг, это Web Audio API, уважающий правила браузера.

Ручные объявления и автоматическая очистка

Администраторы отправляют ручные объявления с точным таргетингом: всем, одному пользователю, группе или организации (столбец target_type в таблице _manual). Это правильный канал для окна обслуживания или изменения процесса без рассылки писем по всей базе. За сроком хранения следит ежедневная CronTask (smartnotify_cleanup), зарегистрированная при установке как MODE_EXTERNAL. Это важно: в MODE_INTERNAL задача запускается по веб-обращениям и может зависнуть в state=2. Запускайте cron GLPI извне (в GLPI 11 - front/cron.php), и очистка будет происходить сама согласно retention_days и logs_retention_days.

# CronTask registrada no install (idempotente), 1x/dia, MODE_EXTERNAL:
#   Nome: smartnotify_cleanup   Frequencia: DAY_TIMESTAMP (86400s)
# Dispare o cron do GLPI por fora (nunca dependa do MODE_INTERNAL via web-hit):
* * * * * www-data /usr/bin/php /var/www/html/front/cron.php >/dev/null 2>&1

Ловушка, которая ломает установку: MySQL 8 и MariaDB

Реальный случай из сопровождения (июнь 2026 г., клиент на MySQL 8.0.46): установка модуля заканчивалась HTTP 500, и парк оставался без колокольчика. Корневая причина была не в GLPI, а в SQL: блок ALTER TABLE ... ADD COLUMN IF NOT EXISTS - синтаксис, существующий только в MariaDB. В MySQL 8 такого IF NOT EXISTS для столбца нет, и оператор падает с ошибкой 1064, обрушивая всю установку. Урок справедлив для любого плагина GLPI: условный DDL не переносим между MariaDB и MySQL. Исправление (версия 2.2.1+) убрало условный DDL из .sql и перенесло миграции в PHP с переносимыми хелперами базового плагина. Если у вас MySQL 8, убедитесь, что модуль версии 2.2.1 или выше.

В NexTool мы внедряем и сопровождаем среды GLPI от начала до конца. Если ваша команда живёт с забытыми заявками и уведомлениями по e-mail, которые никто не открывает, Smart Notify бесплатен и включается за минуты через каталог модулей NexTool - а наша команда сопровождения поможет откалибровать, что получает каждый профиль, чтобы колокольчик стал сигналом, а не шумом.


Проверено командой NexTool Solutions.

Часто задаваемые вопросы

Нет. Встроенный GLPI зависит от очереди queuednotification и шаблонов писем - это асинхронная модель вне инструмента. Бесплатный модуль Smart Notify добавляет в панель навигации колокольчик, который опрашивает базу каждые 30 секунд и собирает шестнадцать источников событий ITIL (комментарии, согласования, задачи, решения, документы, новые заявки и ручные объявления), со звуками по приоритету.

Нет, это взаимодополняющие слои. Колокольчик оповещает тех, кто вошёл в GLPI, - как правило, специалиста в сессии. Инициатор, создавший заявку через self-service, по-прежнему зависит от e-mail. Типичная ошибка - отключить уведомления по e-mail в расчёте на то, что колокольчик охватывает всех; тогда клиент перестаёт получать оповещения.

Незначительно - благодаря режиму delta. Клиент передаёт хеш последнего состояния (state=), и если ничего не изменилось, ответ уменьшается примерно с 18 КБ до ~93 байт - в большинстве опросов новостей нет. Проверка прочтения объединена в один пакетный SELECT (раньше - по одному на уведомление), а GET освобождает блокировку сессии через session_write_close(). Интервал настраивается в refresh_interval.

Калибруя то, что получает каждый профиль. Три триггера по умолчанию выключены (прикреплённые документы, новые проблемы и новые изменения), потому что они шумные или редкие. Каждый специалист донастраивает их в окне предпочтений, а SQL по таблице _preferences показывает, кто что отключил. Если включить всё, наступает усталость от оповещений, и специалист начинает игнорировать колокольчик.

Это политика автовоспроизведения Chrome, а не баг. Браузер позволяет создать AudioContext только после первого действия пользователя, поэтому первый звук каждой сессии раздаётся лишь после первого клика по странице. Дальше звуки по приоритету воспроизводятся нормально.

Работает в обоих начиная с версии 2.2.1. Предыдущие версии содержали в install.sql ALTER TABLE ... ADD COLUMN IF NOT EXISTS - синтаксис только MariaDB, который в MySQL 8 падает с ошибкой 1064 и обрушивает установку (HTTP 500). Исправление перенесло миграции в PHP с переносимыми хелперами. В MySQL 8 используйте 2.2.1 или выше.

Нужна помощь?