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

如何将log4j2 FileAppender与SLF4J API一起使用

笪煌
2023-03-14

我一直在尝试遵循这个网站和其他网站上的食谱,了解如何将log4j2 FileAppender实例添加到使用SLF4J API进行整体日志记录的类中,但我运气不佳。有人能告诉我下面的代码哪里出错了吗?

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());

    }

}

assertTrue语句通过,因此文件由FileAppender创建,但assertEquals失败,因为日志线的长度为零(即日志文件没有内容)。

有什么想法吗?

共有1个答案

亢仰岳
2023-03-14

发现问题:

在上面的代码中,请注意,记录器是在应用任何日志配置设置之前从LoggerFactory获得的。这会导致记录器出现默认错误级别。因此,即使APPENDER具有一定级别的信息,记录器也具有一定级别的错误,并且在信息和警告消息到达APPENDER之前拒绝它们!

以下代码将通过所有测试。请注意,记录器不再是静态成员,配置设置为在获取记录器之前具有任何级别。

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());

    }

}
 类似资料:
  • 我在Ubuntu 14.04中安装了phpbrew以使用PHP5.4。它工作得很好,但当我尝试使用composer时除外,composer会忽略phpbrew并安装与PHP5.5相关的依赖项。 有没有办法强制composer与phpbrew config兼容?我试图在我的作曲家中添加:php:“5.4”。json,但是它说这个要求在我的php版本中是不可能的。

  • 我是Micronaut框架的新手,我正在尝试使用entitymanager创建我的存储库。我这样创建了我的存储库 我使用这个类实现接口并注入entitymanager 问题是我一直有这个错误: PS:我已经启用了注释处理

  • 我正在尝试将composer与我的WampServer一起使用。 我所有文件的路径都是,但当我运行composer时,它会将供应商文件和其他东西安装到其他地方。 我甚至不知道我的项目在哪里,我也不能改变我的项目在哪里的路径。我已经尝试了所有的方法,但它似乎仍然没有在我的项目文件夹中安装供应商文件。

  • API level 28和Google建议使用registerNetworkCallback(NetworkRequest,PendingIntent)不推荐CONNECTIVITY\u操作。 我尝试使用ConnectionManager注册了registerNetworkCallback。NetworkCallback和它的工作,但我想使用PendingContent。 让我困惑的是公共空寄存器

  • 问题内容: 当我尝试将Webpack与简单的Express服务器一起使用时,总是会收到大量错误消息: express.js 我得到所有这些错误: 这是我的配置文件: 我该怎么办,我还需要在服务器端使用webpack。 我像这样运行express.js文件: 问题答案: 我最终要做的是,我使用了两种不同的配置,一种用于使用webpack将服务器内容打包在一起,另一种用于将所有浏览器内容打包在一起,并

  • 我有两个多对多关系的实体。 在类角色中: java.lang.StackOverflowError:空 我该如何解决这个问题?我在Stackoverflow上看到了类似的问题,但我没有找到真正有效的解决方案。 Upd:抛出异常的位置:

  • 我真的不明白我应该从< code>trackBy返回什么。根据我在网上看到的一些例子,我应该返回对象的一些属性值。对不对?为什么我应该获取< code>index作为参数? 例如在以下情况下: 组件.组件. ts 组件.模板.html 尽管名称未更改,此模板中显示的对象仍会更新。为什么?

  • 我看到了很多关于Kryo是否可以用来替换RMI所使用的默认JVM序列化的问题,但没有关于如何实际设置它的问题。我听说Kryo是JVM序列化的“插入式”替换,不确定这是否意味着您可以从运行时类路径中交换一些JAR(就像SLF4J绑定等的情况一样),或者其他东西。 所以我要问:如何使用Kryo而不是Java附带的默认JVM序列化来获得RMI?提前道谢!