1. 使用TreadLocal保存每个调用的uuid
ThreadLocalInfo:
import java.util.HashMap;
/**
* @Description:
* @Author: wangkebing
* @Date: 2020/12/23
* @Param:
* @Retrun:
**/
public class ThreadLocalInfo extends HashMap<String, Object> {
public ThreadLocalInfo addUUID(String uuid) {
this.put("uuid", uuid);
return this;
}
public ThreadLocalInfo addTimeStamp(String timeStamp) {
this.put("timeStamp", timeStamp);
return this;
}
public String getUUID() {
return this.get("uuid") == null ? null : (String) this.get("uuid");
}
public String getTimeStamp() {
return this.get("timeStamp") == null ? null : (String) this.get("timeStamp");
}
}
TLInfo:
/**
* @Description:
* @Author: wangkebing
* @Date: 2020/12/23
* @Param:
* @Retrun:
**/
public class TLInfo {
private TLInfo() {
}
private static final ThreadLocal<ThreadLocalInfo> LOCAL = new ThreadLocal<ThreadLocalInfo>();
public static void set(ThreadLocalInfo threadLocalInfo) {
LOCAL.set(threadLocalInfo);
}
public static ThreadLocalInfo get() {
return LOCAL.get();
}
public static void setUUID(String uuid) {
ThreadLocalInfo threadLocalInfo = TLInfo.get() == null ? new ThreadLocalInfo() : TLInfo.get();
TLInfo.set(threadLocalInfo.addUUID(uuid));
}
public static String getUUID() {
return TLInfo.get() == null ? null : TLInfo.get().getUUID();
}
public static void setTimeStamp(String timeStamp) {
ThreadLocalInfo threadLocalInfo = TLInfo.get() == null ? new ThreadLocalInfo() : TLInfo.get();
TLInfo.set(threadLocalInfo.addTimeStamp(timeStamp));
}
public static String getTimeStamp() {
return TLInfo.get() == null ? null : TLInfo.get().getTimeStamp();
}
}
拦截器设置uuid:
public class LogInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try{
String uuid = UUID.randomUUID().toString().replace("-", "");
TLInfo.setUUID(uuid);
} catch (Exception e) {
// 捕捉异常,不可阻断流程,无需做任何处理
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
TLInfo.set(null);
}
}
配置拦截器:
@Configuration
public class WebInterceptorConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**");
}
}
继承MessageConverter,重写日志方法
public class SensitiveDataConverter extends MessageConverter {
@Override
public String convert(ILoggingEvent event){
//获取原始日志
String oriLogMsg = event.getFormattedMessage();
// 日志增加唯一标识
try{
return insertUUID(oriLogMsg);
} catch (Exception e) {
return oriLogMsg;
}
}
/**
* 日志增加唯一标识
*/
public String insertUUID(String oriLogMsg) {
return MessageFormat.format("[{0}] {1}", TLInfo.getUUID(), oriLogMsg);
}
}
在xml中配置自定义的 SensitiveDataConverter 要放到第一行,否则可能不生效
<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
<configuration scan="true" scanPeriod="10 seconds">
<!--要放到第一行,否则可能不生效-->
<conversionRule conversionWord="msg" converterClass="com.cnpc.cmp.worksheet.log.SensitiveDataConverter"> </conversionRule>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<jmxConfigurator/>
<property name="LOG_PATH" value="${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}" />
<appender name="DEBUG_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_PATH}/debug.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/debug-%d{yyyyMMdd}.log.%i
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留的天数-->
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}
-%msg%n
</Pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="INFO_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${LOG_PATH}/info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/info-%d{yyyyMMdd}.log.%i
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留的天数-->
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}
-%msg%n
</Pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="WARN_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
<File>${LOG_PATH}/warn.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/warn-%d{yyyyMMdd}.log.%i
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}
-%msg%n
</Pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="ERROR_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>ERROR</level>
</filter>
<File>${LOG_PATH}/error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error-%d{yyyyMMdd}.log.%i
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>500MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>2</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}
-%msg%n
</Pattern>
</layout>
<filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!--<root level=""> 最基础的日志输出级别默认是debug-->
<root >
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</configuration>

本文介绍了如何在项目中为每个操作添加一个全局唯一的UUID标识。通过TreadLocal实现每个调用跟踪,拦截器设置UUID,并配置自定义的MessageConverter确保日志记录正确。
1564

被折叠的 条评论
为什么被折叠?



