FNSP Web Page

Logs: o que registar, e o que nunca

Os registos servem para responder a uma pergunta que se faz sempre tarde: o que é que aconteceu às 3 da manhã? Um registo que não responde a isso é papel; um que responde de mais é um problema legal.

1. Níveis, e o que cabe em cada um

  • error — falhou e alguém tem de saber. Uma exceção, uma gravação recusada.

  • warn — não falhou, mas não está bem. Uma tentativa recusada, um limite atingido.

  • info — acontecimentos que interessam depois: arranque, deploy, uma encomenda criada.

  • debug — o detalhe para caçar um problema. Desligado em produção.

Se tudo for error, nada é: o alerta que dispara cem vezes por dia é um alerta que ninguém lê.

2. Estruturados, não frases

// Bonito para uma pessoa, inútil para procurar
console.log(`Utilizador ${id} falhou a entrar às ${new Date()}`);

// Feio de ler, e pesquisável
logger.warn({ evento: 'entrada_falhada', utilizadorId: id, ip });

Com objetos, responder a "quantas tentativas falhadas por IP na última hora" é uma consulta. Com frases, é um grep e alguma esperança.

3. O que nunca entra num registo

  • Passwords. Nem em erros, nem "só desta vez para ver o que se passa".

  • Tokens, chaves e cookies de sessão. Um registo com um token é uma sessão utilizável por quem o ler.

  • Dados pessoais a mais. Moradas, números de identificação, o corpo de mensagens privadas. Os registos vão para sítios com outras regras de acesso — e o RGPD aplica-se lá como aqui.

  • O corpo inteiro dos pedidos. É o caminho mais rápido para os três pontos anteriores.

const OCULTAR = new Set(['password', 'token', 'authorization', 'cookie']);

const seguro = Object.fromEntries(
  Object.entries(dados).map(([chave, valor]) => [
    chave,
    OCULTAR.has(chave.toLowerCase()) ? '[oculto]' : valor,
  ])
);

4. O identificador que junta as pontas

Um pedido que atravessa três serviços deixa três registos sem relação aparente. Um identificador gerado à entrada e passado adiante transforma isso numa história legível:

const pedidoId = crypto.randomUUID();
logger.info({ pedidoId, rota: '/api/encomendas', ms: 42 });

E rotação, sempre. Registos sem limite enchem o disco — e um disco cheio derruba a aplicação que os escrevia.

Comentários

Ainda ninguém comentou este artigo.

Voltar ao blog

Gostávamos de saber quantas pessoas visitam o site, com o Google Analytics. Sem a sua autorização não corre nada. Política de Privacidade.