Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4net MemoryAppender not working

I'm using log4net to log in my app. My FileAppender is working fine, but I'm having problems with MemoryAppender.

Here is my config file.

<?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>

I use this code to setup the config file.

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

Like I said, the FileAppender works great. But I can't seem to get any events. I've tried using something like this to get the MemoryAppender.

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

I've tried using:

var events = mappender.GetEvents()

after logging something, and events is always empty. I've tried setting up the FileAppender and MemoryAppender in code instead of using the config file, and I get the same, the FileAppender works fine, but can't seem to get any events from MemoryAppender. Curious if I'm understanding MemoryAppender right? I also tried setting up a thread that loops checking for the GetEvents to not be empty, and while logging away it always comes back empty. I've tried setting the Threshold to Core.Level.All on the MemoryAppender but that did not change anything.

Thanks for any direction. I've looked around, and from the sites I've seen, I can't tell what I'm doing different.

Even something as simple as this does not work. events length is always zero;

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();
    }
}
like image 858
Terco Avatar asked Apr 09 '11 23:04

Terco


2 Answers

For those that need it, here's how to do it programmatically in C#:

var memoryAppender = new MemoryAppender();
var repository = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
repository.Root.AddAppender(memoryAppender);
var events = memoryAppender.GetEvents();
like image 175
Ralph Willgoss Avatar answered Nov 08 '22 13:11

Ralph Willgoss


I used Ralph's code above in my unit testing:

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;
}

This assumes you have a private static Log field on your class:

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

So, in the test, it's just:

var memoLog = GetMemoLog<MyClass>(); 
// followed by test logic, and then... 
var events = memoLog.GetEvents();
like image 2
CZahrobsky Avatar answered Nov 08 '22 14:11

CZahrobsky