背景
有的时候需要自定义日志字段,即在日志字段里加自定义字段变量。
本质
自定义日志模板,本质是自定义字段变量。
实现步骤
1.自定义字段
2.实现自定义字段处理类
自定义字段
配置文件
value="%date{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%logPreFix|%class.%method:%line|%extjson|%sensitiveMsg%n" />
logPreFix是自定义字段。
实现自定义字段处理类
步骤
1.配置自定义字段处理类
2.实现自定义字段处理类
自定义字段之后,还需要指定自定义字段的自定义处理类。
配置文件
class="kalvan.log.logback.appender.ExtRollingFileAppender">
${logback.logpath}/info.log
INFO
ACCEPT
DENY
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
${logback.logpath}/info.%d{yyyyMMdd}.%i.log
${logback.maxFileSize}
//自定义字段的处理类
${logback.pattern} //自定义字段
实现类
其实这里只是映射字段和字段处理类,字段处理类还需要单独自定义。
public class ExtLayout extends PatternLayout {
static {
// 记录线程号
defaultConverterMap.put("threadid", ThreadIdConverter.class.getName());
// 处理消息内容屏蔽敏感信息
defaultConverterMap.put("sensitiveMsg",
SensitiveMessageConverter.class.getName());
// 统一日志前缀
defaultConverterMap
.put("logPreFix", LogPreFixConverter.class.getName()); //自定义字段
// json扩展数据收集用于图表展示
defaultConverterMap.put("extjson", ExtJsonConverter.class.getName());
}
}
字段处理类
这里的实现比较复杂一点,基于线程本地变量实现全链路跟踪。
public class LogPreFixConverter extends ClassicConverter {
private static final ThreadLocal logPreFixThreadLocal = new ThreadLocal();
@Override
public String convert(ILoggingEvent event) { //这个方法的作用,就是映射字段变量和字段变量的值
try {
return getCurrentThreadLogPreFix(event.getFormattedMessage());
} catch (Throwable t) {
// TODO 处理异常,这时不应该再打印日志避免死循环
System.err.println("LogPreFixConverter处理异常" + t.getMessage());
}
return "errorLogPreFix";
}
总结
1.每个自定义字段,都需要单独的自定义字段处理类,也就是说,一个自定义字段类只能处理一个自定义字段,如果有多个自定义字段,就要实现多个自定义字段处理类分别处理不同的自定义字段。
2.公司封装了自己的日志jar,专门用于同一处理自定义字段。
参考