KPIs e indicadores para el Service Desk en GLPI

Qué KPIs de Service Desk valen realmente en GLPI, de qué tabla y columna sale cada número, rangos de referencia honestos y las trampas que ya han distorsionado decisiones en los entornos que mantenemos.

Un buen indicador es aquel cuyo origen puedes señalar en la base de datos. Esta guía muestra qué KPIs de Service Desk vale realmente la pena seguir en GLPI, de qué tabla y columna sale cada número, qué rangos usamos como referencia y las trampas que ya han distorsionado decisiones en los entornos que mantenemos para clientes.

Antes del KPI, el modelo de datos

El error que más vemos al hacernos cargo de un GLPI existente es medir "por encima": comparar fechas crudas en lugar de usar los campos que GLPI ya calcula. Cada ticket en la tabla glpi_tickets lleva columnas estadísticas listas, las mismas que consume el módulo de Estadísticas:

  • takeintoaccount_delay_stat - segundos hasta la primera toma de conocimiento (base del tiempo de respuesta / TTO).
  • solve_delay_stat - segundos hasta la solución, ya descontando el tiempo en "Pendiente" y ajustado por el calendario laboral de la entidad (base del TMR / TTR).
  • waiting_duration - total de segundos que el ticket estuvo en espera.
  • time_to_resolve y time_to_own - los plazos (deadlines) del SLA de resolución y de atención.
  • status - el estado del ticket, que define qué entra o no en el backlog.

Esto lo cambia todo: el TMR calculado como solvedate - date es distinto (y siempre mayor) de lo que devuelve solve_delay_stat, porque la resta cruda suma madrugadas, fines de semana y pausas. Elegir la columna correcta ya es la mitad del trabajo.

Los KPIs que importan y dónde vive cada uno

No se trata de tener diez indicadores en el panel; se trata de tener los que generan acción. La matriz de abajo enlaza cada KPI con su fuente técnica en GLPI y con un rango de referencia honesto. Un rango, no una meta universal: el número justo depende del contrato y del tipo de operación.

KPIFuente en GLPIRango de referencia
Volumen de ticketsCOUNT(*) en glpi_tickets (filtro por date)dimensiona el equipo; sin meta fija
Tiempo de respuesta (TTO)takeintoaccount_delay_statcuanto menor, mejor; sigue el SLA
Tiempo medio de resolución (TMR)solve_delay_statcomparar con el propio histórico
Cumplimiento de SLA (TTR)solvedate <= time_to_resolvepor encima de 90-95%
Tasa de reaperturaglpi_logs (estado 5 a 1/2/3)por debajo de 5%
Satisfacción (CSAT)glpi_ticketsatisfactions.satisfactionpor encima de 4,0/5,0
Backlogstatus NOT IN (5,6)estable o decreciente
Edad media del backlogAVG(DATEDIFF(NOW(), date)) en los abiertosbaja; alta = tickets olvidados
Resolución en N1grupo asignado, sin escalado70-80%

Extrayendo los números directo de la base

El módulo de Estadísticas (en Asistencia) responde bien para consulta puntual y para explorar por categoría, grupo, técnico y SLA. Pero no versiona el histórico mes a mes ni cruza varios indicadores en una sola fila comparable. Cuando necesitamos la foto consolidada que entra en el informe mensual de los clientes, vamos a la base con un usuario de solo lectura:

-- KPIs del mes en curso en una sola fila (usar un usuario de solo lectura)
-- Origen: glpi_tickets, los mismos campos que consume el módulo Estadísticas
SELECT
    COUNT(*)                                                AS volume,
    SUM(status NOT IN (5,6))                                AS backlog,
    ROUND(AVG(NULLIF(takeintoaccount_delay_stat,0))/60, 1) AS tto_min,
    ROUND(AVG(NULLIF(solve_delay_stat,0))/3600, 1)         AS tmr_horas,
    ROUND(
      100 * SUM(solvedate IS NOT NULL AND solvedate <= time_to_resolve)
          / NULLIF(SUM(time_to_resolve IS NOT NULL AND solvedate IS NOT NULL), 0)
    , 1)                                                    AS sla_ttr_pct
FROM glpi_tickets
WHERE is_deleted = 0
  AND date >= DATE_FORMAT(CURDATE(), '%Y-%m-01');

La reapertura no tiene columna propia: vive en el histórico de cambios de estado. En glpi_logs, una reapertura es el ticket que salió de Resuelto (estado 5) y volvió a atención. El log guarda el valor como "5 Resuelto", así que filtramos por el prefijo numérico para no depender del idioma de la instalación:

-- Reaperturas del mes: tickets que salieron de Resuelto (5) y volvieron
-- a atención. En glpi_logs, id_search_option 12 = el campo estado
SELECT COUNT(DISTINCT items_id) AS reabertos
FROM glpi_logs
WHERE itemtype = 'Ticket'
  AND id_search_option = 12
  AND old_value LIKE '5 %'
  AND new_value REGEXP '^[123] '
  AND date_mod >= DATE_FORMAT(CURDATE(), '%Y-%m-01');

Automatizando la recolección mensual

Ejecutar la consulta a mano cada día 1 no escala. Programamos la extracción con el propio cron del sistema, apuntando a un archivo de credenciales .cnf (chmod 600) para no dejar nunca la contraseña en la línea de comandos, y guardamos el CSV fuera de GLPI. Así nace la serie temporal que el panel nativo no guarda:

# /etc/cron.d/glpi-kpi  ->  día 1 a las 06:00, como www-data
# Credenciales en el archivo .cnf (chmod 600), nunca en la línea de comandos
0 6 1 * * www-data /usr/bin/mysql --defaults-file=/etc/glpi/kpi-ro.cnf glpi \
  < /opt/glpi-kpi/kpi_mensal.sql >> /var/log/glpi-kpi/kpi-$(date +\%Y-\%m).csv 2>&1

Metas: rangos honestos, no números mágicos

  • Cumplimiento de SLA (TTR): por encima de 90-95% es saludable para la mayoría de contratos. Un 100% constante suele indicar un SLA demasiado holgado, no excelencia.
  • Reaperturas: por debajo de 5%. Por encima, investiga solución incompleta o cierre apresurado para "cumplir" el plazo.
  • Resolución en N1: 70-80%. Por debajo de 60% apunta a falta de capacitación o mala categorización; muy por encima de 90%, sospecha de tickets complejos mal clasificados.
  • Satisfacción (CSAT): por encima de 4,0/5,0, pero siempre leída junto con la tasa de respuesta de la encuesta.

Trampas que ya han provocado guardias

En el mantenimiento de entornos de clientes, lo primero que hacemos al asumir un GLPI que ya funcionaba es no confiar en el panel nativo hasta validar la base. En un cliente con alto volumen mensual de tickets, el TMR "oficial" parecía óptimo hasta que notamos que buena parte de los tickets tenía al mismo usuario como autor y técnico ya en la apertura: una autoasignación que pone a cero takeintoaccount_delay_stat y enmascara el tiempo real de respuesta. Estandarizamos la extracción vía SQL programado precisamente porque el módulo de Estadísticas no guarda histórico mes a mes; sin serie temporal, comparas con la memoria, no con el dato.

Las trampas de campo que más distorsionan la lectura:

  • Medir el TMR por diferencia de fechas. solvedate - date infla el número: entran madrugadas, fines de semana y tiempo en "Pendiente". Usa solve_delay_stat, que GLPI ya ajusta por el calendario.
  • Confundir Resuelto con Cerrado. Si hay cierre automático tras X días, medir solo status = 6 oculta los resueltos a la espera de confirmación. El backlog debe excluir 5 y 6.
  • Celebrar un TTO bajo por autoasignación. Un ticket abierto ya asignado pone a cero el tiempo de respuesta; el número baja sin que la operación haya mejorado en nada.
  • Leer la satisfacción sin la tasa de respuesta. Cuando solo responde quien quedó insatisfecho, la media engaña. Cruza satisfaction con cuántas encuestas se respondieron realmente.

Si tu GLPI muestra números en los que nadie confía, el problema rara vez es GLPI: es la base y la forma de extraer. El mantenimiento de GLPI de NexTool incluye el modelado de estos indicadores y el informe mensual consolidado que la dirección lee sin una hoja de cálculo.


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

Preguntas Frecuentes

solve_delay_stat es el tiempo de resolución que GLPI calcula descontando el tiempo en Pendiente y ajustando por el calendario laboral de la entidad. Restar las fechas crudas suma madrugadas, fines de semana y pausas, inflando el TMR. Para informes de gestión usa siempre solve_delay_stat, la misma base que usa el módulo de Estadísticas.

Un ticket cumplió el TTR cuando la fecha de solución (solvedate) es menor o igual al plazo (time_to_resolve). El porcentaje es el total de tickets resueltos dentro del plazo dividido por los que tenían SLA de resolución definido, es decir, time_to_resolve no nulo. Los tickets sin SLA asociado no deben entrar en el denominador.

En la tabla glpi_ticketsatisfactions, columna satisfaction, en escala de 0 a 5. El CSAT es la media de esas notas en el período. La encuesta solo se genera si la satisfacción está habilitada en la configuración de la entidad, y la media debe leerse junto con la tasa de respuesta, ya que las medias bajas suelen tener sesgo de quien solo responde cuando queda insatisfecho.

Porque takeintoaccount_delay_stat queda en cero cuando el autor del ticket ya es el técnico asignado en la apertura (autoasignación). La toma de conocimiento es instantánea, pero eso no refleja agilidad real de triaje. Es la trampa más común: un TTO bajo que en realidad proviene de tickets abiertos ya dirigidos.

Sirve para consulta puntual y para explorar por categoría, grupo, técnico y SLA. La limitación es que no versiona el histórico mes a mes ni consolida varios indicadores en una fila comparable. Para un informe recurrente, extrae vía SQL programado con un usuario de solo lectura y guarda el resultado fuera de GLPI.

?Necesitas ayuda?