Observabilidade em Node.js com OpenTelemetry: Guia Prático
Introdução
A observabilidade deixou de ser um diferencial e se tornou requisito essencial para qualquer aplicação em produção. Sem visibilidade sobre latência, erros e uso de recursos, equipes de desenvolvimento e operações perdem tempo tentando reproduzir incidentes e, muitas vezes, deixam de atender aos acordos de nível de serviço (SLAs). Neste post vamos mostrar como instrumentar uma aplicação Node.js usando OpenTelemetry, exportar métricas e traces para ferramentas populares como Jaeger e Prometheus e, ao final, disponibilizar um exemplo completo com Express.
Nota: Este guia assume conhecimento básico de Node.js e Docker.
Conceitos de Observabilidade
Observabilidade é composta por três pilares:
- Logs – registro textual de eventos.
- Metrics – valores numéricos ao longo do tempo (ex.: contadores, gauges).
- Traces – representação de fluxos de execução distribuídos.
OpenTelemetry (OTel) unifica a coleta desses três pilares por meio de APIs, SDKs e exporters. Ele permite que você escreva instrumentação única e escolha o backend (Jaeger, Prometheus, Grafana, etc.) sem mudar o código da aplicação.
Configurando OpenTelemetry no Node.js
1. Instalação das dependências
bash
Crie um projeto novo ou use um existente
mkdir otel-node-demo && cd otel-node-demo npm init -y
Instale OpenTelemetry core e os plugins para HTTP e Express
npm install @opentelemetry/api @opentelemetry/sdk-node
@opentelemetry/auto-instrumentations-node
@opentelemetry/exporter-jaeger @opentelemetry/exporter-prometheus
2. Arquivo de inicialização (otel.js)
javascript // otel.js const { NodeSDK } = require('@opentelemetry/sdk-node'); const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node'); const { JaegerExporter } = require('@opentelemetry/exporter-jaeger'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus');
// Exporter para Jaeger (traces) const jaegerExporter = new JaegerExporter({ endpoint: 'http://localhost:14268/api/traces', // Jaeger collector HTTP endpoint });
// Exporter para Prometheus (metrics) const prometheusExporter = new PrometheusExporter({ startServer: true, port: 9464, endpoint: '/metrics', });
const sdk = new NodeSDK({ traceExporter: jaegerExporter, metricExporter: prometheusExporter, instrumentations: [getNodeAutoInstrumentations()], });
sdk.start() .then(() => console.log('🟢 OpenTelemetry iniciado')) .catch((err) => console.error('❌ Erro ao iniciar OpenTelemetry', err));
Dica: Mantenha este arquivo separado e o carregue antes da sua aplicação principal.
Exportando Métricas e Traces para Jaeger e Prometheus
3. Docker Compose para os back‑ends
Crie um docker-compose.yml simples:
yaml version: '3.8' services: jaeger: image: jaegertracing/all-in-one:1.53 ports: - "16686:16686" # UI - "14268:14268" # Collector HTTP prometheus: image: prom/prometheus:latest volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090"
E o prometheus.yml apontando para o exporter interno do OTel:
yaml global: scrape_interval: 15s scrape_configs:
- job_name: 'otel-node'
static_configs:
- targets: ['host.docker.internal:9464']
Importante:
host.docker.internalpermite que o container do Prometheus acesse o host onde o exporter está rodando.
4. Iniciando os serviços
bash docker-compose up -d
Agora, Jaeger UI está em http://localhost:16686 e Prometheus em http://localhost:9090.
Exemplo completo de aplicação Express
5. Código da aplicação (app.js)
javascript // app.js require('./otel'); // Garantir que o OpenTelemetry seja iniciado primeiro
const express = require('express'); const axios = require('axios'); const app = express(); const PORT = process.env.PORT || 3000;
app.get('/health', (req, res) => { res.json({ status: 'ok' }); });
// Endpoint que faz chamada externa para demonstrar trace distribuído app.get('/external', async (req, res) => { try { const response = await axios.get('https://api.github.com/repos/open-telemetry/opentelemetry-js'); res.json({ repo: response.data.full_name, stars: response.data.stargazers_count }); } catch (err) { res.status(500).json({ error: err.message }); } });
app.listen(PORT, () => {
console.log(🚀 API rodando na porta ${PORT});
});
6. Executando a aplicação
bash node app.js
Acesse:
http://localhost:3000/health– health check simples.http://localhost:3000/external– gera um trace que inclui a chamada HTTP ao GitHub.http://localhost:9464/metrics– métricas expostas para o Prometheus.- Jaeger UI (
http://localhost:16686) – procure porGET /externalpara visualizar o span.
7. Verificando no Prometheus
No console do Prometheus, experimente a query:
process_cpu_seconds_total
Você verá a métrica coletada pelo exporter do OpenTelemetry.
Conclusão
Neste guia demonstramos como instrumentar uma aplicação Node.js com OpenTelemetry, exportar dados para Jaeger (traces) e Prometheus (metrics) e validar tudo com Docker Compose. A partir daqui, você pode:
- Adicionar custom spans usando a API do OTel para marcar seções críticas do código.
- Configurar alertas no Grafana com base nas métricas coletadas.
- Escalar a solução usando agentes de coleta (OpenTelemetry Collector) para reduzir a sobrecarga nas aplicações.
A observabilidade bem implementada reduz drasticamente o MTTR (Mean Time To Recovery) e fornece insights que ajudam a otimizar performance e custo.
Este post foi escrito por um redator técnico sênior, com foco em tecnologia, desenvolvimento de software e negócios digitais.



