Merge branch '2.2.x'

This commit is contained in:
Adrian Cole
2020-05-17 18:54:30 +08:00
19 changed files with 127 additions and 248 deletions

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.autoconfig;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -40,7 +39,6 @@ import zipkin2.reporter.Reporter;
import zipkin2.reporter.ReporterMetrics;
import zipkin2.reporter.metrics.micrometer.MicrometerReporterMetrics;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -66,14 +64,13 @@ import org.springframework.util.StringUtils;
* @author Marcin Grzejszczak
* @author Tim Ysewyn
* @since 2.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true)
@EnableConfigurationProperties(SleuthProperties.class)
@Import({ TraceBaggageConfiguration.class, SamplerAutoConfiguration.class })
// public allows @AutoConfigureAfter(TraceAutoConfiguration)
// for components needing Tracing
public class TraceAutoConfiguration {
/**
@@ -86,19 +83,15 @@ public class TraceAutoConfiguration {
*/
public static final String DEFAULT_SERVICE_NAME = "default";
@Autowired(required = false)
List<SpanHandler> spanHandlers = new ArrayList<>();
@Autowired(required = false)
List<TracingCustomizer> tracingCustomizers = new ArrayList<>();
@Bean
@ConditionalOnMissingBean
// NOTE: stable bean name as might be used outside sleuth
Tracing tracing(@LocalServiceName String serviceName, Propagation.Factory factory,
CurrentTraceContext currentTraceContext, Sampler sampler,
ErrorParser errorParser, SleuthProperties sleuthProperties,
@Nullable List<Reporter<zipkin2.Span>> spanReporters) {
@Nullable List<Reporter<zipkin2.Span>> spanReporters,
@Nullable List<SpanHandler> spanHandlers,
@Nullable List<TracingCustomizer> tracingCustomizers) {
Tracing.Builder builder = Tracing.newBuilder().sampler(sampler)
.errorParser(errorParser)
.localServiceName(StringUtils.isEmpty(serviceName) ? DEFAULT_SERVICE_NAME
@@ -108,11 +101,15 @@ public class TraceAutoConfiguration {
spanReporters != null ? spanReporters : Collections.emptyList()))
.traceId128Bit(sleuthProperties.isTraceId128())
.supportsJoin(sleuthProperties.isSupportsJoin());
for (SpanHandler spanHandlerFactory : this.spanHandlers) {
builder.addSpanHandler(spanHandlerFactory);
if (spanHandlers != null) {
for (SpanHandler spanHandlerFactory : spanHandlers) {
builder.addSpanHandler(spanHandlerFactory);
}
}
for (TracingCustomizer customizer : this.tracingCustomizers) {
customizer.customize(builder);
if (tracingCustomizers != null) {
for (TracingCustomizer customizer : tracingCustomizers) {
customizer.customize(builder);
}
}
return builder.build();
}
@@ -129,9 +126,6 @@ public class TraceAutoConfiguration {
return new DefaultSpanNamer();
}
@Autowired(required = false)
List<CurrentTraceContextCustomizer> currentTraceContextCustomizers = new ArrayList<>();
@Bean
CurrentTraceContext sleuthCurrentTraceContext(CurrentTraceContext.Builder builder,
@Nullable List<CurrentTraceContext.ScopeDecorator> scopeDecorators,

View File

@@ -29,10 +29,8 @@ import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
*
* @author Dave Syer
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class LazyTraceAsyncCustomizer extends AsyncConfigurerSupport {
private final BeanFactory beanFactory;

View File

@@ -35,10 +35,8 @@ import org.springframework.core.task.AsyncTaskExecutor;
*
* @author Marcin Grzejszczak
* @since 2.1.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class LazyTraceAsyncTaskExecutor implements AsyncTaskExecutor {
private static final Log log = LogFactory.getLog(LazyTraceAsyncTaskExecutor.class);

View File

@@ -32,10 +32,8 @@ import org.springframework.cloud.sleuth.SpanNamer;
*
* @author Dave Syer
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class LazyTraceExecutor implements Executor {
private static final Log log = LogFactory.getLog(LazyTraceExecutor.class);

View File

@@ -39,11 +39,9 @@ import org.springframework.util.concurrent.ListenableFuture;
*
* @author Marcin Grzejszczak
* @since 1.0.10
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@SuppressWarnings("serial")
// public as most types in this package were documented for use
public class LazyTraceThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final Log log = LogFactory

View File

@@ -33,10 +33,8 @@ import org.springframework.cloud.sleuth.SpanNamer;
* @author Spencer Gibb
* @author Marcin Grzejszczak
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class TraceCallable<V> implements Callable<V> {
/**

View File

@@ -30,10 +30,8 @@ import org.springframework.cloud.sleuth.SpanNamer;
* @author Spencer Gibb
* @author Marcin Grzejszczak
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class TraceRunnable implements Runnable {
/**

View File

@@ -36,10 +36,8 @@ import org.springframework.cloud.sleuth.SpanNamer;
*
* @author Gaurav Rai Mazra
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class TraceableExecutorService implements ExecutorService {
final ExecutorService delegate;

View File

@@ -29,10 +29,8 @@ import org.springframework.beans.factory.BeanFactory;
*
* @author Gaurav Rai Mazra
* @since 1.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
// public as most types in this package were documented for use
public class TraceableScheduledExecutorService extends TraceableExecutorService
implements ScheduledExecutorService {

View File

@@ -17,7 +17,6 @@
package org.springframework.cloud.sleuth.instrument.messaging;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import brave.Span;
@@ -47,7 +46,6 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -77,10 +75,7 @@ import org.springframework.util.ReflectionUtils;
*
* @author Marcin Grzejszczak
* @since 2.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(Tracing.class)
@ConditionalOnClass(MessagingTracing.class)
@@ -88,17 +83,17 @@ import org.springframework.util.ReflectionUtils;
TraceSpringMessagingAutoConfiguration.class })
@OnMessagingEnabled
@EnableConfigurationProperties(SleuthMessagingProperties.class)
// public allows @AutoConfigureAfter(TraceMessagingAutoConfiguration)
// for components needing MessagingTracing
public class TraceMessagingAutoConfiguration {
@Autowired(required = false)
List<MessagingTracingCustomizer> messagingTracingCustomizers = new ArrayList<>();
@Bean
@ConditionalOnMissingBean
// NOTE: stable bean name as might be used outside sleuth
MessagingTracing messagingTracing(Tracing tracing,
@Nullable @ProducerSampler SamplerFunction<MessagingRequest> producerSampler,
@Nullable @ConsumerSampler SamplerFunction<MessagingRequest> consumerSampler) {
@Nullable @ConsumerSampler SamplerFunction<MessagingRequest> consumerSampler,
@Nullable List<MessagingTracingCustomizer> messagingTracingCustomizers) {
MessagingTracing.Builder builder = MessagingTracing.newBuilder(tracing);
if (producerSampler != null) {
@@ -107,8 +102,10 @@ public class TraceMessagingAutoConfiguration {
if (consumerSampler != null) {
builder.consumerSampler(consumerSampler);
}
for (MessagingTracingCustomizer customizer : this.messagingTracingCustomizers) {
customizer.customize(builder);
if (messagingTracingCustomizers != null) {
for (MessagingTracingCustomizer customizer : messagingTracingCustomizers) {
customizer.customize(builder);
}
}
return builder.build();
}

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.instrument.rpc;
import java.util.ArrayList;
import java.util.List;
import brave.Tracing;
@@ -25,7 +24,6 @@ import brave.rpc.RpcTracing;
import brave.rpc.RpcTracingCustomizer;
import brave.sampler.SamplerFunction;
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;
@@ -41,27 +39,24 @@ import org.springframework.lang.Nullable;
* Auto-configuration} related to RPC based communication.
*
* @since 2.2.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.sleuth.rpc.enabled", havingValue = "true",
matchIfMissing = true)
@ConditionalOnBean(Tracing.class)
@ConditionalOnClass(RpcTracing.class)
@AutoConfigureAfter(TraceAutoConfiguration.class)
// public allows @AutoConfigureAfter(TraceRpcAutoConfiguration)
// for components needing RpcTracing
public class TraceRpcAutoConfiguration {
@Autowired(required = false)
List<RpcTracingCustomizer> rpcTracingCustomizers = new ArrayList<>();
@Bean
@ConditionalOnMissingBean
// NOTE: stable bean name as might be used outside sleuth
RpcTracing rpcTracing(Tracing tracing,
@Nullable @RpcClientSampler SamplerFunction<RpcRequest> clientSampler,
@Nullable @RpcServerSampler SamplerFunction<RpcRequest> serverSampler) {
@Nullable @RpcServerSampler SamplerFunction<RpcRequest> serverSampler,
@Nullable List<RpcTracingCustomizer> rpcTracingCustomizers) {
RpcTracing.Builder builder = RpcTracing.newBuilder(tracing);
if (clientSampler != null) {
@@ -70,8 +65,10 @@ public class TraceRpcAutoConfiguration {
if (serverSampler != null) {
builder.serverSampler(serverSampler);
}
for (RpcTracingCustomizer customizer : this.rpcTracingCustomizers) {
customizer.customize(builder);
if (rpcTracingCustomizers != null) {
for (RpcTracingCustomizer customizer : rpcTracingCustomizers) {
customizer.customize(builder);
}
}
return builder.build();
}

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.instrument.web;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
@@ -29,13 +28,15 @@ import brave.http.HttpTracingCustomizer;
import brave.sampler.SamplerFunction;
import brave.sampler.SamplerFunctions;
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;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.lang.Nullable;
@@ -45,22 +46,25 @@ import org.springframework.lang.Nullable;
*
* @author Marcin Grzejszczak
* @since 2.0.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TraceWebAutoConfiguration.class)
@ConditionalOnProperty(name = "spring.sleuth.http.enabled", havingValue = "true",
matchIfMissing = true)
@AutoConfigureAfter(TraceWebAutoConfiguration.class)
// This was formerly conditional on TraceWebAutoConfiguration, which was
// conditional on "spring.sleuth.web.enabled". As this is conditional on
// "spring.sleuth.http.enabled", to be compatible with old behavior we have
// to be conditional on two properties.
@ConditionalOnProperty(
name = { "spring.sleuth.http.enabled", "spring.sleuth.web.enabled" },
havingValue = "true", matchIfMissing = true)
@ConditionalOnBean(Tracing.class)
@ConditionalOnClass(HttpTracing.class)
@AutoConfigureAfter(TraceAutoConfiguration.class)
@Import(TraceWebAutoConfiguration.class)
// public allows @AutoConfigureAfter(TraceHttpAutoConfiguration)
// for components needing HttpTracing
public class TraceHttpAutoConfiguration {
static final int TRACING_FILTER_ORDER = Ordered.HIGHEST_PRECEDENCE + 5;
@Autowired(required = false)
List<HttpTracingCustomizer> httpTracingCustomizers = new ArrayList<>();
@Bean
@ConditionalOnMissingBean
// NOTE: stable bean name as might be used outside sleuth
@@ -72,7 +76,8 @@ public class TraceHttpAutoConfiguration {
@Nullable @HttpServerResponseParser HttpResponseParser httpServerResponseParser,
@Nullable brave.http.HttpServerParser serverParser,
@HttpClientSampler SamplerFunction<HttpRequest> httpClientSampler,
@Nullable @HttpServerSampler SamplerFunction<HttpRequest> httpServerSampler) {
@Nullable @HttpServerSampler SamplerFunction<HttpRequest> httpServerSampler,
@Nullable List<HttpTracingCustomizer> httpTracingCustomizers) {
SamplerFunction<HttpRequest> combinedSampler = combineUserProvidedSamplerWithSkipPatternSampler(
httpServerSampler, provider);
HttpTracing.Builder builder = HttpTracing.newBuilder(tracing)
@@ -102,10 +107,11 @@ public class TraceHttpAutoConfiguration {
builder.serverParser(serverParser);
}
for (HttpTracingCustomizer customizer : this.httpTracingCustomizers) {
customizer.customize(builder);
if (httpTracingCustomizers != null) {
for (HttpTracingCustomizer customizer : httpTracingCustomizers) {
customizer.customize(builder);
}
}
return builder.build();
}

View File

@@ -30,7 +30,7 @@ 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.ConditionalOnProperty;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.AsyncClientHttpRequestFactory;
@@ -54,7 +54,7 @@ import org.springframework.web.client.AsyncRestTemplate;
matchIfMissing = true)
@ConditionalOnClass(AsyncRestTemplate.class)
@ConditionalOnBean(HttpTracing.class)
@AutoConfigureAfter(TraceWebServletAutoConfiguration.class)
@AutoConfigureAfter(TraceHttpAutoConfiguration.class)
public class TraceWebAsyncClientAutoConfiguration {
@Configuration(proxyBeanMethods = false)

View File

@@ -42,7 +42,7 @@ import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoR
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.cloud.commons.httpclient.HttpClientConfiguration;
import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -69,7 +69,7 @@ import org.springframework.web.reactive.function.client.WebClient;
@Configuration(proxyBeanMethods = false)
@SleuthWebClientEnabled
@ConditionalOnBean(HttpTracing.class)
@AutoConfigureAfter(TraceWebServletAutoConfiguration.class)
@AutoConfigureAfter(TraceHttpAutoConfiguration.class)
@AutoConfigureBefore(HttpClientConfiguration.class)
public class TraceWebClientAutoConfiguration {

View File

@@ -33,10 +33,7 @@ import org.springframework.context.annotation.Configuration;
* @author Marcin Grzejszczak
* @see SamplerCondition
* @since 2.1.0
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SamplerProperties.class)
// This is not auto-configuration, but it was in the past. Leaving the name as

View File

@@ -46,10 +46,7 @@ import org.springframework.lang.Nullable;
*
* @author Marcin Grzejszczak
* @since 2.1.1
* @deprecated This type should have never been public and will be hidden or removed in
* 3.0
*/
@Deprecated
public final class TracingJmsListenerEndpointRegistry
extends JmsListenerEndpointRegistry {

View File

@@ -3,7 +3,6 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration,\
org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.client.TraceWebClientAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.client.TraceWebAsyncClientAutoConfiguration,\

View File

@@ -59,6 +59,11 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>

View File

@@ -16,180 +16,98 @@
package org.springframework.cloud.sleuth.instrument.async;
import java.util.AbstractMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.sampler.Sampler;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.BeforeEach;
import brave.SpanCustomizer;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.propagation.CurrentTraceContext;
import brave.propagation.CurrentTraceContext.Scope;
import brave.propagation.TraceContext;
import brave.test.IntegrationTestSpanHandler;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.SpanName;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.BDDAssertions.then;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
classes = { TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class })
public class TraceAsyncIntegrationTests {
@Autowired
ClassPerformingAsyncLogic classPerformingAsyncLogic;
@ClassRule
public static IntegrationTestSpanHandler spans = new IntegrationTestSpanHandler();
TraceContext context = TraceContext.newBuilder().traceId(1).spanId(2).sampled(true)
.build();
@Autowired
Tracing tracer;
AsyncLogic asyncLogic;
@Autowired
ArrayListSpanReporter reporter;
@BeforeEach
public void cleanup() {
this.classPerformingAsyncLogic.clear();
this.reporter.clear();
}
CurrentTraceContext currentTraceContext;
@Test
public void should_set_span_on_an_async_annotated_method() {
whenAsyncProcessingTakesPlace();
asyncLogic.invokeAsync();
thenANewAsyncSpanGetsCreated();
assertSpan_invokeAsync(takeDesirableSpan());
}
@Test
public void should_set_span_with_custom_method_on_an_async_annotated_method() {
whenAsyncProcessingTakesPlaceWithCustomSpanName();
asyncLogic.invokeAsync_customName();
thenAsyncSpanHasCustomName();
assertSpan_invokeAsync_customName(takeDesirableSpan());
}
@Test
public void should_continue_a_span_on_an_async_annotated_method() {
Span span = givenASpanInCurrentThread();
try (Scope ws = currentTraceContext.maybeScope(context)) {
asyncLogic.invokeAsync();
try (Tracer.SpanInScope ws = this.tracer.tracer().withSpanInScope(span.start())) {
whenAsyncProcessingTakesPlace();
thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(span);
}
finally {
span.finish();
MutableSpan span = assertSpan_invokeAsync(takeDesirableSpan());
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
}
@Test
public void should_continue_a_span_with_custom_method_on_an_async_annotated_method() {
Span span = givenASpanInCurrentThread();
try (Scope ws = currentTraceContext.maybeScope(context)) {
asyncLogic.invokeAsync_customName();
try (Tracer.SpanInScope ws = this.tracer.tracer().withSpanInScope(span.start())) {
whenAsyncProcessingTakesPlaceWithCustomSpanName();
thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(
span);
}
finally {
span.finish();
MutableSpan span = assertSpan_invokeAsync_customName(takeDesirableSpan());
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
}
private Span givenASpanInCurrentThread() {
return this.tracer.tracer().nextSpan().name("http:existing");
static MutableSpan assertSpan_invokeAsync_customName(MutableSpan span) {
assertThat(span.name()).isEqualTo("foo");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic")
.containsEntry("method", "invokeAsync_customName");
return span;
}
private void whenAsyncProcessingTakesPlace() {
this.classPerformingAsyncLogic.invokeAsynchronousLogic();
static MutableSpan assertSpan_invokeAsync(MutableSpan span) {
assertThat(span.name()).isEqualTo("invoke-async");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic")
.containsEntry("method", "invokeAsync");
return span;
}
private void whenAsyncProcessingTakesPlaceWithCustomSpanName() {
this.classPerformingAsyncLogic.customNameInvokeAsynchronousLogic();
}
private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOne(final Span span) {
Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic
.getSpan();
then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId());
List<zipkin2.Span> spans = TraceAsyncIntegrationTests.this.reporter
.getSpans();
zipkin2.Span reportedAsyncSpan = spans.stream()
.filter(span2 -> span2.name().equals("invoke-asynchronous-logic"))
.findFirst().orElseThrow(() -> new AssertionError(
"Should have a span with custom name"));
then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString());
then(reportedAsyncSpan.name()).isEqualTo("invoke-asynchronous-logic");
then(reportedAsyncSpan.tags())
.contains(new AbstractMap.SimpleEntry<>("class",
"ClassPerformingAsyncLogic"))
.contains(new AbstractMap.SimpleEntry<>("method",
"invokeAsynchronousLogic"));
});
}
private void thenANewAsyncSpanGetsCreated() {
Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
List<zipkin2.Span> spans = TraceAsyncIntegrationTests.this.reporter
.getSpans();
then(spans).hasSize(2);
zipkin2.Span reportedAsyncSpan = spans.stream()
.filter(span -> span.name().equals("invoke-asynchronous-logic"))
.findFirst().orElseThrow(() -> new AssertionError(
"Should have a span with custom name"));
then(reportedAsyncSpan.tags())
.contains(new AbstractMap.SimpleEntry<>("class",
"ClassPerformingAsyncLogic"))
.contains(new AbstractMap.SimpleEntry<>("method",
"invokeAsynchronousLogic"));
});
}
private void thenTraceIdIsPassedFromTheCurrentThreadToTheAsyncOneAndSpanHasCustomName(
final Span span) {
Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
Span asyncSpan = TraceAsyncIntegrationTests.this.classPerformingAsyncLogic
.getSpan();
then(asyncSpan.context().traceId()).isEqualTo(span.context().traceId());
List<zipkin2.Span> spans = TraceAsyncIntegrationTests.this.reporter
.getSpans();
then(spans).hasSize(2);
zipkin2.Span reportedAsyncSpan = spans.stream()
.filter(span2 -> span2.name().equals("foo")).findFirst()
.orElseThrow(() -> new AssertionError(
"Should have a span with custom name"));
then(reportedAsyncSpan.traceId()).isEqualTo(span.context().traceIdString());
then(reportedAsyncSpan.name()).isEqualTo("foo");
then(reportedAsyncSpan.tags())
.contains(new AbstractMap.SimpleEntry<>("class",
"ClassPerformingAsyncLogic"))
.contains(new AbstractMap.SimpleEntry<>("method",
"customNameInvokeAsynchronousLogic"));
});
}
private void thenAsyncSpanHasCustomName() {
Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
List<zipkin2.Span> spans = TraceAsyncIntegrationTests.this.reporter
.getSpans();
zipkin2.Span reportedAsyncSpan = spans.stream()
.filter(span2 -> span2.name().equals("foo")).findFirst()
.orElseThrow(() -> new AssertionError(
"Should have a span with custom name"));
then(reportedAsyncSpan.name()).isEqualTo("foo");
then(reportedAsyncSpan.tags())
.contains(new AbstractMap.SimpleEntry<>("class",
"ClassPerformingAsyncLogic"))
.contains(new AbstractMap.SimpleEntry<>("method",
"customNameInvokeAsynchronousLogic"));
});
// Sleuth adds spans named "async" with no tags when an executor is used.
// We don't want that one.
MutableSpan takeDesirableSpan() {
MutableSpan span1 = spans.takeLocalSpan();
MutableSpan span2 = spans.takeLocalSpan();
return span1.name().equals("async") ? span2 : span1;
}
@DefaultTestAutoConfiguration
@@ -198,49 +116,34 @@ public class TraceAsyncIntegrationTests {
static class TraceAsyncITestConfiguration {
@Bean
ClassPerformingAsyncLogic asyncClass(Tracer tracer) {
return new ClassPerformingAsyncLogic(tracer);
AsyncLogic asyncLogic(SpanCustomizer customizer) {
return new AsyncLogic(customizer);
}
@Bean
Sampler defaultSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
SpanHandler spanHandler() {
return spans;
}
}
static class ClassPerformingAsyncLogic {
static class AsyncLogic {
private final Tracer tracer;
final SpanCustomizer customizer;
AtomicReference<Span> span = new AtomicReference<>();
ClassPerformingAsyncLogic(Tracer tracer) {
this.tracer = tracer;
AsyncLogic(SpanCustomizer customizer) {
this.customizer = customizer;
}
@Async
public void invokeAsynchronousLogic() {
this.span.set(this.tracer.currentSpan());
public void invokeAsync() {
customizer.annotate("@Async"); // proves the handler is in scope
}
@Async
@SpanName("foo")
public void customNameInvokeAsynchronousLogic() {
this.span.set(this.tracer.currentSpan());
}
public Span getSpan() {
return this.span.get();
}
public void clear() {
this.span.set(null);
public void invokeAsync_customName() {
customizer.annotate("@Async"); // proves the handler is in scope
}
}