Imagina el tablero de un automóvil. Los indicadores (velocidad, régimen del motor, nivel de combustible) dan un valor numérico en cada instante: son las métricas. La caja negra, el registrador de eventos de un automóvil moderno, anota lo que pasó, línea por línea, con la hora exacta: son los logs (los registros). Los testigos luminosos (aceite, batería, motor) se encienden solos cuando un valor vigilado sale de su rango normal, sin que tengas que mirar cada indicador de forma permanente: son las alertas. El GPS, que reconstruye el trayecto completo que seguiste con el tiempo empleado en cada tramo, es una traza. Esta imagen vuelve a lo largo de todo el módulo: cada servicio del labo desempeña el papel de una de estas cuatro piezas.
| Pieza del tablero | Lo que representa | Servicio del labo que desempeña ese papel |
|---|---|---|
| Indicadores | Métricas | Prometheus (que lee node-exporter, cadvisor y la API) |
| Caja negra | Logs | Loki, alimentado por Alloy |
| Testigos luminosos | Alertas | Alertmanager, que avisa al webhook |
| GPS que reconstruye el trayecto | Trazas | Ninguno en este labo (se menciona en el módulo 7) |
| El parabrisas | Lo que miras tú | Grafana |
No se observa un sistema por gusto. Se observa porque un día algo se rompe, y hay que entender qué, dónde y desde cuándo, antes de que salga caro. Las tres fallas siguientes son públicas: cada empresa escribió y publicó por sí misma su propio post-mortem. Muestran lo que la observabilidad permite, y lo que no siempre permite al primer intento.
Cloudflare, 18 de noviembre de 2025: cuando las métricas solas no bastan. A las 11:20 UTC, la red de Cloudflare deja de enrutar correctamente una gran parte del tráfico mundial: los visitantes de los sitios de sus clientes reciben una página de error. La causa: un cambio de permisos en un clúster de base de datos ClickHouse duplica el tamaño de un archivo de configuración interno (el archivo de «características» del sistema anti-bots), que supera un límite fijado en el código y hace caer el proxy central. Las métricas de errores HTTP 5xx son visibles desde el primer minuto, en un pico nítido sobre un gráfico. Pero el archivo solo se generaba de forma defectuosa de manera intermitente, en una parte del clúster: el tráfico se recuperaba y volvía a caer cada cinco minutos. Esa fluctuación hizo creer primero al equipo que se trataba de un ataque de denegación de servicio, no de una falla interna. Hubo que cruzar las métricas con los logs del módulo anti-bots para identificar la verdadera causa. El tráfico principal se restablece a las 14:30, todos los sistemas vuelven a la normalidad a las 17:06: casi 5 horas y 46 minutos entre el inicio y el final completo del incidente. Fuente oficial: Cloudflare outage on November 18, 2025.
AWS S3, 28 de febrero de 2017: cuando la herramienta de supervisión depende del sistema que vigila. A las 9:37 (hora del Pacífico), un ingeniero de Amazon S3 ejecuta un comando de mantenimiento que debía retirar algunos servidores de un subsistema de facturación, en la región Virginia del Norte (us-east-1). Un error de tipeo retira una cantidad de servidores mucho mayor que la prevista y tumba dos subsistemas críticos de S3: el índice (los metadatos y la ubicación de los objetos) y el placement (la asignación del nuevo almacenamiento). S3 queda incapaz de procesar las solicitudes GET, LIST, PUT y DELETE, y con él caen los nuevos arranques de instancias EC2, EBS, Lambda, y el propio tablero oficial de estado de AWS, que dependía de S3 para actualizarse. AWS tuvo que comunicar el estado de la falla en su cuenta de Twitter. El índice queda plenamente restablecido a las 13:18, el placement a las 13:54: alrededor de 4 horas y 17 minutos entre el inicio del incidente y la vuelta a la normalidad. Fuente oficial: Summary of the Amazon S3 Service Disruption in the Northern Virginia (US-EAST-1) Region.
GitHub, 14 de agosto de 2024: cuando la supervisión misma provoca la falla. A las 22:59 UTC, GitHub despliega un cambio de configuración en sus bases de datos. Ese cambio rompe la capacidad de esas bases de responder correctamente a las pruebas de salud (health checks) enviadas por la capa de enrutamiento. Al no recibir ya una respuesta válida, la capa de enrutamiento declara esas bases «en mal estado» y retira el acceso en lectura: GitHub.com queda inaccesible para todos los usuarios de 23:02 a 23:38 UTC, es decir, 36 minutos. El equipo corrige anulando el cambio de configuración, luego confirma mediante una vigilancia continua que la conectividad está restablecida antes de cerrar el incidente a las 00:30 del día siguiente. El punto a recordar: no fue la ausencia de supervisión lo que causó la falla, fue uno de los mecanismos de supervisión mismos, la prueba de salud, el que, mal configurado, la provocó. Fuente oficial: GitHub Availability Report: August 2024.
Las tres fallas coinciden en un punto: en los tres casos, la empresa supo muy rápido que algo no andaba (las métricas de error se mueven en unos segundos). Lo que toma tiempo es saber por qué. Es exactamente lo que el labo de este curso te hace construir, en pequeño, en tu computadora.
El monitoreo vigila indicadores elegidos de antemano, con umbrales ya conocidos: «la tasa de errores supera el 5 %». Es eficaz para una falla que ya se vio pasar. La observabilidad es la capacidad de entender el estado interno de un sistema a partir de las señales que ya produce (sus métricas, sus logs, sus trazas), incluso para una pregunta que no se había anticipado, sin redesplegar código para ir a buscarla. El monitoreo dice «algo no anda»; la observabilidad ayuda a responder «por qué, dónde y desde cuándo».
| Término | Definición en una frase | Dónde se encuentra en el labo |
|---|---|---|
| Monitoreo | Vigilar indicadores conocidos de antemano y alertar cuando se cruza un umbral. | Las diez reglas de prometheus/regles/alertes.yml (módulo 6) |
| Observabilidad | Entender el estado interno de un sistema a partir de sus métricas, logs y trazas, incluso para una pregunta imprevista. | El conjunto Prometheus, Loki y Grafana del labo |
| Métrica | Un valor numérico medido a intervalos regulares, que forma una serie en el tiempo. | http_requetes_total, expuesta por la API en /metrics |
| Log | Un mensaje con marca de tiempo que un programa escribe en un instante preciso para describir un evento. | Una línea JSON escrita por la API en su salida estándar, leída por journal api |
| Traza | El trayecto completo de una solicitud a través de varios servicios, con la duración de cada etapa. | Mencionada en este curso, sin herramienta en este labo (módulo 7) |
| Alerta | Una notificación automática enviada cuando una condición medida se mantiene verdadera durante un tiempo dado. | APIInjoignable, enrutada por Alertmanager hacia el webhook |
| SLI (Service Level Indicator) | Una medida cuantitativa del nivel de servicio realmente observado. | La tasa de respuestas 5xx de la API en 5 minutos (api:taux_erreurs_5m) |
| SLO (Service Level Objective) | El objetivo interno fijado sobre un SLI, en un período dado. | «Menos del 5 % de errores»: el umbral de la alerta TauxErreursEleve |
| SLA (Service Level Agreement) | El compromiso contractual con un cliente, con una penalidad en caso de incumplimiento. | Fuera del labo: una cláusula en un contrato con un cliente |
Referencia para las definiciones de SLI, SLO y SLA: Google SRE Book — Service Level Objectives. Para la observabilidad vista por las herramientas del curso: Prometheus — Overview y Grafana — Observability.
La diferencia esencial entre monitoreo y observabilidad: el monitoreo responde a preguntas escritas de antemano («¿la tasa de errores supera el 5 %?»). La observabilidad permite plantear una pregunta que no se había previsto («¿qué solicitudes tardaron más de 500 ms entre las 19:33 y las 19:34?») y obtener la respuesta a partir de lo que el sistema ya registró.
Antes de Prometheus y Grafana, el equipo de plataforma se conectaba por SSH al servidor y escribía grep ERROR /var/log/api.log. Funciona, para una sola máquina, un solo archivo, un solo momento. Pero:
grep solo ve lo que está escrito en ese servidor, en ese archivo. Con varios contenedores de la API corriendo en paralelo, hay que conectarse a cada uno y cruzar a mano.grep no guarda historial más allá del archivo actual: cuando el archivo rota (log rotation) o el contenedor se reinicia, lo que no se leyó se pierde.grep no calcula tendencias: muestra líneas, no una curva de «porcentaje de errores en los últimos cinco minutos».SELECT count(*) FROM inscriptions) dice cuántas inscripciones existen ahora. No dice nada sobre la latencia de las solicitudes HTTP, sobre la tasa de error, ni sobre el estado de los contenedores: esa información no está en esa base.grep ni la consulta SQL avisan a nadie de forma automática. Hay que recordar lanzarlos, una y otra vez, o esperar a que un usuario se queje.La observabilidad cubre esas carencias: centraliza las métricas y los logs de todas las instancias, guarda un historial consultable, calcula tendencias y avisa automáticamente, sin esperar a que alguien haga la pregunta.
Te incorporas al equipo que mantiene en marcha la plataforma de cursos en línea usada en los otros cursos del catálogo. El corazón del sistema es una API, la API de catálogo, escrita en Python con FastAPI, que expone 64 cursos (C0001 a C0064) en las rutas /cours, /cours/{id}, /inscriptions, /lent, /sante y /metrics. Un segundo programa, el generador de carga (el servicio charge), llama a esta API de forma continua, como lo harían cientos de estudiantes recorriendo el catálogo, inscribiéndose a un curso, o cayendo en una página que ya no existe.
Tu jefa de equipo plantea una pregunta simple, pero que ningún grep ni ninguna consulta SQL responde de una sola vez: «¿Funciona? ¿Para quién? ¿Desde cuándo? ¿Y por qué se rompe?». No quiere conectarse al servidor. Quiere un tablero de control que pueda abrir ella misma, y una alerta que le avise antes de que un estudiante escriba para quejarse.
Ese es el hilo conductor del curso. Cada módulo agrega una pieza: las métricas y PromQL (módulo 2), la instrumentación de la propia API (módulo 3), los tableros de control Grafana (módulo 4), los logs con Loki (módulo 5), las alertas que avisan antes de la queja (módulo 6). El módulo 7 lo reúne todo. Y en cada etapa, el labo te deja romper a propósito un pedazo de la plataforma (.\labo.ps1 casser api, casser erreurs, casser lenteur, casser disque) para que aprendas a leer la falla en las herramientas antes de repararla.
| Servicio (nombre del contenedor) | Rol | Puerto en tu máquina |
|---|---|---|
api (labo-api) | El servicio observado: /cours, /inscriptions, /sante, y sus propias métricas en /metrics | 8000 |
charge (labo-charge) | Simula estudiantes que usan la plataforma, para que haya algo que observar | ninguno |
prometheus (labo-prometheus) | Va a buscar (scrape) las métricas de cada servicio cada 15 s, las almacena como series en el tiempo, evalúa las reglas de alerta | 9090 |
alertmanager (labo-alertmanager) | Recibe las alertas disparadas por Prometheus, las agrupa, las enruta hacia un receptor | 9093 |
webhook (labo-webhook) | Recibe las alertas de Alertmanager y las muestra: lo que recibiría un sistema de guardia | 8090 |
alloy (labo-alloy) | Descubre los contenedores Docker y transporta sus logs hacia Loki | 12345 |
loki (labo-loki) | Almacena los logs y los indexa por etiquetas (labels), no por su texto completo | 3100 |
node-exporter (labo-node-exporter) | Expone las métricas de la máquina anfitriona (CPU, memoria, disco) en formato Prometheus | 9100 |
cadvisor (labo-cadvisor) | Expone las métricas de cada contenedor (CPU, memoria, red) en formato Prometheus | 8080 |
grafana (labo-grafana) | Interfaz única para explorar y visualizar Prometheus, Loki y Alertmanager | 3000 (GRAFANA_PORT) |
Todavía no instalaste el labo: ese es el trabajo de las lecciones 03 y 04. Este paso a paso te hace leer cuatro salidas reales, capturadas en la máquina del curso, para que reconozcas una métrica, un log y una alerta cuando los produzcas tú mismo. Mantén esta página abierta durante la lección 04: volverás a encontrar cada una de estas cuatro salidas en pantalla.
Una métrica, tal como la lee Prometheus. Cada 15 segundos, Prometheus llama a http://api:8000/metrics. Aquí hay cuatro líneas de esa página, en la máquina del curso:
# HELP http_requetes_total Nombre de requêtes HTTP reçues, par méthode, route normalisée et code de réponse.
# TYPE http_requetes_total counter
http_requetes_total{code="200",methode="GET",route="/cours"} 3247.0
http_requetes_total{code="500",methode="GET",route="/cours"} 32.0Lo que hay que ver: una métrica tiene un nombre (http_requetes_total), etiquetas entre llaves (code, methode, route) y un valor (3247.0). Las dos líneas tienen el mismo nombre pero etiquetas distintas: son dos series distintas. La línea # TYPE … counter dice que ese número solo aumenta. La lección 02 detalla los cuatro tipos.
Un log, tal como lo escribe la API. La API escribe una línea JSON por solicitud en su salida estándar. .\labo.ps1 journal api las muestra; aquí hay dos, en la máquina del curso:
labo-api | {"horodatage": "2026-09-15T19:33:25.839+00:00", "niveau": "INFO", "id_requete": "46bb533b33e9", "methode": "GET", "route": "/cours/{id}", "code": 200, "duree_ms": 13.9, "message": "GET /cours/C0038 -> 200"}
labo-api | {"horodatage": "2026-09-15T19:33:14.781+00:00", "niveau": "ERROR", "id_requete": "dc1c2ff189a6", "methode": "GET", "route": "/cours/{id}", "code": 500, "duree_ms": 0.1, "message": "GET /cours/C0019 -> 500"}Lo que hay que ver: un log es un evento preciso (esa solicitud, en ese instante, para el curso C0038), mientras que la métrica del paso 1 es un acumulado (3247 solicitudes /cours exitosas desde el arranque). El campo id_requete identifica una solicitud única; el mismo valor se devuelve al cliente en el encabezado HTTP x-id-requete. La segunda línea es un error 500: el labo produce a propósito un 1 % de ellos en funcionamiento normal.
Una alerta, tal como la recibe el equipo de guardia. Cuando la API está detenida (casser api), Prometheus ya no puede leer /metrics, la regla APIInjoignable pasa a firing después de 30 segundos, Alertmanager la transmite al webhook. Esto es lo que contiene entonces http://localhost:8090/alertes.json, en la máquina del curso:
{"recu_a":"2026-09-15T19:41:26+00:00","etat":"firing","nom":"APIInjoignable","severite":"critique","service":"api","resume":"L'API catalogue ne répond plus","description":"Prometheus n'arrive plus à lire http://api:8000/metrics depuis 30 secondes (cible api:8000).","debut":"2026-09-15T19:41:11.496Z","fin":"0001-01-01T00:00:00Z"}Lo que hay que ver: la alerta tiene un nombre, una severidad, un resumen legible por un humano, y un estado firing (está sonando). El campo fin vale una fecha nula mientras la alerta está en curso; después de reparer, llega una segunda notificación con "etat":"resolved" y una fecha de fin real. Nadie tuvo que refrescar una página: el testigo se encendió solo.
La vista de conjunto, en un comando. .\labo.ps1 etat resume el estado de los diez servicios y de la supervisión. En la máquina del curso, en funcionamiento normal:
== Supervision ==
✔ Prometheus répond — cibles up : 8/8
séries en mémoire : 12350
alertes : 0 active(s), 0 en attente (pending)
✔ Alertmanager répond (http://localhost:9093)
✔ Grafana répond (http://localhost:3000)
✔ Loki répond (http://localhost:3100)
✔ API catalogue répond — version 1.0.0, 64 cours
✔ Webhook répond — 0 alerte(s) reçue(s) (http://localhost:8090)
Labo : 10/10 services, 8/8 cibles up, 0 alertes actives.Lo que hay que ver: 8/8 cibles up (Prometheus lee ocho páginas /metrics: los diez servicios menos charge y webhook, que no exponen ninguna), 12350 series en memoria (este número varía de una máquina a otra), 0 alertes actives. Esa es la línea que debes volver a encontrar al final de cada práctica del curso.
La regla que une la métrica con la alerta. La alerta del paso 3 no salió de la nada: está escrita en un archivo del kit, prometheus/regles/alertes.yml, cuyas reglas Prometheus evalúa cada 15 segundos (evaluation_interval: 15s en prometheus/prometheus.yml). Aquí está la primera de las diez reglas, tal como figura en el kit:
groups:
- name: api-catalogue
rules:
- alert: APIInjoignable
expr: up{job="api"} == 0
for: 30s
labels:
severite: critique
service: api
annotations:
resume: "L'API catalogue ne répond plus"
description: "Prometheus n'arrive plus à lire http://api:8000/metrics depuis 30 secondes (cible {{ $labels.instance }})."Lo que hay que ver: expr es una métrica (up, la que Prometheus fabrica por sí mismo en cada lectura: 1 si el destino respondió, 0 si no) comparada con un valor; for: 30s es la duración durante la cual la condición debe mantenerse verdadera antes de que la alerta suene; resume y description son exactamente el texto que el webhook mostró en el paso 3, con {{ $labels.instance }} reemplazado por api:8000. Una alerta es una métrica, un umbral y una duración: nada más. El módulo 6 te hará escribir las tuyas.
Esta lección no te hace instalar nada, pero tres confusiones vuelven desde la lección 04. Los mensajes siguientes fueron provocados de verdad en la máquina del curso.
«La API está caída, responde 404»: no. Un 404 es una respuesta sana de un servicio que corre y que dice «este recurso no existe». En el labo, http://localhost:8000/cours/C9999 responde:
HTTP 404 {"detail":"cours C9999 introuvable"}Una API realmente detenida no responde nada en absoluto. Durante casser api, curl http://localhost:8000/sante devuelve:
curl: (7) Failed to connect to localhost:8000 after 2237 ms: Could not connect to serverY Invoke-RestMethod http://localhost:8000/sante en PowerShell: Le délai de l'opération a expiré. Un 404 es un log de nivel WARNING y una métrica code="404"; una API detenida es up{job="api"} con valor 0.
«No hay ninguna alerta, la supervisión no funciona»: en Prometheus, la métrica ALERTS devuelve un resultado vacío cuando todo va bien. En la máquina del curso, en funcionamiento normal, la API de consulta responde:
{"status":"success","data":{"resultType":"vector","result":[]}}"status":"success" con "result":[]: la consulta es correcta, simplemente no hay nada que mostrar. Es la situación normal, no una falla. ALERTS solo contiene una serie para una alerta pending o firing.
«Una métrica y un log son la misma información»: no. La métrica http_requetes_total{code="500",methode="GET",route="/cours/{id}"} 27.0 dice que hubo 27 errores en esa ruta desde el arranque, sin decir cuáles. El log "GET /cours/C0019 -> 500" con "id_requete": "dc1c2ff189a6" dice precisamente cuál. La métrica es barata y se cuenta; el log es detallado y se lee. El módulo 5 los une por el campo id_requete.
El monitoreo vigila umbrales conocidos de antemano; la observabilidad permite entender una falla que no se había anticipado, a partir de las métricas, los logs y las trazas que un sistema ya produce. Una métrica es un número medido en el tiempo, con un nombre, etiquetas y un valor (http_requetes_total{code="200",methode="GET",route="/cours"} 3247.0). Un log es un evento con marca de tiempo, una línea JSON por solicitud en el labo, con un id_requete único. Una alerta avisa automáticamente cuando una condición se mantiene verdadera el tiempo suficiente (APIInjoignable después de 30 segundos de API inaccesible) y llega al webhook con un estado firing y luego resolved. El tablero de un automóvil lo resume todo: indicadores = métricas, caja negra = logs, testigos = alertas, GPS = trazas, parabrisas = Grafana. Ni un grep en un solo servidor ni una consulta SQL sobre la base de negocio centralizan el historial, calculan una tendencia ni avisan automáticamente. Un 404 es la respuesta sana de un servicio que corre; una API detenida no responde nada y up vale 0. El hilo conductor del curso es la plataforma de cursos en línea, su API de catálogo de 64 cursos, su generador de carga y sus diez servicios.
casser y reparer./metrics del labo: los cuatro tipos de métricas, las etiquetas, la cardinalidad, el pull, y la estructura exacta de una línea de log JSON.