一行中的多种颜色

本文关键字:颜色 一行 | 更新日期: 2023-09-27 18:18:44

我想在控制台上使用log4net进行一些信息记录,并在每行中使用多种颜色。这是我当前的简化配置:

...
<appender name="ConsoleDebug" type="log4net.Appender.ColoredConsoleAppender">
  <filter type="log4net.Filter.LevelRangeFilter">
    <levelMin value="INFO" />
  </filter>
  <mapping>
    <level value="INFO" />
    <foreColor value="Green, HighIntensity" />
  </mapping>
  ...
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%logger{1} %message%newline" />
  </layout>
</appender>
...

这会将我所有的日志记录消息输出为绿色文本。是否可以将%logger输出为白色文本,%message输出为绿色文本?

一行中的多种颜色

我想

了一会儿ANSI转义码可以工作,但显然在最新的操作系统中不再可能。我看到的任何其他解决方案都会让您做一些不平凡的工作。

要处理消息布局中的颜色切换,您可以执行以下操作:

  • 编写一个自定义的 PatternLayoutConverter,让你声明你想要的颜色。通过 Console.ForefrontColor 和 Console.BackgroundColor 属性更改颜色。
  • 编写一个自定义的 PatternLayout,将上面的布局转换器添加到其转换器列表中。
  • 编写
  • 一个自定义追加器,该附加器在编写之前不处理模式布局。而是以块的形式编写布局,处理每个块,然后将其写入输出。这将保留布局转换器的颜色切换功能。

编写大量代码才能使自定义颜色"正确完成"(即您的布局独立于它正在使用的追加器(。


如果您认为只有控制台追加器使用您的布局,则有一种方法可以作弊:

  • 创建从控制台追加器继承的自定义追加程序,并重写Append方法。
  • Append方法中,沿着标记拆分,告诉您想要什么颜色,并逐块处理它们以获得所需的颜色交换。

这可能是一个快速而肮脏的解决方案,但布局只能使用此追加器使用。如果您需要切换追加器,则必须再次覆盖它。下面是此类追加器的示例:

public class ConsoleAppenderWithColorSwitching : ConsoleAppender
{
    // forfeits the auto switch from Console.Error to Console.Out 
    // of the original appender :/
    protected override void Append(LoggingEvent loggingEvent)
    {
        var regex = new Regex(@"('|'w+'|)");
        var renderedLayout = base.RenderLoggingEvent(loggingEvent);
        var chunks = regex.Split(renderedLayout);
        foreach (var chunk in chunks)
        {
            if (chunk.StartsWith("|") && chunk.EndsWith("|"))
            {
                var consoleColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), chunk.Substring(1, chunk.Length - 2));
                Console.ForegroundColor = consoleColor;
            }
            else
            {
                Console.Write(chunk);
            }
        }
    }
}

这允许您使用以下语法更改布局中的前景色:|Green| %logger{1} |Red|%message%newline 。这确实是一个概念证明,但请随意尝试它......


总而言之,我不建议你走这条路。这绝对是可能的,但这可能比您投资动态颜色开关的工作要多。

一种更简单、更一致的方法,是对@samy答案的轻微修改:

public class ConsoleAppenderWithColorSwitching : ConsoleAppender
{
    // forfeits the auto switch from Console.Error to Console.Out
    // of the original appender :/
    protected override void Append(LoggingEvent loggingEvent)
    {
        string renderedLayout = base.RenderLoggingEvent(loggingEvent);
        string ansi = renderedLayout.Replace(@"'e", "'u001b");
        Console.Write(ansi);
    }
}

有了这个,您可以简单地使用表示 ANSI 代码的'e语法,例如:

<conversionPattern value="'e[31m%date'e[0m [%thread] %-5level %logger [%property{NDC}] - %message%newline" />

将日期设置为红色,其余日期为终端默认值。