Guía de despliegue

Grafana Tempo y OpenTelemetry: trazado distribuido en VPS

Desplegar en un VPS Cloud →

Tutorial

Grafana Tempo y OpenTelemetry: trazado distribuido en VPS

Seguridad y monitorización12 min de lectura7 pasos

Seguir una petición a través de múltiples servicios sin una herramienta de trazado significa revisar miles de líneas de logs manualmente. OpenTelemetry y Grafana Tempo forman un dúo open-source que convierte esa investigación en unos pocos clics. Esta guía explica cómo desplegar el stack completo en un VPS, instrumentar tus aplicaciones y usar TraceQL para diagnosticar problemas de latencia.

Contenido· Por qué elegir OpenTelemetry frente a un agente propietario1/12
  1. 01Por qué elegir OpenTelemetry frente a un agente propietario
  2. 02Lo que te da el stack OTel + Grafana Tempo
  3. 03Requisitos previos del VPS
  4. 04Arquitectura del stack: del span a la visualización
  5. 05Desplegar el stack OTel + Tempo en siete pasos
  6. 06Configurar la retención y el almacenamiento de trazas
  7. 07Instrumentar una aplicación Node.js
  8. 08Instrumentar una aplicación Python
  9. 09OTel + Tempo vs Jaeger vs Zipkin vs Datadog APM
  10. 10Alertas y SLOs en Grafana
  11. 11Combinar trazas, logs y métricas en un solo Collector
  12. 12Resolver problemas comunes

Por qué elegir OpenTelemetry frente a un agente propietario

OpenTelemetry es un proyecto graduado de CNCF que unifica los tres pilares de la observabilidad — trazas, métricas y logs — bajo un estándar neutral al proveedor. A diferencia de los agentes Datadog o New Relic que te encierran en un contrato y formato propietario, el OTel Collector recibe, transforma y exporta la telemetría a cualquier backend compatible. Puedes cambiar de almacenamiento sin tocar una sola línea de tu código.

Los SDKs cubren Node.js, Python, Go, Java, PHP, Ruby y la mayoría de los lenguajes modernos. Los propagadores de contexto W3C TraceContext y B3 están incluidos: transmiten automáticamente el trace-id entre tus microservicios vía headers HTTP, sin configuración adicional.

Lo que te da el stack OTel + Grafana Tempo

  • Trazado distribuido sin índice externo — Grafana Tempo v2.x almacena las trazas en bloques comprimidos (parquet) en disco local o almacenamiento de objetos, sin Cassandra ni Elasticsearch.
  • Consultas TraceQL — el lenguaje nativo de Tempo permite filtrar trazas por duración, servicio, estado de error o atributos personalizados en segundos.
  • Compatibilidad multi-protocolo — Tempo acepta OTLP, Zipkin y Jaeger: tus aplicaciones existentes se conectan sin reinstrumentación completa.
  • Stack ligero en VPS — 2 GB de RAM son suficientes para un entorno de dev o staging; en producción bajo carga, 4 GB proporcionan margen cómodo.
  • Coste controlado — un VPS autohospedado desde 99 DH/mes reemplaza una suscripción a Datadog APM facturada a unos 23 $ por host y mes.
  • Correlación trazas–logs–métricas — vinculando Tempo con Loki y Prometheus en Grafana, saltas de una traza a sus logs y métricas en un solo clic.
  • Sin vendor lock-in — si migras a Jaeger mañana, reconfiguras un exportador en el Collector; tus SDKs y código no cambian.

Requisitos previos del VPS

Tu VPS necesita al menos 2 GB de RAM (4 GB recomendados en producción) y acceso root o sudo. Docker Engine ≥ 24 y Docker Compose v2 deben estar instalados.

Planifica un subdominio dedicado — por ejemplo grafana.tu-dominio.com — para exponer la interfaz Grafana detrás de un proxy inverso TLS. Los puertos 4317 (OTLP/gRPC) y 4318 (OTLP/HTTP) deben estar abiertos en tu firewall en el lado privado para recibir telemetría desde tus aplicaciones; no los expongas en la interfaz pública. Los puertos 3200 (Tempo) y 3000 (Grafana) permanecen internos a la red Docker.

Planifica al menos 10 GB libres para los bloques de trazas. El montaje por defecto en /tmp/tempo no sobrevive a los reinicios: reemplázalo con un volumen Docker o un disco dedicado antes de ir a producción.

Arquitectura del stack: del span a la visualización

El flujo de datos sigue cuatro pasos:

1. Tu aplicación instrumenta sus peticiones con un SDK OTel y exporta spans al OTel Collector (OTLP gRPC puerto 4317 o HTTP puerto 4318).
2. El OTel Collector recibe, agrupa en lotes y exporta a Tempo vía OTLP gRPC interno. Puede enviar simultáneamente métricas a Prometheus y logs a Loki.
3. Grafana Tempo almacena bloques de trazas comprimidos en disco (o S3). Expone una API TraceQL en el puerto 3200.
4. Grafana consulta Tempo con TraceQL, muestra flamegraphs, grafos de servicios y span metrics.

TraceQL es el lenguaje de consulta nativo de Tempo: {service.name="api" && status=error && duration>500ms}.

Span Metrics es un pipeline de Tempo que deriva automáticamente métricas RED de las trazas entrantes, sin añadir un solo contador a tu código.

Desplegar el stack OTel + Tempo en siete pasos

  1. Crear la estructura de directorios

    Organiza una carpeta otel-stack/ en tu VPS:

    mkdir -p otel-stack/config
    cd otel-stack

    Colocarás aquí tres archivos de configuración: tempo.yaml, otel-collector-config.yaml y docker-compose.yml.

  2. Escribir la configuración de Tempo (tempo.yaml)

    Crea config/tempo.yaml con backend de almacenamiento local y soporte TraceQL:

    server:
      http_listen_port: 3200
    
    distributor:
      receivers:
        otlp:
          protocols:
            grpc:
              endpoint: 0.0.0.0:4317
    
    ingester:
      max_block_bytes: 1_000_000
      max_block_duration: 5m
    
    compactor:
      compaction:
        block_retention: 168h   # 7 días
    
    storage:
      trace:
        backend: local
        wal:
          path: /tmp/tempo/wal
        local:
          path: /tmp/tempo/blocks
  3. Escribir la configuración del OTel Collector

    Crea config/otel-collector-config.yaml:

    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    
    processors:
      batch:
        timeout: 5s
        send_batch_size: 1000
    
    exporters:
      otlp:
        endpoint: tempo:4317
        tls:
          insecure: true
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlp]
  4. Escribir el docker-compose.yml

    Crea docker-compose.yml en la raíz de otel-stack/:

    services:
      otel-collector:
        image: otel/opentelemetry-collector-contrib:latest
        volumes:
          - ./config/otel-collector-config.yaml:/etc/otelcol-contrib/config.yaml
        ports:
          - "4317:4317"
          - "4318:4318"
        networks:
          - observability
        depends_on:
          - tempo
    
      tempo:
        image: grafana/tempo:latest
        command: ["-config.file=/etc/tempo.yaml"]
        volumes:
          - ./config/tempo.yaml:/etc/tempo.yaml
          - tempo-data:/tmp/tempo
        ports:
          - "3200:3200"
        networks:
          - observability
    
      grafana:
        image: grafana/grafana:latest
        ports:
          - "3000:3000"
        environment:
          - GF_AUTH_ANONYMOUS_ENABLED=true
          - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
        networks:
          - observability
        depends_on:
          - tempo
    
    volumes:
      tempo-data:
    
    networks:
      observability:

    Inicia el stack: docker compose up -d y verifica: docker compose ps.

  5. Configurar Grafana Tempo como fuente de datos

    Abre Grafana en http://tu-vps:3000. Ve a Connections → Data sources → Add data source y selecciona Tempo. Establece la URL a http://tempo:3200. Activa Service graph y Span metrics. Si tu stack incluye Loki, vincula ambas fuentes de datos para navegar de un span a sus logs en un clic.

  6. Enviar tu primera traza de prueba

    Prueba que el stack recibe trazas con telemetrygen:

    docker run --rm --network otel-stack_observability \
      ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:latest \
      traces \
      --otlp-endpoint otel-collector:4317 \
      --otlp-insecure \
      --duration 5s \
      --rate 10

    En Grafana, abre Explore, selecciona la fuente de datos Tempo y ejecuta la consulta {} para ver todas las trazas recibidas.

  7. Consultar tus trazas con TraceQL

    En el panel Explore de Grafana (fuente de datos Tempo), introduce una consulta TraceQL:

    - {service.name="mi-api"} — todas las trazas del servicio
    - {status=error} — todas las trazas con error
    - {duration>1s && service.name="mi-api"} — trazas lentas
    - {span.http.route="/api/orders" && status=error} — errores en una ruta concreta

    Haz clic en una traza para abrir el flamegraph detallado.

Configurar la retención y el almacenamiento de trazas

Tempo ofrece dos opciones principales de almacenamiento.

Almacenamiento local en volumen Docker: recomendado para un VPS standalone. Ajusta block_retention en tempo.yaml: 72 h para staging, 168 a 720 h para producción. Cada hora de trazas comprimidas ocupa aproximadamente 100–300 MB.

Almacenamiento de objetos compatible con S3: para un stack multi-nodo o almacenamiento ilimitado. Tempo es compatible con AWS S3, MinIO, Scaleway Object Storage y cualquier backend con API S3. La WAL siempre permanece en disco local para garantizar la durabilidad de las trazas en vuelo.

El compactor de Tempo fusiona bloques pequeños y aplica la política de retención automáticamente cada 5 minutos.

Instrumentar una aplicación Node.js

La auto-instrumentación OTel para Node.js captura automáticamente llamadas HTTP salientes, peticiones Express/Fastify, consultas a bases de datos y más, sin modificar tu lógica de negocio.

Instala los paquetes:

npm install @opentelemetry/sdk-node \
             @opentelemetry/auto-instrumentations-node \
             @opentelemetry/exporter-trace-otlp-grpc

Crea tracing.js:

const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'grpc://localhost:4317',
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

Inicia tu aplicación:

export OTEL_SERVICE_NAME=mi-api
export OTEL_EXPORTER_OTLP_ENDPOINT=http://tu-vps:4317
node --require ./tracing.js app.js

Instrumentar una aplicación Python

Instala y bootstrap:

pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install

Inicia tu aplicación:

export OTEL_SERVICE_NAME=mi-servicio-python
export OTEL_EXPORTER_OTLP_ENDPOINT=http://tu-vps:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
opentelemetry-instrument python app.py

Django, Flask, FastAPI, SQLAlchemy y los clientes HTTP se instrumentan automáticamente. Para instrumentación manual:

from opentelemetry import trace
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("procesar-pedido") as span:
    span.set_attribute("pedido.id", pedido_id)

OTel + Tempo vs Jaeger vs Zipkin vs Datadog APM

Desplace la tabla

CriterioOTel + Grafana TempoJaegerDatadog APM
Coste mensualSolo alojamiento (99 DH/mes VPS)Solo alojamiento (similar)~23 $ por host al mes
Backend de almacenamientoLocal, S3, GCS, Azure BlobCassandra, Elasticsearch, BadgerSaaS gestionado (opaco)
Lenguaje de consultaTraceQL (nativo, potente)Jaeger Query UI (básico)Lenguaje propietario Datadog
Auto-instrumentaciónSDK OTel universalLibrerías Jaeger o OTelAgente propietario Datadog
Correlación trazas–logsSí (Loki + Grafana)LimitadaSí (integrado, de pago)
Span Metrics (RED)Sí (pipeline nativo Tempo)No nativoSí (calculado por Datadog)
Vendor lock-inNinguno (estándar CNCF)Bajo (compatible OTel)Alto (agente y formato propietarios)
Complejidad de instalaciónMedia (3 contenedores)Baja a mediaBaja (agente automático)

Alertas y SLOs en Grafana

Grafana 10+ permite definir alertas directamente sobre métricas derivadas de trazas. Las Span Metrics de Tempo generan automáticamente tres métricas por servicio: tasa de peticiones, histograma de latencia y contador de errores.

Para crear un SLO sobre la tasa de error de tu API, ve a Alerting → Alert rules → New alert rule en Grafana, elige la fuente de datos Prometheus e introduce una consulta que calcule la proporción de errores. Define el umbral (por ejemplo > 0.05 para una tasa de error superior al 5%) y la ventana de evaluación. Configura un punto de contacto: Alertmanager, PagerDuty, Slack o webhook. Las alertas basadas en trazas son mucho más precisas que las alertas sobre métricas sintéticas.

Combinar trazas, logs y métricas en un solo Collector

El OTel Collector no se limita a las trazas. Añadiendo un filelog receiver recoges los logs de tus contenedores Docker y los envías a Loki. Un prometheus receiver hace scraping de tus endpoints /metrics y los exporta a Prometheus. Un solo proceso gestiona toda la telemetría de tu VPS.

En Grafana, vincula Tempo y Loki mediante derived fields: cuando un log contiene un trace_id, un enlace clicable te lleva directamente al flamegraph correspondiente. Esta navegación cruzada reduce considerablemente el tiempo de diagnóstico.

Resolver problemas comunes

No llegan spans a Tempo. Comprueba primero que el OTel Collector es accesible desde tu aplicación (telnet tu-vps 4317). Revisa los logs del Collector: un error connection refused en tempo:4317 indica que Tempo no ha arrancado o su puerto interno no está expuesto en la red Docker.

Conexión rechazada desde la aplicación al Collector. En UFW o firewalld, permite los puertos 4317 y 4318 solo para las IPs de tus aplicaciones. En producción, aplicaciones y Collector deben estar en la misma red privada.

Trazas truncadas o spans faltantes. El batch processor puede tardar hasta 5 s en enviar. Para desarrollo, reduce timeout: 1s. Si los spans faltan sistemáticamente, verifica que el propagador de contexto W3CTraceContextPropagator está activo en tu SDK.

Tempo consume demasiado espacio en disco. Reduce block_retention y reinicia Tempo. El compactor aplicará la nueva política en el siguiente ciclo.

Grafana no encuentra trazas desde los logs de Loki. Verifica que tus aplicaciones inyectan trace_id en sus logs y que el campo Derived fields en la fuente de datos Loki apunta al patrón correcto.

Aloja tu stack de observabilidad en un VPS

Desde 99 DH/mes — acceso root completo, almacenamiento SSD, sin ataduras a proveedor.

¿Necesita ayuda?

Consulte nuestro centro de ayuda y nuestra FAQ, o contacte con nuestro equipo: llamada, WhatsApp o correo electrónico. Soporte en francés, inglés y árabe.

Escribir por WhatsAppse abre en una pestaña nueva