Log4j使用不同格式

时间:2016-08-26 15:06:48

标签: java log4j

我无法弄清楚为什么log4j会以不同的格式附加两次。有没有人遇到过这个?

这是我的log4j.xml文件:

<log4j:configuration>

    <appender name="async" class="org.apache.log4j.AsyncAppender">
    <!-- this parameter need to be set to false to avoid application from hanging. -->
        <param name="Blocking" value="false" />
        <appender-ref ref="myAppender" />
    </appender>

    <appender name="myAppender" class="org.apache.log4j.ConsoleAppender">
        <param name="Threshold" value="INFO" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{ISO8601} [%t] %c %x - %m%n" />
        </layout>
    </appender>

    <logger name="com.server">
        <level value="INFO" />
    </logger>

    <logger name="org.springframework">
        <level value="INFO" />
    </logger>

    <logger name="org.hibernate.LazyInitializationException" additivity="false">
       <level value="off" />
       <appender-ref ref="async" />
    </logger>

    <logger name="net.sf.ehcache">
        <level value="INFO" />
    </logger>

     <logger name="com.mchange">
         <level value="INFO" />
     </logger>

     <root>
         <priority value="INFO" />
         <appender-ref ref="async" />
     </root>

</log4j:configuration>

以下是一些示例输出:

INFO  2016-08-26 11:01:38,353 [main] com.server.Server  - Server started successfully...
11:01:38,353 INFO :  Server started successfully...

编辑:当我更改&#34; myAppender&#34; appender threshold to&#34; ERROR&#34;,显示的第二条日志消息(一个以时间开头,而不是&#34; INFO&#34;)仍在生成。我需要禁用一些默认记录器吗?似乎某些东西仍在记录那些&#34; INFO&#34;级别消息,即使指定的appender用于&#34; ERROR&#34;级别消息。此外,如果我注释掉整个log4j.xml文件,则仍会记录第二条日志消息(以及所有类似的消息)。我怎么能阻止这个?谢谢!

6 个答案:

答案 0 :(得分:5)

我不熟悉log4j的XML语法(我使用log4j.properties进行配置)所以这是我的2美分,试图帮助您调试和修复代码。

首先尝试使用以下根记录器配置而不是你的<appender-ref ref="async" /> -

<logger name="org.hibernate.LazyInitializationException" additivity="false">
   <level value="off" />
   <appender-ref ref="myAppender" />
</logger>
..............
...........
 <root>
     <priority value="INFO" />
     <appender-ref ref="myAppender" />
 </root>

如果以上情况不起作用,请尝试将<param name="Threshold" value="ERROR" />放在asyncmyAppender中,我想不会打印Server started successfully日志(我认为您已尝试使用myAppender

如果这有帮助,那么这意味着您尝试引用/继承记录器的方式无法正常工作或使用,因此您从这个方向思考并纠正问题,您需要阅读更多关于{{ 1}}元素和appender-ref记录器。

无论上述是否有效,我猜你正在努力实现以下目标 -

  1. 打印您的标准输入/输出,即您的终端窗口
  2. 在文件中打印以及生产环境
  3. 我会在log4j.properties中执行此操作,如下所示:

    AsyncAppender

    所以,我想你可以做如下的事情。

    log4j.logger.com.sks.cs50=DEBUG, CS50GlobalFileAppender, stdout
    
    #####CS50 Web log##########
    log4j.appender.CS50GlobalFileAppender=org.apache.log4j.RollingFileAppender
    log4j.appender.CS50GlobalFileAppender.File=${logDir}cs50.log
    log4j.appender.CS50GlobalFileAppender.MaxBackupIndex=50
    log4j.appender.CS50GlobalFileAppender.Threshold=DEBUG
    log4j.appender.CS50GlobalFileAppender.layout=org.apache.log4j.PatternLayout
    log4j.appender.CS50GlobalFileAppender.layout.ConversionPattern=%C %d [%t] [%X{randomNumber}] %-5p - %m%n
    log4j.appender.CS50GlobalFileAppender.MaxFileSize=500000KB
    
    # Log format to standard output
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.target=System.out
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d [%X{randomNumber}] %-5p - %m%n
    
    log4j.logger.org.apache = INFO
    log4j.logger.com.sun = INFO
    log4j.logger.sun = INFO
    log4j.logger.javax.xml.bind = INFO
    log4j.logger.org.springframework = INFO
    log4j.logger.com.cgi = DEBUG
    

    请注意以上的XML配置假设<log4j:configuration> <appender name="async" class="org.apache.log4j.AsyncAppender"> <!-- this parameter need to be set to false to avoid application from hanging. --> <param name="Blocking" value="false" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{ISO8601} [%t] %c %x - %m%n" /> </layout> </appender> <appender name="myAppender" class="org.apache.log4j.ConsoleAppender"> <param name="Threshold" value="INFO" /> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%-5p %d{ISO8601} [%t] %c %x - %m%n" /> </layout> </appender> <logger name="com.server"> <level value="INFO" /> </logger> <logger name="org.springframework"> <level value="INFO" /> </logger> <logger name="org.hibernate.LazyInitializationException" additivity="false"> <level value="off" /> <appender-ref ref="async" /> </logger> <logger name="net.sf.ehcache"> <level value="INFO" /> </logger> <logger name="com.mchange"> <level value="INFO" /> </logger> <root> <priority value="INFO" /> <appender-ref ref="async" /> <appender-ref ref="myAppender" /> </root> </log4j:configuration> 打印在某个日志文件中,但如果它没有(我猜它没有&#39; t)然后上面将无法工作(如果用org.apache.log4j.AsyncAppender替换AsyncAppender,你仍然可以使用上面的XML配置来实现文件+控制台记录,我想知道你为什么不能这样做直接使用org.apache.log4j.RollingFileAppender因为它已经打印到控制台,所以可能只是使用:

    org.apache.log4j.AsyncAppender

答案 1 :(得分:2)

为什么Log4j会记录两次?

  • Log4j会记录层次结构中的所有记录器,除非您不这样做    要(通过将additivity设置为false),您就会看到输出    来自您的com.server记录器和默认的ROOT记录器    永远存在。

针对上述问题的解决方案

  • 这种情况正在发生,因为你还没有定义 您的 com.server 记录器上的 additivity =&#34; false&#34; 属性。现在我修好了,你可以试试。

    <appender name="async" class="org.apache.log4j.AsyncAppender">
    <!-- this parameter need to be set to false to avoid application from hanging. -->
        <param name="Blocking" value="false" />
        <appender-ref ref="myAppender" />
    </appender>
    
    <appender name="myAppender" class="org.apache.log4j.ConsoleAppender">
        <param name="Threshold" value="INFO" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{ISO8601} [%t] %c %x - %m%n" />
        </layout>
    </appender>
    
    <logger name="com.server" additivity="false">
        <level value="INFO" />
    </logger>
    
    <logger name="org.springframework">
        <level value="INFO" />
    </logger>
    
    <logger name="org.hibernate.LazyInitializationException" additivity="false">
       <level value="off" />
       <appender-ref ref="async" />
    </logger>
    
    <logger name="net.sf.ehcache">
        <level value="INFO" />
    </logger>
    
     <logger name="com.mchange">
         <level value="INFO" />
     </logger>
    
     <root>
         <priority value="INFO" />
         <appender-ref ref="async" />
     </root>
    

答案 2 :(得分:1)

我的猜测是,在您的应用程序中的某个地方,会以编程方式添加另一个appender,可能是这样的:

package de.scrum_master.app;

import java.io.OutputStreamWriter;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public class Application {
    private static Logger log = Logger.getLogger(Application.class);

    public static void main(String[] args) throws InterruptedException {
        //log.setAdditivity(false);
        ConsoleAppender ca = new ConsoleAppender();
        ca.setWriter(new OutputStreamWriter(System.out));
        ca.setLayout(new PatternLayout("%-5p [%t]: %m%n"));
        log.addAppender(ca);
        log.info("Hello world");
        log.info("Bye world");
        Thread.sleep(1000);
    }
}

除了在类路径中找到的 log4j.xml log4j.properties 文件外,还会导致您在日志中看到的效果。

更新:或者甚至可能会调用类似Logger.getRootLogger().addAppender(ca)的内容,影响根记录器,而不仅仅是一个特定的记录器。

使用您的配置文件,这会产生以下日志输出:

INFO  [main]: Hello world
INFO  [main]: Bye world
INFO  2016-09-04 13:48:25,887 [main] de.scrum_master.app.Application  - Hello world
INFO  2016-09-04 13:48:25,889 [main] de.scrum_master.app.Application  - Bye world

答案 3 :(得分:1)

已经有了一些答案,所以我继续创建了一个程序来证明这确实有效,除非你的代码中存在一些问题 - 请参阅下面的两个简单类,并尝试找出这些和你的之间的区别

import org.apache.log4j.xml.DOMConfigurator;

import com.server.Test;

public class MyListener {
public static void main(String[] args) {

    DOMConfigurator.configure("/home/sanjeevd/depot/bas/projects/xxx.1/yyy/src/log4j.xml");

    Test test = new Test();
}

}

package com.server;

import org.apache.log4j.Logger;

public class Test {

private static Logger logger = Logger.getLogger(Test.class);

public Test() {
    logger.info("PRINTTTTTTTTTTTT");
}

}

还要在log4j.xml的顶部添加这两行 -

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

话虽如此,我很确定有一些其他记录器已经初始化或者你的应用程序中有多个lo4j.xml等。请注意,我没有更改log4j.xml中的任何内容而不是添加标题。

输出低于(并打印出来) -

INFO  2016-09-06 10:57:37,506 [main] com.server.Test  - PRINTTTTTTTTTTTT

你应该做的另一件事是为引导程序调试设置“系统属性”,看看在log4j级别发生了什么,即放

System.setProperty("log4j.debug", "true");

在配置log4j之前。如果要将它部署到某个servlet容器(tomcat等)上,那么在启动期间传递-Dlog4j.debug = true参数。

我的案例中的输出是 -

log4j: Trying to find [log4j.xml] using context classloader   sun.misc.Launcher$AppClassLoader@42a57993.
log4j: Using URL [file:/home/sanjeevd/depot/bas/projects/xxx.1/yyy/bin/log4j.xml] for automatic log4j configuration.
log4j: Preferred configurator class: org.apache.log4j.xml.DOMConfigurator
log4j: System property is :null
log4j: Standard DocumentBuilderFactory search succeded.
log4j: DocumentBuilderFactory is: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
log4j: debug attribute= "null".
log4j: Ignoring debug attribute.
log4j: reset attribute= "false".
log4j: Threshold ="null".
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [com.server] additivity to [true].
log4j: Level value for com.server is  [INFO].
log4j: com.server level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [org.springframework] additivity to [true].
log4j: Level value for org.springframework is  [INFO].
log4j: org.springframework level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [org.hibernate.LazyInitializationException] additivity to [false].
log4j: Level value for org.hibernate.LazyInitializationException is  [off].
log4j: org.hibernate.LazyInitializationException level set to OFF
log4j: Class name: [org.apache.log4j.AsyncAppender]
log4j: Attaching appender named [myAppender] to appender named [async].
log4j: Class name: [org.apache.log4j.ConsoleAppender]
log4j: Setting property [threshold] to [INFO].
log4j: Setting property [target] to [System.out].
log4j: Parsing layout of class: "org.apache.log4j.PatternLayout"
log4j: Setting property [conversionPattern] to [%-5p %d{ISO8601} [%t] %c %x - %m%n].
log4j: Adding appender named [async] to category [org.hibernate.LazyInitializationException].
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [net.sf.ehcache] additivity to [true].
log4j: Level value for net.sf.ehcache is  [INFO].
log4j: net.sf.ehcache level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [com.mchange] additivity to [true].
log4j: Level value for com.mchange is  [INFO].
log4j: com.mchange level set to INFO
log4j: Level value for root is  [INFO].
log4j: root level set to INFO
log4j: Adding appender named [async] to category [root].
log4j: System property is :null
log4j: Standard DocumentBuilderFactory search succeded.
log4j: DocumentBuilderFactory is: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
log4j: debug attribute= "null".
log4j: Ignoring debug attribute.
log4j: reset attribute= "false".
log4j: Threshold ="null".
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [com.server] additivity to [true].
log4j: Level value for com.server is  [INFO].
log4j: com.server level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [org.springframework] additivity to [true].
log4j: Level value for org.springframework is  [INFO].
log4j: org.springframework level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [org.hibernate.LazyInitializationException] additivity to [false].
log4j: Level value for org.hibernate.LazyInitializationException is  [off].
log4j: org.hibernate.LazyInitializationException level set to OFF
log4j: Class name: [org.apache.log4j.AsyncAppender]
log4j: Attaching appender named [myAppender] to appender named [async].
log4j: Class name: [org.apache.log4j.ConsoleAppender]
log4j: Setting property [threshold] to [INFO].
log4j: Setting property [target] to [System.out].
log4j: Parsing layout of class: "org.apache.log4j.PatternLayout"
log4j: Setting property [conversionPattern] to [%-5p %d{ISO8601} [%t] %c %x - %m%n].
log4j: Adding appender named [async] to category [org.hibernate.LazyInitializationException].
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [net.sf.ehcache] additivity to [true].
log4j: Level value for net.sf.ehcache is  [INFO].
log4j: net.sf.ehcache level set to INFO
log4j: Retreiving an instance of org.apache.log4j.Logger.
log4j: Setting [com.mchange] additivity to [true].
log4j: Level value for com.mchange is  [INFO].
log4j: com.mchange level set to INFO
log4j: Level value for root is  [INFO].
log4j: root level set to INFO
log4j: Adding appender named [async] to category [root].

答案 4 :(得分:0)

我认为将 additivity =“false”添加到 com.server 记录器可以解决问题。

    <logger name="com.server" additivity="false">
        <level value="INFO" />
    </logger>

https://logging.apache.org/log4j/2.x/manual/configuration.html#Additivity

答案 5 :(得分:0)

问题解决了,我必须这样做:

<logger name="com.server" additivity="false">
    <level value="INFO" />
    <appender-ref ref="async" />
</logger>