log4net - 根据appender呈现(对象)消息

时间:2015-06-03 14:50:29

标签: c# logging log4net

我使用log4net,并且自定义logg facade几乎与log4net.ILog相同以访问它。 我想记录一个简单的文本文件,但也使用自定义XML appender将内容写入XML。

现在问题就在这里。说我做了像

这样的事情
interface IMyILogFacade
{
// An implementation of this interface will eventually route this call to 
// log4net.ILogger.Trace
void Trace(string format, params object[] args);
}

class Test
{
  IMyILogFacade log; // assume this is given (injected)

  public void testMethod(Assembly assembly)
  {
string msg = "Entering Method 'testMethod'. Method Parameter 0 (assembly): {0}";
    log.Trace(msg, assembly);
  }
}

默认情况下,当以任何转换模式或RenderedMessage显式访问%message时,log4net将使用简单的String.Format(msg,assembly)呈现消息。

此行为适用于我的文本文件日志。但是对于我的XML日志,我希望它以不同的方式呈现。简而言之,我想反思参数(程序集)的运行时类型,并转储其所有公共成员及其公共成员'公共成员,等等...到嵌套的XML结构。因此,我不需要使用String.Format(msg,assembly)进行渲染,而是需要使用其他东西,比如String.Format(msg,MyXmlDumper.Dump(assembly))。

我还没有找到任何好的方法来制作渲染,具体取决于Appender的类型。

我目前的做法是让我的记录器外观将所有对Trace,Debug等的调用转换为LogMessage类型的对象。

public class LogMessage
{
    public string message { get; protected set; }
    public object[] @params { get; protected set; }

    public LogMessage(string message, params object[] @params)
    {
        this.message = message;
        this.@params = @params;
    }
}

然后我使用一个实现IObjectRenderer的类来渲染它。这将是一个类似ToString的简单函数

public class LogMessageStringRenderer : IObjectRenderer
{
    public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer)
    {
        LogMessage logMessage = obj as LogMessage;

        if(logMessage == null)
        {
            throw new InvalidOperationException("LogMessageStringRenderer can only render objects of type LogMessage");
        } else 
        {
            writer.Write(
                String.Format(logMessage.message, logMessage.@params)
                ); 
        }
    }
}

当然,创建Xml转储时可以直接创建它。

这似乎是一个不太理想的解决方案。首先,这些渲染器(据我所知)只能附加到log4net存储库。通过代码或在配置文件中作为根元素,如

<renderer renderedClass="LogMessage" RenderingClass="LogMessageStringRenderer"/>

但这意味着我必须在我的应用程序中创建两个日志记录库;一个用于文本文件appender,另一个用于xml appender,并相应地设置它们的渲染对象。

这看起来非常复杂(不过我不知道如何最好地使用日志记录库)。

这个问题可能有更好的解决方案吗?也许可以某种方式以appender为基础而不是整个存储库选择渲染器。或者在概念上完全不同的解决方案我还没有。

任何指针都会非常感激。

由于

1 个答案:

答案 0 :(得分:0)

经典,一整天都花在这上面,在发布这里之后我找到了解决方案......

我将把我的消息包装在上面发布的LogMessage类中。然后我将创建一个从PatternLayoutConverter转换的派生并将其应用于消息参数:

<param name="ConversionPattern" value="%date&#9;-&#9;%thread&#9;-&#9;%level&#9;-&#9;%-80logger&#9;-&#9;%-40method&#9;-&#9;%message%newline" />
  <footer value="&#13;&#10;&#13;&#10;&#13;&#10;"/>
  <converter>
    <name value="message" />
    <type value="MyMessageConverter"/>
  </converter>

如果我很懒,我可能会创建两个转换器,一个用于ToString实现,一个用于基于Xml的转储。 如果我更有野心,我可以创建一个转换器,允许在log4net.config中应用自定义IObjectRenderer并使用它来呈现消息。然后我的IObjcetRenderer实现可以像我在第一篇文章中所描述的那样转换LogMessage。

这应该都很好用;将在下周实施,如果将来有人正在寻找具体的实施,请给我留言。