/// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="success">The success to indicate if the dependency call completed successfully or not.</param>
        /// <param name="synchronous">The synchronous flag to indicate if the dependency call was synchronous or not.</param>
        /// <param name="statusCode">The HTTP status code of the response.</param>
        public void OnEndHttpCallback(long id, bool?success, bool synchronous, int?statusCode)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id);

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

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id);
                return;
            }

            if (!telemetryTuple.Item2)
            {
                this.TelemetryTable.Remove(id);
                DependencyTelemetry telemetry = telemetryTuple.Item1;
                telemetry.DependencyKind = RemoteDependencyKind.Http.ToString();

                if (!statusCode.HasValue)
                {
                    statusCode = -1;
                }

                telemetry.ResultCode = statusCode.Value > 0 ? statusCode.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;

                // We calculate success on the base of http code and do not use the 'success' method argument
                // because framework returns true all the time if you use HttpClient to create a request
                // statusCode == -1 if there is no Response
                telemetry.Success = (statusCode > 0) && (statusCode < 400);

                ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            }
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="request">The HttpWebRequest instance.</param>
        /// <param name="response">The HttpWebResponse instance.</param>
        internal void OnEndResponse(object request, object response)
        {
            try
            {
                if (this.TryGetPendingTelemetry(request, out DependencyTelemetry telemetry))
                {
                    if (response is HttpWebResponse responseObj)
                    {
                        int statusCode = -1;

                        try
                        {
                            statusCode = (int)responseObj.StatusCode;
                            this.SetTarget(telemetry, responseObj.Headers);

                            // Set the operation details for the response
                            telemetry.SetOperationDetail(RemoteDependencyConstants.HttpResponseOperationDetailName, responseObj);
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }

                        SetStatusCode(telemetry, statusCode);
                    }

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(request == null ? 0 : request.GetHashCode(), "OnEndResponse", ex);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="request">WebRequest object.</param>
        /// <param name="statusCode">HttpStatusCode from response.</param>
        /// <param name="responseHeaders">Response headers.</param>
        internal void OnEndResponse(object request, object statusCode, object responseHeaders)
        {
            try
            {
                if (this.TryGetPendingTelemetry(request, out DependencyTelemetry telemetry))
                {
                    if (statusCode != null)
                    {
                        SetStatusCode(telemetry, (int)statusCode);
                    }

                    this.SetTarget(telemetry, (WebHeaderCollection)responseHeaders);
                    if (this.injectW3CHeaders && request is HttpWebRequest httpRequest)
                    {
                        // this.SetLegacyId(telemetry, httpRequest.Headers);
                    }

                    telemetry.SetOperationDetail(RemoteDependencyConstants.HttpResponseHeadersOperationDetailName, responseHeaders);

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(request == null ? 0 : request.GetHashCode(), "OnEndResponse", ex);
            }
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="returnValue">Return value of the function if any.</param>
        private void OnEnd(object exception, object thisObj, object returnValue)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return;
                }

                DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode());

                Tuple <DependencyTelemetry, bool> telemetryTuple = this.TelemetryTable.Get(thisObj);

                if (telemetryTuple == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode());
                    return;
                }

                if (telemetryTuple.Item1 == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode());
                    return;
                }

                if (!telemetryTuple.Item2)
                {
                    this.TelemetryTable.Remove(thisObj);
                    DependencyTelemetry telemetry = telemetryTuple.Item1;

                    var responseObj = returnValue as HttpWebResponse;

                    int statusCode = -1;
                    if (responseObj != null)
                    {
                        try
                        {
                            statusCode = (int)responseObj.StatusCode;
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }
                    }

                    telemetry.ResultCode = statusCode > 0 ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", ex);
            }
        }
Ejemplo n.º 5
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>
        ///  Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exceptionObj">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="sendTelemetryItem">True if telemetry item should be sent, otherwise it only stops the telemetry item.</param>
        private void OnEndInternal(object exceptionObj, object thisObj, bool sendTelemetryItem = true)
        {
            if (thisObj == null)
            {
                DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnEndSql", "thisObj == null");
                return;
            }

            DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));

            DependencyTelemetry telemetry = null;
            Tuple <DependencyTelemetry, bool> telemetryTuple = null;
            bool isCustomGenerated = false;

            telemetryTuple = this.TelemetryTable.Get(thisObj);
            if (telemetryTuple != null)
            {
                telemetry         = telemetryTuple.Item1;
                isCustomGenerated = telemetryTuple.Item2;
            }

            if (telemetry == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                return;
            }

            if (!isCustomGenerated)
            {
                this.TelemetryTable.Remove(thisObj);

                if (sendTelemetryItem)
                {
                    var exception = exceptionObj as Exception;
                    if (exception != null)
                    {
                        telemetry.Success = false;
                        telemetry.Properties.Add("ErrorMessage", exception.Message);

                        var sqlEx = exception as SqlException;
                        telemetry.ResultCode = sqlEx != null?sqlEx.Number.ToString(CultureInfo.InvariantCulture) : "0";
                    }
                    else
                    {
                        telemetry.Success = true;
                    }

                    DependencyCollectorEventSource.Log.AutoTrackingDependencyItem(telemetry.Name);
                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
                else
                {
                    DependencyCollectorEventSource.Log.EndOperationNoTracking(telemetry.Name);
                    ClientServerDependencyTracker.EndOperation(telemetry);
                }
            }
        }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
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");
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="request">HttpWebRequest instance.</param>
        internal void OnEndException(object exception, object request)
        {
            try
            {
                if (this.TryGetPendingTelemetry(request, out DependencyTelemetry telemetry))
                {
                    var webException = exception as WebException;

                    if (webException?.Response is HttpWebResponse responseObj)
                    {
                        int statusCode = -1;

                        try
                        {
                            statusCode = (int)responseObj.StatusCode;
                            this.SetTarget(telemetry, responseObj.Headers);
                            if (this.injectW3CHeaders && request is HttpWebRequest httpRequest)
                            {
                                // this.SetLegacyId(telemetry, httpRequest.Headers);
                            }

                            // Set the operation details for the response
                            telemetry.SetOperationDetail(RemoteDependencyConstants.HttpResponseOperationDetailName, responseObj);
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }

                        SetStatusCode(telemetry, statusCode);
                    }
                    else if (exception != null)
                    {
                        if (webException != null)
                        {
                            telemetry.ResultCode = webException.Status.ToString();
                        }

                        telemetry.Success = false;
                    }

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(request == null ? 0 : request.GetHashCode(), "OnEndException", ex);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="success">The success to indicate if the dependency call completed successfully or not.</param>
        /// <param name="synchronous">The synchronous flag to indicate if the dependency call was synchronous or not.</param>
        /// <param name="statusCode">The HTTP status code of the response.</param>
        public void OnEndHttpCallback(long id, bool?success, bool synchronous, int?statusCode)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id.ToString(CultureInfo.InvariantCulture));
            var telemetryTuple = this.TelemetryTable.Get(id);

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id.ToString(CultureInfo.InvariantCulture));
                return;
            }

            if (!telemetryTuple.Item2)
            {
                DependencyTelemetry telemetry = telemetryTuple.Item1;

                if (statusCode.HasValue)
                {
                    if (DependencyTableStore.IsDesktopHttpDiagnosticSourceActivated && statusCode.Value > 0)
                    {
                        // HttpDesktopDiagnosticSourceListener do not get notifications about exceptions during requests processing.
                        // We will report them here, and we will let HttpDesktopDiagnosticSourceListener track the dependency for successful response
                        DependencyCollectorEventSource.Log.SkipTrackingTelemetryItemWithEventSource(id);
                        return;
                    }

                    // We calculate success on the base of http code and do not use the 'success' method argument
                    // because framework returns true all the time if you use HttpClient to create a request
                    // statusCode == -1 if there is no Response
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);
                    telemetry.ResultCode = statusCode.Value > 0 ? statusCode.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;

                    this.TelemetryTable.Remove(id);
                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
                else
                {
                    // This case is for 4.5.2
                    // We never collected statusCode or success before 2.1.0-beta4
                    // We also had duplicates if runtime is also 4.5.2 (4.6 runtime has no such problem)
                    // So starting with 2.1.0-beta4 we are cutting support for HTTP dependencies in .NET 4.5.2.
                    // But we will let DesktopDiagnosticSourceListener collect dependency if it is activated
                    if (!DependencyTableStore.IsDesktopHttpDiagnosticSourceActivated)
                    {
                        this.TelemetryTable.Remove(id);
                    }
                }
            }
        }
        /// <summary>
        ///  Common helper for all End Callbacks.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="isAsync">Whether the End is for an async invocation.</param>
        private void OnEnd(object context, object exception, object thisObj, bool isAsync)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnEndSql", "thisObj == null");
                    return;
                }

                DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));

                DependencyTelemetry telemetry = null;
                Tuple <DependencyTelemetry, bool> telemetryTuple = null;
                bool isCustomGenerated = false;

                telemetryTuple = this.TelemetryTable.Get(thisObj);
                if (telemetryTuple != null)
                {
                    telemetry         = telemetryTuple.Item1;
                    isCustomGenerated = telemetryTuple.Item2;
                }

                if (telemetry == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                if (!isCustomGenerated)
                {
                    this.TelemetryTable.Remove(thisObj);
                    telemetry.Success = exception == null;
                    var sqlEx = exception as SqlException;
                    if (sqlEx != null)
                    {
                        telemetry.ResultCode = sqlEx.Number.ToString(CultureInfo.InvariantCulture);
                    }

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnEndSql", ex);
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="success">The success to indicate if the dependency call completed successfully or not.</param>
        /// <param name="synchronous">The synchronous flag to indicate if the dependency call was synchronous or not.</param>
        /// <param name="statusCode">The HTTP status code of the response.</param>
        public void OnEndHttpCallback(long id, bool?success, bool synchronous, int?statusCode)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id.ToString(CultureInfo.InvariantCulture));

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

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id.ToString(CultureInfo.InvariantCulture));
                return;
            }

            if (!telemetryTuple.Item2)
            {
                this.TelemetryTable.Remove(id);
                DependencyTelemetry telemetry = telemetryTuple.Item1;

                // If this telemetry was processed via the DiagnosticSource path, we should record that fact in the
                // SdkVersion field
                if (this.HasTouchedByDiagnosticSource(telemetry))
                {
                    telemetry.Context.GetInternalContext().SdkVersion = SdkVersionUtils.GetSdkVersion("rdd" + RddSource.FrameworkAndDiagnostic + ":");
                }

                if (statusCode.HasValue)
                {
                    // We calculate success on the base of http code and do not use the 'success' method argument
                    // because framework returns true all the time if you use HttpClient to create a request
                    // statusCode == -1 if there is no Response
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);
                    telemetry.ResultCode = statusCode.Value > 0 ? statusCode.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
                else
                {
                    // This case is for 4.5.2
                    // We never collected statusCode or success before 2.1.0-beta4
                    // We also had duplicates if runtime is also 4.5.2 (4.6 runtime has no such problem)
                    // So starting with 2.1.0-beta4 we are cutting support for HTTP dependencies in .NET 4.5.2.
                }
            }
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="request">WebRequest object.</param>
        /// <param name="statusCode">HttpStatusCode from response.</param>
        /// <param name="responseHeaders">Response headers.</param>
        internal void OnEndResponse(object request, object statusCode, object responseHeaders)
        {
            try
            {
                if (this.TryGetPendingTelemetry(request, out DependencyTelemetry telemetry))
                {
                    if (statusCode != null)
                    {
                        this.SetStatusCode(telemetry, (int)statusCode);
                    }

                    this.SetTarget(telemetry, (WebHeaderCollection)responseHeaders);

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(request == null ? 0 : request.GetHashCode(), "OnEndResponse", ex);
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">Identifier of SQL connection object.</param>
        /// <param name="success">Indicate whether operation completed successfully.</param>
        /// <param name="sqlExceptionNumber">SQL exception number.</param>
        public void OnEndExecuteCallback(long id, bool success, int sqlExceptionNumber)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id.ToString(CultureInfo.InvariantCulture));

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

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id.ToString(CultureInfo.InvariantCulture));
                return;
            }

            if (!telemetryTuple.Item2)
            {
                this.TelemetryTable.Remove(id);
                var telemetry = telemetryTuple.Item1;
                telemetry.Success    = success;
                telemetry.ResultCode = sqlExceptionNumber != 0 ? sqlExceptionNumber.ToString(CultureInfo.InvariantCulture) : string.Empty;
                DependencyCollectorEventSource.Log.AutoTrackingDependencyItem(telemetry.Name);
                ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="success">The success to indicate if the dependency call completed successfully or not.</param>
        /// <param name="synchronous">The synchronous flag to indicate if the dependency call was synchronous or not.</param>
        /// <param name="statusCode">The HTTP status code of the response.</param>
        public void OnEndHttpCallback(long id, bool?success, bool synchronous, int?statusCode)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id);

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

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id);
                return;
            }

            if (!telemetryTuple.Item2)
            {
                this.TelemetryTable.Remove(id);
                var telemetry = telemetryTuple.Item1 as DependencyTelemetry;
                telemetry.DependencyKind = RemoteDependencyKind.Http.ToString();
                telemetry.Success        = success;
                telemetry.ResultCode     = statusCode.HasValue ? statusCode.ToString() : string.Empty;

                ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
            }
        }
        /// <summary>
        /// On end callback from Framework event source.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="success">The success to indicate if the dependency call completed successfully or not.</param>
        /// <param name="synchronous">The synchronous flag to indicate if the dependency call was synchronous or not.</param>
        /// <param name="statusCode">The HTTP status code of the response.</param>
        public void OnEndHttpCallback(long id, bool?success, bool synchronous, int?statusCode)
        {
            DependencyCollectorEventSource.Log.EndCallbackCalled(id.ToString(CultureInfo.InvariantCulture));

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

            if (telemetryTuple == null)
            {
                DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(id.ToString(CultureInfo.InvariantCulture));
                return;
            }

            if (!telemetryTuple.Item2)
            {
                this.TelemetryTable.Remove(id);
                DependencyTelemetry telemetry = telemetryTuple.Item1;
                telemetry.DependencyKind = RemoteDependencyKind.Http.ToString();

                if (statusCode.HasValue)
                {
                    // We calculate success on the base of http code and do not use the 'success' method argument
                    // because framework returns true all the time if you use HttpClient to create a request
                    // statusCode == -1 if there is no Response
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);
                    telemetry.ResultCode = statusCode.Value > 0 ? statusCode.Value.ToString(CultureInfo.InvariantCulture) : string.Empty;

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
                else
                {
                    // This case is for 4.5.2
                    // We never collected statusCode or success before 2.1.0-beta4
                    // We also had duplicates if runtime is also 4.5.2 (4.6 runtime has no such problem)
                    // So starting with 2.1.0-beta4 we are cutting support for HTTP dependencies in .NET 4.5.2.
                }
            }
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="returnValue">Return value of the function if any.</param>
        private void OnEnd(object exception, object thisObj, object returnValue)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return;
                }

                DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));

                Tuple <DependencyTelemetry, bool> telemetryTuple = this.TelemetryTable.Get(thisObj);

                if (telemetryTuple == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                if (telemetryTuple.Item1 == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                // Not custom created
                if (!telemetryTuple.Item2)
                {
                    this.TelemetryTable.Remove(thisObj);
                    DependencyTelemetry telemetry = telemetryTuple.Item1;

                    int statusCode = -1;

                    var responseObj = returnValue as HttpWebResponse;

                    if (responseObj == null && exception != null)
                    {
                        var webException = exception as WebException;

                        if (webException != null)
                        {
                            responseObj = webException.Response as HttpWebResponse;
                        }
#if !NET40
                        if (responseObj == null)
                        {
                            var httpException = exception as HttpException;

                            if (httpException != null)
                            {
                                statusCode = httpException.GetHttpCode();
                            }
                        }
#endif
                    }

                    if (responseObj != null)
                    {
                        try
                        {
                            statusCode = (int)responseObj.StatusCode;

                            if (responseObj.Headers != null)
                            {
                                var targetIkeyHash = responseObj.Headers[RequestResponseHeaders.TargetInstrumentationKeyHeader];

                                // We only add the cross component correlation key if the key does not remain the current component.
                                if (!string.IsNullOrEmpty(targetIkeyHash) && targetIkeyHash != InstrumentationKeyHashLookupHelper.GetInstrumentationKeyHash(telemetry.Context.InstrumentationKey))
                                {
                                    telemetry.Type    = RemoteDependencyConstants.AI;
                                    telemetry.Target += " | " + targetIkeyHash;
                                }
                            }
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }
                    }

                    telemetry.ResultCode = statusCode > 0 ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
                    telemetry.Success    = (statusCode > 0) && (statusCode < 400);

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", ex);
            }
        }
        /// <summary>
        /// Common helper for all End Callbacks.
        /// </summary>
        /// <param name="exception">The exception object if any.</param>
        /// <param name="thisObj">This object.</param>
        /// <param name="returnValue">Return value of the function if any.</param>
        internal void OnEnd(object exception, object thisObj, object returnValue)
        {
            try
            {
                if (thisObj == null)
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(0, "OnBeginHttp", "thisObj == null");
                    return;
                }

                DependencyCollectorEventSource.Log.EndCallbackCalled(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));

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

                var telemetryTuple = this.GetTupleForWebDependencies(webRequest);
                if (telemetryTuple == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                if (telemetryTuple.Item1 == null)
                {
                    DependencyCollectorEventSource.Log.EndCallbackWithNoBegin(thisObj.GetHashCode().ToString(CultureInfo.InvariantCulture));
                    return;
                }

                // Not custom created
                if (!telemetryTuple.Item2)
                {
                    this.RemoveTupleForWebDependencies(webRequest);

                    DependencyTelemetry telemetry = telemetryTuple.Item1;

                    var responseObj = returnValue as HttpWebResponse;

                    if (responseObj == null && exception != null)
                    {
                        var webException = exception as WebException;

                        if (webException != null)
                        {
                            responseObj = webException.Response as HttpWebResponse;
                        }
                    }

                    if (responseObj != null)
                    {
                        int statusCode = -1;

                        try
                        {
                            statusCode = (int)responseObj.StatusCode;
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }

                        telemetry.ResultCode = statusCode > 0 ? statusCode.ToString(CultureInfo.InvariantCulture) : string.Empty;
                        telemetry.Success    = (statusCode > 0) && (statusCode < 400);
                    }
                    else if (exception != null)
                    {
                        var webException = exception as WebException;
                        if (webException != null)
                        {
                            telemetry.ResultCode = webException.Status.ToString();
                        }

                        telemetry.Success = false;
                    }

                    if (responseObj != null)
                    {
                        try
                        {
                            if (responseObj.Headers != null)
                            {
                                string targetAppId = null;

                                try
                                {
                                    targetAppId = responseObj.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextCorrelationTargetKey);
                                }
                                catch (Exception ex)
                                {
                                    AppMapCorrelationEventSource.Log.GetCrossComponentCorrelationHeaderFailed(ex.ToInvariantString());
                                }

                                string currentComponentAppId;
                                if (this.correlationIdLookupHelper.TryGetXComponentCorrelationId(telemetry.Context.InstrumentationKey, out currentComponentAppId))
                                {
                                    // We only add the cross component correlation key if the key does not remain the current component.
                                    if (!string.IsNullOrEmpty(targetAppId) && targetAppId != currentComponentAppId)
                                    {
                                        telemetry.Type    = RemoteDependencyConstants.AI;
                                        telemetry.Target += " | " + targetAppId;
                                    }
                                }

                                string targetRoleName = null;
                                try
                                {
                                    targetRoleName = responseObj.Headers.GetNameValueHeaderValue(RequestResponseHeaders.RequestContextHeader, RequestResponseHeaders.RequestContextTargetRoleNameKey);
                                }
                                catch (Exception ex)
                                {
                                    AppMapCorrelationEventSource.Log.GetComponentRoleNameHeaderFailed(ex.ToInvariantString());
                                }

                                if (!string.IsNullOrEmpty(targetRoleName))
                                {
                                    telemetry.Type    = RemoteDependencyConstants.AI;
                                    telemetry.Target += " | roleName:" + targetRoleName;
                                }
                            }
                        }
                        catch (ObjectDisposedException)
                        {
                            // ObjectDisposedException is expected here in the following sequence: httpWebRequest.GetResponse().Dispose() -> httpWebRequest.GetResponse()
                            // on the second call to GetResponse() we cannot determine the statusCode.
                        }
                    }

                    ClientServerDependencyTracker.EndTracking(this.telemetryClient, telemetry);
                }
            }
            catch (Exception ex)
            {
                DependencyCollectorEventSource.Log.CallbackError(thisObj == null ? 0 : thisObj.GetHashCode(), "OnBeginHttp", ex);
            }
        }