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 настроен неправильно.