Monitoramento frontend com Sentry e LogRocket

1. Fundamentos do Monitoramento Frontend

Monitorar o frontend é essencial porque erros no cliente diferem drasticamente dos erros no servidor. Enquanto no backend temos controle total sobre logs e stack traces, no frontend o código executa no navegador do usuário, em ambientes imprevisíveis — diferentes sistemas operacionais, versões de navegador, extensões e condições de rede.

Os dados críticos que precisamos capturar incluem: erros de JavaScript não tratados, desempenho de componentes (tempo de renderização), interações do usuário (cliques, navegação) e métricas Web Vitals. Ferramentas como Sentry (foco em erros e performance) e LogRocket (foco em gravação de sessões) se complementam perfeitamente.

2. Configuração do Sentry em Aplicações React

Instale os pacotes necessários:

npm install @sentry/react @sentry/tracing

Configure o Sentry no ponto de entrada da sua aplicação:

import * as Sentry from "@sentry/react";
import { BrowserTracing } from "@sentry/tracing";

Sentry.init({
  dsn: "https://seu-dsn@sentry.io/seu-projeto",
  environment: process.env.NODE_ENV,
  release: "meu-app@1.0.0",
  integrations: [
    new BrowserTracing({
      tracingOrigins: ["localhost", "meusite.com.br"],
      routingInstrumentation: Sentry.reactRouterV6Instrumentation(
        ReactRouterV6BrowserTracingRouting
      ),
    }),
  ],
  tracesSampleRate: 0.2,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
});

Para integrar com React Router, use o componente withSentryReactRouterV6Routing ou configure manualmente o routingInstrumentation. Isso gera breadcrumbs automáticos de navegação.

3. Captura e Tratamento de Erros com Sentry

O Sentry fornece um ErrorBoundary pronto para React:

import { ErrorBoundary } from "@sentry/react";

function App() {
  return (
    <ErrorBoundary fallback={<p>Algo deu errado.</p>}>
      <MeuComponente />
    </ErrorBoundary>
  );
}

Para captura manual de exceções:

import * as Sentry from "@sentry/react";

try {
  await fetchDados();
} catch (erro) {
  Sentry.captureException(erro, {
    tags: { funcionalidade: "fetch-usuarios" },
    extra: { usuarioId: 123, urlTentada: "/api/usuarios" },
  });
}

Enriqueça os eventos com contexto do usuário:

Sentry.setUser({ id: "123", email: "usuario@exemplo.com" });
Sentry.setTag("plano", "premium");
Sentry.setExtra("ultimaAcao", "checkout");

4. Monitoramento de Desempenho (Performance) com Sentry

Crie transações personalizadas para operações críticas:

import * as Sentry from "@sentry/react";

async function carregarDashboard() {
  const transaction = Sentry.startTransaction({
    name: "carregar-dashboard",
    op: "pagina.carregar",
  });

  Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));

  try {
    const span = transaction.startChild({
      op: "api.buscar",
      description: "GET /api/dashboard",
    });

    const dados = await fetch("/api/dashboard").then(res => res.json());
    span.finish();

    const renderSpan = transaction.startChild({
      op: "react.render",
      description: "renderizar-componentes",
    });
    // Renderiza os componentes
    renderSpan.finish();

    transaction.finish();
  } catch (erro) {
    transaction.finish();
    Sentry.captureException(erro);
  }
}

O Sentry rastreia automaticamente métricas como First Input Delay (FID) e Largest Contentful Paint (LCP). Analise as "Slow Traces" no painel para identificar gargalos.

5. Introdução ao LogRocket: Gravação de Sessões de Usuário

Instale o SDK:

npm install logrocket

Configure no início da aplicação:

import LogRocket from 'logrocket';

LogRocket.init('seu-app-id', {
  dom: {
    inputSanitizer: true, // Mascara inputs sensíveis
  },
  release: '1.0.0',
  network: {
    requestSanitizer: (request) => ({
      ...request,
      headers: { ...request.headers, Authorization: undefined },
    }),
  },
});

Vincule usuários às sessões:

LogRocket.identify('usuario-123', {
  name: 'João Silva',
  email: 'joao@exemplo.com',
  plano: 'premium',
});

Para controle granular, ative/desative gravação por rota:

if (window.location.pathname.startsWith('/admin')) {
  LogRocket.stopRecording(); // Não gravar áreas sensíveis
} else {
  LogRocket.startRecording();
}

6. Integração Avançada: Sentry + LogRocket em Conjunto

Sincronize as sessões enviando o URL do LogRocket para o Sentry:

import * as Sentry from "@sentry/react";
import LogRocket from 'logrocket';

function enviarLinkSessaoParaSentry() {
  const sessionURL = LogRocket.sessionURL;
  if (sessionURL) {
    Sentry.setExtra("logrocket_session", sessionURL);
  }
}

Crie um hook personalizado para capturar erros com contexto unificado:

function useMonitoramento() {
  const capturarErro = (erro, contexto = {}) => {
    const sessionURL = LogRocket.sessionURL;
    Sentry.captureException(erro, {
      extra: { ...contexto, logrocket_session: sessionURL },
    });
  };

  return { capturarErro };
}

Exemplo prático em um componente:

function ComponenteCritico() {
  const { capturarErro } = useMonitoramento();

  const processarPagamento = async () => {
    try {
      await api.processarPagamento();
    } catch (erro) {
      capturarErro(erro, { valor: 150.00, metodo: "cartao" });
      LogRocket.log('Erro ao processar pagamento', { erro });
    }
  };

  return <button onClick={processarPagamento}>Pagar</button>;
}

7. Análise de Dados e Melhoria Contínua

No painel do Sentry, filtre erros por versão da aplicação, ambiente (produção, staging) e frequência. Use gráficos de tendência para identificar regressões.

No LogRocket, reproduza sessões completas: veja exatamente o que o usuário fez antes do erro — cliques, scroll, inputs. Isso é crucial para depurar erros intermitentes que você não consegue reproduzir localmente.

Configure alertas no Sentry para notificar times via Slack ou Discord quando erros críticos ultrapassarem um limite:

// Exemplo de regra de alerta no Sentry:
// "Enviar para Slack quando erro 'checkout.falha' ocorrer > 10 vezes em 5 minutos"

8. Boas Práticas e Considerações Finais

Vazamento de dados sensíveis: configure denyUrls para evitar que erros de bibliotecas externas poluam seus logs:

Sentry.init({
  denyUrls: [
    /extensions\//i,
    /^chrome:\/\//i,
  ],
});

Impacto no desempenho: carregue os SDKs de forma lazy quando possível e use amostragem:

if (Math.random() < 0.1) { // 10% das sessões
  LogRocket.init('app-id');
}

Privacidade: no LogRocket, use inputSanitizer: true para mascarar campos de senha e cartão de crédito. Para GDPR, implemente consentimento explícito:

if (usuarioConsentiuMonitoramento) {
  LogRocket.init('app-id');
  Sentry.init({ dsn: '...' });
}

Combinar Sentry e LogRocket oferece uma visão completa: erros com contexto técnico detalhado + gravação visual da jornada do usuário. Essa dupla permite diagnosticar problemas que nenhuma ferramenta isolada resolveria.

Referências