Log4j 2未注销%throwable

问题描述

使用此基本Log4j log4j2.xml记录错误时,我想打印堆栈跟踪:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYstem_OUT">
            <PatternLayout pattern="throwable: %throwable"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="error">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

这就是我所依赖的全部内容

    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.13.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.13.3</version>
        </dependency>
    </dependencies>

运行此命令(asdf不存在)时

public class Main {
    public static void main(String[] args) {
        Logger logger = LogManager.getLogger();
        try {
            new FileInputStream("asdf");
        } catch(Exception e) {
            logger.error(e);
        }
    }
}

我的输出

throwable: 

我想要这样的东西:

throwable: java.io.FileNotFoundException: asdf (No such file or directory)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at Main.main(Main.java:10)

来自PatternLayout的文档,位于:https://logging.apache.org/log4j/2.x/manual/layouts.html#PatternLayout 认值(%throwable)应该记录整个堆栈跟踪

任何帮助都会很棒!

编辑:我正在使用Java 8

解决方法

您正在使用Logger.error(Object)。所有带有单个对象参数的日志记录方法仅记录该对象的toString()值,即使该对象是Throwable。在您的情况下,追加程序模式不包含%m / %msg / %message,因此您在控制台输出中只会看到“ throwable:”。
如果我们将消息添加到模式中,则输出为:

throwable: java.io.FileNotFoundException: asdf (The system cannot find the file specified) 

在使用Log4j2时,这是一个非常常见的陷阱,可悲的是,它出现了won't change in the future

要正确记录异常及其堆栈跟踪,您可以使用带有单独Throwable参数的记录方法之一,例如Logger.error(String,Throwable),也可以使用Logger.catching(Level,Throwable)。但是,应该首选带有message参数的日志记录方法,因为它们允许您描述上下文。否则,您可能很难找出实际创建日志消息的位置。