Programação Por Equipe DevBras

Capa do artigo: Antes de escolher Elastic ou Loki, decida o que o seu sistema vai registrar

Antes de escolher Elastic ou Loki, decida o que o seu sistema vai registrar

Monte um plano de log com eventos, campos obrigatórios, id de requisição e lista do que nunca entra, implemente com pino no Node.js e só então escolha a ferramenta pela pergunta que ela precisa responder.

Um cliente liga às 10h dizendo que o pagamento do pedido 8812 foi recusado ontem à noite, mas o valor apareceu na fatura. A equipe abre a ferramenta de log nova, que custou duas semanas de migração, e digita "8812". Volta nada: o log de pagamento registrava só "erro ao processar" e uma stack trace. Em compensação, a busca por "senha" retorna milhares de linhas, porque o middleware antigo registrava o corpo de toda requisição de login.

A resposta curta: Elastic, Loki, Graylog e as outras guardam e indexam o que você manda. Se você manda texto solto, sem id, com senha no meio, a ferramenta indexa texto solto, sem id, com senha no meio. Decida primeiro quais eventos importam, quais campos todo evento carrega (principalmente o id da requisição), o que nunca entra e por quanto tempo fica. Implemente isso em log estruturado. Só então escolha a ferramenta, pela pergunta que ela precisa responder em menos de um minuto.

Por que trocar de ferramenta não resolve

Listas de "melhores ferramentas de log" comparam ingestão, busca, painéis e preço. Tudo isso importa depois que existe algo útil para ingerir. O valor de um log está em responder perguntas concretas: o que aconteceu com este pedido, por que este login falhou, quanto tempo esta rota está levando. Essas perguntas dependem de campos que o código precisa escrever: id do pedido, id da requisição, resultado, motivo. Nenhuma ferramenta inventa o campo que a aplicação não registrou.

E o que entra no log vai para um lugar acessível a muito mais gente do que o banco de produção, com retenção às vezes indefinida. Senha, token, CPF e número de cartão no log são vazamento em câmera lenta, como explica log útil não carrega senha, token nem documento. Migrar esse conteúdo para uma ferramenta melhor só torna o vazamento mais fácil de pesquisar.

O plano de log em uma página

Antes de qualquer código, escreva um documento curto no repositório com quatro partes.

Campos que todo evento carrega

  • time em ISO 8601 com fuso, level, app e env.
  • request_id, que atravessa a requisição inteira e, de preferência, filas e serviços chamados; o padrão está em um identificador por request.
  • evento, um nome estável em formato dominio.acao, como pagamento.recusado.
  • Ids de negócio quando existirem: pedido_id, usuario_id (o id interno, não e-mail nem CPF).

Eventos que importam

Na loja do exemplo: pedido.criado, pagamento.aprovado, pagamento.recusado (com o motivo devolvido pelo provedor), pagamento.notificacao_recebida, login.falhou (sem a senha, com o motivo genérico), http.resposta (método, rota, status, duração) e erros não tratados com stack trace. É pouco, e é isso que resolve o chamado das 10h.

O que nunca entra

Senha, token, cookie, cabeçalho Authorization, número de cartão, CPF completo, corpo inteiro de requisição ou resposta. A regra é escrita como lista de bloqueio no código e revisada em code review.

Retenção e acesso

Quanto tempo cada nível fica (por exemplo, 14 dias para info e 90 para error, se isso fizer sentido para você) e quem pode consultar. Retenção tem custo de armazenamento e, quando há dado pessoal, custo de conformidade.

Como implementar com log estruturado

  1. Use uma biblioteca de log estruturado, que escreve JSON por linha. No Node.js, o pino é uma escolha comum e rápida.
  2. Configure a redação de campos sensíveis na própria biblioteca, para que um descuido no código não vaze dado.
  3. Crie o id da requisição num middleware e use um logger filho que já carrega esse id.
  4. Registre eventos de negócio com nome e campos, não frases montadas por concatenação.
  5. Escreva para a saída padrão e deixe o coletor (do container, do sistema ou do agente da ferramenta) levar ao destino.
  6. Teste a pergunta real: encontre um pedido de ontem pelo id em menos de um minuto.
// log.js
import pino from 'pino';

export const log = pino({
  level: process.env.LOG_LEVEL || 'info',
  base: { app: 'loja', env: process.env.NODE_ENV },
  timestamp: pino.stdTimeFunctions.isoTime,
  redact: {
    paths: [
      'req.headers.authorization',
      'req.headers.cookie',
      '*.senha',
      '*.token',
      '*.cpf',
      '*.cartao'
    ],
    censor: '[removido]'
  }
});

// app.js
import express from 'express';
import { randomUUID } from 'node:crypto';
import { log } from './log.js';

const app = express();

app.use((req, res, next) => {
  req.id = randomUUID();
  res.set('x-request-id', req.id);
  req.log = log.child({ request_id: req.id });

  const inicio = process.hrtime.bigint();
  res.on('finish', () => {
    req.log.info({
      evento: 'http.resposta',
      metodo: req.method,
      rota: req.route?.path,
      status: res.statusCode,
      duracao_ms: Number(process.hrtime.bigint() - inicio) / 1e6
    }, 'requisição concluída');
  });
  next();
});

// dentro do fluxo de pagamento
function registrarRecusa(req, pedido, resultado) {
  req.log.warn({
    evento: 'pagamento.recusado',
    pedido_id: pedido.id,
    usuario_id: pedido.usuarioId,
    motivo: resultado.status_detail
  }, 'pagamento recusado');
}

A linha que sai no terminal é JSON, uma por evento:

{"level":40,"time":"2026-10-16T23:41:07.512Z","app":"loja","env":"production","request_id":"3f1c9a2e-7b44-4d0e-9a61-2c8e5f0b7d13","evento":"pagamento.recusado","pedido_id":8812,"usuario_id":5531,"motivo":"cc_rejected_insufficient_amount","msg":"pagamento recusado"}

O middleware gera sempre um id novo. Se a sua aplicação fica atrás de um proxy ou gateway que já cria um id de requisição, aproveite o dele em vez de gerar outro, mas só quando o valor vier desse proxy confiável. Aceitar o cabeçalho de qualquer cliente permite que alguém injete ids falsos e polua a investigação.

Agora sim: escolhendo a ferramenta

Com eventos estruturados, a escolha fica objetiva. Faça a pergunta "o que aconteceu com o pedido 8812 ontem?" em cada candidata. No Loki, com rótulos de app e um filtro JSON, a consulta é algo como {app="loja"} | json | pedido_id="8812"; no Elastic ou no OpenSearch, uma busca pelo campo pedido_id. Avalie quanto custa guardar o volume que você realmente gera, quem na equipe sabe operar e consultar, e se a retenção configurável atende ao plano. Uma ferramenta que todos sabem usar, com um painel que responde às três perguntas mais frequentes, vale mais que três ferramentas que ninguém abre.

Erros comuns

  • Migrar de ferramenta sem mudar o que se registra. A fatura muda, o tempo de investigação não.
  • Logar o corpo inteiro das requisições "para debugar depois". Senhas, tokens e documentos vão parar num sistema com retenção longa e acesso amplo.
  • Mensagens montadas por concatenação. "Erro no pedido " + id não é pesquisável por campo e cada desenvolvedor escreve de um jeito.
  • Nenhum id de requisição. Num servidor com tráfego simultâneo, as linhas de requisições diferentes se misturam e não há como reconstruir o caminho de um pedido.
  • Retenção infinita por padrão. O custo cresce todo mês, e dados pessoais ficam guardados muito além da necessidade.
  • Nível debug ligado em produção. O volume explode, a busca fica lenta e o que importa some no ruído.

Checklist

  • Existe um plano de log escrito com campos obrigatórios, eventos, lista de bloqueio e retenção.
  • Os logs saem em JSON, uma linha por evento.
  • Todo evento carrega request_id, e a resposta HTTP devolve esse id.
  • A biblioteca de log redige senha, token, cookie, CPF e cartão.
  • Eventos de negócio têm nome estável e ids de negócio como campos.
  • A retenção está configurada na ferramenta, não deixada no padrão.
  • Alguém da equipe encontra um pedido de ontem pelo id em menos de um minuto.

Pegue o último chamado de suporte que chegou com um número de pedido e tente reconstruir o que aconteceu só pelos logs: dá para achar o erro de ontem sem tropeçar em senha de usuário no meio?

Avalie este artigo

Referência: https://elven.works/conheca-as-12-ferramentas-mais-populares-para-gerenciamento-de-log/