Seguimiento distribuido en bibliotecas de System.Net
El seguimiento distribuido es una técnica de diagnóstico que ayuda a los ingenieros a localizar errores y problemas de rendimiento dentro de las aplicaciones, especialmente las que se distribuyen entre varias máquinas o procesos. Esta técnica realiza un seguimiento de las solicitudes a través de una aplicación al correlacionar el trabajo conjunto realizado por distintos componentes y separarlo de otro trabajo que la aplicación podría estar realizando para solicitudes simultáneas. Por ejemplo, una solicitud a un servicio web típico podría recibirse primero mediante un equilibrador de carga y, a continuación, reenviarse a un proceso de servidor web, que luego realiza varias consultas en una base de datos. El seguimiento distribuido permite a los ingenieros distinguir si se produjo un error en alguno de esos pasos y cuánto tiempo se llevó a cabo cada paso. También puede registrar los mensajes generados por cada paso a medida que se ejecutó.
El sistema de seguimiento de .NET está diseñado para trabajar con OpenTelemetry (OTel) y usa OTel para exportar los datos a los sistemas de supervisión. El seguimiento en .NET se implementa mediante las API de System.Diagnostics, donde una unidad de trabajo se representa mediante la clase System.Diagnostics.Activity, que se corresponde a un intervalo de OTel. OpenTelemetry define un esquema de nomenclatura estándar en todo el sector para intervalos (actividades) junto con sus atributos (etiquetas), lo que se conoce como convenciones semánticas. La telemetría de .NET usa las convenciones semánticas existentes siempre que sea posible.
Nota
Los términos intervalo y actividad son sinónimos en este artículo. En el contexto del código de .NET, hacen referencia a una instancia de System.Diagnostics.Activity. No confunda el intervalo de OTel con System.Span<T>.
Sugerencia
Para obtener una lista completa de todas las actividades integradas junto con sus etiquetas o atributos, consulte actividades integradas en .NET.
Instrumentación
Para emitir seguimientos, las bibliotecas de System.Net se instrumentan con fuentes de ActivitySource integradas, que crean objetos Activity para realizar un seguimiento del trabajo realizado. Las actividades solo se crean si hay agentes de escucha suscritos al ActivitySource.
La instrumentación integrada evolucionó con versiones de .NET.
- En .NET 8 y versiones anteriores, la instrumentación se limita a crear una actividad de solicitud de cliente HTTP vacía. Esto significa que los usuarios tienen que confiar en la biblioteca
OpenTelemetry.Instrumentation.Http
para rellenar la actividad con la información (por ejemplo, etiquetas) necesaria para emitir trazas útiles. - En .NET 9 se extendió la instrumentación emitiendo el nombre, el estado, la información de excepción y las etiquetas más importantes de acuerdo con las convenciones semánticas del cliente HTTP de OTel en la actividad de solicitud del cliente HTTP. Esto significa que, en .NET 9 y versiones posteriores, se puede omitir la dependencia de
OpenTelemetry.Instrumentation.Http
, a menos que se requieran características más avanzadas, como el enriquecimiento . - En .NET 9 también se introdujo el seguimiento de conexiones experimentales, lo que añadió nuevas actividades en las bibliotecas de
System.Net
para admitir el diagnóstico de problemas de conexión.
Recopilación de seguimientos de System.Net
En el nivel más bajo, se admite la recopilación de seguimientos a través del método AddActivityListener, que registra objetos ActivityListener que contienen lógica definida por el usuario.
Sin embargo, como desarrollador de aplicaciones, es probable que prefiera confiar en el ecosistema enriquecido basado en las características proporcionadas por el SDK de OpenTelemetry para .NET para recopilar, exportar y supervisar seguimientos.
- Para obtener un entendimiento básico sobre la recolección de trazas con OTel, consulte nuestra guía acerca de recolección de trazas mediante OpenTelemetry.
- Para la recopilación y supervisión de seguimientos en tiempo de producción, puede usar OpenTelemetry con Prometheus, Grafana y Jaeger o con Azure Monitor y Application Insights. Sin embargo, estas herramientas son bastante complejas y pueden ser inconvenientes de usar en tiempo de desarrollo.
- Para la recopilación y supervisión de seguimientos en tiempo de desarrollo, recomendamos utilizar .NET Aspire, que proporciona una forma sencilla pero extensible de poner en marcha métricas y seguimiento distribuido en su aplicación y diagnosticar problemas localmente.
- También es posible reutilizar el proyecto Aspire Service Defaults sin la orquestación de Aspire. Esta es una forma práctica de introducir y configurar el seguimiento y las métricas de OpenTelemetry en los proyectos de ASP.NET.
Recopilar rastros con .NET Aspire
Una manera sencilla de recopilar seguimientos y métricas en aplicaciones ASP.NET es usar .NET Aspire. .NET Aspire es un conjunto de extensiones en .NET para facilitar la creación y el trabajo con aplicaciones distribuidas. Una de las ventajas de usar .NET Aspire es que la telemetría está integrada mediante las bibliotecas de OpenTelemetry para .NET.
Las plantillas de proyecto predeterminadas para .NET Aspire contienen un proyecto de ServiceDefaults
. Cada servicio de la solución .NET Aspire tiene una referencia al proyecto Service Defaults. Los servicios lo usan para establecer y configurar OTel.
La plantilla de proyecto Service Defaults incluye el SDK de OTel, ASP.NET, HttpClient y paquetes de instrumentación en tiempo de ejecución. Estos componentes de instrumentación se configuran en el archivo Extensions.cs. Para poder visualizar la telemetría en el panel de Aspire, el proyecto Service Defaults también incluye el exportador de OTLP por defecto.
Aspire Dashboard está diseñado para llevar la observación de telemetría al ciclo de depuración local, lo que permite a los desarrolladores asegurarse de que las aplicaciones producen telemetría. La visualización de telemetría también ayuda a diagnosticar esas aplicaciones localmente. Poder observar las llamadas entre servicios es tan útil en tiempo de depuración como en producción. El panel de .NET Aspire se inicia automáticamente cuando presiona F5 en el proyecto AppHost
desde Visual Studio o dotnet run
en el proyecto AppHost
desde la línea de comandos.
Para obtener más información sobre .NET Aspire, consulte:
Reutilización del proyecto Service Defaults sin orquestación de .NET Aspire
El proyecto Aspire Service Defaults proporciona una manera sencilla de configurar OTel para proyectos de ASP.NET, incluso si no se usa el resto de .NET Aspire como AppHost para orquestación. El proyecto Service Defaults está disponible como plantilla de proyecto a través de Visual Studio o dotnet new
. Configura OTel y configura el exportador OTLP. A continuación, puede usar las variables de entorno de OTel para configurar el punto de conexión de OTLP para enviar telemetría y proporcionar las propiedades de recursos para la aplicación.
Los pasos para usar ServiceDefaults fuera de .NET Aspire son:
Agregue el proyecto ServiceDefaults a la solución mediante Agregar nuevo proyecto en Visual Studio o use
dotnet new
:dotnet new aspire-servicedefaults --output ServiceDefaults
Haga referencia al proyecto ServiceDefaults desde la aplicación de ASP.NET. En Visual Studio, seleccione Agregar>Referencia de proyecto y seleccione el proyecto ServiceDefaults"
Llame a la función de configuración de OpenTelemetry
ConfigureOpenTelemetry()
como parte de la inicialización de su compilador de aplicaciones.var builder = WebApplication.CreateBuilder(args) builder.ConfigureOpenTelemetry(); // Extension method from ServiceDefaults. var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
Para ver un tutorial completo, consulte Ejemplo: Uso de OpenTelemetry con OTLP y el panel de Aspire independiente.
Seguimiento de conexiones experimentales
Cuando se resuelven problemas o cuellos de botella de HttpClient
, puede ser crucial ver en qué se emplea el tiempo al enviar solicitudes HTTP. A menudo, el problema se produce durante el establecimiento de la conexión HTTP, que normalmente se interrumpe en la búsqueda de DNS, la conexión TCP y el protocolo de enlace TLS.
.NET 9 introdujo el seguimiento de conexiones experimentales agregando un intervalo de HTTP connection setup
con tres intervalos secundarios que representan las fases DNS, TCP y TLS del establecimiento de la conexión. La parte HTTP del seguimiento de conexiones se implementa en SocketsHttpHandler, lo que significa que el modelo de actividad tiene que respetar el comportamiento de agrupación de conexiones subyacente.
Nota
En SocketsHttpHandler, las conexiones y las solicitudes tienen ciclos de vida independientes. Una conexión agrupada puede funcionar durante mucho tiempo y atender muchas solicitudes. Al realizar una solicitud, si no hay conexión disponible inmediatamente en el grupo de conexiones, la solicitud se agrega a una cola de solicitudes para esperar una conexión disponible. No hay ninguna relación directa entre las solicitudes en espera y las conexiones. Es posible que el proceso de conexión se haya iniciado cuando otra conexión esté disponible para su uso, en cuyo caso se usa la conexión libre. Como resultado, el intervalo HTTP connection setup
no se modela como un secundario del intervalo HTTP client request
; en su lugar, se utilizan enlaces de intervalos.
.NET 9 introdujo los siguientes intervalos para habilitar la recopilación de información detallada de conexión:
Nombre | ActivitySource | Descripción |
---|---|---|
HTTP wait_for_connection |
Experimental.System.Net.Http.Connections |
Un intervalo secundario del intervalo de HTTP client request que representa el intervalo de tiempo durante el cual la solicitud está esperando a que haya una conexión disponible en la cola de solicitudes. |
HTTP connection_setup |
Experimental.System.Net.Http.Connections |
Representa el establecimiento de la conexión HTTP. Un intervalo de raíz de seguimiento independiente con su propio TraceId . Los intervalos HTTP client request pueden contener vínculos a HTTP connection_setup . |
DNS lookup |
Experimental.System.Net.NameResolution |
Búsqueda DNS realizada por la clase Dns. |
socket connect |
Experimental.System.Net.Sockets |
Establecimiento de una conexión Socket. |
TLS handshake |
Experimental.System.Net.Security |
Protocolo de enlace de servidor o cliente TLS realizado por SslStream. |
Nota
Los nombres de ActivitySource
correspondientes comienzan con el prefijo Experimental
, ya que estos intervalos pueden cambiarse en versiones futuras a medida que aprendemos más sobre cómo funcionan en producción.
Estos intervalos son demasiado detallados para utilizarlos de forma ininterrumpida en escenarios de producción con cargas de trabajo altas: son ruidosos y este nivel de instrumentación no suele ser necesario. Sin embargo, si intenta diagnosticar problemas de conexión o comprender mejor cómo afecta la red y la latencia de conexión a los servicios, proporcionan información difícil de recopilar por otros medios.
Cuando ActivitySource de Experimental.System.Net.Http.Connections
está habilitado, el intervalo HTTP client request
contiene un vínculo al intervalo de HTTP connection_setup
correspondiente a la conexión que gestiona la solicitud. Como una conexión HTTP puede ser de larga duración, eso podría dar lugar a muchos vínculos al intervalo de conexión de cada una de las actividades de solicitud. Algunas herramientas de supervisión de APM recorren de forma agresiva los vínculos entre intervalos para crear sus vistas, por lo que incluir este intervalo puede causar problemas cuando las herramientas se han diseñado para tener en cuenta un gran número de vínculos.
En el diagrama siguiente se muestra el comportamiento de los intervalos y su relación:
Tutorial: Uso del seguimiento de conexiones experimentales en .NET 9
En este tutorial se usa una .NET Aspire 9 Starter App para demostrar el seguimiento de conexiones, pero debería ser fácil configurarlo también con otras herramientas de supervisión. El paso clave es habilitar ActivitySources.
Cree una .NET Aspire 9 Starter App utilizando
dotnet new
:dotnet new aspire-starter-9 --output ConnectionTracingDemo
O en Visual Studio:
Abra
Extensions.cs
en el proyectoServiceDefaults
y edite el métodoConfigureOpenTelemetry
añadiendo activitySources para la conexión en la devolución de llamada de configuración de seguimiento:.WithTracing(tracing => { tracing.AddAspNetCoreInstrumentation() // Instead of using .AddHttpClientInstrumentation() // .NET 9 allows to add the ActivitySources directly. .AddSource("System.Net.Http") // Add the experimental connection tracking ActivitySources using a wildcard. .AddSource("Experimental.System.Net.*"); });
Inicie la solución. Esto debería abrir el .NET Aspire Dashboard .
Navegue a la página Weather de la aplicación
webfrontend
para generar una solicitudHttpClient
haciaapiservice
.Vuelva al panel y vaya a la página Traces. Abra el seguimiento de
webfrontend: GET /weather
.
Cuando se realizan solicitudes HTTP con la instrumentación de conexión habilitada, debería ver los siguientes cambios en los intervalos de solicitudes de cliente:
- Si es necesario establecer una conexión o si la aplicación está esperando una conexión desde el grupo de conexiones, se muestra un intervalo de
HTTP wait_for_connection
adicional, que representa el retraso para esperar a que se realice una conexión. Esto ayuda a comprender los retrasos entre la solicitudHttpClient
que se realiza en el código, y cuando realmente se inicia el procesamiento de la solicitud. En la imagen anterior:- El rango seleccionado es la solicitud de HttpClient.
- El intervalo siguiente representa el tiempo que la solicitud dedica a esperar a que se establezca una conexión.
- El último intervalo en amarillo procede del destino que procesa la solicitud.
- El intervalo HttpClient tendrá un vínculo al intervalo de
HTTP connection_setup
, que representa la actividad para crear la conexión HTTP utilizada por la solicitud.
Como se mencionó anteriormente, el intervalo de HTTP connection_setup
es un intervalo independiente con su propio TraceId
, ya que su duración es independiente de cada solicitud de cliente individual. Este intervalo suele tener intervalos secundarios DNS lookup
, (TCP) socket connect
y TLS client handshake
.
Enriquecimiento
En algunos casos, es necesario aumentar la funcionalidad de seguimiento de System.Net
existente. Normalmente esto significa insertar etiquetas o atributos adicionales en las actividades integradas. Esto se denomina enriquecimiento.
API de enriquecimiento en la biblioteca de instrumentación de OpenTelemetry
Para agregar etiquetas o atributos adicionales a la actividad de solicitud de cliente HTTP, el enfoque más sencillo es usar las API de enriquecimiento de HttpClient
de la biblioteca de instrumentación HttpClient y HttpWebRequest de OpenTelemetry. Esto requiere depender del paquete OpenTelemetry.Instrumentation.Http
.
Enriquecimiento manual
Es posible implementar el enriquecimiento de la actividad HTTP client request
manualmente. Para ello, debe acceder a Activity.Current en el código que se ejecuta en el ámbito de la actividad de solicitud, antes de que finalice la actividad. Esto se puede hacer implementando un IObserver<DiagnosticListener>
y suscribiéndolo a AllListeners para obtener devoluciones de llamada cuando se produzca actividad de red. De hecho, así es como se implementa la biblioteca de instrumentación HttpClient y HttpWebRequest de OpenTelemetry. Para obtener un ejemplo de código, consulte el código de suscripción en DiagnosticSourceSubscriber.cs
y la implementación subyacente en HttpHandlerDiagnosticListener.cs en la que se deleguen las notificaciones.
¿Necesita más seguimiento?
Si tiene alguna sugerencia relativa a otra información de utilidad que podría exponerse a través de seguimientos, cree una incidencia de dotnet/runtime.