Example #1
0
        public void BeginWebTrackingReturnsOperationItemWithTelemetryItem()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            Assert.AreEqual(telemetry.StartTime, telemetry.StartTime);
            Assert.AreEqual(telemetry.Timestamp, telemetry.Timestamp);
        }
Example #2
0
        /// <summary>
        /// On begin callback from Framework event source.
        /// </summary>
        /// <param name="id">Identifier of SQL connection object.</param>
        /// <param name="dataSource">Data source name.</param>
        /// <param name="database">Database name.</param>
        /// <param name="commandText">Command text.</param>
        public void OnBeginExecuteCallback(long id, string dataSource, string database, string commandText)
        {
            try
            {
                var resourceName = this.GetResourceName(dataSource, database, commandText);

                DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginSql", "resourceName is empty");
                    return;
                }

                var telemetryTuple = this.TelemetryTable.Get(id);
                if (telemetryTuple == null)
                {
                    bool isCustomCreated = false;
                    var  telemetry       = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);
                    telemetry.Name           = resourceName;
                    telemetry.DependencyKind = RemoteDependencyKind.SQL.ToString();
                    this.TelemetryTable.Store(id, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(id, "OnBeginSql", exception);
            }
        }
Example #3
0
        public void EndTrackingComputesTheDurationOfTelemetryItem()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            var telemetryItem = this.sendItems[0] as DependencyTelemetry;

            this.ValidateSentTelemetry(telemetryItem);
        }
        /// <summary>
        /// On begin callback from Framework event source.
        /// </summary>
        /// <param name="id">This object.</param>
        /// <param name="resourceName">URI of the web request.</param>
        public void OnBeginHttpCallback(long id, string resourceName)
        {
            try
            {
                DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginHttp", "resourceName is empty");
                    return;
                }

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(resourceName))
                {
                    return;
                }

                Uri url;
                try
                {
                    url = new Uri(resourceName);
                }
                catch (UriFormatException)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginHttp", "resourceName is not a URL " + resourceName);
                    return;
                }

                var telemetryTuple = this.TelemetryTable.Get(id);

                if (telemetryTuple != null)
                {
                    // this operation is already being tracked. We will not restart operation
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return;
                    }
                }

                bool isCustomCreated = false;

                var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Name   = url.AbsolutePath;
                telemetry.Target = url.Host;
                telemetry.Data   = url.OriginalString;

                this.TelemetryTable.Store(id, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(id, "OnBeginHttp", exception);
            }
        }
        /// <summary>
        ///  Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="isAsyncCall">Is Async Invocation.</param>
        /// <returns>The context for end callback.</returns>
        private object OnBegin(object thisObj, bool isAsyncCall)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginSql", "thisObj == null");
                    return(null);
                }

                string resourceName = this.GetResourceName(thisObj);
                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginSql", "resourceName is empty");
                    return(null);
                }

                var telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    // The BeginExecuteReader method returns immediately, but until the code executes the corresponding EndExecuteReader method call,
                    // it must not execute any other calls that start a synchronous or asynchronous execution against the same SqlCommand object.
                    // howeever if customer tries to execute such call we need clean the watch state as command execution is incorrect to not report the wrong data.
                    // note: This particular case is not dealt with in HTTP case.
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                string commandText = this.GetCommandName(thisObj);

                // Try to begin if sampling this operation
                bool isCustomCreated = false;
                var  telemetry       = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name           = resourceName;
                telemetry.DependencyKind = RemoteDependencyKind.SQL.ToString();
                telemetry.CommandName    = commandText;

                // We use weaktables to store the thisObj for correlating begin with end call.
                this.TelemetryTable.Store(thisObj, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
                return(null);
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginSql", exception);
            }

            return(null);
        }
Example #6
0
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="isAsyncCall">Indicates if the method used is async or not.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        private object OnBegin(object thisObj, bool isAsyncCall)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                string resourceName = this.GetResourceName(thisObj);

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp", "resourceName is empty");
                    return(null);
                }

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(resourceName))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                // If the object already exists, dont add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                var telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                bool isCustomCreated = false;

                var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name           = resourceName;
                telemetry.DependencyKind = RemoteDependencyKind.Http.ToString();

                this.TelemetryTable.Store(thisObj, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", exception);
            }

            return(null);
        }
Example #7
0
        public void BeginWebTrackingReturnsOperationItemWithTelemetryItem()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            Assert.AreEqual(telemetry.Timestamp, telemetry.Timestamp);

            Assert.IsNull(telemetry.Context.Operation.ParentId);
            Assert.IsNotNull(telemetry.Context.Operation.Id);
            Assert.IsTrue(telemetry.Id.StartsWith('|' + telemetry.Context.Operation.Id, StringComparison.Ordinal));
            Assert.AreEqual(0, telemetry.Context.Properties.Count);
        }
Example #8
0
        public void EndTrackingSendsTelemetryItemOnSuccess()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            Assert.AreEqual(1, this.sendItems.Count);

            telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);
            ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            Assert.AreEqual(2, this.sendItems.Count);
        }
        /// <summary>
        ///  Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <returns>The context for end callback.</returns>
        private object OnBegin(object thisObj)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginSql", "thisObj == null");
                    return(null);
                }

                string resourceName = this.GetDependencyName(thisObj);
                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginSql", "resourceName is empty");
                    return(null);
                }

                var telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    // We are already tracking this item
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                string commandText = this.GetCommandName(thisObj);

                // Try to begin if sampling this operation
                bool isCustomCreated = false;
                var  telemetry       = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name   = resourceName;
                telemetry.Type   = RemoteDependencyConstants.SQL;
                telemetry.Target = this.GetDependencyTarget(thisObj);
                telemetry.Data   = commandText;
                telemetry.SetOperationDetail(RemoteDependencyConstants.SqlCommandOperationDetailName, thisObj);

                // We use weaktables to store the thisObj for correlating begin with end call.
                this.TelemetryTable.Store(thisObj, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
                return(null);
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginSql", exception);
            }

            return(null);
        }
Example #10
0
        public void EndTrackingTracksTelemetryItemWithInitializedContent()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            var telemetryItem = this.sendItems[0] as DependencyTelemetry;

            Assert.IsNotNull(telemetryItem.Context.User.Id);
            Assert.IsNotNull(telemetryItem.Context.Session.Id);
            Assert.AreEqual(telemetryItem.Context.User.Id, "UserID");
            Assert.AreEqual(telemetryItem.Context.Session.Id, "SessionID");
        }
        /// <summary>
        /// On begin callback from Framework event source.
        /// </summary>
        /// <param name="id">Identifier of SQL connection object.</param>
        /// <param name="dataSource">Data source name.</param>
        /// <param name="database">Database name.</param>
        /// <param name="commandText">Command text.</param>
        public void OnBeginExecuteCallback(long id, string dataSource, string database, string commandText)
        {
            try
            {
                var resourceName = this.GetResourceName(dataSource, database, commandText);

                DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginSql", "resourceName is empty");
                    return;
                }

                var telemetryTuple = this.TelemetryTable.Get(id);
                if (telemetryTuple == null)
                {
                    bool isCustomCreated = false;
                    var  telemetry       = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);
                    telemetry.Name           = resourceName;
                    telemetry.DependencyKind = RemoteDependencyKind.SQL.ToString();
                    this.TelemetryTable.Store(id, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
                }
                else
                {
                    // The BeginExecuteReader method returns immediately, but until the code executes the corresponding EndExecuteReader method call,
                    // it must not execute any other calls that start a synchronous or asynchronous execution against the same SqlCommand object.
                    // howeever if customer tries to execute such call we need clean the watch state as command execution is incorrect to not report the wrong data.
                    // note: This particular case is not dealt with in HTTP case.
                    if (!telemetryTuple.Item2)
                    {
                        this.TelemetryTable.Remove(id);
                    }

                    DependencyCollectorEventSource.Log.RemoteDependencyModuleVerbose("SqlProcessingFramework.OnBegin removed the entry from cache to prevent incorrect information for " + resourceName);
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(id, "OnBeginSql", exception);
            }
        }
        /// <summary>
        /// On begin callback from Framework event source.
        /// </summary>
        /// <param name="id">This object.</param>
        /// <param name="resourceName">URI of the web request.</param>
        public void OnBeginHttpCallback(long id, string resourceName)
        {
            try
            {
                DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginHttp", "resourceName is empty");
                    return;
                }

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(resourceName))
                {
                    return;
                }

                var telemetryTuple = this.TelemetryTable.Get(id);

                if (telemetryTuple != null)
                {
                    // this operation is already being tracked. We will not restart operation
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return;
                    }
                }

                bool isCustomCreated = false;

                var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name = resourceName;

                this.TelemetryTable.Store(id, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(id, "OnBeginHttp", exception);
            }
        }
        public void BeginWebTrackingWithParentActivityReturnsOperationItemWithTelemetryItem()
        {
            var parentActivity = new Activity("test");

            parentActivity.SetParentId("|guid.1234_");
            parentActivity.AddBaggage("k", "v");

            parentActivity.Start();

            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            Assert.AreEqual(parentActivity.Id, telemetry.Context.Operation.ParentId);
            Assert.AreEqual(parentActivity.RootId, telemetry.Context.Operation.Id);

            var properties = telemetry.Context.Properties;

            Assert.AreEqual(1, properties.Count);
            Assert.AreEqual("v", properties["k"]);
            parentActivity.Stop();
        }
Example #14
0
        public void BeginWebTrackingWithParentCallContextReturnsOperationItemWithTelemetryItem()
        {
            var requestTelemetry = new RequestTelemetry {
                Id = "|guid.1234_"
            };
            var correlationContext = new Dictionary <string, string> {
                ["k"] = "v"
            };

            CorrelationHelper.SetOperationContext(requestTelemetry, correlationContext);

            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            Assert.AreEqual("|guid.1234_", telemetry.Context.Operation.ParentId);
            Assert.AreEqual("guid", telemetry.Context.Operation.Id);

            var properties = telemetry.Context.Properties;

            Assert.AreEqual(1, properties.Count);
            Assert.AreEqual("v", properties["k"]);
            CorrelationHelper.CleanOperationContext();
        }
Example #15
0
        /// <summary>
        /// On begin callback from Framework event source.
        /// </summary>
        /// <param name="id">Identifier of SQL connection object.</param>
        /// <param name="dataSource">Data source name.</param>
        /// <param name="database">Database name.</param>
        /// <param name="commandText">Command text.</param>
        public void OnBeginExecuteCallback(long id, string dataSource, string database, string commandText)
        {
            try
            {
                var resourceName = GetResourceName(dataSource, database);

                DependencyCollectorEventSource.Log.BeginCallbackCalled(id, resourceName);

                if (string.IsNullOrEmpty(resourceName))
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(id, "OnBeginSql", "resourceName is empty");
                    return;
                }

                var telemetryTuple = this.TelemetryTable.Get(id);
                if (telemetryTuple == null)
                {
                    var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);
                    telemetry.Name   = resourceName;
                    telemetry.Target = string.Join(" | ", dataSource, database);
                    telemetry.Type   = RemoteDependencyConstants.SQL;
                    telemetry.Data   = commandText;
                    this.TelemetryTable.Store(id, new Tuple <DependencyTelemetry, bool>(telemetry, false));
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(id, "OnBeginSql", exception);
            }
            finally
            {
                Activity current = Activity.Current;
                if (current?.OperationName == ClientServerDependencyTracker.DependencyActivityName)
                {
                    current.Stop();
                }
            }
        }
Example #16
0
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="isAsyncCall">Indicates if the method used is async or not.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        private object OnBegin(object thisObj, bool isAsyncCall)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                WebRequest webRequest = thisObj as WebRequest;
                if (webRequest == null)
                {
                    DependencyCollectorEventSource.Log.UnexpectedCallbackParameter("WebRequest");
                }

                var url = this.GetUrl(webRequest);

                if (url == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp", "resourceName is empty");
                    return(null);
                }

                string httMethod    = webRequest.Method;
                string resourceName = url.AbsolutePath;

                if (!string.IsNullOrEmpty(httMethod))
                {
                    resourceName = httMethod + " " + resourceName;
                }

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(url.ToString()))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                // If the object already exists, dont add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                var telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                bool isCustomCreated = false;

                var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name   = resourceName;
                telemetry.Target = url.Host;
                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Data   = url.OriginalString;

                this.TelemetryTable.Store(thisObj, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", exception);
            }

            return(null);
        }
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="isAsyncCall">Indicates if the method used is async or not.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        private object OnBegin(object thisObj, bool isAsyncCall)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                WebRequest webRequest = thisObj as WebRequest;
                if (webRequest == null)
                {
                    DependencyCollectorEventSource.Log.UnexpectedCallbackParameter("WebRequest");
                }

                var url = this.GetUrl(webRequest);

                if (url == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp", "resourceName is empty");
                    return(null);
                }

                string httMethod    = webRequest.Method;
                string resourceName = url.AbsolutePath;

                if (!string.IsNullOrEmpty(httMethod))
                {
                    resourceName = httMethod + " " + resourceName;
                }

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(url.ToString()))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                // If the object already exists, don't add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                var telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    if (telemetryTuple.Item1 != null)
                    {
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                bool isCustomCreated = false;

                var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                telemetry.Name   = resourceName;
                telemetry.Target = DependencyTargetNameHelper.GetDependencyTargetName(url);
                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Data   = url.OriginalString;

                this.TelemetryTable.Store(thisObj, new Tuple <DependencyTelemetry, bool>(telemetry, isCustomCreated));

                if (string.IsNullOrEmpty(telemetry.Context.InstrumentationKey))
                {
                    // Instrumentation key is probably empty, because the context has not yet had a chance to associate the requestTelemetry to the telemetry client yet.
                    // and get they instrumentation key from all possible sources in the process. Let's do that now.
                    this.telemetryClient.Initialize(telemetry);
                }

                // Add the source instrumentation key header if collection is enabled, the request host is not in the excluded list and the same header doesn't already exist
                if (this.setCorrelationHeaders &&
                    !this.correlationDomainExclusionList.Contains(url.Host))
                {
                    if (!string.IsNullOrEmpty(telemetry.Context.InstrumentationKey) &&
                        webRequest.Headers[RequestResponseHeaders.SourceInstrumentationKeyHeader] == null)
                    {
                        webRequest.Headers.Add(RequestResponseHeaders.SourceInstrumentationKeyHeader, InstrumentationKeyHashLookupHelper.GetInstrumentationKeyHash(telemetry.Context.InstrumentationKey));
                    }

                    // Add the root ID
                    var rootId = telemetry.Context.Operation.Id;
                    if (!string.IsNullOrEmpty(rootId) && webRequest.Headers[RequestResponseHeaders.StandardRootIdHeader] == null)
                    {
                        webRequest.Headers.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                    }

                    // Add the parent ID
                    var parentId = telemetry.Id;
                    if (!string.IsNullOrEmpty(parentId) && webRequest.Headers[RequestResponseHeaders.StandardParentIdHeader] == null)
                    {
                        webRequest.Headers.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                    }
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", exception);
            }

            return(null);
        }
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="injectCorrelationHeaders">Flag that enables Request-Id and Correlation-Context headers injection.
        /// Should be set to true only for profiler and old versions of DiagnosticSource Http hook events.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        internal object OnBegin(object thisObj, bool injectCorrelationHeaders = true)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                WebRequest webRequest = thisObj as WebRequest;
                if (webRequest == null)
                {
                    DependencyCollectorEventSource.Log.UnexpectedCallbackParameter("WebRequest");
                }

                var url = GetUrl(webRequest);
                if (url == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp",
                                                                           "resourceName is empty");
                    return(null);
                }

                string httpMethod   = webRequest.Method;
                string resourceName = url.AbsolutePath;

                if (!string.IsNullOrEmpty(httpMethod))
                {
                    resourceName = httpMethod + " " + resourceName;
                }

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(url))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                if (webRequest.Headers[W3C.W3CConstants.TraceParentHeader] != null && Activity.DefaultIdFormat == ActivityIdFormat.W3C)
                {
                    DependencyCollectorEventSource.Log.HttpRequestAlreadyInstrumented();
                    return(null);
                }

                // If the object already exists, don't add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                DependencyTelemetry telemetry = null;
                var telemetryTuple            = this.GetTupleForWebDependencies(webRequest);
                if (telemetryTuple?.Item1 != null)
                {
                    DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                    return(null);
                }

                // Create and initialize a new telemetry object
                telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                this.AddTupleForWebDependencies(webRequest, telemetry, false);

                if (string.IsNullOrEmpty(telemetry.Context.InstrumentationKey))
                {
                    // Instrumentation key is probably empty, because the context has not yet had a chance to associate the requestTelemetry to the telemetry client yet.
                    // and get they instrumentation key from all possible sources in the process. Let's do that now.
                    this.telemetryClient.InitializeInstrumentationKey(telemetry);
                }

                telemetry.Name   = resourceName;
                telemetry.Target = DependencyTargetNameHelper.GetDependencyTargetName(url);
                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Data   = url.OriginalString;
                telemetry.SetOperationDetail(RemoteDependencyConstants.HttpRequestOperationDetailName, webRequest);

                Activity currentActivity = Activity.Current;
                // Add the source instrumentation key header if collection is enabled, the request host is not in the excluded list and the same header doesn't already exist
                if (this.setCorrelationHeaders && !this.correlationDomainExclusionList.Contains(url.Host))
                {
                    string applicationId = null;
                    try
                    {
                        if (!string.IsNullOrEmpty(telemetry.Context.InstrumentationKey) &&
                            webRequest.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader,
                                                                       RequestResponseHeaders.RequestContextCorrelationSourceKey) == null &&
                            (this.configuration.ApplicationIdProvider?.TryGetApplicationId(
                                 telemetry.Context.InstrumentationKey, out applicationId) ?? false))
                        {
                            webRequest.Headers.SetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader,
                                                                       RequestResponseHeaders.RequestContextCorrelationSourceKey, applicationId);
                        }
                    }
                    catch (Exception ex)
                    {
                        AppMapCorrelationEventSource.Log.SetCrossComponentCorrelationHeaderFailed(
                            ex.ToInvariantString());
                    }

                    if (this.injectLegacyHeaders)
                    {
                        // Add the root ID
                        var rootId = telemetry.Context.Operation.Id;
                        if (!string.IsNullOrEmpty(rootId) &&
                            webRequest.Headers[RequestResponseHeaders.StandardRootIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                        }

                        // Add the parent ID
                        var parentId = telemetry.Id;
                        if (!string.IsNullOrEmpty(parentId))
                        {
                            if (webRequest.Headers[RequestResponseHeaders.StandardParentIdHeader] == null)
                            {
                                webRequest.Headers.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                            }
                        }
                    }

                    if (currentActivity != null)
                    {
                        // ApplicationInsights only needs to inject W3C, potentially Request-Id and Correlation-Context
                        // headers for profiler instrumentation.
                        // in case of Http Desktop DiagnosticSourceListener they are injected in
                        // DiagnosticSource (with the System.Net.Http.Desktop.HttpRequestOut.Start event)
                        if (injectCorrelationHeaders)
                        {
                            if (currentActivity.IdFormat == ActivityIdFormat.W3C)
                            {
                                if (webRequest.Headers[W3C.W3CConstants.TraceParentHeader] == null)
                                {
                                    webRequest.Headers.Add(W3C.W3CConstants.TraceParentHeader, currentActivity.Id);
                                }

                                if (webRequest.Headers[W3C.W3CConstants.TraceStateHeader] == null &&
                                    !string.IsNullOrEmpty(currentActivity.TraceStateString))
                                {
                                    webRequest.Headers.Add(W3C.W3CConstants.TraceStateHeader,
                                                           currentActivity.TraceStateString);
                                }
                            }
                            else
                            {
                                // Request-Id format
                                if (webRequest.Headers[RequestResponseHeaders.RequestIdHeader] == null)
                                {
                                    webRequest.Headers.Add(RequestResponseHeaders.RequestIdHeader, telemetry.Id);
                                }
                            }

                            InjectCorrelationContext(webRequest.Headers, currentActivity);
                        }
                    }
                }

                // Active bug in .NET Fx diagnostics hook: https://github.com/dotnet/corefx/pull/40777
                // Application Insights has to inject Request-Id to work it around
                if (currentActivity?.IdFormat == ActivityIdFormat.W3C)
                {
                    // if (this.injectRequestIdInW3CMode)
                    {
                        if (webRequest.Headers[RequestResponseHeaders.RequestIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.RequestIdHeader, string.Concat('|', telemetry.Context.Operation.Id, '.', telemetry.Id, '.'));
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(),
                                                                 "OnBeginHttp", exception);
            }
            finally
            {
                Activity current = Activity.Current;
                if (current?.OperationName == ClientServerDependencyTracker.DependencyActivityName)
                {
                    current.Stop();
                }
            }

            return(null);
        }
        /// <summary>
        /// Common helper for all Begin Callbacks.
        /// </summary>
        /// <param name="thisObj">This object.</param>
        /// <param name="injectCorrelationHeaders">Flag that enables Request-Id and Correlation-Context headers injection.
        /// Should be set to true only for profiler and old versions of DiagnosticSource Http hook events.</param>
        /// <returns>Null object as all context is maintained in this class via weak tables.</returns>
        internal object OnBegin(object thisObj, bool injectCorrelationHeaders = true)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return(null);
                }

                WebRequest webRequest = thisObj as WebRequest;
                if (webRequest == null)
                {
                    DependencyCollectorEventSource.Log.UnexpectedCallbackParameter("WebRequest");
                }

                var url = this.GetUrl(webRequest);

                if (url == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(thisObj.GetHashCode(), "OnBeginHttp", "resourceName is empty");
                    return(null);
                }

                string httpMethod   = webRequest.Method;
                string resourceName = url.AbsolutePath;

                if (!string.IsNullOrEmpty(httpMethod))
                {
                    resourceName = httpMethod + " " + resourceName;
                }

                DependencyCollectorEventSource.Log.BeginCallbackCalled(thisObj.GetHashCode(), resourceName);

                if (this.applicationInsightsUrlFilter.IsApplicationInsightsUrl(url))
                {
                    // Not logging as we will be logging for all outbound AI calls
                    return(null);
                }

                // If the object already exists, don't add again. This happens because either GetResponse or GetRequestStream could
                // be the starting point for the outbound call.
                DependencyTelemetry telemetry = null;
                var telemetryTuple            = this.GetTupleForWebDependencies(webRequest);
                if (telemetryTuple != null)
                {
                    if (telemetryTuple.Item1 != null)
                    {
                        telemetry = telemetryTuple.Item1;
                        DependencyCollectorEventSource.Log.TrackingAnExistingTelemetryItemVerbose();
                        return(null);
                    }
                }

                // Create and initialize a new telemetry object if needed
                if (telemetry == null)
                {
                    bool isCustomCreated = false;

                    telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

                    this.AddTupleForWebDependencies(webRequest, telemetry, isCustomCreated);

                    if (string.IsNullOrEmpty(telemetry.Context.InstrumentationKey))
                    {
                        // Instrumentation key is probably empty, because the context has not yet had a chance to associate the requestTelemetry to the telemetry client yet.
                        // and get they instrumentation key from all possible sources in the process. Let's do that now.
                        this.telemetryClient.Initialize(telemetry);
                    }
                }

                telemetry.Name   = resourceName;
                telemetry.Target = DependencyTargetNameHelper.GetDependencyTargetName(url);
                telemetry.Type   = RemoteDependencyConstants.HTTP;
                telemetry.Data   = url.OriginalString;

                // Add the source instrumentation key header if collection is enabled, the request host is not in the excluded list and the same header doesn't already exist
                if (this.setCorrelationHeaders &&
                    !this.correlationDomainExclusionList.Contains(url.Host))
                {
                    try
                    {
                        if (!string.IsNullOrEmpty(telemetry.Context.InstrumentationKey) &&
                            webRequest.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationSourceKey) == null)
                        {
                            string appId;
                            if (this.correlationIdLookupHelper.TryGetXComponentCorrelationId(telemetry.Context.InstrumentationKey, out appId))
                            {
                                webRequest.Headers.SetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationSourceKey, appId);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        AppMapCorrelationEventSource.Log.SetCrossComponentCorrelationHeaderFailed(ex.ToInvariantString());
                    }

                    // Add the root ID
                    var rootId = telemetry.Context.Operation.Id;
                    if (!string.IsNullOrEmpty(rootId) && webRequest.Headers[RequestResponseHeaders.StandardRootIdHeader] == null)
                    {
                        webRequest.Headers.Add(RequestResponseHeaders.StandardRootIdHeader, rootId);
                    }

                    // Add the parent ID
                    var parentId = telemetry.Id;
                    if (!string.IsNullOrEmpty(parentId))
                    {
                        if (webRequest.Headers[RequestResponseHeaders.StandardParentIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.StandardParentIdHeader, parentId);
                        }
                    }

                    // ApplicationInsights only need to inject Request-Id and Correlation-Context headers
                    // for profiler instrumentation, in case of Http Desktop DiagnosticSourceListener
                    // they are injected in DiagnosticSource (with the System.Net.Http.Desktop.HttpRequestOut.Start event)
                    if (injectCorrelationHeaders)
                    {
                        if (webRequest.Headers[RequestResponseHeaders.RequestIdHeader] == null)
                        {
                            webRequest.Headers.Add(RequestResponseHeaders.RequestIdHeader, telemetry.Id);
                        }

                        if (webRequest.Headers[RequestResponseHeaders.CorrelationContextHeader] == null)
                        {
                            var currentActivity = Activity.Current;
                            if (currentActivity != null && currentActivity.Baggage.Any())
                            {
                                webRequest.Headers.SetHeaderFromNameValueCollection(RequestResponseHeaders.CorrelationContextHeader, currentActivity.Baggage);
                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", exception);
            }

            return(null);
        }