简体   繁体   中英

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?

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 string s), but rather use type information to include the entire namespace.

This essentially creates a singleton, although there are many of problems with that, including making effective unit tests. Unit tests don't need to log and this introduces an unnecessary dependency.

You should consider using an IoC container and dependency injection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM