Observabilidade em Node.js com OpenTelemetry: Guia Prático

Observabilidade em Node.js com OpenTelemetry: Guia Prático

# Observabilidade em Node.js com OpenTelemetry: Guia Prático...

4 min de leitura
🔒 Faça login para curtir

Autor

Luis Henrique Cuba

Luis Henrique Cuba

Autor no blog LHCX.

Gostou do conteúdo?

🔒 Faça login para curtir

Sua curtida nos ajuda a melhorar

Observabilidade em Node.js com OpenTelemetry: Guia Prático

Tecnologia e Inovação

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:

  1. Logs – registro textual de eventos.
  2. Metrics – valores numéricos ao longo do tempo (ex.: contadores, gauges).
  3. 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.

Desenvolvimento e Código

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.internal permite 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 por GET /external para 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.

Tags

Carregando comentários...