Search code examples
c#nunitlog4netnunit-2.5

Initialize log4Net as early as possible with NUnit


I'm wondering what is the best way to initialize log4Net in a NUnit project. Of course I want to call the init code (ie. XmlConfigurator.Configure()) as soon as I can to get as many early log output as I can. But since my project is run through NUnit, I have little control on its entry point.

According to NUnit documentation, it should call some constructors first, then a method marked with the [SetUp] attribute in a class marked with [TestFixtureSetup].

So, First, I created a static helper class which I can call several times without trouble.

  public static class LoggingFacility
  {
    private static bool _loggerIsUp = false;

    public static void InitLogger()
    {
      if (_loggerIsUp == false)
        XmlConfigurator.ConfigureAndWatch(f);

      _loggerIsUp = true;
    }
  }

Then, I made all my [TestFixtureSetup] inherit a single one that does pretty much nothing else than calling LoggingFacility.initLogger(). But that still leaves all constructors that are run earlier, in an order I can only assume random. And moreover, it will probably do some static initializations before I am even able to execute some code.

In fact, as I can see in my log, the first 4 seconds or so of execution are completely unrecorded.

Does it mean I will have to call my InitLogger() in every constructor and forbid the use of any static initializer? That's tough job!

Does somebody know a magic trick with this?


Solution

  • A work mate provided me with the following workaround, that does the job:

    In all my classes that require logging, I had the following logger initialization

    private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    

    I simply changed it to a singleton initializer

    private static readonly ILog Log = LoggingFacility.GetLoggerWithInit(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
    
    /*** ... ***/
    
    public static class LoggingFacility
    {
      private static bool _loggerIsUp = false;
    
      public static ILog GetLoggerWithInit(Type declaringType)
      {
        if (_loggerIsUp == false)
          XmlConfigurator.Configure(_log4NetCfgFile);
        _loggerIsUp = true;
        return LogManager.GetLogger(declaringType);
      }
    }
    

    Because I have this code in every class, this static initializer has to be called very early by NUnit wile instantiating my test classes.

    Next step is to make that thread safe :(