Registro em aplicações JavaScript: melhores práticas na prática
Registro não é apenas escrever mensagens no console. Em ambiente de produção, um registro bem configurado se torna a principal ferramenta de monitoramento, depuração e auditoria. Sem ele, você trabalha às cegas. Neste artigo, vamos abordar as melhores práticas de registro para aplicações JavaScript no Node.js, desde a escolha da biblioteca até a configuração da rotação de arquivos. Todos os exemplos de código estão prontos para uso.
1. Por que console.log é ruim?
Na fase de desenvolvimento, todos usamos console.log. É rápido e conveniente. Mas em produção, essa abordagem é perigosa:
- Sem níveis de registro. Você não conseguirá filtrar erros de mensagens informativas.
- Bloqueio síncrono. O
console.logpadrão pode desacelerar a aplicação com um grande fluxo de requisições. - Falta de estrutura. Logs JSON não podem ser analisados sem adaptações adicionais.
- Sem rotação. O arquivo de log crescerá infinitamente até encher o disco.
Em vez disso, use bibliotecas profissionais. As duas mais populares no Node.js são Winston e Pino.
2. Escolha da biblioteca: Winston vs Pino
Ambas as bibliotecas resolvem o mesmo problema, mas têm prioridades diferentes.
Winston — universal e flexível
Winston é o "canivete suíço" do registro. Ele suporta múltiplos transportes (arquivos, console, HTTP, bancos de dados) e é facilmente configurável.
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ],});
// Em desenvolvimento, adicionamos saída no consoleif (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), }));}
logger.info('Servidor iniciado na porta 3000');logger.error('Erro de conexão com o BD', { db: 'postgres' });Pino — velocidade em primeiro lugar
Pino se posiciona como o logger mais rápido para Node.js. Ele é 5-6x mais rápido que o Winston graças ao uso de sonic-boom (escrita assíncrona). Ideal para projetos de alta carga.
const pino = require('pino');
const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino/file', options: { destination: './app.log' }, },});
logger.info({ user: 'admin' }, 'Usuário entrou no sistema');logger.error({ err: new Error('Timeout') }, 'Requisição excedeu o limite');Dica: Para microsserviços e APIs de alta carga, escolha Pino. Para configurações complexas com múltiplos transportes, escolha Winston.
3. Níveis de registro: não escreva tudo em info
Use a escala padrão de níveis (em ordem crescente de importância):
trace/debug— apenas para desenvolvimento. Depuração detalhada.info— operação normal da aplicação: inicialização, requisições bem-sucedidas, eventos de negócio.warn— problemas potenciais: requisições lentas, falta de memória, métodos obsoletos.error— exceções, falhas, quedas. Devem estar sempre em um arquivo separado ou sistema de monitoramento.fatal— erros críticos após os quais a aplicação não pode continuar funcionando.
Configure a variável de ambiente LOG_LEVEL para alterar o nível de filtragem sem reiniciar o código:
// Exemplo com Winstonconst logger = winston.createLogger({ level: process.env.LOG_LEVEL || 'info', // ...});
// Em