Dans GLPI standard, une notification est un e-mail asynchrone : il tombe dans les spams, le technicien ne vit pas dans sa messagerie et le suivi reste des heures sans réponse. Smart Notify remplace ce modèle par une cloche dans la barre de navigation de GLPI qui interroge la base de données et agrège plus d'une douzaine d'événements ITIL en quasi temps réel. Maintenir des parcs GLPI clients en production nous a appris qu'activer la cloche est le plus facile ; le difficile est de calibrer ce qu'elle affiche pour qu'elle ne devienne pas du bruit. Ce guide couvre le fonctionnement du poll en coulisses, un SQL de diagnostic, la matrice des événements à laisser actifs et les pièges de terrain qui cassent le plus souvent l'installation.
Pourquoi l'e-mail natif ne résout pas l'alerte opérationnelle
Les notifications natives de GLPI reposent sur la file queuednotification et des modèles d'e-mail. C'est un modèle asynchrone et hors de l'outil : le technicien doit basculer entre GLPI et sa boîte de réception, l'e-mail transactionnel tombe dans le spam d'entreprise et personne ne surveille la messagerie en temps réel. Le résultat classique en exploitation est une validation bloquée pendant des heures et une tâche affectée que personne n'a vue.
La cloche résout cela pour qui est connecté à GLPI. Mais attention au premier piège : la cloche ne remplace pas l'e-mail pour le demandeur. Elle notifie le technicien en session, pas le client qui a ouvert le ticket via le self-service. L'erreur courante est de désactiver les notifications par e-mail en pensant que la cloche couvre tout le monde, et le demandeur cesse d'être averti. Cloche et e-mail sont des couches complémentaires, pas exclusives.
Comment la cloche fonctionne en coulisses (polling + delta)
Le JavaScript de la cloche effectue un poll toutes les 30 secondes (refresh_interval par défaut) sur un endpoint AJAX. À chaque cycle, le backend parcourt jusqu'à seize sources d'événements, construit la liste, applique la rétention (retention_days, 90 jours par défaut), plafonne à max_notifications (50 par défaut) et trie par date décroissante. Chaque notification reçoit un hash stable (sha1(type_id_timestamp)) : c'est lui qui marque l'élément comme lu sans ajouter de champ au ticket.
Ce que seul l'exploitant remarque, c'est le coût de ce poll toutes les 30 s par technicien connecté. C'est pourquoi l'endpoint utilise le mode delta : le client renvoie le hash du dernier état (state=) ; si rien n'a changé, la réponse passe d'environ 18 Ko à ~93 octets. Et le read-check est devenu un seul SELECT groupé : c'était auparavant un SELECT par notification, atteignant ~700 par poll chez les utilisateurs à gros backlog. Le GET appelle aussi session_write_close() d'emblée pour ne pas retenir le verrou de session PHP pendant le parcours de la base.
# La cloche interroge cet endpoint toutes les 30s (route via module_ajax):
GET /plugins/nextool/ajax/module_ajax.php?module=smartnotify&file=notifications.php&action=get&state=${HASH}
# Sans nouveaute depuis le dernier poll, la reponse est un delta d'~93 octets:
{ "success": true, "unchanged": true, "state": "...md5...", "unread_count": 4 }
# Ce n'est que lorsque quelque chose change qu'arrive le payload complet (~18KB) avec le tableau notifications[].
Les sources d'événements et ce qu'il faut laisser actif
La configuration globale expose seize déclencheurs et chaque technicien affine les siens dans la fenêtre de préférences (accessible directement depuis le menu déroulant de la cloche). Deux règles de ciblage comptent : le suivi que vous avez écrit ne vous notifie pas (la requête filtre users_id != utilisateur), et la notification arrive par implication directe ou par groupe technique (notify_group_involvement), en respectant toujours les entités actives de la session.
En maintien en condition opérationnelle, trois déclencheurs arrivent désactivés par défaut à dessein, et l'expérience confirme le choix : les documents joints sont du bruit dans les parcs à forts téléversements ; les nouveaux problèmes et nouveaux changements sont des événements moins fréquents qui encombrent la cloche de qui ne gère que des tickets. Tout activer est le chemin le plus rapide vers la fatigue d'alerte : le technicien commence à ignorer la cloche, et elle ne sert alors plus à rien.
| Famille d'événement | Déclencheur (config) | Par défaut | Note de terrain |
|---|---|---|---|
| Suivis (ticket, problème, changement) | notify_*_followup | Actif | Ce qui fait le plus bouger le backlog ; à garder |
| Validations et réponses de validation | notify_*_validation(_response) | Actif | Une approbation bloquée est un goulot silencieux |
| Tâches affectées | notify_*_task | Actif | C'est la file de travail du technicien |
| Solutions enregistrées | notify_solution | Actif | Boucle la boucle pour ceux qui suivent |
| Documents joints | notify_document | Inactif | Bruyant là où les téléversements abondent |
| Nouveaux tickets | notify_new_ticket | Actif | Signal d'entrée de file |
| Nouveaux problèmes / changements | notify_new_problem / _change | Inactif | Moins courants ; à activer par profil |
| Avis manuels (broadcast) | notify_manual | Actif | Maintenance, changement de processus |
Diagnostic par SQL : qui a coupé quoi
Quand un client se plaint que « la cloche ne prévient pas », le problème est presque toujours une préférence individuelle ou la mauvaise entité, pas un bug. Ces trois requêtes règlent le tri directement en base (tables réelles du module) :
-- 1. Combien de techniciens ont coupe chaque type d'evenement (bruit/fatigue):
SELECT
SUM(ticket_followups = 0) AS coupe_followup_ticket,
SUM(solutions = 0) AS coupe_solution,
SUM(documents = 0) AS coupe_document,
SUM(sound_enabled = 0) AS son_coupe
FROM glpi_plugin_nextool_smartnotify_preferences;
-- 2. Enregistrements de lecture par utilisateur (backlog et derniere activite):
SELECT users_id, COUNT(*) AS lectures_enregistrees, MAX(date_read) AS derniere_lecture
FROM glpi_plugin_nextool_smartnotify_read
GROUP BY users_id
ORDER BY derniere_lecture DESC;
-- 3. Broadcasts manuels actifs et leur cible (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;
Sons par priorité et le piège de l'autoplay
Les notifications émettent un son via la Web Audio API, avec quatre timbres mappés par priorité. Avant de regarder l'écran, le technicien entend si ce qui est arrivé est de la routine ou une urgence :
| Priorité | Son | Timbre (approx.) |
|---|---|---|
| Basse | subtle | Court et grave (440 Hz) |
| Normale | default | Standard (523 Hz) |
| Haute | alert | Moyen (659 Hz) |
| Urgente | alarm | Long et aigu (880 Hz) |
Le piège ici n'est pas le module, c'est le navigateur : la politique d'autoplay de Chrome n'autorise la création de l'AudioContext qu'après le premier geste de l'utilisateur. En pratique, le premier son d'une session ne sort qu'après le premier clic sur la page. Chaque mois quelqu'un ouvre un ticket disant « le son ne marche pas » : la réponse est de cliquer une fois sur la page. Ce n'est pas un bug, c'est la Web Audio API qui respecte le navigateur.
Broadcasts manuels et nettoyage automatique
Les administrateurs envoient des avis manuels avec un ciblage précis : tous, un utilisateur, un groupe ou une entité (la colonne target_type dans la table _manual). C'est le bon canal pour une fenêtre de maintenance ou un changement de processus sans e-mailer toute la base. La rétention est gérée par une CronTask quotidienne (smartnotify_cleanup), enregistrée à l'installation en MODE_EXTERNAL. C'est important : en MODE_INTERNAL la tâche s'exécute par web-hit et peut se bloquer en state=2. Déclenchez le cron de GLPI de l'extérieur (sur GLPI 11, front/cron.php) et le nettoyage se fait tout seul selon retention_days et logs_retention_days.
# CronTask enregistree a l'installation (idempotente), 1x/jour, MODE_EXTERNAL:
# Nom: smartnotify_cleanup Frequence: DAY_TIMESTAMP (86400s)
# Declenchez le cron de GLPI de l'exterieur (ne dependez jamais du MODE_INTERNAL via web-hit):
* * * * * www-data /usr/bin/php /var/www/html/front/cron.php >/dev/null 2>&1
Le piège qui casse l'installation : MySQL 8 vs MariaDB
Un cas réel de maintenance (juin 2026, client sous MySQL 8.0.46) : l'installation du module se transformait en HTTP 500 et le parc restait sans cloche. La cause racine n'était pas dans GLPI, elle était dans le SQL : un bloc ALTER TABLE ... ADD COLUMN IF NOT EXISTS, syntaxe exclusive à MariaDB. Sous MySQL 8, ce IF NOT EXISTS au niveau colonne n'existe pas et le statement échoue avec l'erreur 1064, faisant tomber toute l'installation. La leçon vaut pour tout plugin GLPI : le DDL conditionnel n'est pas portable entre MariaDB et MySQL. Le correctif (version 2.2.1+) a retiré le DDL conditionnel du .sql et déplacé les migrations en PHP avec les helpers portables du plugin de base. Si vous êtes sous MySQL 8, assurez-vous d'avoir le module en 2.2.1 ou supérieur.
Chez NexTool, nous déployons et maintenons des environnements GLPI de bout en bout. Si votre équipe vit avec des tickets oubliés et des notifications par e-mail que personne n'ouvre, Smart Notify est gratuit et s'active en quelques minutes depuis le catalogue de modules NexTool, et notre équipe de maintien aide à calibrer ce que reçoit chaque profil pour que la cloche devienne un signal, pas du bruit.
Ce contenu a été produit avec l'aide de l'intelligence artificielle et revu par l'équipe Nextool Solutions.