diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebServletConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebServletConfiguration.java index abb21771a..e398fbac3 100644 --- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebServletConfiguration.java +++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/web/TraceWebServletConfiguration.java @@ -29,6 +29,7 @@ import javax.servlet.ServletResponse; import org.apache.catalina.Valve; import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; @@ -102,7 +103,8 @@ class TraceWebServletConfiguration { @Bean(name = CUSTOMIZER_NAME) @Order(Ordered.HIGHEST_PRECEDENCE) WebServerFactoryCustomizer traceTomcatWebServerFactoryCustomizer( - HttpServerHandler httpServerHandler, CurrentTraceContext currentTraceContext) { + ObjectProvider httpServerHandler, + ObjectProvider currentTraceContext) { return factory -> factory.addEngineValves(new TraceValve(httpServerHandler, currentTraceContext)); } diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValve.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValve.java index 4472c8557..69387a122 100644 --- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValve.java +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValve.java @@ -25,6 +25,7 @@ import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.cloud.sleuth.CurrentTraceContext; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.SpanCustomizer; @@ -33,6 +34,7 @@ import org.springframework.cloud.sleuth.http.HttpServerHandler; import org.springframework.cloud.sleuth.instrument.web.servlet.HttpServletRequestWrapper; import org.springframework.cloud.sleuth.instrument.web.servlet.HttpServletResponseWrapper; import org.springframework.core.log.LogAccessor; +import org.springframework.lang.NonNull; /** * A trace representation of a {@link Valve}. @@ -44,28 +46,42 @@ public class TraceValve extends ValveBase { private static final LogAccessor log = new LogAccessor(TraceValve.class); - private final HttpServerHandler httpServerHandler; + private HttpServerHandler httpServerHandler; - private final CurrentTraceContext currentTraceContext; + private CurrentTraceContext currentTraceContext; - public TraceValve(HttpServerHandler httpServerHandler, CurrentTraceContext currentTraceContext) { + private final ObjectProvider httpServerHandlerProvider; + + private final ObjectProvider currentTraceContextProvider; + + public TraceValve(@NonNull HttpServerHandler httpServerHandler, @NonNull CurrentTraceContext currentTraceContext) { this.httpServerHandler = httpServerHandler; this.currentTraceContext = currentTraceContext; + this.httpServerHandlerProvider = null; + this.currentTraceContextProvider = null; + setAsyncSupported(true); + } + + public TraceValve(@NonNull ObjectProvider httpServerHandler, + @NonNull ObjectProvider currentTraceContext) { + this.httpServerHandler = null; + this.currentTraceContext = null; + this.httpServerHandlerProvider = httpServerHandler; + this.currentTraceContextProvider = currentTraceContext; setAsyncSupported(true); } @Override public void invoke(Request request, Response response) throws IOException, ServletException { Exception ex = null; - Span handleReceive = this.httpServerHandler - .handleReceive(HttpServletRequestWrapper.create(request.getRequest())); + Span handleReceive = httpServerHandler().handleReceive(HttpServletRequestWrapper.create(request.getRequest())); if (log.isDebugEnabled()) { log.debug("Created a server receive span [" + handleReceive + "]"); } request.setAttribute(SpanCustomizer.class.getName(), handleReceive); request.setAttribute(TraceContext.class.getName(), handleReceive.context()); request.setAttribute(Span.class.getName(), handleReceive); - try (CurrentTraceContext.Scope ws = this.currentTraceContext.maybeScope(handleReceive.context())) { + try (CurrentTraceContext.Scope ws = currentTraceContext().maybeScope(handleReceive.context())) { Valve next = getNext(); if (null == next) { // no next valve @@ -78,7 +94,7 @@ public class TraceValve extends ValveBase { throw exception; } finally { - this.httpServerHandler.handleSend( + httpServerHandler().handleSend( HttpServletResponseWrapper.create(request.getRequest(), response.getResponse(), ex), handleReceive); if (log.isDebugEnabled()) { log.debug("Handled send of span [" + handleReceive + "]"); @@ -86,4 +102,18 @@ public class TraceValve extends ValveBase { } } + private HttpServerHandler httpServerHandler() { + if (this.httpServerHandler == null) { + this.httpServerHandler = this.httpServerHandlerProvider.getIfAvailable(); + } + return this.httpServerHandler; + } + + private CurrentTraceContext currentTraceContext() { + if (this.currentTraceContext == null) { + this.currentTraceContext = this.currentTraceContextProvider.getIfAvailable(); + } + return this.currentTraceContext; + } + } diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValveTests.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValveTests.java index 44eb67bc1..3d2e4c555 100644 --- a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValveTests.java +++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/web/tomcat/TraceValveTests.java @@ -68,7 +68,7 @@ class TraceValveTests { @Test void should_have_async_supported_by_default() throws ServletException, IOException { - TraceValve traceValve = new TraceValve(null, null); + TraceValve traceValve = new TraceValve((HttpServerHandler) null, null); BDDAssertions.then(traceValve.isAsyncSupported()).isTrue(); }