您可以创建一个自定义布局来格式化日志消息:
StructLayout
public class StructLayout : PatternLayout
{
public override void Format(TextWriter writer, LoggingEvent loggingEvent)
{
LoggingEvent newLoggingEvent;
var message = loggingEvent.MessageObject;
if (MessageObjectBuilder.TryBuildMessageObject(message, out object newMessage))
{
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
var callerStackBoundaryDeclaringType = loggingEvent.GetType().GetField("m_callerStackBoundaryDeclaringType", bindingFlags)?.GetValue(loggingEvent);
newLoggingEvent =
new LoggingEvent(callerStackBoundaryDeclaringType as Type,
loggingEvent.Repository,
loggingEvent.LoggerName,
loggingEvent.Level,
newMessage as SystemStringFormat,
loggingEvent.ExceptionObject);
}
else
{
newLoggingEvent = loggingEvent;
}
base.Format(writer, newLoggingEvent);
}
}
MessageObjectBuilder - 使用
Newtonsoft
格式化消息:
public class MessageObjectBuilder
{
public static bool TryBuildMessageObject(object messageObject, out object newMessage)
{
var message = messageObject;
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
object[] args = message.GetType().GetField("m_args", bindingFlags)?.GetValue(message) as object[];
if (args == null || args.Length == 0)
{
newMessage = message;
return false;
}
var argsAsJson = SerializeArgs(args);
var provider = message.GetType().GetField("m_provider", bindingFlags)?.GetValue(message);
var format = message.GetType().GetField("m_format", bindingFlags)?.GetValue(message);
newMessage = new SystemStringFormat(provider as IFormatProvider, format as string, argsAsJson);
return true;
}
private static object[] SerializeArgs(object[] args)
{
var newArgs = new List<string>();
foreach (var arg in args)
{
newArgs.Add(Newtonsoft.Json.JsonConvert.SerializeObject(arg));
}
return newArgs.ToArray();
}
}
最后,将以下内容添加到log4net.config
中,而不是您当前的布局:
<appender name="StructLogAppender" type="log4net.Appender.RollingFileAppender">
<file value="StructLogAppender\StrcutLog.log" />
<layout type="Namespace.StructLayout, AssmbllyName">
<conversionPattern value="%date{M/d/yyyy H:mm:ss.fff} - %message%newline" />
</layout>
<filter type="log4net.Filter.LevelRangeFilter">
<param name="LevelMax" value="ERROR" />
</filter>
<appendToFile value="true" />
</appender>
注意:
- 此代码使用反射,因此可能会有一些负担,如果性能是一个问题,则不建议使用。
- 请确保在
log4net.config
中自定义Namespace
和AssmbllyName