Notifiche in tempo reale in GLPI con Smart Notify

Nel GLPI standard una notifica è una e-mail asincrona che nessuno controlla. Il modulo gratuito Smart Notify mette una campanella nella navbar che interroga il database (modalità delta ~93 byte) e aggrega sedici sorgenti di eventi ITIL. Scopri come funziona il poll, l'SQL di diagnostica, la matrice di quali eventi tenere attivi e le trappole sul campo, dall'autoplay di Chrome all'errore 1064 di MySQL 8.

Nel GLPI standard una notifica è una e-mail asincrona: finisce nello spam, il tecnico non vive nella webmail e il follow-up resta ore senza risposta. Smart Notify sostituisce questo modello con una campanella nella barra di navigazione di GLPI che interroga il database e aggrega più di una dozzina di eventi ITIL quasi in tempo reale. Gestire parchi GLPI di clienti in produzione ci ha insegnato che accendere la campanella è la parte facile; la difficile è calibrare ciò che mostra perché non diventi rumore. Questa guida spiega come funziona il poll sotto il cofano, un SQL di diagnostica, la matrice di quali eventi tenere attivi e le trappole sul campo che più spesso rompono l'installazione.

Perché l'e-mail nativa non risolve l'allerta operativa

Le notifiche native di GLPI dipendono dalla coda queuednotification e da modelli e-mail. È un modello asincrono e fuori dallo strumento: il tecnico deve alternare tra GLPI e la casella di posta, l'e-mail transazionale finisce nello spam aziendale e nessuno controlla la webmail in tempo reale. L'esito classico dell'operatività è un'approvazione ferma per ore e un'attività assegnata che nessuno ha visto.

La campanella risolve questo per chi è connesso a GLPI. Ma attenzione alla prima trappola: la campanella non sostituisce l'e-mail per il richiedente. Notifica il tecnico in sessione, non il cliente che ha aperto il ticket dal self-service. L'errore comune è disattivare le notifiche e-mail pensando che la campanella copra tutti, e il richiedente smette di essere avvisato. Campanella ed e-mail sono livelli complementari, non alternativi.

Come funziona la campanella sotto il cofano (polling + delta)

Il JavaScript della campanella esegue un poll ogni 30 secondi (refresh_interval predefinito) verso un endpoint AJAX. A ogni ciclo il backend scorre fino a sedici sorgenti di eventi, compone la lista, applica la ritenzione (retention_days, 90 giorni di default), taglia a max_notifications (50 di default) e ordina per data decrescente. Ogni notifica riceve un hash stabile (sha1(tipo_id_timestamp)): è ciò che segna l'elemento come letto senza aggiungere un campo al ticket.

Ciò che solo chi opera nota è il costo di quel poll ogni 30 s per tecnico connesso. Per questo l'endpoint usa la modalità delta: il client restituisce l'hash dell'ultimo stato (state=); se nulla è cambiato, la risposta scende da circa 18 KB a ~93 byte. E il read-check è diventato un unico SELECT in blocco: prima era un SELECT per notifica, arrivando a ~700 per poll negli utenti con grande backlog. Il GET chiama anche session_write_close() subito, per non trattenere il lock di sessione PHP mentre scorre il database.

# La campanella fa polling ogni 30s su questo endpoint (instradato da module_ajax):
GET /plugins/nextool/ajax/module_ajax.php?module=smartnotify&file=notifications.php&action=get&state=${HASH}

# Senza novita dall'ultimo poll, la risposta e un delta di ~93 byte:
{ "success": true, "unchanged": true, "state": "...md5...", "unread_count": 4 }

# Solo quando qualcosa cambia arriva il payload completo (~18KB) con l'array notifications[].

Le sorgenti di eventi e cosa lasciare attivo

La configurazione globale espone sedici trigger e ogni tecnico affina i propri nella finestra delle preferenze (raggiungibile direttamente dal menu a tendina della campanella). Contano due regole di targeting: il follow-up che tu hai scritto non ti notifica (la query filtra users_id != utente), e la notifica arriva per coinvolgimento diretto oppure per gruppo tecnico (notify_group_involvement), rispettando sempre le entità attive della sessione.

Nel mantenimento operativo tre trigger arrivano disattivati di default di proposito, e l'esperienza conferma la scelta: i documenti allegati sono rumore nei parchi con molti caricamenti; i nuovi problemi e i nuovi cambiamenti sono eventi meno frequenti che intasano la campanella di chi gestisce solo ticket. Accendere tutto è la via più rapida alla fatica da allerta: il tecnico inizia a ignorare la campanella, e allora non serve a nulla.

Famiglia di eventoTrigger (config)DefaultNota sul campo
Follow-up (ticket, problema, cambiamento)notify_*_followupAttivoCiò che muove di più il backlog; tienilo
Validazioni e risposte di validazionenotify_*_validation(_response)AttivoUn'approvazione ferma è un collo di bottiglia silenzioso
Attività assegnatenotify_*_taskAttivoÈ la coda di lavoro del tecnico
Soluzioni registratenotify_solutionAttivoChiude il cerchio per chi segue
Documenti allegatinotify_documentInattivoRumoroso dove i caricamenti abbondano
Nuovi ticketnotify_new_ticketAttivoSegnale di ingresso in coda
Nuovi problemi / cambiamentinotify_new_problem / _changeInattivoMeno comuni; attivali per profilo
Avvisi manuali (broadcast)notify_manualAttivoManutenzione, cambio di processo

Diagnostica via SQL: chi ha silenziato cosa

Quando un cliente si lamenta che "la campanella non avvisa", il problema è quasi sempre una preferenza individuale o l'entità sbagliata, non un bug. Queste tre query risolvono il triage direttamente nel database (tabelle reali del modulo):

-- 1. Quanti tecnici hanno silenziato ogni tipo di evento (trova rumore/fatica):
SELECT
  SUM(ticket_followups = 0) AS muto_followup_ticket,
  SUM(solutions = 0)        AS muto_soluzione,
  SUM(documents = 0)        AS muto_documento,
  SUM(sound_enabled = 0)    AS suono_off
FROM glpi_plugin_nextool_smartnotify_preferences;

-- 2. Record di lettura per utente (backlog e ultima attivita):
SELECT users_id, COUNT(*) AS letture_registrate, MAX(date_read) AS ultima_lettura
FROM glpi_plugin_nextool_smartnotify_read
GROUP BY users_id
ORDER BY ultima_lettura DESC;

-- 3. Broadcast manuali attivi e loro destinazione (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;

Suoni per priorità e la trappola dell'autoplay

Le notifiche emettono un suono tramite la Web Audio API, con quattro timbri mappati per priorità. Prima di guardare lo schermo, il tecnico sente se ciò che è arrivato è routine o urgenza:

PrioritàSuonoTimbro (circa)
BassasubtleBreve e grave (440 Hz)
NormaledefaultStandard (523 Hz)
AltaalertMedio (659 Hz)
UrgentealarmLungo e acuto (880 Hz)

La trappola qui non è del modulo, è del browser: la politica di autoplay di Chrome consente di creare l'AudioContext solo dopo il primo gesto dell'utente. In pratica, il primo suono di una sessione esce solo dopo il primo clic sulla pagina. Ogni mese qualcuno apre un ticket dicendo "il suono non funziona": la risposta è fare un clic sulla pagina. Non è un bug, è la Web Audio API che rispetta il browser.

Broadcast manuali e pulizia automatica

Gli amministratori inviano avvisi manuali con targeting preciso: tutti, un utente, un gruppo o un'entità (la colonna target_type nella tabella _manual). È il canale giusto per una finestra di manutenzione o un cambio di processo senza inviare e-mail all'intera base. La ritenzione è gestita da una CronTask giornaliera (smartnotify_cleanup), registrata all'installazione come MODE_EXTERNAL. È importante: in MODE_INTERNAL l'attività gira via web-hit e può bloccarsi in state=2. Attiva il cron di GLPI dall'esterno (su GLPI 11, front/cron.php) e la pulizia avviene da sola secondo retention_days e logs_retention_days.

# CronTask registrata all'installazione (idempotente), 1x/giorno, MODE_EXTERNAL:
#   Nome: smartnotify_cleanup   Frequenza: DAY_TIMESTAMP (86400s)
# Attiva il cron di GLPI dall'esterno (non dipendere mai dal MODE_INTERNAL via web-hit):
* * * * * www-data /usr/bin/php /var/www/html/front/cron.php >/dev/null 2>&1

La trappola che rompe l'installazione: MySQL 8 vs MariaDB

Un caso reale di mantenimento (giugno 2026, cliente su MySQL 8.0.46): l'installazione del modulo diventava un HTTP 500 e il parco restava senza campanella. La causa radice non era in GLPI, era nel SQL: un blocco ALTER TABLE ... ADD COLUMN IF NOT EXISTS, sintassi esclusiva di MariaDB. Su MySQL 8 quell'IF NOT EXISTS a livello di colonna non esiste e lo statement fallisce con errore 1064, facendo cadere l'intera installazione. La lezione vale per qualsiasi plugin GLPI: il DDL condizionale non è portabile tra MariaDB e MySQL. La correzione (versione 2.2.1+) ha rimosso il DDL condizionale dal .sql e spostato le migrazioni in PHP con gli helper portabili del plugin base. Se usi MySQL 8, assicurati che il modulo sia alla 2.2.1 o superiore.

In NexTool implementiamo e manteniamo ambienti GLPI end to end. Se il tuo team convive con ticket dimenticati e notifiche e-mail che nessuno apre, Smart Notify è gratuito e si attiva in pochi minuti dal catalogo di moduli NexTool, e il nostro team di mantenimento aiuta a calibrare cosa riceve ogni profilo perché la campanella diventi segnale, non rumore.


Questo contenuto è stato prodotto con l'ausilio dell'intelligenza artificiale e revisionato dal team di Nextool Solutions.

Domande Frequenti

No. GLPI nativo dipende dalla coda queuednotification e da modelli e-mail, un modello asincrono e fuori dallo strumento. Il modulo gratuito Smart Notify aggiunge una campanella nella navbar che interroga il database ogni 30 secondi e aggrega sedici sorgenti di eventi ITIL (follow-up, validazioni, attività, soluzioni, documenti, nuovi ticket e avvisi manuali), con suoni per priorità.

No, sono livelli complementari. La campanella avvisa chi è connesso a GLPI, tipicamente il tecnico in sessione. Il richiedente che ha aperto il ticket dal self-service dipende ancora dall'e-mail. L'errore comune è disattivare le notifiche e-mail pensando che la campanella copra tutti; allora il cliente smette di essere avvisato.

Poco, grazie alla modalità delta. Il client restituisce l'hash dell'ultimo stato (state=) e, se nulla è cambiato, la risposta scende da circa 18 KB a ~93 byte: la maggior parte dei poll non ha novità. Il read-check è stato consolidato in un unico SELECT in blocco (prima era uno per notifica) e il GET rilascia il lock di sessione con session_write_close(). L'intervallo è configurabile in refresh_interval.

Calibrando ciò che riceve ogni profilo. Tre trigger arrivano già disattivati di default (documenti allegati, nuovi problemi e nuovi cambiamenti) perché rumorosi o poco frequenti. Ogni tecnico affina nella finestra delle preferenze, e l'SQL sulla tabella _preferences mostra chi ha silenziato cosa. Accendere tutto porta alla fatica da allerta e il tecnico inizia a ignorare la campanella.

È la politica di autoplay di Chrome, non un bug. Il browser consente di creare l'AudioContext solo dopo il primo gesto dell'utente, quindi il primo suono di ogni sessione esce solo dopo il primo clic sulla pagina. Da lì in poi i suoni per priorità partono normalmente.

Funziona su entrambi dalla versione 2.2.1. Le versioni precedenti portavano un ALTER TABLE ... ADD COLUMN IF NOT EXISTS in install.sql, sintassi esclusiva di MariaDB che su MySQL 8 fallisce con errore 1064 e rompe l'installazione (HTTP 500). La correzione ha spostato le migrazioni in PHP con helper portabili. Su MySQL 8, usa la 2.2.1 o superiore.

Hai bisogno di aiuto?