feat(monitoring+events): add connz filtering, event payloads, and message trace context (E12+E13+E14)
- Add ConnzHandler with sorting, filtering, pagination, CID lookup, and closed connection ring buffer - Add full Go events.go parity types (ConnectEventMsg, DisconnectEventMsg, ServerStatsMsg, etc.) - Add MessageTraceContext for per-message trace propagation with header parsing - 74 new tests (17 ConnzFilter + 16 EventPayload + 41 MessageTraceContext)
This commit is contained in:
@@ -218,6 +218,18 @@ public sealed class ConnzOptions
|
||||
|
||||
public string MqttClient { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// When non-zero, returns only the connection with this CID.
|
||||
/// Go reference: monitor.go ConnzOptions.CID.
|
||||
/// </summary>
|
||||
public ulong Cid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to include authorized user info.
|
||||
/// Go reference: monitor.go ConnzOptions.Username.
|
||||
/// </summary>
|
||||
public bool Auth { get; set; }
|
||||
|
||||
public int Offset { get; set; }
|
||||
|
||||
public int Limit { get; set; } = 1024;
|
||||
|
||||
@@ -16,6 +16,13 @@ public sealed class ConnzHandler(NatsServer server)
|
||||
|
||||
var connInfos = new List<ConnInfo>();
|
||||
|
||||
// If a specific CID is requested, search for that single connection
|
||||
// Go reference: monitor.go Connz() — CID fast path
|
||||
if (opts.Cid > 0)
|
||||
{
|
||||
return HandleSingleCid(opts, now);
|
||||
}
|
||||
|
||||
// Collect open connections
|
||||
if (opts.State is ConnState.Open or ConnState.All)
|
||||
{
|
||||
@@ -23,7 +30,7 @@ public sealed class ConnzHandler(NatsServer server)
|
||||
connInfos.AddRange(clients.Select(c => BuildConnInfo(c, now, opts)));
|
||||
}
|
||||
|
||||
// Collect closed connections
|
||||
// Collect closed connections from the ring buffer
|
||||
if (opts.State is ConnState.Closed or ConnState.All)
|
||||
{
|
||||
connInfos.AddRange(server.GetClosedClients().Select(c => BuildClosedConnInfo(c, now, opts)));
|
||||
@@ -81,6 +88,59 @@ public sealed class ConnzHandler(NatsServer server)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles a request for a single connection by CID.
|
||||
/// Go reference: monitor.go Connz() — CID-specific path.
|
||||
/// </summary>
|
||||
private Connz HandleSingleCid(ConnzOptions opts, DateTime now)
|
||||
{
|
||||
// Search open connections first
|
||||
var client = server.GetClients().FirstOrDefault(c => c.Id == opts.Cid);
|
||||
if (client != null)
|
||||
{
|
||||
var info = BuildConnInfo(client, now, opts);
|
||||
return new Connz
|
||||
{
|
||||
Id = server.ServerId,
|
||||
Now = now,
|
||||
NumConns = 1,
|
||||
Total = 1,
|
||||
Offset = 0,
|
||||
Limit = 1,
|
||||
Conns = [info],
|
||||
};
|
||||
}
|
||||
|
||||
// Search closed connections ring buffer
|
||||
var closed = server.GetClosedClients().FirstOrDefault(c => c.Cid == opts.Cid);
|
||||
if (closed != null)
|
||||
{
|
||||
var info = BuildClosedConnInfo(closed, now, opts);
|
||||
return new Connz
|
||||
{
|
||||
Id = server.ServerId,
|
||||
Now = now,
|
||||
NumConns = 1,
|
||||
Total = 1,
|
||||
Offset = 0,
|
||||
Limit = 1,
|
||||
Conns = [info],
|
||||
};
|
||||
}
|
||||
|
||||
// Not found — return empty result
|
||||
return new Connz
|
||||
{
|
||||
Id = server.ServerId,
|
||||
Now = now,
|
||||
NumConns = 0,
|
||||
Total = 0,
|
||||
Offset = 0,
|
||||
Limit = 0,
|
||||
Conns = [],
|
||||
};
|
||||
}
|
||||
|
||||
private static ConnInfo BuildConnInfo(NatsClient client, DateTime now, ConnzOptions opts)
|
||||
{
|
||||
var info = new ConnInfo
|
||||
@@ -228,6 +288,12 @@ public sealed class ConnzHandler(NatsServer server)
|
||||
if (q.TryGetValue("limit", out var limit) && int.TryParse(limit, out var l))
|
||||
opts.Limit = l;
|
||||
|
||||
if (q.TryGetValue("cid", out var cid) && ulong.TryParse(cid, out var cidValue))
|
||||
opts.Cid = cidValue;
|
||||
|
||||
if (q.TryGetValue("auth", out var auth))
|
||||
opts.Auth = auth.ToString().ToLowerInvariant() is "1" or "true";
|
||||
|
||||
if (q.TryGetValue("mqtt_client", out var mqttClient))
|
||||
opts.MqttClient = mqttClient.ToString();
|
||||
|
||||
@@ -243,10 +309,13 @@ public sealed class ConnzHandler(NatsServer server)
|
||||
|
||||
private static bool MatchesSubjectFilter(ConnInfo info, string filterSubject)
|
||||
{
|
||||
if (info.Subs.Any(s => SubjectMatch.MatchLiteral(s, filterSubject)))
|
||||
// Go reference: monitor.go — matchLiteral(testSub, string(sub.subject))
|
||||
// The filter subject is the literal, the subscription subject is the pattern
|
||||
// (subscriptions may contain wildcards like orders.> that match the filter orders.new)
|
||||
if (info.Subs.Any(s => SubjectMatch.MatchLiteral(filterSubject, s)))
|
||||
return true;
|
||||
|
||||
return info.SubsDetail.Any(s => SubjectMatch.MatchLiteral(s.Subject, filterSubject));
|
||||
return info.SubsDetail.Any(s => SubjectMatch.MatchLiteral(filterSubject, s.Subject));
|
||||
}
|
||||
|
||||
private static string FormatRtt(TimeSpan rtt)
|
||||
|
||||
Reference in New Issue
Block a user