简体   繁体   English

如何使用 log4j2 FileAppender 与 SLF4J API

[英]How to use log4j2 FileAppender with SLF4J API

I've been trying to follow the recipes on this site and others for how to add a log4j2 FileAppender instance to a class that's using the SLF4J API for its overall logging, and I'm not having much luck.我一直在尝试遵循本网站和其他网站上的食谱,了解如何将 log4j2 FileAppender 实例添加到使用 SLF4J API 进行整体日志记录的 class 中,但我运气不佳。 Can somebody tell me what I'm doing wrong with the following code?有人可以告诉我下面的代码我做错了什么吗?

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileAppenderTest {

    private static final Logger log = LoggerFactory.getLogger(FileAppenderTest.class);

    private final Layout<?> taskLogLayout = PatternLayout.newBuilder()
        .withPattern("%d %-5p [%t:%C{1}.%M] %m%n")
        .build();

    @Test
    public void testFileAppender() throws IOException {

        File appenderFile = new File("build/test", "file-appender.log");

        FileAppender taskLog = FileAppender.newBuilder()
            .withFileName(appenderFile.getAbsolutePath())
            .setName("file-appender.log")
            .setLayout(taskLogLayout)
            .build();
        taskLog.start();

        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration c = ctx.getConfiguration();
        LoggerConfig lc = c.getLoggerConfig("");
        lc.addAppender(taskLog, Level.ALL, null);

        log.info("Here is a test message with INFO level");
        log.warn("Here is a test message with WARN level");

        lc.removeAppender("file-appender.log");

        assertTrue(appenderFile.exists());

        List<String> logLines = FileUtils.readLines(appenderFile, (Charset) null);
        assertEquals(2, logLines.size());

    }

}

The assertTrue statement passes, so the file is created by the FileAppender, but the assertEquals fails because the length of logLines is zero (ie, the log file has no content). assertTrue 语句通过,因此文件由 FileAppender 创建,但 assertEquals 失败,因为 logLines 的长度为零(即日志文件没有内容)。

Any ideas?有任何想法吗?

Found the problem:发现问题:

In the code above, note that the Logger is obtained from the LoggerFactory prior to application of any logging configuration settings.在上面的代码中,请注意 Logger 是在应用任何日志记录配置设置之前从 LoggerFactory 获得的。 This causes the logger to have a default level of ERROR.这会导致记录器具有默认级别的 ERROR。 Thus, even though the APPENDER has a level of INFO, the LOGGER has a level of ERROR and that rejects the INFO and WARN messages before they even get to the appender!因此,即使 APPENDER 具有 INFO 级别,LOGGER 也具有 ERROR 级别,并且在 INFO 和 WARN 消息到达 appender 之前就拒绝它们!

The following code will pass all its tests.以下代码将通过所有测试。 Note that the Logger is no longer a static member and that the configuration is set to have a level of ANY before the Logger is obtained.请注意,Logger 不再是 static 成员,并且在获取 Logger 之前将配置设置为具有 ANY 级别。

package gov.nasa.ziggy.worker;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.appender.FileAppender;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.layout.PatternLayout;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileAppenderTest {

    private final Layout<?> taskLogLayout = PatternLayout.newBuilder()
        .withPattern("%d %-5p [%t:%C{1}.%M] %m%n")
        .build();

    @Test
    public void testFileAppender() throws IOException {

        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration c = ctx.getConfiguration();
        LoggerConfig lc = c.getLoggerConfig("");
        lc.setLevel(Level.ALL);

        Logger log = LoggerFactory.getLogger(FileAppenderTest.class);
        File appenderFile = new File("build/test", "file-appender.log");

        FileAppender taskLog = FileAppender.newBuilder()
            .withFileName(appenderFile.getAbsolutePath())
            .setName("file-appender.log")
            .setLayout(taskLogLayout)
            .build();
        taskLog.start();

        lc.addAppender(taskLog, Level.ALL, null);

        log.info("Here is a test message with INFO level");
        log.warn("Here is a test message with WARN level");

        lc.removeAppender("file-appender.log");

        assertTrue(appenderFile.exists());

        List<String> logLines = FileUtils.readLines(appenderFile, (Charset) null);
        assertEquals(2, logLines.size());

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM