我将 log4net 与 FileAppender 一起使用。布局模式是"%utcdate %message%newline"
,因此每条消息占用 1 行。
但是,包含换行符的消息存在问题;在写入文件之前是否可以转义新行?
3 回答
您可以创建一个自定义 PatternConverter 来转义换行符。
这提供了比其他答案更灵活的解决方案,因为您可以将它与任何附加程序一起使用。
我按照这些文章实现了一个自定义 PatternConverter,用空格替换换行符:
https://dejanfajfar.wordpress.com/2011/04/14/log4net-custom-layoutpattern/
自定义 PatternConverter 的代码如下所示:
using System.IO;
using log4net.Util;
public class EncodedMessagePatternConvertor : PatternConverter
{
protected override void Convert(TextWriter writer, object state)
{
var loggingEvent = state as log4net.Core.LoggingEvent;
if (loggingEvent == null)
return;
// Replace newline characters with spaces
var encodedMessage = loggingEvent.RenderedMessage.Replace("\r", " ").Replace("\n", " ");
writer.Write(encodedMessage);
}
}
自定义 PatternLayout 的代码如下所示:
using log4net.Layout;
using log4net.Util;
public class CustomPatternLayout : PatternLayout
{
public CustomPatternLayout()
{
AddConverter(new ConverterInfo { Name = "encodedmessage", Type = typeof(EncodedMessagePatternConvertor) });
}
}
appender 配置应如下所示:
<appender name="SomeAppender" type"...">
...
<layout type="YourNamespace.CustomPatternLayout, YourAssemblyName">
<conversionPattern value="%date %-5level %logger %encodedmessage %newline" />
</layout>
</appender>
我为模式名称选择了“ codedmessage ”,但是您可以通过在 AddConverter 调用和配置中更改它来命名它。
通过更改 Convert 方法中的代码以满足您的需要,此解决方案应该适用于其他编码要求。
到目前为止,我的解决方案是使用自定义文件附加程序:
class MyFileAppender : FileAppender
{
protected override void Append(LoggingEvent loggingEvent)
{
var val = Convert(loggingEvent);
base.Append(val);
}
protected override void Append(LoggingEvent[] loggingEvents)
{
var vals = loggingEvents.Select(Convert).ToArray();
base.Append(vals);
}
private static LoggingEvent Convert(LoggingEvent loggingEvent)
{
var eventData = loggingEvent.GetLoggingEventData();
eventData.ExceptionString = Convert(eventData.ExceptionString);
eventData.Message = Convert(eventData.Message);
var val = new LoggingEvent(eventData);
return val;
}
static string Convert(object val)
{
var res = val.ToString().Replace("\r", "\\r").Replace("\n", "\\n");
return res;
}
}
Avalanchis 建议的解决方案有效。但是,我来到这个线程是为了找到将异常消息和堆栈跟踪附加在一行中的解决方案。因此,我将 Convert 方法更改为如下内容:
protected override void Convert(TextWriter writer, object state)
{
var loggingEvent = state as log4net.Core.LoggingEvent;
string encodedMessage = string.Empty;
if (loggingEvent == null)
{
return;
}
// Replace newline characters with <space>
if (loggingEvent.ExceptionObject == null)
{
encodedMessage = loggingEvent.RenderedMessage.Replace("\r\n", " ");
}
else
{
encodedMessage = loggingEvent.GetExceptionString().Replace("\r\n", " ");
}
writer.Write(encodedMessage);
}
此外,我必须在 log4net 配置的布局标记中将 IgnoresException 属性设置为 false:
<layout type="{Namespace}.CustomPatternLayout">
<IgnoresException value="False" />
<conversionPattern value="%date %-5level %logger - %encodedmessage%newline" />
</layout>
这指定不包含异常数据,因为我们已经在编码消息中包含了异常数据。