Refactored the async tracing
This commit is contained in:
@@ -20,28 +20,78 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.cloud.sleuth.SpanAccessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.AsyncClientHttpRequest;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
/**
|
||||
* Wrapper that adds trace related headers to the created AsyncClientHttpRequest
|
||||
*
|
||||
* @see org.springframework.web.client.RestTemplate
|
||||
* @see SpanAccessor
|
||||
* Wrapper that adds trace related headers to the created {@link AsyncClientHttpRequest}
|
||||
* and to the {@link ClientHttpRequest}
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Spencer Gibb
|
||||
*/
|
||||
public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttpRequestInterceptor
|
||||
implements AsyncClientHttpRequestFactory {
|
||||
implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory {
|
||||
|
||||
private final Tracer tracer;
|
||||
private final AsyncClientHttpRequestFactory delegate;
|
||||
private final ClientHttpRequestFactory syncDelegate;
|
||||
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor,
|
||||
/**
|
||||
* According to the javadocs all Spring {@link AsyncClientHttpRequestFactory} implement
|
||||
* the {@link ClientHttpRequestFactory} interface.
|
||||
*
|
||||
* In case that it's not true we're setting the {@link SimpleClientHttpRequestFactory}
|
||||
* as a default for sync request processing.
|
||||
*
|
||||
* @see org.springframework.web.client.AsyncRestTemplate#AsyncRestTemplate(AsyncClientHttpRequestFactory)
|
||||
*/
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer,
|
||||
AsyncClientHttpRequestFactory delegate) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
this.delegate = delegate;
|
||||
this.syncDelegate = delegate instanceof ClientHttpRequestFactory ?
|
||||
(ClientHttpRequestFactory) delegate : defaultClientHttpRequestFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation that creates a {@link SimpleClientHttpRequestFactory} that
|
||||
* has a wrapped task executor via the {@link TraceAsyncListenableTaskExecutor}
|
||||
*/
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = defaultClientHttpRequestFactory();
|
||||
this.delegate = simpleClientHttpRequestFactory;
|
||||
this.syncDelegate = simpleClientHttpRequestFactory;
|
||||
}
|
||||
|
||||
public TraceAsyncClientHttpRequestFactoryWrapper(SpanAccessor accessor, Tracer tracer,
|
||||
AsyncClientHttpRequestFactory delegate, ClientHttpRequestFactory syncDelegate) {
|
||||
super(accessor);
|
||||
this.tracer = tracer;
|
||||
this.delegate = delegate;
|
||||
this.syncDelegate = syncDelegate;
|
||||
}
|
||||
|
||||
private SimpleClientHttpRequestFactory defaultClientHttpRequestFactory() {
|
||||
SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
|
||||
simpleClientHttpRequestFactory.setTaskExecutor(asyncListenableTaskExecutor(this.tracer));
|
||||
return simpleClientHttpRequestFactory;
|
||||
}
|
||||
|
||||
private AsyncListenableTaskExecutor asyncListenableTaskExecutor(Tracer tracer) {
|
||||
ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
threadPoolTaskScheduler.initialize();
|
||||
return new TraceAsyncListenableTaskExecutor(threadPoolTaskScheduler, tracer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,4 +105,16 @@ public class TraceAsyncClientHttpRequestFactoryWrapper extends AbstractTraceHttp
|
||||
publishStartEvent(request);
|
||||
return request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod)
|
||||
throws IOException {
|
||||
ClientHttpRequest request = this.syncDelegate.createRequest(uri, httpMethod);
|
||||
if (!isTracing()) {
|
||||
doNotSampleThisSpan(request);
|
||||
return request;
|
||||
}
|
||||
publishStartEvent(request);
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2013-2016 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.web.client;
|
||||
|
||||
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.SpanAccessor;
|
||||
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.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = "spring.sleuth.async.client.enabled", matchIfMissing = true)
|
||||
@ConditionalOnClass(AsyncRestTemplate.class)
|
||||
@ConditionalOnBean(SpanAccessor.class)
|
||||
@AutoConfigureAfter(TraceAutoConfiguration.class)
|
||||
public class TraceWebAsyncClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory(SpanAccessor spanAccessor, Tracer tracer) {
|
||||
return new TraceAsyncClientHttpRequestFactoryWrapper(spanAccessor, tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AsyncRestTemplate asyncRestTemplate(AsyncClientHttpRequestFactory asyncClientHttpRequestFactory) {
|
||||
return new AsyncRestTemplate(asyncClientHttpRequestFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,16 +29,10 @@ 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.SpanAccessor;
|
||||
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.core.task.AsyncListenableTaskExecutor;
|
||||
import org.springframework.http.client.AsyncClientHttpRequestFactory;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.web.client.AsyncRestTemplate;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
@@ -63,29 +57,6 @@ public class TraceWebClientAutoConfiguration {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AsyncClientHttpRequestFactory asyncClientHttpRequestFactory(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(SpanAccessor spanAccessor,
|
||||
AsyncClientHttpRequestFactory asyncClientHttpRequestFactory, RestTemplate restTemplate) {
|
||||
return new AsyncRestTemplate(new TraceAsyncClientHttpRequestFactoryWrapper(
|
||||
spanAccessor, asyncClientHttpRequestFactory), restTemplate);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class TraceInterceptorConfiguration {
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfigurati
|
||||
org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.client.TraceWebAsyncClientAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.web.client.TraceFeignClientAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.instrument.zuul.TraceZuulAutoConfiguration
|
||||
|
||||
|
||||
Reference in New Issue
Block a user