Reputation: 1673
Is there any way you can log only the simple name of an exception without explicitly retrieving it from the code?
For example, by calling
log.error(exception);
with a logback pattern
%d{yyyy-MM-dd}|%-5level|%m%n
instead of just logging the exception stack traces
2018-01-01|ERROR|
mainPackage.foo.bar.RocketExplosionException: Houston we have a problem
at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
A separate column with the simple name of the exception is expected to be logged
2018-01-01|ERROR|RocketExplosionException|
mainPackage.foo.bar.RocketExplosionException: Houston we have a problem
at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
Upvotes: 4
Views: 5649
Reputation: 47905
You could write your own custom conversion specifier.
To do this, you would declare a conversion rule in your logback.xml
for the %exname
symbolic like so:
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<conversionRule conversionWord="exname" converterClass="com.foo.ExceptionNameConverter" />
...
</configuration>
Then declare ExceptionNameConverter
like so:
import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
import ch.qos.logback.classic.spi.IThrowableProxy;
public class ExceptionNameConverter extends ThrowableProxyConverter {
@Override
protected String throwableProxyToString(IThrowableProxy tp) {
return tp.getClassName();
}
}
Now, using this pattern:
%d{yyyy-MM-dd}|%-5level|%exname|%m%n
The following log statement:
logger.error("Boom!", new RuntimeException("ouch"));
Will emit:
2018-09-26|ERROR|java.lang.RuntimeException|Boom!
Upvotes: 5
Reputation: 1673
As is Andreas suggests, one way to support exception name logging is use a custom Layout
instead of PatternLayout
A sample layout:
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.ThrowableProxyUtil;
import ch.qos.logback.core.CoreConstants;
import ch.qos.logback.core.LayoutBase;
public class ErrorLoggingLayout extends LayoutBase<ILoggingEvent> {
private static final char SEP = '|';
@Override
public String doLayout(final ILoggingEvent event) {
StringBuilder sb = new StringBuilder(128);
sb.append(event.getTimeStamp() - event.getLoggerContextVO().getBirthTime());
sb.append(SEP);
sb.append(event.getLevel());
sb.append(SEP);
sb.append(event.getThreadName());
sb.append(SEP);
StackTraceElement frame = event.getCallerData()[0];
sb.append(extractSimpleName(frame.getClassName())).append('.').append(frame.getMethodName()).append(':').append(frame.getLineNumber());
sb.append(SEP);
IThrowableProxy throwableProxy = event.getThrowableProxy();
if (throwableProxy != null) {
String simpleName = extractSimpleName(throwableProxy.getClassName());
sb.append(simpleName);
}
sb.append(SEP);
sb.append(event.getFormattedMessage());
sb.append(CoreConstants.LINE_SEPARATOR);
if (throwableProxy != null) {
sb.append(ThrowableProxyUtil.asString(throwableProxy));
}
return sb.toString();
}
@NotNull
private String extractSimpleName(final String cName) {
int index = cName.lastIndexOf('.');
return cName.substring(index + 1);
}
}
This result turns out like
7645|ERROR|Thread-Name-0|RocketConsole.report:22|RocketExplosionException|custom msg
mainPackage.foo.bar.RocketExplosionException: Houston we have a problem
at mainPackage.foo.bar.TestThrower.fire(TestThrower.java:22)
at mainPackage.foo.bar.TestThrower.readyToLaunch(TestThrower.java:17)
at mainPackage.ExceptionLauncher.main(ExceptionLauncher.java:38)
However, one shortage of this approach is that the output format might be slightly different than the original pattern, and it takes extra effort to format the fields.
Upvotes: 0