log4net MemoryAppender无法正常工作

问题描述 投票:7回答:5

我正在使用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
5个回答
10
投票

对于那些需要它的人来说,这里是如何在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;
}

假设您的类上有一个私有静态日志字段:

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

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

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

1
投票

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

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


1
投票

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


0
投票

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

被测试的类具有声明的日志字段:

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

在GetMemLog逻辑中,我必须首先创建一个MyClass实例,然后通过名称'Logger'和BindingFlags.Instance而不是BindingFlags.Static将logField更改为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

© www.soinside.com 2019 - 2024. All rights reserved.