1

I have run into some strange behavior with log4net and wondered if anyone can explain this to me, I would love to learn more to understand it.

Inside my WPF App.xaml.cs OnStartup override method I have the following code which sets a log4net property used for logging:

// logLocation is a path to a subdir in the users' appdata roaming dir
log4net.GlobalContext.Properties["LogLocation"] = logLocation;
logger = LogManager.GetLogger(typeof(App));
logger.Info("OnStartup: " + string.Join(" ", e.Args));

I do this before I create any other loggers (or so I thought).

In my config file I have the following line:

<file type="log4net.Util.PatternString" value="%property{LogLocation}" />

This works to specify the logging file location. However, I have run into a situation in which this fails - resulting in logging writing to a file name "(null)" in the executing directory.

What seems to cause this is the following pseudo code, which is in the same OnStartup method after the code above:

AnyClass ac = new AnyClass();
ac.NoOp();

where AnyClass has a logger instantiated like this:

private static ILog logger = LogManager.GetLogger(typeof(AnyClass));

The reason I am using pseudo code, is that I can replicate this behavior with any class I instantiate AND call a method on. If no method is called, then the logging path works as expected.

A couple of things to note:

  1. This works when I run it in the debugger in debug or release mode. The error only appears when I run the exe directly or via 'Start Without Debugging'.
  2. If the logger is not defined statically - then the problem goes away
  3. If I add a static constructor to AnyClass, then the problem goes away, i.e.:

    static AnyClass() {}

  4. If I move the call to ac.NoOp() to a secondary method, which is called by OnStartup - the error goes away.

So, to recap, the error is only caused by instantiating a class with a static logger initialization, and invoking a method on that class within the OnStartup method.

I have several ways to work around this, but I would love to learn more to understand why this is happening.

  • You can probably learn more by reading the Jon Skeet articles linked in Marc Gravell's answer to this question http://stackoverflow.com/questions/3965976/when-do-static-variables-get-initialized-in-c – sgmoore May 09 '13 at 16:55
  • Thanks, will read this. Apparently static initialization is not quite as straightforward as I thought. – Douglas Miller May 09 '13 at 17:29

1 Answers1

0

I think ac.NoOp(); is creating a new instance of logger and new instance does not know what is value of PatternString. hence null value is being used.

refer this link

public static Logger getLogger(String name)

Retrieve a logger named according to the value of the name parameter. 

If the named logger already exists, then the existing instance will be returned. 
Otherwise, **a new instance** is created. 
swapneel
  • 3,061
  • 1
  • 25
  • 32