Instrumentar una aplicación JavaScript con OpenTelemetry
OpenTelemetry (OTel) es un framework de observabilidad de código abierto que proporciona un conjunto de APIs, SDKs y herramientas para recopilar datos de telemetría, como métricas, registros (logs) y trazas de aplicaciones. Con OpenTelemetry, los desarrolladores pueden obtener información valiosa sobre cómo rinden sus servicios en producción o durante el desarrollo local.
Un componente clave de OpenTelemetry es el OpenTelemetry Protocol (OTLP), un protocolo de propósito general e independiente del proveedor diseñado para transmitir datos de telemetría de manera eficiente y confiable. OTLP admite múltiples tipos de datos (trazas, métricas, logs) a través de HTTP o gRPC, lo que lo convierte en el protocolo predeterminado y recomendado para la comunicación entre aplicaciones instrumentadas, el OpenTelemetry Collector y backends como Jaeger o Prometheus.
Esta guía te acompaña en el proceso de instrumentar una aplicación Node.js simple con OpenTelemetry y ejecutar tanto la aplicación como un recolector usando Docker. Esta configuración es ideal para el desarrollo local y para probar la observabilidad antes de integrarla con plataformas de observabilidad externas como Prometheus, Jaeger o Grafana.
En esta guía, aprenderás a:
- Configurar OpenTelemetry en una aplicación Node.js.
- Ejecutar un OpenTelemetry Collector en Docker.
- Visualizar trazas con Jaeger.
- Usar Docker Compose para administrar la pila completa de observabilidad.
Uso de OpenTelemetry con Docker
La imagen oficial de Docker para OpenTelemetry proporciona una forma conveniente de desplegar y administrar instancias de Dex. OpenTelemetry está disponible para varias arquitecturas de CPU, incluidas amd64, armv7 y arm64, lo que garantiza la compatibilidad con diferentes dispositivos y plataformas. Lo mismo aplica para la imagen Docker de Jaeger.
Requisitos previos
Docker Compose: Recomendado para administrar aplicaciones Docker de múltiples contenedores.
Conocimiento básico de Node.js y Docker.
Estructura del proyecto
Crea el directorio del proyecto:
mkdir otel-js-app
cd otel-js-appotel-js-app/
├── docker-compose.yaml
├── collector-config.yaml
├── app/
│ ├── package.json
│ ├── app.js
│ └── tracer.jsCrear una aplicación Node.js simple
Inicializa una aplicación Node.js básica:
mkdir app && cd app
npm init -y
npm install express @opentelemetry/api @opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-httpAhora, agrega la lógica de la aplicación:
// app/app.js
const express = require('express');
require('./tracer'); // Inicializa OpenTelemetry
const app = express();
app.get('/', (req, res) => {
res.send('Hello from OpenTelemetry demo app!');
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`App listening at http://localhost:${PORT}`);
});Configurar el rastreo (tracing) con OpenTelemetry
Crea el archivo de configuración del rastreador (tracer):
// app/tracer.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({
url: 'http://collector:4318/v1/traces',
}),
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();Configurar el OpenTelemetry Collector
Crea un archivo collector-config.yaml en la raíz:
# collector-config.yaml
receivers:
otlp:
protocols:
http:
exporters:
logging:
loglevel: debug
jaeger:
endpoint: jaeger:14250
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
exporters: [logging, jaeger]Agregar la configuración de Docker Compose
Crea el archivo docker-compose.yaml:
version: '3.9'
services:
app:
build: ./app
ports:
- "3000:3000"
environment:
- NODE_ENV=development
depends_on:
- collector
collector:
image: otel/opentelemetry-collector:latest
volumes:
- ./collector-config.yaml:/etc/otelcol/config.yaml
command: ["--config=/etc/otelcol/config.yaml"]
ports:
- "4318:4318" # OTLP
jaeger:
image: jaegertracing/all-in-one:latest
ports:
- "16686:16686" # UI
- "14250:14250" # Recolector gRPCAhora, agrega el Dockerfile dentro de la carpeta app/:
# app/Dockerfile
FROM node:18
WORKDIR /usr/src/app
COPY . .
RUN npm install
CMD ["node", "app.js"]Iniciar la pila
Inicia todos los servicios con Docker Compose:
docker compose up --buildUna vez que los servicios estén en ejecución:
Visita tu aplicación en http://localhost:3000
Verifica las trazas en http://localhost:16686 en la interfaz de usuario de Jaeger
Verificar trazas en Jaeger
Después de visitar el endpoint raíz de tu aplicación, abre la interfaz de usuario de Jaeger, busca el servicio (el valor predeterminado suele ser unknown_service a menos que se nombre explícitamente) y comprueba las trazas.
Deberías ver spans para la solicitud HTTP, el middleware y las bibliotecas autoinstrumentadas.
Conclusión
Ahora tienes una configuración de OpenTelemetry completamente funcional utilizando Docker Compose. Has instrumentado una aplicación JavaScript básica para exportar trazas y las has visualizado usando Jaeger. Esta arquitectura se puede extender para aplicaciones más complejas y canales de observabilidad utilizando Prometheus, Grafana o exportadores nativos de la nube.
Para temas avanzados como la creación de spans personalizados, métricas y registros (logs), consulta la documentación de OpenTelemetry para JavaScript.