Reputation: 682
I'm using SpringBoot 2.4.8 (and it uses logback-classic 1.2.3) and I want to configure a custom converter that collapses multiline stack trace into one line (same as this question).
Let's say I have this code snippet that intentionally throws an Exception for test purposes:
package co.foo.bar.test;
// ...
@Slf4j
public class Foo {
public void bar() {
// ...
try {
Integer.parseInt(null);
} catch (Exception e) {
log.error(e.getLocalizedMessage(), e);
}
}
}
When I have defined the conversionRule
and added the %ex
symbolic to the pattern, logback just ignores the ERROR log:
logback.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<conversionRule conversionWord="ex" converterClass="co.foo.bar.logging.CompressedStackTraceConverter" />
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg %ex%n
</pattern>
</encoder>
</appender>
// ...
<logger name="co.foo.bar.test" additivity="false" level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="MESSAGING_LOG"/>
</logger>
</configuration>
CompressedStackTraceConverter.java:
package co.foo.bar.logging;
// ...
public class CompressedStackTraceConverter extends ThrowableProxyConverter {
public CompressedStackTraceConverter() {
}
protected String throwableProxyToString(IThrowableProxy tp) {
String original = super.throwableProxyToString(tp);
return original.replaceAll("\\R\\t?", " ~~ ");
}
}
When I remove the %ex
symbolic, logback continues to print ERROR logs so the logback.xml should be correct. And when I debug the custom converter class, I can see it can successfully return a one-line exception string whenever an exception occurs.
I'm pretty sure there is a simple solution to this but cannot figure it out yet. What am I missing here?
Thanks in advance.
Upvotes: 2
Views: 4872
Reputation: 1140
Since your custom converter is just a String#replace
call, you may be able to use the solution mentioned in this blogpost.
This can go in the application.properties file.
# Single line. Full stack trace will be captured in a single line logging.exception-conversion-word=%replace(%wEx){'\n','\u2028'}%nopex # Truncated Single line. Only the exception message will be captured in a single line logging.exception-conversion-word=%replace(%wEx{short}){'\n','\u2028'}%nopex # Truncated. Default formatting but only capturing a single line logging.exception-conversion-word=%wEx{short}
This works if you don’t override logging.pattern.console as the default logging.pattern.console allows you to use logging.exception-converstion-word
In my case I had to use \r
instead of \n
like in the above CompressedStackTraceConverter
class, presumably because of being on windows.
My final expression in my application.yml
was
logging:
exception-conversion-word: "%replace(%wEx){'(\n|\r)\t?','\u2028'}%nopex"
which includes optional matching of the tab as in the above CompressedStackTraceConverter
class. The quotes were needed for the YAML parser.
Upvotes: 1
Reputation: 682
I think there may be another (newer?) way to achieve this than the one described in the related question or there is a bug in this logback version.
Instead, I ended up using logstash-logback-encoder to print everything as a one-line JSON string.
Here is the example if anyone is interested:
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.6</version>
</dependency>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<maxDepthPerThrowable>30</maxDepthPerThrowable>
<maxLength>2048</maxLength>
<rootCauseFirst>true</rootCauseFirst>
<inlineHash>true</inlineHash>
</throwableConverter>
<shortenedLoggerNameLength>36</shortenedLoggerNameLength>
<timeZone>UTC</timeZone>
</encoder>
</appender>
Upvotes: 1