Suivez Qui a Consulté Chaque Ticket dans GLPI avec Ticket Tracker

Dans GLPI standard, aucun enregistrement de lecture n'existe. Le module gratuit Ticket Tracker enregistre chaque consultation de ticket - comptage, première et dernière lecture et un journal d'accès par utilisateur - et livre même les requêtes SQL pour trouver les tickets que le responsable n'a jamais ouverts.

Dans GLPI standard, il n'existe aucun enregistrement de lecture : l'historique du ticket garde ce qui a changé, jamais qui l'a simplement ouvert et lu. Dans la maintenance de parcs GLPI de clients, cela devient l'impasse classique du "le technicien n'a même pas regardé le ticket" contre "si, je l'ai lu" - et sans donnée objective, c'est la parole de l'un contre celle de l'autre. Le module gratuit Ticket Tracker comble cette lacune en enregistrant chaque consultation de ticket. Ce guide montre comment il stocke les données, comment le configurer sans gonfler les compteurs et trois requêtes SQL qui répondent "qui a lu quoi" sur-le-champ.

Pourquoi GLPI ne sait pas qui a lu un ticket

L'historique natif (glpi_logs) n'enregistre que les changements : création, changement de statut, nouveau suivi, réattribution de technicien. Ouvrir le formulaire et le lire ne modifie aucun champ, donc ne produit aucune ligne. Il n'y a, dans le cœur de GLPI, aucun événement de "consultation". Ticket Tracker règle cela en s'accrochant au moment où le formulaire du ticket est rendu (le hook postShowItem du Ticket) : chaque fois qu'une session authentifiée affiche un ticket, le module enregistre la consultation. Sans action manuelle, sans nouveau champ sur le formulaire.

Les deux couches d'enregistrement : résumé et journal

Le module écrit dans deux tables aux finalités distinctes. Le résumé répond "combien de fois et quand" ; le journal répond "chaque accès, un par un" :

-- Résumé par (ticket, utilisateur) : une ligne, mise à jour à chaque accès.
CREATE TABLE `glpi_plugin_nextool_tickettracker_views` (
  `id`         int unsigned NOT NULL AUTO_INCREMENT,
  `tickets_id` int unsigned NOT NULL,
  `users_id`   int unsigned NOT NULL,
  `view_count` int unsigned NOT NULL DEFAULT 1,
  `first_view` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `last_view`  timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_ticket_user` (`tickets_id`, `users_id`)
);

-- Journal détaillé : une ligne par accès individuel.
CREATE TABLE `glpi_plugin_nextool_tickettracker_viewlog` (
  `id`         int unsigned NOT NULL AUTO_INCREMENT,
  `tickets_id` int unsigned NOT NULL,
  `users_id`   int unsigned NOT NULL,
  `view_date`  timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
);

La clé UNIQUE (tickets_id, users_id) est le cœur de la table de résumé : chaque paire ticket/utilisateur a exactement une ligne. L'écriture utilise INSERT ... ON DUPLICATE KEY UPDATE view_count = view_count + 1, un upsert atomique - deux accès simultanés du même utilisateur ne créent pas de ligne dupliquée et ne perdent aucun comptage. L'onglet "Consultations" sur le ticket lit le résumé (tableau avec tous les lecteurs, comptage, première et dernière lecture) et propose une cascade dépliable qui tire du journal chaque accès individuel, avec date et heure.

Activation et checklist de configuration

Le module est gratuit et s'active depuis le catalogue NexTool. Une fois activé, la configuration se trouve dans Modules > Ticket Tracker, onglet Fonctionnalités :

  1. Module actif - le même interrupteur que sur la page Modules. Éteint, rien n'est suivi.
  2. Suivi actif (tracking_enabled) - active l'enregistrement des consultations. Il peut rester actif avec l'onglet masqué si vous voulez collecter sans exposer.
  3. Afficher l'onglet sur le ticket (show_tab_on_ticket) - affiche ou masque l'onglet "Consultations" sur le formulaire du ticket.
  4. Intervalle minimum (s) (min_interval_seconds, défaut 60) - une fenêtre de debounce : les accès du même utilisateur au même ticket dans cet intervalle comptent pour un.
  5. Ignorés (onglet Permissions supplémentaires) - utilisateurs, profils ou groupes qui consultent sans être suivis. Tout vide = chaque accès compte.

L'erreur de champ qui gonfle (ou met à zéro) les compteurs

L'erreur courante est de mettre l'intervalle minimum à zéro en pensant "plus c'est granulaire, mieux c'est". Le hook se déclenche à chaque rendu du formulaire - y compris rechargements, navigation arrière et réouvertures de l'onglet. Avec min_interval_seconds = 0, un technicien qui laisse le ticket ouvert et actualise trois fois devient "trois lectures", et view_count perd son sens de "combien de fois il est vraiment revenu sur le sujet". La valeur par défaut de 60 secondes existe précisément pour réduire la rafale de rechargements à une seule lecture. N'utilisez 0 que pour un diagnostic ponctuel et revenez à la valeur par défaut ensuite.

La seconde erreur est plus subtile et nous l'avons rencontrée chez un client : jusqu'à la version 1.2.0 du module, l'enregistrement dépendait de la permission de voir l'onglet Consultations - autrement dit, seuls les profils administratifs étaient comptés. Le demandeur et les observateurs ouvraient le ticket et rien n'était enregistré, donc la base sous-déclarait exactement ceux qui comptent le plus dans un litige de SLA. Nous avons découplé l'enregistrement de la permission de voir l'onglet : aujourd'hui toute session authentifiée qui rend le ticket est comptabilisée - demandeur, observateur ou technicien - quel que soit le profil. Si vous exploitez une version antérieure, mettez à jour avant de faire confiance aux chiffres.

Matrice de décision : intervalle et ignorés par scénario

Le bon réglage dépend de ce que vous voulez prouver. La matrice que nous utilisons en conception :

Scénario d'exploitationSuiviIntervalle minimum (s)Qui mettre en "ignorés"
Audit de lecture / SLA (défaut)Activé60Personne
Parc avec auto-rafraîchissement ou tableau muralActivé180 à 300Comptes d'intégration / bots
Supervision qui ne doit pas gonfler le compteurActivé60Profil de gestionnaires / auditeurs
Diagnostic ponctuel (compter chaque accès)Activé0 (temporaire)Personne

Trois requêtes SQL qui répondent sur-le-champ

L'onglet règle le cas par cas ; pour une vue de parc, allez droit à la base de données. Tickets ouverts attribués que le technicien responsable n'a pas encore ouverts (type = 2 dans glpi_tickets_users, c'est le technicien attribué) :

-- Tickets ouverts attribués que le technicien responsable n'a JAMAIS consultés.
SELECT t.id AS ticket, t.name AS titre, u.name AS technicien, t.date AS ouvert_le
FROM glpi_tickets t
JOIN glpi_tickets_users tu ON tu.tickets_id = t.id AND tu.type = 2
JOIN glpi_users u ON u.id = tu.users_id
LEFT JOIN glpi_plugin_nextool_tickettracker_views v
       ON v.tickets_id = t.id AND v.users_id = tu.users_id
WHERE t.is_deleted = 0
  AND t.status IN (1, 2, 3, 4)   -- nouveau, attribué, planifié, en attente
  AND v.id IS NULL               -- aucune lecture enregistrée par le technicien
ORDER BY t.date ASC;

Latence de lecture - combien de minutes le ticket est resté ouvert jusqu'à la première lecture du technicien attribué. C'est la métrique qui précède la première réponse et explique souvent un SLA dépassé :

-- Minutes entre l'ouverture et la 1re lecture par le technicien attribué.
SELECT t.id AS ticket,
       TIMESTAMPDIFF(MINUTE, t.date, v.first_view) AS minutes_avant_1re_lecture
FROM glpi_tickets t
JOIN glpi_tickets_users tu ON tu.tickets_id = t.id AND tu.type = 2
JOIN glpi_plugin_nextool_tickettracker_views v
       ON v.tickets_id = t.id AND v.users_id = tu.users_id
WHERE t.is_deleted = 0
ORDER BY minutes_avant_1re_lecture DESC;

Les lecteurs les plus actifs d'un ticket précis, depuis le résumé, pour savoir qui le suit vraiment (remplacez 12345 par l'ID du ticket) :

-- Qui a le plus ouvert le ticket 12345, du plus récurrent au moins.
SELECT u.name AS utilisateur, v.view_count, v.first_view, v.last_view
FROM glpi_plugin_nextool_tickettracker_views v
JOIN glpi_users u ON u.id = v.users_id
WHERE v.tickets_id = 12345
ORDER BY v.view_count DESC;

Lire n'est pas répondre : ce que prouve le compteur

La donnée est puissante, mais elle a une limite honnête : elle prouve que le formulaire a été rendu pour cet utilisateur, pas que la personne l'a lu attentivement ni qu'elle a agi. Un view_count élevé sans suivi est un signal orange - quelqu'un ouvre et ferme sans résoudre. Un ticket avec zéro consultation du responsable pendant que le SLA court est un signal rouge - personne n'a même regardé. En maintenance, la vraie valeur n'est pas de surveiller le technicien, c'est de combler le vide probatoire : quand le client demande "pourquoi ce ticket est resté trois jours sans bouger ?", la réponse cesse d'être une opinion et gagne un horodatage.

Besoin d'une visibilité réelle sur le traitement dans votre GLPI, avec les bons modules activés et ajustés à votre flux ? Découvrez le service de maintenance GLPI de NexTool.


Ce contenu a été produit avec l'aide de l'intelligence artificielle et révisé par l'équipe Nextool Solutions.

Questions fréquentes

Non. L'historique (glpi_logs) n'enregistre que les changements de champs - statut, suivis, réattribution de technicien. Ouvrir et lire ne change rien, il n'existe donc aucun enregistrement natif de consultation. Ticket Tracker comble ce manque en enregistrant chaque rendu du formulaire du ticket.

Pas dans la version actuelle. Le journal détaillé stocke ticket, utilisateur et horodatage de chaque accès ; l'identification se fait par l'utilisateur authentifié de GLPI, pas par l'IP. Pour un audit par personne, users_id est plus fiable que l'IP, qui change avec VPN, NAT et proxy.

Non, si l'intervalle minimum est réglé. La valeur par défaut de 60 secondes fait que les accès du même utilisateur au même ticket dans la fenêtre comptent pour un. Seul un intervalle de 0 transforme chaque rafraîchissement en une lecture - n'utilisez 0 que pour un diagnostic et revenez à la valeur par défaut.

Ajoutez l'utilisateur, le profil ou le groupe à la liste des "ignorés" (onglet Permissions supplémentaires). Celui qui correspond consulte normalement, mais l'accès n'est pas enregistré - pratique pour la supervision et pour les comptes d'intégration.

Joignez glpi_tickets_users (type = 2, technicien attribué) à la table de résumé du module via LEFT JOIN et filtrez v.id IS NULL. La requête de l'article liste exactement les tickets ouverts, attribués et jamais lus par le responsable.

Oui. C'est un module gratuit de NexTool, disponible pour GLPI 10 et 11, et il s'active directement depuis le catalogue, sans configuration supplémentaire obligatoire.

Besoin d'aide ?