public void InitializerPopulatesTraceStateOnRequestAndDependencyTelemetry()
        {
            Activity a = new Activity("dummy")
                         .Start()
                         .GenerateW3CContext();

            a.SetTracestate("key=value");

            string expectedTrace  = a.GetTraceId();
            string expectedSpanId = a.GetSpanId();

            RequestTelemetry    request    = new RequestTelemetry();
            DependencyTelemetry dependency = new DependencyTelemetry();
            TraceTelemetry      trace      = new TraceTelemetry();
            var initializer = new W3COperationCorrelationTelemetryInitializer();

            initializer.Initialize(request);
            initializer.Initialize(dependency);
            initializer.Initialize(trace);

            Assert.AreEqual(expectedTrace, request.Context.Operation.Id);
            Assert.AreEqual($"|{expectedTrace}.{expectedSpanId}.", request.Id);

            Assert.AreEqual("key=value", request.Properties[W3CConstants.TracestateTag]);
            Assert.AreEqual("key=value", dependency.Properties[W3CConstants.TracestateTag]);
            Assert.IsFalse(trace.Properties.Any());
        }
        internal static RequestTelemetry CreateRequestTelemetryPrivate(
            this HttpContext platformContext)
        {
            if (platformContext == null)
            {
                throw new ArgumentNullException(nameof(platformContext));
            }

            var result          = new RequestTelemetry();
            var currentActivity = Activity.Current;
            var requestContext  = result.Context.Operation;

            if (currentActivity == null)
            {
                // if there was no BeginRequest, ASP.NET HttpModule did not have a chance to set current activity (and will never do it).
                currentActivity = new Activity(ActivityHelpers.RequestActivityItemName);

                if (ActivityHelpers.IsW3CTracingEnabled)
                {
                    ActivityHelpers.ExtractW3CContext(platformContext.Request, currentActivity);
                    ActivityHelpers.ExtractTracestate(platformContext.Request, currentActivity, result);
                    // length enforced in SetW3CContext
                    currentActivity.SetParentId(currentActivity.GetTraceId());
                    W3COperationCorrelationTelemetryInitializer.UpdateTelemetry(result, currentActivity, true);

                    SetLegacyContextIds(platformContext.Request, result);
                }
                else if (currentActivity.Extract(platformContext.Request.Headers))
                {
                    requestContext.ParentId = currentActivity.ParentId;
                }
                else if (ActivityHelpers.TryParseCustomHeaders(platformContext.Request, out var rootId, out var parentId))
                {
                    currentActivity.SetParentId(rootId);
                    if (!string.IsNullOrEmpty(parentId))
                    {
                        currentActivity.SetParentId(rootId);
                        if (!string.IsNullOrEmpty(parentId))
                        {
                            requestContext.ParentId = parentId;
                        }
                    }
                }
                else
                {
                    // As a first step in supporting W3C protocol in ApplicationInsights,
                    // we want to generate Activity Ids in the W3C compatible format.
                    // While .NET changes to Activity are pending, we want to ensure trace starts with W3C compatible Id
                    // as early as possible, so that everyone has a chance to upgrade and have compatibility with W3C systems once they arrive.
                    // So if there is no current Activity (i.e. there were no Request-Id header in the incoming request), we'll override ParentId on
                    // the current Activity by the properly formatted one. This workaround should go away
                    // with W3C support on .NET https://github.com/dotnet/corefx/issues/30331
                    currentActivity.SetParentId(StringUtilities.GenerateTraceId());
                    // end of workaround
                }

                currentActivity.Start();
            }
コード例 #3
0
        /// <summary>
        /// The function that needs to be called before sending a request to the server. Creates and initializes dependency telemetry item.
        /// </summary>
        /// <param name="telemetryClient">Telemetry client object to initialize the context of the telemetry item.</param>
        internal static DependencyTelemetry BeginTracking(TelemetryClient telemetryClient)
        {
            var telemetry = new DependencyTelemetry();

            telemetry.Start();
            Activity activity;
            Activity currentActivity = Activity.Current;

            // On .NET46 without profiler, outgoing requests are instrumented with reflection hook in DiagnosticSource
            //// see https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/HttpHandlerDiagnosticListener.cs
            // it creates an Activity and injects standard 'Request-Id' and 'Correlation-Context' headers itself, so we should not start Activity in this case
            if (currentActivity != null && currentActivity.OperationName == "System.Net.Http.Desktop.HttpRequestOut")
            {
                activity = currentActivity;

                // OperationCorrelationTelemetryInitializer will initialize telemetry as a child of current activity:
                // But we need to initialize dependency telemetry from the current Activity:
                // Activity was created for this dependency in the Http Desktop DiagnosticSource
                var context = telemetry.Context;
                context.Operation.Id       = activity.RootId;
                context.Operation.ParentId = activity.ParentId;
                foreach (var item in activity.Baggage)
                {
                    if (!telemetry.Properties.ContainsKey(item.Key))
                    {
                        telemetry.Properties.Add(item);
                    }
                }

                telemetryClient.Initialize(telemetry);
            }
            else
            {
                telemetryClient.Initialize(telemetry);

                // Every operation must have its own Activity
                // if dependency is tracked with profiler of event source, we need to generate a proper Id for it
                // in case of HTTP it will be propagated into the requert header.
                // So, we will create a new Activity for the dependency, just to generate an Id.
                activity = new Activity(DependencyActivityName);

                // As a first step in supporting W3C protocol in ApplicationInsights,
                // we want to generate Activity Ids in the W3C compatible format.
                // While .NET changes to Activity are pending, we want to ensure trace starts with W3C compatible Id
                // as early as possible, so that everyone has a chance to upgrade and have compatibility with W3C systems once they arrive.
                // So if there is no parent Activity (i.e. this request has happened in the background, without parent scope), we'll override
                // the current Activity with the one with properly formatted Id. This workaround should go away
                // with W3C support on .NET https://github.com/dotnet/corefx/issues/30331 (TODO)
                if (currentActivity == null)
                {
                    activity.SetParentId(StringUtilities.GenerateTraceId());
                }

                // end of workaround

                activity.Start();
            }

            // telemetry is initialized from current Activity (root and parent Id, but not the Id)
            telemetry.Id = activity.Id;

            // set operation root Id in case there was no parent activity (e.g. HttpRequest in background thread)
            if (string.IsNullOrEmpty(telemetry.Context.Operation.Id))
            {
                telemetry.Context.Operation.Id = activity.RootId;
            }

#pragma warning disable 612, 618
            if (IsW3CEnabled)
            {
                W3COperationCorrelationTelemetryInitializer.UpdateTelemetry(telemetry, activity, true);
            }
#pragma warning restore 612, 618

            PretendProfilerIsAttached = false;
            return(telemetry);
        }