在静态类中保存对记录器的引用

本文关键字:记录器 引用 保存 静态类 | 更新日期: 2023-09-27 18:36:37

我正在使用log4net,其中我正在获取对静态类中记录器的引用,如下所示:

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

并在整个应用程序中使用该引用,如下所示:

Constants.Log.Info(_message);
然而,我

感觉这可能会导致问题,我意识到常量(全局?)变量可能是一件坏事。

  • 这种方法有什么问题吗?
  • 原因是什么?
  • 可以做些什么来解决这些问题?

在静态类中保存对记录器的引用

你是对的,如果你希望能够轻松区分日志级别并为每个类使用不同的日志目标("追加器"),这不是最好的方法

通常建议每个类都有一个静态ILog实例,以它的完全限定类型命名:

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));
   }
}

虽然与拥有单例相比,这看起来需要更多的工作,但从长远来看,它证明非常方便。完成此操作后,可以通过配置文件轻松区分DogCat日志级别(使用 log4net 语法显示的示例):

<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>

像log4net这样的日志记录框架也使用分层日志记录的概念:如果一个记录器的名称后跟一个点是后代记录器名称的前缀,则称其为另一个记录器的祖先。若要使用此功能,最好避免手动命名记录器(使用硬编码的 string s),而是使用类型信息来包含整个命名空间。

这实质上创建了一个单例,尽管存在许多问题,包括进行有效的单元测试。单元测试不需要记录,这引入了不必要的依赖项。

应考虑使用 IoC 容器和依赖项注入。