Registro em Aplicações JavaScript: Melhores Práticas para Node.js
Registro (logging) não é apenas escrever mensagens no console. Em aplicações Node.js modernas, é uma ferramenta criticamente importante para depuração, monitoramento e auditoria. Um registro configurado corretamente permite encontrar erros rapidamente, analisar o comportamento dos usuários e garantir a estabilidade do serviço. Neste artigo, vamos abordar as melhores práticas de registro em JavaScript (Node.js), desde a escolha da biblioteca até a configuração da coleta centralizada de logs.
1. Escolha da Biblioteca de Registro
O console.log nativo é bom apenas para desenvolvimento. Para ambientes de produção, são necessárias bibliotecas especializadas que forneçam níveis de registro, formatação, rotação de arquivos e integração com sistemas externos.
Vamos considerar três opções populares:
- Winston — a biblioteca mais popular. Flexível, com suporte a múltiplos transportes (arquivos, console, HTTP, bancos de dados). Ideal para sistemas complexos.
- Pino — um logger ultrarrápido. Recomendado para aplicações de alta carga onde o desempenho é crítico.
- Bunyan — gera logs no formato JSON. Conveniente para processamento por máquinas.
Exemplo de configuração do Winston:
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ],});
if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), }));}
logger.info('Serviço iniciado');logger.error('Erro ao conectar ao banco de dados', { db: 'main' });2. Uso de Níveis de Registro
Os níveis de registro ajudam a filtrar mensagens por importância. A hierarquia padrão (do menos para o mais crítico):
- debug — informações detalhadas de depuração (apenas para desenvolvimento).
- info — eventos padrão (requisição processada, usuário autenticado).
- warn — problemas potenciais (baixo nível de memória, requisição lenta).
- error — erros críticos (falha de módulo, exceção).
Regra: Em produção, use o nível info ou superior. O debug deve estar desativado para não sobrecarregar os discos e reduzir o desempenho.
Exemplo de mudança dinâmica de nível:
const logger = require('./logger');
if (process.env.LOG_LEVEL) { logger.level = process.env.LOG_LEVEL;}
logger.debug('Esta mensagem não aparecerá em produção');logger.info('Usuário fez login');logger.error('Falha ao salvar dados');3. Logs Estruturados (JSON)
Logs em texto são difíceis de analisar. A prática moderna é usar logs estruturados no formato JSON. Isso permite fácil integração com sistemas de análise (ELK, Splunk, Grafana Loki).
O que deve estar em cada log:
- timestamp — hora exata do evento (ISO 8601).
- level — nível de registro.
- message — descrição legível por humanos.
- context — dados adicionais (ID da requisição, nome do usuário, código do erro).
Exemplo com Pino:
const pino = require('pino');
const logger = pino({ level: 'info', timestamp: pino.stdTimeFunctions.isoTime, formatters: { level(label) { return
```