【问题标题】:log4net MemoryAppender not workinglog4net MemoryAppender 不工作
【发布时间】:2011-04-09 23:26:26
【问题描述】:

我正在使用 log4net 登录我的应用程序。我的 FileAppender 工作正常,但 MemoryAppender 出现问题。

这是我的配置文件。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    </configSections>
<log4net>
<appender name="LogFileAppender" type="log4net.Appender.FileAppender">
  <param name="File" value="Envision.log" />
  <param name="AppendToFile" value="true" />
  <layout type="log4net.Layout.PatternLayout">
    <param name="Header" value="" />
    <param name="Footer" value="" />
    <param name="ConversionPattern" value="%d [%t] %-5p %m%n" />
  </layout>
</appender>
<appender name="MemoryAppender" type="log4net.Appender.MemoryAppender">

</appender>
<root>
  <level value="ALL" />
  <appender-ref ref="LogFileAppender" />
  <appender-ref ref="MemoryAppender" />
</root>
</log4net>
</configuration>

我使用此代码来设置配置文件。

FileInfo file = new FileInfo(configPath);
log4net.Config.XmlConfigurator.Configure(file);
file = null;

就像我说的,FileAppender 工作得很好。但我似乎无法得到任何事件。 我试过用这样的东西来获取 MemoryAppender。

Hierarchy hierarchy = LogManager.GetRepository() as Hierarchy;
MemoryAppender mappender = hierarchy.Root.GetAppender("MemoryAppender") as MemoryAppender;

我尝试过使用:

var events = mappender.GetEvents()

在记录一些东西之后,事件总是空的。我尝试在代码中设置 FileAppender 和 MemoryAppender 而不是使用配置文件,我得到了相同的结果,FileAppender 工作正常,但似乎无法从 MemoryAppender 获取任何事件。好奇我是否理解 MemoryAppender 对吗?我还尝试设置一个线程来循环检查 GetEvents 是否为空,并且在注销时它总是返回为空。我尝试在 MemoryAppender 上将 Threshold 设置为 Core.Level.All 但这并没有改变任何东西。

感谢您的任何指导。我环顾四周,从我看到的网站来看,我无法判断我在做什么不同。

即使是这样简单的事情也行不通。事件长度始终为零;

public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();

        MemoryAppender appender = new MemoryAppender();
        ILog logger = LogManager.GetLogger("foo");
        BasicConfigurator.Configure(appender);

        logger.Error("Should work");
        var events = appender.GetEvents();
    }
}

【问题讨论】:

    标签: log4net appender


    【解决方案1】:

    对于那些需要它的人,这里是如何在 C# 中以编程方式完成它:

    var memoryAppender = new MemoryAppender();
    var repository = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
    repository.Root.AddAppender(memoryAppender);
    var events = memoryAppender.GetEvents();
    

    【讨论】:

    • 太棒了,谢谢!我只是想为单元测试捕获日志行(不向我的项目添加模拟框架),所以我修改了你的代码
    【解决方案2】:

    我在单元测试中使用了上述 Ralph 的代码:

    using log4net;
    using log4net.Appender;
    // ...
    internal static MemoryAppender GetMemoLog<T>() where T: class 
    {
        var memoLog = new MemoryAppender();
        ILog appendableLog = LogManager.GetLogger(typeof(T).Assembly, typeof(T));
        var repository = (log4net.Repository.Hierarchy.Hierarchy)appendableLog.Logger.Repository;
        repository.Root.AddAppender(memoLog);            
        var logField = typeof(T).GetField("Log", BindingFlags.Static | BindingFlags.NonPublic);
        if (logField != null) logField.SetValue(null, appendableLog);
        return memoLog;
    }
    

    这假设您的班级有一个私有静态 Log 字段:

    private static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));
    

    所以,在测试中,它只是:

    var memoLog = GetMemoLog<MyClass>(); 
    // followed by test logic, and then... 
    var events = memoLog.GetEvents();
    

    【讨论】:

      【解决方案3】:

      您发布的简单示例代码使用 log4net 1.2.10.0 对我来说很好。

      我建议下载源代码并在调试器中单步执行。一开始可能看起来有点令人生畏,但你很快就会习惯他们的代码,而且不难理解。当我遇到自定义约束和附加程序问题时,我已经多次这样做了。它确实有助于快速解决问题,让您更好地了解 log4net 的工作原理。

      【讨论】:

        【解决方案4】:

        我想通了。我错误地使用了 Compact Framework .dll。一旦我意识到我切换到 .net 2.0 版本,这导致找不到 log4net 命名空间的问题,所以我对其进行了搜索并意识到我需要将我的 .net Framework 4 客户端配置文件更改为 .net Framework 4。我现在按预期收到了事件。

        【讨论】:

          【解决方案5】:

          我改编了 CZahrobsky 的回答。不得不稍微调整一下,因为我的班级不能有静态记录器的设计。

          被测类的日志字段声明如下:

          private ILog Logger = Log4netFactory.GetLogger(typeof(MyClass));
          

          在 GetMemLog 逻辑中,我必须首先创建 MyClass 的一个实例并将 logField 查找更改为按名称 'Logger' 和 BindingFlags.Instance 而不是 BindingFlags.Static 的 getField

          //create an instance of the class
          var myObject = new MyClass(context);
          
          var memoryLog = new MemoryAppender();
          ILog appendableLog = LogManager.GetLogger(typeof(JobQueue).Assembly, typeof(MyClass));
          var repository = (log4net.Repository.Hierarchy.Hierarchy)appendableLog.Logger.Repository;
          repository.Root.AddAppender(memoryLog);
          var logField = typeof(MyClass).GetField("Logger", BindingFlags.NonPublic | BindingFlags.Instance);
          
          if (logField != null)
          {
              //set logfield property value for the instance
              logField.SetValue(myObject, appendableLog);
          }
          

          PropertyInfo 的 SetValue() 示例为 here

          【讨论】:

            猜你喜欢
            • 2023-03-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多