Módulo 7: Observability Latency And Evals In Production
1. Introducción al módulo: el mismo vocabulario, métricas nuevas
Descripción
sre-and-incident-response-guide ya dejó, terminado y verificado, el vocabulario completo que este módulo va a usar sin volver a explicarlo desde cero: qué es un SLI, qué es un SLO, cómo se calcula un error budget, cómo se lee AWS/Lambda/Errors con awslocal cloudwatch get-metric-statistics, y el patrón de "eventos válidos, eventos buenos" que convierte una intuición ("el sistema anda bien") en un número defendible. Este módulo no repite nada de eso. Lo reaplica, con la misma disciplina exacta, a una carga de trabajo distinta — una que invoca un modelo de lenguaje, no solo un Lambda determinista — y hace la pregunta que ninguna guía anterior de este ecosistema tuvo que responder todavía: ¿qué de todo esto se puede medir de verdad, sin invocar Bedrock ni una sola vez?
Conexión con el módulo
Los Módulos 1 a 6 de esta guía construyeron, pieza por pieza, la infraestructura, los guardrails y el modelo de costo de extract-shipment-manifest-fields. Este módulo cierra el círculo de operación con la tercera disciplina que toda carga en producción necesita, junto a seguridad (M5) y costo (M6): observabilidad. La lección 2 define los tres indicadores nuevos; las lecciones 3 a 6 los construyen, cada una con su propia honestidad exacta sobre qué corrió de verdad; la lección 7 traza el límite final, el mismo tipo de límite que el M3.6 y el M4.7 ya trazaron para apply y para el bloqueo del guardrail; la lección 8 cierra el módulo con el panel documentado.
Analogía: los mismos instrumentos, un motor distinto
Un mecánico que sabe leer el tablero de un auto de combustión —velocímetro, tacómetro, temperatura del motor, nivel de combustible— no tiene que aprender a leer instrumentos nuevos el día que se sienta frente a un auto eléctrico. Sigue existiendo un velocímetro. Sigue existiendo un indicador de "cuánta energía queda". Lo que cambia no es el tipo de instrumento — es qué cifra concreta aparece detrás de la aguja, y qué significa un valor alto o bajo para este motor específico. sre-and-incident-response-guide te enseñó a leer el tablero completo de un sistema en producción: SLI (la aguja), SLO (la zona verde del velocímetro), error budget (cuánto margen te queda antes de salir de esa zona). Este módulo no cambia ningún instrumento. Cambia el motor — de un Lambda que parsea clave=valor a un Lambda que, cuando ese parseo falla, invoca un modelo de lenguaje — y te enseña a leer las cifras nuevas que ese motor específico produce, con las mismas herramientas de siempre.
EL TABLERO (sre-and-incident-response-guide) EL MOTOR NUEVO (este módulo)
SLI = medida cuantitativa de un aspecto Tasa de escalamiento
del nivel de servicio Latencia de inferencia
SLO = el objetivo numérico sobre ese SLI Tasa de bloqueo del guardrail
Error budget = 100% - SLO, en minutos
Los mismos tres términos de la
Ya construido, ya verificado -- izquierda, aplicados a números
process-shipment-manifest, Módulos 1-4 que ninguna guía anterior de
de esa guía este ecosistema tuvo que medir
Qué hereda este módulo, sin volver a explicarlo
| Pieza | Origen | Qué hace este módulo con ella |
|---|---|---|
| La fórmula de SLI: "the proportion of valid events that were good" | sre-and-incident-response-guide, Módulo 2, lección 3, citando Google — The Art of SLOs | Se reaplica en la lección 2, con la honestidad de que uno de los tres SLI nuevos no encaja limpiamente en ese molde |
| SLI, SLO, error budget — las definiciones exactas | sre-and-incident-response-guide, Módulo 1, lección 7 (07-the-vocabulary-youll-use-all-guide.md), citando el Google SRE Book | Se dan por conocidas — esta lección no las vuelve a citar en extenso, la lección 2 sí cuando cada SLI nuevo lo necesita |
| El patrón de CloudWatch Logs/Metrics reales sobre un Lambda heredado | sre-and-incident-response-guide, Módulo 3, lecciones 3 y 4 | La lección 3 de este módulo aplica el mismo patrón a extract-shipment-manifest-fields, con logging estructurado nuevo |
El hallazgo de que awslocal cloudwatch/awslocal logs son representativos en este entorno específico (sin LOCALSTACK_AUTH_TOKEN) | sre-and-incident-response-guide, Módulo 3, lecciones 3 y 4 | Se reconfirma, sin volver a investigarlo, en la lección 3 de este módulo |
parse_manifest(), el parser determinista | Este mismo curso, Módulo 1, lección 3 | Reusado, sin ningún cambio, como el motor de cálculo de la lección 4 |
SHIPMENT_FIELDS_SCHEMA, validate_shipment_fields() (guardrails/post_invoke_checks.py) | Este mismo curso, Módulo 4, lección 6 | Reusado, sin ningún cambio, en las lecciones 4 y 6 de este módulo |
| La frontera con AI Engineering | Este mismo curso, Módulo 1, lección 4 | Se retoma explícitamente en la lección 5, aplicada esta vez a la evaluación de calidad |
Fíjate en el patrón: cuatro de las siete filas de esta tabla no son de sre-and-incident-response-guide — son de esta misma guía, de módulos anteriores. Este módulo no solo hereda vocabulario de una guía hermana; hereda código real, ya construido y ya probado, de sus propios Módulos 1 y 4. Ningún SLI de este módulo empieza desde cero.
Mapa de las ocho lecciones
M7.1 Introducción (esta lección) -- el mismo vocabulario, métricas nuevas
M7.2 Los tres SLI de una carga de IA -- definiciones formales, con
la honestidad de cuál encaja en el molde clásico y cuál no
M7.3 Manos a la obra: CloudWatch Logs/Metrics del extractor --
EJECUTADO (logging estructurado), REPRESENTATIVO (awslocal)
M7.4 Manos a la obra: la métrica de tasa de escalamiento --
EJECUTADO, el único SLI de IA 100% literal de esta guía
M7.5 Qué es un eval en producción, y por qué no es un test unitario
-- conceptual, la frontera con AI Engineering, otra vez
M7.6 Manos a la obra: el arnés de smoke test con manifiestos fijos
-- EJECUTADO (el arnés), REPRESENTATIVO (la salida del modelo)
M7.7 El límite exacto: por qué la latencia y la calidad reales
no se pueden medir aquí -- REPRESENTATIVO, con la razón exacta
M7.8 Proyecto: el panel de observabilidad de la carga de IA de
Andes Cargo -- EJECUTADO (el documento)
Las lecciones 3, 4 y 6 son manos a la obra; cada una deja claro, en el momento exacto en que aparece cada bloque de código, si lo que ves corrió de verdad o es una reconstrucción precisa de lo que correría. La lección 5 es la única puramente conceptual del módulo, y existe porque la línea que traza —correctitud de forma frente a calidad semántica— es la que sostiene la honestidad de la lección 6. La lección 7 cierra con el mismo tipo de honestidad que el M3.6 y el M4.7 ya modelaron: no un obstáculo nuevo, el mismo límite de fondo, aplicado esta vez a tiempo y calidad.
El ledger de honestidad de este módulo, adelantado
Antes de entrar en detalle, vale la pena ver la tabla completa de una vez — la misma disciplina de honestidad explícita que cada módulo de esta guía ya aplicó a su propio dominio:
| SLI / pieza | ¿Se puede calcular sin invocar Bedrock? | Estado en este módulo |
|---|---|---|
Tasa de escalamiento (ManifestParseFailed / total) | Sí — depende solo de parse_manifest() y de qué manifiestos llegan, nunca de una invocación al modelo | Literal (M7.4) |
| Tasa de bloqueo del guardrail propio | Sí — depende de validate_shipment_fields(), código propio, ejecutado sobre cualquier candidato, real o representativo | Calculable, sobre datos del arnés de M7.6 |
| Latencia de inferencia | No — InvocationLatency/TimeToFirstToken (CloudWatch, AWS/Bedrock) solo existen si una invocación real ocurrió | Representativo (M7.7) |
| Calidad semántica de la extracción | No, y además fuera del alcance de esta guía por diseño (M1.4) | Nombrado, no construido (M7.5) |
| Logging estructurado del handler | Sí — es código Python propio, sin ninguna dependencia de Bedrock | Literal (M7.3) |
| Métricas de CloudWatch sobre ese logging | Solo con LOCALSTACK_AUTH_TOKEN, no disponible en este entorno | Representativo (M7.3) |
Tres filas literales, dos representativas, una fuera de alcance por diseño. Ese es, con precisión, el mapa completo de lo que este módulo puede y no puede demostrar — y cada una de las ocho lecciones que siguen declara, en el momento exacto en que corresponde, en cuál de esas filas cae.
Errores comunes
Esperar que este módulo enseñe a configurar Prometheus/Grafana para Bedrock, como sre-and-incident-response-guide ya hizo para process-shipment-manifest (de expectativa de herramienta). Qué pasa: alguien, familiarizado con el Módulo 3 de la guía hermana, busca aquí un docker-compose.yml con un exporter de métricas de Bedrock. Cómo detectarlo: si tu primera pregunta al abrir este módulo es "¿dónde está el dashboard de Grafana?". Cómo corregirlo: este módulo se queda deliberadamente en CloudWatch nativo — el mismo alcance que sre-and-incident-response-guide, Módulo 3, lección 3 ya usó para las métricas nativas de Lambda, antes de llegar a Prometheus en su lección 6. Levantar un stack de observabilidad completo para una carga que, honestamente, nunca invoca un modelo real en este laboratorio, sería construir infraestructura para datos que no existen todavía.
Asumir que "tres SLI nuevos" significa que los tres se calculan con el mismo tipo de fórmula (de generalizar de más desde sre-and-incident-response-guide). Qué pasa: alguien, acostumbrado a la fórmula "eventos buenos ÷ eventos válidos" de la guía hermana, intenta aplicarla mecánicamente a los tres SLI de este módulo sin pensar si encaja. Cómo detectarlo: si tu definición de tasa de escalamiento usa la palabra "buenos" en algún lado. Cómo corregirlo: la lección 2 de este módulo dedica una sección completa a esta distinción exacta — la tasa de escalamiento no mide "qué proporción de invocaciones fue buena", mide "qué proporción del tráfico total tomó el camino caro". Son preguntas distintas, y confundirlas es, precisamente, el error que la lección 2 previene con cuidado.
Concluir, de la tabla de honestidad de esta lección, que "la mitad de este módulo no sirve para nada real" (de subestimar lo que sí es literal). Qué pasa: alguien ve dos filas marcadas "representativo" y descarta el módulo entero como principalmente teórico. Cómo detectarlo: si tu resumen de este módulo es "no se puede medir casi nada sin pagar por Bedrock". Cómo corregirlo: la tasa de escalamiento —el SLI más importante de esta guía para decidir si el camino de IA sigue siendo una minoría del tráfico, la tesis central del M1.6— es 100% literal, corrida sobre un conjunto de eventos real. El logging estructurado que instrumenta el handler es código Python real, ejecutado, probado. Lo que queda representativo es, específicamente, lo que depende de una invocación real del modelo — el mismo límite exacto que cada módulo anterior de esta guía ya declaró para su propio dominio, nunca una limitación nueva de este módulo en particular.
Ejercicios
Ejercicio 1 — Sin mirar la tabla de honestidad de esta lección, predice cuál de los tres SLI nuevos (tasa de escalamiento, latencia de inferencia, tasa de bloqueo del guardrail) es el único 100% literal de este módulo. Justifica tu respuesta usando lo que ya sabes del Módulo 1 de esta guía.
Ver solución
La tasa de escalamiento. La razón, ya establecida desde el Módulo 1, lección 3: ManifestParseFailed se publica —o no se publica— exclusivamente en función de si parse_manifest() produjo los cinco campos de ShipmentFields, una decisión que se toma antes de que exista cualquier intento de invocar Bedrock. La latencia de inferencia, por definición, no existe sin una invocación real (no hay nada que cronometrar). La tasa de bloqueo del guardrail está a medio camino: es calculable con código propio (validate_shipment_fields()), pero necesita un candidato —real o representativo— sobre el cual correr; no es tan autosuficiente como la tasa de escalamiento, que solo necesita el texto crudo del manifiesto.
Ejercicio 2 — Explica, con tus propias palabras, por qué este módulo puede reusar la fórmula de SLI de sre-and-incident-response-guide sin tener que redefinir SLI, SLO o error budget desde cero. ¿Qué haría que esa reutilización fuera un error, en vez de una decisión correcta?
Ver solución
Reusar la fórmula es correcto porque SLI, SLO y error budget son conceptos independientes del tipo de sistema que miden — la definición de Google SRE ("una medida cuantitativa, cuidadosamente definida, de algún aspecto del nivel de servicio") no menciona Lambdas, LLMs ni ningún tipo de carga específica. Sería un error, en cambio, asumir que la definición específica de un SLI de process-shipment-manifest —por ejemplo, "sin excepción, dentro del timeout, con un registro correcto en Shipments"— se traslada sin cambios a extract-shipment-manifest-fields. El vocabulario se hereda; el contenido específico de cada SLI, no — exactamente la distinción que la lección 2 de este módulo desarrolla con cuidado para cada uno de los tres SLI nuevos.
Ejercicio 3 — Basándote en el ledger de honestidad de esta lección, predice qué le pasaría a la fila de "latencia de inferencia" si, algún día, alguien corriera esta guía completa contra una cuenta AWS real con Bedrock habilitado. ¿Cambiaría de representativo a literal automáticamente, o haría falta algo más?
Ver solución
Cambiaría a literal, pero no automáticamente — haría falta, como mínimo, ejecutar de verdad las invocaciones que esta guía nunca ejecuta, y leer InvocationLatency/TimeToFirstToken de CloudWatch (AWS/Bedrock) después de que esas invocaciones existan. El código y los comandos de esta guía —los que la lección 7 documenta con precisión sobre el schema real de esas métricas— seguirían siendo exactamente los mismos; lo único que cambiaría es que, por primera vez, existiría tráfico real detrás de ellos. Es la misma relación que el M3.6 ya estableció para apply contra Bedrock: el código no cambia entre el laboratorio $0 y una cuenta real, cambia si el servicio detrás de ese código existe.
Resumen y siguiente paso
Esta lección mapeó las ocho lecciones de este módulo y confirmó, tabla por tabla, exactamente qué hereda de sre-and-incident-response-guide (el vocabulario SLI/SLO/error budget, el patrón de CloudWatch, el hallazgo de que awslocal es representativo en este entorno) y qué hereda de los propios Módulos 1 y 4 de esta guía (parse_manifest(), SHIPMENT_FIELDS_SCHEMA, validate_shipment_fields()). Viste, adelantado, el ledger completo de honestidad de este módulo: tres piezas literales, dos representativas, una fuera de alcance por diseño.
Antes de avanzar deberías poder: nombrar los tres SLI nuevos de este módulo sin ayuda; explicar por qué la fórmula de SLI se reusa sin cambios pero el contenido específico de cada SLI no; y predecir cuál de los tres es el único 100% literal, con su justificación.
La lección 2 define, con precisión formal, cada uno de los tres SLI nuevos — y dedica especial cuidado a explicar por qué la tasa de escalamiento no encaja limpiamente en el molde clásico de "eventos buenos ÷ eventos válidos" que sre-and-incident-response-guide ya estableció.
Recursos
- Google SRE Book, Capítulo 4 — Service Level Objectives — la fuente exacta de SLI/SLO/SLA, ya citada por
sre-and-incident-response-guide, Módulo 1, lección 7. - Google — The Art of SLOs (Participant Handbook) — la fórmula exacta de SLI ("la proporción de eventos válidos que fueron buenos"), reaplicada con cuidado en la lección 2 de este módulo.
sre-and-incident-response-guide, Módulo 3, lecciones 3 y 4 — el precedente exacto de CloudWatch Logs/Metrics reales sobre un Lambda heredado, y el hallazgo de queawslocal cloudwatch/awslocal logsson representativos sinLOCALSTACK_AUTH_TOKEN.- Este mismo curso, Módulo 1, lección 3 (
03-andes-cargos-ai-workload-when-the-deterministic-parser-is-not-enough.md) — el origen deparse_manifest()y de la tasa de escalamiento como concepto. - Este mismo curso, Módulo 4, lección 6 (
06-hands-on-the-output-schema-validator.md) — el origen deSHIPMENT_FIELDS_SCHEMAyvalidate_shipment_fields(), reusados en las lecciones 4 y 6 de este módulo.