Monitoramento de Apps Node.js em Produção: OpenTelemetry e Sentry: Do Básico ao Avançado Já leu

Introdução: Por que monitorar Node.js em produção? Aplicações Node.js em produção enfrentam desafios reais: latência inesperada, erros silenciosos, picos de memória e degradação de performance. Sem visibilidade adequada, você só descobre problemas quando seus usuários reclamam. OpenTelemetry e Sentry resolvem isso fornecendo observabilidade completa — rastreamento distribuído, métricas em tempo real e captura de exceções. OpenTelemetry é um padrão open-source para instrumentação, enquanto Sentry é uma plataforma de error tracking que complementa perfeitamente. Juntas, essas ferramentas criam uma rede de segurança que identifica problemas antes que se tornem críticos. OpenTelemetry: Instrumentação Completa Instalação e Setup Básico Comece instalando os pacotes essenciais: Crie um arquivo que deve ser importado antes de qualquer outra dependência: No seu ou , importe este arquivo primeira coisa: Métricas e Spans Customizados Além da instrumentação automática, você pode criar spans customizados para lógica de negócio: Sentry: Captura Inteligente de Erros Configuração e Integração Sentry detecta erros não tratados, exceções e problemas de performance. Instale: Configure no

Introdução: Por que monitorar Node.js em produção?

Aplicações Node.js em produção enfrentam desafios reais: latência inesperada, erros silenciosos, picos de memória e degradação de performance. Sem visibilidade adequada, você só descobre problemas quando seus usuários reclamam. OpenTelemetry e Sentry resolvem isso fornecendo observabilidade completa — rastreamento distribuído, métricas em tempo real e captura de exceções.

OpenTelemetry é um padrão open-source para instrumentação, enquanto Sentry é uma plataforma de error tracking que complementa perfeitamente. Juntas, essas ferramentas criam uma rede de segurança que identifica problemas antes que se tornem críticos.

OpenTelemetry: Instrumentação Completa

Instalação e Setup Básico

Comece instalando os pacotes essenciais:

npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto \
  @opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http \
  @opentelemetry/resources @opentelemetry/semantic-conventions

Crie um arquivo tracing.js que deve ser importado antes de qualquer outra dependência:

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');

const traceExporter = new OTLPTraceExporter({
  url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://localhost:4318/v1/traces',
});

const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'meu-app-nodejs',
    [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
  }),
  traceExporter,
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();
console.log('OpenTelemetry iniciado');

process.on('SIGTERM', () => {
  sdk.shutdown()
    .then(() => console.log('Tracing finalizado'))
    .catch((log) => console.log('Erro ao finalizar tracing', log))
    .finally(() => process.exit(0));
});

No seu index.js ou app.js, importe este arquivo primeira coisa:

require('./tracing');
const express = require('express');

const app = express();

app.get('/api/users/:id', (req, res) => {
  const userId = req.params.id;
  // Simulando busca em BD
  res.json({ id: userId, name: 'João' });
});

app.listen(3000, () => console.log('Servidor rodando na porta 3000'));

Métricas e Spans Customizados

Além da instrumentação automática, você pode criar spans customizados para lógica de negócio:

const { trace } = require('@opentelemetry/api');

const tracer = trace.getTracer('meu-app-tracer', '1.0.0');

async function processarPagamento(pedidoId) {
  const span = tracer.startSpan('processarPagamento');

  try {
    span.setAttribute('pedido.id', pedidoId);

    // Span filho para validação
    const validSpan = tracer.startSpan('validarPagamento', { parent: span });
    await validarPagamento(pedidoId);
    validSpan.end();

    // Span filho para processamento
    const procSpan = tracer.startSpan('enviarGateway', { parent: span });
    const resultado = await enviarParaGateway(pedidoId);
    procSpan.setAttribute('resultado.status', resultado.status);
    procSpan.end();

    span.setStatus({ code: 0 }); // OK
    return resultado;
  } catch (erro) {
    span.recordException(erro);
    span.setStatus({ code: 2 }); // ERROR
    throw erro;
  } finally {
    span.end();
  }
}

Sentry: Captura Inteligente de Erros

Configuração e Integração

Sentry detecta erros não tratados, exceções e problemas de performance. Instale:

npm install @sentry/node @sentry/tracing

Configure no início da sua aplicação (depois do OpenTelemetry):

require('./tracing'); // OpenTelemetry primeiro
const Sentry = require('@sentry/node');
const { nodeProfilingIntegration } = require('@sentry/profiling-node');
const express = require('express');

const app = express();

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  environment: process.env.NODE_ENV || 'development',
  tracesSampleRate: 1.0,
  profilesSampleRate: 0.1, // 10% para profiling
  integrations: [
    new Sentry.Integrations.Http({ tracing: true }),
    new Sentry.Integrations.Express({ app }),
    nodeProfilingIntegration(),
  ],
});

// Middleware ANTES das rotas
app.use(Sentry.Handlers.requestHandler());
app.use(Sentry.Handlers.tracingHandler());

// Suas rotas aqui
app.get('/api/dados', (req, res) => {
  res.json({ ok: true });
});

// Middleware de erro DEPOIS das rotas
app.use(Sentry.Handlers.errorHandler());

app.listen(3000);

Captura Manual e Contexto

Para eventos específicos, capture manualmente com contexto:

app.post('/api/transferencia', async (req, res) => {
  const { origem, destino, valor } = req.body;

  Sentry.setContext('transferencia', {
    origem,
    destino,
    valor,
    timestamp: new Date().toISOString(),
  });

  try {
    const resultado = await executarTransferencia(origem, destino, valor);
    res.json(resultado);
  } catch (erro) {
    // Capture com level apropriado
    Sentry.captureException(erro, {
      level: 'error',
      tags: {
        operacao: 'transferencia',
        severidade: valor > 10000 ? 'alto' : 'normal',
      },
    });
    res.status(500).json({ erro: 'Falha na transferência' });
  }
});

Integração OpenTelemetry + Sentry

OpenTelemetry e Sentry trabalham juntos. Adicione o Sentry como exportador de traces:

npm install @sentry/opentelemetry-node
require('./tracing');
const Sentry = require('@sentry/node');
const { SentryPropagator, SentrySpanProcessor } = require('@sentry/opentelemetry-node');

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  integrations: [
    new Sentry.Integrations.Http({ tracing: true }),
    new SentrySpanProcessor(), // Sincroniza spans com Sentry
  ],
});

Agora todos os spans do OpenTelemetry aparecem como transactions no Sentry, criando uma visão unificada de performance e erros.

Boas Práticas e Alerts

Configure alertas no Sentry para problemas críticos: aumente de taxa de erro acima de 5%, latência P95 acima de 1 segundo, ou memory usage crescente. Use tags e contexto consistentemente para facilitar investigação.

No código, sempre adicione informação do usuário aos erros: Sentry.setUser({ id, email }). Isso ajuda a correlacionar problemas com experiências reais.

Exporte métricas do OpenTelemetry para Grafana ou Datadog para visualizar tendências. Configure sampling inteligente: 100% para erros, 10-20% para traces normais, reduzindo custos sem perder visibilidade.

Conclusão

Monitorar Node.js em produção não é opcional — é essencial. OpenTelemetry fornece observabilidade estruturada com traces distribuídos que rastreiam requisições através de múltiplos serviços. Sentry complementa com captura de erros inteligente, análise de performance e alertas proativos. Juntas, essas ferramentas transformam você de reativo (esperando reclamações) para proativo (identificando problemas antes do impacto). Comece instrumentando sua app hoje: seu futuro eu agradecerá quando rastrear um bug complexo em 5 minutos em vez de 5 horas.

Referências


Artigos relacionados