为什么没有slf4j的Logger有一个方法接受消息的varargs和异常?

时间:2018-04-25 07:24:32

标签: java logging slf4j

SLF4J's Logger具有接受异常或varargs但不同时接受异常的记录方法。

知道为什么吗?

缺少签名的问题在于,有时我想记录异常并为邮件提供参数,但我没有方法签名来执行这两项操作。

2 个答案:

答案 0 :(得分:5)

参考In the presence of an exception/throwable, is it possible to parameterize a logging statement?,你可以这样做,因为SLF4J 1.6.0,如果异常是最后一个参数:

  

是的,从 SLF4J 1.6.0 开始,但在之前的版本中没有。 SLF4J   API支持在出现异常时进行参数化,   a ssuming异常是最后一个参数。因此,

String s = "Hello world";

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

将按预期打印NumberFormatException及其堆栈跟踪。   java编译器将调用带有String和two的错误方法   对象参数。 SLF4J,按照程序员的最多   可能的意图,将NumberFormatException实例解释为   throwable而不是未使用的Object参数。在SLF4J版本中   在1.6.0之前,只是忽略了NumberFormatException实例。

     

如果异常不是最后一个参数,则将其视为a   普通对象及其堆栈跟踪将不会被打印。但是,这样的   情况不应该在实践中发生。

作为一个示例实现,这是由 Logback 调用的方法(此方法在类ch.qos.logback.classic.spi.EventArgUtil中并由ch.qos.logback.classic.spi.LoggingEvent调用):

public static final Throwable extractThrowable(Object[] argArray) {
    if (argArray == null || argArray.length == 0) {
        return null;
    }

    final Object lastEntry = argArray[argArray.length - 1];
    if (lastEntry instanceof Throwable) {
        return (Throwable) lastEntry;
    }
    return null;
}

答案 1 :(得分:0)

可能的原因是varargs必须是签名中的最后一个arg,添加Object参数(用于异常)后面跟Object ...参数很复杂。根据@Berger的回答,它似乎已在版本SLF4J 1.6.0中得到解决。但是,我以不同方式解决了同样的问题。我写了一个开源库MgntUtils(可从Maven Central仓库和github获得)。其中一个实用程序是从Throwable中提取堆栈跟踪作为String。此外,该实用程序还可以过滤掉堆栈跟踪的一些不相关的部分,并使其非常简洁且易于阅读格式。因此,在这种情况下,您可以将提取的堆栈跟踪作为varargs的一部分传递给记录器。我发现它非常方便,特别是过滤堆栈跟踪。它看起来像这样:

LOGGER.error("My message {} {}", MyStringParam, TextUtils.getStacktrace(e));

以下是文章的链接,该文章介绍了如何获取库以及如何使用它:MgntUtils Open source library库附带源代码和javadoc