diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java index 2da89a861..c3671e2e2 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/ExecutorBeanPostProcessor.java @@ -73,6 +73,7 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof LazyTraceThreadPoolTaskExecutor + || bean instanceof TraceableScheduledExecutorService || bean instanceof TraceableExecutorService || bean instanceof LazyTraceAsyncTaskExecutor || bean instanceof LazyTraceExecutor) { @@ -87,6 +88,14 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { log.info("Not instrumenting bean " + beanName); } } + else if (bean instanceof ScheduledExecutorService) { + if (isProxyNeeded(beanName)) { + return wrapScheduledExecutorService(bean); + } + else { + log.info("Not instrumenting bean " + beanName); + } + } else if (bean instanceof ExecutorService) { if (isProxyNeeded(beanName)) { return wrapExecutorService(bean); @@ -148,6 +157,14 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { return createExecutorServiceProxy(bean, cglibProxy, executor); } + private Object wrapScheduledExecutorService(Object bean) { + ScheduledExecutorService executor = (ScheduledExecutorService) bean; + boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers()); + boolean methodFinal = anyFinalMethods(executor, ExecutorService.class); + boolean cglibProxy = !classFinal && !methodFinal; + return createScheduledExecutorServiceProxy(bean, cglibProxy, executor); + } + private Object wrapAsyncTaskExecutor(Object bean) { AsyncTaskExecutor executor = (AsyncTaskExecutor) bean; boolean classFinal = Modifier.isFinal(bean.getClass().getModifiers()); @@ -193,6 +210,12 @@ class ExecutorBeanPostProcessor implements BeanPostProcessor { }); } + Object createScheduledExecutorServiceProxy(Object bean, boolean cglibProxy, + ScheduledExecutorService executor) { + return getProxiedObject(bean, cglibProxy, executor, + () -> new TraceableScheduledExecutorService(this.beanFactory, executor)); + } + Object createAsyncTaskExecutorProxy(Object bean, boolean cglibProxy, AsyncTaskExecutor executor) { return getProxiedObject(bean, cglibProxy, executor, () -> { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthKafkaStreamsConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthKafkaStreamsConfiguration.java index 0e46f3721..7fb7f6e8e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthKafkaStreamsConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/SleuthKafkaStreamsConfiguration.java @@ -60,12 +60,12 @@ public class SleuthKafkaStreamsConfiguration { */ @Bean @ConditionalOnMissingBean - KafkaStreamsTracing kafkaStreamsTracing(Tracing tracing) { + static KafkaStreamsTracing kafkaStreamsTracing(Tracing tracing) { return KafkaStreamsTracing.create(tracing); } @Bean - KafkaStreamsBuilderFactoryBeanPostProcessor kafkaStreamsBuilderFactoryBeanPostProcessor( + static KafkaStreamsBuilderFactoryBeanPostProcessor kafkaStreamsBuilderFactoryBeanPostProcessor( KafkaStreamsTracing kafkaStreamsTracing) { return new KafkaStreamsBuilderFactoryBeanPostProcessor(kafkaStreamsTracing); } 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 b1004285f..c78114d84 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 @@ -160,7 +160,7 @@ public class TraceWebClientAutoConfiguration { static class NettyConfiguration { @Bean - public HttpClientBeanPostProcessor httpClientBeanPostProcessor( + static HttpClientBeanPostProcessor httpClientBeanPostProcessor( BeanFactory beanFactory) { return new HttpClientBeanPostProcessor(beanFactory); } @@ -173,14 +173,14 @@ public class TraceWebClientAutoConfiguration { protected static class TraceOAuthConfiguration { @Bean - UserInfoRestTemplateCustomizerBPP userInfoRestTemplateCustomizerBeanPostProcessor( + static UserInfoRestTemplateCustomizerBPP userInfoRestTemplateCustomizerBeanPostProcessor( BeanFactory beanFactory) { return new UserInfoRestTemplateCustomizerBPP(beanFactory); } @Bean @ConditionalOnMissingBean - UserInfoRestTemplateCustomizer traceUserInfoRestTemplateCustomizer( + static UserInfoRestTemplateCustomizer traceUserInfoRestTemplateCustomizer( BeanFactory beanFactory) { return new TraceUserInfoRestTemplateCustomizer(beanFactory); } 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 b6a63ceb7..ae1f852a5 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 @@ -54,7 +54,7 @@ public class SleuthLogAutoConfiguration { @Bean @ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true) - public CurrentTraceContext.ScopeDecorator slf4jSpanDecorator( + static CurrentTraceContext.ScopeDecorator slf4jSpanDecorator( SleuthProperties sleuthProperties, SleuthSlf4jProperties sleuthSlf4jProperties) { return new Slf4jScopeDecorator(sleuthProperties, sleuthSlf4jProperties); diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/propagation/SleuthTagPropagationAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/propagation/SleuthTagPropagationAutoConfiguration.java index da8bb98f3..7023750f6 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/propagation/SleuthTagPropagationAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/propagation/SleuthTagPropagationAutoConfiguration.java @@ -42,7 +42,7 @@ public class SleuthTagPropagationAutoConfiguration { protected static class TagPropagationConfiguration { @Bean - public FinishedSpanHandler sleuthFinishedSpanHandler( + static FinishedSpanHandler sleuthFinishedSpanHandler( SleuthProperties sleuthProperties, SleuthTagPropagationProperties tagPropagationProperties) { return new TagPropagationFinishedSpanHandler(sleuthProperties, diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfigurationTests.java new file mode 100644 index 000000000..c002b8cd5 --- /dev/null +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/AsyncDefaultAutoConfigurationTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2020 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 + * + * https://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.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.assertj.core.api.BDDAssertions; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = AsyncDefaultAutoConfigurationTests.Config.class) +public class AsyncDefaultAutoConfigurationTests { + + @Autowired + ScheduledExecutorService executor; + + @Test + public void should_work_with_proxies() { + BDDAssertions.then(this.executor).isNotNull() + .isInstanceOf(TraceableScheduledExecutorService.class); + } + + @Configuration + @EnableAutoConfiguration + static class Config { + + @Bean + public ScheduledExecutorService createExecutorService() { + return Executors.newSingleThreadScheduledExecutor(); + } + + } + +}