/// <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);
            }
        }
Exemple #2
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);
            }
        }
        public void RddTestHttpProcessingFrameworkNoDuplication()
        {
            Stopwatch      stopwatch    = Stopwatch.StartNew();
            HttpWebRequest request      = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id           = ClientServerDependencyTracker.GetIdForRequestObject(request);
            var            returnObject = TestUtils.GenerateHttpWebResponse(HttpStatusCode.BadRequest);

            this.httpProcessingFramework.OnRequestSend(request);
            this.httpProcessingFramework.OnRequestSend(request);
            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
            this.httpProcessingFramework.OnRequestSend(request);
            this.httpProcessingFramework.OnRequestSend(request);
            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.OriginalString);
            this.httpProcessingFramework.OnRequestSend(request);
            Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
            this.httpProcessingFramework.OnResponseReceive(request, returnObject);
            this.httpProcessingFramework.OnEndHttpCallback(id, false, false, 409);
            this.httpProcessingFramework.OnEndHttpCallback(id, true, false, 304);
            this.httpProcessingFramework.OnResponseReceive(request, returnObject);
            this.httpProcessingFramework.OnEndHttpCallback(id, true, false, 200);
            this.httpProcessingFramework.OnResponseReceive(request, returnObject);
            this.httpProcessingFramework.OnEndHttpCallback(id, false, false, 400);
            stopwatch.Stop();

            Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
            ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, false, stopwatch.Elapsed.TotalMilliseconds, "409");
        }
Exemple #4
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);
            }
        }
        /// <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);
            }
        }
Exemple #6
0
        public void BeginWebTrackingReturnsOperationItemWithTelemetryItem()
        {
            var telemetry = ClientServerDependencyTracker.BeginTracking(this.telemetryClient);

            Assert.AreEqual(telemetry.StartTime, telemetry.StartTime);
            Assert.AreEqual(telemetry.Timestamp, telemetry.Timestamp);
        }
Exemple #7
0
        /// <summary>
        /// This method gets called once for each event from the Http DiagnosticSource.
        /// </summary>
        /// <param name="value">The pair containing the event name, and an object representing the payload. The payload
        /// is essentially a dynamic object that contain different properties depending on the event.</param>
        public void OnNext(KeyValuePair <string, object> value)
        {
            try
            {
                switch (value.Key)
                {
                case "System.Net.Http.Desktop.HttpRequestOut.Start":
                {
                    var request = (HttpWebRequest)this.requestFetcherRequestEvent.Fetch(value.Value);
                    DependencyCollectorEventSource.Log.HttpDesktopBeginCallbackCalled(ClientServerDependencyTracker.GetIdForRequestObject(request), request.RequestUri.ToString());

                    // With this event, DiagnosticSource injects headers himself (after the event)
                    // ApplicationInsights must not do this
                    this.httpDesktopProcessing.OnBegin(request, false);
                    break;
                }

                case "System.Net.Http.Desktop.HttpRequestOut.Stop":
                {
                    // request is never null
                    var request = this.requestFetcherResponseEvent.Fetch(value.Value);
                    DependencyCollectorEventSource.Log.HttpDesktopEndCallbackCalled(ClientServerDependencyTracker.GetIdForRequestObject(request));
                    var response = this.responseFetcher.Fetch(value.Value);
                    this.httpDesktopProcessing.OnEndResponse(request, response);
                    break;
                }

                case "System.Net.Http.Desktop.HttpRequestOut.Ex.Stop":
                {
                    // request is never null
                    var request = this.requestFetcherResponseExEvent.Fetch(value.Value);
                    DependencyCollectorEventSource.Log.HttpDesktopEndCallbackCalled(ClientServerDependencyTracker.GetIdForRequestObject(request));
                    object statusCode = this.responseExStatusFetcher.Fetch(value.Value);
                    object headers    = this.responseExHeadersFetcher.Fetch(value.Value);
                    this.httpDesktopProcessing.OnEndResponse(request, statusCode, headers);
                    break;
                }

                case "System.Net.Http.InitializationFailed":
                {
                    DependencyTableStore.IsDesktopHttpDiagnosticSourceActivated = false;

                    Exception ex = (Exception)value.Value.GetType().GetProperty("Exception")?.GetValue(value.Value);
                    DependencyCollectorEventSource.Log.HttpHandlerDiagnosticListenerFailedToInitialize(ex?.ToInvariantString());
                    break;
                }

                default:
                {
                    DependencyCollectorEventSource.Log.NotExpectedCallback(value.GetHashCode(), value.Key, "unknown key");
                    break;
                }
                }
            }
            catch (Exception exc)
            {
                DependencyCollectorEventSource.Log.CallbackError(0, "OnNext", exc);
            }
        }
Exemple #8
0
        public void AddTupleForWebDependenciesThrowsExceptionIfExists()
        {
            var telemetry      = new DependencyTelemetry();
            var falseTelemetry = new DependencyTelemetry();

            ClientServerDependencyTracker.AddTupleForWebDependencies(this.webRequest, falseTelemetry, false);
            ClientServerDependencyTracker.AddTupleForWebDependencies(this.webRequest, telemetry, false);
        }
        /// <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);
            }
        }
Exemple #10
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);
                }
            }
        }
        /// <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);
            }
        }
Exemple #13
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>
        /// <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);
        }
Exemple #15
0
        public void AddTupleForSqlDependenciesAddsTelemteryTupleToTheTable()
        {
            var telemetry = new DependencyTelemetry();

            ClientServerDependencyTracker.AddTupleForSqlDependencies(this.sqlRequest, telemetry, false);
            var tuple = ClientServerDependencyTracker.GetTupleForSqlDependencies(this.sqlRequest);

            Assert.IsNotNull(tuple);
            Assert.IsNotNull(tuple.Item1);
            Assert.AreEqual(telemetry, tuple.Item1);
        }
Exemple #16
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);
        }
Exemple #17
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);
        }
        public void FrameworkHttpProcessingIsDisabledWhenHttpDesktopDiagSourceIsEnabled()
        {
            DependencyTableStore.IsDesktopHttpDiagnosticSourceActivated = true;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id      = ClientServerDependencyTracker.GetIdForRequestObject(request);

            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
            this.httpProcessingFramework.OnEndHttpCallback(id, null, false, 200);

            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be sent");
        }
Exemple #19
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>
        ///  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);
        }
        public void RddTestHttpProcessingFrameworkOnEndHttpCallbackInvalidId()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id1     = ClientServerDependencyTracker.GetIdForRequestObject(request);
            var            id2     = 200;

            this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
            Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");

            this.httpProcessingFramework.OnEndHttpCallback(id2, true, true, null);
            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed as invalid id is passed");
        }
Exemple #22
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);
            }
        }
        public void HttpProcessorSetsTargetForNonStandardPort()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrlNonStandardPort);
            var            id      = ClientServerDependencyTracker.GetIdForRequestObject(request);

            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrlNonStandardPort.ToString());
            this.httpProcessingFramework.OnEndHttpCallback(id, null, false, 500);

            Assert.AreEqual(1, this.sendItems.Count, "Exactly one telemetry item should be sent");
            DependencyTelemetry receivedItem = (DependencyTelemetry)this.sendItems[0];
            string expectedTarget            = this.testUrlNonStandardPort.Host + ":" + this.testUrlNonStandardPort.Port;

            Assert.AreEqual(expectedTarget, receivedItem.Target, "HttpProcessingFramework returned incorrect target for non standard port.");
        }
        public void OnEndHttpCallbackSetsSuccessToTrueForLessThan400()
        {
            int statusCode = 399;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id      = ClientServerDependencyTracker.GetIdForRequestObject(request);

            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
            this.httpProcessingFramework.OnEndHttpCallback(id, null, false, statusCode);

            Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
            var actual = this.sendItems[0] as DependencyTelemetry;

            Assert.IsTrue(actual.Success.Value);
        }
Exemple #25
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);
                    }
                }
            }
        }
        public void OnEndHttpCallbackSetsSuccessToFalseForNegativeStatusCode()
        {
            // -1 StatusCode is returned in case of no response
            int statusCode = -1;

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id      = ClientServerDependencyTracker.GetIdForRequestObject(request);

            this.httpProcessingFramework.OnBeginHttpCallback(id, this.testUrl.ToString());
            this.httpProcessingFramework.OnEndHttpCallback(id, null, false, statusCode);

            Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
            var actual = this.sendItems[0] as DependencyTelemetry;

            Assert.IsFalse(actual.Success.Value);
        }
        /// <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);
            }
        }
        public void RddTestHttpProcessingFrameworkOnEndHttpCallback()
        {
            var       request            = WebRequest.Create(this.testUrl);
            var       returnObjectPassed = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK);
            Stopwatch stopwatch          = new Stopwatch();

            stopwatch.Start();
            this.httpProcessingFramework.OnRequestSend(request);
            Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
            this.httpProcessingFramework.OnResponseReceive(request, returnObjectPassed);
            this.httpProcessingFramework.OnEndHttpCallback(ClientServerDependencyTracker.GetIdForRequestObject(request), true, true, 200);
            stopwatch.Stop();

            Assert.AreEqual(1, this.sendItems.Count, "Only one telemetry item should be sent");
            ValidateTelemetryPacketForOnRequestSend(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
        }
        public void RddTestHttpProcessingFrameworkStartTimeFromGetRequestStreamAsync()
        {
            Stopwatch      stopwatch = Stopwatch.StartNew();
            HttpWebRequest request   = (HttpWebRequest)WebRequest.Create(this.testUrl);
            var            id1       = ClientServerDependencyTracker.GetIdForRequestObject(request);

            this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
            Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
            this.httpProcessingFramework.OnBeginHttpCallback(id1, this.testUrl.ToString());
            Thread.Sleep(this.sleepTimeMsecBetweenBeginAndEnd);
            Assert.AreEqual(0, this.sendItems.Count, "No telemetry item should be processed without calling End");
            this.httpProcessingFramework.OnEndHttpCallback(id1, true, false, 200);
            stopwatch.Stop();

            Assert.AreEqual(1, this.sendItems.Count, "Exactly one telemetry item should be sent");
            ValidateTelemetryPacketForOnBeginHttpCallback(this.sendItems[0] as DependencyTelemetry, this.testUrl, RemoteDependencyConstants.HTTP, true, stopwatch.Elapsed.TotalMilliseconds, "200");
        }
        private void SimulateWebRequestResponseWithAppId(string appId)
        {
            var request = WebRequest.Create(this.testUrl);

            Dictionary <string, string> headers = new Dictionary <string, string>();

            headers.Add(RequestResponseHeaders.RequestContextHeader, this.GetCorrelationIdHeaderValue(appId));

            var returnObjectPassed = TestUtils.GenerateHttpWebResponse(HttpStatusCode.OK, headers);

            this.httpProcessingFramework.OnBeginHttpCallback(ClientServerDependencyTracker.GetIdForRequestObject(request), this.testUrl.OriginalString);
            this.httpProcessingFramework.OnRequestSend(request);
            this.httpProcessingFramework.OnResponseReceive(request, returnObjectPassed);
            this.httpProcessingFramework.OnEndHttpCallback(
                ClientServerDependencyTracker.GetIdForRequestObject(request),
                true,
                true,
                (int)HttpStatusCode.OK);
        }