项目日志添加统一个uuid标识

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

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>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值