Truncating stacktraces of exceptions in logger based on condition

Viewed 2129

I'm using slf4j to log custom exceptions and their stack traces in both console and a custom file. I met a situation that I had to truncate the stack traces of some non-critical exceptions.

Using this documentation, I added the following configuration in my logback.xml file

<evaluator name="DISPLAY_EX_EVAL">
    <expression>throwable != null &amp;&amp; throwable instanceof com.abc.NonCriticalException</expression>
    </evaluator>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%-30(%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]) %-5level
                %logger{150} -%msg%n%ex{full, DISPLAY_EX_EVAL}
            </pattern>
        </encoder>
    </appender>

But, the above configuration removes all the stacktraces during logging of the configured exception. Is there a way to log the truncated stack trace (1 or 2 lines) of the matched exception ?

2 Answers

There is an open-source library (written by me) that provides smart stacktrace filtering. I use it in my own projects and it works great. Here is the article about the library: Open-Source Java Library With Stack Trace Filtering, Silent String Parsing, and Version Comparison. Look specifically for paragraph "Stack Trace Noise Filter". Basically it filters the stacktrace based on a package prefix that you set that interests you. You can find the library as Maven artifact or on the Github (including source code and javadoc). Here is Javadoc. Here is an example. Assume that your code is located in package "com.plain.*". So if you set your prefix to "com.plain." than the original stacktrace:

at com.plain.BookService.listBooks()
at com.plain.BookService$FastClassByCGLIB$e7645040.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke()
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed()
at com.plain.LoggingAspect.logging()
at sun.reflect.NativeMethodAccessorImpl.invoke0()
at sun.reflect.NativeMethodAccessorImpl.invoke()
at sun.reflect.DelegatingMethodAccessorImpl.invoke()
at java.lang.reflect.Method.invoke()
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs()
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod()
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke()
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed()
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept()
at com.plain.BookService$EnhancerByCGLIB$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

will be replaced with:

at com.plain.BookService.listBooks()
at com.plain.BookService$FastClassByCGLIB$e7645040.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke()
...
at com.plain.LoggingAspect.logging()
at sun.reflect.NativeMethodAccessorImpl.invoke0()
...
at com.plain.BookService$EnhancerByCGLIB$7cb147e4.listBooks()
at com.plain.web.BookController.listBooks()

The utility works well with entire stacktrace including "caused by" and "suppressed" parts, as well as filtering could be done on the fly (from exception itself) or from string that contains the original stacktrace

But why do you want to truncate the stacktrace at all? Why not log the full stacktrace. After all, it's important and useful information. Right?

I guess you are thinking you must log the stacktrace for all exceptions. That is a mistake. You should log a stack trace only for exceptions that indicate a bug in called code (an unexpected exception). Of course, it should be uncommon that your program logs those stack traces, and when it does, you will want the full stack trace to help you debug the problem.

Related