'Springboot stack-trace logging filter only from my packages

I'm using Springboot with the sl4j-api 1.7.2.

Is there a way to filter out from stack-traces only the lines starting with my packages, or excluding from the log file lines coming from spring framework or other libraries that I use.

This would simplify reading the log file, and reduce enormously the space required for log files. In more than 99% of the cases, the errors are in my code, not in the libs I use.

I wanted to see if there are any consolidated solutions before embarking in my onw, home made remedies.

Eg. This 30+ lines long stack-trace

2020-12-18 03:59:40,179 [SimpleAsyncTaskExecutor-2] ERROR RestCommunicatorImpl - sort
com.my.package.exception.AlreadyRunningException: Already running
    at com.my.package.impl.RestCommunicatorImpl.validate(RestCommunicatorImpl.java:244) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl.spawn(RestCommunicatorImpl.java:200) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestOrchestratorImpl.onAction(RestCommunicatorImpl.java:819) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl.sort(RestCommunicatorImpl.java:561) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl$$FastClassBySpringCGLIB$$db5641d3.invoke(<generated>) [classes!/:0.6.0-SNAPSHOT]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738) [spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) [spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) [spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) [spring-tx-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) [spring-aop-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at com.ge.og.rmd.analytics.kernel.boot.orchestrator.impl.RestOrchestratorImpl$$EnhancerBySpringCGLIB$$f68bccb1.sortRuntime(<generated>) [classes!/:0.6.0-SNAPSHOT]
    at com.ge.og.rmd.analytics.kernel.boot.amqp.consumer.ConsumerManager.processCommandOutMessage(ConsumerManager.java:622) [classes!/:0.6.0-SNAPSHOT]
    at sun.reflect.GeneratedMethodAccessor268.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_222]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_222]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:180) [spring-messaging-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:112) [spring-messaging-4.3.8.RELEASE.jar!/:4.3.8.RELEASE]
    at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:49) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:126) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:106) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:822) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:745) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:97) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:189) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1276) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:726) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1219) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1189) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1500(SimpleMessageListenerContainer.java:97) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1421) [spring-rabbit-1.7.2.RELEASE.jar!/:na]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_222]

Sould be 7 rows

2020-12-18 03:59:40,179 [SimpleAsyncTaskExecutor-2] ERROR RestCommunicatorImpl - sort
com.my.package.exception.AlreadyRunningException: Already running
    at com.my.package.impl.RestCommunicatorImpl.validate(RestCommunicatorImpl.java:244) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl.spawn(RestCommunicatorImpl.java:200) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestOrchestratorImpl.onAction(RestCommunicatorImpl.java:819) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl.sort(RestCommunicatorImpl.java:561) ~[classes!/:0.6.0-SNAPSHOT]
    at com.my.package.impl.RestCommunicatorImpl$$FastClassBySpringCGLIB$$db5641d3.invoke(<generated>) [classes!/:0.6.0-SNAPSHOT]

Thanks.



Solution 1:[1]

There is an Open source library MgntUtils (written by me) that does exactly what you are asking - smart stacktrace filtering. Here is Javadoc for TextUtils Class

All you will you will have to do is this:

try {
...
} catch(Exception e) {
  logger.info("your message {}", TextUtils.getStacktrace(e, true, "com.my.package.");
}

Also if you anywhere in your code will invoke just once TextUtils.setRelevantPackage("com.my.package."); than instead of using TextUtils.getStacktrace(e, true, "com.my.package."); you can just use TextUtils.getStacktrace(e);. All the versions of the method TextUtils.getStacktrace(...) return stacktrace as a string that may be filtered or unfiltered. You can get the library as maven artifacts or on the Github including source code and Javadoc. You can read an article describing the library here: MgntUtils Open Source Java library with stack trace filtering, Silent String parsing, Unicode converter and Version comparison. Note that the article describes most but not all features of the library

Solution 2:[2]

For maintenance purpose, a better practice is to let the code as is, and to perform the filtering using the logger. This also reduces the number of required dependencies as compared to Michael Gantman solution.

Logback for instance has such a feature that you can configure in your logback.xml file with "%rEx{}"

Relevant SO resource: Logback - filtering stack trace

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Julien