LLM para triagem de log: útil sem virar gerador de alarme falso
Pedir para um modelo "analisar os logs e dizer o que está errado" produz texto convincente e inútil. O uso que funciona é mais modesto, mais barato e muito mais confiável.
Equipe EasyOps Cloud · · 7 min de leitura
A ideia é sedutora: jogar o log no modelo e perguntar o que está acontecendo. O resultado costuma ser um texto bem escrito, organizado em tópicos, com aparência de diagnóstico — e frequentemente errado.
O problema não é o modelo ser ruim. É a tarefa estar mal formulada. "Analise estes logs" pede uma conclusão sobre um sistema que o modelo não conhece, a partir de uma amostra que provavelmente não contém a causa. Ele então produz a resposta mais plausível, que é exatamente o que você não quer em diagnóstico.
Existe um conjunto de usos que funciona bem. Todos têm em comum uma coisa: o modelo transforma texto em vez de decidir o que está errado.
Por que o resumo genérico falha
Três razões estruturais, e vale entendê-las antes de montar qualquer fluxo.
A causa raramente está na amostra. O log tem gigabytes; você envia dois mil
tokens. A linha que explica o incidente costuma estar minutos antes do sintoma,
e não no trecho que você recortou por conter a palavra error.
O modelo não conhece o normal do seu sistema. Uma exceção que aparece cem vezes por dia há dois anos e não incomoda ninguém será apresentada como problema crítico. Sem linha de base, não há como distinguir sinal de rotina.
Plausível não é verdadeiro. Diante de sinais ambíguos, o modelo produz a explicação mais comum para aquele padrão — que pode não ser a sua. E o texto sai com o mesmo tom de confiança em ambos os casos, o que é pior do que uma resposta hesitante.
O efeito somado é caro: alarme falso corrói a confiança na ferramenta. Depois de três alertas errados, ninguém lê o quarto — inclusive o correto.
Filtre antes com ferramenta determinística
O princípio que faz tudo funcionar: o modelo não deve decidir o que é relevante. Ele deve receber o que já foi selecionado por regra e transformar em algo mais legível.
Fazer a seleção com as ferramentas de sempre é mais barato, mais rápido e não erra:
# Só o que é erro de verdade, na janela do incidente
journalctl -u meuapp --since '30 min ago' -p err --no-pager
# Agrupar por assinatura, que é o que revela padrão
journalctl -u meuapp --since '1 hour ago' -p err --no-pager \
| sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9:.]+Z?//; s/[0-9a-f]{8,}/ID/g; s/[0-9]+/N/g' \
| sort | uniq -c | sort -rn | head -20Aquele sed faz o trabalho pesado: remove data, identificador e número, deixando
a forma da mensagem. O resultado é uma contagem por tipo de erro, que já
responde à maior parte das perguntas sem modelo nenhum.
É a partir daí — vinte linhas agrupadas e contadas — que o modelo tem o que fazer.
Os quatro usos que funcionam
Explicar mensagem obscura. Erro de biblioteca, código de kernel, exceção de driver. O modelo traduz para linguagem comum e sugere onde olhar. Aqui ele está recuperando conhecimento geral, que é exatamente onde é forte.
Agrupar por semelhança semântica. Cinco mensagens com texto diferente
descrevendo a mesma falha. O uniq não junta, o modelo junta. Útil quando a
aplicação gera erros com formatação inconsistente.
Escrever o resumo do incidente. Depois de resolvido, transformar a sequência de eventos em narrativa cronológica para o registro. O modelo é bom em texto, e essa é uma tarefa de texto — feita a partir de fatos que você já apurou.
Sugerir o comando seguinte. Dado um erro, propor o que investigar. Aqui vale a regra de ouro: ele sugere, você executa. Nunca o contrário.
Repare no padrão: em nenhum deles o modelo decide se há um problema. Ele reformula informação que já passou por um filtro confiável.
O prompt que reduz invenção
Três instruções mudam muito a qualidade da resposta:
- Dar o contexto do sistema. Que aplicação é, qual pilha, o que é esperado. Sem isso ele adivinha a arquitetura.
- Exigir citação da linha. "Para cada afirmação, cite a linha do log que a sustenta." Reduz drasticamente conclusão sem base, porque força o modelo a apontar evidência.
- Autorizar a incerteza. "Se o log não permitir concluir, diga que não permite e liste o que seria necessário." Sem essa permissão explícita, o modelo sempre responde alguma coisa.
Um esqueleto que funciona:
Contexto: API Node.js com Postgres, atrás de nginx, em VPS Linux.
Comportamento normal: ~50 req/s, latência p95 de 120 ms.
Abaixo, erros da última hora agrupados por assinatura, com contagem.
Para cada grupo: o que a mensagem significa, e qual comando eu
deveria rodar para confirmar a hipótese.
Cite a linha que sustenta cada afirmação.
Se não for possível concluir, diga isso explicitamente.
<dados>Note que ele pede comando para confirmar, não conclusão. É a diferença entre uma ferramenta que acelera investigação e uma que substitui investigação — e só a primeira é confiável.
Para detectar anomalia, estatística ganha do modelo
Existe uma tentação natural: se o modelo entende texto, que ele descubra o que está fora do normal. Na prática, a contagem simples resolve melhor, mais barato e sem inventar.
O que caracteriza anomalia em log é quase sempre quantitativo — uma assinatura de erro que não existia ontem, ou uma que existia e multiplicou. Isso é comparação de duas listas:
#!/usr/bin/env bash
# Assinaturas de erro que apareceram hoje e não existiam ontem
assinaturas() {
journalctl -u meuapp --since "$1" --until "$2" -p err --no-pager \
| sed -E 's/^.{0,32}//; s/[0-9a-f]{8,}/ID/g; s/[0-9]+/N/g' \
| sort -u
}
comm -13 \
<(assinaturas '2 days ago' '1 day ago') \
<(assinaturas '1 day ago' 'now')O que sai daí é uma lista curta de erros genuinamente novos — e essa lista, sim, vale mandar para o modelo explicar. A ordem importa: estatística encontra, modelo explica. Invertida, você paga para o modelo ler milhares de linhas e recebe uma opinião sobre a amostra que coube.
O mesmo raciocínio vale para volume. Um alerta disparado quando a contagem de erros por minuto ultrapassa três desvios da média da semana é mais confiável, mais rápido e infinitamente mais barato que qualquer análise semântica — e não tem como alucinar.
Custo e privacidade
Log é volumoso e contém dado sensível com frequência maior do que se imagina: token em URL, e-mail de usuário, endereço IP, corpo de requisição registrado em modo de depuração.
Duas consequências práticas:
- Nunca envie log bruto para API externa. Filtre e anonimize antes. O agrupamento
por assinatura mostrado acima já ajuda muito, porque o
sedremove identificadores. - O volume é o custo. Enviar log inteiro é caro e piora o resultado. Vinte linhas agrupadas custam centavos e funcionam melhor que dez mil linhas cruas.
Se o log contiver dado que não pode sair, esta é uma das tarefas em que um modelo pequeno local resolve bem — a exigência de qualidade é modesta, e a decisão entre API e modelo próprio pende para o lado de dentro quando o dado é o critério. Vale ler junto o que realmente expõe dado em integrações com IA: log é justamente o vetor mais subestimado.
O que continua sendo trabalho de gente
Vale ser direto sobre o limite, porque é onde as expectativas costumam quebrar.
O modelo não sabe que o pico de erro coincidiu com o deploy das 14h. Não sabe que aquele serviço depende de uma integração que cai toda terça. Não sabe que o cliente que reclamou usa a funcionalidade de um jeito específico. Esse conhecimento é do time, e é ele que resolve incidente.
O que a ferramenta entrega é tempo: menos minutos lendo texto repetitivo, tradução rápida de mensagem obscura, e o rascunho do registro pós-incidente pronto para revisão.
E há um pré-requisito que nenhuma IA substitui: log que preste. Antes de investir nesse fluxo, vale garantir que a aplicação registra com nível adequado, com identificador de requisição para correlacionar, em formato consistente e com retenção suficiente. Modelo nenhum extrai informação de log que não foi escrito — e um journald bem configurado com retenção definida vale mais, na prática, que qualquer camada de IA por cima.
O teste que resolve a dúvida sobre por onde começar é simples: pegue o último incidente e pergunte se, relendo o log com calma, seria possível reconstruir o que aconteceu. Se a resposta for não, o problema está na instrumentação, e nenhuma camada de análise vai contorná-lo. Se for sim mas tenha levado horas, aí sim existe tempo real a ser economizado — e é exatamente esse o espaço em que essa ferramenta entrega valor.