From 2dbd5be9245bb9c43f89a95d48c7f524021b5a52 Mon Sep 17 00:00:00 2001
From: Jonnern <10881387+Jonnern@users.noreply.github.com>
Date: Tue, 16 Apr 2024 14:37:00 +0200
Subject: [PATCH] Get the state of ApiClient, SocketConnection, and
Subscription as a record (#195)
---
.../Clients/BaseSocketClient.cs | 14 +++
CryptoExchange.Net/Clients/SocketApiClient.cs | 92 ++++++++++++++-----
.../Sockets/SocketConnection.cs | 40 ++++++++
CryptoExchange.Net/Sockets/Subscription.cs | 23 +++++
4 files changed, 145 insertions(+), 24 deletions(-)
diff --git a/CryptoExchange.Net/Clients/BaseSocketClient.cs b/CryptoExchange.Net/Clients/BaseSocketClient.cs
index c913a33..01258b8 100644
--- a/CryptoExchange.Net/Clients/BaseSocketClient.cs
+++ b/CryptoExchange.Net/Clients/BaseSocketClient.cs
@@ -108,5 +108,19 @@ namespace CryptoExchange.Net.Clients
}
return result.ToString();
}
+
+ ///
+ /// Returns the state of all socket api clients
+ ///
+ ///
+ public List GetSocketApiClientStates()
+ {
+ var result = new List();
+ foreach (var client in ApiClients.OfType())
+ {
+ result.Add(client.GetState());
+ }
+ return result;
+ }
}
}
diff --git a/CryptoExchange.Net/Clients/SocketApiClient.cs b/CryptoExchange.Net/Clients/SocketApiClient.cs
index c0a68bc..3121e3d 100644
--- a/CryptoExchange.Net/Clients/SocketApiClient.cs
+++ b/CryptoExchange.Net/Clients/SocketApiClient.cs
@@ -622,32 +622,76 @@ namespace CryptoExchange.Net.Clients
///
public string GetSubscriptionsState(bool includeSubDetails = true)
{
- var sb = new StringBuilder();
- sb.AppendLine($"{GetType().Name}");
- sb.AppendLine($" Connections: {socketConnections.Count}");
- sb.AppendLine($" Subscriptions: {CurrentSubscriptions}");
- sb.AppendLine($" Download speed: {IncomingKbps} kbps");
- foreach (var connection in socketConnections)
+ return GetState(includeSubDetails).ToString();
+ }
+
+ ///
+ /// Gets the state of the client
+ ///
+ /// True to get details for each subscription
+ ///
+ public SocketApiClientState GetState(bool includeSubDetails = true)
+ {
+ var connectionStates = new List();
+ foreach (var socketIdAndConnection in socketConnections)
{
- sb.AppendLine($" Id: {connection.Key}");
- sb.AppendLine($" Address: {connection.Value.ConnectionUri}");
- sb.AppendLine($" Subscriptions: {connection.Value.UserSubscriptionCount}");
- sb.AppendLine($" Status: {connection.Value.Status}");
- sb.AppendLine($" Authenticated: {connection.Value.Authenticated}");
- sb.AppendLine($" Download speed: {connection.Value.IncomingKbps} kbps");
- sb.AppendLine($" Subscriptions:");
- if (includeSubDetails)
- {
- foreach (var subscription in connection.Value.Subscriptions)
- {
- sb.AppendLine($" Id: {subscription.Id}");
- sb.AppendLine($" Confirmed: {subscription.Confirmed}");
- sb.AppendLine($" Invocations: {subscription.TotalInvocations}");
- sb.AppendLine($" Identifiers: [{string.Join(", ", subscription.ListenerIdentifiers)}]");
- }
- }
+ SocketConnection connection = socketIdAndConnection.Value;
+ SocketConnection.SocketConnectionState connectionState = connection.GetState(includeSubDetails);
+ connectionStates.Add(connectionState);
+ }
+
+ return new SocketApiClientState(socketConnections.Count, CurrentSubscriptions, IncomingKbps, connectionStates);
+ }
+
+ ///
+ /// Get the current state of the client
+ ///
+ /// Number of sockets for this client
+ /// Total number of subscriptions
+ /// Total download speed
+ /// State of each socket connection
+ public record SocketApiClientState(
+ int Connections,
+ int Subscriptions,
+ double DownloadSpeed,
+ List ConnectionStates)
+ {
+ ///
+ /// Print the state of the client
+ ///
+ ///
+ ///
+ protected virtual bool PrintMembers(StringBuilder sb)
+ {
+ sb.AppendLine();
+ sb.AppendLine($"\tTotal connections: {Connections}");
+ sb.AppendLine($"\tTotal subscriptions: {Subscriptions}");
+ sb.AppendLine($"\tDownload speed: {DownloadSpeed} kbps");
+ sb.AppendLine($"\tConnections:");
+ ConnectionStates.ForEach(cs =>
+ {
+ sb.AppendLine($"\t\tId: {cs.Id}");
+ sb.AppendLine($"\t\tAddress: {cs.Address}");
+ sb.AppendLine($"\t\tTotal subscriptions: {cs.Subscriptions}");
+ sb.AppendLine($"\t\tStatus: {cs.Status}");
+ sb.AppendLine($"\t\tAuthenticated: {cs.Authenticated}");
+ sb.AppendLine($"\t\tDownload speed: {cs.DownloadSpeed} kbps");
+ sb.AppendLine($"\t\tPending queries: {cs.PendingQueries}");
+ if (cs.SubscriptionStates?.Count > 0)
+ {
+ sb.AppendLine($"\t\tSubscriptions:");
+ cs.SubscriptionStates.ForEach(subState =>
+ {
+ sb.AppendLine($"\t\t\tId: {subState.Id}");
+ sb.AppendLine($"\t\t\tConfirmed: {subState.Confirmed}");
+ sb.AppendLine($"\t\t\tInvocations: {subState.Invocations}");
+ sb.AppendLine($"\t\t\tIdentifiers: [{string.Join(",", subState.Identifiers)}]");
+ });
+ }
+ });
+
+ return true;
}
- return sb.ToString();
}
///
diff --git a/CryptoExchange.Net/Sockets/SocketConnection.cs b/CryptoExchange.Net/Sockets/SocketConnection.cs
index 637b503..6389ad4 100644
--- a/CryptoExchange.Net/Sockets/SocketConnection.cs
+++ b/CryptoExchange.Net/Sockets/SocketConnection.cs
@@ -19,6 +19,28 @@ namespace CryptoExchange.Net.Sockets
///
public class SocketConnection
{
+ ///
+ /// State of a the connection
+ ///
+ /// The id of the socket connection
+ /// The connection URI
+ /// Number of subscriptions on this socket
+ /// Socket status
+ /// If the connection is authenticated
+ /// Download speed over this socket
+ /// Number of non-completed queries
+ /// State for each subscription on this socket
+ public record SocketConnectionState(
+ int Id,
+ string Address,
+ int Subscriptions,
+ SocketStatus Status,
+ bool Authenticated,
+ double DownloadSpeed,
+ int PendingQueries,
+ List SubscriptionStates
+ );
+
///
/// Connection lost event
///
@@ -620,6 +642,24 @@ namespace CryptoExchange.Net.Sockets
return _listeners.OfType().SingleOrDefault(s => s.Id == id);
}
+ ///
+ /// Get the state of the connection
+ ///
+ ///
+ public SocketConnectionState GetState(bool includeSubDetails)
+ {
+ return new SocketConnectionState(
+ SocketId,
+ ConnectionUri.AbsoluteUri,
+ UserSubscriptionCount,
+ Status,
+ Authenticated,
+ IncomingKbps,
+ PendingQueries: _listeners.OfType().Count(x => !x.Completed),
+ includeSubDetails ? Subscriptions.Select(sub => sub.GetState()).ToList() : new List()
+ );
+ }
+
///
/// Send a query request and wait for an answer
///
diff --git a/CryptoExchange.Net/Sockets/Subscription.cs b/CryptoExchange.Net/Sockets/Subscription.cs
index 9fd1f21..ac5141c 100644
--- a/CryptoExchange.Net/Sockets/Subscription.cs
+++ b/CryptoExchange.Net/Sockets/Subscription.cs
@@ -156,6 +156,29 @@ namespace CryptoExchange.Net.Sockets
{
Exception?.Invoke(e);
}
+
+ ///
+ /// State of this subscription
+ ///
+ /// The id of the subscription
+ /// True when the subscription query is handled (either accepted or rejected)
+ /// Number of times this subscription got a message
+ /// Identifiers the subscription is listening to
+ public record SubscriptionState(
+ int Id,
+ bool Confirmed,
+ int Invocations,
+ HashSet Identifiers
+ );
+
+ ///
+ /// Get the state of this subscription
+ ///
+ ///
+ public SubscriptionState GetState()
+ {
+ return new SubscriptionState(Id, Confirmed, TotalInvocations, ListenerIdentifiers);
+ }
}
///