Registro em aplicações JavaScript: melhores práticas para iniciantes
Registro é a base da depuração e monitoramento de qualquer aplicação. Sem logs de qualidade, você estará "procurando uma agulha no palheiro" quando algo der errado. Neste artigo, vamos abordar as melhores práticas de registro em JavaScript (Node.js), adequadas tanto para pequenos projetos quanto para produção.
1. Por que não confiar no console.log?
Muitos desenvolvedores iniciantes usam console.log para tudo. Isso é conveniente durante o desenvolvimento, mas em ambiente de produção essa abordagem causa problemas:
- Sem níveis de registro — você não pode filtrar erros de mensagens informativas.
- Difícil gerenciar a saída — não é possível desabilitar logs para módulos específicos.
- Baixo desempenho — a serialização de objetos em
console.logpode ser custosa. - Falta de estrutura — os logs não têm um formato unificado (JSON, timestamp, nível).
Em vez disso, use bibliotecas especializadas. Aqui está um exemplo simples, mas correto, usando Winston:
// logger.jsconst 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' }), ],});
if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), }));}
module.exports = logger;2. Níveis de registro: quando usar cada um
Os níveis padrão de registro (em ordem crescente de gravidade): debug, info, warn, error. É importante entender quando aplicar cada nível:
- debug — informações detalhadas para desenvolvedores (valores de variáveis, estado do sistema). Desabilitado em produção.
- info — eventos normais de funcionamento da aplicação (requisição processada, usuário registrado).
- warn — situações potencialmente perigosas (pouca memória disponível, API obsoleta).
- error — erros que exigem intervenção (exceções, falhas no banco de dados).
Exemplo de uso correto com a biblioteca Pino (a mais rápida para Node.js):
const pino = require('pino');
const logger = pino({ level: process.env.LOG_LEVEL || 'info', transport: { target: 'pino-pretty', options: { colorize: true } }});
// Usologger.info({ userId: 123 }, 'Usuário fez login no sistema');logger.error(new Error('Erro de conexão com o banco de dados'), 'Erro crítico');logger.debug('Valor da variável x = 42'); // não será exibido se level = 'info'3. Registro estruturado: JSON e contexto
Em vez de strings de texto, use logs estruturados (geralmente JSON). Isso permite:
- Parsear logs facilmente com ferramentas (ELK, Graylog).
- Adicionar contexto (ID da requisição, usuário, versão).
- Filtrar e agregar dados.
Exemplo de log estruturado com contexto:
const logger = require('./logger');
app.use((req, res, next) => { req.requestId = uuidv4(); next();});
app.get('/api/users', async (req, res) => { logger.info({ requestId: req.requestId, method: req.method, url: req.originalUrl, ip: req.ip }, 'Requisição recebida');
try { const users = await getUsers(); logger.info({ requestId: req.requestId, count: users.length }, 'Usuários obtidos'); res.json(users); } catch (err) { logger.error({