From 8f8b9893f09efbcf6aa5daad7de16a25fd63945e Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 15 Apr 2016 12:03:01 +0200 Subject: [PATCH] Easier Async configuration (#251) added possibility to provide in an easy way custom client request factories fixes #236 --- .../main/asciidoc/spring-cloud-sleuth.adoc | 9 +++- .../TraceWebAsyncClientAutoConfiguration.java | 47 ++++++++++++++++--- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc index 2f42898fc..e7b1da43b 100644 --- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc +++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc @@ -439,8 +439,13 @@ just set `spring.sleuth.web.client.enabled` to `false`. ==== Asynchronous Rest Template -Custom instrumentation is set to create and close Spans upon sending and receiving requests. To block the `AsyncRestTemplate` -features set `spring.sleuth.web.async.client.enabled` to `false`. +Custom instrumentation is set to create and close Spans upon sending and receiving requests. You can customize the `ClientHttpRequestFactory` +and the `AsyncClientHttpRequestFactory` by registering your beans. Remember to use tracing compatible implementations (e.g. don't forget to +wrap `ThreadPoolTaskScheduler` in a `TraceAsyncListenableTaskExecutor`). + +To block the `AsyncRestTemplate` features set `spring.sleuth.web.async.client.enabled` to `false`. +To disable creation of the default `TraceAsyncClientHttpRequestFactoryWrapper` set `spring.sleuth.web.async.client.factory.enabled` +to `false`. If you don't want to create `AsyncRestClient` at all set `spring.sleuth.web.async.client.template.enabled` to `false`. === Feign diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java index 320890741..e5f7e9412 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceWebAsyncClientAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.sleuth.instrument.web.client; +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; @@ -27,8 +28,13 @@ import org.springframework.cloud.sleuth.Tracer; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.http.HttpRequest; import org.springframework.http.client.AsyncClientHttpRequestFactory; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.web.client.AsyncRestTemplate; /** @@ -46,18 +52,45 @@ import org.springframework.web.client.AsyncRestTemplate; @AutoConfigureAfter(TraceAutoConfiguration.class) public class TraceWebAsyncClientAutoConfiguration { + @Autowired Tracer tracer; + @Autowired SpanInjector spanInjector; + @Autowired(required = false) ClientHttpRequestFactory clientHttpRequestFactory; + @Autowired(required = false) AsyncClientHttpRequestFactory asyncClientHttpRequestFactory; + @Bean - @ConditionalOnMissingBean - public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory(Tracer tracer, - SpanInjector spanInjector) { - return new TraceAsyncClientHttpRequestFactoryWrapper(tracer, spanInjector); + @Primary + @ConditionalOnProperty(value = "spring.sleuth.web.async.client.factory.enabled", matchIfMissing = true) + public TraceAsyncClientHttpRequestFactoryWrapper traceAsyncClientHttpRequestFactory() { + ClientHttpRequestFactory clientFactory = this.clientHttpRequestFactory; + AsyncClientHttpRequestFactory asyncClientFactory = this.asyncClientHttpRequestFactory; + if (clientFactory == null) { + clientFactory = defaultClientHttpRequestFactory(this.tracer); + } + if (asyncClientFactory == null) { + asyncClientFactory = clientFactory instanceof AsyncClientHttpRequestFactory ? + (AsyncClientHttpRequestFactory) clientFactory : defaultClientHttpRequestFactory(this.tracer); + } + return new TraceAsyncClientHttpRequestFactoryWrapper(this.tracer, this.spanInjector, + asyncClientFactory, clientFactory); + } + + private SimpleClientHttpRequestFactory defaultClientHttpRequestFactory(Tracer tracer) { + SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory(); + simpleClientHttpRequestFactory.setTaskExecutor(asyncListenableTaskExecutor(tracer)); + return simpleClientHttpRequestFactory; + } + + private AsyncListenableTaskExecutor asyncListenableTaskExecutor(Tracer tracer) { + ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); + threadPoolTaskScheduler.initialize(); + return new TraceAsyncListenableTaskExecutor(threadPoolTaskScheduler, tracer); } @Bean @ConditionalOnMissingBean - public AsyncRestTemplate asyncRestTemplate(AsyncClientHttpRequestFactory asyncClientHttpRequestFactory, - Tracer tracer) { - return new TraceAsyncRestTemplate(asyncClientHttpRequestFactory, tracer); + @ConditionalOnProperty(value = "spring.sleuth.web.async.client.template.enabled", matchIfMissing = true) + public AsyncRestTemplate traceAsyncRestTemplate() { + return new TraceAsyncRestTemplate(traceAsyncClientHttpRequestFactory(), this.tracer); } }