Quarkus访问日志未显示MDC内容:如何调整过滤器与日志顺序?
问题解决:Quarkus访问日志先记录MDC再清除的执行顺序调整
问题原因
Quarkus的访问日志记录时机晚于JAX-RS ContainerResponseFilter 的执行时机。你在ContainerResponseFilter中清除MDC后,访问日志才开始记录,导致访问日志无法获取到MDC内容。
解决方案
方案一:利用RequestScoped Bean的销毁时机清除MDC
创建一个请求作用域的Bean,在其销毁阶段(整个请求处理完成后,包括访问日志记录)清除MDC。
- 移除原
LoggingFilter中ContainerResponseFilter的实现,仅保留请求过滤器设置MDC:
import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.ext.Provider; import org.jboss.logging.MDC; @Provider public class LoggingFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { MDC.put("test", "testValue"); } }
- 创建请求作用域的MDC清理Bean:
import javax.enterprise.context.RequestScoped; import javax.annotation.PreDestroy; import org.jboss.logging.MDC; @RequestScoped public class MdcCleanupBean { @PreDestroy void cleanupMdc() { MDC.clear(); } }
请求处理流程变为:
- 请求进入 →
LoggingFilter设置MDC → 资源方法执行 → JAX-RS处理响应 → 发送响应给客户端 → Quarkus记录访问日志(此时MDC未被清除) → 请求作用域Bean销毁 → 清除MDC
方案二:使用Quarkus HttpServerFilter设置最高优先级
创建一个优先级最低(数值最大)的HttpServerFilter,确保在所有请求处理逻辑(包括访问日志记录)完成后再清除MDC。
- 保留原
LoggingFilter的请求过滤器部分(仅设置MDC):
import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.ext.Provider; import org.jboss.logging.MDC; @Provider public class LoggingFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { MDC.put("test", "testValue"); } }
- 创建HttpServerFilter用于清理MDC:
import io.quarkus.http.runtime.filter.HttpServerFilter; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import org.jboss.logging.MDC; @HttpServerFilter(priority = Integer.MAX_VALUE) public class MdcCleanupFilter implements io.quarkus.http.runtime.filter.Filter { @Override public void doFilter(HttpServerRequest request, HttpServerResponse response, Chain chain) throws Exception { try { chain.doFilter(request, response); // 执行所有后续请求处理(包括访问日志) } finally { MDC.clear(); // 所有处理完成后清除MDC } } }
priority = Integer.MAX_VALUE 确保该过滤器是最后执行的,try-finally 保证无论请求是否异常,MDC都会被清除。
验证效果
调整后,访问日志的输出会包含MDC内容:
{"timestamp":"2023-11-24T16:06:08.434+03:00","sequence":1995,"loggerClassName":"org.jboss.logging.Logger","loggerName":"io.quarkus.http.access-log","level":"INFO","message":"127.0.0.1 - - 24/Nov/2023:16:06:08 +0300 \"GET /hello-resteasy HTTP/1.1\" 200 14","threadName":"executor-thread-0","threadId":85,"mdc":{"test":"testValue"},"ndc":"","hostName":"hj9xgjxrql","processName":"code-with-quarkus-dev.jar","processId":12056}
内容的提问来源于stack exchange,提问作者C. Bilgin
相关产品推荐
相关产品推荐

