mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-13 09:23:04 +00:00
e823114623
* Result types: * (Web)CallResult types are replaced by HttpResult, WebSocketResult and QueryResult with the same logic * Updated result types to record type * Result creation can be done with (Http/WebSocket/Query)Result.Ok(..) and .Fail(..) * Removed implicit result type conversion to bool, `if (result)` no longer works, instead use `if (result.Success)` * Replaced CallResult.SuccessResult with CallResult.Ok() * Fixed result object nullability hinting, for example Data might be null if Success isn't checked for true * Parameters & serialization: * Added support for `enabled` and `disabled` strings to bool converter * Removed ParameterCollection type, has been replaced by Parameters type * Removed ArraySerialization, OrderParameters and ParameterOrderComparer properties from RestApiClient, moved to ParameterSerializationsSettings * Updated RestRequestConfiguration in AuthenticationProvider.ProcessRequest to contain the full RequestDefinition instead of copied fields * Clients: * Updated Api client constructor logging parameter from ILogger to ILoggerFactory? * Added Api client constructor exchange name parameter * Added ToString overrides on base API types * Added Exchange property on BaseApiClient * Added ApiCredentials property on IRestApiClient and ISocketApiClient interfaces * Updated ILogger source from client name to topic specific client name * Removed logging from client creation * Fixed BaseRestClient SetApiCredentials not marked as virtual * Rest: * Added BaseAddress to RequestDefinition object * Updated RestApiClient AuthenticationProvider logic from private to protected and virtual * Removed RestApiClient.SendAsync baseAddress parameter removed * Removed RestApiClient.SendAsync without type parameter * WebSocket: * Updated MessageRouting definition into CreateForEvent for subscriptions and CreateForQuery for queries * Improved Query type safety with CeateForQuery which allows second parameter for specifying the result type * Renamed MessageRouter.CreateWithoutHandler to CreateVoid * Updated SocketApiClient.GetSocketConnection to check connection uri instead of Tag for finding compatible connections * Removed unused UnhandledMessageExpected property SocketApiClient * Fixed issue in SocketApiClient.GetSocketConnection causing requests to always wait the full max 10 seconds when there was a reconnecting socket * Shared APIs: * Updated Option definitions to always require the exchange name as first parameter * Added missing dedicated option types * Added Discover method on ISharedClient interface, returning info on supported capabilities and operations * Added SharedRequest GetParamValue helper method accepting multiple parameter names * Added ResetStaticExchangeParameters method on ExchangeParameters * Added Status property to SharedWithdrawal model * Added TradingModes property to SharedBalance model * Updated ExchangeSymbolCache to support multiple environments and additional key separation * Updated Shared ExchangeParameters parameter names to be case insensitive * Updated code comments * Replaced ExchangeResult with ExchangeCallResult type * Removed AsExchangeResult/ExchangeWebResult * Removed TradingMode from the response model, only maintained on models where it makes sense * Removed IListenKey support, listen keys now rely on internal management with TokenManager * Rate limiting: * Fixed websocket connection attempts counting towards rate limit even when server could not be reached * Removed host from rate limit methods, now part of the already provided RequestDefinition * Added amount parameter to RateLimit Reset method to allow partially resetting the limit * Added TokenManager implementation for automatic listenkey/token management * Added UserClientProvider base class * Added async streaming on UserDataTracker items with StreamUpdatesAsync * Added cancellation token support to UserDataTracker starting * Added Unit type for non-result types * Added ServerError constructor taking ErrorType and message to make it easier to create * Added SupportedEnvironments property to PlatformInfo * Updated SymbolOrderBook DoResyncAsync to return CallResult instead of CallResult<bool> which was redundant * Various small performance improvements
160 lines
7.7 KiB
C#
160 lines
7.7 KiB
C#
using CryptoExchange.Net.Objects;
|
|
using Microsoft.Extensions.Logging;
|
|
using System;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
|
|
namespace CryptoExchange.Net.Logging.Extensions
|
|
{
|
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
public static class RestApiClientLoggingExtensions
|
|
{
|
|
private static readonly Action<ILogger, int?, int?, long, string?, string?, Exception?> _restApiErrorReceived;
|
|
private static readonly Action<ILogger, int?, int?, long, string?, Exception?> _restApiResponseReceived;
|
|
private static readonly Action<ILogger, int, string, Exception?> _restApiFailedToSyncTime;
|
|
private static readonly Action<ILogger, int, string, Exception?> _restApiNoApiCredentials;
|
|
private static readonly Action<ILogger, int, Uri, Exception?> _restApiCreatingRequest;
|
|
private static readonly Action<ILogger, int, HttpMethod, string, Uri, string, Exception?> _restApiSendingRequest;
|
|
private static readonly Action<ILogger, int, DateTime, Exception?> _restApiRateLimitRetry;
|
|
private static readonly Action<ILogger, int, DateTime, Exception?> _restApiRateLimitPauseUntil;
|
|
private static readonly Action<ILogger, int, RequestDefinition, string?, string, string, Exception?> _restApiSendRequest;
|
|
private static readonly Action<ILogger, string, Exception?> _restApiCheckingCache;
|
|
private static readonly Action<ILogger, string, Exception?> _restApiCacheHit;
|
|
private static readonly Action<ILogger, string, Exception?> _restApiCacheNotHit;
|
|
private static readonly Action<ILogger, int?, Exception?> _restApiCancellationRequested;
|
|
|
|
static RestApiClientLoggingExtensions()
|
|
{
|
|
_restApiErrorReceived = LoggerMessage.Define<int?, int?, long, string?, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(4000, "RestApiErrorReceived"),
|
|
"[Req {RequestId}] {ResponseStatusCode} - error received in {ResponseTime}ms: {ErrorMessage}, Data: {OriginalData}");
|
|
|
|
_restApiResponseReceived = LoggerMessage.Define<int?, int?, long, string?>(
|
|
LogLevel.Debug,
|
|
new EventId(4001, "RestApiResponseReceived"),
|
|
"[Req {RequestId}] {ResponseStatusCode} - response received in {ResponseTime}ms: {OriginalData}");
|
|
|
|
_restApiFailedToSyncTime = LoggerMessage.Define<int, string>(
|
|
LogLevel.Debug,
|
|
new EventId(4002, "RestApiFailedToSyncTime"),
|
|
"[Req {RequestId}] failed to sync time, aborting request: {ErrorMessage}");
|
|
|
|
_restApiNoApiCredentials = LoggerMessage.Define<int, string>(
|
|
LogLevel.Warning,
|
|
new EventId(4003, "RestApiNoApiCredentials"),
|
|
"[Req {RequestId}] request {RestApiUri} failed because no ApiCredentials were provided");
|
|
|
|
_restApiCreatingRequest = LoggerMessage.Define<int, Uri>(
|
|
LogLevel.Information,
|
|
new EventId(4004, "RestApiCreatingRequest"),
|
|
"[Req {RequestId}] creating request for {RestApiUri}");
|
|
|
|
_restApiSendingRequest = LoggerMessage.Define<int, HttpMethod, string, Uri, string>(
|
|
LogLevel.Trace,
|
|
new EventId(4005, "RestApiSendingRequest"),
|
|
"[Req {RequestId}] sending {Method} {Signed} request to {RestApiUri}{Query}");
|
|
|
|
_restApiRateLimitRetry = LoggerMessage.Define<int, DateTime>(
|
|
LogLevel.Warning,
|
|
new EventId(4006, "RestApiRateLimitRetry"),
|
|
"[Req {RequestId}] received ratelimit error, retrying after {Timestamp}");
|
|
|
|
_restApiRateLimitPauseUntil = LoggerMessage.Define<int, DateTime>(
|
|
LogLevel.Warning,
|
|
new EventId(4007, "RestApiRateLimitPauseUntil"),
|
|
"[Req {RequestId}] ratelimit error from server, pausing requests until {Until}");
|
|
|
|
_restApiSendRequest = LoggerMessage.Define<int, RequestDefinition, string?, string, string>(
|
|
LogLevel.Debug,
|
|
new EventId(4008, "RestApiSendRequest"),
|
|
"[Req {RequestId}] sending {Definition} request with body {Body}, query parameters {Query} and headers {Headers}");
|
|
|
|
_restApiCheckingCache = LoggerMessage.Define<string>(
|
|
LogLevel.Trace,
|
|
new EventId(4009, "RestApiCheckingCache"),
|
|
"checking cache for key {Key}");
|
|
|
|
_restApiCacheHit = LoggerMessage.Define<string>(
|
|
LogLevel.Trace,
|
|
new EventId(4010, "RestApiCacheHit"),
|
|
"cache hit for key {Key}");
|
|
|
|
_restApiCacheNotHit = LoggerMessage.Define<string>(
|
|
LogLevel.Trace,
|
|
new EventId(4011, "RestApiCacheNotHit"),
|
|
"cache not hit for key {Key}");
|
|
|
|
_restApiCancellationRequested = LoggerMessage.Define<int?>(
|
|
LogLevel.Debug,
|
|
new EventId(4012, "RestApiCancellationRequested"),
|
|
"[Req {RequestId}] request cancelled by user");
|
|
|
|
}
|
|
|
|
public static void RestApiErrorReceived(this ILogger logger, int? requestId, HttpStatusCode? responseStatusCode, long responseTime, string? error, string? originalData, Exception? exception)
|
|
{
|
|
_restApiErrorReceived(logger, requestId, (int?)responseStatusCode, responseTime, error, originalData, exception);
|
|
}
|
|
|
|
public static void RestApiResponseReceived(this ILogger logger, int? requestId, HttpStatusCode? responseStatusCode, long responseTime, string? originalData)
|
|
{
|
|
_restApiResponseReceived(logger, requestId, (int?)responseStatusCode, responseTime, originalData, null);
|
|
}
|
|
|
|
public static void RestApiFailedToSyncTime(this ILogger logger, int requestId, string error)
|
|
{
|
|
_restApiFailedToSyncTime(logger, requestId, error, null);
|
|
}
|
|
|
|
public static void RestApiNoApiCredentials(this ILogger logger, int requestId, string uri)
|
|
{
|
|
_restApiNoApiCredentials(logger, requestId, uri, null);
|
|
}
|
|
|
|
public static void RestApiCreatingRequest(this ILogger logger, int requestId, Uri uri)
|
|
{
|
|
_restApiCreatingRequest(logger, requestId, uri, null);
|
|
}
|
|
|
|
public static void RestApiSendingRequest(this ILogger logger, int requestId, HttpMethod method, string signed, Uri uri, string paramString)
|
|
{
|
|
_restApiSendingRequest(logger, requestId, method, signed, uri, paramString, null);
|
|
}
|
|
|
|
public static void RestApiRateLimitRetry(this ILogger logger, int requestId, DateTime retryAfter)
|
|
{
|
|
_restApiRateLimitRetry(logger, requestId, retryAfter, null);
|
|
}
|
|
|
|
public static void RestApiRateLimitPauseUntil(this ILogger logger, int requestId, DateTime retryAfter)
|
|
{
|
|
_restApiRateLimitPauseUntil(logger, requestId, retryAfter, null);
|
|
}
|
|
|
|
public static void RestApiSendRequest(this ILogger logger, int requestId, RequestDefinition definition, string? body, string query, string headers)
|
|
{
|
|
_restApiSendRequest(logger, requestId, definition, body, query, headers, null);
|
|
}
|
|
|
|
public static void CheckingCache(this ILogger logger, string key)
|
|
{
|
|
_restApiCheckingCache(logger, key, null);
|
|
}
|
|
|
|
public static void CacheHit(this ILogger logger, string key)
|
|
{
|
|
_restApiCacheHit(logger, key, null);
|
|
}
|
|
|
|
public static void CacheNotHit(this ILogger logger, string key)
|
|
{
|
|
_restApiCacheNotHit(logger, key, null);
|
|
}
|
|
public static void RestApiCancellationRequested(this ILogger logger, int? requestId)
|
|
{
|
|
_restApiCancellationRequested(logger, requestId, null);
|
|
}
|
|
}
|
|
}
|