From 9b8950747ffa0f70be087ed559c4f2d6907a6322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D0=B5=D0=BC=20=D0=9A=D1=83=D1=80=D1=8C?= =?UTF-8?q?=D1=8F=D0=BD=D0=BE=D0=B2?= Date: Fri, 14 Aug 2020 14:15:13 +0000 Subject: [PATCH] added optional request tracing id for much better logs reading --- CryptoExchange.Net/CryptoExchange.Net.xml | 163 ++---------------- CryptoExchange.Net/Interfaces/IRequest.cs | 4 + .../Interfaces/IRequestFactory.cs | 3 +- CryptoExchange.Net/Objects/Options.cs | 2 +- CryptoExchange.Net/Requests/Request.cs | 10 +- CryptoExchange.Net/Requests/RequestFactory.cs | 9 +- CryptoExchange.Net/RestClient.cs | 18 +- 7 files changed, 44 insertions(+), 165 deletions(-) diff --git a/CryptoExchange.Net/CryptoExchange.Net.xml b/CryptoExchange.Net/CryptoExchange.Net.xml index 5415b61..ff62654 100644 --- a/CryptoExchange.Net/CryptoExchange.Net.xml +++ b/CryptoExchange.Net/CryptoExchange.Net.xml @@ -588,6 +588,11 @@ Uri + + + internal request id for tracing + + Set byte content @@ -628,12 +633,13 @@ - + Configure the requests created by this factory Request timeout to use Proxy settings to use + Should generate unique id for requests @@ -1772,7 +1778,7 @@ - Event when order book was updated, containing the changed bids and asks. Be careful! It can generate a lot of events at high-liquidity markets + Event when order book was updated, containing the changed bids and asks. Be careful! It can generate a lot of events at high-liquidity markets @@ -2025,12 +2031,13 @@ Request object - + Create request object for web request + if true, should assign unique id for request @@ -2044,6 +2051,9 @@ + + + @@ -2061,7 +2071,7 @@ WebRequest factory - + @@ -3094,148 +3104,3 @@ -System.Diagnostics.CodeAnalysis.AllowNullAttribute"> - - Specifies that is allowed as an input even if the - corresponding type disallows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that is disallowed as an input even if the - corresponding type allows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that a method that will never return under any circumstance. - - - - - Initializes a new instance of the class. - - - - - Specifies that the method will not return if the associated - parameter is passed the specified value. - - - - - Gets the condition parameter value. - Code after the method is considered unreachable by diagnostics if the argument - to the associated parameter matches this value. - - - - - Initializes a new instance of the - class with the specified parameter value. - - - The condition parameter value. - Code after the method is considered unreachable by diagnostics if the argument - to the associated parameter matches this value. - - - - - Specifies that an output may be even if the - corresponding type disallows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that when a method returns , - the parameter may be even if the corresponding type disallows it. - - - - - Gets the return value condition. - If the method returns this value, the associated parameter may be . - - - - - Initializes the attribute with the specified return value condition. - - - The return value condition. - If the method returns this value, the associated parameter may be . - - - - - Specifies that an output is not even if the - corresponding type allows it. - - - - - Initializes a new instance of the class. - - - - - Specifies that the output will be non- if the - named parameter is non-. - - - - - Gets the associated parameter name. - The output will be non- if the argument to the - parameter specified is non-. - - - - - Initializes the attribute with the associated parameter name. - - - The associated parameter name. - The output will be non- if the argument to the - parameter specified is non-. - - - - - Specifies that when a method returns , - the parameter will not be even if the corresponding type allows it. - - - - - Gets the return value condition. - If the method returns this value, the associated parameter will not be . - - - - - Initializes the attribute with the specified return value condition. - - - The return value condition. - If the method returns this value, the associated parameter will not be . - - - - diff --git a/CryptoExchange.Net/Interfaces/IRequest.cs b/CryptoExchange.Net/Interfaces/IRequest.cs index 9e819cb..9d02651 100644 --- a/CryptoExchange.Net/Interfaces/IRequest.cs +++ b/CryptoExchange.Net/Interfaces/IRequest.cs @@ -27,6 +27,10 @@ namespace CryptoExchange.Net.Interfaces /// Uri Uri { get; } /// + /// internal request id for tracing + /// + string? RequestId { get; } + /// /// Set byte content /// /// diff --git a/CryptoExchange.Net/Interfaces/IRequestFactory.cs b/CryptoExchange.Net/Interfaces/IRequestFactory.cs index ceb7f8c..d519fe9 100644 --- a/CryptoExchange.Net/Interfaces/IRequestFactory.cs +++ b/CryptoExchange.Net/Interfaces/IRequestFactory.cs @@ -22,6 +22,7 @@ namespace CryptoExchange.Net.Interfaces /// /// Request timeout to use /// Proxy settings to use - void Configure(TimeSpan requestTimeout, ApiProxy? proxy); + /// Should generate unique id for requests + void Configure(TimeSpan requestTimeout, ApiProxy? proxy, bool isTracingEnabled=false); } } diff --git a/CryptoExchange.Net/Objects/Options.cs b/CryptoExchange.Net/Objects/Options.cs index 515494d..7015b3e 100644 --- a/CryptoExchange.Net/Objects/Options.cs +++ b/CryptoExchange.Net/Objects/Options.cs @@ -127,7 +127,7 @@ namespace CryptoExchange.Net.Objects /// The time the server has to respond to a request before timing out /// public TimeSpan RequestTimeout { get; set; } = TimeSpan.FromSeconds(30); - + public bool IsRequestsTracingEnabled { get; set; } = false; /// /// ctor /// diff --git a/CryptoExchange.Net/Requests/Request.cs b/CryptoExchange.Net/Requests/Request.cs index 5c4530c..0afa03e 100644 --- a/CryptoExchange.Net/Requests/Request.cs +++ b/CryptoExchange.Net/Requests/Request.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Net.Http; using System.Net.Http.Headers; using System.Text; @@ -21,10 +22,15 @@ namespace CryptoExchange.Net.Requests /// /// /// - public Request(HttpRequestMessage request, HttpClient client) + /// if true, should assign unique id for request + public Request(HttpRequestMessage request, HttpClient client, bool isTracingEnabled=false) { httpClient = client; this.request = request; + if (isTracingEnabled) + { + RequestId = Path.GetRandomFileName(); + } } /// @@ -45,6 +51,8 @@ namespace CryptoExchange.Net.Requests /// public Uri Uri => request.RequestUri; + /// + public string? RequestId { get; } /// public void SetContent(string data, string contentType) diff --git a/CryptoExchange.Net/Requests/RequestFactory.cs b/CryptoExchange.Net/Requests/RequestFactory.cs index 2434ca1..dd5d861 100644 --- a/CryptoExchange.Net/Requests/RequestFactory.cs +++ b/CryptoExchange.Net/Requests/RequestFactory.cs @@ -12,10 +12,11 @@ namespace CryptoExchange.Net.Requests public class RequestFactory : IRequestFactory { private HttpClient? httpClient; - + private bool isTracingEnabled; /// - public void Configure(TimeSpan requestTimeout, ApiProxy? proxy) + public void Configure(TimeSpan requestTimeout, ApiProxy? proxy, bool isTracingEnabled = false) { + this.isTracingEnabled = isTracingEnabled; HttpMessageHandler handler = new HttpClientHandler() { Proxy = proxy == null ? null : new WebProxy @@ -25,7 +26,7 @@ namespace CryptoExchange.Net.Requests } }; - httpClient = new HttpClient(handler) {Timeout = requestTimeout}; + httpClient = new HttpClient(handler) { Timeout = requestTimeout }; } /// @@ -34,7 +35,7 @@ namespace CryptoExchange.Net.Requests if (httpClient == null) throw new InvalidOperationException("Cant create request before configuring http client"); - return new Request(new HttpRequestMessage(method, uri), httpClient); + return new Request(new HttpRequestMessage(method, uri), httpClient, isTracingEnabled); } } } diff --git a/CryptoExchange.Net/RestClient.cs b/CryptoExchange.Net/RestClient.cs index d3a0f55..1072ca8 100644 --- a/CryptoExchange.Net/RestClient.cs +++ b/CryptoExchange.Net/RestClient.cs @@ -83,7 +83,7 @@ namespace CryptoExchange.Net throw new ArgumentNullException(nameof(exchangeOptions)); RequestTimeout = exchangeOptions.RequestTimeout; - RequestFactory.Configure(exchangeOptions.RequestTimeout, exchangeOptions.Proxy); + RequestFactory.Configure(exchangeOptions.RequestTimeout, exchangeOptions.Proxy,exchangeOptions.IsRequestsTracingEnabled); RateLimitBehaviour = exchangeOptions.RateLimitingBehaviour; var rateLimiters = new List(); foreach (var rateLimiter in exchangeOptions.RateLimiters) @@ -190,14 +190,14 @@ namespace CryptoExchange.Net } if (limitResult.Data > 0) - log.Write(LogVerbosity.Debug, $"Request {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}"); + log.Write(LogVerbosity.Debug, $"Request {request.RequestId} {uri.AbsolutePath} was limited by {limitResult.Data}ms by {limiter.GetType().Name}"); } string? paramString = null; if (method == HttpMethod.Post) paramString = " with request body " + request.Content; - log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null? "": $" via proxy {apiProxy.Host}")}"); + log.Write(LogVerbosity.Debug, $"Sending {method}{(signed ? " signed" : "")} request to {request.Uri}{paramString ?? " "}{(apiProxy == null? "": $" via proxy {apiProxy.Host}")} {(request.RequestId==null?"":$" with id {request.RequestId}")}"); return await GetResponse(request, cancellationToken).ConfigureAwait(false); } @@ -224,7 +224,7 @@ namespace CryptoExchange.Net var data = await reader.ReadToEndAsync().ConfigureAwait(false); responseStream.Close(); response.Close(); - log.Write(LogVerbosity.Debug, $"Data received: {data}"); + log.Write(LogVerbosity.Debug, $"Data {(request.RequestId==null?"":$"for request {request.RequestId} ")}received: {data}"); var parseResult = ValidateJson(data); if (!parseResult.Success) @@ -249,7 +249,7 @@ namespace CryptoExchange.Net { using var reader = new StreamReader(responseStream); var data = await reader.ReadToEndAsync().ConfigureAwait(false); - log.Write(LogVerbosity.Debug, $"Error received: {data}"); + log.Write(LogVerbosity.Debug, $"Error {(request.RequestId == null ? "" : $"for request {request.RequestId} ")}received: {data}"); responseStream.Close(); response.Close(); var parseResult = ValidateJson(data); @@ -258,7 +258,7 @@ namespace CryptoExchange.Net } catch (HttpRequestException requestException) { - log.Write(LogVerbosity.Warning, "Request exception: " + requestException.Message); + log.Write(LogVerbosity.Warning, $"Request {request.RequestId} exception: " + requestException.Message); return new WebCallResult(null, null, default, new ServerError(requestException.Message)); } catch (TaskCanceledException canceledException) @@ -266,14 +266,14 @@ namespace CryptoExchange.Net if(canceledException.CancellationToken == cancellationToken) { // Cancellation token cancelled - log.Write(LogVerbosity.Warning, "Request cancel requested"); + log.Write(LogVerbosity.Warning, $"Request {request.RequestId} cancel requested"); return new WebCallResult(null, null, default, new CancellationRequestedError()); } else { // Request timed out - log.Write(LogVerbosity.Warning, "Request timed out"); - return new WebCallResult(null, null, default, new WebError("Request timed out")); + log.Write(LogVerbosity.Warning, $"Request {request.RequestId} timed out"); + return new WebCallResult(null, null, default, new WebError($"Request {request.RequestId} timed out")); } } }