Exemple #1
0
        /**
         * With `EnableTcpStats` set, the states of active TCP connections will now be included
         * on the response and in the debug information.
         *
         * The client includes a `TcpStats`
         * class to help with retrieving more detail about active TCP connections should it be
         * required
         */
        [I] public void TcpStatistics()
        {
            // hide
            var client = this.Client;

            var tcpStatistics = TcpStats.GetActiveTcpConnections();                        // <1> Retrieve details about active TCP connections, including local and remote addresses and ports
            var ipv4Stats     = TcpStats.GetTcpStatistics(NetworkInterfaceComponent.IPv4); // <2> Retrieve statistics about IPv4
            var ipv6Stats     = TcpStats.GetTcpStatistics(NetworkInterfaceComponent.IPv6); // <3> Retrieve statistics about IPv6

            var response = client.Search <Project>(s => s
                                                   .Query(q => q
                                                          .MatchAll()
                                                          )
                                                   );
        }
        /// <inheritdoc cref="IConnection.Request{TResponse}"/>>
        public virtual TResponse Request <TResponse>(RequestData requestData)
            where TResponse : class, ITransportResponse, new()
        {
            int?statusCode = null;
            IEnumerable <string> warnings = null;
            Stream    responseStream      = null;
            Exception ex       = null;
            string    mimeType = null;
            ReadOnlyDictionary <TcpState, int> tcpStats = null;
            ReadOnlyDictionary <string, ThreadPoolStatistics> threadPoolStats = null;

            try
            {
                var request = CreateHttpWebRequest(requestData);
                var data    = requestData.PostData;

                if (data != null)
                {
                    using (var stream = request.GetRequestStream())
                    {
                        if (requestData.HttpCompression)
                        {
                            using var zipStream = new GZipStream(stream, CompressionMode.Compress);
                            data.Write(zipStream, requestData.ConnectionSettings);
                        }
                        else
                        {
                            data.Write(stream, requestData.ConnectionSettings);
                        }
                    }
                }
                requestData.MadeItToResponse = true;

                if (requestData.TcpStats)
                {
                    tcpStats = TcpStats.GetStates();
                }

                if (requestData.ThreadPoolStats)
                {
                    threadPoolStats = ThreadPoolStats.GetStats();
                }

                //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx
                //Either the stream or the response object needs to be closed but not both although it won't
                //throw any errors if both are closed atleast one of them has to be Closed.
                //Since we expose the stream we let closing the stream determining when to close the connection
                var httpWebResponse = (HttpWebResponse)request.GetResponse();
                HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType);

                //response.Headers.HasKeys() can return false even if response.Headers.AllKeys has values.
                if (httpWebResponse.SupportsHeaders && httpWebResponse.Headers.Count > 0 && httpWebResponse.Headers.AllKeys.Contains("Warning"))
                {
                    warnings = httpWebResponse.Headers.GetValues("Warning");
                }
            }
            catch (WebException e)
            {
                ex = e;
                if (e.Response is HttpWebResponse httpWebResponse)
                {
                    HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType);
                }
            }

            responseStream ??= Stream.Null;
            var response = ResponseBuilder.ToResponse <TResponse>(requestData, ex, statusCode, warnings, responseStream, mimeType);

            // set TCP and threadpool stats on the response here so that in the event the request fails after the point of
            // gathering stats, they are still exposed on the call details. Ideally these would be set inside ResponseBuilder.ToResponse,
            // but doing so would be a breaking change in 7.x
            response.ApiCall.TcpStats        = tcpStats;
            response.ApiCall.ThreadPoolStats = threadPoolStats;
            return(response);
        }
        /// <inheritdoc cref="IConnection.RequestAsync{TResponse}"/>>
        public virtual async Task <TResponse> RequestAsync <TResponse>(RequestData requestData,
                                                                       CancellationToken cancellationToken
                                                                       )
            where TResponse : class, ITransportResponse, new()
        {
            Action unregisterWaitHandle   = null;
            int?   statusCode             = null;
            IEnumerable <string> warnings = null;
            Stream    responseStream      = null;
            Exception ex       = null;
            string    mimeType = null;
            ReadOnlyDictionary <TcpState, int> tcpStats = null;
            ReadOnlyDictionary <string, ThreadPoolStatistics> threadPoolStats = null;

            try
            {
                var data    = requestData.PostData;
                var request = CreateHttpWebRequest(requestData);
                using (cancellationToken.Register(() => request.Abort()))
                {
                    if (data != null)
                    {
                        var apmGetRequestStreamTask =
                            Task.Factory.FromAsync(request.BeginGetRequestStream, r => request.EndGetRequestStream(r), null);
                        unregisterWaitHandle = RegisterApmTaskTimeout(apmGetRequestStreamTask, request, requestData);

                        using (var stream = await apmGetRequestStreamTask.ConfigureAwait(false))
                        {
                            if (requestData.HttpCompression)
                            {
                                using var zipStream = new GZipStream(stream, CompressionMode.Compress);
                                await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
                            }
                            else
                            {
                                await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false);
                            }
                        }
                        unregisterWaitHandle?.Invoke();
                    }
                    requestData.MadeItToResponse = true;
                    //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx
                    //Either the stream or the response object needs to be closed but not both although it won't
                    //throw any errors if both are closed atleast one of them has to be Closed.
                    //Since we expose the stream we let closing the stream determining when to close the connection

                    var apmGetResponseTask = Task.Factory.FromAsync(request.BeginGetResponse, r => request.EndGetResponse(r), null);
                    unregisterWaitHandle = RegisterApmTaskTimeout(apmGetResponseTask, request, requestData);

                    if (requestData.TcpStats)
                    {
                        tcpStats = TcpStats.GetStates();
                    }

                    if (requestData.ThreadPoolStats)
                    {
                        threadPoolStats = ThreadPoolStats.GetStats();
                    }

                    var httpWebResponse = (HttpWebResponse)await apmGetResponseTask.ConfigureAwait(false);

                    HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType);
                    if (httpWebResponse.SupportsHeaders && httpWebResponse.Headers.HasKeys() && httpWebResponse.Headers.AllKeys.Contains("Warning"))
                    {
                        warnings = httpWebResponse.Headers.GetValues("Warning");
                    }
                }
            }
            catch (WebException e)
            {
                ex = e;
                if (e.Response is HttpWebResponse httpWebResponse)
                {
                    HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType);
                }
            }
            finally
            {
                unregisterWaitHandle?.Invoke();
            }
            responseStream ??= Stream.Null;
            var response = await ResponseBuilder.ToResponseAsync <TResponse>
                               (requestData, ex, statusCode, warnings, responseStream, mimeType, cancellationToken)
                           .ConfigureAwait(false);

            // set TCP and threadpool stats on the response here so that in the event the request fails after the point of
            // gathering stats, they are still exposed on the call details. Ideally these would be set inside ResponseBuilder.ToResponse,
            // but doing so would be a breaking change in 7.x
            response.ApiCall.TcpStats        = tcpStats;
            response.ApiCall.ThreadPoolStats = threadPoolStats;
            return(response);
        }
        private TcpStats AnalyzeConnections(ConnectionData[] connections, TimeSpan measurePeriod)
        {
            _receivedSinceLastRun = 0;
            _sentSinceLastRun = 0;
            _pendingSendOnLastRun = 0;
            _inSendOnLastRun = 0;
            _pendingReceivedOnLastRun = 0;
            _anySendBlockedOnLastRun = false;

            foreach (var connection in connections)
            {
                AnalyzeConnection(connection);
            }

            var stats = new TcpStats(connections.Length,
                                     _sentTotal,
                                     _receivedTotal,
                                     _sentSinceLastRun,
                                     _receivedSinceLastRun,
                                     _pendingSendOnLastRun,
                                     _inSendOnLastRun,
                                     _pendingReceivedOnLastRun,
                                     measurePeriod);

            Log.Debug("# Total connections: {0,3}. Out: {1:8}  In: {2:8}  Pending Send: {3}  " +
                      "In Send: {4}  Pending Received: {5} Measure Time: {6}",
                stats.Connections,
                stats.SendingSpeed,
                stats.ReceivingSpeed,
                stats.PendingSend,
                stats.InSend,
                stats.PendingSend,
                stats.MeasureTimeFriendly);

            return stats;
        }