<h2>Introdução: Por que monitorar Node.js em produção?</h2>
<p>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.</p>
<p>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.</p>
<h2>OpenTelemetry: Instrumentação Completa</h2>
<h3>Instalação e Setup Básico</h3>
<p>Comece instalando os pacotes essenciais:</p>
<pre><code class="language-bash">npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto \
@opentelemetry/sdk-trace-node @opentelemetry/exporter-trace-otlp-http \
@opentelemetry/resources @opentelemetry/semantic-conventions</code></pre>
<p>Crie um arquivo <code>tracing.js</code> que deve ser importado <strong>antes</strong> de qualquer outra dependência:</p>
<pre><code class="language-javascript">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));
});</code></pre>
<p>No seu <code>index.js</code> ou <code>app.js</code>, importe este arquivo <strong>primeira coisa</strong>:</p>
<pre><code class="language-javascript">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'));</code></pre>
<h3>Métricas e Spans Customizados</h3>
<p>Além da instrumentação automática, você pode criar spans customizados para lógica de negócio:</p>
<pre><code class="language-javascript">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();
}
}</code></pre>
<h2>Sentry: Captura Inteligente de Erros</h2>
<h3>Configuração e Integração</h3>
<p>Sentry detecta erros não tratados, exceções e problemas de performance. Instale:</p>
<pre><code class="language-bash">npm install @sentry/node @sentry/tracing</code></pre>
<p>Configure no início da sua aplicação (depois do OpenTelemetry):</p>
<pre><code class="language-javascript">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);</code></pre>
<h3>Captura Manual e Contexto</h3>
<p>Para eventos específicos, capture manualmente com contexto:</p>
<pre><code class="language-javascript">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' });
}
});</code></pre>
<h2>Integração OpenTelemetry + Sentry</h2>
<p>OpenTelemetry e Sentry trabalham juntos. Adicione o Sentry como exportador de traces:</p>
<pre><code class="language-bash">npm install @sentry/opentelemetry-node</code></pre>
<pre><code class="language-javascript">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
],
});</code></pre>
<p>Agora todos os spans do OpenTelemetry aparecem como transactions no Sentry, criando uma visão unificada de performance e erros.</p>
<h2>Boas Práticas e Alerts</h2>
<p>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.</p>
<p>No código, sempre adicione informação do usuário aos erros: <code>Sentry.setUser({ id, email })</code>. Isso ajuda a correlacionar problemas com experiências reais.</p>
<p>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.</p>
<h2>Conclusão</h2>
<p>Monitorar Node.js em produção não é opcional — é essencial. <strong>OpenTelemetry fornece observabilidade estruturada</strong> com traces distribuídos que rastreiam requisições através de múltiplos serviços. <strong>Sentry complementa com captura de erros inteligente, análise de performance e alertas proativos</strong>. 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.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://opentelemetry.io/docs/instrumentation/js/" target="_blank" rel="noopener noreferrer">OpenTelemetry Official Documentation</a></li>
<li><a href="https://docs.sentry.io/platforms/javascript/guides/node/" target="_blank" rel="noopener noreferrer">Sentry Node.js SDK</a></li>
<li><a href="https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/packages/auto-instrumentations-node" target="_blank" rel="noopener noreferrer">OpenTelemetry Node Auto-Instrumentation</a></li>
<li><a href="https://docs.sentry.io/product/integrations/opentelemetry/" target="_blank" rel="noopener noreferrer">Sentry OpenTelemetry Integration</a></li>
<li><a href="https://www.cncf.io/blog/2021/05/18/distributed-tracing-overview/" target="_blank" rel="noopener noreferrer">Distributed Tracing Best Practices - Cloud Native Computing Foundation</a></li>
</ul>