/// <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(); telemetryClient.Initialize(telemetry); #if NET45 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; } else { // Every operation must have its own Activity // if dependency is tracked with profiler of event source, we need to generate a proper hierarchical 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, jut to generate an Id. activity = new Activity(DependencyActivityName); // This is workaround for the issue https://github.com/Microsoft/ApplicationInsights-dotnet/issues/538 // if there is no parent Activity, ID Activity generates is not random enough to work well with // ApplicationInsights sampling algorithm // This code should go away when Activity is fixed: https://github.com/dotnet/corefx/issues/18418 if (Activity.Current == null) { activity.SetParentId(telemetry.Id); } //// end of workaround activity.Start(); activity.Stop(); } // 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; } #else // telemetry is initialized by Base SDK OperationCorrealtionTelemetryInitializer // however it does not know about Activity on .NET40 and does not know how to properly generate Ids // let's fix it telemetry.Id = ApplicationInsightsActivity.GenerateDependencyId(telemetry.Context.Operation.ParentId); telemetry.Context.Operation.Id = ApplicationInsightsActivity.GetRootId(telemetry.Id); #endif PretendProfilerIsAttached = false; return(telemetry); }
public void RddTestHttpDesktopProcessingFrameworkOnBeginAddsParentIdHeader() { var request = WebRequest.Create(this.testUrl); Assert.IsNull(request.Headers[RequestResponseHeaders.StandardParentIdHeader]); var client = new TelemetryClient(this.configuration); using (var op = client.StartOperation <RequestTelemetry>("request")) { this.httpDesktopProcessingFramework.OnBegin(request); var actualParentIdHeader = request.Headers[RequestResponseHeaders.StandardParentIdHeader]; var actualRequestIdHeader = request.Headers[RequestResponseHeaders.RequestIdHeader]; Assert.IsNotNull(actualParentIdHeader); Assert.AreNotEqual(actualParentIdHeader, op.Telemetry.Context.Operation.Id); Assert.AreEqual(actualParentIdHeader, actualRequestIdHeader); #if NET45 Assert.IsTrue(actualRequestIdHeader.StartsWith(Activity.Current.Id, StringComparison.Ordinal)); Assert.AreNotEqual(Activity.Current.Id, actualRequestIdHeader); #else Assert.AreEqual(op.Telemetry.Context.Operation.Id, ApplicationInsightsActivity.GetRootId(request.Headers[RequestResponseHeaders.StandardParentIdHeader])); #endif // This code should go away when Activity is fixed: https://github.com/dotnet/corefx/issues/18418 // check that Ids are not generated by Activity // so they look like OperationTelemetry.Id var operationId = op.Telemetry.Context.Operation.Id; // length is like default RequestTelemetry.Id length Assert.AreEqual(new DependencyTelemetry().Id.Length, operationId.Length); // operationId is ulong base64 encoded byte[] data = Convert.FromBase64String(operationId); Assert.AreEqual(8, data.Length); BitConverter.ToUInt64(data, 0); // does not look like root Id generated by Activity Assert.AreEqual(1, operationId.Split('-').Length); //// end of workaround test } }