Java 根据测试配置,将logback.xml配置为在一个文件中或在每个测试的单独文件中输出所有日志消息

Java 根据测试配置,将logback.xml配置为在一个文件中或在每个测试的单独文件中输出所有日志消息,java,logging,junit,logback,Java,Logging,Junit,Logback,我有五个JUnit测试要在一个循环中运行。(了解JUnit参数化,但暂时不使用) 我想要的是,在运行测试之前,它会检查配置文件,其中有一个选项可以选择separeLogFile=true/false。如果该选项为true,则测试应为每个测试生成单独的日志文件,如果该选项为false,则仅为所有五个测试生成一个日志文件 我正在使用logback.xml和SL4J记录器进行日志记录。目前,它只为所有测试生成一个日志文件 我很困惑如何根据选项以编程方式指定日志文件应该生成在哪个位置?是否有任何方法可以

我有五个JUnit测试要在一个循环中运行。(了解JUnit参数化,但暂时不使用)

我想要的是,在运行测试之前,它会检查配置文件,其中有一个选项可以选择
separeLogFile=true/false
。如果该选项为true,则测试应为每个测试生成单独的日志文件,如果该选项为false,则仅为所有五个测试生成一个日志文件

我正在使用
logback.xml
和SL4J记录器进行日志记录。目前,它只为所有测试生成一个日志文件

我很困惑如何根据选项以编程方式指定日志文件应该生成在哪个位置?是否有任何方法可以指定两个文件名和位置,并根据配置文件中的选项从中进行选择?我第一次使用了
logback.xml

当前我的
logback.xml
如下所示:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        </pattern>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </encoder>
</appender>


<appender name="FILE"
          class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy
            class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- Daily rollover -->
        <fileNamePattern>target/logs/Log_Test_%d{yyyy-MM-dd}.log
        </fileNamePattern>

        <!-- Keep 7 days' worth of history -->
        <maxHistory>7</maxHistory>
    </rollingPolicy>

    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        </pattern>
    </encoder>
</appender>

<!-- Configure so that it outputs to both console and log file -->
<root level="INFO">
    <appender-ref ref="FILE"/>
    <appender-ref ref="STDOUT"/>
</root>


%d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg%n
信息
target/logs/Log_Test_uu%d{yyyy-MM-dd}.Log
7.
%d{HH:mm:ss.SSS}[%thread]-5级别%logger{36}-%msg%n

您可以使用Logback将日志定向到特定的日志文件

下面是一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>
                %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
            </Pattern>
        </layout>
    </appender>

    <appender name="SIFTER" class="ch.qos.logback.classic.sift.SiftingAppender">
        <discriminator>
            <key>testName</key>
            <defaultValue>ALL</defaultValue>
        </discriminator>
        <sift>
            <appender name="FILE-${testName}" class="ch.qos.logback.core.FileAppender">
                <file>target/logs/Log_Test_${testName}.log</file>

                <encoder>
                    <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
                    </pattern>
                </encoder>
            </appender>
        </sift>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="SIFTER"/>
    </root>

</configuration>
。。。将导致填充两个日志文件:

~/dev/code/stackoverflow/target/logs$ cat Log_Test_one.log 
09:04:19.922 [main] INFO  SomeClassTest - This message should go into the log file for one
~/dev/code/stackoverflow/target/logs$ cat Log_Test_two.log 
09:04:19.938 [main] INFO  SomeClassTest - This message should go into the log file for two
~/dev/code/stackoverflow/target/logs$ cat Log_Test_ALL.log 
09:06:54.009 [main] INFO  SomeClassTest - This message should go into the log file for one
09:06:54.022 [main] INFO  SomeClassTest - This message should go into the log file for two
下面的代码

String[] testNames = new String[] { "one", "two"};

for (String testName : testNames) {
    MDC.put("testName", testName);
    logger.info("This message should go into the log file for {}", testName);
}
String[] testNames = new String[] { "one", "two"};

for (String testName : testNames) {
    logger.info("This message should go into the log file for {}", testName);
}
。。。将导致填充一个日志文件:

~/dev/code/stackoverflow/target/logs$ cat Log_Test_one.log 
09:04:19.922 [main] INFO  SomeClassTest - This message should go into the log file for one
~/dev/code/stackoverflow/target/logs$ cat Log_Test_two.log 
09:04:19.938 [main] INFO  SomeClassTest - This message should go into the log file for two
~/dev/code/stackoverflow/target/logs$ cat Log_Test_ALL.log 
09:06:54.009 [main] INFO  SomeClassTest - This message should go into the log file for one
09:06:54.022 [main] INFO  SomeClassTest - This message should go into the log file for two
因此,如果在调用
logger.xxx()
之前填充
testName
MDC属性,那么日志事件将被筛选,即定向到以该MDC值命名的日志文件。如果不填充
testName
MDC属性,则所有日志事件都将被定向到“all”日志文件

更新1回应此评论:


嗯,我用您提供的那个文件追加器对我的原始文件追加器的整个块进行了回复,但它根本没有生成日志文件..出现了一些问题

在不查看所有配置的情况下很难诊断出发生了什么问题,因此我更新了此答案,以包含完整的
logback.xml
,并且此配置已启用调试,因此您应该可以看到如下输出

09:59:32,268 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [SIFTER]
09:59:32,281 |-INFO in ch.qos.logback.core.joran.action.NestedComplexPropertyIA - Assuming default type [ch.qos.logback.classic.sift.MDCBasedDiscriminator] for [discriminator] property
09:59:32,298 |-INFO in ch.qos.logback.classic.joran.action.RootLoggerAction - Setting level of ROOT logger to INFO
09:59:32,298 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [STDOUT] to Logger[ROOT]
09:59:32,304 |-INFO in ch.qos.logback.core.joran.action.AppenderRefAction - Attaching appender named [SIFTER] to Logger[ROOT]
...
09:59:34,725 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - About to instantiate appender of type [ch.qos.logback.core.FileAppender]
09:59:34,730 |-INFO in ch.qos.logback.core.joran.action.AppenderAction - Naming appender as [FILE-one]
...
09:59:34,732 |-INFO in ch.qos.logback.core.FileAppender[FILE-one] - File property is set to [target/logs/Log_Test_one.log]

。。。这显示了正在运行的筛选附加器。

谢谢您的小故障。这可能正是我要找的。当我写这个筛选追加器时,我要删除文件追加器吗?如果不是的话,我怎么能同时写这两个呢?我两个都写了,但都没用!SiftingAppender包装了FileAppender,因此不需要单独的FileAppender。你可以用我提供的例子;它按原样工作。我建议从我的示例开始,一旦它起作用,然后根据需要更改筛选Appender中的FileAppender。我用您提供的文件Appender替换了我原始文件Appender的整个块,但它根本不会生成日志文件。出现了一些问题。我用完整的logback.xml更新了答案,请尝试并阅读答案的最后一部分,其中描述了Logback的调试输出。Glitch,我发现它总是接受Key的defaultValu,而不是变量TestName,例如so MDC.put(“tesName”,Integer.toString(test));它不起作用。test对我来说是一个整数,因此将其转换为字符串。。