mirror of
https://github.com/JKorf/CryptoExchange.Net.git
synced 2026-08-12 00:43:03 +00:00
d079796020
Performance update: Authentication Added Ed25519 signing support for NET8.0 and newer Added static methods on ApiCredentials to create credentials of a specific type Added static ApiCredentials.ReadFromFile method to read a key from file Added required abstract SupportedCredentialTypes property on AuthenticationProvider base class General Performance Added checks before logging statements to prevent overhead of building the log string if logging is not needed Added ExchangeHelpers.ProcessQueuedAsync method to process updates async Replaced locking object types from object to Lock in NET9.0 and newer Replaced some Task response types with ValueTask to prevent allocation overhead on hot paths Updated Json ArrayConverter to reduce some allocation overhead Updated Json BoolConverter to prevent boxing Updated Json DateTimeConverter to prevent boxing Updated Json EnumConverter caching to reduce lookup overhead Updated ExtensionMethods.CreateParamString to reduce allocations Updated ExtensionMethods.AppendPath to reduce overhead REST Refactored REST message processing to separate IRestMessageHandler instance Split RestApiClient.PrepareAsync into CheckTimeSync and RateLimitAsync Updated IRequest.Accept type from string to MediaTypeWithQualityHeaderValue to prevent creation on each request Updated IRequest.GetHeaders response type from KeyValuePair<string, string[]>[] to HttpRequestHeaders to prevent additional mapping Updated IResponse.ResponseHeaders type from KeyValuePair<string, string[]>[] to HttpResponseHeaders to prevent additional mapping Updated WebCallResult RequestHeaders and ResponseHeaders types to HttpRequestHeaders and HttpResponseHeaders Removed unnecessary empty dictionary initializations for each request Removed CallResult creation in internal methods to prevent having to create multiple versions for different result types Socket Added HighPerformance websocket client implementation which significantly reduces memory overhead and improves speed but with certain limitations Added MaxIndividualSubscriptionsPerConnection setting in SocketApiClient to limit the number of individual stream subscriptions on a connection Added SocketIndividualSubscriptionCombineTarget option to set the target number of individual stream subscriptions per connection Added new websocket message handling logic which is faster and reduces memory allocation Added UseUpdatedDeserialization option to toggle between updated deserialization and old deserialization Added Exchange property to DataEvent to prevent additional mapping overhead for Shared apis Refactored message callback to be sync instead of async to prevent async overhead Refactored CryptoExchangeWebSocketClient.IncomingKbps calculation to significantly reduce overhead Moved websocket client creation from SocketApiClient to SocketConnection Removed DataEvent.As and DataEvent.ToCallResult methods in favor of single ToType method Removed DataEvent creation on lower levels to prevent having to create multiple versions for different result types Removed Subscription<TSubResponse, TUnsubResponse> as its no longer used Other Added null check to ParameterCollection for required parameters Added Net10.0 target framework Updated dependency versions Updated Shared asset aliases check to be culture invariant Updated Error string representation Updated some namespaces Updated SymbolOrderBook processing of buffered updates to prevent additional allocation Removed ExchangeEvent type which is no longer needed Removed unused usings
339 lines
17 KiB
C#
339 lines
17 KiB
C#
using System;
|
|
using System.Net.WebSockets;
|
|
using CryptoExchange.Net.Sockets.Default;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CryptoExchange.Net.Logging.Extensions
|
|
{
|
|
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
|
public static class SocketConnectionLoggingExtension
|
|
{
|
|
private static readonly Action<ILogger, int, bool, Exception?> _activityPaused;
|
|
private static readonly Action<ILogger, int, SocketStatus, SocketStatus, Exception?> _socketStatusChanged;
|
|
private static readonly Action<ILogger, int, string?, Exception?> _failedReconnectProcessing;
|
|
private static readonly Action<ILogger, int, Exception?> _unknownExceptionWhileProcessingReconnection;
|
|
private static readonly Action<ILogger, int, WebSocketError, string?, Exception?> _webSocketErrorCodeAndDetails;
|
|
private static readonly Action<ILogger, int, string?, Exception?> _webSocketError;
|
|
private static readonly Action<ILogger, int, string, Exception?> _receivedData;
|
|
private static readonly Action<ILogger, int, string, Exception?> _failedToParse;
|
|
private static readonly Action<ILogger, int, string, Exception?> _failedToEvaluateMessage;
|
|
private static readonly Action<ILogger, int, Exception?> _errorProcessingMessage;
|
|
private static readonly Action<ILogger, int, string, string, Exception?> _processorMatched;
|
|
private static readonly Action<ILogger, int, int, Exception?> _receivedMessageNotRecognized;
|
|
private static readonly Action<ILogger, int, string?, Exception?> _failedToDeserializeMessage;
|
|
private static readonly Action<ILogger, int, string, Exception?> _userMessageProcessingFailed;
|
|
private static readonly Action<ILogger, int, long, long, Exception?> _messageProcessed;
|
|
private static readonly Action<ILogger, int, int, Exception?> _closingSubscription;
|
|
private static readonly Action<ILogger, int, Exception?> _notUnsubscribingSubscriptionBecauseDuplicateRunning;
|
|
private static readonly Action<ILogger, int, Exception?> _alreadyClosing;
|
|
private static readonly Action<ILogger, int, Exception?> _closingNoMoreSubscriptions;
|
|
private static readonly Action<ILogger, int, int, int, Exception?> _addingNewSubscription;
|
|
private static readonly Action<ILogger, int, Exception?> _nothingToResubscribeCloseConnection;
|
|
private static readonly Action<ILogger, int, Exception?> _failedAuthenticationDisconnectAndReconnect;
|
|
private static readonly Action<ILogger, int, Exception?> _authenticationSucceeded;
|
|
private static readonly Action<ILogger, int, string?, Exception?> _failedRequestRevitalization;
|
|
private static readonly Action<ILogger, int, Exception?> _allSubscriptionResubscribed;
|
|
private static readonly Action<ILogger, int, int, Exception?> _subscriptionUnsubscribed;
|
|
private static readonly Action<ILogger, int, string, Exception?> _sendingPeriodic;
|
|
private static readonly Action<ILogger, int, string, string, Exception?> _periodicSendFailed;
|
|
private static readonly Action<ILogger, int, int, string, Exception?> _sendingData;
|
|
private static readonly Action<ILogger, int, string, string, Exception?> _receivedMessageNotMatchedToAnyListener;
|
|
private static readonly Action<ILogger, int, int, int, Exception?> _sendingByteData;
|
|
|
|
static SocketConnectionLoggingExtension()
|
|
{
|
|
_activityPaused = LoggerMessage.Define<int, bool>(
|
|
LogLevel.Information,
|
|
new EventId(2000, "ActivityPaused"),
|
|
"[Sckt {SocketId}] paused activity: {Paused}");
|
|
|
|
_socketStatusChanged = LoggerMessage.Define<int, SocketStatus, SocketStatus>(
|
|
LogLevel.Debug,
|
|
new EventId(2001, "SocketStatusChanged"),
|
|
"[Sckt {SocketId}] status changed from {OldStatus} to {NewStatus}");
|
|
|
|
_failedReconnectProcessing = LoggerMessage.Define<int, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(2002, "FailedReconnectProcessing"),
|
|
"[Sckt {SocketId}] failed reconnect processing: {ErrorMessage}, reconnecting again");
|
|
|
|
_unknownExceptionWhileProcessingReconnection = LoggerMessage.Define<int>(
|
|
LogLevel.Warning,
|
|
new EventId(2003, "UnknownExceptionWhileProcessingReconnection"),
|
|
"[Sckt {SocketId}] Unknown exception while processing reconnection, reconnecting again");
|
|
|
|
_webSocketErrorCodeAndDetails = LoggerMessage.Define<int, WebSocketError, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(2004, "WebSocketErrorCode"),
|
|
"[Sckt {SocketId}] error: Websocket error code {WebSocketErrorCode}, details: {Details}");
|
|
|
|
_webSocketError = LoggerMessage.Define<int, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(2005, "WebSocketError"),
|
|
"[Sckt {SocketId}] error: {ErrorMessage}");
|
|
|
|
_receivedData = LoggerMessage.Define<int, string>(
|
|
LogLevel.Trace,
|
|
new EventId(2007, "ReceivedData"),
|
|
"[Sckt {SocketId}] received {OriginalData}");
|
|
|
|
_failedToEvaluateMessage = LoggerMessage.Define<int, string>(
|
|
LogLevel.Warning,
|
|
new EventId(2008, "FailedToEvaluateMessage"),
|
|
"[Sckt {SocketId}] failed to evaluate message. {OriginalData}");
|
|
|
|
_errorProcessingMessage = LoggerMessage.Define<int>(
|
|
LogLevel.Error,
|
|
new EventId(2009, "ErrorProcessingMessage"),
|
|
"[Sckt {SocketId}] error processing message");
|
|
|
|
_receivedMessageNotRecognized = LoggerMessage.Define<int, int>(
|
|
LogLevel.Warning,
|
|
new EventId(2011, "ReceivedMessageNotRecognized"),
|
|
"[Sckt {SocketId}] received message not recognized by handler {ProcessorId}");
|
|
|
|
_failedToDeserializeMessage = LoggerMessage.Define<int, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(2012, "FailedToDeserializeMessage"),
|
|
"[Sckt {SocketId}] deserialization failed: {ErrorMessage}");
|
|
|
|
_userMessageProcessingFailed = LoggerMessage.Define<int, string>(
|
|
LogLevel.Warning,
|
|
new EventId(2013, "UserMessageProcessingFailed"),
|
|
"[Sckt {SocketId}] user message processing failed: {ErrorMessage}");
|
|
|
|
_messageProcessed = LoggerMessage.Define<int, long, long>(
|
|
LogLevel.Trace,
|
|
new EventId(2014, "MessageProcessed"),
|
|
"[Sckt {SocketId}] message processed in {ProcessingTime}ms, {ParsingTime}ms parsing");
|
|
|
|
_closingSubscription = LoggerMessage.Define<int, int>(
|
|
LogLevel.Debug,
|
|
new EventId(2015, "ClosingSubscription"),
|
|
"[Sckt {SocketId}] closing subscription {SubscriptionId}");
|
|
|
|
_notUnsubscribingSubscriptionBecauseDuplicateRunning = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2016, "NotUnsubscribingSubscription"),
|
|
"[Sckt {SocketId}] not unsubscribing subscription as there is still a duplicate subscription running");
|
|
|
|
_alreadyClosing = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2017, "AlreadyClosing"),
|
|
"[Sckt {SocketId}] already closing");
|
|
|
|
_closingNoMoreSubscriptions = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2018, "ClosingNoMoreSubscriptions"),
|
|
"[Sckt {SocketId}] closing as there are no more subscriptions");
|
|
|
|
_addingNewSubscription = LoggerMessage.Define<int, int, int>(
|
|
LogLevel.Debug,
|
|
new EventId(2019, "AddingNewSubscription"),
|
|
"[Sckt {SocketId}] adding new subscription with id {SubscriptionId}, total subscriptions on connection: {UserSubscriptionCount}");
|
|
|
|
_nothingToResubscribeCloseConnection = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2020, "NothingToResubscribe"),
|
|
"[Sckt {SocketId}] nothing to resubscribe, closing connection");
|
|
|
|
_failedAuthenticationDisconnectAndReconnect = LoggerMessage.Define<int>(
|
|
LogLevel.Warning,
|
|
new EventId(2021, "FailedAuthentication"),
|
|
"[Sckt {SocketId}] authentication failed on reconnected socket. Disconnecting and reconnecting");
|
|
|
|
_authenticationSucceeded = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2022, "AuthenticationSucceeded"),
|
|
"[Sckt {SocketId}] authentication succeeded on reconnected socket");
|
|
|
|
_failedRequestRevitalization = LoggerMessage.Define<int, string?>(
|
|
LogLevel.Warning,
|
|
new EventId(2023, "FailedRequestRevitalization"),
|
|
"[Sckt {SocketId}] failed request revitalization: {ErrorMessage}");
|
|
|
|
_allSubscriptionResubscribed = LoggerMessage.Define<int>(
|
|
LogLevel.Debug,
|
|
new EventId(2024, "AllSubscriptionResubscribed"),
|
|
"[Sckt {SocketId}] all subscription successfully resubscribed on reconnected socket");
|
|
|
|
_subscriptionUnsubscribed = LoggerMessage.Define<int, int>(
|
|
LogLevel.Information,
|
|
new EventId(2025, "SubscriptionUnsubscribed"),
|
|
"[Sckt {SocketId}] subscription {SubscriptionId} unsubscribed");
|
|
|
|
_sendingPeriodic = LoggerMessage.Define<int, string>(
|
|
LogLevel.Trace,
|
|
new EventId(2026, "SendingPeriodic"),
|
|
"[Sckt {SocketId}] sending periodic {Identifier}");
|
|
|
|
_periodicSendFailed = LoggerMessage.Define<int, string, string>(
|
|
LogLevel.Warning,
|
|
new EventId(2027, "PeriodicSendFailed"),
|
|
"[Sckt {SocketId}] periodic send {Identifier} failed: {ErrorMessage}");
|
|
|
|
_sendingData = LoggerMessage.Define<int, int, string>(
|
|
LogLevel.Trace,
|
|
new EventId(2028, "SendingData"),
|
|
"[Sckt {SocketId}] [Req {RequestId}] sending message: {Data}");
|
|
|
|
_receivedMessageNotMatchedToAnyListener = LoggerMessage.Define<int, string, string>(
|
|
LogLevel.Warning,
|
|
new EventId(2029, "ReceivedMessageNotMatchedToAnyListener"),
|
|
"[Sckt {SocketId}] received message not matched to any listener. ListenId: {ListenId}, current listeners: [{ListenIds}]");
|
|
|
|
_failedToParse = LoggerMessage.Define<int, string>(
|
|
LogLevel.Warning,
|
|
new EventId(2030, "FailedToParse"),
|
|
"[Sckt {SocketId}] failed to parse data: {Error}");
|
|
|
|
_sendingByteData = LoggerMessage.Define<int, int, int>(
|
|
LogLevel.Trace,
|
|
new EventId(2031, "SendingByteData"),
|
|
"[Sckt {SocketId}] [Req {RequestId}] sending byte message of length: {Length}");
|
|
|
|
_processorMatched = LoggerMessage.Define<int, string, string>(
|
|
LogLevel.Trace,
|
|
new EventId(2032, "ProcessorMatched"),
|
|
"[Sckt {SocketId}] listener '{ListenId}' matched to message with listener identifier {ListenerId}");
|
|
|
|
}
|
|
|
|
public static void ActivityPaused(this ILogger logger, int socketId, bool paused)
|
|
{
|
|
_activityPaused(logger, socketId, paused, null);
|
|
}
|
|
|
|
public static void SocketStatusChanged(this ILogger logger, int socketId, SocketStatus oldStatus, SocketStatus newStatus)
|
|
{
|
|
_socketStatusChanged(logger, socketId, oldStatus, newStatus, null);
|
|
}
|
|
|
|
public static void FailedReconnectProcessing(this ILogger logger, int socketId, string? error)
|
|
{
|
|
_failedReconnectProcessing(logger, socketId, error, null);
|
|
}
|
|
|
|
public static void UnknownExceptionWhileProcessingReconnection(this ILogger logger, int socketId, Exception e)
|
|
{
|
|
_unknownExceptionWhileProcessingReconnection(logger, socketId, e);
|
|
}
|
|
|
|
public static void WebSocketErrorCodeAndDetails(this ILogger logger, int socketId, WebSocketError error, string? details, Exception e)
|
|
{
|
|
_webSocketErrorCodeAndDetails(logger, socketId, error, details, e);
|
|
}
|
|
|
|
public static void WebSocketError(this ILogger logger, int socketId, string? errorMessage, Exception e)
|
|
{
|
|
_webSocketError(logger, socketId, errorMessage, e);
|
|
}
|
|
|
|
public static void ReceivedData(this ILogger logger, int socketId, string originalData)
|
|
{
|
|
_receivedData(logger, socketId, originalData, null);
|
|
}
|
|
|
|
public static void FailedToParse(this ILogger logger, int socketId, string error)
|
|
{
|
|
_failedToParse(logger, socketId, error, null);
|
|
}
|
|
|
|
public static void FailedToEvaluateMessage(this ILogger logger, int socketId, string originalData)
|
|
{
|
|
_failedToEvaluateMessage(logger, socketId, originalData, null);
|
|
}
|
|
public static void ErrorProcessingMessage(this ILogger logger, int socketId, Exception e)
|
|
{
|
|
_errorProcessingMessage(logger, socketId, e);
|
|
}
|
|
public static void ProcessorMatched(this ILogger logger, int socketId, string listener, string listenerId)
|
|
{
|
|
_processorMatched(logger, socketId, listener, listenerId, null);
|
|
}
|
|
public static void ReceivedMessageNotRecognized(this ILogger logger, int socketId, int id)
|
|
{
|
|
_receivedMessageNotRecognized(logger, socketId, id, null);
|
|
}
|
|
public static void FailedToDeserializeMessage(this ILogger logger, int socketId, string? errorMessage, Exception? ex)
|
|
{
|
|
_failedToDeserializeMessage(logger, socketId, errorMessage, ex);
|
|
}
|
|
public static void UserMessageProcessingFailed(this ILogger logger, int socketId, string errorMessage, Exception e)
|
|
{
|
|
_userMessageProcessingFailed(logger, socketId, errorMessage, e);
|
|
}
|
|
public static void MessageProcessed(this ILogger logger, int socketId, long processingTime, long parsingTime)
|
|
{
|
|
_messageProcessed(logger, socketId, processingTime, parsingTime, null);
|
|
}
|
|
public static void ClosingSubscription(this ILogger logger, int socketId, int subscriptionId)
|
|
{
|
|
_closingSubscription(logger, socketId, subscriptionId, null);
|
|
}
|
|
public static void NotUnsubscribingSubscriptionBecauseDuplicateRunning(this ILogger logger, int socketId)
|
|
{
|
|
_notUnsubscribingSubscriptionBecauseDuplicateRunning(logger, socketId, null);
|
|
}
|
|
public static void AlreadyClosing(this ILogger logger, int socketId)
|
|
{
|
|
_alreadyClosing(logger, socketId, null);
|
|
}
|
|
public static void ClosingNoMoreSubscriptions(this ILogger logger, int socketId)
|
|
{
|
|
_closingNoMoreSubscriptions(logger, socketId, null);
|
|
}
|
|
public static void AddingNewSubscription(this ILogger logger, int socketId, int subscriptionId, int userSubscriptionCount)
|
|
{
|
|
_addingNewSubscription(logger, socketId, subscriptionId, userSubscriptionCount, null);
|
|
}
|
|
|
|
public static void NothingToResubscribeCloseConnection(this ILogger logger, int socketId)
|
|
{
|
|
_nothingToResubscribeCloseConnection(logger, socketId, null);
|
|
}
|
|
public static void FailedAuthenticationDisconnectAndRecoonect(this ILogger logger, int socketId)
|
|
{
|
|
_failedAuthenticationDisconnectAndReconnect(logger, socketId, null);
|
|
}
|
|
public static void AuthenticationSucceeded(this ILogger logger, int socketId)
|
|
{
|
|
_authenticationSucceeded(logger, socketId, null);
|
|
}
|
|
public static void FailedRequestRevitalization(this ILogger logger, int socketId, string? errorMessage)
|
|
{
|
|
_failedRequestRevitalization(logger, socketId, errorMessage, null);
|
|
}
|
|
public static void AllSubscriptionResubscribed(this ILogger logger, int socketId)
|
|
{
|
|
_allSubscriptionResubscribed(logger, socketId, null);
|
|
}
|
|
public static void SubscriptionUnsubscribed(this ILogger logger, int socketId, int subscriptionId)
|
|
{
|
|
_subscriptionUnsubscribed(logger, socketId, subscriptionId, null);
|
|
}
|
|
public static void SendingPeriodic(this ILogger logger, int socketId, string identifier)
|
|
{
|
|
_sendingPeriodic(logger, socketId, identifier, null);
|
|
}
|
|
public static void PeriodicSendFailed(this ILogger logger, int socketId, string identifier, string errorMessage, Exception e)
|
|
{
|
|
_periodicSendFailed(logger, socketId, identifier, errorMessage, e);
|
|
}
|
|
|
|
public static void SendingData(this ILogger logger, int socketId, int requestId, string data)
|
|
{
|
|
_sendingData(logger, socketId, requestId, data, null);
|
|
}
|
|
|
|
public static void ReceivedMessageNotMatchedToAnyListener(this ILogger logger, int socketId, string listenId, string listenIds)
|
|
{
|
|
_receivedMessageNotMatchedToAnyListener(logger, socketId, listenId, listenIds, null);
|
|
}
|
|
|
|
public static void SendingByteData(this ILogger logger, int socketId, int requestId, int length)
|
|
{
|
|
_sendingByteData(logger, socketId, requestId, length, null);
|
|
}
|
|
}
|
|
} |