Java日志追踪唯一id如何实现?
SpringBoot 2.3+
Java 1.8+
Slf4j
记录日志,每条打印的日志都会有不同的ID,不方便追踪当前请求日志记录,给当前请求添加唯一ID,
网上找到一些比较老的文章,说的是过滤器
和AOP
实现,
现在主流是啥方式啊,大佬们
方案1
https://tlog.yomahub.com/pages/eea781/
找到个开源的轻量级包,适用于小项目
方案2,根据回答zxdposter
的思路
1.TraceInterceptor拦截器
@Componentpublic class TraceInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
MDC.put("TID", UUID.randomUUID().toString());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
MDC.clear();
}
}
2.TraceInterceptor注册
@Configurationpublic class TraceConfig implements WebMvcConfigurer {
@Autowired
private TraceInterceptor traceInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(traceInterceptor)
.addPathPatterns("/**")//指定该类拦截的url
.excludePathPatterns("/static/**");//过滤静态资源
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS", "HEAD")
.allowedHeaders("*")
.maxAge(3600);
}
}
3.application.properties 文件路径
logging.file.path=/home/logs/baba
4.logback-spring.xml
配置文件
<configuration scan="true" scanPeriod="10 seconds"> <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<springProperty scope="context" name="fileActive" source="spring.profiles.active"/>
<property name="LOG_PATH" value="${LOG_PATH:-.}"/>
<property name="CONSOLE_LOG_PATTERN" value="%X{TID}|--${CONSOLE_LOG_PATTERN}"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</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>16MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>10</maxHistory>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} -[%X{TID}]- [%thread] %-5level %logger{36} -%msg%n
</Pattern>
</layout>
</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>16MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>10</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>
</appender>
<!-- hibernate日志输入 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="INFO"/>
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="INFO"/>
<logger name="org.hibernate.SQL" level="TRACE"/>
<root level="INFO">
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="ERROR_FILE"/>
<appender-ref ref="CONSOLE" />
</root>
</configuration>
回答:
我的方案
我认为最好的方案是用拦截器 + LogFormat
+ MDC
。
利用日志框架自身提供的特性解决问题。
第一步
首先配置日志格式,下面的格式是我从 springboot 中拷贝的,可以直接使用,之后增加一个 %X{REQUEST_ID}
标志占位。
logging: pattern:
console: '%clr(%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:%5p}) %clr(${PID: }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint}%clr(%X{REQUEST_ID}){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}'
file: '%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:%5p} ${PID: } --- [%t] %-40.40logger{39} :%X{REQUEST_ID} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}'
第二步
增加一个 http 请求拦截器,我用的是 spring boot 2.7
,实现方式是增加 WebMvcConfigurer
类型的 bean
,再实现 addInterceptors
方法,增加自定义的 HandlerInterceptor
类。
第三步
实现自定义 HandlerInterceptor
类中的方法 preHandle
。
在每次请求前,生成一个唯一 ID,调用 MDC
的静态方法 put
。
示例(kotlin)
class MvcLoggingConfigurer : WebMvcConfigurer { override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(LoggingHandlerInterceptor())
}
internal class LoggingHandlerInterceptor : HandlerInterceptor {
override fun preHandle(
httpServletRequest: HttpServletRequest,
httpServletResponse: HttpServletResponse,
o: Any
): Boolean {
val requestId = httpServletRequest.getHeader(SystemConstant.REQUEST_ID)
if (CharSequenceUtil.isNotBlank(requestId)) {
MDC.put(SystemConstant.LOGGING_PATTERN_REQUEST_ID, "[$requestId]")
}
return true
}
}
}
回答:
主流方式还是过滤器
+ MDC
,因为整体逻辑还是比较简单的,所以可能也就没啥变化
回答:
用spring-cloud-starter-sleuth的链路追踪; 支持新线程,线程池等场景;过滤器/拦截器+MDC,在新线程中就追踪不到了
以上是 Java日志追踪唯一id如何实现? 的全部内容, 来源链接: utcz.com/p/944821.html