AppException stack traces are not informative.
Current behaviour
When we wrap an exception inside AppException and the exception object is logged, inner stack trace is not populated by default.
The reason being, the printStackTrace implementation of Throwable
class
synchronized (s.lock()) {
// Print our stack trace
s.println(this);
StackTraceElement[] trace = getOurStackTrace();
for (StackTraceElement traceElement : trace)
s.println("\tat " + traceElement);
// Print suppressed exceptions, if any
for (Throwable se : getSuppressed())
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
// Print cause, if any
Throwable ourCause = getCause();
if (ourCause != null)
ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu);
}
Here, when stacktrace is printed by logger, the AppException's StackTrace gets printed. Along with it, if a cause is attached, then the stacktrace of the cause also gets printed.
However, the originalException
field in AppException
class is not registered as cause. So, when we print the exception in logs, we miss important information about the cause. For eg: If we encounter a NullPointerException - Right now there is no way to identify the point at which the exception was thrown from.
Here is the current sample stack trace printed in logs
2021-04-07 18:17:29.672 ERROR LAPTOP-TS9M1QFT --- [nio-8082-exec-2] o.o.o.a.l.Slf4JLogger correlation-id=688c57a6-39a7-4666-b90b-4d5a461e77f3 data-partition-id=opendes: storage.app null {correlation-id=688c57a6-39a7-4666-b90b-4d5a461e77f3, data-partition-id=opendes}
AppException(error=AppError(code=500, reason=Server error., message=An unknown error has occurred., errors=null, debuggingInfo=null, originalException=java.lang.NullPointerException), originalException=java.lang.NullPointerException)
at org.opengroup.osdu.storage.util.GlobalOtherExceptionMapper.handleGeneralException(GlobalOtherExceptionMapper.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
Expected Behaviour
The stacktrace could contain cause as well
021-04-07 20:29:23.858 ERROR LAPTOP-TS9M1QFT --- [nio-8082-exec-2] o.o.o.a.l.Slf4JLogger correlation-id=56bbc5c2-19e8-4aef-a449-3c684d733326 data-partition-id=opendes: storage.app null {correlation-id=56bbc5c2-19e8-4aef-a449-3c684d733326, data-partition-id=opendes}
AppException(error=AppError(code=500, reason=Server error., message=An unknown error has occurred., errors=null, debuggingInfo=null, originalException=java.lang.NullPointerException), originalException=java.lang.NullPointerException)
at org.opengroup.osdu.storage.util.GlobalOtherExceptionMapper.handleGeneralException(GlobalOtherExceptionMapper.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
Caused by: java.lang.NullPointerException
at org.opengroup.osdu.storage.service.QueryServiceImpl.getRecordInfo(QueryServiceImpl.java:72)
at org.opengroup.osdu.storage.api.RecordApi.getLatestRecordVersion(RecordApi.java:113)
at org.opengroup.osdu.storage.api.RecordApi$$FastClassBySpringCGLIB$$495e8f0c.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
... 100 more