log4net MemoryAppender не работает - PullRequest
       19

log4net MemoryAppender не работает

7 голосов
/ 10 апреля 2011

Я использую 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 не был пустым, и при выходе из системы он всегда возвращается пустым.Я попытался установить порог для Core.Level.All в MemoryAppender, но это ничего не изменило.

Спасибо за любое направление.Я посмотрел вокруг, и с сайтов, которые я видел, я не могу сказать, что я делаю по-другому.

Даже что-то столь простое, как это, не работает.длина событий всегда равна нулю;

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 ]

10 голосов
/ 10 сентября 2012

Для тех, кому это нужно, вот как это сделать программно в C #:

var memoryAppender = new MemoryAppender();
var repository = (log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository();
repository.Root.AddAppender(memoryAppender);
var events = memoryAppender.GetEvents();
2 голосов
/ 03 августа 2017

Я использовал приведенный выше код Ральфа в своем модульном тестировании:

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 голос
/ 11 апреля 2011

Я понял это. Я использовал Compact Framework .dll по ошибке. Однажды я понял, что переключился на версию .net 2.0, что вызвало проблему с отсутствием пространства имен log4net, поэтому я выполнил поиск по этому вопросу и понял, что мне нужно изменить мой клиентский профиль .net Framework 4 на .net Framework 4. Теперь я получаю события, как ожидалось.

1 голос
/ 10 апреля 2011

Простой пример кода, который вы разместили, отлично работает для меня, используя log4net 1.2.10.0.

Я бы порекомендовал загрузить исходный код и пройти по нему в отладчике. Поначалу это может показаться немного сложным, но вы довольно быстро привыкаете к их коду, и за ним нетрудно следить. Я делал это много раз, когда у меня были проблемы с пользовательскими ограничениями и приложениями. Это действительно помогает быстро решать проблемы и дает вам лучшее понимание того, как работает log4net.

0 голосов
/ 18 апреля 2019

Я адаптировал ответ Чагробского.Пришлось немного подправить, так как у моего класса не может быть статического логгера по дизайну.

Тестируемый класс имеет поле журнала, объявленное как:

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

В логике GetMemLog мне нужно сначала создать экземпляр MyClass и изменить поиск logField на getField by name 'Logger'и BindingFlags.Instance вместо BindingFlags.Static

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

Примеры для SetValue () для PropertyInfo: здесь

...