Módulo 2: Slis Slos And The Error Budget

3. Manos a la obra: tu primera definición de SLI

Descripción

La lección anterior eligió errores como la señal que el SLI primario de Andes Cargo va a medir. Esta lección hace el trabajo real de convertir esa elección en una definición precisa —por escrito, con criterio explícito, decidido caso por caso— antes de que exista una sola línea de código de la calculadora. Es la parte del proceso que menos se parece a programar y más se parece a un ejercicio de producto: decidir, con evidencia y no por conveniencia, qué cuenta exactamente como un "evento bueno" y qué cuenta exactamente como un "evento válido" para process-shipment-manifest.

Conexión con el módulo

La calculadora de la lección 4 va a recibir un dataset con dos números por día: eventos válidos y eventos buenos. Esos dos números no son un detalle de implementación —son la definición completa del SLI, resumida en dos columnas—. Si esta lección se salta o se hace con descuido, la lección 4 corre un script perfectamente correcto sobre datos que no significan lo que deberían significar. Esta es, literalmente, la lección que hace que el resto del módulo mida algo real.


La fórmula exacta, con su fuente

La fórmula de SLI que este módulo usa no es "eventos buenos ÷ eventos totales" — es más precisa que eso, y la precisión importa:

"The SLI Equation: The proportion of valid events that were good."

"Events can be prevented from counting against an error budget either by including them in the numerator or by excluding them from the denominator. The former is achieved by classifying some events good, the latter by classifying some events invalid."

Google — The Art of SLOs (Participant Handbook)

   SLI = eventos buenos / eventos validos

La misma fuente distingue, con una frase clave, cómo se decide qué es "válido" según el tipo de sistema:

"Typically, for data processing systems, validity is determined by input parameters, to scope the SLI to subsets of the data."

process-shipment-manifest es, exactamente, un sistema de procesamiento de datos —no una API HTTP donde la validez se decide por hostname o ruta—. Esto significa que la validez de un evento, para este Lambda, se decide por qué tipo de entrada disparó la invocación, no por cómo respondió el sistema.


Paso 1 — Decidiendo qué cuenta como "válido"

Un evento válido es el que debería contar en el denominador del SLI —el universo completo sobre el cual se mide "bueno" frente a "malo"—. Un evento inválido no cuenta ni a favor ni en contra: simplemente se excluye de la medición por completo, porque no representa el tipo de trabajo real que el SLI intenta capturar.

process-shipment-manifest se dispara de dos formas distintas, y solo una de ellas debería contar:

Origen de la invocación¿Cuenta como evento válido?Justificación
Trigger real de S3, disparado por la subida de un manifiesto real de un cliente de Andes CargoEs exactamente el tipo de trabajo que el SLI debe medir — la señal citada de "input parameters" aplicada literalmente: la fuente del evento (una subida real, no una prueba interna) es el parámetro de entrada que decide validez
Invocación manual de prueba (aws lambda invoke desde consola o CLI, con un payload sintético usado solo para verificar que el Lambda desplegado funciona)NoNo representa tráfico real de ningún cliente; incluirla contaminaría el SLI con eventos que nadie fuera del equipo de ingeniería nunca vio

Esta decisión tiene una consecuencia directa sobre el dataset que la lección 4 va a usar: cada fila del dataset de 30 días cuenta únicamente invocaciones disparadas por subidas reales de manifiestos a andes-cargo-shipment-docs — nunca invocaciones de prueba, sin importar cuántas de esas haya habido ese día.


Paso 2 — Decidiendo qué cuenta como "bueno"

Con el universo de eventos válidos ya definido, la pregunta siguiente es más difícil: de esas invocaciones reales, ¿cuáles cuentan como éxito? La fuente da dos caminos: clasificar un evento como bueno (entra al numerador) o clasificar un evento como inválido (sale del denominador). Esta lección elige el primer camino para los tres riesgos que el Módulo 1 ya identificó — a propósito, para que ninguno de esos riesgos quede escondido fuera de la medición.

Resultado real de la invocación¿Cuenta como evento bueno?Por qué (con el riesgo del Módulo 1 que corresponde)
Procesa el manifiesto sin excepción, dentro del Timeout: 10, y escribe el registro correcto en ShipmentsEl caso esperado: latencia dentro del límite, sin error explícito ni implícito
Termina con una excepción no manejadaNoError explícito — la señal de errores de la lección 2, en su forma más directa
Excede el Timeout: 10 y se corta a la fuerzaNoEl riesgo de latencia que el Módulo 1, lección 4, ya identificó como un límite duro sin métrica de duración real todavía
Se regula por falta de concurrencia (la sexta invocación simultánea, con las 5 ranuras ocupadas)NoEl riesgo de saturación del Módulo 1 — y la decisión más importante de esta tabla, ver más abajo
Agota sus dos reintentos automáticos y se descarta sin haberse procesado nuncaNoEl riesgo de reintentos-sin-DLQ del Módulo 1 — un manifiesto que nunca se procesó, sin que nadie se entere

La decisión que vale la pena explicar con más cuidado es la tercera fila. Una invocación regulada por saturación, técnicamente, ni siquiera corrió — Lambda la rechazó antes de ejecutar una sola línea del handler. Sería defendible, siguiendo la fuente citada arriba, clasificarla como inválida en vez de mala —excluirla del denominador en vez de contarla como un evento malo en el numerador—. Esta guía elige explícitamente no hacer eso: una invocación regulada representa un manifiesto real de un cliente que Andes Cargo no procesó cuando debía, exactamente el tipo de falla que el inventario de riesgo del Módulo 1 nombró y dejó pendiente de medir. Excluirla del denominador la haría invisible para el SLI —el presupuesto de error nunca se enteraría de que pasó—, lo cual sería, en los hechos, esconder el riesgo detrás de una decisión de contabilidad conveniente. Contarla como un evento malo, dentro de eventos válidos, es la única forma de que el SLI de esta guía mida lo que de verdad le importa a un cliente: si su manifiesto se procesó o no, sin que importe la razón técnica interna.


La definición completa del SLI, en una frase

Con las dos decisiones anteriores ya tomadas, el SLI de disponibilidad de process-shipment-manifest queda así, formalmente:

   SLI de disponibilidad de process-shipment-manifest =

   (invocaciones disparadas por subidas reales de manifiestos que terminaron
    sin excepcion, dentro de los 10 segundos de timeout, con un registro
    correcto escrito en Shipments)
   ------------------------------------------------------------------------
   (todas las invocaciones disparadas por subidas reales de manifiestos,
    incluidas las reguladas por saturacion y las descartadas tras agotar
    reintentos, excluidas unicamente las invocaciones manuales de prueba)

Esta es, literalmente, la definición que el dataset de la lección 4 implementa con dos columnas de números: valid_events (el denominador de esta fórmula) y good_events (el numerador). Cada fila del dataset de 30 días que vas a usar en la próxima lección es una aplicación directa de esta definición, día por día.


Errores comunes

Excluir del denominador cualquier resultado incómodo, en vez de contarlo como malo (de "limpiar" el SLI). Qué pasa: alguien, incómodo con que las invocaciones reguladas bajen el SLI, propone clasificarlas como "inválidas" para que no cuenten en absoluto. Cómo detectarlo: si tu justificación para excluir un tipo de evento del denominador es "así el número se ve mejor" en vez de "este evento no representa el trabajo que el SLI intenta medir". Cómo corregirlo: la fuente citada en esta lección es explícita en que excluir del denominador y contar como malo son dos mecanismos legítimos, pero la elección entre ellos debe basarse en si el evento representa trabajo real, no en su efecto sobre el número final. Una invocación regulada representa un manifiesto real que no se procesó — pertenece al denominador, aunque eso haga que el SLI se vea peor.

Definir "bueno" solo en términos de errores explícitos, olvidando los implícitos (de la lección 2). Qué pasa: alguien define "bueno" como "sin excepción y sin timeout", sin ninguna mención a la corrección del dato escrito en Shipments. Cómo detectarlo: si tu definición de evento bueno no incluye ninguna verificación sobre el contenido del registro escrito, solo sobre si la invocación "terminó sin fallar". Cómo corregirlo: la lección 2 ya advirtió sobre errores implícitos —una invocación que "funciona" pero escribe datos corruptos—. La definición de esta lección incluye explícitamente "con un registro correcto escrito en Shipments" precisamente para no repetir ese error.

Confundir "eventos válidos" con "todas las invocaciones que existieron alguna vez" (de no filtrar nada). Qué pasa: alguien incluye las invocaciones manuales de prueba en el denominador, razonando que "también son invocaciones reales del Lambda". Cómo detectarlo: si tu conteo de eventos válidos de un día incluye pruebas hechas por el propio equipo de ingeniería. Cómo corregirlo: la cita de la fuente sobre sistemas de procesamiento de datos es exactamente sobre esto — la validez se decide por el parámetro de entrada (¿es una subida real de un cliente, o una prueba interna?), no por si técnicamente el Lambda se ejecutó. Una prueba interna, sin importar cuántas veces se corra, nunca debería mover el SLI de disponibilidad de Andes Cargo.


Ejercicios

Ejercicio 1 — Clasifica un evento nuevo, no mencionado en esta lección. Una invocación real de process-shipment-manifest, disparada por la subida de un manifiesto genuino, se ejecuta sin excepción, dentro del timeout, pero el manifiesto en sí tiene un campo obligatorio vacío (un error del cliente al generar el archivo, no del sistema) y el Lambda responde correctamente con un estado de "manifiesto rechazado: campo faltante", sin escribir ningún registro en Shipments. ¿Es un evento válido? ¿Es un evento bueno?

Ver solución

Es un evento válido — proviene de una subida real de un cliente, cumple exactamente el criterio de validez de esta lección (el parámetro de entrada es una subida genuina, no una prueba interna). Si es bueno depende de una distinción que esta lección no resolvió explícitamente y que vale la pena precisar ahora: el sistema se comportó correctamente — detectó un manifiesto malformado y lo rechazó con una respuesta clara, en vez de fallar silenciosamente o escribir un dato corrupto—. Esto es, en los hechos, el sistema funcionando como se espera frente a una entrada inválida del cliente, no una falla del sistema. La clasificación correcta es contarlo como evento bueno: el SLI de disponibilidad mide si process-shipment-manifest cumplió su trabajo (procesar o rechazar correctamente), no si cada manifiesto individual llegó bien formado — esa sería una responsabilidad del cliente, no del sistema. Este es exactamente el tipo de decisión de criterio que esta lección insiste en tomar caso por caso, con justificación explícita, en vez de asumir automáticamente que "cualquier cosa que no sea el camino feliz completo" cuenta como malo.

Ejercicio 2 — Explica, con tus propias palabras, por qué "eventos válidos" no es lo mismo que "eventos totales". Un compañero, familiarizado con la fórmula más simple de "eventos buenos ÷ eventos totales" que otras fuentes usan, pregunta por qué esta guía insiste en la palabra "válidos" en vez de "totales".

Ver solución

"Eventos totales" implicaría contar absolutamente todo lo que ocurrió, sin ningún filtro — incluidas las invocaciones de prueba interna, que nunca representaron trabajo real de ningún cliente. "Eventos válidos" introduce, a propósito, un paso de criterio antes de contar: decidir qué universo de eventos representa el trabajo que el SLI intenta medir, y excluir explícitamente lo que no pertenece a ese universo (según la fuente citada, por parámetros de entrada, en el caso de un sistema de procesamiento de datos como este). La diferencia práctica: si Andes Cargo corriera, digamos, 50 invocaciones de prueba manual en un día particular y todas fallaran (porque los payloads de prueba son intencionalmente malformados para verificar el manejo de errores), un SLI de "eventos totales" contaría esas 50 fallas contra el presupuesto de error del día, distorsionando por completo la medición de lo que de verdad le pasó a los clientes reales ese día. "Eventos válidos" existe, precisamente, para que ese tipo de ruido nunca entre a la ecuación.

Ejercicio 3 — Defiende, frente a una objeción real, la decisión de contar las invocaciones reguladas como "malas" en vez de excluirlas. Un ingeniero de Andes Cargo argumenta: "regular una invocación es el sistema funcionando exactamente como se diseñó —proteger la concurrencia—, así que debería ser invisible para el SLI, no contar en contra". ¿Qué le respondes?

Ver solución

Una respuesta completa: "Que el sistema haya funcionado exactamente como se diseñó no significa que el resultado para el cliente haya sido bueno — son dos preguntas distintas. El ReservedConcurrentExecutions: 5 se diseñó, correctamente, para proteger tanto la función como una API externa de transportista de un pico de tráfico (Módulo 1, lección 4); esa es una decisión de diseño defendible. Pero desde la perspectiva del cliente cuyo manifiesto llegó en la sexta posición simultánea, su manifiesto no se procesó — punto—, sin importar cuán buena haya sido la razón técnica interna. El SLI mide la experiencia del cliente, no la corrección del diseño interno del sistema. Si excluyéramos las invocaciones reguladas del SLI porque 'el sistema hizo lo que debía', estaríamos usando la fórmula del SLI para justificar el propio diseño, en vez de usarla para medir honestamente cuántos manifiestos reales se procesaron con éxito — exactamente la trampa que esta lección evita a propósito."


Resumen y siguiente paso

En esta lección definiste, por escrito y con criterio explícito, el primer SLI real de esta guía: eventos válidos son las invocaciones disparadas por subidas reales de manifiestos (nunca pruebas internas); eventos buenos son las que terminan sin excepción, dentro del timeout, con un registro correcto en Shipments —contando explícitamente como malas las invocaciones reguladas por saturación y las descartadas tras agotar reintentos, los dos riesgos que el Módulo 1 dejó identificados y sin resolver—. Esta definición, no un algoritmo, es la pieza que hace que la calculadora de la próxima lección mida algo real.

Antes de avanzar deberías poder: recitar la definición completa de "válido" y "bueno" para process-shipment-manifest sin mirar esta lección; explicar por qué las invocaciones reguladas cuentan como malas y no como inválidas; y defender esa decisión frente a la objeción de que "el sistema funcionó como se diseñó".

La lección 4 convierte esta definición en código real: scripts/error_budget_calculator.py, corrido por primera vez sobre un dataset fijo de 30 días que aplica, día por día, exactamente los criterios que acabas de definir.

Recursos

  1. Google — The Art of SLOs (Participant Handbook) — fuente exacta de "la proporción de eventos válidos que fueron buenos" y de cómo se decide validez en sistemas de procesamiento de datos.
  2. Google SRE Workbook — Implementing SLOs — la formulación complementaria de SLI como razón de eventos, con ejemplos numéricos.
  3. Este mismo repositorio, Módulo 1, lección 4 (04-hands-on-reading-andes-cargo-like-an-sre.md) — los tres riesgos (saturación, timeout, reintentos sin DLQ) que esta lección incorpora, a propósito, dentro de la definición de "malo".