当前位置: 首页 > 知识库问答 >
问题:

使用不同格式记录两次Log4j

翟俊哲
2023-03-14

我不明白为什么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...

编辑:当我将“myAppender”appender阈值更改为“ERROR”时,显示的第二条日志消息(以时间开始的消息,而不是“INFO”)仍在生成。是否有需要禁用的默认记录器?尽管指定的appender用于“ERROR”级别的消息,但似乎仍有一些东西在记录这些“INFO”级别的消息。另外,如果我注释掉整个log4j。xml文件,第二条日志消息(以及所有类似消息)仍在记录中。我如何防止这种情况?谢谢

共有3个答案

冯良才
2023-03-14
匿名用户

我的猜测是,在应用程序的某个地方,另一个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文件之外,还会导致您在日志中看到的效果。

更新:甚至可能是类似于记录器的东西。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

包唯
2023-03-14

为什么Log4j记录两次

  • 除非您要求它不这样做(通过将加法设置为false),否则日志4J将记录到层次结构中的所有记录器,因此您可以看到com的输出。服务器记录器和始终存在的默认根记录器

上述问题的解决方案

>

  • 这是因为您尚未在com上定义additivity=“false”属性。服务器记录器。现在我修好了,你可以试试

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

  • 刘兴朝
    2023-03-14

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

    首先尝试使用下面的根记录器配置,而不是您的

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

    如果上述操作不起作用,请尝试放置

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

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

    1. 在标准输入/输出(即终端窗口)上打印
    2. 产品环境的打印文件

    我会在log4j中这样做。属性如下:

    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
    

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

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

    请注意,上面的XML配置是假设org.apache.log4j。AsyncAppender打印在一些日志文件中,但如果它没有(我猜它没有),那么上面将不起作用(如果您将AsyncAppender替换为org.apache.log4j,您仍然可以使用上面的XML配置来实现文件控制台日志记录。RollingFileAppender),我想知道为什么您不能使用org.apache.log4j。AsyncAppender直接因为它已经打印到控制台,所以可能只是使用:

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

     类似资料:
    • 问题内容: 我想在我的应用程序中将slf4j + logback用于两个目的-日志和审计。 对于日志记录,我以常规方式记录日志: 对于审计,我创建一个特殊的命名记录器并登录到它: 登录配置: 问题:通过审核记录器记录的消息出现两次-一次在AUDIT_LOGGER下,一次在根记录器下。 14:41:57.975 [main]调试com.gammay.example.Main–> main() 14:

    • 我想在我的应用程序中使用SLF4J+logback用于两个目的--日志和审计。 14:41:57.978[main]信息AUDIT_LOGGER-110欢迎使用main 如何确保审核消息在审核记录器下只出现一次?

    • 我们有一个spring批处理程序,它可以访问读卡器中的一组数据,对其进行处理和写入。这一切都是成批发生的。 我注意到,处理器和写入程序对同一数据进行了两次检查,一次作为批处理,一次作为单个记录。 例如:写入器读取1000条记录,向处理器发送1000条记录,向写入器发送1000条记录。 在此之后,记录再次被单独处理,但只调用处理器和写入器。 我们在所有读卡器、处理器和写入程序中都有日志语句,我可以看

    • 我将winston用于我的NodeJS应用程序,以获得结构化日志记录格式(JSON),稍后我将处理该格式并通过FileBeat发送到Logstash。 按照PM2和12Factor.NET的建议,我使用传输进行日志记录,并让PM2处理我的中的和。 在我的模块中,我有以下内容: 在我的主应用程序文件中,我运行以下代码来模拟抛出的未处理异常,需要一个假的依赖项,但没有找到: 最后,在我的PM2中有以下

    • 我们有两个不同的ASP.NET应用程序启用了Log4net日志记录。它们都有相同的log4net1.2.10.0版本。

    • 如何在SL4J中配置日志记录?我的项目有很多类:class1、class2、Class3....我想做两件事:将所有类记录到一个名为FILE1的文件追加器中,并具有警告级别(class1、class2、class3...)将一个名为class1的类记录到具有调试级别的名为FILE2的文件追加器中。 问题是,当我将class1的记录器配置为具有WARN级别的FILE1 appender时,我不知道如