Stack de observabilidad homelab: Grafana + Loki + Prometheus + OTEL (part-03)

22 June, 2026 | homelab

Serie Homelab Agentic · Parte 2/13 — Del bare metal al agente conversacional. Ver todos los posts

TL;DR

Los agentes de IA son tan buenos como los datos que consultan. Si tu infra no tiene buena observabilidad, tus agentes van a responder con confianza y con datos malos — que es peor que no responder. En este post armo el pipeline completo: OpenTelemetry Alloy como collector, Prometheus para métricas, Loki para logs, Grafana para visualización, ntfy para alertas, y Langfuse para el tracing específico de LLMs. Este stack es la fundación. Sin él, el resto de la serie no existe.

¿Podés operar algo que no podés ver?

Técnicamente sí. Podés tener servidores corriendo, servicios respondiendo, y no tener ninguna visibilidad de métricas ni logs.

Funciona. Hasta que deja de funcionar.

El problema con operar sin observabilidad no es que las cosas fallen — es que cuando fallan, no sabés cuándo empezaron a fallar, no sabés qué cambió, y no tenés datos históricos para comparar el estado actual con el estado previo. Estás diagnosticando en modo forense, sin evidencia.

Tuve esa experiencia exacta en las primeras semanas del homelab. Un servicio empezó a comportarse raro. ¿Cuándo empezó? No sé. ¿Hubo un pico de CPU antes? No tengo registro. ¿Los logs dicen algo? ¿Cuáles logs, dónde?

Eso es manejar a ciegas. Funciona en recta. En una curva complicada, te vas a la banquina.

Pero acá viene el punto que va más allá del argumento tradicional de “necesitás observabilidad para operar bien” — y es el punto específico de esta serie:

Los agentes de IA consultan datos de tu infra. Si esos datos no existen, los agentes inventan. Si son malos, los agentes generalizan basura. Garbage in, garbage out, con lenguaje natural y aparente confianza.

La observabilidad no es opcional cuando ponés agentes encima. Es el prerequisito.

La arquitectura del pipeline

Antes de entrar en cada componente, el mapa completo:

Nodos Proxmox / Contenedores Docker / Aplicaciones
       |
       ↓ (métricas OTEL, logs, traces)
  Alloy (collector) 
       |
       ├──→ Prometheus (métricas) 
       ├──→ Loki (logs)
       └──→ Tempo (traces distribuidos)
                |
                ↓
         Grafana (visualización) 
                |
                ↓
    ntfy (alertas push) + Langfuse (tracing LLMs)

Cada flecha es un protocolo real, una conexión de red real. No es diagrama de PowerPoint aspiracional. Este pipeline corre ahora mismo en mi homelab mientras escribo esto.

OpenTelemetry: el estándar que no deberías ignorar

Empiezo por acá porque es donde más gente se traba: hay muchas formas de recolectar datos de una aplicación, y elegir el estándar correcto importa.

OpenTelemetry (OTEL) es el estándar de la Cloud Native Computing Foundation para instrumentación de observabilidad. Define cómo las aplicaciones reportan métricas, logs y traces de manera uniforme, independientemente del backend donde vayas a guardar esos datos.

La ventaja práctica es enorme: instrumentás tu aplicación una sola vez con OTEL, y después podés enviar esos datos a Prometheus, a Datadog, a Grafana Cloud, a lo que sea, simplemente cambiando la configuración del collector. No reescribís el código de instrumentación.

Para el homelab esto importa porque me da flexibilidad. Empecé con Prometheus + Loki. En el futuro podría agregar otro backend, o cambiar alguno, sin tocar las aplicaciones.

La alternativa más común es instrumentar directamente contra un backend específico (por ejemplo, usar el cliente de Prometheus directamente). Eso funciona pero te ata. OTEL es más trabajo inicial, más ganancia a largo plazo.

Alloy: el collector que reemplazó al stack clásico

Alloy es el componente menos conocido del stack y el que más preguntas genera cuando lo menciono.

La situación histórica: Grafana Labs tenía un agente llamado Grafana Agent para recolectar datos y enviarlos a su stack. Después decidieron unificar ese agente con el OpenTelemetry Collector en un solo binario más potente. Ese resultado es Alloy.

¿Por qué Alloy en vez de el OpenTelemetry Collector vanilla?

El OTel Collector vanilla es potente pero su configuración es más verbosa. Para casos simples, hay que escribir más YAML de lo que el problema justifica. Alloy tiene un lenguaje de configuración propio (River, basado en HCL) que es más expresivo para el tipo de pipelines que uso en homelab: scrape métricas de Prometheus, recolectar logs de Docker, enviar a múltiples destinos.

La configuración de Alloy también hace más fácil la autodescubrimiento de servicios: puede detectar automáticamente contenedores Docker nuevos y empezar a recolectar sus logs sin que yo cambie nada manualmente.

Un fragmento real de configuración Alloy para recolectar logs de Docker:

discovery.docker "containers" {
  host = "unix:///var/run/docker.sock"
}

loki.source.docker "default" {
  host    = "unix:///var/run/docker.sock"
  targets = discovery.docker.containers.targets

  forward_to = [loki.write.local.receiver]
}

loki.write "local" {
  endpoint {
    url = "http://192.168.100.73:3100/loki/api/v1/push"
  }
}


Eso es todo lo que necesitás para que Alloy recoja automáticamente los logs de todos los contenedores Docker del host y los envíe a Loki. Cuando creás un contenedor nuevo, Alloy lo detecta y empieza a recolectar sus logs sin intervención manual. Si eso no es conveniente, no sé qué lo es.

Prometheus: las métricas de tiempo real

Prometheus (192.168.100.73:9090) es el motor de métricas. Funciona con un modelo de pull — Prometheus va a buscar las métricas a cada target en un intervalo configurable, en vez de que los targets envíen datos a Prometheus.

En cada nodo del cluster Proxmox corre un Node Exporter — un proceso pequeño que expone métricas del sistema operativo en formato Prometheus: CPU, memoria, disco, red, temperatura. Prometheus hace scrape de todos esos endpoints cada 15 segundos.

También corro el cAdvisor de Google en los hosts que corren Docker, que expone métricas de cada contenedor: CPU por contenedor, memoria, I/O de red. Esto es fundamental para entender qué contenedores están consumiendo recursos.

La configuración de targets en Prometheus es straightforward:

scrape_configs:
  - job_name: 'node-exporter'
    static_configs:
      - targets:
          - '192.168.100.45:9100'   # proxmox-01
          - '192.168.100.62:9100'   # proxmox-02
    scrape_interval: 15s

  - job_name: 'cadvisor'
    static_configs:
      - targets:
          - '192.168.100.45:8080'
          - '192.168.100.62:8080'

Lo más valioso de Prometheus no es solo las métricas en tiempo real — es la retención histórica y las queries con PromQL. Cuando un agente me pregunta “¿cómo estuvo el uso de CPU del cluster en las últimas 4 horas?”, Prometheus puede responder esa pregunta con datos reales, no con una estimación.

Loki: los logs que antes perdías

Loki es el sistema de logs del stack Grafana. La diferencia con Elasticsearch (el otro jugador clásico en este espacio) es fundamental: Loki no indexa el contenido de los logs, solo indexa las etiquetas (labels). Esto lo hace mucho más eficiente en almacenamiento y más rápido de operar para homelabs donde no tenés un equipo dedicado a gestionar el cluster de búsqueda.

Lo que indexa Loki por default con la config de Docker que mostré arriba: el nombre del contenedor, la imagen, el host de origen. Podés buscar “todos los logs del contenedor llamado grafana del último día” instantáneamente. Para el caso de homelab, eso cubre el 95% de las consultas.

El Agent-02 (Log Analyzer) usa Loki como fuente principal de datos para su análisis diario de logs. Tira queries a Loki, agrupa los errores, y produce el resumen de las 8am. Sin Loki, ese agente no tiene nada que analizar.

Grafana: el lugar donde todo se ve

Grafana (192.168.100.74:3000) es la interfaz de visualización que agrupa las tres fuentes de datos: Prometheus para métricas, Loki para logs, y Tempo para traces distribuidos.

Los dashboards más útiles que tengo configurados:

Cluster Overview: un dashboard con el estado de todos los nodos — CPU, memoria, disco, estado de la red. Es el primer lugar donde miro cuando algo parece raro. Un vistazo de 5 segundos me dice si el problema es de infra o de aplicación.

Container Metrics: métricas por contenedor Docker para todos los hosts. Útil para detectar contenedores que consumen más de lo esperado o que tienen memory leaks.

Log Explorer: un panel simple de Loki donde puedo hacer queries ad-hoc de logs. No un dashboard fijo, sino una herramienta de exploración.

Agent Activity: este dashboard lo agregué después de montar los agentes IA. Muestra cuántas llamadas LLM se hicieron, con qué latencia, y cuántos tokens se consumieron. Los datos vienen de Langfuse (más sobre eso en un segundo).

Una cosa que aprendí: los dashboards de Grafana tienen una curva de configuración no obvia. Hay una diferencia enorme entre “tengo Grafana instalado” y “tengo Grafana con paneles útiles configurados”. Es fácil pasar horas configurando paneles que después nunca usás. La regla que aplico: si no miro un panel al menos una vez por semana, lo saco.

ntfy: alertas que realmente llegás a ver

El sistema de alertas tiene que cumplir un requisito básico que parece obvio pero que es fácil de ignorar: tenés que verlas cuando importan.

Email no sirve — los emails de alerta terminan en una carpeta de notificaciones y los revisás cuando ya es tarde. Telegram funciona pero requiere configurar un bot. Slack requiere tener Slack abierto.

ntfy es una solución de push notifications self-hosteable que envía notificaciones al teléfono mediante la app ntfy. No requiere configurar un bot, no depende de que tengas alguna app de mensajería abierta. Simplemente llega como una notificación de sistema.

Los umbrales que configuré:

MétricaWarningCritical
RAM83%93%
CPU (5min avg)75%90%
Disco80%90%

El umbral de RAM en 83%/93% puede parecer alto, pero tiene lógica: el homelab corre varios servicios en memoria, y hay variaciones normales de uso. Poner el warning muy bajo genera fatiga de alertas — si la alerta llega todo el tiempo, dejás de hacerle caso. El 83% es un punto donde todavía tenés margen para actuar antes de que la cosa se ponga crítica.

Grafana tiene integración nativa con ntfy a través de webhooks. La configuración es simple: definís un contact point de tipo Webhook apuntando al endpoint de ntfy, y lo asociás a las alertas que querés.

Langfuse: el tracing que los LLMs necesitan y Prometheus no da

Acá viene algo que Prometheus y Loki no pueden hacer solos, y es específico del caso de agentes IA.

Los agentes hacen múltiples llamadas al LLM en el curso de responder una pregunta. Un agente ReAct típico puede hacer 5-10 llamadas encadenadas: primero razona, después llama una herramienta, procesa el resultado, razona de nuevo, llama otra herramienta, y así hasta llegar a la respuesta.

¿Cómo sabés si el agente está siendo eficiente? ¿Cuántos tokens usó? ¿Cuánto tardó cada llamada individual? ¿En qué punto del trace está el mayor bottleneck? ¿La llamada que tardó más fue la del LLM o la del MCP server que consulta Prometheus?

Prometheus no responde esas preguntas. Prometheus sabe de infraestructura. Langfuse sabe de LLMs.

Langfuse es una plataforma de observabilidad específica para LLMs. Lo corro self-hosted en el homelab. Captura cada llamada al LLM con su trace completo: el prompt exacto que se envió, la respuesta recibida, los tokens usados, la latencia, y el árbol de llamadas cuando hay múltiples LLMs involucrados.

En el Post 10 hay un post completo sobre Langfuse. Acá solo quiero plantar la idea: observabilidad de infraestructura y observabilidad de LLMs son cosas distintas y complementarias. Necesitás ambas si vas a correr agentes en producción (o en homelab-producción, que es lo que tengo).

El momento epifanía

Hubo un momento específico en que todo esto dejó de ser “infraestructura de observabilidad” y se convirtió en algo más interesante.

Tenía al Agent-01 (Infra Query) configurado para consultar Prometheus. Hice una pregunta en lenguaje natural: “¿Hay algún nodo del cluster con presión de memoria en este momento?”

El agente consultó Prometheus, procesó los datos, y respondió: “proxmox-01 está usando el 78% de la memoria RAM disponible. Los contenedores con mayor consumo son Grafana (1.2GB) y PostgreSQL (900MB). proxmox-02 está al 45%.”

No fue magia. Fue datos reales de Prometheus, procesados por un LLM, presentados en lenguaje natural. Pero la experiencia de recibir esa respuesta fue cualitativamente diferente a abrir Grafana y hacer el análisis manual.

Eso fue cuando entendí que el stack de observabilidad no es solo la base para los agentes. Es lo que hace que los agentes sean útiles.

Garbage in, garbage out. Pero con datos buenos, datos reales, datos con historia — los agentes hacen algo que vale la pena.

El stack completo, resumido

Para que te quede el mapa claro:

Componente IP Puerto Rol
Alloy 192.168.100.88 4317 (OTLP) Collector central
Prometheus 192.168.100.73 9090 Métricas de infra
Loki 192.168.100.73 3100 Logs
Grafana 192.168.100.74 3000 Visualización
ntfy self-hosted — Alertas push
Langfuse self-hosted — Tracing de LLMs

Todos estos servicios corren en contenedores Docker en el homelab. El compose file tiene sus propias historias (el bug de asyncio/anyio que casi me cuesta la cordura está en el Post 08, si te interesa sufrir conmigo).

Lo que sigue en la serie

Ahora tenés la base. Podés ver tu infra, tenés métricas históricas, tenés logs centralizados, tenés alertas que realmente llegan.

La siguiente pregunta es: ¿cómo hacés para que la IA también vea todo eso?

La respuesta es MCP — Model Context Protocol. Es el protocolo que le da acceso a herramientas reales a los LLMs. Y es donde la serie se pone interesante de verdad.

En el siguiente post explico qué es MCP, cómo funciona, y por qué es el componente que lo cambia todo.

Lo que sigue

← Anterior Por qué monté un homelab en 2025
Siguiente → Model Context Protocol: cómo la IA habla con tu infra

También en esta serie:

  • 8 servidores MCP corriendo en paralelo
  • Agente ReAct para consultas de infra
  • Langfuse: tracing para LLMs en producción
  • El bug de asyncio/anyio que me costó dos días

¿Te fue útil? Dejá un comentario o compartilo. Y si tenés dudas, encontrá el resto de la historia en la serie completa.