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

本文关键字:对象 消息 呈现 -根 appender log4net | 更新日期: 2023-09-27 17:53:09

我正在使用log4net,以及一个与log4net几乎相同的自定义日志facade。我登录来访问它。我想记录到一个简单的文本文件,但也使用一个自定义的XML追加器来写东西到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);
  }
}

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

这个行为对于我的文本文件日志来说是好的。但是,对于我的XML日志,我希望以不同的方式呈现它。简而言之,然后我想反映参数(程序集)的运行时类型并转储其所有公共成员,以及其公共成员的公共成员,以及…等等……到一个嵌套的XML结构。而不是用字符串呈现。Format(msg, assembly),我需要用别的东西,比如String。格式(味精、MyXmlDumper.Dump(组装))。

我还没有找到任何好的方法来根据Appender的类型进行渲染。

我当前的方法是让我的日志程序facade将所有调用转换为Trace, Debug,…etc转换成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"/>

但这意味着我必须在我的应用程序中创建两个日志存储库;一个用于文本文件附加器,另一个用于XML附加器,并相应地设置它们的呈现对象。

这看起来非常复杂,但没有必要(更不用说我现在不知道如何最好地使用日志存储库)。

对于这个问题有没有更好的解决办法?也许是一种以某种方式选择基于追加的渲染器而不是整个存储库的方式。或者一些概念上完全不同的解决方案,我还没有想到。

请指教。

谢谢

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

经典,我花了一整天的时间在这上面,刚刚在这里发帖后,我确实找到了一个解决方案…

我将把我的消息包装在上面发布的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中应用自定义IObjectRenderer。配置并使用它来呈现消息。我的IObjcetRenderer实现可以像我在第一篇文章中描述的那样负责转换LogMessage。

这两个应该都能很好地工作;将在下周实现这个,如果将来有人正在寻找具体的实现,请给我留言。