Volver al blog

Síguenos y suscríbete

Sólo disponible en inglés

Por el momento, esta página solo está disponible en inglés. Lamentamos las molestias. Vuelva a visitar esta página más tarde.

El registro de errores de red y los usuarios finales

Hooman Beheshti

VP of Technology, Fastly

La visibilidad deja de existir cuando quieres ver cómo los usuarios interactúan con los sitios web y las aplicaciones. Para ello, no vendría mal contar con una visión integral que te permita conocer las experiencias del usuario, las características de rendimiento y las situaciones donde se producen fallos u errores. Por tanto, cualquier mecanismo o métrica que lo permita sería de gran valor.

En Fastly, trabajamos con una enorme red de servidores distribuidos por todo el mundo, por lo que tenemos mucha información de cómo son las interacciones de los clientes web con nuestra red desde el punto de vista de los servidores. Sin embargo, queremos tener una visión integral, por lo que nos encantan los mecanismos que ofrecen una idea de lo que sucede desde la perspectiva del cliente. Por eso, son muy valiosas algunas tecnologías para navegadores como Navigation Timing y Resource Timing (ya usadas en Fastly Insights), que ofrecen métricas muy útiles para entender las características de rendimiento de la experiencia del cliente. Además, hemos publicado un artículo sobre la relativamente nueva especificación Server Timing, que nos permite recopilar métricas del servidor junto con las del navegador en el lado del cliente.

En este artículo, profundizaré en el tema del registro de errores de red, otra especificación que sirve para mejorar la visibilidad. Explicaré para qué sirve, cómo funciona y cómo puedes utilizar Fastly para recopilar los datos que consigue extraer.

¿Qué es el registro de errores de red?

Un registro de errores de red (o NEL, como lo llaman los modernos) solo por su nombre ya nos da pistas sobre cuál es su función. Es un estándar propuesto por W3C para captar y recopilar errores o fallos de red que se producen en el navegador. Navigation Timing, Resource Timing y, en cierta medida, Server Timing ofrecen visibilidad sobre el rendimiento del cliente, mientras que el NEL proporciona datos sobre la disponibilidad. 

Dicho de otra manera, el objetivo del NEL es descubrir fallos y ofrecer mecanismos de creación de informes en situaciones donde el cliente no consigue acceder al conjunto de recursos web. Los servidores no pueden saber si un cliente ha tenido problemas de acceso, por lo que las métricas del lado del servidor no pueden desvelar los problemas que ocurran más allá de este. El NEL permite derribar ese muro para que podamos tener una visión de extremo a extremo más completa.

Cómo funciona el NEL

En pocas palabras, el NEL detecta errores y fallos de red en el navegador durante las fases de DNS, conexión (TCP y TLS) o aplicación (HTTP) de una petición para informar sobre ellos a los puntos de conexión. El NEL trabaja con Reporting API (otra especificación de W3C), que define los mecanismos de creación de informes genéricos de un navegador. Estos mecanismos, a su vez, se encargan de habilitar cualquier característica que necesite distribuir los informes a cualquier sitio. Sin embargo, el NEL no es el único en utilizar Reporting API (por ejemplo, Content Security Policy, entre otros, también utiliza esta API). NEL define las políticas de registro de errores de los orígenes y crea informes sobre las distintas situaciones donde se producen errores y Reporting API se encarga de distribuir estos informes a uno o más puntos de conexión.

Para activar los mecanismos, se necesitan dos encabezados de respuesta:

  • El encabezado de respuesta del NEL es poco común y llamativo, pero define la política del NEL de origen que se encarga de enviar el encabezado.

  • El encabezado Report-to define un grupo de uno o más puntos de conexión para distribuir informes y, luego, el encabezado del NEL decide cuál es el grupo de puntos de conexión al que se deben enviar los informes en función del nombre del grupo que se haya definido.

El encabezado del NEL es un objeto JSON y su forma más simple es la siguiente:

NEL: {"report_to": "network-errors", "max_age": 2592000}

El miembro report_to es necesario para especificar adónde se envían los informes. En el caso de este ejemplo, «network-errors» se corresponde con el nombre del grupo de puntos de conexión que el encabezado Report-to ha definido, pero de este ya hablaré más adelante. Por otro lado, también hace falta el miembro max_age, ya que define durante cuántos segundos es válida la política. Si max_age tiene un valor de «0», entonces la política del NEL desaparece del cliente (este es el único caso donde puedes omitir el elemento report_to).

Además de report_to y max_age, hay otros miembros opcionales que el encabezado del NEL puede incluir:

  • El miembro include_subdomains es una expresión booleana que indica si la política se aplica a este origen o a todos sus subdominios. Por defecto, es false.

  • El miembro failure_fraction define una tasa de muestra de la creación de informes de fallos. Se trata de una buena forma de gestionar el volumen de informes si no quieres registrar error por error. Tiene un valor que se sitúa entre 0.0 y 1.0, pero por defecto es 1.0.

  • Además, el NEL sirve para crear informes cuando las transacciones salen bien. El miembro success_fraction define la tasa de muestra para crear informes de éxito. Su valor también se sitúa entre 0.0 y 1.0, y es 0.0 de forma predeterminada. Puede ser útil registrar las situaciones donde todo sale bien o mal si se quiere calcular cuál es el porcentaje de error.

Por ejemplo, supongamos que las respuestas de https://example.com tienen el siguiente encabezado del NEL:

NEL: {"report_to": "network-errors", "max_age": 2592000, "include_subdomains": true, "success_fraction": 0.01, "failure_fraction": 0.05}

En este caso, se registraría en el navegador una política de NEL válida durante 30 días, se recopilaría e informaría sobre los errores de example.com y sus subdominios, y se obtendrían el 1 % de los casos de éxito y el 5 % de los errores. Después, se enviarían los informes al grupo de puntos de conexión que el encabezado Report-to haya definido como «network-errors».

El encabezado Report-to también es un objeto JSON que define un grupo de uno o más puntos de conexión para crear informes. Se trata de un grupo porque las funcionalidades del sistema de recuperación de fallos y del equilibrio de carga están integradas en Reporting API. Su forma más simple sería la siguiente:

Report-to: {"group": "network-errors", "max_age": 2592000, "endpoints": [{"url": "https://nel.example.com/report"}]}

El miembro group especifica un nombre para el grupo de uno o varios puntos de conexión definidos. Su uso es opcional y el valor predeterminado es «default», pero puede ser conveniente utilizar un nombre que tenga sentido. Ten en cuenta que el encabezado del NEL indica cuál es el nombre del grupo. Además, al igual que sucede con el encabezado del NEL, se necesita un miembro max_age que defina la duración en segundos del grupo y un miembro max_age con valor «0» que elimine al grupo del cliente. También es opcional utilizar un miembro booleano include_subdomains, que en este caso ejerce la misma función que tenía en el encabezado del NEL. Si quieres recibir informes de los errores en los subdominios, entonces habría que añadirlo en los dos encabezados. 

El miembro endpoints se corresponde con una matriz de objetos JSON que define los puntos de conexión dentro de un grupo. Cada punto de conexión especificado en esta matriz puede tener hasta tres miembros:

  • El miembro endpoints[].url es obligatorio e indica a qué URL se envían los informes.

  • El miembro endpoints[].priority es un entero no negativo opcional que sirve para definir el comportamiento del sistema de recuperación de fallos y su valor predeterminado es «1». Hace que se intente primero distribuir el informe al punto de conexión con la prioridad más baja del grupo. Si la distribución falla, entonces el informe se enviará al punto de conexión cuya prioridad sea inmediatamente superior.

  • El miembro endpoints[].weight también es un entero no negativo opcional, y su función es definir el comportamiento del equilibrio de carga. Su valor por defecto también es «1». Si se supone que todos los puntos de conexión de un grupo tienen la misma prioridad, entonces el equilibrio de carga de estos se realiza tomando como referencia la diferencia de peso entre sí.

Supongamos que tenemos este encabezado de respuesta de https://example.com:

Report-to: {"group":"network-errors","max_age":2592000,"include_subdomains":true,"endpoints":[{"url":"https://nel1.example.com/report","priority":1,"weight":1},{"url":"https://nel2.example.com/report","priority":1,"weight":3},{"url":"https://nel3.example.com/report","priority":2}]}

Este encabezado define un grupo llamado «network-errors» válido durante 30 días que incluye informes de los subdominios de example.com. Un 25 % del equilibrio de carga de los informes se realiza en https://nel1.example.com/report y el otro 75 % en https://nel2.example.com/report. Si uno de los puntos de conexión falla, al otro le corresponderá el 100 %. En caso de que los dos fallen, todos los informes se enviarían a https://nel3.example.com/report.

Puede que ahora tengas más claro cómo trabajan en equipo los encabezados del NEL y Report-to para recopilar e informar sobre las situaciones donde se producen errores: el encabezado del NEL define la política y el encabezado Report-to define adónde se envían los informes.

Cada informe individual es un objeto JSON que se distribuye a un punto de conexión de informes mediante una matriz que contiene uno o varios de ellos en forma de cuerpo de petición POST de HTTP. Es importante mencionar que los informes no tienen por qué enviarse en tiempo real. El cliente podría ponerlos en una cola de espera y realizar el envío por lotes. Ahora veamos un informe de ejemplo para profundizar un poco más en este tema:

[
  {
    "age": 666,
    "body": {
      "elapsed_time": 37,
      "method": "GET",
      "phase": "connection",
      "protocol": "http/1.1",
      "referrer": "https://www.example.com/",
      "sampling_fraction": 1,
      "server_ip": "1.2.3.4",
      "status_code": 0,
      "type": "tcp.reset"
    },
    "type": "network-error",
    "url": "https://www.example.com/image.png",
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
  }
]

Las especificaciones ya aparecen en todos estos campos, pero me gustaría detenerme un momento en algunas de ellas. 

Como ya he mencionado antes, el NEL informa sobre los errores de DNS, conexión o aplicación. Todo esto se especifica en el informe: en phase, dentro de body. En este caso, hay un error de connection. El NEL establece un número de tipos de error y, en el ejemplo anterior, el type de error es tcp.reset. Esto quiere decir que la conexión TCT se restableció cuando se intentaba capturar https://www.example.com/image.png.

Los informes pueden ponerse en la cola de espera y enviarse por lotes, pero el tiempo de los errores se puede calcular con los valores de age y elapsed_time. En el informe, age es el tiempo que transcurre entre que ocurre el error y se envía el informe. En el ejemplo de antes, el informe se envió 11 minutos después del error, pero esta cifra podría ser muchísimo más alta. Si fuese “age”: 0, entonces el informe se habría enviado justo al detectar el error. Con elapsed_time, podemos saber cuánto tiempo pasó entre el inicio de la petición y el momento en que el navegador decidió que se trataba de un error (o cuando desistió de averiguarlo). En este caso, pasaron 37 segundos entre que el cliente realizó la petición a https://www.example.com/image.png y detectó que la conexión TCP se había restablecido. Los informes no incluyen a propósito una marca de tiempo exacta porque puede haber desajustes horarios y no todos los relojes de los clientes pueden estar en hora. No obstante, si tienes en cuenta estos datos y registras una marca de tiempo en el punto de conexión de informes para cuando estos lleguen, te puedes hacer una idea bastante aproximada de cuándo ocurrió en realidad el error en el lado del cliente.

Aprovechar las ventajas de Fastly para desplegar el NEL

Ya hemos visto lo más básico sobre el NEL y lo útil que puede ser para obtener visibilidad de los fallos en el lado del cliente y las situaciones donde se producen los errores. Ahora es cuando la cosa se pone interesante. Vamos a poner en funcionamiento todos estos mecanismos con la plataforma de edge cloud de Fastly.

Con VCL es muy sencillo añadir los encabezados de respuesta para establecer la política del NEL y los puntos de conexión de los informes:

Pero eso no es todo. Con un proceso muy similar a la terminación de balizas, puedes crear un punto de conexión de informes sin origen para recopilar y registrar los informes del NEL con Fastly. Hacen falta algo más de dos líneas de código, pero el proceso es bastante sencillo.

Primero, el cliente realizará una petición preparatoria CORS para comprobar si puede enviar peticiones POST al punto de conexión, ya que los informes del NEL se envían en forma de cuerpos POST desde el navegador. Por tanto, el primer paso consiste en estar seguros de que el punto de conexión puede gestionar las peticiones preparatorias de forma correcta. Para que sea así, las respuestas deben tener los encabezados Access-Control-* idóneos:


Aquí en vcl_recv, finalizamos cualquier petición con /report y generamos una respuesta sintética 204 (No Content) en vcl_error que contenga los encabezados de respuesta CORS adecuados. De este modo, se procesarán la petición preparatoria OPTIONS y los propios informes, ya que también podremos responder a las peticiones POST de distribución de informes con una respuesta 204. 

Lo único que queda es registrar el informe en un punto de conexión de registro tras haberse distribuido con un cuerpo POST. En el caso del contenido del informe, podemos usar una variable de VCL req.postbody. Sin embargo, puedes decidir qué es lo que registras o no en VCL, así que también puedes añadir información adicional que te sirva para el análisis posterior. Ya te he explicado antes que la marca de tiempo te puede resultar útil, pero hay otras variables de VCL que también podrían serlo. Aquí tienes un ejemplo donde registramos el informe del NEL, la marca de tiempo de llegada y alguna información de vcl_log sobre la geolocalización de la IP del cliente en un cubo GCS:

En este caso, «reports_bucket» es el nombre configurado del punto de conexión del registro de GCS en el servicio de Fastly. Además, hemos creado las líneas de registro para que sean objetos JSON, de modo que los archivos de GCS estarán en formato JSON delimitado y de nueva línea. Así, será más fácil exportarlos para realizar el análisis posterior. Ten en cuenta que esto es solo un ejemplo con GCS, pero puedes configurar el envío de informes para cualquier punto de conexión de registro que elijas.

También sería ideal poder registrar los informes directamente en BigQuery de Google, por poner un ejemplo. Así podrías analizar los datos de manera instantánea en cuanto estuvieran registrados. No obstante, el cuerpo de los informes complica las cosas, ya que el envío podría ser por lotes y una única petición puede contener varios informes. Además, VCL no puede procesar el formato JSON y extraer los informes uno por uno. Por eso, si enviaras el informe completo a BigQuery, podría haber celdas en la tabla que incluyeran varios informes, lo cual complicaría las consultas. Como alternativa, puedes enviar el cuerpo entero a GCS y utilizar Cloud Functions para procesar los archivos uno por uno y extraer los informes individuales antes de insertarlos en BigQuery; entonces sí tendrías un informe en cada fila.

Si se pudieran leer y procesar los cuerpos de las peticiones, podrías saltarte los dos pasos anteriores. Pues bien, resulta que esa es exactamente una de las muchas posibilidades que Compute puede aportarnos. Es todo lo que puedo desvelar ahora mismo. En un nuevo artículo del blog, explicaremos qué uso podemos darle a Compute para simplificar y mejorar el registro de cuerpos JSON.

Lo que hemos aprendido con el despliegue del NEL

El NEL parece no haber tenido una gran acogida por el momento. Por un lado, el soporte técnico en navegadores no está muy extendido. Por otro lado, se han consultado los datos de HTTP Archive (que hace poco tenía en sus registros más de 5,4 millones de peticiones de distintos nombres de host únicos en internet) y solo el 1,7 % de los hosts incluyen encabezados de NEL en las respuestas. No obstante, el NEL promete mucho y a nosotros nos encantan las cosas prometedoras. Por eso, hemos estado experimentando con el NEL dentro de Fastly Insights y hemos aprendido algunas cosas útiles que quiero compartir contigo:

  • La distribución de informes no aparece como una petición en las DevTools de Chrome. Por tanto, tendrás que echar mano de la creatividad si quieres ver las peticiones enviadas desde el cliente (o resolver el problema si no hay peticiones). Si aceptas sugerencias, te aconsejo Wireshark, la mejor herramienta de solución de problemas del mundo.

  • En Chrome, puedes ver los puntos de conexión de informes y las políticas de NEL en chrome://net-export. El proceso es más complicado que con la interfaz antigua de chrome://net-internals, donde todo estaba condensado en el mismo sitio. Sin embargo, una vez que te acostumbras, puedes ver todo lo relacionado con el NEL.

  • Si acabas teniendo varias políticas aplicadas a un mismo origen, la mejor será la más específica. Por ejemplo, si tienes una política para https://example.com con include_subdomains y otra política para https://www.example.com con un error en un recurso de https://www.example.com, el navegador utilizará la política de https://www.example.com. Es recomendable mantener la coherencia en la aplicación de los puntos de conexión de informes y los encabezados del NEL para que no te lleves sorpresas. Sin embargo, si quieres tener flexibilidad entre subdominios, esa es una forma de conseguirlo.

  • Los propios puntos de conexión de informes pueden estar dentro de una política de NEL, así que el NEL puede avisarte cuando haya fallos en la distribución de errores.

  • Por restricciones de seguridad, el NEL tiene una manera especial de gestionar los errores de orígenes con una dirección IP que ha cambiado. Esto puede pasar a menudo si usas varias direcciones IP en un origen (y un DNS de round robin, por ejemplo) o cuando se usan grandes redes de distribución de contenido que utilizan el enrutamiento dinámico para llevar a los usuarios a una ubicación en el edge. En casos como estos, los informes de errores pierden un poco de granularidad. No voy a meterme más de lleno en este momento, pero si quieres saber más sobre el NEL y te parece algo importante, puede que te interese leer esta sección de la especificación.

  • Las especificaciones del NEL y Reporting API están evolucionando. El borrador más reciente del editor del NEL ha cambiado un poco desde la publicación de la última versión oficial. Si siguieran adelante con el borrador, entonces el NEL también podría recopilar peticiones y encabezados de respuesta dentro del informe del NEL. En cuanto a la versión más reciente del borrador del editor de Reporting API, también ha habido cambios en comparación con la última versión publicada: el encabezado Report-to ha cambiado de nombre y ahora es un encabezado con estructura, lo que no es tan mala idea. Además, se habrán incluido otros cambios. Por tanto, si todo esto te parece interesante y te sigue llamando la atención, quizás te interese seguir de cerca la evolución de las especificaciones.

  • Ten cuidado si intentas hacer el informe de errores y supervisarlos en el mismo sitio. En este caso, te puede venir muy bien utilizar el mecanismo del sistema de recuperación de fallos de Reporting API.


Soy un gran fan de todo el potencial que tiene el NEL a nivel conceptual. Tiene la capacidad para ofrecer visibilidad sobre el estado de la aplicación y la red desde el punto de vista del cliente. Además, también me encanta crear aplicaciones con las funciones del edge de Fastly, y un buen ejemplo de ello puede ser un punto de conexión de informes sin origen. Si a ti también te parecen útiles todos estos mecanismos y quieres probarlos, cuéntanoslo. Además, si has descubierto o aprendiendo algo y quieres compartirlo en el blog y las presentaciones, sería estupendo.