Java Logback-如何单独记录异常的简单名称

Java Logback-如何单独记录异常的简单名称,java,spring,logging,logback,slf4j,Java,Spring,Logging,Logback,Slf4j,有没有办法只记录异常的简单名称而不从代码中显式检索它? 例如,通过调用 log.error(exception); 具有向后退模式 %d{yyyy-MM-dd}|%-5level|%m%n 而不仅仅是记录异常堆栈跟踪 2018-01-01|ERROR| mainPackage.foo.bar.RocketExplosionException: Houston we have a problem at mainPackage.foo.bar.TestThrower.fire(TestThr

有没有办法只记录异常的简单名称而不从代码中显式检索它?

例如,通过调用

log.error(exception);
具有向后退模式

%d{yyyy-MM-dd}|%-5level|%m%n
而不仅仅是记录异常堆栈跟踪

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)
预计将记录一个单独的列,其中包含异常的简单名称

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)

正如Andreas所建议的,支持异常名称日志记录的一种方法是使用自定义的
布局
,而不是
模式布局

布局示例:

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);
    }
}
然而,这种方法的一个缺点是输出格式可能与原始模式略有不同,并且格式化字段需要额外的努力。

您可以自己编写

为此,您需要在
logback.xml
中声明
%exname
符号的转换规则,如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <conversionRule conversionWord="exname" converterClass="com.foo.ExceptionNameConverter" />

    ...

</configuration>
现在,使用此模式:

%d{yyyy-MM-dd}|%-5level|%exname|%m%n
以下日志语句:

logger.error("Boom!", new RuntimeException("ouch"));
将发出:

2018-09-26|ERROR|java.lang.RuntimeException|Boom!

您可以实现自己的
Layout
而不是使用
patternalyout
@Andreas谢谢,但是我发现既要保留原始的
patternalyout
语法,又要支持异常名称的新功能是相当困难的,特别是当模式相当复杂时。谢谢,它可以工作。同时为了打印堆栈跟踪,可以将模式修改为
%d{yyyy-MM-dd}|%-5level |%exname |%m%n%ex
是,
%ex
提供完整的堆栈跟踪。
logger.error("Boom!", new RuntimeException("ouch"));
2018-09-26|ERROR|java.lang.RuntimeException|Boom!