feat: add stale connection stats tracking and varz exposure
This commit is contained in:
@@ -157,6 +157,12 @@ public sealed class Varz
|
|||||||
[JsonPropertyName("slow_consumer_stats")]
|
[JsonPropertyName("slow_consumer_stats")]
|
||||||
public SlowConsumersStats SlowConsumerStats { get; set; } = new();
|
public SlowConsumersStats SlowConsumerStats { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonPropertyName("stale_connections")]
|
||||||
|
public long StaleConnections { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("stale_connection_stats")]
|
||||||
|
public StaleConnectionStats StaleConnectionStatsDetail { get; set; } = new();
|
||||||
|
|
||||||
[JsonPropertyName("subscriptions")]
|
[JsonPropertyName("subscriptions")]
|
||||||
public uint Subscriptions { get; set; }
|
public uint Subscriptions { get; set; }
|
||||||
|
|
||||||
@@ -219,6 +225,25 @@ public sealed class SlowConsumersStats
|
|||||||
public ulong Leafs { get; set; }
|
public ulong Leafs { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Statistics about stale connections by connection type.
|
||||||
|
/// Corresponds to Go server/monitor.go StaleConnectionStats struct.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class StaleConnectionStats
|
||||||
|
{
|
||||||
|
[JsonPropertyName("clients")]
|
||||||
|
public ulong Clients { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("routes")]
|
||||||
|
public ulong Routes { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("gateways")]
|
||||||
|
public ulong Gateways { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName("leafs")]
|
||||||
|
public ulong Leafs { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cluster configuration monitoring information.
|
/// Cluster configuration monitoring information.
|
||||||
/// Corresponds to Go server/monitor.go ClusterOptsVarz struct.
|
/// Corresponds to Go server/monitor.go ClusterOptsVarz struct.
|
||||||
|
|||||||
@@ -91,6 +91,14 @@ public sealed class VarzHandler : IDisposable
|
|||||||
Gateways = (ulong)Interlocked.Read(ref stats.SlowConsumerGateways),
|
Gateways = (ulong)Interlocked.Read(ref stats.SlowConsumerGateways),
|
||||||
Leafs = (ulong)Interlocked.Read(ref stats.SlowConsumerLeafs),
|
Leafs = (ulong)Interlocked.Read(ref stats.SlowConsumerLeafs),
|
||||||
},
|
},
|
||||||
|
StaleConnections = Interlocked.Read(ref stats.StaleConnections),
|
||||||
|
StaleConnectionStatsDetail = new StaleConnectionStats
|
||||||
|
{
|
||||||
|
Clients = (ulong)Interlocked.Read(ref stats.StaleConnectionClients),
|
||||||
|
Routes = (ulong)Interlocked.Read(ref stats.StaleConnectionRoutes),
|
||||||
|
Gateways = (ulong)Interlocked.Read(ref stats.StaleConnectionGateways),
|
||||||
|
Leafs = (ulong)Interlocked.Read(ref stats.StaleConnectionLeafs),
|
||||||
|
},
|
||||||
Subscriptions = _server.SubList.Count,
|
Subscriptions = _server.SubList.Count,
|
||||||
ConfigLoadTime = _server.StartTime,
|
ConfigLoadTime = _server.StartTime,
|
||||||
HttpReqStats = stats.HttpReqStats.ToDictionary(kv => kv.Key, kv => (ulong)kv.Value),
|
HttpReqStats = stats.HttpReqStats.ToDictionary(kv => kv.Key, kv => (ulong)kv.Value),
|
||||||
|
|||||||
@@ -682,6 +682,12 @@ public sealed class NatsClient : IDisposable
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reason == ClientClosedReason.StaleConnection)
|
||||||
|
{
|
||||||
|
Interlocked.Increment(ref _serverStats.StaleConnections);
|
||||||
|
Interlocked.Increment(ref _serverStats.StaleConnectionClients);
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogDebug("Client {ClientId} connection closed: {CloseReason}", Id, reason);
|
_logger.LogDebug("Client {ClientId} connection closed: {CloseReason}", Id, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,5 +16,9 @@ public sealed class ServerStats
|
|||||||
public long SlowConsumerRoutes;
|
public long SlowConsumerRoutes;
|
||||||
public long SlowConsumerLeafs;
|
public long SlowConsumerLeafs;
|
||||||
public long SlowConsumerGateways;
|
public long SlowConsumerGateways;
|
||||||
|
public long StaleConnectionClients;
|
||||||
|
public long StaleConnectionRoutes;
|
||||||
|
public long StaleConnectionLeafs;
|
||||||
|
public long StaleConnectionGateways;
|
||||||
public readonly ConcurrentDictionary<string, long> HttpReqStats = new();
|
public readonly ConcurrentDictionary<string, long> HttpReqStats = new();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,27 @@ public class ServerStatsTests : IAsyncLifetime
|
|||||||
client.StartTime.ShouldNotBe(default);
|
client.StartTime.ShouldNotBe(default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StaleConnection_stats_incremented_on_mark_closed()
|
||||||
|
{
|
||||||
|
var stats = new ServerStats();
|
||||||
|
stats.StaleConnectionClients.ShouldBe(0);
|
||||||
|
|
||||||
|
Interlocked.Increment(ref stats.StaleConnectionClients);
|
||||||
|
stats.StaleConnectionClients.ShouldBe(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void StaleConnection_stats_all_fields_default_to_zero()
|
||||||
|
{
|
||||||
|
var stats = new ServerStats();
|
||||||
|
stats.StaleConnections.ShouldBe(0);
|
||||||
|
stats.StaleConnectionClients.ShouldBe(0);
|
||||||
|
stats.StaleConnectionRoutes.ShouldBe(0);
|
||||||
|
stats.StaleConnectionLeafs.ShouldBe(0);
|
||||||
|
stats.StaleConnectionGateways.ShouldBe(0);
|
||||||
|
}
|
||||||
|
|
||||||
private static int GetFreePort()
|
private static int GetFreePort()
|
||||||
{
|
{
|
||||||
using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
using var sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
|
|||||||
Reference in New Issue
Block a user