Rastreie Quem Visualizou Cada Ticket no GLPI com Ticket Tracker

No GLPI padrão não há registo de leitura. O módulo gratuito Ticket Tracker grava cada visualização de ticket - contagem, primeira e última leitura e um log de cada acesso por utilizador - e ainda rende as consultas SQL para encontrar pedidos que o responsável nunca abriu.

No GLPI padrão não existe registo de leitura: o histórico do pedido guarda o que mudou, nunca quem apenas o abriu e leu. Na manutenção de parques GLPI de clientes, isto torna-se o clássico impasse do "o técnico nem olhou para o pedido" contra "eu li, sim" - e sem um dado objetivo é a palavra de um contra a do outro. O módulo gratuito Ticket Tracker fecha essa lacuna registando cada visualização de ticket. Este guia mostra como grava os dados, como o configurar sem inflacionar contadores e três consultas SQL que respondem "quem leu o quê" na hora.

Porque é que o GLPI não sabe quem leu um pedido

O histórico nativo (glpi_logs) só regista alterações: criação, mudança de estado, novo seguimento, troca de técnico. Abrir o formulário e ler não muda nenhum campo, portanto não gera qualquer linha. Não existe, no núcleo do GLPI, um evento de "visualização". O Ticket Tracker resolve isto ligando-se ao momento em que o formulário do ticket é renderizado (o hook postShowItem do Ticket): sempre que uma sessão autenticada exibe um pedido, o módulo grava a visualização. Sem ação manual, sem campo novo no formulário.

As duas camadas de registo: resumo e log

O módulo grava em duas tabelas com propósitos distintos. A de resumo responde "quantas vezes e quando"; a de log responde "cada acesso, um a um":

-- Resumo por (ticket, utilizador): uma linha, atualizada a cada acesso.
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 detalhado: uma linha por acesso 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`)
);

A chave UNIQUE (tickets_id, users_id) é o coração da tabela de resumo: cada par ticket/utilizador tem exatamente uma linha. A gravação usa INSERT ... ON DUPLICATE KEY UPDATE view_count = view_count + 1, um upsert atómico - dois acessos simultâneos do mesmo utilizador não criam linha duplicada nem perdem contagem. O separador "Visualizações" no ticket lê o resumo (tabela com todos os visualizadores, contagem, primeira e última leitura) e oferece uma cascata expansível que puxa do log cada acesso individual, com data e hora.

Ativação e checklist de configuração

O módulo é gratuito e liga-se no catálogo NexTool. Depois de ativado, a configuração fica em Módulos > Ticket Tracker, separador Funcionalidades:

  1. Módulo ativo - o mesmo interruptor da página de Módulos. Desligado, nada é rastreado.
  2. Rastreamento ativo (tracking_enabled) - liga a gravação das visualizações. Pode ficar ligado com o separador escondido, se quiser recolher sem expor.
  3. Mostrar separador no ticket (show_tab_on_ticket) - mostra ou oculta o separador "Visualizações" no formulário do pedido.
  4. Intervalo mínimo (s) (min_interval_seconds, predefinição 60) - uma janela de debounce: acessos do mesmo utilizador ao mesmo ticket dentro desse intervalo contam como um só.
  5. Ignorados (separador Permissões adicionais) - utilizadores, perfis ou grupos que visualizam sem serem rastreados. Tudo em branco = todos os acessos contam.

O erro de campo que inflaciona (ou zera) os contadores

O erro comum é pôr o intervalo mínimo a zero achando que "quanto mais granular, melhor". O hook dispara a cada render do formulário - incluindo recarregamentos, navegação para trás e reaberturas do separador. Com min_interval_seconds = 0, um técnico que deixa o pedido aberto e faz três atualizações passa a "três leituras", e o view_count perde o sentido de "quantas vezes voltou de facto ao assunto". A predefinição de 60 segundos existe precisamente para colapsar a rajada de recarregamentos numa única leitura. Use 0 apenas em diagnóstico pontual e volte à predefinição depois.

O segundo erro é mais subtil e demos com ele num cliente: até à versão 1.2.0 do módulo, a gravação dependia da permissão de ver o separador de Visualizações - ou seja, só os perfis administrativos eram contados. O requerente e os observadores abriam o pedido e nada era registado, portanto a base subnotificava exatamente quem mais importa numa disputa de SLA. Desacoplámos o registo da permissão de ver o separador: hoje qualquer sessão autenticada que renderiza o ticket é contabilizada - requerente, observador ou técnico - independentemente do perfil. Se opera uma versão anterior, atualize antes de confiar nos números.

Matriz de decisão: intervalo e ignorados por cenário

O ajuste certo depende do que quer provar. A matriz que usamos no desenho:

Cenário de operaçãoRastreamentoIntervalo mínimo (s)Quem colocar em "ignorados"
Auditoria de leitura / SLA (predefinição)Ligado60Ninguém
Parque com atualização automática ou painel de paredeLigado180 a 300Contas de integração / robôs
Supervisão que não deve inflacionar o contadorLigado60Perfil de gestores / auditores
Diagnóstico pontual (contar cada acesso)Ligado0 (temporário)Ninguém

Três consultas SQL que respondem na hora

O separador resolve o caso a caso; para uma visão de parque, vá direto à base de dados. Pedidos abertos atribuídos que o técnico responsável ainda não abriu (type = 2 em glpi_tickets_users é o técnico atribuído):

-- Pedidos abertos atribuídos que o técnico responsável NUNCA visualizou.
SELECT t.id AS pedido, t.name AS titulo, u.name AS tecnico, t.date AS aberto_em
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)   -- novo, atribuído, planeado, pendente
  AND v.id IS NULL               -- nenhuma leitura registada pelo técnico
ORDER BY t.date ASC;

Latência de leitura - quantos minutos o pedido esteve aberto até à primeira leitura do técnico atribuído. É a métrica que antecede a primeira resposta e costuma explicar um SLA ultrapassado:

-- Minutos entre a abertura e a 1a leitura pelo técnico atribuído.
SELECT t.id AS pedido,
       TIMESTAMPDIFF(MINUTE, t.date, v.first_view) AS minutos_ate_1a_leitura
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_ate_1a_leitura DESC;

Os visualizadores mais ativos de um pedido específico, a partir do resumo, para saber quem realmente o acompanha (troque 12345 pelo ID do ticket):

-- Quem mais abriu o pedido 12345, do mais recorrente ao menos.
SELECT u.name AS utilizador, 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;

Ler não é responder: o que o contador prova

O dado é poderoso, mas tem um limite honesto: prova que o formulário foi renderizado para aquele utilizador, não que a pessoa o leu com atenção nem que agiu. Um view_count alto sem seguimento é sinal amarelo - alguém está a abrir e fechar sem resolver. Um pedido com zero visualizações do responsável enquanto o SLA corre é sinal vermelho - ninguém sequer olhou. Na manutenção, o valor real não é vigiar o técnico, é fechar a lacuna probatória: quando o cliente pergunta "porque é que este pedido ficou parado três dias?", a resposta deixa de ser opinião e passa a ter carimbo de data e hora.

Precisa de visibilidade real sobre o atendimento no seu GLPI, com os módulos certos ativados e ajustados ao seu fluxo? Conheça o serviço de manutenção de GLPI da NexTool.


Este conteúdo foi produzido com o auxílio de inteligência artificial e revisto pela equipa da Nextool Solutions.

Perguntas Frequentes

Não. O histórico (glpi_logs) só grava alterações de campos - estado, seguimentos, troca de técnico. Abrir e ler não muda nada, portanto não existe registo nativo de visualização. O Ticket Tracker preenche a lacuna gravando cada render do formulário do ticket.

Não na versão atual. O log detalhado guarda ticket, utilizador e data/hora de cada acesso; a identificação é pelo utilizador autenticado do GLPI, não pelo IP. Para auditoria por pessoa, o users_id é mais fiável do que o IP, que muda com VPN, NAT e proxy.

Não, se o intervalo mínimo estiver configurado. A predefinição de 60 segundos faz com que acessos do mesmo utilizador ao mesmo ticket dentro da janela contem como um. Só com intervalo 0 é que cada atualização se torna uma leitura - use 0 apenas para diagnóstico e volte à predefinição.

Coloque o utilizador, o perfil ou o grupo na lista de "ignorados" (separador Permissões adicionais). Quem se enquadra visualiza normalmente, mas o acesso não é registado - útil para supervisão e para contas de integração.

Cruze glpi_tickets_users (type = 2, técnico atribuído) com a tabela de resumo do módulo por LEFT JOIN e filtre v.id IS NULL. A consulta do artigo lista exatamente os pedidos abertos, atribuídos e nunca lidos pelo responsável.

Sim. É um módulo gratuito do NexTool, disponível para GLPI 10 e 11, e ativa-se diretamente pelo catálogo, sem configuração adicional obrigatória.

Precisa de ajuda?