log4j记录两次

时间:2011-04-18 06:33:12

标签: logging log4j

我正在使用log4j来记录错误和其他系统信息。但是在INFO级别记录两次信息。

public static void main(final String... args) throws Exception {

    LOGGER.info("program started");
    try {
        // try body codes
    } catch (Exception ex) {
        LOGGER.info("program start-up failed.",ex);
    }
}

然而,当程序启动或失败时,记录两次的信息,任何人都可以帮助我找到可能的原因。

9 个答案:

答案 0 :(得分:90)

看起来您的消息由根记录器记录一次,并且由特定记录器再次记录,因为您可能已配置两个appender(可能位于不同的位置 - 在属性文件中,然后在代码中)。

这可以通过在记录器上将 additivity 设置为false来解决。 Log4j manual在Appenders和Layout部分提到了可加性。检查出来

答案 1 :(得分:33)

同意亚特兰蒂斯。

log4j.rootCategory=INFO, console
log4j.logger.org.hibernate=INFO

以上属性设置将导致双重记录。

但是添加

log4j.additivity.org.hibernate=false

解决了这个问题。

查看本书第62页。 http://books.google.com/books?id=hZBimlxiyAcC&printsec=frontcover#v=onepage&q&f=false

答案 2 :(得分:30)

对于那些使用XML格式:

<logger name="package.class" additivity="false">
    <level value="info" />
    <appender-ref ref="file" />
    <appender-ref ref="console" />
</logger>

注意:默认情况下,记录器的可加性标志设置为true。

答案 3 :(得分:4)

只需添加

即可
logger.setadditivity(false);

代码(Reference)。

我们在控制台中有双重结果,这是因为appenders不是单例,它们是附加的。意思是,类别从其祖先继承所有appender(默认情况下)。如果我们将一个appender添加到一个类别并且它写入与其他appender相同的底层流(控制台,相同的文件等),则相同的日志消息将在日志中出现两次(或更多)。此外,如果层次结构中的两个类别配置为使用相同的appender名称,则Log4j将向该appender写入两次。为该类别配置

答案 4 :(得分:2)

如果您可以使用Java调试器运行程序,请在程序中放置一个断点,其中会发生其中一个双重日志记录调用。

检查调试器中的logger对象。如果它是org.apache.log4j.Logger(v 1.2.x),那么它可能有一个AppenderAttachableImpl。您可以查询AppenderAttachableImpl以获取appender列表。

如果你找到超过1个appender,这可能是问题 - 并且修复它的线索。

答案 5 :(得分:0)

调整additivity属性的一种可能的替代方法是检查从最具体到最通用的记录器。在下面的示例中,我们希望在控制台中看到foo.bar.LoggingExampleClass中发生的任何日志事件的双重日志记录。从foo.bar.LoggingExampleClass Logger中删除额外的Console appender是安全的,因为它已被Root记录器覆盖。

<Logger name="foo.bar.LoggingExampleClass" level="DEBUG">
  <AppenderRef ref="Console" />   <!-- THIS APPENDER COULD BE REMOVED -->
  <AppenderRef ref="FooBarPackageLogging" />
</Logger>

<Root level="WARN">
  <AppenderRef ref="Console" />
  <AppenderRef ref="MainLogFile" />
</Root>

可加性调整方法和追加器调整方法存在权衡。关闭可加性可能会无意中阻止使用所需的通用级别记录器的appender。在上面的示例中,在foo.bar.LoggingExampleClass Logger上设置additivity="false"属性意味着日志记录事件不会附加到Root记录器中引用的MainLogFile。

另一方面,如果更改父appender而不检查对更细粒度记录器的影响,则依赖父appender可能会有问题。例如,假设需要将foo.bar.LoggingExampleClass日志记录事件写入控制台。由于可加性,它们目前处于上面的示例配置中,即使删除了foo.bar.LoggingExampleClass Logger的Console appender也是如此。但是,如果在没有任何其他调整的情况下也从Root记录器中删除了Console appender,则将不再满足该要求。

答案 6 :(得分:0)

我遇到了同样的问题,并通过从根记录器中删除所有附加程序来解决。 我不知道为什么,但是解决了我的问题,然后分享:

        // Root
    rootLogger = Logger.getRootLogger();
    rootLogger.removeAllAppenders(); // Solve my problem
        // CSV
    csvLogger = rootLogger.getLogger("csvLogger");
        // Txt
    txtLogger = rootLogger.getLogger("txtLogger");

每当我使用csvLogger或txtLogger登录时,甚至没有将多余的行设置为false,就将其记录两次。

答案 7 :(得分:0)

在您的resources/log4.properties文件中。

在该配置文件中,如果您有“ log4j.rootLogger= DEBUG, file”,则不要包含“ log4j.logger.org.springframework=DEBUG, file”。只需保留log4j.rootLogger部分。

答案 8 :(得分:0)

如果您不喜欢使用“可加性”功能,这是另一种选择。

在我的情况下(也是大多数情况下,也是这样),根记录器位于此附加日志的后面,并且您的配置中还有另一个高级记录器,诸如此类

  <Loggers>
    <Logger name="com.foo.Bar" level="trace">
      <AppenderRef ref="Console"/>
    </Logger>
    <Root level="error">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>

这将导致日志重复,并且如果您从该配置文件中完全删除了根记录器,log4j将强制使用默认的根记录器,请选中this note

如果

Log4j找不到配置文件,它将提供默认配置。 DefaultConfiguration类中提供的默认配置将进行设置:

附加到根记录器的ConsoleAppender

已将PatternLayout设置为附加到ConsoleAppender的模式“%d {HH:mm:ss.SSS} [%t]%-5level%logger {36}-%msg%n”

请注意,默认情况下,Log4j会将根记录程序分配给Level.ERROR。

如果您想覆盖默认的根记录器并强制其不记录,请按如下所示从您的配置文件中删除它的Appender :

<Root level="error">
</Root>

这只是另一个选项,但是,我喜欢使用推荐的方法,并为子记录器设置“ additivity”属性

<Logger name="com.foo.Bar" level="trace" additivity="false">
  <AppenderRef ref="Console"/>
</Logger>