/** * 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; }