目录
前文《logback之pattern详解以及源码分析》已经介绍了pattern,以及通过相应的源码分析了pattern关联的转换器如何进行日志转换,也说道了可以自行定义转换器,实现自己的需求。本篇就介绍一下如何自定义转换器:
(1)场景介绍
首先有这么一个场景:我定义了一个ImpossibleLogger,用于在比较复杂的场景(通常涉及并发),不可能执行的地方进行日志打印,并且单独记录日志。这样如果这个日志文件不为空,说明程序可能偏离我们的设想,需要排查。
public final class ImpossibleLogger {
private static final Logger LOGGER = LoggerFactory.getLogger("impossible");
public static void warn(String message) {
LOGGER.warn(message);
}
public static void warn(String message, Throwable t) {
LOGGER.warn(message, t);
}
public static void warn(Marker marker, String message) {
LOGGER.warn(marker, message);
}
public static void warn(Marker marker, String message, Throwable t) {
LOGGER.warn(marker, message, t);
}
}
因为包装了一层,那么如果使用%class %m打印调用类以及方法,那么只会是ImpossibleLogger以及对应的warn,无法实际区分业务调用类。所以我们想实现自己的转换器,把实际的业务调用类打印出来。
(2)定义转换器BizCallerConverter
我们模仿%m对应的转换器MethodOfCallerConverter,继承NamedConverter
package com.mall.common.log;
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
/**
* @author Lft
* @since 2024/12/28 19:06
*/
public class BizCallerConverter extends ClassicConverter {
public String convert(ILoggingEvent event) {
StackTraceElement[] cda = event.getCallerData();
if (cda != null && cda.length > 1) {
return cda[1].getClassName() + "." + cda[1].getMethodName();
} else {
return CallerData.NA;
}
}
}
(3)logback配置conversionRule
完整配置如下:
<configuration>
<conversionRule conversionWord="bizCaller"
converterClass="com.mall.common.log.BizCallerConverter"></conversionRule>
<conversionRule conversionWord="biz" converterClass="com.mall.common.log.BizCallerConverter"></conversionRule>
<!-- Appenders -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/logback.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/logback.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory> <!-- 保留最近30天的日志文件 -->
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<appender name="impossible" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/impossible.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
<fileNamePattern>impossible.%i.log.zip</fileNamePattern>
<minIndex>1</minIndex>
<maxIndex>3</maxIndex>
</rollingPolicy>
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<maxFileSize>5MB</maxFileSize>
</triggeringPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} %biz - %msg%n</pattern>
</encoder>
</appender>
<logger name="impossible" level="warn" addtivity="false">
<appender-ref ref="impossible"/>
</logger>
<!-- Root Logger -->
<root level="Info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="ROLLING"/>
</root>
</configuration>
conversionWord:这个是关键字,在pattern中使用
converterClass:关键字对应转换器类
(4)测试效果
简单调用,执行效果如下:转换器成功将上一层的调用打印出来了