internal static RequestTelemetry CreateRequestTelemetryPrivate()

in WEB/Src/Web/Web/Implementation/RequestTrackingExtensions.cs [14:132]


        internal static RequestTelemetry CreateRequestTelemetryPrivate(
            this HttpContext platformContext)
        {
            if (platformContext == null)
            {
                throw new ArgumentNullException(nameof(platformContext));
            }

            var currentActivity = Activity.Current;

            var result = new RequestTelemetry();
            var requestContext = result.Context.Operation;
            string legacyParentId = null;
            string legacyRootId = null;

            var headers = platformContext.Request.Unvalidated.Headers;
            if (currentActivity == null)
            {
                // if there was no BeginRequest, ASP.NET HttpModule did not have a chance to set current activity yet
                // this could happen if ASP.NET TelemetryCorrelation module is not the first in the pipeline
                // and some module before it tracks telemetry.
                // The ASP.NET module will be invoked later with proper correlation ids.
                // But we only get one chance to create request telemetry and we have to create it when method is called to avoid breaking changes 
                // The correlation will be BROKEN anyway as telemetry reported before ASP.NET TelemetryCorrelation HttpModule is called
                // will not be correlated  properly to telemetry reported within the request 
                // Here we simply maintaining backward compatibility with this behavior...

#pragma warning disable CA2000 // Dispose objects before losing scope
                // Since we don't know when it will finish, we will not dispose
                currentActivity = new Activity(ActivityHelpers.RequestActivityItemName);
#pragma warning restore CA2000 // Dispose objects before losing scope
                if (!currentActivity.Extract(headers))
                {
                    if (ActivityHelpers.ParentOperationIdHeaderName != null &&
                        ActivityHelpers.RootOperationIdHeaderName != null)
                    {
                        legacyRootId = StringUtilities.EnforceMaxLength(platformContext.Request.UnvalidatedGetHeader(ActivityHelpers.RootOperationIdHeaderName),
                            InjectionGuardConstants.RequestHeaderMaxLength);
                        legacyParentId = StringUtilities.EnforceMaxLength(
                            platformContext.Request.UnvalidatedGetHeader(ActivityHelpers.ParentOperationIdHeaderName),
                            InjectionGuardConstants.RequestHeaderMaxLength);
                        currentActivity.SetParentId(legacyRootId);
                    }

                    headers.ReadActivityBaggage(currentActivity);
                }

                currentActivity.Start();
            }

            if (currentActivity.IdFormat == ActivityIdFormat.W3C && 
                currentActivity.ParentId != null 
                && !currentActivity.ParentId.StartsWith("00-", StringComparison.Ordinal))
            {
                if (W3CUtilities.TryGetTraceId(currentActivity.ParentId, out var traceId))
                {
                    legacyParentId = currentActivity.ParentId;
#pragma warning disable CA2000 // Dispose objects before losing scope
                    // Since we don't know when it will finish, we will not dispose
                    currentActivity = CreateSubstituteActivityFromCompatibleRootId(currentActivity, traceId);
#pragma warning restore CA2000 // Dispose objects before losing scope
                }
                else
                {
                    legacyRootId = W3CUtilities.GetRootId(currentActivity.ParentId);
                    legacyParentId = legacyParentId ?? GetLegacyParentId(currentActivity.ParentId, platformContext.Request);
                }
            }
            else if (currentActivity.IdFormat == ActivityIdFormat.Hierarchical &&
                     currentActivity.ParentId != null)
            {
                legacyParentId = GetLegacyParentId(currentActivity.ParentId, platformContext.Request);
            }

            if (currentActivity.IdFormat == ActivityIdFormat.W3C)
            {
                // we have Activity.Current, we need to properly initialize request telemetry and store it in HttpContext
                requestContext.Id = currentActivity.TraceId.ToHexString();

                if (currentActivity.ParentSpanId != default && legacyParentId == null)
                {
                    requestContext.ParentId = currentActivity.ParentSpanId.ToHexString();
                }
                else
                {
                    requestContext.ParentId = legacyParentId;
                    if (legacyRootId != null)
                    {
                        result.Properties[W3CConstants.LegacyRootPropertyIdKey] = legacyRootId;
                    }
                }

                result.Id = currentActivity.SpanId.ToHexString();
            }
            else
            {
                // we have Activity.Current, we need to properly initialize request telemetry and store it in HttpContext
                requestContext.Id = currentActivity.RootId;
                requestContext.ParentId = legacyParentId ?? currentActivity.ParentId;

                result.Id = currentActivity.Id;
            }

            foreach (var item in currentActivity.Baggage)
            {
                if (!result.Properties.ContainsKey(item.Key))
                {
                    result.Properties.Add(item);
                }
            }

            // save current activity in case it will be lost (under the same name TelemetryCorrelation stores it)
            // TelemetryCorrelation will restore it when possible.
            platformContext.Items[ActivityHelpers.RequestActivityItemName] = currentActivity;
            platformContext.Items[RequestTrackingConstants.RequestTelemetryItemName] = result;
            WebEventSource.Log.WebTelemetryModuleRequestTelemetryCreated();

            return result;
        }