diff --git a/README.adoc b/README.adoc index c4f9b28fb..7fa260c97 100644 --- a/README.adoc +++ b/README.adoc @@ -598,11 +598,11 @@ a modified file in the correct place. Just commit it and push the change. If you don't have an IDE preference we would recommend that you use http://www.springsource.com/developer/sts[Spring Tools Suite] or http://eclipse.org[Eclipse] when working with the code. We use the -http://eclipse.org/m2e/[m2eclipe] eclipse plugin for maven support. Other IDEs and tools +http://eclipse.org/m2e/[m2eclipse] eclipse plugin for maven support. Other IDEs and tools should also work without issue as long as they use Maven 3.3.3 or better. ==== Importing into eclipse with m2eclipse -We recommend the http://eclipse.org/m2e/[m2eclipe] eclipse plugin when working with +We recommend the http://eclipse.org/m2e/[m2eclipse] eclipse plugin when working with eclipse. If you don't already have m2eclipse installed it is available from the "eclipse marketplace". diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceExecutorBeanPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceExecutorBeanPostProcessor.java index 04e8ea0ef..3d59e9e48 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceExecutorBeanPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceExecutorBeanPostProcessor.java @@ -17,6 +17,7 @@ package org.springframework.cloud.sleuth.instrument.async; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -43,8 +44,11 @@ class TraceExecutorBeanPostProcessor implements BeanPostProcessor { if (bean instanceof ThreadPoolTaskExecutor && !(bean instanceof TaskScheduler) && !(bean instanceof LazyTraceThreadPoolTaskExecutor)) { return new LazyTraceThreadPoolTaskExecutor(this.beanFactory, (ThreadPoolTaskExecutor) bean); - } else if (bean instanceof Executor && !(bean instanceof TaskScheduler) && !(bean instanceof LazyTraceExecutor)) { + } else if (bean instanceof Executor && !(bean instanceof ExecutorService) && + !(bean instanceof TaskScheduler) && !(bean instanceof LazyTraceExecutor)) { return new LazyTraceExecutor(this.beanFactory, (Executor) bean); + } else if (bean instanceof ExecutorService) { + return new TraceableExecutorService(this.beanFactory, (ExecutorService) bean); } return bean; } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java index 4bd0d578e..fbf547f28 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/async/TraceableExecutorService.java @@ -25,6 +25,7 @@ import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.springframework.beans.factory.BeanFactory; import org.springframework.cloud.sleuth.SpanNamer; import org.springframework.cloud.sleuth.TraceKeys; import org.springframework.cloud.sleuth.Tracer; @@ -36,17 +37,24 @@ import org.springframework.cloud.sleuth.Tracer; * @since 1.0.0 */ public class TraceableExecutorService implements ExecutorService { - final ExecutorService delegate; - final Tracer tracer; + ExecutorService delegate; + Tracer tracer; private final String spanName; - final TraceKeys traceKeys; - final SpanNamer spanNamer; + TraceKeys traceKeys; + SpanNamer spanNamer; + BeanFactory beanFactory; public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer, TraceKeys traceKeys, SpanNamer spanNamer) { this(delegate, tracer, traceKeys, spanNamer, null); } + public TraceableExecutorService(BeanFactory beanFactory, final ExecutorService delegate) { + this.delegate = delegate; + this.beanFactory = beanFactory; + this.spanName = null; + } + public TraceableExecutorService(final ExecutorService delegate, final Tracer tracer, TraceKeys traceKeys, SpanNamer spanNamer, String spanName) { this.delegate = delegate; @@ -58,8 +66,8 @@ public class TraceableExecutorService implements ExecutorService { @Override public void execute(Runnable command) { - final Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, - this.spanNamer, command, this.spanName); + final Runnable r = new LocalComponentTraceRunnable(tracer(), traceKeys(), + spanNamer(), command, this.spanName); this.delegate.execute(r); } @@ -90,22 +98,22 @@ public class TraceableExecutorService implements ExecutorService { @Override public Future submit(Callable task) { - Callable c = new LocalComponentTraceCallable<>(this.tracer, this.traceKeys, - this.spanNamer, this.spanName, task); + Callable c = new LocalComponentTraceCallable<>(tracer(), traceKeys(), + spanNamer(), this.spanName, task); return this.delegate.submit(c); } @Override public Future submit(Runnable task, T result) { - Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, - this.spanNamer, task, this.spanName); + Runnable r = new LocalComponentTraceRunnable(tracer(), traceKeys(), + spanNamer(), task, this.spanName); return this.delegate.submit(r, result); } @Override public Future submit(Runnable task) { - Runnable r = new LocalComponentTraceRunnable(this.tracer, this.traceKeys, - this.spanNamer, task, this.spanName); + Runnable r = new LocalComponentTraceRunnable(tracer(), traceKeys(), + spanNamer(), task, this.spanName); return this.delegate.submit(r); } @@ -135,11 +143,32 @@ public class TraceableExecutorService implements ExecutorService { List> ts = new ArrayList<>(); for (Callable task : tasks) { if (!(task instanceof LocalComponentTraceCallable)) { - ts.add(new LocalComponentTraceCallable<>(this.tracer, this.traceKeys, - this.spanNamer, this.spanName, task)); + ts.add(new LocalComponentTraceCallable<>(tracer(), traceKeys(), + spanNamer(), this.spanName, task)); } } return ts; } + Tracer tracer() { + if (this.tracer == null && this.beanFactory != null) { + this.tracer = this.beanFactory.getBean(Tracer.class); + } + return this.tracer; + } + + TraceKeys traceKeys() { + if (this.traceKeys == null && this.beanFactory != null) { + this.traceKeys = this.beanFactory.getBean(TraceKeys.class); + } + return this.traceKeys; + } + + SpanNamer spanNamer() { + if (this.spanNamer == null && this.beanFactory != null) { + this.spanNamer = this.beanFactory.getBean(SpanNamer.class); + } + return this.spanNamer; + } + } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java index dd3c17a08..1c8e3b283 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/async/issues/issue410/Issue410Tests.java @@ -19,6 +19,8 @@ package org.springframework.cloud.sleuth.instrument.async.issues.issue410; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.logging.Log; @@ -36,6 +38,7 @@ import org.springframework.cloud.sleuth.Sampler; import org.springframework.cloud.sleuth.Span; import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor; +import org.springframework.cloud.sleuth.instrument.async.TraceableExecutorService; import org.springframework.cloud.sleuth.sampler.AlwaysSampler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -67,6 +70,10 @@ public class Issue410Tests { @Autowired Tracer tracer; @Autowired AsyncTask asyncTask; @Autowired RestTemplate restTemplate; + /** + * Related to issue #445 + */ + @Autowired ExecutorService executorService; @Test public void should_pass_tracing_info_for_tasks_running_without_a_pool() { @@ -138,6 +145,14 @@ public class Issue410Tests { } } + /** + * Related to issue #445 + */ + @Test + public void should_wrap_executor_service_in_trace_representation() { + then(this.executorService).isInstanceOf(TraceableExecutorService.class); + } + private int port() { return this.environment.getProperty("local.server.port", Integer.class); } @@ -148,11 +163,11 @@ public class Issue410Tests { @EnableAsync class AppConfig { - @Bean Sampler testSampler() { + @Bean public Sampler testSampler() { return new AlwaysSampler(); } - @Bean RestTemplate restTemplate() { + @Bean public RestTemplate restTemplate() { return new RestTemplate(); } @@ -281,4 +296,11 @@ class Application { return Span.idToHex(this.asyncTask.taskScheduler().getTraceId()); } + /** + * Related to issue #445 + */ + @Bean public ExecutorService executorService() { + return Executors.newSingleThreadExecutor(); + } + }