La primera vez que un ingeniero pone un console.log en un trabajador de producción y no ve que aparezca nada en ninguna parte, el instinto es sospechar que hay un error en la implementación. El registro simplemente desaparece. No hay ningún servidor de aplicaciones con salida estándar persistente, no hay ningún archivo de registro en el disco, no hay ningún proceso que acumule resultados entre invocaciones. Cada ejecución de Worker ocurre dentro de un aislamiento V8 que nace, procesa la solicitud y desaparece, sin dejar rastro a menos que lo esté capturando activamente. Comprender este modelo es un requisito previo para cualquier estrategia de observabilidad que realmente funcione en el borde.
cola de wrangler: qué es y qué no es
wrangler tail abre una conexión de streaming a la infraestructura de Cloudflare y retransmite en tiempo real los eventos de las invocaciones de sus Workers: metadatos de cada solicitud (método, URL, estado de respuesta, duración de la CPU, país de origen), la salida completa de console.log y console.error, excepciones no detectadas con el seguimiento de la pila y el resultado de waitUntil() cuando finaliza.
Lo que wrangler tail no hace: persistir. Al cerrar la sesión se pierden los eventos que aún no han llegado. Los eventos que ocurrieron antes de que abrieras la sesión tampoco existen para ti. wrangler tail es una herramienta de investigación en vivo, útil para reproducir un problema tal como lo observas, inútil para reconstruir lo que sucedió hace una hora.
Puede filtrar la salida con --filter-status 500 para ver solo errores, o --filter-sampling-rate 0.1 para muestrear el 10% del tráfico y no inundarse bajo una carga alta. En servicios con cientos de solicitudes por segundo, la cola sin filtrar rápidamente hace que el terminal sea ilegible.
El problema de las excepciones silenciosas
Hay un comportamiento en tiempo de ejecución que atrapa a los ingenieros experimentados: un trabajador puede entregar una respuesta 200 al cliente y aun así haber generado una excepción, siempre y cuando la excepción se haya lanzado después de enviar el Response.
El escenario concreto: llamas al 10 para hacer un trabajo de fondo después de la respuesta. Si se lanza minhaFuncaoAssincrona, el cliente ya recibió 200 y está contento. La excepción aparece en wrangler tail como un evento de error asociado con la solicitud, pero no cambia el estado HTTP que vio el cliente. Sin la cola abierta, el error nunca se ve.
Lo mismo ocurre con cualquier promesa que no hagas dentro del manejador. Si dispara un fetch() sin espera y sin manejo de errores, y lo rechaza, el rechazo no capturado aparece en la cola pero no afecta la respuesta que recibió el cliente. En un entorno local con wrangler dev, este comportamiento puede ser diferente: las advertencias son más visibles. En la producción reina un silencio total.
La defensa es sistemática: cada controlador debe tener un try/catch en el nivel más alto que capture, registre con console.error y devuelva un HTTP 500 explícito. Cada promesa pasada a waitUntil() debe tener un manejo de errores interno. No porque el tiempo de ejecución te recuerde, no lo hará.
wrangler dev local versus --remote
wrangler dev sin banderas ejecuta un servidor local usando Miniflare, una implementación de Node.js del tiempo de ejecución de Workers. Para la mayoría de los casos de desarrollo, esto es suficiente: los enlaces KV, D1, R2 y Queue funcionan con implementaciones locales en memoria o SQLite, y el ciclo de retroalimentación es inmediato sin involucrar a la red Cloudflare.
wrangler dev --remote es diferente: envía al trabajador a la infraestructura real de Cloudflare y enruta las solicitudes de desarrollo a través del borde real. Esto es necesario cuando necesita probar comportamientos que Miniflare no puede simular fielmente: objetos duraderos en producción con estado real, comportamientos de almacenamiento en caché de CDN o funciones de tiempo de ejecución que la versión actual de Miniflare aún no ha implementado.
La compensación es obvia: --remote requiere [autenticación 40, tiene latencia de red y cualquier operación de escritura en KV o D1 va a los recursos reales (a menos que configure espacios de nombres/bancos de prueba separados, lo cual debería ser estándar). Usar --remote sin aislamiento del entorno de prueba es el camino más corto para corromper los datos de producción durante el desarrollo.
Logpush: de la cola efímera a la retención real
Para cualquier servicio que necesite reconstruir lo que sucedió después del hecho (auditoría, depuración post mortem, análisis de patrones de error), wrangler tail es insuficiente. Logpush resuelve esto exportando eventos de trabajadores a un destino de almacenamiento configurado.
Los destinos admitidos incluyen R2 (el almacenamiento propio de Cloudflare, a 0,05 dólares por millón de filas exportadas), S3, Datadog, Splunk y algunos otros. La configuración se realiza a través del panel o API: usted elige el conjunto de datos (workers-trace-events), el destino y los campos que desea exportar: timestamp, event.request.url, event.response.status, event.exceptions, event.logs (que incluye la salida de console.log).
Lo importante del campo event.logs: captura lo que pasaste al console.log, pero como texto serializado. Si registró un objeto JavaScript complejo, lo que llega a Logpush es la representación de cadena de ese objeto, no JSON estructurado. Para los registros que deben analizarse y filtrarse en el destino (para crear alertas en Datadog o consultas en Splunk), serialícelos explícitamente en JSON antes de iniciar sesión: console.log(JSON.stringify({ level: 'error', message, requestId, stack })). Logpush entrega la cadena; el objetivo analiza el JSON.
Qué monitorear en producción y qué no ofrece el tiempo de ejecución
Los trabajadores no emiten tramos de seguimiento distribuido de forma nativa. No hay integración automática con OpenTelemetry, no hay propagación del contexto de seguimiento entre subsolicitudes sin implementación manual. Si un trabajador llama a tres servicios a través de fetch() y uno de ellos tarda 800 ms, wrangler tail muestra la duración total pero no desglosa dónde se gastó el tiempo. Para tener esta visibilidad, cronometre manualmente: const t0 = Date.now() antes de la búsqueda, Date.now() - t0 después y registre el resultado estructurado con el nombre del servicio.
Cloudflare adquirió Baselime y está integrando sus capacidades bajo el nombre Cloudflare Observability: análisis de registros y métricas con más ergonomía que la cola manual, pero el verdadero seguimiento distribuido aún requiere instrumentación en el código o un SDK que propague traceparent entre subsolicitudes.
Las métricas más útiles para detectar la degradación antes de que el cliente se dé cuenta: distribución percentil de duración de la CPU (p50, p95, p99), tasa de error segmentada por ruta y recuento de subsolicitudes por invocación. Ninguno sale gratis del tiempo de ejecución: deben crearse, exportarse mediante Logpush y convertirse en alertas en el destino. La diferencia entre un servicio que opera con confianza y uno que teme poner en producción es casi siempre la calidad de la instrumentación que construyó antes del primer incidente.
Lea también
- Trabajadores de Cloudflare en producción: qué cambia después de hello world
- Observabilidad en sistemas distribuidos: registros, métricas y seguimiento
- Observabilidad más allá de los registros: qué cambia OpenTelemetry en la práctica
- Trabajadores + D1 + KV + R2: componer vinculaciones en un mismo servicio
- Trabajadores: límites de CPU y memoria, que la documentación no explica bien
- Testing Workers: unidad, integración y cómo simular el tiempo de ejecución sin depender de Cloudflare
