我应该在每个类或基类中声明一次log4net记录器吗?

时间:2012-01-30 22:30:13

标签: c# .net log4net

声明一个记录器并在基类中调用LogManager.GetLogger似乎更干净,这样每个继承的人都可以使用它。但是,在log4net站点和this blog post之类的其他博客中,它声明最好为每个类声明一个记录器,因为:

  

您可以通过这种方式使用记录器来隔离对象的日志记录问题,我完全建议您这样做。这将使您能够使用log4net的分层配置机制来限制和指示各个记录器的日志输出。

这是否意味着如果我把它放在基类中,它会使该记录器成为瓶颈?

如果是这样,是否有其他解决方案,或者我只需要为每个类创建一个记录器?

5 个答案:

答案 0 :(得分:23)

该帖子并未明确告诉您在每个派生的类中使用不同的记录器,而是通常每个类类型使用不同的记录器。您可以,但不必在每个派生类中使用新的记录器实例。

查看它的一种方法是,同时实例化两个单独的记录器可能会令人困惑(因为基本记录器仍然存在),尤其是如果使用相同的记录器名称隐藏基本记录器。您的基类方法(未被覆盖)仍将引用基本静态记录器,而重写的方法将使用不同的方法。

此外,该文章实例化了这样的记录器:

static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType );

虽然可能使用稍微简单的方法:

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

首先,它标记为readonly,这意味着一旦初始化,您将无法意外更改字段。使用该类型将以与反射相同的方式工作,但稍快(在编译时解析)。如果您选择重命名它,Visual Studio也会自动更新类名(不会使用字符串重载)。

答案 1 :(得分:5)

通常的做法是每个类有一个记录器,而不是基类。这样,您就可以基于每个类启用/禁用日志记录。

我可能还建议使用Common Logging 2.0,http://netcommon.sourceforge.net/

  

目前正在使用的.NET有各种日志记录实现,log4net,企业库日志记录,NLog,以命名最受欢迎。具有不同实现的缺点是它们不共享公共接口,因此会对库的用户强加特定的日志记录实现。

     

Common.Logging库引入了一个简单的抽象,允许您在运行时选择特定的日志记录实现。因此,您可以推迟决定在部署之前使用的特定日志库。适配器用于将特定的日志记录系统插入Common.Logging。

答案 2 :(得分:1)

提供的声明不涉及瓶颈。在基类中声明记录器会限制对派生类中的日志记录的控制。如果您从包含相同记录器的基类派生类A和B,那么对于在A和B类中完成的所有日志记录,您将遇到相同的日志记录设置。

log4net允许您根据创建的类或命名空间配置记录器,从而可以非常严格地控制记录的内容。例如,在信息级别具有A类日志,在调试级别具有B类日志。

为您希望记录的每个类添加一行代码对于它提供的灵活性来说是一个非常小的负担。

答案 3 :(得分:0)

我在基类中使用静态字典,键入类型名称:

private static readonly Dictionary<string, ILog> _loggers = new Dictionary<string, ILog>();

使用方法(在基类上)返回记录器:

    private ILog GetLogger(){
        var tn = this.GetType().FullName;
        if (!_loggers.ContainsKey(tn)) {
            _loggers.Add(tn,LogManager.GetLogger(this.GetType()));
        }
        return _loggers[tn];
    }

我也有基类的日志记录方法:

    public void Log(string msg, params object[] args) {
        GetLogger().InfoFormat(msg, args);
    }

我认为这将允许我为每种类型配置日志记录(虽然我不这样做)并且GetLogger方法可以暴露给派生类,以便他们可以自己进行日志记录。

答案 4 :(得分:-2)

通常你应该有一个记录器类,你可以使用单例模式,并确保你的应用程序只有一个记录器实例。

编辑:现在让它保持线程安全,感谢您的评论。

    public class Logger
    { 
      private static object syncRoot = new Object();
      private static Logger instance=null;
      // private constructor
      private Logger()
      {
      }
      /// <summary>
    /// Gets an instance with default parameters based upon the caller
    /// </summary>
    /// <returns></returns>
    public static Logger GetInstance()
    {
       // make sure you return single instance
       if (instance == null)
        {
           lock (syncRoot) 
           { 
            instance=new Logger();
           } 
        }
        return instance;
    }
   }

希望这有帮助