package com.hz3r.config.log.pattern.converters; import ch.qos.logback.classic.pattern.ClassicConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.LoggingEvent; import ch.qos.logback.classic.spi.ThrowableProxy; import ch.qos.logback.classic.spi.ThrowableProxyVO; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.text.StrFormatter; import cn.hutool.core.util.NumberUtil; import com.hz3r.infrastructure.park.domain.constant.share.SystemCacheType; import com.hz3r.infrastructure.park.service.share.SystemCacheService; import com.hz3r.utils.MyStrUtils; import com.hz3r.utils.SpringBeanUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 自定义异常堆栈合并成行转换器 * * 用法:在 PatternLayout 中使用 %ctx 来引用此转换器 */ public class CustomOneLineExceptionConverter extends ClassicConverter { @Override public String convert(ILoggingEvent event) { // 异常栈合并成一行输出。 String oneLineMessage = MyStrUtils.EMPTY; SystemCacheService SCService = SpringBeanUtils.getBean(SystemCacheService.class); Boolean oneLineExceptionCallStack = SCService.describeAll().stream() .filter(e -> e.getKey() == SystemCacheType.LOG_OUT_ONE_LINE_EXCEPTION) .map(e -> MyStrUtils.equalsIgnoreCase(MyStrUtils.defaultString(e.getValue()), "true")) .findFirst().orElse(Boolean.TRUE); // 默认行长度 final Integer defaultLineSize = 2000; int oneLineMessageSize = SCService.describeAll().stream() .filter(e -> e.getKey() == SystemCacheType.LOG_OUT_ONE_LINE_SIZE) .map(e -> NumberUtil.parseInt(MyStrUtils.defaultIfBlank(e.getValue(), String.valueOf(defaultLineSize)))) .findFirst().orElse(defaultLineSize); if ((oneLineExceptionCallStack) && (event.getCallerData() != null && event.getCallerData().length > 0)) { //if (event.getThrowableProxy() instanceof ThrowableProxy) { // ThrowableProxy throwableProxy = ((ThrowableProxy) event.getThrowableProxy()); // oneLineMessage = ExceptionUtil.stacktraceToOneLineString(throwableProxy.getThrowable(), oneLineMessageSize * 3); //} else if (event.getThrowableProxy() instanceof Throwable) { // Throwable throwable = ((Throwable) event.getThrowableProxy()); // oneLineMessage = ExceptionUtil.stacktraceToOneLineString(throwable, oneLineMessageSize * 3); //} String hz3rRootPackageSearch = ".hz3r."; String hz3rRootPackage = MyStrUtils.substring(this.getClass().getPackageName(), 0, this.getClass().getPackageName().indexOf(hz3rRootPackageSearch) + hz3rRootPackageSearch.length()); List busCodeStack = new ArrayList<>(100); String splitDelimiter = ","; String[] packageFilters = SCService.describeAll().stream() .filter(e -> e.getKey() == SystemCacheType.LOG_OUT_ONE_LINE_PACKAGES) .map(e -> { String value = MyStrUtils.replace(MyStrUtils.defaultString(e.getValue()), ",", splitDelimiter); value = StrFormatter.format("{},{}", hz3rRootPackage, value); value = MyStrUtils.replace(value, ",,", splitDelimiter); return MyStrUtils.split(value, splitDelimiter); }) .findFirst().orElse(new String[] { hz3rRootPackage, "org.springframework.web.servlet.mvc."}); Arrays.stream(event.getThrowableProxy().getStackTraceElementProxyArray()) .forEach(e -> { if (MyStrUtils.startsWithAny(e.getStackTraceElement().getClassName(), packageFilters)) { busCodeStack.add(e.getSTEAsString()); } }); oneLineMessage = MyStrUtils.join(busCodeStack, "\\n\t"); // 缩减长度,只留指定长度的字符串。 if (oneLineMessage.length() > oneLineMessageSize) { int startSize = oneLineMessageSize / 2; startSize = startSize <= 0 ? oneLineMessageSize : startSize; int endSize = oneLineMessageSize - startSize; oneLineMessage = StrFormatter.format("{}\\n...\\n{}", MyStrUtils.substring(oneLineMessage, 0, startSize), MyStrUtils.substring(oneLineMessage, -(endSize), oneLineMessage.length())); } // ch.qos.logback.classic.spi.LoggingEvent if (event instanceof LoggingEvent) { LoggingEvent loggingEvent = LoggingEvent.class.cast(event); //loggingEvent.setCallerData(null); //loggingEvent.setThrowableProxy(null); //(ThrowableProxyVO.class.cast(loggingEvent.getThrowableProxy())).set() } } final String specHead = ",#!!///ole"; return MyStrUtils.isBlank(oneLineMessage) ? oneLineMessage : StrFormatter.format("{} at{}", specHead, oneLineMessage); } }