English · Español
01 — Métricas RED + USE¶
🇪🇸 RED mide el servicio (lo que ven los usuarios). USE mide el hierro (lo que el servicio sufre). Juntas son completas; por separado son ciegas. Para LLMs hay que añadir métricas específicas — slots del KV cache, profundidad de cola del batcher — que no caen limpiamente en ninguna de las dos.
Hay dos filosofías de métricas que dominan la monitorización operativa, y se desarrollaron de forma independiente:
- RED (Tom Wilkie, Weaveworks, ~2015) para servicios — rates, errors, durations.
- USE (Brendan Gregg, Netflix, ~2013) para recursos — utilization, saturation, errors.
Son complementarias. RED te dice qué ve el usuario. USE te dice qué empuja desde abajo desde el hardware. Una historia madura de observabilidad usa ambas. Esta página deriva cada una, las ajusta al servicio de LLM y lista las métricas específicas de LLM que viven encima.
RED¶
Para cada servicio (handler HTTP, método gRPC, cola interna), registra tres series temporales:
| Letra | Métrica | Unidades | Tipo de Prometheus |
|---|---|---|---|
| R | Rate (tasa) | requests / segundo | counter (con tasa vía rate()) |
| E | Errors (errores) | errores / segundo, desglosado por status | counter |
| D | Duration (duración) | distribución de latencia | histogram |
¿Por qué estas tres? Porque juntas caracterizan un servicio del mismo modo que lo hace un SLO: "el 99% de las peticiones tienen éxito en menos de T segundos".
- La tasa por sí sola te dice la carga; sin errores, no sabes si la carga rompió el servicio.
- Los errores por sí solos te dicen lo roto que está; sin tasa, no sabes si es entrada mala o servicio malo.
- La duración por sí sola te dice la lentitud; sin tasa ni errores, no sabes si lento + pocos tuvieron éxito > rápido + todos fallaron.
RED para servir LLM¶
Para el servidor de la Fase 33, RED se instancia como:
- Rate.
http_requests_total{endpoint, method, status}— counter de Prometheus. PromQL:rate(http_requests_total[1m])da RPS. - Errors. Ya en el mismo counter — filtra por
status="5xx". Counter separadollm_generation_errors_total{reason}para errores de aplicación (p. ej.,prompt_too_long,kv_cache_full). - Duration. Dos histogramas:
request_duration_seconds— end-to-end (HTTP-in a HTTP-out).time_to_first_token_seconds(TTFT) — el específico de LLM. Distingue "el usuario mira una pantalla en blanco" de "el usuario está leyendo la respuesta".
La elección de buckets importa. Para LLMs:
13 buckets cubriendo ~3.5 décadas. No añadas más — cada bucket es su propia serie temporal, y la cardinalidad es tu enemiga.
USE¶
Para cada recurso (CPU, RAM, disco, NIC de red, GPU, cola), registra tres series temporales:
| Letra | Métrica | Pregunta |
|---|---|---|
| U | Utilization (utilización) | ¿qué fracción del recurso está ocupada? |
| S | Saturation (saturación) | ¿cuánto trabajo extra está encolado esperando al recurso? |
| E | Errors (errores) | ¿qué eventos de error emitió el recurso? |
La claridad del método USE viene de un diagrama de flujo simple: para cada recurso, hazte las tres preguntas. Si alguna respuesta es preocupante, ahí es donde escarbas primero.
USE para una caja sirviendo LLM (solo CPU, Fase 34)¶
| Recurso | U | S | E |
|---|---|---|---|
| CPU | node_cpu_seconds_total{mode="user\|system"} ratiado |
node_load1 |
node_cpu_seconds_total{mode="iowait"} (proxy) |
| RAM | node_memory_MemAvailable_bytes |
node_memory_SwapUsed_bytes |
node_vmstat_oom_kill |
| Disco | node_disk_io_time_seconds_total |
node_disk_io_now |
node_disk_io_errors_total (si está expuesto) |
| Cola del batcher | llm_batcher_active_slots |
llm_batcher_queue_depth |
llm_batcher_admission_errors_total |
| KV cache | llm_kv_cache_slots_used |
llm_kv_cache_evictions_total |
n/a (fallos de asignación = error de admisión del batcher) |
La mayoría de las filas a nivel de SO vienen "gratis" con node_exporter. Las filas específicas de LLM — cola del batcher, KV cache — las cableas a mano en src/observability/metrics.py.
USE para una caja multi-GPU (referencia adelantada a la Fase 35)¶
Añade:
| Recurso | U | S | E |
|---|---|---|---|
| GPU SM | DCGM_FI_DEV_GPU_UTIL |
n/a (no hay concepto de cola) | DCGM_FI_DEV_XID_ERRORS |
| Ancho de banda HBM | DCGM_FI_DEV_MEM_COPY_UTIL |
n/a | DCGM_FI_DEV_MEM_ERRORS |
| Capacidad HBM | DCGM_FI_DEV_FB_USED / FB_TOTAL |
eventos OOM | eventos del OOM-killer |
| Colectivos NCCL | histograma de latencia | gauge de colectivo activo | counter de timeout |
El exporter DCGM de NVIDIA es el estándar. Lo cablearemos en la Fase 35; no es alcance aquí.
Métricas específicas de LLM que no encajan en RED ni USE¶
Cinco métricas viven en su propia categoría:
tokens_total{kind="prompt|completion"}— counter. Tokens acumulados servidos. Se usa para calcular throughput en tokens/seg y coste por 1k tokens.time_to_first_token_seconds— histogram. La cola de esto es lo que "se siente lento" para un usuario durante streaming.inter_token_latency_seconds— histogram. Velocidad de generación en estado estable.generation_length_tokens— histogram. Distribución sesgada a la derecha; te deja detectar los outliers del estilo "el usuario pidió un ensayo de 10k tokens".cost_per_request_usd— histogram. Cubierto entheory/02-cost-accounting.md.
Estas cinco más RED más USE te dan el dashboard completo de LLM. Seis paneles para RED, ~6 para USE, 5 para específicos de LLM. ~17 paneles en un dashboard.
Un ejemplo trabajado: ¿qué alertas deberías escribir?¶
Tres alertas que cualquier servicio LLM debería tener desde el día uno:
- Tasa de errores alta. PromQL:
(sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m]))) > 0.01durante 5 minutos. Objetivo: cazar un deployment que rompió la generación. - TTFT p95 lento.
histogram_quantile(0.95, rate(time_to_first_token_seconds_bucket[5m])) > 2durante 5 minutos. Objetivo: cazar regresiones en prefill. - Explosión de coste.
histogram_quantile(0.95, rate(cost_per_1k_completion_tokens_usd_bucket[15m])) > 0.05durante 15 minutos. Objetivo: cazar un patrón de prompt fuera de control.
Estas tres son las alertas de guardia para un servicio LLM.
Cardinalidad: el asesino silencioso¶
Cada combinación de etiquetas es una serie temporal separada. Prometheus escala a ~1M de series activas en hardware básico; pasado eso, se cae.
Etiquetas con cardinalidad acotada (buenas):
endpoint(5–20 valores)method(4 valores)status(decenas de valores)model_name(un puñado)tenant_idsi tienes una lista cerrada
Etiquetas que explotan (malas):
user_id(no acotada)prompt_hash(no acotada)request_id(no acotada — para esto estátrace_id, no las métricas)prompt_first_100_chars(efectivamente no acotada)
Regla: si una etiqueta puede tomar más de ~1000 valores distintos a lo largo del tiempo, no pertenece a una métrica. Pertenece a un log o a un atributo de span de traza, donde el coste de almacenamiento es lineal en eventos y no en número de series.
El modelo mental del cliente Prometheus¶
Para el laboratorio de Borja, la librería prometheus_client expone cuatro tipos de métrica:
Counter: monotónicamente creciente..inc(). Úsalo para tasas y totales.Gauge: valor arbitrario..set(),.inc(),.dec(). Úsalo para cosas que suben y bajan (profundidad de cola, slots usados).Histogram: pre-bucketizado..observe(value). Úsalo para latencia, coste, cualquier cosa donde quieras percentiles.Summary: como histogram pero con estimación de cuantiles hecha del lado cliente. Evítalo — no agregable entre instancias. Usa histogramas.
Para la Fase 34 usas exactamente tres: Counter, Gauge, Histogram. Nunca Summary.
Recapitulación en un párrafo¶
RED (rate, errors, duration) caracteriza un servicio por lo que ven sus usuarios; USE (utilization, saturation, errors) caracteriza un recurso por lo que empuja desde abajo. Juntas son completas; por separado cada una es ciega a la mitad del cuadro. Servir LLM añade cinco métricas específicas (counters de tokens, TTFT, ITL, longitud de generación, coste por petición) que no encajan limpiamente en ninguna. Los buckets de histograma deben tener forma LLM (sub-segundo a dos minutos, 13 buckets). Las etiquetas deben tener cardinalidad acotada — las dimensiones por usuario pertenecen a trazas/logs, no a métricas.
Siguiente: theory/02-cost-accounting.md.