英文:
Append correlation id to every log 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>
</configuration>
英文:
I need to append correlation id to logs from every request I get.
Here is my filter. It works good until I get to async block like runAsync()
.
I read about MDC and how it use ThreadLocal but can't understand how to use it in async because it uses 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>
</configuration>
答案1
得分: 1
这是我得出的解决方案。感谢 @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();
}
}
然后,使用静态方法 MdcRetention.wrap()
将您的 Runnable 包装在 runAsync()
块中。
之前:
runAsync(() -> someMethod());
之后:
runAsync(wrap(() -> someMethod()));
英文:
Here's the solution I ended up. Thanks to @M.Prokhorov
Create a class called MdcRetention
inside your project.
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();
}}
Then wrap your Runnable inside runAsync()
block using static method MdcRetention.wrap()
Before:
runAsync(() -> someMethod());
After:
runAsync(wrap(() -> someMethod()));
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论