log4net MemoryAppender无法正常工作

时间:2011-04-09 23:26:27

标签: log4net appender

我正在使用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();
    }
}

5 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分: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;
}

这假设您的班级上有一个私人静态日志字段:

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

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

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

答案 2 :(得分:1)

您发布的简单示例代码使用log4net 1.2.10.0可以正常使用。

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

我改编了扎罗布斯基的答案。由于我的课程在设计上不能具有静态记录器,因此必须稍作调整。

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

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