如何使用SLF4J记录带有占位符的异常和消息

109

如何使用SLF4J记录错误消息和异常信息的正确方法是什么?

我尝试过这样做,但异常堆栈跟踪从未被打印出来:

logger.error("无法解析数据 {}", inputMessage, e);

在这种情况下,我想要用{}填充inputMessage,并记录异常堆栈跟踪。

我唯一能想到的方法是:

logger.error("Unable to parse data " + inputMessage, e);

这不太好看。


你的第一行logger.error在slf4j版本1.7.25中按照你想要的方式工作。 - kiml42
2个回答

150
自从SLF4J 1.6版本起,SLF4J会将最后一个参数作为异常信息处理。您可能在使用旧版的SLF4J API。这一特性在FAQ中有所说明,并且在Logger的Java文档中也有提到。

8
这是否在Javadoc中有描述?我本来期望在这里找到类似的信息:http://www.slf4j.org/apidocs/org/slf4j/Logger.html。 - Scot
2
我相信你,但像@Scot一样,我希望这种行为能够被记录下来。 - Stephan
4
斯科特,@Stephan - 上述行为似乎在他们的常见问题解答中有记录这里 - Priidu Neemre
10
这就像一个最好保守的秘密。感谢你指出来。我的后续问题是,为什么他们要隐藏这个在可变参数中是可行的事实?他们为什么不能创建一个新的重载方法,在传入 Throwable 后再加上可变参数?这里是否有类型擦除问题?其他库中是否有将异常作为最后一个参数传递的标准? - gaoagong
9
这已经在常见问题解答(FAQ)中有记录:https://www.slf4j.org/faq.html#paramException。我同意应该更清晰地记录这个功能。 - Stephan202
有没有办法按照需要覆盖这种行为?我有时不想记录异常堆栈跟踪,但是通过配置而不是更改对记录器的调用来实现。 - Johny

4

http://www.slf4j.org/faq.html#paramException上得知:

是的,从SLF4J 1.6.0开始支持,但之前的版本不支持。在存在异常的情况下,SLF4J API支持参数化,假设异常是最后一个参数。因此,

String s = "Hello world";
try {
  Integer i = Integer.valueOf(s);
} catch (NumberFormatException e) {
  logger.error("Failed to format {}", s, e);
}

将按预期打印NumberFormatException及其堆栈跟踪。Java编译器将调用带有一个字符串和两个对象参数的错误方法。SLF4J将根据程序员最可能的意图,将NumberFormatException实例解释为可抛出的异常而不是未使用的对象参数。在1.6.0之前的SLF4J版本中,NumberFormatException实例被简单地忽略。

如果异常不是最后一个参数,则它将被视为普通对象,并且其堆栈跟踪将不会被打印。然而,在实践中不应该出现这种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接