有的时候需要自定义日志字段,即在日志字段里加自定义字段变量。
自定义日志模板,本质是自定义字段变量。
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,专门用于同一处理自定义字段。
https://my.oschina.net/u/2277...