log4net - 一行中有多种颜色

时间:2014-08-20 09:49:16

标签: c# log4net

我想在控制台上使用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输出为绿色吗?

2 个答案:

答案 0 :(得分:3)

我想了ANSI escape codes可能有效,但显然在最新的操作系统中已经不可能了。我看到的任何其他解决方案都会让你做一些非常重要的工作。

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

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

这是为了使自定义颜色“正确完成”而编写的大量代码(即您的布局独立于它正在使用的扩展器)。


如果您认为只有Console appender使用您的布局,有一种方法可以作弊:

  • 创建一个继承自Console appender的自定义appender并覆盖Append方法。
  • Append方法中,使用标记分割,告诉您所需的颜色,并按块处理它们以获得所需的颜色交换。

这可能是一个快速而肮脏的解决方案,但布局将仅适用于此appender。如果您需要切换appender,则必须再次覆盖它。这是一个这样的appender的例子:

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。这实际上是一个概念证明,但可以随意尝试......


总而言之,我不建议你走这条路。这绝对是可能的,但它可能比你投资动态彩色开关更有效。

答案 1 :(得分:1)

一种更简单、更一致的方法,对@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" />

将日期置于红色,其余在终端默认。