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

log4j2:并行测试时的空日志文件

谢海阳
2023-03-14
Logger logger = (Logger) LogManager.getLogger(loggerName);
Appender appender = FileAppender.newBuilder()
            .withAppend(false)
            .withBufferedIo(true)
            .withFileName(DIR_NAME + File.separator + loggerName + ".log")
            .withIgnoreExceptions(false)
            .withImmediateFlush(true)
            .withLocking(false)
            .withLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss.SSS}  [%-5level] %msg%n").withCharset(Charset.forName("UTF-8")).build())
            .withName(loggerName)
            .build();

    appender.start();
    logger.addAppender(appender);

我怀疑缓存有问题。第一个文件附加器保存所有缓存以供写入,因此第二个文件附加器无法写入。我说的对吗?对此有什么解决办法?

谢谢你。

共有1个答案

谢骏奇
2023-03-14

您应该可以在不使用编程配置的情况下实现您想要的。不以编程方式配置log4j2的原因有很多,但在我看来,最好的一个原因是这样做会使代码依赖于log4j2中不属于公共API的方面。这意味着,如果log4j2的实现发生了变化,那么您的代码也必须发生变化。从长远来看,这为您创造了更多的工作。

因此,考虑到这一点,我将提供一个演示,演示如何使用XML配置文件设置log4j2,以便为每个测试生成单独的日志。由于您的问题中没有指定,我假设您的目标是为每个带有test注释的方法创建一个日志,并且这些方法中的每个方法都是并行执行的。

首先,这里是我的TestNG类:

package testpkg;

import java.lang.reflect.Method;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
import org.testng.annotations.BeforeMethod;
import org.testng.annotathtml" target="_blank">ions.Test;

public class NewTest {
    private static final Logger log = LogManager.getLogger();

    @BeforeMethod
    public void setThreadName(Method method){
        ThreadContext.put("threadName", method.getName());
    }

    @Test
    public void test1() {
        log.info("This is the first test!");
        log.warn("Something may be wrong, better take a look.");
    }

    @Test
    public void test2() {
        log.info("Here's the second test!");
        log.error("There's a problem, better fix it");
    }
}

正如您在这里看到的,我有两个test方法和一个名为setThreadNameBeforeMethod。显然,setThreadName方法是在每个test方法之前执行的。它使用将要运行的方法的名称将一个名为ThreadName的键放入log4j2ThreadContext中。这将用作log4j2配置文件中日志文件名的一部分。

下面是log4j2.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Routing name="MyRoutingAppender">
            <Routes pattern="$${ctx:threadName}">
                <Route>
                    <File
                        fileName="logs/${ctx:threadName}.log"
                        name="appender-${ctx:threadName}"
                        append="false">
                        <PatternLayout>
                            <Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
                        </PatternLayout>
                    </File>
                </Route>
            </Routes>
        </Routing>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="testpkg" level="TRACE" additivity="false">
            <AppenderRef ref="STDOUT" />
            <AppenderRef ref="MyRoutingAppender" />
        </Logger>
        <Root level="WARN">
            <AppenderRef ref="STDOUT" />
        </Root>
    </Loggers>
</Configuration>

正如您所看到的,我已将配置文件设置为使用RoutingAppender在运行时根据ThreadContextThreadName动态生成附加文件,并且ThreadName还在FileAppenderFileName属性中使用了RoutingAppender

下面是我的testNG配置文件:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="My suite" parallel="methods" thread-count="5" verbose="1">
  <test name="testpkg" >
    <classes>
       <class name="testpkg.NewTest" />
    </classes>
  </test>
</suite>

正如您在这里所看到的,我已经对它进行了设置,使类中的每个test方法并行运行。

执行时,将产生以下控制台输出:

[RemoteTestNG] detected TestNG version 6.14.3
[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-2] Here's the second test!
[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-1] This is the first test!
[2018-05-04T21:54:54,709][WARN ][TestNG-test=testpkg-1] Something may be wrong, better take a look.
[2018-05-04T21:54:54,709][ERROR][TestNG-test=testpkg-2] There's a problem, better fix it

===============================================
My suite
Total tests run: 2, Failures: 0, Skips: 0
===============================================

test1.log:

[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-1] This is the first test!
[2018-05-04T21:54:54,709][WARN ][TestNG-test=testpkg-1] Something may be wrong, better take a look.

test2.log:

[2018-05-04T21:54:54,703][INFO ][TestNG-test=testpkg-2] Here's the second test!
[2018-05-04T21:54:54,709][ERROR][TestNG-test=testpkg-2] There's a problem, better fix it

因此,我们在这里看到,正如预期的那样,第一个方法的日志转到test1.log,第二个方法的日志转到test2.log

 类似资料:
  • 我在我的项目中使用log4j2,如下所示: 我的配置文件如下所示: 它创建了我的文件,我在其中记录了一些东西,但它仍然是空的。当我试图删除这个文件时,操作系统告诉我它正在使用中(若应用程序正在工作),但即使我停止应用程序,文件仍然是空的。 那么,我应该更改哪些设置以使其正常工作?

  • 我按照这里的教程SpringEureka教程创建了一个基本的Eureka注册表jar应用程序。下一步是将日志记录更改为log4j2,这样我就可以使用Spring log4j2指南中的指南获得一个滚动文件。 我遇到的问题是,当我运行应用程序时,没有抛出错误,但是 eureka服务器日志仍会输出到控制台 已创建自定义日志输出文件“eureka.log”,但该文件为空 我编写的任何自定义日志,例如

  • 我正在研究Wildfly 9/10。我使用定制的Log4j2配置文件编写了web应用程序。 配置文件正确地包含在war jar库中。 结果是,当我运行web应用程序时,它会生成以下文件: 但它继续在服务器控制台上打印日志,而文件保持为空。 相同的配置在独立应用程序上正常工作。我错过了什么? 更新当我部署我的应用程序时,服务器会打印以下调试级别信息:

  • 我最近升级到了log4j2,发现当java进程启动并初始化log4j上下文时,log4j为我的所有滚动文件追加器创建了空日志文件。因此,即使我的一些作业线程没有运行,它们也会为相关appender创建空日志文件。 有没有办法将日志文件的创建推迟到触发第一个LogEvent的时间? 附言-我见过如何让log4j仅按需创建日志文件?但它没有多大帮助。

  • 我希望由log4j2创建的日志文件在其文件名中包含日期模式,包括当前活动文件。也就是说,如果今天的日期是2016-12-15,我希望当前日志文件是lager-2016-12-15.log。当日期改变时,我希望创建一个名为lager-2016-12-16.log的新文件。 使用,我无法使当前活动日志文件的文件名中具有日期模式。我的log4j2.xml: 使用此配置,翻转时的复制被搞乱了。从fileN

  • 我有以下控制台附加器; 问题是我在这里使用的模式输出了一个空的ThreadContext()。我不想使用特定的密钥名称(例如,),因为系统非常广泛,密钥集也不同。示例输出: 2017-09-26 10:39:55396[main]信息:启动内部HTTP客户端{}