Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
361 views
in Technique[技术] by (71.8m points)

c# - log4net with DI Simple Injector

I am trying to use Simple Injector ( + integration MVC) v 2.5.2. for an MVC 4 Application and I need to track/log performance (execution) as well(by log4net module). Current implementation (during runtime) creates log4net file in specified path but did not write any line of text into it (when I debug it everything went with no error to the end of _logger.Info("message") ).

Does anyone try to use Simple Injector DI for log4net?

The way how I've registered log4net module is:

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

    }
}

And in Global.asax

LoggingModule.RegisterServices(container);

Log4net configuration file looks like so (I dont think there is any problem):

<log4net>
  <appender name="PerformanceLogFile" type="log4net.Appender.RollingFileAppender" >
  <param name="File" value="..PerformancePricingManager" />
  <param name="AppendToFile" value="true" />
  <param name="RollingStyle" value="Date" />
  <param name="DatePattern" value="_yyyy-MM-dd.log" />
  <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>

And to turn on/off logging I've been using:

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

And PerformanceStatisticLogger or DisablePerformanceStatisticLogger sets

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

What I am doing wrong? Seems to me the problem of the way of injection. Thanks for any advice

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There's nothing special about Simple Injector when it comes to configuring log4net. For instance, you can register ILog as follows:

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

Obviously this registered a single logger for the complete application. In case you want to inject a different logger per class, you will have to define your own adapter implementation:

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

You can register this adapter as follows:

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

This ensures that each consumer gets its own Log4NetAdapter<T> implementation.

Do note though that IMO it's much better to prevent application code to take a dependency on 3rd party library abstractions. I think it's much better to define you own logger abstraction.

My experience with log4net is that when log4net doesn't log anything, there's something wrong with your log4net configuration. What I hate about log4net is that it never throws any exceptions when you misconfigured it. It just swallows and continues, which makes working with log4net much more painful than it should be.

One thing that can help is hooking onto the LogLog.LogReceived event of log4net at startup. This allows you to check if there are any errors. For instance this is the code I used in a previous project:

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

This makes sure your application directly stops with a clear exception when log4net is misconfigured.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...