В стандартном 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.