You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@logging.apache.org by "Arthur Gavlyukovskiy (Jira)" <ji...@apache.org> on 2022/07/19 17:22:00 UTC

[jira] [Updated] (LOG4J2-3556) JsonTemplateLayout truncation ignores exception cause

     [ https://issues.apache.org/jira/browse/LOG4J2-3556?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Arthur Gavlyukovskiy updated LOG4J2-3556:
-----------------------------------------
    Description: 
Stacktrace truncation is helpful to reduce the size of the event, but current approach implemented in LOG4J2-2993 completely removes any "Caused by:" that might be in the stacktrace, while those are the most useful parts of stacktrace.

I'm using the modified EcsLayout.json with suggested truncation point
{code:java}
"error.stack_trace": {
  "$resolver": "exception",
  "field": "stackTrace",
  "stackTrace": {
    "stringified": {
      "truncation": {
        "pointMatcherStrings": ["at javax.servlet.http.HttpServlet.service"],
        "suffix": "\n\t<skipped internal frames>"
      }
    }
  }
} {code}
and the stacktrace I saw on a real production server was rendered as
{code:java}
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service
    <skipped internal frames> {code}
which doesn't show anything about origin of the error.

 

The fix should be relatively simple - change StackTraceStringResolver.truncate method to
{code:java}
    private void truncate(
            final TruncatingBufferedPrintWriter writer,
            final int index) {
        int causedByIndex = writer.indexOf("Caused by:");
        CharSequence causedBy = null;
        if (causedByIndex != -1) {
            causedBy = writer.subSequence(causedByIndex - 1, writer.position());
        }
        writer.position(index);
        writer.print(truncationSuffix);
        if (causedByIndex != -1) {
            writer.print(causedBy);
        }
    }
 {code}
and it correctly displays the stack trace:
{code:java}
java.lang.IllegalArgumentException: wrapper error
	at reproducer.log4jjsontemplate.StackTraceController.test(StackTraceController.java:18)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service
	<skipped internal frames>
Caused by: java.lang.NullPointerException: original error
	at reproducer.log4jjsontemplate.StackTraceController.test(StackTraceController.java:16)
	... 50 more {code}
 

I have created an MRE [here|https://github.com/gavlyukovskiy/log4j-json-template-reproducer] where you can find more details and monkey patch on a [separate branch|https://github.com/gavlyukovskiy/log4j-json-template-reproducer/tree/monkey-patch].

  was:
Stacktrace truncation is helpful to reduce the size of the event, but current approach implemented in LOG4J2-2993 completely removes any "Caused by:" that might be in the stacktrace, while those are the most useful parts of stacktrace.

I'm using the modified EcsLayout.json with suggested truncation point
{code:java}
"error.stack_trace": {
  "$resolver": "exception",
  "field": "stackTrace",
  "stackTrace": {
    "stringified": {
      "truncation": {
        "pointMatcherStrings": ["at javax.servlet.http.HttpServlet.service"],
        "suffix": "\n\t<skipped internal frames>"
      }
    }
  }
} {code}
and the stacktrace I saw on a real production server was rendered as
{code:java}
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service
    <skipped internal frames> {code}
which doesn't show anything about origin of the error.

 

The fix should be relatively simple - change StackTraceStringResolver.truncate method to
{code:java}
    private void truncate(
            final TruncatingBufferedPrintWriter writer,
            final int index) {
        int causedByIndex = writer.indexOf("Caused by:");
        CharSequence causedBy = null;
        if (causedByIndex != -1) {
            causedBy = writer.subSequence(causedByIndex - 1, writer.position());
        }
        writer.position(index);
        writer.print(truncationSuffix);
        if (causedByIndex != -1) {
            writer.print(causedBy);
        }
    }
 {code}
and it correctly displays the stack trace.

 

I have created an MRE [here|https://github.com/gavlyukovskiy/log4j-json-template-reproducer] where you can find more details and monkey patch on a [separate branch|https://github.com/gavlyukovskiy/log4j-json-template-reproducer/tree/monkey-patch].


> JsonTemplateLayout truncation ignores exception cause
> -----------------------------------------------------
>
>                 Key: LOG4J2-3556
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-3556
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: JsonTemplateLayout
>            Reporter: Arthur Gavlyukovskiy
>            Priority: Minor
>
> Stacktrace truncation is helpful to reduce the size of the event, but current approach implemented in LOG4J2-2993 completely removes any "Caused by:" that might be in the stacktrace, while those are the most useful parts of stacktrace.
> I'm using the modified EcsLayout.json with suggested truncation point
> {code:java}
> "error.stack_trace": {
>   "$resolver": "exception",
>   "field": "stackTrace",
>   "stackTrace": {
>     "stringified": {
>       "truncation": {
>         "pointMatcherStrings": ["at javax.servlet.http.HttpServlet.service"],
>         "suffix": "\n\t<skipped internal frames>"
>       }
>     }
>   }
> } {code}
> and the stacktrace I saw on a real production server was rendered as
> {code:java}
> org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
>     at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
>     at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
>     at javax.servlet.http.HttpServlet.service
>     <skipped internal frames> {code}
> which doesn't show anything about origin of the error.
>  
> The fix should be relatively simple - change StackTraceStringResolver.truncate method to
> {code:java}
>     private void truncate(
>             final TruncatingBufferedPrintWriter writer,
>             final int index) {
>         int causedByIndex = writer.indexOf("Caused by:");
>         CharSequence causedBy = null;
>         if (causedByIndex != -1) {
>             causedBy = writer.subSequence(causedByIndex - 1, writer.position());
>         }
>         writer.position(index);
>         writer.print(truncationSuffix);
>         if (causedByIndex != -1) {
>             writer.print(causedBy);
>         }
>     }
>  {code}
> and it correctly displays the stack trace:
> {code:java}
> java.lang.IllegalArgumentException: wrapper error
> 	at reproducer.log4jjsontemplate.StackTraceController.test(StackTraceController.java:18)
> 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
> 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> 	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
> 	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
> 	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
> 	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
> 	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
> 	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
> 	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
> 	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
> 	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
> 	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
> 	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
> 	at javax.servlet.http.HttpServlet.service
> 	<skipped internal frames>
> Caused by: java.lang.NullPointerException: original error
> 	at reproducer.log4jjsontemplate.StackTraceController.test(StackTraceController.java:16)
> 	... 50 more {code}
>  
> I have created an MRE [here|https://github.com/gavlyukovskiy/log4j-json-template-reproducer] where you can find more details and monkey patch on a [separate branch|https://github.com/gavlyukovskiy/log4j-json-template-reproducer/tree/monkey-patch].



--
This message was sent by Atlassian Jira
(v8.20.10#820010)