Ir al contenido principal
Laravel, thinking fast.

Capitulo 14

Observabilidad para lo que no puedes reproducir

Julian Beaujardin

El informe de error dice que el sitio que construyó estaba mal.

Tienes la conversación. No tienes el turno: ni qué herramientas se ejecutaron, ni cuánto tardó nada, ni qué estaba pensando el modelo, ni cuánto costó. Y no puedes reejecutarlo, porque reejecutarlo produce un turno distinto.

Esa es toda la dificultad. En la depuración habitual, reproducir es el primer paso. Aquí no está disponible, y lo que registraste en su momento es todo lo que tendrás jamás.

Nombres y tamaños, nunca entradas

Antes de decidir qué registrar, decide qué no debe registrarse nunca.

// Deliberately logs the tool name and nothing else from the payload: the
// arguments carry the business description, the email and the address.

Los argumentos de las herramientas son los datos más ricos del sistema, los más tentadores y los más peligrosos. Son exactamente lo que escribió un usuario: su correo, su dirección, su teléfono, su descripción del negocio. Una línea de registro que los contiene es dato personal en un sistema con retención larga, acceso de lectura amplio y ningún rastro de consentimiento.

La regla que ha aguantado: nombres y tamaños, nunca entradas ni resultados.

Log::info('ai_widget.round_trip', [
    'iteration' => $iteration,
    'duration_ms' => $durationMs,
    'stop_reason' => $stopReason,
    'tool_count' => count($tools),
    'tools' => $tools,
    // A proxy for how much of the time was generation rather than transport:
    // a long reply legitimately takes longer.
    'text_chars' => array_sum(array_map(
        fn (array $block): int => mb_strlen((string) ($block['text'] ?? '')),
        $textBlocks
    )),
]);

Qué herramientas se ejecutaron, cuántas, cuánto tardaron, por qué se detuvo y cuántos caracteres volvieron en lugar de los caracteres mismos. Ese último es el truco que merece robarse: text_chars responde a «¿fue una respuesta larga o una lenta?» sin almacenar ni una palabra.

Durante un incidente tendrás la tentación de añadir las cargas «sólo temporalmente». No lo hagas. El registro temporal sobrevive al incidente, y el reloj de retención arrancó cuando lo desplegaste.

Una línea estructurada por ida y vuelta

La unidad es la ida y vuelta, no el turno: un turno son muchas llamadas de formas distintas, y promediarlas esconde lo que necesitas.

iteration es lo que hace reconstruible un turno después: cuatro líneas con iteraciones del 1 al 4 te cuentan la forma de todo aquello. Qué herramientas se dispararon y cuándo. Si paró porque había terminado o porque un tope se agotó. Dónde se fue el tiempo.

Emparéjalo con una línea de resumen por turno —la contabilidad de tokens del capítulo 4— y entre ambas puedes responder casi cualquier pregunta sobre una conversación que no puedes reejecutar.