Melhores Práticas para Registro de Erros em JavaScript
  Aplicações JavaScript em produção falham silenciosamente todos os dias. Usuários encontram erros que os desenvolvedores nunca veem, levando a experiências ruins e perda de receita. A diferença entre aplicações que capturam esses problemas e aquelas que não capturam? Registro adequado de erros.
Este artigo aborda práticas essenciais para implementar um registro robusto de erros em JavaScript em ambientes frontend e backend. Você aprenderá como ir além do console.log, implementar registro estruturado com frameworks comprovados e construir um sistema que captura erros críticos antes que os usuários os reportem.
Pontos-Chave
- Registro via console carece de persistência, centralização e estrutura necessárias para ambientes de produção
 - Registro estruturado com frameworks como Winston ou Pino fornece dados analisáveis por máquina
 - Tratamento de erros no frontend requer manipuladores globais e soluções específicas de frameworks como React Error Boundaries
 - Proteger dados sensíveis e incluir informações contextuais são críticos para um registro eficaz
 
Por Que o Registro via Console Falha em Produção
A maioria dos desenvolvedores começa com console.log() para depuração. Embora adequada durante o desenvolvimento, essa abordagem falha em produção:
// This error disappears into the user's browser
try {
  processPayment(order);
} catch (error) {
  console.error(error); // Lost forever in production
}
Métodos de console carecem de:
- Persistência além da sessão atual
 - Coleta centralizada entre usuários
 - Dados estruturados para análise
 - Níveis de severidade para priorização
 - Proteção de dados sensíveis
 
Aplicações em produção precisam de registro que capture, estruture e transmita erros para um local central para análise.
Implementando Registro Estruturado com Frameworks Comprovados
Escolhendo o Framework Adequado
Para registro em Node.js, dois frameworks dominam o ecossistema:
Winston oferece flexibilidade e opções extensivas de transporte:
const winston = require('winston');
const logger = winston.createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: 'error.log', level: 'error' })
  ]
});
Pino prioriza desempenho com sobrecarga mínima:
const pino = require('pino');
const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  timestamp: pino.stdTimeFunctions.isoTime,
  formatters: {
    level: (label) => ({ level: label })
  }
});
Estruturando Seus Logs
Substitua strings não estruturadas por objetos JSON que máquinas possam analisar:
// Bad: Unstructured string
logger.info(`User ${userId} failed login attempt`);
// Good: Structured JSON
logger.info({
  event: 'login_failed',
  userId: userId,
  ip: request.ip,
  timestamp: new Date().toISOString(),
  userAgent: request.headers['user-agent']
});
Discover how at OpenReplay.com.
Componentes Essenciais de Registro Eficaz de Erros em JavaScript
1. Use Níveis de Log Apropriados
Implemente níveis de severidade consistentes em toda sua aplicação:
logger.debug('Detailed debugging information');
logger.info('Normal application flow');
logger.warn('Warning: degraded performance detected');
logger.error('Error occurred but application continues');
logger.fatal('Critical failure, application shutting down');
2. Sempre Inclua Stack Traces
Capture o contexto completo do erro para depuração:
process.on('uncaughtException', (error) => {
  logger.fatal({
    message: error.message,
    stack: error.stack,
    timestamp: new Date().toISOString()
  });
  process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
  logger.error({
    message: 'Unhandled Promise Rejection',
    reason: reason,
    promise: promise
  });
});
3. Adicione Informações Contextuais
Inclua IDs de requisição, IDs de usuário e dados de sessão para rastrear problemas:
const requestLogger = logger.child({
  requestId: generateRequestId(),
  sessionId: request.session.id
});
requestLogger.info('Processing payment request');
4. Proteja Dados Sensíveis
Nunca registre senhas, tokens ou informações pessoais:
const logger = pino({
  redact: ['password', 'creditCard', 'ssn', 'authorization']
});
// These fields will be automatically redacted
logger.info({
  user: email,
  password: 'secret123', // Will show as [REDACTED]
  action: 'login_attempt'
});
Estratégias de Tratamento de Erros no Frontend
Manipuladores Globais de Erros
Capture todos os erros não tratados em ambientes de navegador:
window.addEventListener('error', (event) => {
  logToServer({
    message: event.message,
    source: event.filename,
    line: event.lineno,
    column: event.colno,
    stack: event.error?.stack
  });
});
window.addEventListener('unhandledrejection', (event) => {
  logToServer({
    type: 'unhandledRejection',
    reason: event.reason,
    promise: event.promise
  });
});
React Error Boundaries
Para aplicações React, implemente error boundaries para capturar erros de componentes:
class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
  static getDerivedStateFromError(error) {
    return { hasError: true };
  }
  componentDidCatch(error, errorInfo) {
    logger.error({
      message: error.toString(),
      componentStack: errorInfo.componentStack,
      timestamp: new Date().toISOString()
    });
  }
  render() {
    if (this.state.hasError) {
      return <h2>Something went wrong. Please refresh the page.</h2>;
    }
    return this.props.children;
  }
}
Centralizando Logs para Análise
Direcione todos os logs para stdout e deixe sua infraestrutura lidar com o roteamento:
// Configure logger to output to stdout only
const logger = pino({
  transport: {
    target: 'pino-pretty',
    options: {
      destination: 1 // stdout
    }
  }
});
Esta abordagem permite que Docker, Kubernetes ou coletores de logs como Fluentd coletem e encaminhem logs para sistemas centralizados para análise. Para aplicações client-side, implemente um endpoint simples para receber e encaminhar logs dos navegadores para sua infraestrutura centralizada de registro.
Conclusão
Registro eficaz de erros em JavaScript requer mais do que substituir console.log por um framework. Exige dados estruturados, níveis de severidade apropriados, contexto abrangente de erros e coleta centralizada. Ao implementar essas práticas com frameworks como Winston ou Pino, protegendo dados sensíveis e estabelecendo error boundaries adequados no código frontend, você cria um sistema que captura problemas antes que impactem os usuários. Comece com esses fundamentos e depois expanda baseado nas necessidades específicas de monitoramento da sua aplicação.
Perguntas Frequentes
Pino tem sobrecarga mínima, adicionando apenas 2-3% de latência na maioria dos casos. Winston é um pouco mais pesado, mas ainda negligenciável para a maioria das aplicações. Ambos são prontos para produção e usados por aplicações de alto tráfego em todo o mundo.
Use recursos de redação integrados no seu framework de registro para mascarar automaticamente campos sensíveis. Defina uma lista de nomes de campos para redação como senhas, tokens e números de cartão de crédito. Sempre audite seus logs regularmente para exposição acidental de dados.
Registre erros em ambos os lados. Registro client-side captura problemas específicos do navegador e erros JavaScript que nunca chegam ao seu servidor. Registro server-side trata erros de API e falhas de backend. Use um sistema centralizado para agregar ambas as fontes.
Configure alertas para níveis error e fatal imediatamente. Níveis warning podem acionar resumos diários. Níveis info e debug devem ser pesquisáveis, mas não acionar alertas, a menos que você esteja investigando problemas específicos ou monitorando eventos críticos de negócio.
Understand every bug
Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.