`wrangler tail`: los logs de producción en vivo
Abrir una ventana en tiempo real sobre un Worker desplegado: qué es una sesión de tail, cómo se transporta el stream desde el edge hasta tu terminal, y cómo domar el torrente filtrando por estado, método y búsqueda o reduciéndolo con muestreo cuando el tráfico es alto.
En un backend regional depuras entrando a la máquina: un ssh, un tail -f sobre el archivo de log, y ves lo que pasa. En el edge no hay máquina a la que entrar —tu Worker corre en cientos de ubicaciones a la vez, dentro de isolates efímeros que arrancan y mueren con cada request—. wrangler tail es la respuesta de Cloudflare a esa imposibilidad: abre una sesión que se suscribe a los eventos de tu Worker en producción y te los transmite en vivo, sin desplegar nada nuevo y sin tocar el código. Es la herramienta más inmediata de observabilidad, y también la más malinterpretada: no es un almacén de logs, es una ventana que solo muestra lo que ocurre mientras la miras.
- Entender qué es una sesión de tail y cómo viaja el stream desde el edge a tu terminal.
- Filtrar el torrente de eventos por estado, método y texto de búsqueda.
- Usar el muestreo para sobrevivir a un Worker de tráfico alto sin ahogar la sesión.
- Distinguir el formato
prettydeljsony encadenartailcon otras herramientas.
Qué es una sesión de tail
Cuando ejecutas wrangler tail desde el directorio de tu proyecto, no ocurre ningún despliegue: Wrangler llama a la API de Cloudflare para abrir una sesión de tail contra el Worker que ya está en producción. A partir de ese momento, cada isolate que atiende una petición de ese Worker —en cualquier ubicación del planeta— emite un evento estructurado que la red enruta de vuelta a tu terminal por un canal en tiempo real.
# Sigue el Worker del proyecto actual (lee wrangler.jsonc)
wrangler tail
# O nómbralo explícitamente, útil desde fuera del proyecto
wrangler tail mi-worker
Cada evento no es una línea suelta de texto, sino un objeto con toda la anatomía de la invocación: el resultado (outcome: ok, exception, canceled…), la petición que lo disparó (método, URL, cabeceras), el array de mensajes de console.log que tu código produjo, el array de excepciones no capturadas, y las marcas de tiempo. Esa estructura es lo que hace a tail mucho más que un tail -f: no ves texto plano, ves la invocación entera como un dato inspeccionable.
Nada de lo que ves en wrangler tail se guarda. Si cierras la sesión, el flujo desaparece; los eventos que pasaron mientras no mirabas no se recuperan. Esto no es una carencia, es la naturaleza de la herramienta: tail es la ventana en vivo, y la persistencia es trabajo de Workers Logs (siguiente lección). Confundir ambas —esperar que tail te dé el historial de ayer— es el primer malentendido que hay que desactivar.
Filtrar el torrente
Un Worker con tráfico real produce demasiados eventos para leerlos todos. La disciplina de tail consiste en pedir de entrada solo lo que te interesa, y los filtros se aplican en el lado de Cloudflare, no en tu terminal: reducen lo que viaja por el cable, no solo lo que se imprime.
# Solo las invocaciones que terminaron en error
wrangler tail --status error
# Solo peticiones POST que además fallaron
wrangler tail --status error --method POST
# Solo eventos cuyo contenido incluye una cadena
wrangler tail --search "checkout"
# Por IP del cliente, o por una cabecera concreta
wrangler tail --ip self --header "x-tenant:acme"
El filtro por --status error es probablemente el más valioso: convierte una manguera de miles de peticiones sanas en el goteo exacto de las que se rompen, que es justo lo que quieres ver cuando algo va mal en producción. --search recorre el contenido de los eventos (incluidos tus console.log), de modo que si etiquetas tus logs con un identificador —un orderId, un nombre de ruta— puedes aislar el rastro de una operación concreta entre todo el ruido.
Muestreo: sobrevivir al tráfico alto
Hay un límite físico: una sesión de tail no puede transmitir un volumen arbitrario. Si tu Worker recibe muchas peticiones por segundo, Cloudflare empieza a descartar eventos para proteger la sesión, y lo que ves deja de ser representativo. La solución no es rendirse, es muestrear: pedir explícitamente solo una fracción de las invocaciones.
# Muestra aproximadamente el 1% de las peticiones
wrangler tail --sampling-rate 0.01
# Un 10% de las que además fallaron: errores, pero sin ahogo
wrangler tail --sampling-rate 0.1 --status error
El --sampling-rate toma un valor entre 0 y 1 que expresa la probabilidad de que cada evento se incluya. En un Worker con tráfico masivo, un 1 por ciento sigue siendo un flujo enorme y perfectamente útil para detectar patrones, mientras que pedir el 100 por cien solo garantiza que la red te descarte eventos de forma incontrolada. La lección de fondo es que en observabilidad de alto volumen el muestreo no es una degradación que sufres, sino una decisión que tomas: eliges tú la fracción, en vez de dejar que la infraestructura la elija por ti.
sequenceDiagram participant Dev as tu terminal participant API as Cloudflare API participant Edge as isolates en el edge Dev->>API: wrangler tail abre sesion con filtros API->>Edge: suscribe y aplica status method search Edge-->>API: eventos de cada invocacion API-->>Dev: stream en vivo ya filtrado Note over API,Edge: si el volumen supera el limite se descartan eventos Dev->>API: sampling-rate reduce la fraccion en origen
Formato y automatización
Cuando tail detecta una terminal interactiva usa el formato pretty: coloreado, legible, pensado para leer con los ojos. Pero el mismo stream puede emitirse como JSON, y ahí es donde tail se convierte en una pieza de tubería.
# JSON crudo, una linea por evento, apto para procesar
wrangler tail --format json
# Encadenado con jq: extrae solo la URL de los eventos con error
wrangler tail --format json --status error \
| jq -r 'select(.outcome=="exception") | .event.request.url'
Con --format json puedes canalizar los eventos hacia jq, hacia un archivo, o hacia un script que los agregue en caliente durante un incidente. Es el puente entre la inspección humana y la automatización: la misma sesión que lees con los ojos en pretty la procesas con una herramienta en json.
La mentalidad del backend clásico es la del depurador presencial: si algo falla, entro a la máquina, adjunto un debugger, pongo un breakpoint y detengo el mundo para mirarlo de cerca. Esa mentalidad no sobrevive al edge, y entender por qué es entender la observabilidad moderna. Tu Worker no vive en un sitio: vive en cientos, y cada invocación ocurre en un isolate que nace y muere en milisegundos, sin estado que persista entre peticiones y sin un proceso al que puedas engancharte. No puedes detener ese mundo porque no hay un mundo, hay una multitud de mundos efímeros y simultáneos. wrangler tail es la aceptación elegante de esa realidad: renuncia a la inspección —parar y mirar— y la sustituye por la observación —dejar que el sistema te cuente lo que hace mientras sigue corriendo—. Por eso el stream es en vivo y efímero: no es un log que consultas, es una ventana abierta sobre un proceso que no se detiene por ti. Y por eso los filtros y el muestreo no son comodidades, son la única forma de mirar un sistema demasiado grande y demasiado rápido para mirarlo entero: eliges qué fracción de la realidad observas porque observarla toda es imposible. Interiorizar esto —que en un sistema distribuido depuras infiriendo desde la telemetría que el propio sistema emite, no interviniéndolo desde fuera— es el salto mental que separa a quien echa de menos su ssh de quien ya piensa como ingeniero del edge.
- Despliega un Worker sencillo con
wrangler deployy abrewrangler tail; provoca una petición y observa la anatomía completa del evento (outcome, request, logs). - Añade un
console.logcon una etiqueta reconocible, redespliega, y aísla ese rastro conwrangler tail --searchusando tu etiqueta. - Fuerza un error (lanza una excepción) y compruébalo con
wrangler tail --status error: verás solo las invocaciones rotas. - Emite el stream con
--format jsony canalízalo ajqpara extraer un único campo del evento. - Razona en voz alta: si este Worker recibiera diez mil peticiones por segundo, ¿qué
--sampling-ratepedirías y por qué?