wandres.dev
OBSERVABILIDAD · logs, tail, analytics

Workers Logs: retención persistente y búsqueda

Convertir el stream efímero de tail en una historia consultable: activar la observabilidad en wrangler.jsonc, entender el muestreo de cabecera que decide qué invocaciones se guardan enteras, y explotar los logs estructurados para interrogar tu producción como si fuera una base de datos.

⏱ 14 min

wrangler tail te da una ventana en vivo, pero una ventana solo muestra el presente: en cuanto la cierras, lo que pasó se pierde. La operación real necesita lo contrario —poder preguntar “¿qué ocurrió a las tres de la madrugada, cuando yo dormía?”—. Workers Logs es esa capa: captura automáticamente los console.log, las excepciones y los metadatos de cada invocación, los retiene durante unos días y te deja buscarlos desde el panel de Cloudflare con la potencia de un motor de consultas. El giro conceptual es grande: dejas de mirar un flujo que pasa y empiezas a interrogar un conjunto de datos que se queda.

🎯 Al terminar esta lección sabrás
  • Distinguir la ventana efímera de tail del almacén persistente de Workers Logs.
  • Activar la observabilidad con el bloque observability en wrangler.jsonc.
  • Entender el muestreo de cabecera y por qué decide guardar invocaciones enteras.
  • Explotar los logs estructurados para buscar por campos como si consultaras una tabla.

De la ventana efímera al almacén persistente

Workers Logs recoge, sin que escribas una línea extra de código, todo lo que tu Worker ya emite: cada console.log, console.warn y console.error, cada excepción no capturada, y los metadatos de la invocación (resultado, estado HTTP, duración de CPU, nombre del script). Lo guarda en un almacén indexado y lo expone en el panel, bajo la sección de observabilidad, con un constructor de consultas: filtras por rango temporal, por campos, por texto, y abres cualquier invocación para ver su rastro completo.

La diferencia con tail no es de grado sino de naturaleza. tail es un flujo que solo existe mientras lo miras; Workers Logs es un registro que persiste aunque nadie mire. Uno responde “¿qué está pasando ahora?”; el otro, “¿qué pasó entonces?”. En un incidente los usas juntos: tail para la reacción en caliente, Workers Logs para la investigación posterior y para el patrón que solo se ve mirando horas de datos.

📝
Historia reciente, no archivo permanente

La retención de Workers Logs es corta —del orden de días (tres en el momento de escribir esta guía; verifica los límites vigentes de tu plan)—. Es tu memoria reciente, deliberadamente acotada: suficiente para depurar un incidente de ayer, insuficiente para auditar el trimestre pasado. Si necesitas retención larga o análisis histórico, ese es trabajo de Analytics Engine o de exportar los eventos a un almacén externo mediante un Tail Worker, no de Workers Logs.

Activar la observabilidad en wrangler.jsonc

La observabilidad no se enciende en un menú del panel, sino en tu manifiesto —lo que la hace versionable, revisable y reproducible junto al resto de la configuración—. El bloque vive en wrangler.jsonc:

{
  "name": "mi-worker",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-01",
  "observability": {
    "enabled": true,
    "head_sampling_rate": 1
  }
}

enabled: true activa la captura y el almacenamiento de logs para ese Worker. head_sampling_rate es un número entre 0 y 1 que decide qué fracción de invocaciones se registra: un 1 lo guarda todo, un 0.1 guarda una de cada diez. En cuanto redespliegas con wrangler deploy, la configuración toma efecto y los logs empiezan a aparecer en el panel.

💡
Muestreo de cabecera: coherencia, no recorte ciego

La palabra clave es head: el dado se lanza al principio de la invocación, no al final. Cuando una petición sale elegida, se guardan todos sus logs —el rastro completo, de la primera línea a la excepción final—; cuando no, no se guarda ninguno. Eso preserva la coherencia: nunca acabas con media traza huérfana. Es la diferencia con un recorte que descartara logs sueltos al azar y te dejara invocaciones a medias. Baja el head_sampling_rate en Workers de tráfico masivo para controlar volumen y coste, sabiendo que cada invocación que conservas la conservas entera.

Buscar como si fuera una tabla

Aquí está el verdadero poder, y depende de cómo escribas tus logs. Si registras texto plano, solo puedes buscar por subcadena. Pero si registras objetos estructurados, Workers Logs indexa cada campo y te deja filtrar por él en el constructor de consultas, igual que un WHERE sobre columnas.

// Log plano: solo buscable por texto
console.log("pedido " + orderId + " fallo con estado " + status);

// Log estructurado: cada campo se vuelve un filtro en el panel
console.log({
  evento: "pedido_fallido",
  orderId,
  status,
  tenant: "acme",
  duracionMs: Date.now() - inicio,
});

Con la segunda forma, el panel te permite consultas del tipo “muéstrame las invocaciones donde evento es pedido_fallido y tenant es acme”, combinables con los metadatos que Cloudflare añade por su cuenta bajo un espacio reservado (el resultado de la invocación, el estado HTTP, la duración). Tus logs dejan de ser prosa que relees y se convierten en un conjunto de datos que interrogas.

flowchart LR
R[invocacion del Worker] --> H{head sampling elige esta?}
H -->|no| X[no se registra]
H -->|si| C[captura console y excepciones]
C --> S[campos estructurados indexados]
S --> D[almacen persistente unos dias]
D --> Q[constructor de consultas en el panel]
Q --> F[filtra por campo tenant evento status]
style C fill:#89b4fa,color:#11111b
style S fill:#94e2d5,color:#11111b
style D fill:#cba6f7,color:#11111b
style X fill:#f38ba8,color:#11111b

Reenviar a sistemas externos: Tail Workers

Cuando necesitas más de lo que el panel ofrece —retención de meses, correlación con logs de otros servicios, alertas en tu herramienta de guardia— Cloudflare deja que un Tail Worker consuma los eventos de otro Worker y haga con ellos lo que quieras: filtrarlos, transformarlos y reenviarlos a un destino externo. Se declara con tail_consumers en el manifiesto del Worker productor, y el consumidor recibe cada lote de eventos en un handler tail. Es la vía canónica para llevar la observabilidad de Cloudflare a un pipeline propio sin renunciar al modelo del edge.

La observabilidad como código convierte los logs de anécdota en evidencia

Que la observabilidad se configure en wrangler.jsonc y no en un menú del panel parece un detalle de ergonomía, y es en realidad una declaración de principios. Cuando el enabled, el head_sampling_rate y los tail_consumers viven en tu manifiesto, tu capacidad de ver el sistema deja de ser un ajuste volátil que alguien tocó una tarde y se convierte en parte del artefacto que despliegas: versionada en git, revisada en un pull request, idéntica en cada entorno, reproducible desde cero. Eso es observabilidad como código, y arregla el pecado original de la operación tradicional —que la instrumentación fuera un añadido manual, distinto en cada máquina, que nadie recordaba haber cambiado—. Pero el salto más profundo es el que ocurre en cómo piensas tus propios logs. Un console.log de texto plano es una anécdota: una frase que alguien redactó para que otro alguien la leyera con los ojos, útil una vez y muerta después. Un log estructurado es evidencia: un dato tipado, con campos, que se indexa, se agrega y se consulta como cualquier fila de una base de datos. La misma información —“el pedido tal falló con el estado cual”— cambia de género según cómo la escribes: como prosa, es literatura que se relee; como objeto, es un hecho que se interroga. Diseñar tus logs desde el primer día como datos estructurados y no como frases es la decisión que determina si, dentro de tres días y en mitad de un incidente, tu historia de producción será un archivo que respondes con una consulta o un montón de texto que relees rezando por encontrar la línea correcta.

⚔️ Interroga tu historia de producción
  1. Añade el bloque observability a tu wrangler.jsonc con enabled: true y head_sampling_rate: 1, y redespliega.
  2. Genera tráfico contra el Worker durante unos minutos, incluyendo alguna petición que falle, y luego abre la sección de observabilidad en el panel.
  3. Reescribe un console.log de texto plano como un objeto estructurado con campos (evento, un identificador, un status) y comprueba que el panel te deja filtrar por esos campos.
  4. Baja el head_sampling_rate a 0.1, redespliega y razona qué cambia: qué se guarda, qué se pierde, y por qué las invocaciones que quedan siguen siendo trazas enteras.
  5. Investiga el manifiesto de un Tail Worker con tail_consumers y esboza a qué sistema externo reenviarías tus eventos y por qué.