Observabilidade em Node.js: OpenTelemetry + Grafana passo a passo

Observabilidade em Node.js: OpenTelemetry + Grafana passo a passo

# Observabilidade em Node.js: OpenTelemetry + Grafana passo a passo...

5 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: OpenTelemetry + Grafana passo a passo

Tecnologia e Inovação

Introdução

Nos últimos anos, a observabilidade deixou de ser um diferencial e se tornou requisito básico para aplicações em produção. Sem visibilidade clara sobre latência, erros e recursos consumidos, equipes de desenvolvimento gastam horas (ou dias) tentando reproduzir problemas que já aconteceram. Ferramentas como OpenTelemetry, Prometheus e Grafana permitem coletar métricas, traces e logs de forma padronizada, facilitando a detecção precoce de incidentes e a tomada de decisão baseada em dados.

Este post mostra, de forma prática, como instrumentar uma aplicação Node.js usando o SDK do OpenTelemetry, exportar os dados para o Prometheus e visualizá‑los no Grafana. Ao final, você terá um pipeline completo de observabilidade pronto para ser integrado ao seu CI/CD.


1. Preparando o ambiente

1.1 Requisitos

  • Node.js >= 14
  • Docker & Docker‑Compose
  • Conta no Grafana Cloud (ou instalação local)
  • Git instalado

1.2 Estrutura do projeto

bash my-observability-app/ ├─ src/ │ └─ index.js ├─ otel-config/ │ └─ otel-setup.js ├─ docker-compose.yml ├─ package.json └─ .env

1.3 Inicializando o projeto

bash mkdir my-observability-app && cd $_ npm init -y npm install express @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/exporter-prometheus

2. Configurando o OpenTelemetry

2.1 Arquivo de bootstrap (otel-config/otel-setup.js)

javascript // otel-config/otel-setup.js const { NodeSDK } = require('@opentelemetry/sdk-node'); const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node'); const { PrometheusExporter } = require('@opentelemetry/exporter-prometheus'); const { diag, DiagConsoleLogger, DiagLogLevel } = require('@opentelemetry/api');

// Habilita logs de diagnóstico (útil em dev) diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.INFO);

// Exporter que expõe métricas no endpoint /metrics const prometheusExporter = new PrometheusExporter({ startServer: true, port: 9464, endpoint: '/metrics', });

const sdk = new NodeSDK({ instrumentations: [getNodeAutoInstrumentations()], metricReader: prometheusExporter, });

sdk.start();

process.on('SIGTERM', () => { sdk.shutdown() .then(() => console.log('OpenTelemetry shut down')) .catch((error) => console.error('Error shutting down OpenTelemetry', error)) .finally(() => process.exit(0)); });

2.2 Integrando ao código da aplicação (src/index.js)

javascript // src/index.js require('dotenv').config(); require('../otel-config/otel-setup'); // <-- inicializa OpenTelemetry antes de tudo

const express = require('express'); const app = express(); const PORT = process.env.PORT || 3000;

app.get('/health', (req, res) => { res.json({ status: 'ok' }); });

app.get('/slow', async (req, res) => { // Simula latência aleatória entre 200ms e 2s const delay = Math.floor(Math.random() * 1800) + 200; await new Promise((r) => setTimeout(r, delay)); res.json({ delayMs: delay }); });

app.listen(PORT, () => { console.log(🚀 App rodando na porta ${PORT}); });

Importante: O require('../otel-config/otel-setup') deve ser a primeira linha que executa código da aplicação, garantindo que todos os módulos sejam instrumentados.

3. Orquestrando com Docker‑Compose

3.1 docker-compose.yml

yaml version: '3.8' services: app: build: . ports: - "3000:3000" - "9464:9464" # porta do exporter Prometheus environment: - NODE_ENV=production depends_on: - prometheus

prometheus: image: prom/prometheus:latest volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml ports: - "9090:9090"

grafana: image: grafana/grafana:latest ports: - "3001:3000" depends_on: - prometheus environment: - GF_SECURITY_ADMIN_PASSWORD=admin volumes: - grafana-data:/var/lib/grafana

volumes: grafana-data:

3.2 Configuração do Prometheus (prometheus.yml)

yaml global: scrape_interval: 15s

scrape_configs:

  • job_name: 'node_app' static_configs:
    • targets: ['app:9464']

3.3 Dockerfile

dockerfile FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 9464 CMD ["node", "src/index.js"]

Com tudo configurado, basta executar:

bash docker-compose up --build

A aplicação ficará disponível em http://localhost:3000, o endpoint de métricas em http://localhost:9464/metrics e o Prometheus em http://localhost:9090.

Desenvolvimento e Código

4. Visualizando métricas no Grafana

  1. Acesse http://localhost:3001 (login: admin / admin).
  2. Adicione um Data SourcePrometheus → URL: http://prometheus:9090Save & Test.
  3. Crie um DashboardAdd Panel → escolha a métrica process_cpu_seconds_total ou http_server_requests_duration_seconds.
  4. Salve o painel e explore: você verá o número de requisições, latência média, uso de CPU e memória da aplicação Node.js.

4.1 Painel de latência das rotas

promql

Latência média da rota /slow em segundos

histogram_quantile(0.95, sum(rate(http_server_requests_duration_seconds_bucket{handler="/slow"}[5m])) by (le))

Esse query exibe o 95º percentil da latência nos últimos 5 minutos, permitindo identificar picos de resposta lenta.

5. Boas práticas e próximos passos

  • Instrumentação manual: embora o auto‑instrumentation cubra a maioria dos casos, você pode criar spans customizados com api.trace.getTracer('my-app') para rastrear fluxos de negócio críticos.
  • Logs estruturados: combine traces com logs usando o OpenTelemetry Logging SDK ou ferramentas como Elastic Stack.
  • Alertas: configure alertas no Grafana (ou Alertmanager) para disparar notificações quando a latência ultrapassar limites definidos.
  • CI/CD: inclua testes de performance que validem métricas básicas (ex.: tempo médio < 300 ms) antes de promover para produção.
  • Escalabilidade: ao escalar horizontalmente, garanta que cada instância exponha seu próprio endpoint /metrics; o Prometheus agregará automaticamente.

Conclusão

Implementar observabilidade com OpenTelemetry, Prometheus e Grafana em uma aplicação Node.js não precisa ser complexo. Com poucos arquivos de configuração, você ganha visibilidade completa sobre métricas, traces e, futuramente, logs. Essa camada de insight reduz o MTTR (Mean Time to Recovery), melhora a experiência do usuário e fornece dados valiosos para otimizações de performance.

Próximos passos recomendados:

  1. Adicionar tracing: exporte spans para o Jaeger ou Tempo e correlacione com os dashboards Grafana.
  2. Integrar ao GitHub Actions: execute docker-compose up em pipelines de teste para validar a coleta de métricas.
  3. Explorar OpenTelemetry Collector: centralize dados de múltiplas aplicações e envie para destinos como Loki, Datadog ou Splunk.

A observabilidade está se tornando o novo “monitoramento”. Comece hoje, experimente os exemplos acima e evolua seu stack conforme a necessidade do negócio.

Tecnologia e Negócios

Carregando comentários...