Saltar al contenido principal
55 min de lectura1 de septiembre de 2026
MonitoreoObservabilidadPrometheusGrafanaDevOps

Requisitos previos

  • docker
  • kubernetes

Lo que aprenderás

  • Entender los tres pilares de la observabilidad: métricas, logs y trazas
  • Configurar Prometheus para recolectar métricas de aplicaciones y infraestructura
  • Crear dashboards en Grafana con paneles y alertas visuales
  • Centralizar logs con Loki y Grafana
  • Instrumentar aplicaciones con OpenTelemetry para trazas distribuidas
Tutorial55 min

Monitoreo y observabilidad

Observabilidad es la capacidad de entender el estado interno de un sistema a partir de sus salidas externas. Un sistema observable te dice qué falla y por qué, sin necesidad de desplegar código nuevo. Este tutorial recorre las tres pilares — métricas, logs y trazas — con las herramientas más usadas en producción.


Pilares de la observabilidad

Toda estrategia de observabilidad se apoya en tres tipos de datos que responden a preguntas distintas. Juntos forman una imagen completa del comportamiento de tu sistema.

Métricas

Las métricas son valores numéricos agregados a lo largo del tiempo: requests_por_segundo, latencia_p99, errores_5xx. Son ligeras, baratas de almacenar y ideales para alertas y dashboards. No te dicen qué pasó con una petición concreta, pero sí cuántas están fallando y si la latencia sube.

Logs

Los logs son eventos discretos con contexto: cada línea describe qué ocurrió en un momento dado. Son la fuente más rica de detalle — un log puede incluir el ID de usuario, el endpoint y el tiempo de ejecución — pero también la más pesada. Sin centralización, buscar en logs de diez servidores es inviable.

Trazas distribuidas

Una traza sigue una petición desde que entra al sistema hasta que sale, cruzando servicios, colas de mensajes y bases de datos. Cada paso se llama span y contiene duración, metadatos y el ID de la traza padre. Las trazas son la única pista fiable para diagnosticar cuellos de botella en arquitecturas microservicio.

Métricas, logs y trazas no compiten — se complementan. Las métricas te dicen cuántos errores hay, los logs te dicen qué falla, y las trazas te dicen dónde se origina el problema. Empezar por las tres es el camino más seguro.

Métricas con Prometheus

Prometheus es el estándar de facto para métricas en entornos containerizados. Usa un modelo de pull: cada servicio expone un endpoint /metrics y Prometheus lo raspa cada cierto intervalo.

Instalación con Docker

Ejecuta Prometheus con Docker y un archivo de configuración que le diga qué servicios raspar:

# prometheus.yml
global:
  scrape_interval: 15s        # cada cuánto raspa targets
  evaluation_interval: 15s    # cada cuánto evalúa reglas

scrape_configs:
  - job_name: "node-app"
    static_configs:
      - targets: ["host.docker.internal:3000"]  # tu app Node.js
    metrics_path: "/metrics"
# Arrancar Prometheus
docker run -d --name prometheus \
  -p 9090:9090 \
  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

# Verificar que raspa correctamente
curl http://localhost:9090/api/v1/targets

Fundamentos de PromQL

PromQL es el lenguaje de consulta de Prometheus. Permite filtrar, agregar y transformar métricas en tiempo real.

# Tasa de peticiones por segundo (últimos 5 min)
rate(http_requests_total[5m])

# Percentil 99 de latencia
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# Errores 5xx agrupados por servicio
sum by (service) (
  rate(http_requests_total{status=~"5.."}[5m])
)

# Disponibilidad: peticiones exitosas / total
sum(rate(http_requests_total{status!~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))

Exponer métricas en Node.js

La librería prom-client expone métricas automáticamente y crea el endpoint /metrics:

import express from "express";
import { register, Counter, Histogram } from "prom-client";

const app = express();

const httpRequests = new Counter({
  name: "http_requests_total",
  help: "Total de peticiones HTTP",
  labelNames: ["method", "route", "status"],
});

const httpDuration = new Histogram({
  name: "http_request_duration_seconds",
  help: "Duración de peticiones HTTP en segundos",
  labelNames: ["method", "route"],
  buckets: [0.01, 0.05, 0.1, 0.5, 1, 2, 5],
});

app.use((req, res, next) => {
  const end = httpDuration.startTimer({ method: req.method, route: req.path });
  res.on("finish", () => {
    end();
    httpRequests.inc({
      method: req.method,
      route: req.path,
      status: res.statusCode,
    });
  });
  next();
});

app.get("/metrics", async (_req, res) => {
  res.set("Content-Type", register.contentType);
  res.end(await register.metrics());
});

app.listen(3000);
Usa rate() para contadores y histogram_quantile() para histograms. No uses increase() en dashboards de tiempo real: rate() suaviza mejor los picos.

Dashboards con Grafana

Grafana conecta Prometheus como fuente de datos y te permite construir paneles visuales — gráficos, estadísticas y tablas — que actualizan en tiempo real.

Instalación con Docker

# Añadir Grafana al docker-compose
services:
  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  grafana-data:

Añadir Prometheus como fuente

En Grafana ve a Configuration → Data Sources → Add data source y selecciona Prometheus. La URL será http://prometheus:9090 si usas Docker Compose.

Crear paneles

Grafana ofrece tres tipos de panel principales:

Graph:.series temporales — ideal para latencia, tasa de errores y throughput. Usa PromQL como query.

Stat:un solo valor grande con color condicional — útil para mostrar disponibilidad actual o peticiones activas.

Table:datos tabulares — perfecto para el top 5 de endpoints con mayor latencia.

# Ejemplo de PromQL para panel Graph — latencia P99
histogram_quantile(0.99,
  sum by (le) (
    rate(http_request_duration_seconds_bucket[5m])
  )
)

# Ejemplo para panel Stat — disponibilidad actual
1 - (
  sum(rate(http_requests_total{status=~"5.."}[5m]))
  /
  sum(rate(http_requests_total[5m]))
)

Variables para filtrar por servicio

Las variables permiten crear dashboards reutilizables. En Grafana ve a Dashboard Settings → Variables → New y crea una variable service con la query label_values(http_requests_total, service). Después usa $service en tus queries para filtrar.

Grafana tiene miles de dashboards comunitarios en grafana.com/grafana/dashboards. Importa el ID del dashboard y ajusta las variables de tu entorno. Es la forma más rápida de empezar sin construir todo desde cero.

Logging con Loki

Loki es el complemento de Prometheus para logs. No indexa el contenido completo de cada línea — solo las etiquetas — lo que lo hace mucho más ligero que Elasticsearch. Se integra directamente con Grafana.

Logging centralizado vs archivos sueltos

En un solo contenedor puedes leer logs con docker logs. Pero cuando tienes múltiples servicios o réplicas, necesitas centralizar: recopilar logs de todos los contenedores en un solo lugar, buscarlos y alertar sobre ellos. Eso es lo que hace Loki con Promtail.

Docker Compose con Loki + Promtail

services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"
    volumes:
      - loki-data:/loki

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - ./promtail-config.yml:/etc/promtail/config.yml
    command: -config.file=/etc/promtail/config.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    volumes:
      - grafana-data:/var/lib/grafana

volumes:
  loki-data:
  grafana-data:
# promtail-config.yml
server:
  http_listen_port: 9080

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: docker
    docker_sd_configs:
      - host: unix:///var/run/docker.sock
    relabel_configs:
      - source_labels: ["__meta_docker_container_name"]
        target_label: "container"

Consultas con LogQL

LogQL se parece a PromQL. Filtras por etiquetas y luego aplicas operadores de texto:

# Todos los logs del contenedor "api"
{container="api"}

# Logs que contienen "error"
{container="api"} |= "error"

# Logs de errores 5xx en los últimos 5 min
{container="api"} |~ "5[0-9]{2}" [5m]

# Conteo de errores por minuto
rate({container="api"} |= "error" [1m])
Loki indexa etiquetas (como container o service), no el contenido de los logs. Usar demasiadas etiquetas de alta cardinalidad (como IDs de usuario) puede degradar el rendimiento. Mantén las etiquetas bajas y usa filtros de texto para el contenido.

Trazas distribuidas con OpenTelemetry

OpenTelemetry (OTel) es el estándar de la CNCF para telemetría. Provee APIs unificadas para métricas, logs y trazas, con SDKs para la mayoría de lenguajes y un Collector que recibe, procesa y exporta datos a múltiples backends.

Qué son traces, spans y context propagation

Una trace representa el recorrido completo de una petición a través del sistema. Se compone de spans, cada uno representando una unidad de trabajo — una llamada HTTP, una query a la base de datos, una operación en cola. Cada span tiene un traceId, un spanId, un padre opcional, timestamps y atributos.

La context propagation es el mecanismo que transporta el ID de traza entre servicios. Cuando tu API llama a otro microservicio, el SDK OTel inyecta headers HTTP (traceparent) para que el siguiente servicio cree un span hijo en la misma traza.

Instalar el OTel Collector

# Añadir al docker-compose
services:
  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    command: ["--config=/etc/otelcol/config.yml"]
    volumes:
      - ./otel-config.yml:/etc/otelcol/config.yml
    ports:
      - "4317:4317"   # OTLP gRPC
      - "4318:4318"   # OTLP HTTP
      - "8888:8888"   # Métricas del propio collector

volumes:
  loki-data:
  grafana-data:
# otel-config.yml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    timeout: 5s
    send_batch_size: 1024

exporters:
  jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [jaeger]

Instrumentar una app Node.js

import { NodeSDK } from "@opentelemetry/sdk-node";
import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node";
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: "http://otel-collector:4317",
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start();

// Tu app Express/Koa/Fastify se instrumenta automáticamente
// Los spans se crean para cada request HTTP, query SQL, etc.

Con las auto-instrumentaciones, cada petición HTTP entrante y saliente, cada query a base de datos y cada llamada a cola se convierte en un span automáticamente, sin que modifiques tu código de negocio.

Ver trazas en Jaeger UI

Jaeger es un backend de trazas que visualiza las trazas recogidas por el Collector. Añádelo al compose y accede a la UI en http://localhost:16686:

# Añadir Jaeger al docker-compose
services:
  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"   # UI
      - "14250:14250"   # gRPC

  otel-collector:
    image: otel/opentelemetry-collector-contrib:latest
    command: ["--config=/etc/otelcol/config.yml"]
    volumes:
      - ./otel-config.yml:/etc/otelcol/config.yml
    ports:
      - "4317:4317"
      - "4318:4318"
    depends_on:
      - jaeger

En Jaeger UI selecciona tu servicio, busca trazas por duración o etiqueta, y explora el grafo de spans: verás exactamente cuánto tarda cada paso y dónde se acumula la latencia.

No necesitas instalar las tres herramientas de golpe. Empieza por las métricas (Prometheus + Grafana) — son las más baratas de operar y las que más valor dan al principio. Cuando tengas alerts funcionando, añade logs (Loki) y después trazas (OTel + Jaeger). Cada pilar se integra con los anteriores en Grafana.

Observabilidad no es un lujo — es una inversión que reduce el tiempo de resolución de incidentes de horas a minutos. Con Prometheus, Grafana, Loki y OpenTelemetry tienes un stack completo y gratuito que escala desde un portátil hasta un cluster de producción. La clave está en empezar poco a poco y construir la cultura de observabilidad en tu equipo.

Siguiente lección

Infraestructura como código con Terraform

Domina Terraform: declarativo vs imperativo, HCL, providers, recursos y data sources, variables y outputs, módulos reutilizables, remote state y despliegue CI/CD de infraestructura.