背景
有的时候需要自定义日志字段,即在日志字段里加自定义字段变量。
本质
自定义日志模板,本质是自定义字段变量。
实现步骤
1.自定义字段
2.实现自定义字段处理类
自定义字段
配置文件
<!-- 统一日志格式输出用|分隔方便 elk日志工具收集处理 ,默认日志格式是 时间|级别|日志戳|代码路径|扩展json(收集图表数据,无则域留空)|脱敏后日志内容 -->
<property name="logback.pattern"
value="%date{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%logPreFix|%class.%method:%line|%extjson|%sensitiveMsg%n" />
logPreFix是自定义字段。
实现自定义字段处理类
步骤
1.配置自定义字段处理类
2.实现自定义字段处理类
自定义字段之后,还需要指定自定义字段的自定义处理类。
配置文件
<appender name="INFO_FILE"
class="kalvan.log.logback.appender.ExtRollingFileAppender">
<file>${logback.logpath}/info.log</file>
<!-- see https://logback.qos.ch/manual/filters.html -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- see https://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedFNATP -->
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${logback.logpath}/info.%d{yyyyMMdd}.%i.log
</fileNamePattern>
<maxFileSize>${logback.maxFileSize}</maxFileSize>
</rollingPolicy>
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<!-- see https://logback.qos.ch/manual/layouts.html -->
<layout class="kalvan.log.logback.layout.ExtLayout"> //自定义字段的处理类
<pattern>${logback.pattern}</pattern> //自定义字段
</layout>
</encoder>
</appender>
实现类
其实这里只是映射字段和字段处理类,字段处理类还需要单独自定义。
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<String> logPreFixThreadLocal = new ThreadLocal<String>();
@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,专门用于同一处理自定义字段。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。