Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Holding a reference to logger in a static class

I am using log4net in which I am obtaining a reference to the logger within a static class like so:

internal static class Constants
{
   public static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
}

and using that reference throughout the app like so:

Constants.Log.Info(_message);

However I've got the feeling that this may cause problems and I realise that constant (global?) variables can be a bad thing.

  • Is there anything wrong with this method?
  • What are the reasons?
  • What can be done to resolve these?
like image 882
m.edmondson Avatar asked Jun 08 '12 11:06

m.edmondson


People also ask

Can we do dependency injection in static class c#?

You can use dependency injection in a static class using method or property injection. However, you cannot use constructor injection in a static class because the constructor of a static class cannot accept any parameters.

Should Ilogger be static?

Loggers should be declared to be static and final. It is good programming practice to share a single logger object between all of the instances of a particular class and to use the same logger for the duration of the program.

When to use singleton vs static class?

A Singleton can implement interfaces, inherit from other classes and allow inheritance. While a static class cannot inherit their instance members. So Singleton is more flexible than static classes and can maintain state. A Singleton can be initialized lazily or asynchronously and loaded automatically by the .


1 Answers

You are correct, that is not the best approach, if you want to be able to easily differentiate log levels and use different log targets ("appenders") for each class.

It's usually recommended that each class has a static ILog instance, named after it's fully qualified type:

namespace Animals
{
   public class Dog
   {
       private static readonly ILog Log = LogManager.GetLogger(typeof(Dog));
   }

   public class Cat
   {
       private static readonly ILog Log = LogManager.GetLogger(typeof(Cat));
   }
}

While this looks like more work compared to having a singleton, it proves very handy in the long term. Once you've done this, it is easy to differentiate Dog and Cat log levels through your configuration file (example shown with log4net syntax):

<log4net>

   <!-- appender definitions ommited -->

   <!-- default for all loggers in Animals namespace -->
   <logger name="Animals">
     <level value="WARN"/>
   </logger>

   <!-- ...but we need full debug for Dogs -->
   <logger name="Animals.Dog">
     <level value="DEBUG"/>
   </logger>

   <!-- ...and we want to send Cat messages over e-mail -->
   <logger name="Animals.Cat">
     <level value="INFO"/>
     <appender-ref ref="SmtpAppender"/> 
   </logger>

</log4net>

Logging frameworks like log4net also use the notion of hierarchical logging: a logger is said to be an ancestor of another logger if its name followed by a dot is a prefix of the descendant logger name. To make use of this feature, it's best to avoid naming loggers manually (using hardcoded strings), but rather use type information to include the entire namespace.

like image 148
Groo Avatar answered Nov 11 '22 21:11

Groo