一行中的多种颜色
本文关键字:颜色 一行 | 更新日期: 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" />
将日期设置为红色,其余日期为终端默认值。