From 37d7b5bedbca24338acfb34247079e8c39327127 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 11 Aug 2015 18:11:00 +0100 Subject: [PATCH] Split out @Async instrumentation into its own package There was an ordering error in the conditions as well, causing the wrong async customizers to be registered. Another issue was the servlet async processing (request atribute not cached in all branches) resulting in multiple spans per request. --- .../cloud/sleuth/MilliSpan.java | 1 + .../cloud/sleuth/TimelineAnnotation.java | 1 + .../autoconfig/TraceAutoConfiguration.java | 2 + .../async/AsyncCustomAutoConfiguration.java | 57 +++++++++++++++++++ .../async/AsyncDefaultAutoConfiguration.java | 50 ++++++++++++++++ .../LazyTraceAsyncCustomizer.java | 9 +-- .../LazyTraceExecutor.java} | 17 +++++- ...aceSpringIntegrationAutoConfiguration.java | 6 ++ .../TraceSchedulingAutoConfiguration.java | 55 ++---------------- .../sleuth/instrument/web/TraceFilter.java | 6 +- .../web/TraceWebAutoConfiguration.java | 5 ++ .../TraceWebClientAutoConfiguration.java | 6 ++ .../cloud/sleuth/log/JsonLogSpanListener.java | 12 ++-- .../log/SleuthLogAutoConfiguration.java | 6 ++ .../cloud/sleuth/log/Slf4jSpanListener.java | 3 +- .../main/resources/META-INF/spring.factories | 2 + .../sleuth/sample/SampleApplication.java | 5 +- .../cloud/sleuth/sample/SampleController.java | 2 +- .../sleuth/zipkin/ZipkinSpanListener.java | 12 ++-- 19 files changed, 178 insertions(+), 79 deletions(-) create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java create mode 100644 spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/{scheduling => async}/LazyTraceAsyncCustomizer.java (82%) rename spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/{scheduling/TraceExecutor.java => async/LazyTraceExecutor.java} (67%) diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java index 11c1defa9..39473fef5 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/MilliSpan.java @@ -56,6 +56,7 @@ public class MilliSpan implements Span { } //for serialization + @SuppressWarnings("unused") private MilliSpan() { this.begin = 0; this.name = null; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java index a7d7974a8..de433c6be 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/TimelineAnnotation.java @@ -28,6 +28,7 @@ public class TimelineAnnotation { private final long time; private final String msg; + @SuppressWarnings("unused") private TimelineAnnotation() { this.time = 0; this.msg = null; diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index f9bc7e233..513422f52 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.autoconfig; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.sleuth.IdGenerator; import org.springframework.cloud.sleuth.RandomUuidGenerator; import org.springframework.cloud.sleuth.Sampler; @@ -31,6 +32,7 @@ import org.springframework.context.annotation.Configuration; * @author Spencer Gibb */ @Configuration +@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true) public class TraceAutoConfiguration { @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java new file mode 100644 index 000000000..a5f10ca94 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncCustomAutoConfiguration.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth.instrument.async; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; + +@Configuration +@ConditionalOnBean(AsyncConfigurer.class) +@AutoConfigureBefore(AsyncDefaultAutoConfiguration.class) +@ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true) +@AutoConfigureAfter(TraceSchedulingAutoConfiguration.class) +public class AsyncCustomAutoConfiguration implements BeanPostProcessor { + + @Autowired + private BeanFactory beanFactory; + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof AsyncConfigurer) { + AsyncConfigurer configurer = (AsyncConfigurer) bean; + return new LazyTraceAsyncCustomizer(this.beanFactory, configurer); + } + return bean; + } + +} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java new file mode 100644 index 000000000..52cd44943 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfiguration.java @@ -0,0 +1,50 @@ +/* + * Copyright 2015 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.sleuth.instrument.async; + +import java.util.concurrent.Executor; + +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.annotation.AsyncConfigurerSupport; +import org.springframework.scheduling.annotation.EnableAsync; + +@EnableAsync +@Configuration +@ConditionalOnMissingBean(AsyncConfigurer.class) +@ConditionalOnProperty(value = "spring.sleuth.async.enabled", matchIfMissing = true) +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(AsyncCustomAutoConfiguration.class) +public class AsyncDefaultAutoConfiguration extends AsyncConfigurerSupport { + + @Autowired + private BeanFactory beanFactory; + + @Override + public Executor getAsyncExecutor() { + return new LazyTraceExecutor(this.beanFactory, new SimpleAsyncTaskExecutor()); + } + +} \ No newline at end of file diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/LazyTraceAsyncCustomizer.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java similarity index 82% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/LazyTraceAsyncCustomizer.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java index 10461898b..e8a6df7bf 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/LazyTraceAsyncCustomizer.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceAsyncCustomizer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.sleuth.instrument.scheduling; +package org.springframework.cloud.sleuth.instrument.async; import java.util.concurrent.Executor; @@ -22,7 +22,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.beans.factory.BeanFactory; -import org.springframework.cloud.sleuth.Trace; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; @@ -33,16 +32,12 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport; @RequiredArgsConstructor public class LazyTraceAsyncCustomizer extends AsyncConfigurerSupport { - private Trace trace; private final BeanFactory beanFactory; private final AsyncConfigurer delegate; @Override public Executor getAsyncExecutor() { - if (this.trace == null) { - this.trace = this.beanFactory.getBean(Trace.class); - } - return new TraceExecutor(this.trace, this.delegate.getAsyncExecutor()); + return new LazyTraceExecutor(this.beanFactory, this.delegate.getAsyncExecutor()); } @Override diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceExecutor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java similarity index 67% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceExecutor.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java index 796b32d28..5638c4064 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceExecutor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/LazyTraceExecutor.java @@ -14,12 +14,14 @@ * limitations under the License. */ -package org.springframework.cloud.sleuth.instrument.scheduling; +package org.springframework.cloud.sleuth.instrument.async; import java.util.concurrent.Executor; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.cloud.sleuth.Trace; import org.springframework.cloud.sleuth.instrument.TraceRunnable; @@ -28,13 +30,22 @@ import org.springframework.cloud.sleuth.instrument.TraceRunnable; * */ @RequiredArgsConstructor -public class TraceExecutor implements Executor { +public class LazyTraceExecutor implements Executor { - private final Trace trace; + private Trace trace; + private final BeanFactory beanFactory; private final Executor delegate; @Override public void execute(Runnable command) { + if (this.trace == null) { + try { + this.trace = this.beanFactory.getBean(Trace.class); + } + catch (NoSuchBeanDefinitionException e) { + this.delegate.execute(command); + } + } this.delegate.execute(new TraceRunnable(this.trace, command)); } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java index 628644e32..1b8c95581 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/integration/TraceSpringIntegrationAutoConfiguration.java @@ -16,8 +16,12 @@ package org.springframework.cloud.sleuth.instrument.integration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.config.GlobalChannelInterceptor; @@ -27,6 +31,8 @@ import org.springframework.integration.config.GlobalChannelInterceptor; */ @Configuration @ConditionalOnClass(GlobalChannelInterceptor.class) +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(TraceAutoConfiguration.class) public class TraceSpringIntegrationAutoConfiguration { @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java index e7f690d97..093bb5851 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/scheduling/TraceSchedulingAutoConfiguration.java @@ -20,25 +20,16 @@ package org.springframework.cloud.sleuth.instrument.scheduling; * @author Spencer Gibb */ -import java.util.concurrent.Executor; - import org.aspectj.lang.ProceedingJoinPoint; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.scheduling.annotation.AsyncConfigurer; -import org.springframework.scheduling.annotation.AsyncConfigurerSupport; -import org.springframework.scheduling.annotation.EnableAsync; /** * Registers beans related to task scheduling. @@ -51,6 +42,8 @@ import org.springframework.scheduling.annotation.EnableAsync; @Configuration @EnableAspectJAutoProxy @ConditionalOnProperty(value = "spring.sleuth.schedule.enabled", matchIfMissing = true) +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(TraceAutoConfiguration.class) public class TraceSchedulingAutoConfiguration { @ConditionalOnClass(ProceedingJoinPoint.class) @@ -59,44 +52,4 @@ public class TraceSchedulingAutoConfiguration { return new TraceSchedulingAspect(trace); } - @EnableAsync - @Configuration - @ConditionalOnMissingBean(AsyncConfigurer.class) - protected static class AsyncDefaultConfiguration extends AsyncConfigurerSupport { - - @Autowired - private Trace trace; - - @Override - public Executor getAsyncExecutor() { - return new TraceExecutor(this.trace, new SimpleAsyncTaskExecutor()); - } - - } - - @Configuration - @ConditionalOnBean(AsyncConfigurer.class) - protected static class AsyncCustomConfiguration implements BeanPostProcessor { - - @Autowired - private BeanFactory beanFactory; - - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) - throws BeansException { - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) - throws BeansException { - if (bean instanceof AsyncConfigurer) { - AsyncConfigurer configurer = (AsyncConfigurer) bean; - return new LazyTraceAsyncCustomizer(this.beanFactory, configurer); - } - return bean; - } - - } - } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java index 81b0272fb..d208a8094 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceFilter.java @@ -121,6 +121,7 @@ public class TraceFilter extends OncePerRequestFilter { } else { traceScope = this.trace.startSpan(name); + request.setAttribute(TRACE_REQUEST_ATTR, traceScope); } } @@ -131,13 +132,12 @@ public class TraceFilter extends OncePerRequestFilter { filterChain.doFilter(request, response); } finally { - if (request.isAsyncSupported() && request.isAsyncStarted()) { - //TODO: howto deal with response annotations and async? + if (isAsyncStarted(request) || request.isAsyncStarted()) { + //TODO: how to deal with response annotations and async? return; } if (traceScope != null) { addResponseAnnotations(response); - traceScope.close(); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java index c95e27737..421e2d7c1 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/TraceWebAutoConfiguration.java @@ -19,11 +19,14 @@ import java.util.regex.Pattern; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; @@ -39,6 +42,8 @@ import org.springframework.util.StringUtils; @Configuration @ConditionalOnProperty(value = "spring.sleuth.web.enabled", matchIfMissing = true) @ConditionalOnWebApplication +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(TraceAutoConfiguration.class) public class TraceWebAutoConfiguration { /** diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java index c10c0a309..988ab1832 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebClientAutoConfiguration.java @@ -21,9 +21,13 @@ import java.util.Collection; import javax.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @@ -34,6 +38,8 @@ import org.springframework.web.client.RestTemplate; @Configuration @ConditionalOnProperty(value = "spring.sleuth.client.enabled", matchIfMissing = true) @ConditionalOnClass(RestTemplate.class) +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(TraceAutoConfiguration.class) public class TraceWebClientAutoConfiguration { @Bean diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/JsonLogSpanListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/JsonLogSpanListener.java index efc0a32e7..69b0b33a4 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/JsonLogSpanListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/JsonLogSpanListener.java @@ -32,7 +32,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Spencer Gibb */ @CommonsLog -@Order(Ordered.LOWEST_PRECEDENCE) @Data public class JsonLogSpanListener { @@ -41,16 +40,17 @@ public class JsonLogSpanListener { private final ObjectMapper objectMapper = new ObjectMapper(); public JsonLogSpanListener() { - prefix = "[span]"; - suffix = "[endspan]"; - objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + this.prefix = "[span]"; + this.suffix = "[endspan]"; + this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } @SneakyThrows @EventListener(SpanStoppedEvent.class) + @Order(Ordered.LOWEST_PRECEDENCE-10) public void stop(SpanStoppedEvent event) { - log.info(prefix + objectMapper.writeValueAsString(event.getSpan()) + - suffix); + log.info(this.prefix + this.objectMapper.writeValueAsString(event.getSpan()) + + this.suffix); } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java index 74c31f1a2..d8d3c2619 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/SleuthLogAutoConfiguration.java @@ -18,8 +18,12 @@ package org.springframework.cloud.sleuth.log; import org.apache.commons.logging.Log; import org.slf4j.MDC; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cloud.sleuth.Trace; +import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -27,6 +31,8 @@ import org.springframework.context.annotation.Configuration; * @author Spencer Gibb */ @Configuration +@ConditionalOnBean(Trace.class) +@AutoConfigureAfter(TraceAutoConfiguration.class) public class SleuthLogAutoConfiguration { @Configuration diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java index 019378c85..64246409f 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/log/Slf4jSpanListener.java @@ -33,10 +33,10 @@ import org.springframework.core.annotation.Order; * @author Spencer Gibb */ @Slf4j -@Order(Ordered.LOWEST_PRECEDENCE) public class Slf4jSpanListener { @EventListener(SpanStartedEvent.class) + @Order(Ordered.LOWEST_PRECEDENCE) public void start(SpanStartedEvent event) { Span span = event.getSpan(); MDC.put(Trace.SPAN_ID_NAME, span.getSpanId()); @@ -49,6 +49,7 @@ public class Slf4jSpanListener { } @EventListener(SpanStoppedEvent.class) + @Order(Ordered.LOWEST_PRECEDENCE) public void stop(SpanStoppedEvent event) { //TODO: what should this log level be? log.info("Stopped span: {}", event.getSpan()); diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index 32b4b9e5e..6c92c6089 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -3,6 +3,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration,\ org.springframework.cloud.sleuth.log.SleuthLogAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.integration.TraceSpringIntegrationAutoConfiguration,\ +org.springframework.cloud.sleuth.instrument.async.AsyncCustomAutoConfiguration,\ +org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java index 4cdbe8e80..75d807a99 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleApplication.java @@ -16,8 +16,6 @@ package org.springframework.cloud.sleuth.sample; -import com.github.kristofa.brave.LoggingSpanCollectorImpl; -import com.github.kristofa.brave.SpanCollector; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -27,6 +25,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableAsync; +import com.github.kristofa.brave.LoggingSpanCollectorImpl; +import com.github.kristofa.brave.SpanCollector; + /** * @author Spencer Gibb */ diff --git a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java index b4b4ef620..fe400bc27 100644 --- a/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java +++ b/spring-cloud-sleuth-sample/src/main/java/org/springframework/cloud/sleuth/sample/SampleController.java @@ -39,7 +39,7 @@ import org.springframework.web.client.RestTemplate; */ @Slf4j @RestController -class SampleController implements +public class SampleController implements ApplicationListener { @Autowired private RestTemplate restTemplate; diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java index e7f504c49..6653d0c1b 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin/ZipkinSpanListener.java @@ -49,7 +49,6 @@ import com.twitter.zipkin.gen.zipkinCoreConstants; * @author Spencer Gibb */ @CommonsLog -@Order(0) public class ZipkinSpanListener { private SpanCollector spanCollector; @@ -63,6 +62,7 @@ public class ZipkinSpanListener { } @EventListener + @Order(0) public void start(SpanStartedEvent event) { if (event.getParent()!=null && event.getParent().isRemote()) { event.getParent().addTimelineAnnotation(zipkinCoreConstants.SERVER_RECV); @@ -71,17 +71,20 @@ public class ZipkinSpanListener { } @EventListener + @Order(0) public void clientSend(ClientSentEvent event) { event.getSpan().addTimelineAnnotation(zipkinCoreConstants.CLIENT_SEND); } @EventListener + @Order(0) public void clientReceive(ClientReceivedEvent event) { event.getSpan().addTimelineAnnotation(zipkinCoreConstants.CLIENT_RECV); } @EventListener - public void start(SpanStoppedEvent event) { + @Order(0) + public void stop(SpanStoppedEvent event) { if (event.getParent()!=null && event.getParent().isRemote()) { event.getParent().addTimelineAnnotation(zipkinCoreConstants.SERVER_SEND); this.spanCollector.collect(convert(event.getParent())); @@ -93,10 +96,9 @@ public class ZipkinSpanListener { /** * Converts a given Sleuth span to a Zipkin Span. * */ public com.twitter.zipkin.gen.Span convert(Span span) {