Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4net logger defined in base class

I want to build my log4net logger in my MVC controller abstract base class like so:

protected static readonly ILog Log = LogManager.GetLogger(typeof(AuthorizedController));

In this manner I can define the logger once and be done with it. The only problem is that the logger attribute in the log output will always be AuthorizedController, and if I have FooController inherited from AuthorizedController I'd like the log output to reflect that.

What would be a good KISS, DRY, and efficient way do doing this?

like image 645
Jeremy Holovacs Avatar asked Aug 17 '12 15:08

Jeremy Holovacs


People also ask

How do I enable log4net logging?

If you are using a separate configuration file for log4net, do this: after following all the other setup instructions, make sure that u right click on the file in the visual studio solution explorer, select properties, expand the "Advanced" option group, set the "Copy To Output Directory" value as "Copy always".

Where are log4net logs stored?

You can configure the log4net. config file to create log files. The file is located in the webroot\App_data directory of the installation. The different log files are described in Services logs.

Where do I put log4net in web config?

Add log4net in config file config and enter the following details. Add a class Log. cs in the Utilities folder. Now, in the constructor of this class, instantiate logs for monitoring and debugger loggers.


3 Answers

I'm not sure how expensive the call to LogManager.GetLogger() is, but I suspect that there is some clever caching and/or lazy initialization in the log4net system that keeps requested instances available for quick retrieval. After all, there is no reason why calling LogManager.GetLogger() twice with the same type parameter would return a different instance.

That said, perhaps replacing the field with the following property will suffice.

protected ILog Logger
{
    get { return LogManager.GetLogger(GetType()); }
}

GetType() is virtual and overloaded so each concrete type will supply its type when this property is called.

like image 119
Steve Guidi Avatar answered Sep 26 '22 02:09

Steve Guidi


As Steve Guidi suggested - use GetType to create logger for specific instance of type. You can save reference to instance of logger which gets calling LogManager.GetLogger in backing field:

    private ILog _log;
    protected ILog Log => _log ?? (_log = LogManager.GetLogger(GetType()));
like image 38
Vasyl Senko Avatar answered Sep 27 '22 02:09

Vasyl Senko


I did something similar by using NInject as an IoC container, but I suppose you can grab the idea to use with your own container. Basically I inject ILog on the requesting types constructor, but instead of binding to an instance, I bind it to a provider.

  kernel.Bind<ILog>().ToProvider<MyProvider>();

public object Create(IContext context)
{
    return LogManager.GetLogger(context.Request.Target.Member.DeclaringType);
}

so each type receive a logger that is the same as doing GetLogger(GetType()) in the constructor.

like image 27
Felice Pollano Avatar answered Sep 25 '22 02:09

Felice Pollano