Pular para o conteúdo

Reduzir o custo de logs sem perder diagnóstico

Intermediário14 min de leituraobservabilidade

Log costuma ser a maior fatia da conta de observabilidade e a mais fácil de cortar errado. O objetivo aqui não é “logar menos”: é parar de pagar pelo que ninguém consulta, mantendo intacto o que você usa em incidente e o que a auditoria exige.

Corte sem medição vira aposta. Comece pelo ranking.

# Loki: quem produz mais linhas na última hora
topk(10, sum by (app) (rate({namespace="loja"}[1h])))
# e dentro do maior, quais mensagens se repetem
topk(10, sum by (msg) (rate({app="pedidos"} | json [1h])))
Janela do terminal
# CloudWatch: grupos por volume de ingestão
aws logs describe-log-groups \
--query 'reverse(sort_by(logGroups,&storedBytes))[:10].[logGroupName,storedBytes,retentionInDays]' \
--output table

Em quase todo ambiente, o topo da lista é o mesmo: log de acesso com sucesso, health check, debug esquecido ligado, e stack trace repetido de uma exceção esperada.

Log estruturado é pré-requisito para amostrar e filtrar com precisão — sem campos, você só consegue cortar por serviço, o que é grosseiro demais.

{"ts":"2026-09-04T09:12:44Z","level":"info","service":"pedidos","event":"request",
"route":"/pedidos","status":200,"duracao_ms":42,"trace_id":"4bf92f35..."}

Com isso no lugar, as decisões seguintes podem ser cirúrgicas: amostre event=request com status<400 e mantenha todo o resto.

Antes de amostrar, elimine. Isso não perde diagnóstico:

  • Health check e probe (o maior volume inútil da maioria dos serviços).
  • Log de debug em produção — ligue por serviço, temporariamente, quando precisar.
  • Mensagens de framework repetidas a cada requisição.
  • Stack trace completo de exceção esperada e tratada.
# no Collector ou no agente, descarte antes de pagar pela ingestão
processors:
filter/ruido:
logs:
exclude:
match_type: regexp
record_attributes:
- { key: http.route, value: "^/(healthz|readyz|metrics)$" }

Log de sucesso é repetitivo por natureza: uma amostra representa bem o conjunto. Erro, nunca se amostra.

# amostragem na origem: 1 em cada 10 requisições bem-sucedidas
if status >= 400 or random.random() < 0.1:
logger.info("request", extra={"route": route, "status": status,
"amostrado": status < 400})

Duas boas práticas: marque a linha como amostrada (para não interpretar contagens erradas depois) e amostre por trace, não por linha — se você guardar metade dos logs de uma requisição, a investigação fica pior que se guardasse nenhum.

E lembre da regra que economiza mais que tudo: o que você quer contar é métrica, não log. Um counter de erros por rota custa quase nada; contar linhas em cada consulta de painel custa caro para sempre.

Nem todo log vale o mesmo tempo de armazenamento.

Classe Exemplo Retenção quente Depois
Diagnóstico request, debug de aplicação 7–14 dias descarta
Operacional deploy, alerta, mudança de estado 30–90 dias arquivo frio
Auditoria acesso a dado, mudança de permissão conforme a exigência arquivo imutável
Financeiro/fiscal conforme a lei conforme a lei arquivo imutável
Janela do terminal
# CloudWatch: grupos sem retenção definida guardam para sempre — corrija todos
aws logs describe-log-groups --query 'logGroups[?!retentionInDays].logGroupName' --output text \
| tr '\t' '\n' | while read g; do
aws logs put-retention-policy --log-group-name "$g" --retention-in-days 14
done

Para o que precisa durar, exporte para armazenamento de objetos com classe fria e, quando for auditoria, com imutabilidade — é muito mais barato que manter no índice quente.

Antes de aplicar qualquer corte, valide com quem responde por conformidade quais registros têm prazo obrigatório: acesso a dado pessoal, trilha de mudanças em produção, logs financeiros. Reduzir retenção desses é economia que vira problema jurídico.

Aproveite a passagem para conferir o inverso: log que não deveria conter dado pessoal e contém. Veja compliance e LGPD.

sum(rate({namespace="loja"}[5m])) # linhas por segundo, antes e depois

Acompanhe também o que importa de verdade: nos próximos incidentes, faltou alguma informação? Se faltou, você cortou fundo demais em algum ponto — ajuste aquele ponto, não reverta tudo.

Sintoma Causa provável
Custo não caiu O corte foi em serviço pequeno; volte ao ranking
Faltou log no incidente Amostragem pegou erro junto, ou retenção curta demais
Contagens erradas nos painéis Amostra sem marcação e sem fator de correção
Loki lento e caro Cardinalidade de labels, não volume — label não é campo
Auditoria reclamou Retenção reduzida em classe com exigência legal
  • Ranking de volume por serviço e por mensagem.
  • Logs estruturados em JSON com campos estáveis.
  • Health check e debug fora de produção.
  • Amostragem só em log de sucesso, por trace, marcada.
  • Retenção definida por classe, sem grupo “para sempre” por descuido.
  • Exigências de auditoria e LGPD confirmadas antes do corte.
  • Volume e custo medidos antes e depois.