File: System\Net\Http\SocketsHttpHandler\ConnectionPool\ConnectionSetupDistributedTracing.cs
Web Access
Project: src\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
 
namespace System.Net.Http
{
    // Implements distributed tracing logic for managing the "HTTP connection_setup" and "HTTP wait_for_connection" Activities.
    internal static class ConnectionSetupDistributedTracing
    {
        private static readonly ActivitySource s_connectionsActivitySource = new ActivitySource(DiagnosticsHandlerLoggingStrings.ConnectionsNamespace);
 
        public static Activity? StartConnectionSetupActivity(bool isSecure, HttpAuthority authority)
        {
            Activity? activity = null;
            if (s_connectionsActivitySource.HasListeners())
            {
                // Connection activities should be new roots and not parented under whatever
                // request happens to be in progress when the connection is started.
                Activity.Current = null;
                activity = s_connectionsActivitySource.StartActivity(DiagnosticsHandlerLoggingStrings.ConnectionSetupActivityName);
            }
 
            if (activity is not null)
            {
                activity.DisplayName = $"HTTP connection_setup {authority.HostValue}:{authority.Port}";
                if (activity.IsAllDataRequested)
                {
                    activity.SetTag("server.address", authority.HostValue);
                    activity.SetTag("server.port", authority.Port);
                    activity.SetTag("url.scheme", isSecure ? "https" : "http");
                }
            }
 
            return activity;
        }
 
        public static void StopConnectionSetupActivity(Activity activity, Exception? exception, IPEndPoint? remoteEndPoint)
        {
            Debug.Assert(activity is not null);
            if (exception is not null)
            {
                ReportError(activity, exception);
            }
            else
            {
                if (activity.IsAllDataRequested && remoteEndPoint is not null)
                {
                    activity.SetTag("network.peer.address", remoteEndPoint.Address.ToString());
                }
            }
 
            activity.Stop();
        }
 
        public static void ReportError(Activity? activity, Exception exception)
        {
            Debug.Assert(exception is not null);
            if (activity is null) return;
            activity.SetStatus(ActivityStatusCode.Error);
 
            if (activity.IsAllDataRequested)
            {
                DiagnosticsHelper.TryGetErrorType(null, exception, out string? errorType);
                Debug.Assert(errorType is not null, "DiagnosticsHelper.TryGetErrorType() should succeed whenever an exception is provided.");
                activity.SetTag("error.type", errorType);
            }
        }
 
        public static Activity? StartWaitForConnectionActivity(HttpAuthority authority)
        {
            Activity? activity = s_connectionsActivitySource.StartActivity(DiagnosticsHandlerLoggingStrings.WaitForConnectionActivityName);
            if (activity is not null)
            {
                activity.DisplayName = $"HTTP wait_for_connection {authority.HostValue}:{authority.Port}";
            }
 
            return activity;
        }
 
        public static void AddConnectionLinkToRequestActivity(Activity connectionSetupActivity)
        {
            Debug.Assert(connectionSetupActivity is not null);
 
            // We only support links for request activities created by the "System.Net.Http" ActivitySource.
            if (DiagnosticsHandler.s_activitySource.HasListeners())
            {
                Activity? requestActivity = Activity.Current;
                if (requestActivity?.Source == DiagnosticsHandler.s_activitySource)
                {
                    requestActivity.AddLink(new ActivityLink(connectionSetupActivity.Context));
                }
            }
        }
    }
}