Log4J:创建Logger实例的策略

Adr*_*ian 69 java logging log4j

我决定将Log4J日志框架用于新的Java项目.我想知道我应该使用什么策略来创建/管理Logger实例以及为什么?

  • 每个类的一个Logger实例,例如

    class Foo {
        private static final Logger log = Logger.getLogger(Foo.class);
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 每个线程一个Logger实例
  • 每个应用程序的一个Logger实例
  • 水平切片:应用程序每层中的一个Logger实例(例如视图层,控制器层和持久层)
  • 垂直切片:应用程序功能分区中的一个Logger实例

注意:在这些文章中已经在某种程度上考虑了这个问题:

什么是创建Log4j记录器的开销

PSp*_*eed 45

通常,您需要为每个类设置记录器,因为这是一个很好的逻辑组件.线程已经是日志消息的一部分(如果您的过滤器显示它们),因此切片记录器可能是多余的.

关于应用程序或基于图层的记录器,问题是你必须找到一个坚持该Logger对象的地方.不是什么大不了的事.更大的问题是某些类可能会在多个应用程序的多个级别使用...可能很难让您的记录器正确.或者至少是棘手的.

...而你想要的最后一件事是你的日志记录设置中的错误假设.

如果您关心应用程序和图层并拥有简单的分离点,那么NDC就是您的选择.代码有时可能有点过分,但我不知道有多少次我被一个准确的上下文堆栈保存,显示我从层Y中的应用程序X调用了Foo.bar().


rsp*_*rsp 32

最常用的策略是为每个类创建一个记录器.如果您创建新线程,则为它们提供有用的名称,以便可以轻松区分它们的日志记录.

每个类创建记录器的好处是能够在类的包结构中打开/关闭日志记录:

log4j.logger.org.apache = INFO
log4j.logger.com.example = DEBUG
log4j.logger.com.example.verbose = ERROR
Run Code Online (Sandbox Code Playgroud)

上面会将所有apache库代码设置为INFOlevel,将日志记录从您自己的代码切换到DEBUG级别,但是详细的软件包除外.

  • 是的,我认为您将使用String变体,如`private static Logger logger = Logger.getLogger(MyClass.class.getPackage());`如果您创建名为"ab","abc"的记录器,则记录器层次结构也可以使用等.请参阅http://logging.apache.org/log4j/1.2/manual.html上的手册 (2认同)

Dea*_*n J 13

我确定这不是最佳实践,但我在应用程序之前已经解除了一些启动时间以保存代码行.特别是,粘贴时:

Logger logger = Logger.getLogger(MyClass.class);
Run Code Online (Sandbox Code Playgroud)

...开发人员经常忘记将"MyClass"更改为当前的类名,并且几个记录器总是指向错误的位置.这是不好的.

我偶尔会写:

static Logger logger = LogUtil.getInstance(); 
Run Code Online (Sandbox Code Playgroud)

和:

class LogUtil {
   public Logger getInstance() {
      String callingClassName = 
         Thread.currentThread().getStackTrace()[2].getClass().getCanonicalName();
      return Logger.getLogger(callingClassName);
   }
}
Run Code Online (Sandbox Code Playgroud)

该代码中的"2"可能是错误的,但要点就在那里; 将性能命中(在类加载时,作为静态变量)找到类名,以便开发人员实际上没有办法输入错误或引入任何错误.

我一般不会因为在运行时防止开发人员错误而失去性能而感到兴奋,但如果它发生在单身人士身上,那么一次?通常听起来对我来说是个好交易.


Mat*_*ell 10

正如其他人所说,我会为每个类创建一个Logger:

private final static Logger LOGGER = Logger.getLogger(Foo.class);
Run Code Online (Sandbox Code Playgroud)

要么

private final Logger logger = Logger.getLogger(this.getClass());
Run Code Online (Sandbox Code Playgroud)

但是,我发现过去在记录器中包含其他信息很有用.例如,如果您有一个网站,则可以在每条日志消息中包含用户ID.这样,您可以跟踪用户正在做的所有事情(对调试问题非常有用等).

最简单的方法是使用MDC,但您可以使用为类的每个实例创建的Logger,其名称包括用户ID.

使用MDC的另一个好处是,如果使用SL4J,则可以根据MDC中的值更改设置.因此,如果您希望在DEBUG级别记录特定用户的所有活动,并将所有其他用户留在ERROR,则可以.您还可以根据MDC将不同的输出重定向到不同的位置.

一些有用的链接:

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html

http://www.slf4j.org/api/index.html?org/slf4j/MDC.html