1
0
mirror of https://github.com/JKorf/CryptoExchange.Net synced 2025-06-07 16:06:15 +00:00

Updated response logging, added RequestId to WebCallResult

This commit is contained in:
JKorf 2023-11-30 14:19:58 +01:00
parent 8788dd3deb
commit 104ac7caad
3 changed files with 49 additions and 28 deletions

View File

@ -113,6 +113,11 @@ namespace CryptoExchange.Net
return new WebCallResult(request.Error!); return new WebCallResult(request.Error!);
var result = await GetResponseAsync<object>(request.Data, deserializer, cancellationToken, true).ConfigureAwait(false); var result = await GetResponseAsync<object>(request.Data, deserializer, cancellationToken, true).ConfigureAwait(false);
if (!result)
_logger.Log(LogLevel.Warning, $"[{result.RequestId}] Error received in {result.ResponseTime!.Value.TotalMilliseconds}ms: {result.Error}");
else
_logger.Log(LogLevel.Debug, $"[{result.RequestId}] Response received in {result.ResponseTime!.Value.TotalMilliseconds}ms{(OutputOriginalData ? (": " + result.OriginalData) : "")}");
if (await ShouldRetryRequestAsync(result, currentTry).ConfigureAwait(false)) if (await ShouldRetryRequestAsync(result, currentTry).ConfigureAwait(false))
continue; continue;
@ -160,6 +165,11 @@ namespace CryptoExchange.Net
return new WebCallResult<T>(request.Error!); return new WebCallResult<T>(request.Error!);
var result = await GetResponseAsync<T>(request.Data, deserializer, cancellationToken, false).ConfigureAwait(false); var result = await GetResponseAsync<T>(request.Data, deserializer, cancellationToken, false).ConfigureAwait(false);
if (!result)
_logger.Log(LogLevel.Warning, $"[{result.RequestId}] Error received in {result.ResponseTime!.Value.TotalMilliseconds}ms: {result.Error}");
else
_logger.Log(LogLevel.Debug, $"[{result.RequestId}] Response received in {result.ResponseTime!.Value.TotalMilliseconds}ms{(OutputOriginalData ? (": " + result.OriginalData) : "")}");
if (await ShouldRetryRequestAsync(result, currentTry).ConfigureAwait(false)) if (await ShouldRetryRequestAsync(result, currentTry).ConfigureAwait(false))
continue; continue;
@ -261,9 +271,9 @@ namespace CryptoExchange.Net
CancellationToken cancellationToken, CancellationToken cancellationToken,
bool expectedEmptyResponse) bool expectedEmptyResponse)
{ {
var sw = Stopwatch.StartNew();
try try
{ {
var sw = Stopwatch.StartNew();
var response = await request.GetResponseAsync(cancellationToken).ConfigureAwait(false); var response = await request.GetResponseAsync(cancellationToken).ConfigureAwait(false);
sw.Stop(); sw.Stop();
var statusCode = response.StatusCode; var statusCode = response.StatusCode;
@ -281,23 +291,22 @@ namespace CryptoExchange.Net
responseLength ??= data.Length; responseLength ??= data.Length;
responseStream.Close(); responseStream.Close();
response.Close(); response.Close();
_logger.Log(LogLevel.Debug, $"[{request.RequestId}] Response received in {sw.ElapsedMilliseconds}ms{(OutputOriginalData ? (": " + data) : "")}");
if (!expectedEmptyResponse) if (!expectedEmptyResponse)
{ {
// Validate if it is valid json. Sometimes other data will be returned, 502 error html pages for example // Validate if it is valid json. Sometimes other data will be returned, 502 error html pages for example
var parseResult = ValidateJson(data); var parseResult = ValidateJson(data);
if (!parseResult.Success) if (!parseResult.Success)
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, parseResult.Error!); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, parseResult.Error!);
// Let the library implementation see if it is an error response, and if so parse the error // Let the library implementation see if it is an error response, and if so parse the error
var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false); var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false);
if (error != null) if (error != null)
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error!); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error!);
// Not an error, so continue deserializing // Not an error, so continue deserializing
var deserializeResult = Deserialize<T>(parseResult.Data, deserializer, request.RequestId); var deserializeResult = Deserialize<T>(parseResult.Data, deserializer, request.RequestId);
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), deserializeResult.Data, deserializeResult.Error); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), deserializeResult.Data, deserializeResult.Error);
} }
else else
{ {
@ -306,16 +315,16 @@ namespace CryptoExchange.Net
var parseResult = ValidateJson(data); var parseResult = ValidateJson(data);
if (!parseResult.Success) if (!parseResult.Success)
// Not empty, and not json // Not empty, and not json
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, parseResult.Error!); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, parseResult.Error!);
var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false); var error = await TryParseErrorAsync(parseResult.Data).ConfigureAwait(false);
if (error != null) if (error != null)
// Error response // Error response
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error!); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error!);
} }
// Empty success response; okay // Empty success response; okay
return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, default); return new WebCallResult<T>(response.StatusCode, response.ResponseHeaders, sw.Elapsed, responseLength, OutputOriginalData ? data : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, default);
} }
} }
else else
@ -326,7 +335,7 @@ namespace CryptoExchange.Net
responseStream.Close(); responseStream.Close();
response.Close(); response.Close();
return new WebCallResult<T>(statusCode, headers, sw.Elapsed, 0, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, null); return new WebCallResult<T>(statusCode, headers, sw.Elapsed, 0, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, null);
} }
// Success status code, and we don't have to check for errors. Continue deserializing directly from the stream // Success status code, and we don't have to check for errors. Continue deserializing directly from the stream
@ -334,7 +343,7 @@ namespace CryptoExchange.Net
responseStream.Close(); responseStream.Close();
response.Close(); response.Close();
return new WebCallResult<T>(statusCode, headers, sw.Elapsed, responseLength, OutputOriginalData ? desResult.OriginalData : null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), desResult.Data, desResult.Error); return new WebCallResult<T>(statusCode, headers, sw.Elapsed, responseLength, OutputOriginalData ? desResult.OriginalData : null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), desResult.Data, desResult.Error);
} }
} }
else else
@ -342,7 +351,6 @@ namespace CryptoExchange.Net
// Http status code indicates error // Http status code indicates error
using var reader = new StreamReader(responseStream); using var reader = new StreamReader(responseStream);
var data = await reader.ReadToEndAsync().ConfigureAwait(false); var data = await reader.ReadToEndAsync().ConfigureAwait(false);
_logger.Log(LogLevel.Warning, $"[{request.RequestId}] Error received in {sw.ElapsedMilliseconds}ms: {data}");
responseStream.Close(); responseStream.Close();
response.Close(); response.Close();
@ -354,29 +362,26 @@ namespace CryptoExchange.Net
if (error.Code == null || error.Code == 0) if (error.Code == null || error.Code == 0)
error.Code = (int)response.StatusCode; error.Code = (int)response.StatusCode;
return new WebCallResult<T>(statusCode, headers, sw.Elapsed, data.Length, data, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error); return new WebCallResult<T>(statusCode, headers, sw.Elapsed, data.Length, data, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, error);
} }
} }
catch (HttpRequestException requestException) catch (HttpRequestException requestException)
{ {
// Request exception, can't reach server for instance // Request exception, can't reach server for instance
var exceptionInfo = requestException.ToLogString(); var exceptionInfo = requestException.ToLogString();
_logger.Log(LogLevel.Warning, $"[{request.RequestId}] Request exception: " + exceptionInfo); return new WebCallResult<T>(null, null, sw.Elapsed, null, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError(exceptionInfo));
return new WebCallResult<T>(null, null, null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError(exceptionInfo));
} }
catch (OperationCanceledException canceledException) catch (OperationCanceledException canceledException)
{ {
if (cancellationToken != default && canceledException.CancellationToken == cancellationToken) if (cancellationToken != default && canceledException.CancellationToken == cancellationToken)
{ {
// Cancellation token canceled by caller // Cancellation token canceled by caller
_logger.Log(LogLevel.Warning, $"[{request.RequestId}] Request canceled by cancellation token"); return new WebCallResult<T>(null, null, sw.Elapsed, null, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new CancellationRequestedError());
return new WebCallResult<T>(null, null, null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new CancellationRequestedError());
} }
else else
{ {
// Request timed out // Request timed out
_logger.Log(LogLevel.Warning, $"[{request.RequestId}] Request timed out: " + canceledException.ToLogString()); return new WebCallResult<T>(null, null, sw.Elapsed, null, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError($"Request timed out"));
return new WebCallResult<T>(null, null, null, null, null, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, new WebError($"[{request.RequestId}] Request timed out"));
} }
} }
} }
@ -580,14 +585,14 @@ namespace CryptoExchange.Net
{ {
var timeSyncParams = GetTimeSyncInfo(); var timeSyncParams = GetTimeSyncInfo();
if (timeSyncParams == null) if (timeSyncParams == null)
return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, true, null); return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, null, true, null);
if (await timeSyncParams.TimeSyncState.Semaphore.WaitAsync(0).ConfigureAwait(false)) if (await timeSyncParams.TimeSyncState.Semaphore.WaitAsync(0).ConfigureAwait(false))
{ {
if (!timeSyncParams.SyncTime || (DateTime.UtcNow - timeSyncParams.TimeSyncState.LastSyncTime < timeSyncParams.RecalculationInterval)) if (!timeSyncParams.SyncTime || (DateTime.UtcNow - timeSyncParams.TimeSyncState.LastSyncTime < timeSyncParams.RecalculationInterval))
{ {
timeSyncParams.TimeSyncState.Semaphore.Release(); timeSyncParams.TimeSyncState.Semaphore.Release();
return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, true, null); return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, null, true, null);
} }
var localTime = DateTime.UtcNow; var localTime = DateTime.UtcNow;
@ -616,7 +621,7 @@ namespace CryptoExchange.Net
timeSyncParams.TimeSyncState.Semaphore.Release(); timeSyncParams.TimeSyncState.Semaphore.Release();
} }
return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, true, null); return new WebCallResult<bool>(null, null, null, null, null, null, null, null, null, null, true, null);
} }
} }
} }

View File

@ -186,6 +186,11 @@ namespace CryptoExchange.Net.Objects
/// </summary> /// </summary>
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? RequestHeaders { get; set; } public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? RequestHeaders { get; set; }
/// <summary>
/// The request id
/// </summary>
public int? RequestId { get; set; }
/// <summary> /// <summary>
/// The url which was requested /// The url which was requested
/// </summary> /// </summary>
@ -217,6 +222,7 @@ namespace CryptoExchange.Net.Objects
/// <param name="code"></param> /// <param name="code"></param>
/// <param name="responseHeaders"></param> /// <param name="responseHeaders"></param>
/// <param name="responseTime"></param> /// <param name="responseTime"></param>
/// <param name="requestId"></param>
/// <param name="requestUrl"></param> /// <param name="requestUrl"></param>
/// <param name="requestBody"></param> /// <param name="requestBody"></param>
/// <param name="requestMethod"></param> /// <param name="requestMethod"></param>
@ -226,6 +232,7 @@ namespace CryptoExchange.Net.Objects
HttpStatusCode? code, HttpStatusCode? code,
IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders, IEnumerable<KeyValuePair<string, IEnumerable<string>>>? responseHeaders,
TimeSpan? responseTime, TimeSpan? responseTime,
int? requestId,
string? requestUrl, string? requestUrl,
string? requestBody, string? requestBody,
HttpMethod? requestMethod, HttpMethod? requestMethod,
@ -235,6 +242,7 @@ namespace CryptoExchange.Net.Objects
ResponseStatusCode = code; ResponseStatusCode = code;
ResponseHeaders = responseHeaders; ResponseHeaders = responseHeaders;
ResponseTime = responseTime; ResponseTime = responseTime;
RequestId = requestId;
RequestUrl = requestUrl; RequestUrl = requestUrl;
RequestBody = requestBody; RequestBody = requestBody;
@ -255,7 +263,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public WebCallResult AsError(Error error) public WebCallResult AsError(Error error)
{ {
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error); return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -281,6 +289,11 @@ namespace CryptoExchange.Net.Objects
/// </summary> /// </summary>
public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? RequestHeaders { get; set; } public IEnumerable<KeyValuePair<string, IEnumerable<string>>>? RequestHeaders { get; set; }
/// <summary>
/// The request id
/// </summary>
public int? RequestId { get; set; }
/// <summary> /// <summary>
/// The url which was requested /// The url which was requested
/// </summary> /// </summary>
@ -319,6 +332,7 @@ namespace CryptoExchange.Net.Objects
/// <param name="responseTime"></param> /// <param name="responseTime"></param>
/// <param name="responseLength"></param> /// <param name="responseLength"></param>
/// <param name="originalData"></param> /// <param name="originalData"></param>
/// <param name="requestId"></param>
/// <param name="requestUrl"></param> /// <param name="requestUrl"></param>
/// <param name="requestBody"></param> /// <param name="requestBody"></param>
/// <param name="requestMethod"></param> /// <param name="requestMethod"></param>
@ -331,6 +345,7 @@ namespace CryptoExchange.Net.Objects
TimeSpan? responseTime, TimeSpan? responseTime,
long? responseLength, long? responseLength,
string? originalData, string? originalData,
int? requestId,
string? requestUrl, string? requestUrl,
string? requestBody, string? requestBody,
HttpMethod? requestMethod, HttpMethod? requestMethod,
@ -343,6 +358,7 @@ namespace CryptoExchange.Net.Objects
ResponseTime = responseTime; ResponseTime = responseTime;
ResponseLength = responseLength; ResponseLength = responseLength;
RequestId = requestId;
RequestUrl = requestUrl; RequestUrl = requestUrl;
RequestBody = requestBody; RequestBody = requestBody;
RequestHeaders = requestHeaders; RequestHeaders = requestHeaders;
@ -355,7 +371,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public new WebCallResult AsDataless() public new WebCallResult AsDataless()
{ {
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestUrl, RequestBody, RequestMethod, RequestHeaders, Error); return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, Error);
} }
/// <summary> /// <summary>
/// Copy as a dataless result /// Copy as a dataless result
@ -363,14 +379,14 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public new WebCallResult AsDatalessError(Error error) public new WebCallResult AsDatalessError(Error error)
{ {
return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error); return new WebCallResult(ResponseStatusCode, ResponseHeaders, ResponseTime, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, error);
} }
/// <summary> /// <summary>
/// Create a new error result /// Create a new error result
/// </summary> /// </summary>
/// <param name="error">The error</param> /// <param name="error">The error</param>
public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, null, null, default, error) { } public WebCallResult(Error? error) : this(null, null, null, null, null, null, null, null, null, null, default, error) { }
/// <summary> /// <summary>
/// Copy the WebCallResult to a new data type /// Copy the WebCallResult to a new data type
@ -380,7 +396,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public new WebCallResult<K> As<K>([AllowNull] K data) public new WebCallResult<K> As<K>([AllowNull] K data)
{ {
return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, data, Error); return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, data, Error);
} }
/// <summary> /// <summary>
@ -391,7 +407,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public new WebCallResult<K> AsError<K>(Error error) public new WebCallResult<K> AsError<K>(Error error)
{ {
return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestUrl, RequestBody, RequestMethod, RequestHeaders, default, error); return new WebCallResult<K>(ResponseStatusCode, ResponseHeaders, ResponseTime, ResponseLength, OriginalData, RequestId, RequestUrl, RequestBody, RequestMethod, RequestHeaders, default, error);
} }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -41,7 +41,7 @@ namespace CryptoExchange.Net.Objects
/// <returns></returns> /// <returns></returns>
public override string ToString() public override string ToString()
{ {
return Code != null ? $"{Code}: {Message} {Data}" : $"{Message} {Data}"; return Code != null ? $"[{GetType().Name}] {Code}: {Message} {Data}" : $"[{GetType().Name}] {Message} {Data}";
} }
} }