java - 将相关 ID 附加到每个日志 java
问题描述
我需要将相关 ID 附加到我收到的每个请求的日志中。
这是我的过滤器。在我进入异步块之前它运行良好,例如runAsync()
.
我阅读了 MDC 以及它如何使用 ThreadLocal,但不明白如何在异步中使用它,因为它使用 ForkJoinPool。
@Component
public class Slf4jFilter extends OncePerRequestFilter {
private static final String CORRELATION_ID_HEADER_NAME = "correlation-id";
private static final String CORRELATION_ID_LOG_VAR_NAME = "correlationId";
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
try {
ofNullable(request.getHeader(CORRELATION_ID_HEADER_NAME)).ifPresent(correlationId -> MDC
.put(CORRELATION_ID_LOG_VAR_NAME, correlationId));
chain.doFilter(request, response);
}finally {
removeCorrelationId();
}
}
protected void removeCorrelationId() {
MDC.remove(CORRELATION_ID_LOG_VAR_NAME);
}
}
logback.xml
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{dd-MM-yyyy HH:mm:ss.SSS} [%thread %X{correlationId}] %-5level %logger{36} - %msg %n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="stdout" />
</root>
解决方案
这是我最终得到的解决方案。感谢@M.Prokhorov
MdcRetention
在您的项目中创建一个名为的类。
public final class MdcRetention {
public static Runnable wrap(final Runnable delegate) {
return new MdcRetainingRunnable() {
@Override
protected void runInContext() {
delegate.run();
}
};
}
private static abstract class MdcRetentionSupport {
protected final Map<String, String> originalMdc;
protected MdcRetentionSupport() {
Map<String, String> originalMdc = MDC.getCopyOfContextMap();
this.originalMdc = originalMdc == null ? Collections.emptyMap() : originalMdc;
}
}
public static abstract class MdcRetainingRunnable extends MdcRetentionSupport implements Runnable {
@Override
public final void run() {
Map<String, String> currentMdc = MDC.getCopyOfContextMap();
MDC.setContextMap(originalMdc);
try {
runInContext();
} finally {
MDC.setContextMap(currentMdc);
}
}
abstract protected void runInContext();
}}
runAsync()
然后使用静态方法将您的 Runnable 包装在块内MdcRetention.wrap()
前:
runAsync(() -> someMethod());
后:
runAsync(wrap(() -> someMethod()));
推荐阅读
- java - Java webdrivermanager 没有在 jenkins ubuntu 中打开浏览器
- javascript - localhost 与生产版本不同的 css
- firebase - 无法识别的 Firebase 项目。我希望这是一个演示项目
- c# - 更改控件模板中文本块的文本
- typescript - 从另一个地图获取地图数据 - Ionic 4,Firestore
- terraform - 使用 terraform 覆盖已删除的 aws_secretsmanager_secret 资源
- html - bg 颜色的 CSS 标头有问题
- python - Jupyter notebook 无法启动(ImportError: DLL load failed while importing)
- angular - 如何在角度 10 中实现 3d 滑块
- javascript - 我可以在没有 Content Manager 系统的情况下使用 html 模板吗?