Refactored the async tracing

This commit is contained in:
Marcin Grzejszczak
2016-02-22 18:29:52 +01:00
parent 7927f4914f
commit 0cd1441f9b
4 changed files with 123 additions and 35 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -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