Rastree Quién Visualizó Cada Ticket en GLPI con Ticket Tracker

En GLPI estándar no hay registro de lectura. El módulo gratuito Ticket Tracker registra cada visualización de ticket - conteo, primera y última lectura y un log de accesos por usuario - y hasta rinde las consultas SQL para hallar tickets que el responsable nunca abrió.

En GLPI estándar no existe registro de lectura: el historial del ticket guarda lo que cambió, nunca quién solo lo abrió y lo leyó. En el mantenimiento de parques GLPI de clientes, esto se convierte en el clásico punto muerto de "el técnico ni miró el ticket" contra "sí lo leí" - y sin un dato objetivo es la palabra de uno contra la del otro. El módulo gratuito Ticket Tracker cierra esa brecha registrando cada visualización de ticket. Esta guía muestra cómo almacena los datos, cómo configurarlo sin inflar contadores y tres consultas SQL que responden "quién leyó qué" al instante.

Por qué GLPI no sabe quién leyó un ticket

El historial nativo (glpi_logs) solo registra cambios: creación, cambio de estado, nuevo seguimiento, reasignación de técnico. Abrir el formulario y leerlo no modifica ningún campo, así que no genera fila alguna. En el núcleo de GLPI no hay un evento de "visualización". Ticket Tracker lo resuelve enganchando en el momento en que se renderiza el formulario del ticket (el hook postShowItem de Ticket): cada vez que una sesión autenticada muestra un ticket, el módulo registra la visualización. Sin acción manual, sin campo nuevo en el formulario.

Las dos capas de registro: resumen y log

El módulo escribe en dos tablas con propósitos distintos. La de resumen responde "cuántas veces y cuándo"; la de log responde "cada acceso, uno a uno":

-- Resumen por (ticket, usuario): una fila, actualizada en cada acceso.
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`)
);

-- Log detallado: una fila por acceso individual.
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 clave UNIQUE (tickets_id, users_id) es el corazón de la tabla de resumen: cada par ticket/usuario tiene exactamente una fila. La escritura usa INSERT ... ON DUPLICATE KEY UPDATE view_count = view_count + 1, un upsert atómico - dos accesos simultáneos del mismo usuario ni crean fila duplicada ni pierden conteo. La pestaña "Visualizaciones" en el ticket lee el resumen (tabla con todos los visualizadores, conteo, primera y última lectura) y ofrece una cascada expandible que extrae del log cada acceso individual, con fecha y hora.

Activación y checklist de configuración

El módulo es gratuito y se activa desde el catálogo NexTool. Una vez habilitado, la configuración está en Módulos > Ticket Tracker, pestaña Funcionalidades:

  1. Módulo activo - el mismo interruptor de la página de Módulos. Apagado, no se rastrea nada.
  2. Tracking activo (tracking_enabled) - activa el registro de visualizaciones. Puede quedar activo con la pestaña oculta si quieres recolectar sin exponer.
  3. Mostrar pestaña en el ticket (show_tab_on_ticket) - muestra u oculta la pestaña "Visualizaciones" en el formulario del ticket.
  4. Intervalo mínimo (s) (min_interval_seconds, por defecto 60) - ventana de debounce: los accesos del mismo usuario al mismo ticket dentro de ese intervalo cuentan como uno.
  5. Ignorados (pestaña Permisos adicionales) - usuarios, perfiles o grupos que visualizan sin ser rastreados. Todo en blanco = todos los accesos cuentan.

El error de campo que infla (o pone a cero) los contadores

El error común es poner a cero el intervalo mínimo pensando que "cuanto más granular, mejor". El hook se dispara en cada render del formulario - incluidas recargas, navegación hacia atrás y reaperturas de la pestaña. Con min_interval_seconds = 0, un técnico que deja el ticket abierto y pulsa actualizar tres veces se convierte en "tres lecturas", y view_count pierde su sentido de "cuántas veces volvió de verdad al asunto". El valor por defecto de 60 segundos existe justamente para colapsar la ráfaga de recargas en una sola lectura. Usa 0 solo en un diagnóstico puntual y vuelve al valor por defecto después.

El segundo error es más sutil y lo topamos en un cliente: hasta la versión 1.2.0 del módulo, el registro dependía del permiso de ver la pestaña de Visualizaciones - es decir, solo se contaban los perfiles administrativos. El solicitante y los observadores abrían el ticket y no se registraba nada, así que la base subnotificaba justo a quien más importa en una disputa de SLA. Desacoplamos el registro del permiso de ver la pestaña: hoy cualquier sesión autenticada que renderiza el ticket se contabiliza - solicitante, observador o técnico - sin importar el perfil. Si operas una versión anterior, actualiza antes de confiar en los números.

Matriz de decisión: intervalo e ignorados por escenario

El ajuste correcto depende de qué quieres demostrar. La matriz que usamos en el diseño:

Escenario de operaciónTrackingIntervalo mínimo (s)Quién poner en "ignorados"
Auditoría de lectura / SLA (por defecto)Activado60Nadie
Parque con auto-refresco o panel de paredActivado180 a 300Cuentas de integración / bots
Supervisión que no debe inflar el contadorActivado60Perfil de gestores / auditores
Diagnóstico puntual (contar cada acceso)Activado0 (temporal)Nadie

Tres consultas SQL que responden al instante

La pestaña resuelve el caso a caso; para una vista de parque, ve directo a la base de datos. Tickets abiertos asignados que el técnico responsable aún no ha abierto (type = 2 en glpi_tickets_users es el técnico asignado):

-- Tickets abiertos asignados que el técnico responsable NUNCA visualizó.
SELECT t.id AS ticket, t.name AS titulo, u.name AS tecnico, t.date AS abierto_en
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)   -- nuevo, asignado, planificado, pendiente
  AND v.id IS NULL               -- ninguna lectura registrada por el técnico
ORDER BY t.date ASC;

Latencia de lectura - cuántos minutos el ticket estuvo abierto hasta la primera lectura del técnico asignado. Es la métrica que antecede a la primera respuesta y suele explicar un SLA incumplido:

-- Minutos entre la apertura y la 1a lectura por el técnico asignado.
SELECT t.id AS ticket,
       TIMESTAMPDIFF(MINUTE, t.date, v.first_view) AS minutos_hasta_1a_lectura
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 minutos_hasta_1a_lectura DESC;

Los visualizadores más activos de un ticket concreto, desde el resumen, para saber quién de verdad lo sigue (cambia 12345 por el ID del ticket):

-- Quién abrió más el ticket 12345, del más recurrente al menos.
SELECT u.name AS usuario, 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;

Leer no es responder: qué demuestra el contador

El dato es potente, pero tiene un límite honesto: demuestra que el formulario se renderizó para ese usuario, no que la persona lo leyó con atención ni que actuó. Un view_count alto sin seguimiento es señal amarilla - alguien abre y cierra sin resolver. Un ticket con cero visualizaciones del responsable mientras el SLA corre es señal roja - nadie lo miró siquiera. En el mantenimiento, el valor real no es vigilar al técnico, es cerrar la brecha probatoria: cuando el cliente pregunta "¿por qué este ticket estuvo parado tres días?", la respuesta deja de ser opinión y pasa a tener sello de fecha y hora.

¿Necesitas visibilidad real sobre la atención en tu GLPI, con los módulos adecuados activados y ajustados a tu flujo? Conoce el servicio de mantenimiento de GLPI de NexTool.


Este contenido fue producido con ayuda de inteligencia artificial y revisado por el equipo de Nextool Solutions.

Preguntas Frecuentes

No. El historial (glpi_logs) solo registra cambios de campos - estado, seguimientos, reasignación de técnico. Abrir y leer no cambia nada, así que no existe registro nativo de visualización. Ticket Tracker cubre la brecha registrando cada render del formulario del ticket.

No en la versión actual. El log detallado guarda ticket, usuario y fecha/hora de cada acceso; la identificación es por el usuario autenticado de GLPI, no por IP. Para auditoría por persona, users_id es más fiable que la IP, que cambia con VPN, NAT y proxy.

No, si el intervalo mínimo está configurado. El valor por defecto de 60 segundos hace que los accesos del mismo usuario al mismo ticket dentro de la ventana cuenten como uno. Solo con intervalo 0 cada actualización se vuelve una lectura - usa 0 solo para diagnóstico y vuelve al valor por defecto.

Añade el usuario, el perfil o el grupo a la lista de "ignorados" (pestaña Permisos adicionales). Quien encaja visualiza con normalidad, pero el acceso no se registra - útil para supervisión y para cuentas de integración.

Cruza glpi_tickets_users (type = 2, técnico asignado) con la tabla de resumen del módulo por LEFT JOIN y filtra v.id IS NULL. La consulta del artículo lista exactamente los tickets abiertos, asignados y nunca leídos por el responsable.

Sí. Es un módulo gratuito de NexTool, disponible para GLPI 10 y 11, y se activa directo desde el catálogo, sin configuración adicional obligatoria.

?Necesitas ayuda?