log4net с простым инжектором DI

Я пытаюсь использовать Simple Injector ( + интеграция MVC) v 2.5.2. для приложения MVC 4 и мне нужно также отслеживать / регистрировать производительность (выполнение) (с помощью модуля log4net). Текущая реализация (во время выполнения) создает файл log4net по указанному пути, но не записывает в него ни одной строки текста (когда я его отлаживал, все прошло без ошибок до конца _logger.Info ("message")).

Кто-нибудь пытается использовать Simple Injector DI для log4net?

Как я зарегистрировал модуль log4net:

public static class LoggingModule
{
    public static void RegisterServices(Container container)
    {
        string log4NetConfigFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config");
        log4net.Config.XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFile));
        var logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        container.RegisterSingle(logger);

    }
}

И в Global.asax

LoggingModule.RegisterServices(container);

Файл конфигурации Log4net выглядит так (я не думаю, что есть какие-либо проблемы):

<log4net>
  <appender name="PerformanceLogFile" type="log4net.Appender.RollingFileAppender" >
  <param name="File" value="..\Performance\PricingManager" />
  <param name="AppendToFile" value="true" />
  <param name="RollingStyle" value="Date" />
  <param name="DatePattern" value="_yyyy-MM-dd.lo\g" />
  <param name="MaxSizeRollBackups" value="10" />
  <param name="StaticLogFileName" value="false" />
  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%m%n"/>
  </layout>
  <filter type="log4net.Filter.LevelRangeFilter">
    <param name="LevelMin" value="INFO" />
    <param name="LevelMax" value="FATAL" />
  </filter>
  </appender>
  <logger name="SoftTech.PricingEngine.PricingService.PerformanceStatisticLoggerWithAPI">
    <level value="ALL" />
    <appender-ref ref="PerformanceLogFile" />
  </logger>
</log4net>

И чтобы включить / выключить ведение журнала я использовал:

private static void RegisterIPerformanceStatisticLogger(Container container)
    {
        if (ShouldLogPerformance())
        {
            container.Register<IPerformanceStatisticLogger, PerformanceStatisticLogger>(WebLifestyle); 
        }
        else
        {
            // do nothing
            container.Register<IPerformanceStatisticLogger, DisabledPerformanceStatisticLogger>(WebLifestyle); 
        }
    }

И PerformanceStatisticLogger или DisablePerformanceStatisticLogger устанавливают

IsLoggingEnabled = true; // | false
IsAPITraceEnabled = false; // | true

Что я делаю не так? Сдается мне проблема способа впрыска. Спасибо за любой совет

1 ответ

Решение

Нет ничего особенного в Simple Injector, когда дело доходит до настройки log4net. Например, вы можете зарегистрироваться ILog следующее:

container.RegisterSingleton<ILog>(LogManager.GetLogger(typeof(object)));

Очевидно это зарегистрировало единственного регистратора для полного заявления. Если вы хотите внедрить другой регистратор для каждого класса, вам нужно определить собственную реализацию адаптера:

public sealed class Log4NetAdapter<T> : LogImpl
{
    public Log4NetAdapter() : base(LogManager.GetLogger(typeof(T)).Logger) { }
}

Вы можете зарегистрировать этот адаптер следующим образом:

container.RegisterConditional(typeof(ILog),
    c => typeof(Log4NetAdapter<>).MakeGenericType(c.Consumer.ImplementationType),
    Lifestyle.Singleton,
    c => true);

Это гарантирует, что каждый потребитель получает свой собственный Log4NetAdapter<T> реализация.

Однако обратите внимание, что IMO гораздо лучше не допускать зависимости кода приложения от абстракций сторонних библиотек. Я думаю, что гораздо лучше определить собственную абстракцию логгера.

Мой опыт работы с log4net заключается в том, что когда log4net ничего не регистрирует, что-то не так с вашей конфигурацией log4net. Что я ненавижу в log4net, так это в том, что он никогда не генерирует никаких исключений, когда вы его неправильно настроили. Он просто глотает и продолжает, что делает работу с log4net гораздо более болезненной, чем она должна быть.

Одна вещь, которая может помочь, это зацепить LogLog.LogReceived событие log4net при запуске. Это позволяет проверить, есть ли какие-либо ошибки. Например, это код, который я использовал в предыдущем проекте:

LogLog.LogReceived += (s, e) =>
{
    if (e.LogLog.Prefix.Contains("ERROR"))
    {
        throw new ConfigurationErrorsException(e.LogLog.Message,
            e.LogLog.Exception);
    }
};

Это гарантирует, что ваше приложение напрямую останавливается с явным исключением, когда log4net настроен неправильно.

Другие вопросы по тегам