La Chamelle
La Chamelle

Reputation: 2967

Log exception and parameters

I use sl4j-api 1.7.2 with slf4j-log4j12.

I would like to log something like this:

22:52:27,345 WARN [class] Failed to load user 1 - Reason : javax.ejb.EJBException: javax.persistence.NoResultException: No entity found for query at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:166) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:230) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final] at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:304) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final] ... fullstackTrace

So I tried

try {
            //...
        } catch (Exception e) {
            logger.warn("Failed to load User {} - Reason : {}", userId, e);
        }

Or

try {
               // ...
            } catch (Exception e) {
                logger.warn("Failed to load User {} - Reason : ", userId, e);
            }

But none of this two solutions work

The first try give :

Failed to load User 4 - Reason : javax.ejb.EJBException: javax.persistence.NoResultException: No entity found for query

The second :

Failed to load User 4 - Reason :

Is it possible to made it ?

Thanks.

Upvotes: 2

Views: 2781

Answers (2)

Eugene Maysyuk
Eugene Maysyuk

Reputation: 3378

This might be not obvious, but with Slf4J it's possible to attach exception to the log event if exception passed as a last argument.

Example:

logger.error("Parameterized msg {} {} {}", 1, 2, 3, exception)

Output (JSON Appender in my case):

{"message":"Parameterized msg 1 2 3","logger_name":"com.may.Main$","stack_trace":"java.lang.Exception: My Exception\n\tat com.may.Main$.main(Main.scala:34)\n\tat com.may.Main.main(Main.scala)\n","application":"app1","environment":"ENV"}

Docs:

https://www.slf4j.org/faq.html#paramException

Upvotes: 0

Anthony Accioly
Anthony Accioly

Reputation: 22461

Check the Logger API and the SL4J FAQ. You are probably using a SL4J version prior to 1.6.0 in which e will be interpreted as a simple object (i.e., SL4J will call e.toString()) if you have a parameter placeholder or ignored if you don't.

As for why it is using a version different than 1.7.2, a previous version is probably included in your Application Server Classpath and getting loaded before you even start your application.

You can either try to fix the Classloading problem or workaround the old version behavior.

If you choose the latter path, from the overloaded versions you need either the warn(String msg, Throwable t)) version that auto expands the stacktrace:

logger.warn("Failed to load User " + userId + " - Reason",  e);

Or the warn(String format, Object arg1, Object arg2) one with code that expands the stacktrace for you.

if (logger.isWarnEnabled()) {
   StringWriter sw = new StringWriter();
   PrintWriter pw = new PrintWriter(sw);
   e.printStackTrace(pw);
   String expanded = sw.toString(); // stack trace as a string
   logger.warn("Failed to load User {} - Reason : {}", userId, expanded);
}

Upvotes: 3

Related Questions