问题
I'm using log4net with FileAppender. The layout pattern is "%utcdate %message%newline"
, so every message takes 1 line.
However, there is an issue with messages containing new line chars; is it possible to escape new lines before writing to the file?
回答1:
You can create a custom PatternConverter which escapes the newline characters.
This provides a more flexible solution than the other answer because you can use it with any appender.
I followed these articles to implement a custom PatternConverter that replaces the newline characters with spaces:
https://dejanfajfar.wordpress.com/2011/04/14/log4net-custom-layoutpattern/
http://www.hanselman.com/blog/CreatingYourOwnCustomPatternLayoutPatternParserAndPatternConvertorWithLog4net.aspx
The code for the custom PatternConverter looks like this:
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);
}
}
The code for the custom PatternLayout looks like this:
using log4net.Layout;
using log4net.Util;
public class CustomPatternLayout : PatternLayout
{
public CustomPatternLayout()
{
AddConverter(new ConverterInfo { Name = "encodedmessage", Type = typeof(EncodedMessagePatternConvertor) });
}
}
The appender configuration should look something like this:
<appender name="SomeAppender" type"...">
...
<layout type="YourNamespace.CustomPatternLayout, YourAssemblyName">
<conversionPattern value="%date %-5level %logger %encodedmessage %newline" />
</layout>
</appender>
I chose "encodedmessage" for the pattern name, but you can name it whatever you like by changing it in the AddConverter call and the configuration.
This solution should work for other encoding requirements by changing the code in the Convert method to suit your needs.
回答2:
My solution so far is to use a custom file appender:
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;
}
}
回答3:
The solution suggested by Avalanchis works. However, I came to this thread for finding the solution for attaching the exception message and the stack trace in a single line. So, I changed the Convert method to something like this:
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);
}
Also, I had to set IgnoresException property to false in the layout tag in log4net configuration:
<layout type="{Namespace}.CustomPatternLayout">
<IgnoresException value="False" />
<conversionPattern value="%date %-5level %logger - %encodedmessage%newline" />
</layout>
This specifies not to include the exception data as we have already included the same in the encoded message.
来源:https://stackoverflow.com/questions/19993416/how-to-escape-newline-characters-in-the-message