在Log4Net或NLog(或其他一些记录器)中是否有一种方法可以以执行堆栈嵌套的XML或JSON格式输出日志?

Tar*_*Tar 6 c# logging log4net nlog postsharp

在Log4Net或NLog(或其他一些记录器)中是否有一种方法可以以执行堆栈嵌套的XML或JSON格式输出日志,这样如果A()调用函数B(7)调用C("something"),它将输出如下内容:

<Method name="A">
    <Method name="B" params="(int) 7">
        <Method name="C" params="(string) 'something'"/>
    </Method>
</Method>
Run Code Online (Sandbox Code Playgroud)

甚至更好:

<Method name="A">
    <Method name="B" params="(int) 7">
        <Params>
            <int>7</int>
        </Params>
        <Method name="C">
            <Params>
                <string>something</string>
            </Params>
        </Method>
    </Method>
</Method>
Run Code Online (Sandbox Code Playgroud)

为什么?因此,我可以使用(例如)XML Notepad或某些JSON-viewer(不知道任何显着的...)来快速折叠(不相关)或展开(相关)子调用,同时试图理解发生了什么错误.我PostSharp用来记录(目前只使用缩进)每个方法入口/出口和异常

Ale*_*exD 2

日志记录框架没有有关方法边界的信息,因此它无法正确格式化 XML。您可以尝试扩展框架并将附加信息传递到日志记录方法中。

不过,获得此输出的更简单方法是在方面类中执行所有消息格式化,并将日志记录框架配置为仅输出消息文本,而不输出任何其他信息。

例如,在log4net配置中:

<layout type="log4net.Layout.PatternLayout">
  <conversionPattern value="%message%newline" />
</layout>
Run Code Online (Sandbox Code Playgroud)

在方面的OnEntry方法中,您将打开 XML 标记(或 JSON 对象),并在OnExit方法中关闭该标记。您可以从下面的简单示例开始,并针对您的特定情况优化代码(例如,初始化记录器实例并在RuntimeInitializeCompileTimeInitialize方法中格式化字符串)。

[Serializable]
public class XmlLogAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    {
        ILog log = LogManager.GetLogger(args.Method.DeclaringType);
        if (log.IsDebugEnabled)
        {
            log.DebugFormat("<Method name=\"{0}\">", args.Method.Name);
            log.Debug("<Params>");
            foreach (object methodArgument in args.Arguments)
            {
                if (methodArgument == null)
                {
                    log.Debug("<null/>");
                }
                else
                {
                    log.DebugFormat("<{0}>{1}</{0}>", methodArgument.GetType(), methodArgument);
                }
            }
            log.Debug("</Params>");
        }
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        ILog log = LogManager.GetLogger(args.Method.DeclaringType);
        log.Debug("</Method>");
    }
}
Run Code Online (Sandbox Code Playgroud)