AlikElzin-kilaka
AlikElzin-kilaka

Reputation: 36021

Why doesn't slf4j's Logger has a method that accepts both varargs for the message and an exception?

SLF4J's Logger have logging methods that either accept exception or varargs but not both.

Any idea why?

The problem with the missing signature is that sometimes I'd like to both log an exception and provide params to the message, but I don't have a method signature to do both.

Upvotes: 4

Views: 2167

Answers (2)

Michael Gantman
Michael Gantman

Reputation: 7798

Possible reason is that varargs has to be the last arg in the signature and it was complicated to add a Object parameter (which is intended for exception) followed by Object... parameter. As per answer by @Berger it appears that it was resolved in version SLF4J 1.6.0. However, I resolved the same problem differently. I wrote an Open Source library MgntUtils (available from Maven Central repository and github). One of the utilities there is extracting stacktrace from Throwable as a String. Also optionaly this utility can filter out some irrelevant parts of stacktrace and leave it very concised and easy to read format. So in this case you can pass extracted stacktrace to your logger as part of varargs. I found it very convinient aspeccially with filtered stacktrace. It would look like this:

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

Here is the link to the article that explains where to get the library and how to use it: MgntUtils Open source library Library comes with source code and javadoc

Upvotes: 0

Arnaud
Arnaud

Reputation: 17534

Referring to In the presence of an exception/throwable, is it possible to parameterize a logging statement?, you can do that since SLF4J 1.6.0, if the exception is the last argument :

Yes, as of SLF4J 1.6.0, but not in previous versions. The SLF4J API supports parametrization in the presence of an exception, assuming the exception is the last parameter. Thus,

String s = "Hello world";

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

will print the NumberFormatException with its stack trace as expected. The java compiler will invoke the error method taking a String and two Object arguments. SLF4J, in accordance with the programmer's most probable intention, will interpret NumberFormatException instance as a throwable instead of an unused Object parameter. In SLF4J versions prior to 1.6.0, the NumberFormatException instance was simply ignored.

If the exception is not the last argument, it will be treated as a plain object and its stack trace will NOT be printed. However, such situations should not occur in practice.

As an example implementation , this is the method that gets called by Logback (this method is in the class ch.qos.logback.classic.spi.EventArgUtil and gets called by 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;
}

Upvotes: 12

Related Questions