From cf75077bc41ac3f6112edf1c9182913c7a67d61b Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 23 Feb 2026 00:43:27 -0500 Subject: [PATCH] feat: add CLI flags for debug/trace modes, file logging, syslog, color, timestamps --- src/NATS.Server.Host/Program.cs | 89 ++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 7 deletions(-) diff --git a/src/NATS.Server.Host/Program.cs b/src/NATS.Server.Host/Program.cs index 4dde566..f0d614c 100644 --- a/src/NATS.Server.Host/Program.cs +++ b/src/NATS.Server.Host/Program.cs @@ -1,15 +1,10 @@ using NATS.Server; using Serilog; - -Log.Logger = new LoggerConfiguration() - .MinimumLevel.Debug() - .Enrich.FromLogContext() - .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}") - .CreateLogger(); +using Serilog.Sinks.SystemConsole.Themes; var options = new NatsOptions(); -// Simple CLI argument parsing +// Parse ALL CLI flags into NatsOptions first for (int i = 0; i < args.Length; i++) { switch (args[i]) @@ -55,9 +50,89 @@ for (int i = 0; i < args.Length; i++) case "--tlsverify": options.TlsVerify = true; break; + case "-D": + options.Debug = true; + break; + case "-V" or "-T": + options.Trace = true; + break; + case "-DV": + options.Debug = true; + options.Trace = true; + break; + case "--log_file" when i + 1 < args.Length: + options.LogFile = args[++i]; + break; + case "--log_size_limit" when i + 1 < args.Length: + options.LogSizeLimit = long.Parse(args[++i]); + break; + case "--log_max_files" when i + 1 < args.Length: + options.LogMaxFiles = int.Parse(args[++i]); + break; + case "--logtime" when i + 1 < args.Length: + options.Logtime = bool.Parse(args[++i]); + break; + case "--logtime_utc": + options.LogtimeUTC = true; + break; + case "--syslog": + options.Syslog = true; + break; + case "--remote_syslog" when i + 1 < args.Length: + options.RemoteSyslog = args[++i]; + break; } } +// Build Serilog configuration from options +var logConfig = new LoggerConfiguration() + .Enrich.FromLogContext(); + +// Set minimum level based on flags +if (options.Trace) + logConfig.MinimumLevel.Verbose(); +else if (options.Debug) + logConfig.MinimumLevel.Debug(); +else + logConfig.MinimumLevel.Information(); + +// Build output template +var timestampFormat = options.LogtimeUTC + ? "{Timestamp:yyyy/MM/dd HH:mm:ss.ffffff} " + : "{Timestamp:HH:mm:ss} "; +var template = options.Logtime + ? $"[{timestampFormat}{{Level:u3}}] {{Message:lj}}{{NewLine}}{{Exception}}" + : "[{Level:u3}] {Message:lj}{NewLine}{Exception}"; + +// Console sink with color auto-detection +if (!Console.IsOutputRedirected) + logConfig.WriteTo.Console(outputTemplate: template, theme: AnsiConsoleTheme.Code); +else + logConfig.WriteTo.Console(outputTemplate: template); + +// File sink with rotation +if (!string.IsNullOrEmpty(options.LogFile)) +{ + logConfig.WriteTo.File( + options.LogFile, + fileSizeLimitBytes: options.LogSizeLimit > 0 ? options.LogSizeLimit : null, + retainedFileCountLimit: options.LogMaxFiles > 0 ? options.LogMaxFiles : null, + rollOnFileSizeLimit: options.LogSizeLimit > 0, + outputTemplate: template); +} + +// Syslog sink +if (!string.IsNullOrEmpty(options.RemoteSyslog)) +{ + logConfig.WriteTo.UdpSyslog(options.RemoteSyslog); +} +else if (options.Syslog) +{ + logConfig.WriteTo.LocalSyslog("nats-server"); +} + +Log.Logger = logConfig.CreateLogger(); + using var loggerFactory = new Serilog.Extensions.Logging.SerilogLoggerFactory(Log.Logger); using var server = new NatsServer(options, loggerFactory);