From 62398519252d92daedaa5a82f6165f1d10e86813 Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Sun, 29 Oct 2023 17:51:02 +0100 Subject: [PATCH] Added Setup-extension-method WriteToColoredConsole (#5389) --- src/NLog/SetupLoadConfigurationExtensions.cs | 62 +++++++++++++++++++ .../Targets/ColoredConsoleTargetTests.cs | 48 ++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/src/NLog/SetupLoadConfigurationExtensions.cs b/src/NLog/SetupLoadConfigurationExtensions.cs index afa0ead0cc..3d98423d34 100644 --- a/src/NLog/SetupLoadConfigurationExtensions.cs +++ b/src/NLog/SetupLoadConfigurationExtensions.cs @@ -468,6 +468,68 @@ public static ISetupConfigurationTargetBuilder WriteToConsole(this ISetupConfigu return configBuilder.WriteTo(consoleTarget); } + /// + /// Write to and color log-messages based on + /// + /// Fluent interface parameter. + /// Override the default Layout for output + /// Highlight only the Level-part + /// Override the default Encoding for output (Ex. UTF8) + /// Write to stderr instead of standard output (stdout) + /// Skip overhead from writing to console, when not available (Ex. running as Windows Service) + /// Enables output using ANSI Color Codes (Windows console does not support this by default) + public static ISetupConfigurationTargetBuilder WriteToColoredConsole(this ISetupConfigurationTargetBuilder configBuilder, Layout layout = null, bool highlightWordLevel = false, System.Text.Encoding encoding = null, bool stderr = false, bool detectConsoleAvailable = false, bool enableAnsiOutput = false) + { + var consoleTarget = new ColoredConsoleTarget(); + if (layout != null) + consoleTarget.Layout = layout; + if (encoding != null) + consoleTarget.Encoding = encoding; + consoleTarget.StdErr = stderr; + consoleTarget.DetectConsoleAvailable = detectConsoleAvailable; + consoleTarget.EnableAnsiOutput = enableAnsiOutput; + consoleTarget.UseDefaultRowHighlightingRules = false; + + if (enableAnsiOutput) + { + if (highlightWordLevel) + { + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Fatal", ConsoleOutputColor.DarkRed, ConsoleOutputColor.NoChange) { Condition = "level == LogLevel.Fatal", IgnoreCase = true, WholeWords = true }); + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Error", ConsoleOutputColor.DarkRed, ConsoleOutputColor.NoChange) { Condition = "level == LogLevel.Error", IgnoreCase = true, WholeWords = true }); + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Warn", ConsoleOutputColor.DarkYellow, ConsoleOutputColor.NoChange) { Condition = "level == LogLevel.Warn", IgnoreCase = true, WholeWords = true }); + } + else + { + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Fatal", ConsoleOutputColor.DarkRed, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Error", ConsoleOutputColor.DarkRed, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Warn", ConsoleOutputColor.DarkYellow, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Info", ConsoleOutputColor.NoChange, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Debug", ConsoleOutputColor.NoChange, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Trace", ConsoleOutputColor.NoChange, ConsoleOutputColor.NoChange)); + } + } + else + { + if (highlightWordLevel) + { + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Fatal", ConsoleOutputColor.White, ConsoleOutputColor.DarkRed) { Condition = "level == LogLevel.Fatal", IgnoreCase = true, WholeWords = true }); + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Error", ConsoleOutputColor.Red, ConsoleOutputColor.NoChange) { Condition = "level == LogLevel.Error", IgnoreCase = true, WholeWords = true }); + consoleTarget.WordHighlightingRules.Add(new ConsoleWordHighlightingRule("Warn", ConsoleOutputColor.DarkYellow, ConsoleOutputColor.NoChange) { Condition = "level == LogLevel.Warn", IgnoreCase = true, WholeWords = true }); + } + else + { + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Fatal", ConsoleOutputColor.White, ConsoleOutputColor.DarkRed)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Error", ConsoleOutputColor.Red, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Warn", ConsoleOutputColor.DarkYellow, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Info", ConsoleOutputColor.White, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Debug", ConsoleOutputColor.Gray, ConsoleOutputColor.NoChange)); + consoleTarget.RowHighlightingRules.Add(new ConsoleRowHighlightingRule("level == LogLevel.Trace", ConsoleOutputColor.Gray, ConsoleOutputColor.NoChange)); + } + } + + return configBuilder.WriteTo(consoleTarget); + } + /// /// Write to /// diff --git a/tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs b/tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs index ba0377ad97..f3b943f4da 100644 --- a/tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs +++ b/tests/NLog.UnitTests/Targets/ColoredConsoleTargetTests.cs @@ -174,6 +174,54 @@ public void ColoredConsoleAnsi_OverlappingWordHighlight_VerificationTest() new string[] { "The \x1B[31mbig \x1B[35mw\x1B[32ma\x1B[35mrn\x1B[31ming\x1B[0m mess\x1B[32ma\x1B[0mge\x1B[0m" }); } + [Fact] + public void SetupBuilder_WriteToColoredConsole() + { + var logFactory = new LogFactory().Setup().LoadConfiguration(c => + { + c.ForLogger().FilterMinLevel(LogLevel.Error).WriteToColoredConsole("${level}|${message}", stderr: true, enableAnsiOutput: true); + }).LogFactory; + + var consoleErrorWriter = new StringWriter(); + TextWriter oldConsoleErrorWriter = Console.Error; + Console.SetError(consoleErrorWriter); + + try + { + logFactory.GetCurrentClassLogger().Error("Abort"); + logFactory.GetCurrentClassLogger().Info("Continue"); + Assert.Equal($"\u001b[31mError|Abort\u001b[0m{System.Environment.NewLine}", consoleErrorWriter.ToString()); + } + finally + { + Console.SetError(oldConsoleErrorWriter); + } + } + + [Fact] + public void SetupBuilder_WriteToColoredConsole_HighlightWord() + { + var logFactory = new LogFactory().Setup().LoadConfiguration(c => + { + c.ForLogger().FilterMinLevel(LogLevel.Error).WriteToColoredConsole("${level}|${message}", stderr: true, enableAnsiOutput: true, highlightWordLevel: true); + }).LogFactory; + + var consoleErrorWriter = new StringWriter(); + TextWriter oldConsoleErrorWriter = Console.Error; + Console.SetError(consoleErrorWriter); + + try + { + logFactory.GetCurrentClassLogger().Error("Abort"); + logFactory.GetCurrentClassLogger().Info("Continue"); + Assert.Equal($"\u001b[31mError\u001b[0m|Abort\u001b[0m{System.Environment.NewLine}", consoleErrorWriter.ToString()); + } + finally + { + Console.SetError(oldConsoleErrorWriter); + } + } + [Fact] public void ColoredConsoleAnsi_RepeatedWordHighlight_VerificationTest() {