feat: add protocol tracing (<<- op arg) at LogLevel.Trace

This commit is contained in:
Joseph Doherty
2026-02-23 00:52:00 -05:00
parent 0347e8a28c
commit e9b6c7fdd3
2 changed files with 83 additions and 7 deletions

View File

@@ -1,5 +1,6 @@
using System.Buffers;
using System.Text;
using Microsoft.Extensions.Logging;
namespace NATS.Server.Protocol;
@@ -35,6 +36,7 @@ public sealed class NatsParser
{
private static readonly byte[] CrLfBytes = "\r\n"u8.ToArray();
private readonly int _maxPayload;
private readonly ILogger? _logger;
// State for split-packet payload reading
private bool _awaitingPayload;
@@ -44,9 +46,20 @@ public sealed class NatsParser
private int _pendingHeaderSize;
private CommandType _pendingType;
public NatsParser(int maxPayload = NatsProtocol.MaxPayloadSize)
public NatsParser(int maxPayload = NatsProtocol.MaxPayloadSize, ILogger? logger = null)
{
_maxPayload = maxPayload;
_logger = logger;
}
private void TraceInOp(string op, ReadOnlySpan<byte> arg = default)
{
if (_logger == null || !_logger.IsEnabled(LogLevel.Trace))
return;
if (arg.IsEmpty)
_logger.LogTrace("<<- {Op}", op);
else
_logger.LogTrace("<<- {Op} {Arg}", op, Encoding.ASCII.GetString(arg));
}
public bool TryParse(ref ReadOnlySequence<byte> buffer, out ParsedCommand command)
@@ -91,6 +104,7 @@ public sealed class NatsParser
{
command = ParsedCommand.Simple(CommandType.Ping);
buffer = buffer.Slice(reader.Position);
TraceInOp("PING");
return true;
}
@@ -98,6 +112,7 @@ public sealed class NatsParser
{
command = ParsedCommand.Simple(CommandType.Pong);
buffer = buffer.Slice(reader.Position);
TraceInOp("PONG");
return true;
}
@@ -121,6 +136,7 @@ public sealed class NatsParser
{
command = ParseSub(lineSpan);
buffer = buffer.Slice(reader.Position);
TraceInOp("SUB", lineSpan[4..]);
return true;
}
@@ -131,6 +147,7 @@ public sealed class NatsParser
{
command = ParseUnsub(lineSpan);
buffer = buffer.Slice(reader.Position);
TraceInOp("UNSUB", lineSpan[6..]);
return true;
}
@@ -141,6 +158,7 @@ public sealed class NatsParser
{
command = ParseConnect(lineSpan);
buffer = buffer.Slice(reader.Position);
TraceInOp("CONNECT");
return true;
}
@@ -151,6 +169,7 @@ public sealed class NatsParser
{
command = ParseInfo(lineSpan);
buffer = buffer.Slice(reader.Position);
TraceInOp("INFO");
return true;
}
@@ -159,11 +178,13 @@ public sealed class NatsParser
case (byte)'+': // +OK
command = ParsedCommand.Simple(CommandType.Ok);
buffer = buffer.Slice(reader.Position);
TraceInOp("+OK");
return true;
case (byte)'-': // -ERR
command = ParsedCommand.Simple(CommandType.Err);
buffer = buffer.Slice(reader.Position);
TraceInOp("-ERR");
return true;
}
@@ -215,6 +236,7 @@ public sealed class NatsParser
_pendingHeaderSize = -1;
_pendingType = CommandType.Pub;
TraceInOp("PUB", argsSpan);
return TryReadPayload(ref buffer, out command);
}
@@ -264,6 +286,7 @@ public sealed class NatsParser
_pendingHeaderSize = hdrSize;
_pendingType = CommandType.HPub;
TraceInOp("HPUB", argsSpan);
return TryReadPayload(ref buffer, out command);
}