Refactoring modules to be consistent with Spring Boot (#1784)

# Modules

* New modules: `spring-cloud-sleuth-autoconfigure`, `spring-cloud-sleuth-api`, `spring-cloud-sleuth-instrumentation`
  `spring-cloud-sleuth-core` removed and changed to `spring-cloud-sleuth-instrumentation` & `spring-cloud-sleuth-api`
* Removed `spring-cloud-starter-sleuth-otel`
  To add OpenTelemetry support you need to add `spring-cloud-starter-sleuth` (adds Brave by default), exclude Brave and add `spring-cloud-sleuth-otel` dependency
* Except for the tests, `spring-cloud-sleuth-autoconfigure` is the only module that can have access to `@Configuration`, `@ConfigurationProperties` classes.
Tests have been added to ensure such separation.

## Package moving

* `org.springframework.cloud.sleuth.api` -> `org.springframework.cloud.sleuth`
* `org.springframework.cloud.sleuth.brave.autoconfig` -> `org.springframework.cloud.sleuth.autoconfig.brave`
* `org.springframework.cloud.sleuth.otel.autoconfig` -> `org.springframework.cloud.sleuth.autoconfig.otel`
* `org.springframework.cloud.sleuth` -> `org.springframework.cloud.sleuth`
* Instrumentation: `org.springframework.cloud.sleuth.annotation` -> `org.springframework.cloud.sleuth.instrument.annotation`
* All the autoconfiguration classes were moved under `org.springframework.cloud/sleuth.autoconfig` package

## Global class modifications

* Any class registered as a bean is now public

## Classes

* `RateLimitingSampler` constructor changed
* Merged a lot of auto configuration classes into one (e.g. `BraveAutoConfiguration` now imports various other configurations)
* Renamed `TraceBraveAutoConfiguration` to `BraveAutoConfiguration`
* Renamed `TraceOtelAutoConfiguration` to `OtelAutoConfiguration`
* Removed all `NoOp` implementations of the API
This commit is contained in:
Marcin Grzejszczak
2020-11-23 15:39:13 +01:00
committed by GitHub
parent c81ee04dac
commit 76ad931b42
625 changed files with 9302 additions and 5795 deletions

View File

@@ -50,6 +50,7 @@
<module>spring-cloud-sleuth-instrumentation-rxjava-tests</module>
<module>spring-cloud-sleuth-instrumentation-scheduling-tests</module>
<module>spring-cloud-sleuth-instrumentation-webflux-tests</module>
<module>spring-cloud-sleuth-zipkin-tests</module>
</modules>
<build>

View File

@@ -63,27 +63,22 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = NullSpanTagAnnotationHandlerTests.Config.class)
public class NullSpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.annotation.NullSpanTagAnnotationHandlerTests {
extends org.springframework.cloud.sleuth.instrument.annotation.NullSpanTagAnnotationHandlerTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -19,9 +19,9 @@ package org.springframework.cloud.sleuth.brave.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.api.TraceContext;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.brave.bridge.BraveTraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -30,12 +30,12 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectFluxTests.Config.class)
public class SleuthSpanCreatorAspectFluxTests
extends org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorAspectFluxTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectFluxTests {
@Override
public TraceContext traceContext() {
return BraveTraceContext
.fromBrave(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
return BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
}
@Configuration(proxyBeanMethods = false)

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectMonoTests.Config.class)
public class SleuthSpanCreatorAspectMonoTests
extends org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorAspectMonoTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectMonoTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectNegativeTests.Config.class)
public class SleuthSpanCreatorAspectNegativeTests
extends org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorAspectNegativeTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectNegativeTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectTests.Config.class)
public class SleuthSpanCreatorAspectTests
extends org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorAspectTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorCircularDependencyTests.Config.class)
public class SleuthSpanCreatorCircularDependencyTests
extends org.springframework.cloud.sleuth.annotation.SleuthSpanCreatorCircularDependencyTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorCircularDependencyTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -28,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SpanTagAnnotationHandlerTests.Config.class)
public class SpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.annotation.SpanTagAnnotationHandlerTests {
extends org.springframework.cloud.sleuth.instrument.annotation.SpanTagAnnotationHandlerTests {
@Configuration(proxyBeanMethods = false)
static class Config {

View File

@@ -64,25 +64,17 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -18,7 +18,7 @@ package org.springframework.cloud.sleuth.brave.instrument.async;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.api.Span;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;

View File

@@ -151,8 +151,8 @@ public class Issue410Tests {
@Test
public void should_pass_tracing_info_for_completable_futures_with_task_scheduler() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/taskScheduler",
String.class);
@@ -175,8 +175,8 @@ public class Issue410Tests {
@Test
public void should_pass_tracing_info_for_submitted_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_submit", String.class);
@@ -196,8 +196,8 @@ public class Issue410Tests {
@Test
public void should_pass_tracing_info_for_scheduled_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_schedule", String.class);
@@ -220,8 +220,8 @@ public class Issue410Tests {
@Test
public void should_pass_tracing_info_for_completable_futures_with_scheduledThreadPoolExecutor() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/scheduledThreadPoolExecutor", String.class);

View File

@@ -70,23 +70,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -23,13 +23,13 @@ import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.context.ContextConfiguration;
/**
* @author Taras Danylchuk
*/
@SpringBootTest(// WebEnvironment.NONE will not read a Yaml profile
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(classes = BaggageEntryTagSpanHandlerTest.Config.class)
public class BaggageEntryTagSpanHandlerTest
extends org.springframework.cloud.sleuth.baggage.BaggageEntryTagSpanHandlerTest {
@@ -38,7 +38,7 @@ public class BaggageEntryTagSpanHandlerTest
static class Config {
@Bean
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler, Environment environment) {
return new BraveTestSpanHandler(testSpanHandler);
}

View File

@@ -20,11 +20,15 @@ import brave.baggage.BaggageField;
import brave.baggage.BaggagePropagationConfig;
import brave.sampler.Sampler;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.api.Span;
import org.springframework.cloud.sleuth.api.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.brave.bridge.BraveTraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -52,15 +56,17 @@ public class MultipleHopsIntegrationTests
// set with baggage api
then(this.application.allSpans()).as("All have request ID")
.allMatch(span -> "f4308d05-2228-4468-80f6-92a8377ba193"
.equals(REQUEST_ID.getValue(BraveTraceContext.toBrave(span.context()))));
.equals(REQUEST_ID.getValue(BraveAccessor.traceContext(span.context()))));
// baz is not tagged in the initial span, only downstream!
then(this.application.allSpans()).as("All downstream have country-code")
.filteredOn(span -> !span.equals(initialSpan))
.allMatch(span -> "FO".equals(COUNTRY_CODE.getValue(BraveTraceContext.toBrave(span.context()))));
.allMatch(span -> "FO".equals(COUNTRY_CODE.getValue(BraveAccessor.traceContext(span.context()))));
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(
exclude = { MongoAutoConfiguration.class, QuartzAutoConfiguration.class, JmxAutoConfiguration.class })
static class Config {
@Bean

View File

@@ -66,23 +66,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -20,8 +20,8 @@ import brave.sampler.Sampler;
import org.assertj.core.api.BDDAssertions;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.api.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@@ -18,8 +18,8 @@ package org.springframework.cloud.sleuth.brave.instrument.circuitbreaker;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.api.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class CircuitBreakerTests

View File

@@ -71,11 +71,6 @@
<version>4.8.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
@@ -95,22 +90,18 @@
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -42,7 +42,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
@@ -72,7 +71,7 @@ interface MyFeignClient {
*/
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource(properties = { "server.port=9998" })
@TestPropertySource(properties = { "server.port=9998", "spring.sleuth.web.servlet.enabled=false" })
public class Issue362Tests {
RestTemplate template = new RestTemplate();
@@ -126,10 +125,7 @@ public class Issue362Tests {
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(
// spring boot test will otherwise instrument the client and server with the
// same bean factory which isn't expected
exclude = TraceWebServletAutoConfiguration.class)
@EnableAutoConfiguration
@EnableFeignClients(basePackageClasses = { SleuthTestController.class })
class Application {

View File

@@ -32,7 +32,6 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.ResponseEntity;
@@ -58,7 +57,8 @@ interface MyNameRemote {
*/
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource(properties = { "spring.application.name=demo-feign-uri", "server.port=9978" })
@TestPropertySource(properties = { "spring.application.name=demo-feign-uri", "server.port=9978",
"spring.sleuth.web.servlet.enabled=false" })
public class Issue393Tests {
RestTemplate template = new RestTemplate();
@@ -90,10 +90,7 @@ public class Issue393Tests {
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(
// spring boot test will otherwise instrument the client and server with the
// same bean factory which isn't expected
exclude = TraceWebServletAutoConfiguration.class)
@EnableAutoConfiguration
@EnableFeignClients
@EnableDiscoveryClient
class Application {

View File

@@ -62,23 +62,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -61,41 +61,34 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<!-- This forces the guava version to 20 within the test scope, which is required by GRPC -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<scope>test</scope>
</dependency>
<!-- GRPC Optional Dependencies -->
<dependency>
<groupId>io.github.lognet</groupId>
<artifactId>grpc-spring-boot-starter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-grpc</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -61,29 +61,24 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

View File

@@ -24,6 +24,8 @@ import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.autoconfig.brave.instrument.redis.TraceRedisProperties;
import org.springframework.cloud.sleuth.autoconfig.instrument.redis.TraceLettuceClientResourcesBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -32,9 +34,9 @@ import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Chao Chang
*/
@SpringBootTest(classes = TraceRedisAutoConfigurationTests.Config.class,
@SpringBootTest(classes = BraveRedisAutoConfigurationTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class TraceRedisAutoConfigurationTests {
public class BraveRedisAutoConfigurationTests {
@Autowired
ClientResources clientResources;

View File

@@ -19,8 +19,7 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd
https://www.w3.org/2001/XMLSchema-instance ">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-instrumentation-messaging-tests</artifactId>
@@ -67,8 +66,7 @@ https://www.w3.org/2001/XMLSchema-instance ">
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
@@ -79,13 +77,11 @@ https://www.w3.org/2001/XMLSchema-instance ">
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream</artifactId>
<type>test-jar</type>
<scope>test</scope>
<classifier>test-binder</classifier>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
@@ -96,12 +92,10 @@ https://www.w3.org/2001/XMLSchema-instance ">
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
@@ -147,19 +141,16 @@ https://www.w3.org/2001/XMLSchema-instance ">
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
<scope>test</scope>
</dependency>
<!-- to test DefaultJcaListenerContainerFactory -->
<dependency>
<groupId>javax.resource</groupId>
<artifactId>javax.resource-api</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-ra</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -41,9 +41,9 @@ import static org.assertj.core.api.BDDAssertions.then;
* @author Roberto Tassi
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TraceMessagingAutoConfiguration1664Tests.Config.class,
@SpringBootTest(classes = BraveMessagingAutoConfiguration1664Tests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class TraceMessagingAutoConfiguration1664Tests {
public class BraveMessagingAutoConfiguration1664Tests {
@Autowired
MySleuthKafka1664Aspect mySleuthKafka1664Aspect;

View File

@@ -41,8 +41,8 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.cloud.sleuth.brave.autoconfig.TraceBraveAutoConfiguration;
import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.cloud.sleuth.autoconfig.brave.instrument.messaging.BraveMessagingAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaListener;
@@ -55,9 +55,9 @@ import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(classes = TraceMessagingAutoConfigurationTests.Config.class,
@SpringBootTest(classes = BraveMessagingAutoConfigurationTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class TraceMessagingAutoConfigurationTests {
public class BraveMessagingAutoConfigurationTests {
@Autowired
RabbitTemplate rabbitTemplate;
@@ -144,9 +144,8 @@ public class TraceMessagingAutoConfigurationTests {
}
private ApplicationContextRunner contextRunner(String... propertyValues) {
return new ApplicationContextRunner().withPropertyValues(propertyValues)
.withConfiguration(AutoConfigurations.of(TraceBraveAutoConfiguration.class,
TraceAutoConfiguration.class, TraceMessagingAutoConfiguration.class));
return new ApplicationContextRunner().withPropertyValues(propertyValues).withConfiguration(
AutoConfigurations.of(BraveAutoConfiguration.class, BraveMessagingAutoConfiguration.class));
}
@Configuration(proxyBeanMethods = false)

View File

@@ -33,8 +33,8 @@ import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Tim te Beek
*/
@SpringBootTest(classes = SleuthKafkaStreamsConfigurationTest.Config.class, webEnvironment = WebEnvironment.NONE)
public class SleuthKafkaStreamsConfigurationTest {
@SpringBootTest(classes = BraveKafkaStreamsAutoConfigurationTest.Config.class, webEnvironment = WebEnvironment.NONE)
public class BraveKafkaStreamsAutoConfigurationTest {
@Autowired
TestTraceStreamsBuilderFactoryBean streamsBuilderFactoryBean;

View File

@@ -37,6 +37,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.jms.XAConnectionFactoryWrapper;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
@@ -164,7 +166,8 @@ public class JmsTracingConfigurationTest {
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(exclude = KafkaAutoConfiguration.class)
@EnableAutoConfiguration(
exclude = { KafkaAutoConfiguration.class, MongoAutoConfiguration.class, QuartzAutoConfiguration.class })
class JmsTestTracingConfiguration {
}

View File

@@ -78,7 +78,6 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -90,23 +89,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -45,7 +45,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.cloud.sleuth.autoconfig.instrument.web.SleuthWebProperties;
import org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter;
import org.springframework.cloud.sleuth.util.SpanUtil;
import org.springframework.context.annotation.Bean;
@@ -299,7 +299,7 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
}
@Bean
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
@Order(SleuthWebProperties.TRACING_FILTER_ORDER + 1)
Filter myFilter(Tracer tracer) {
return new MyFilter(tracer);
}
@@ -359,7 +359,7 @@ public class TraceFilterIntegrationTests extends AbstractMvcIntegrationTest {
// tag::response_headers[]
@Component
@Order(TraceWebServletAutoConfiguration.TRACING_FILTER_ORDER + 1)
@Order(SleuthWebProperties.TRACING_FILTER_ORDER + 1)
class MyFilter extends GenericFilterBean {
private final Tracer tracer;

View File

@@ -22,9 +22,9 @@ import brave.http.HttpTracing;
import org.assertj.core.api.BDDAssertions;
import org.junit.jupiter.api.Test;
import org.springframework.cloud.sleuth.api.http.HttpServerHandler;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.brave.bridge.http.BraveHttpServerHandler;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import org.springframework.cloud.sleuth.http.HttpServerHandler;
import org.springframework.cloud.sleuth.instrument.web.servlet.TracingFilter;
import org.springframework.cloud.sleuth.test.TestTracingAware;
import org.springframework.cloud.sleuth.test.TracerAware;
@@ -50,7 +50,7 @@ public class TraceFilterTests extends org.springframework.cloud.sleuth.instrumen
public HttpServerHandler httpServerHandler() {
HttpTracing httpTracing = this.testTracing.httpTracingBuilder()
.serverSampler(new SkipPatternHttpServerSampler(() -> Pattern.compile(""))).build();
return new BraveHttpServerHandler(brave.http.HttpServerHandler.create(httpTracing));
return BraveAccessor.httpServerHandler(brave.http.HttpServerHandler.create(httpTracing));
}
@Test

View File

@@ -36,8 +36,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.api.http.HttpClientHandler;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.cloud.sleuth.http.HttpClientHandler;
import org.springframework.cloud.sleuth.instrument.web.mvc.TracingAsyncClientHttpRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
@@ -67,7 +66,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@SpringBootTest(classes = RestTemplateTraceAspectIntegrationTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = "spring.sleuth.web.client.skipPattern=/issue.*")
properties = { "spring.sleuth.web.client.skipPattern=/issue.*", "spring.sleuth.web.servlet.enabled=false" })
@DirtiesContext
public class RestTemplateTraceAspectIntegrationTests {
@@ -175,10 +174,7 @@ public class RestTemplateTraceAspectIntegrationTests {
this.mockMvc.perform(asyncDispatch(mvcResult)).andDo(print()).andExpect(status().isOk());
}
@EnableAutoConfiguration(
// spring boot test will otherwise instrument the client and server with the
// same bean factory which isn't expected
exclude = TraceWebServletAutoConfiguration.class)
@EnableAutoConfiguration
@Import(AspectTestingController.class)
public static class Config {
@@ -194,7 +190,7 @@ public class RestTemplateTraceAspectIntegrationTests {
@Bean
public AsyncRestTemplate asyncRestTemplate(
org.springframework.cloud.sleuth.api.CurrentTraceContext currentTraceContext,
org.springframework.cloud.sleuth.CurrentTraceContext currentTraceContext,
HttpClientHandler httpClientHandler) {
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
asyncRestTemplate.setInterceptors(Collections.singletonList(

View File

@@ -18,7 +18,7 @@ package org.springframework.cloud.sleuth.brave.instrument.web.client;
import java.util.Map;
import org.springframework.cloud.sleuth.api.Span;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;

View File

@@ -35,7 +35,6 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@@ -53,7 +52,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
*/
@SpringBootTest(classes = { TraceWebAsyncClientAutoConfigurationTests.TestConfiguration.class },
webEnvironment = RANDOM_PORT)
webEnvironment = RANDOM_PORT, properties = "spring.sleuth.web.servlet.enabled=false")
public class TraceWebAsyncClientAutoConfigurationTests {
@Autowired
@@ -120,10 +119,7 @@ public class TraceWebAsyncClientAutoConfigurationTests {
return this.environment.getProperty("local.server.port", Integer.class);
}
@EnableAutoConfiguration(
// spring boot test will otherwise instrument the client and server with the
// same bean factory which isn't expected
exclude = TraceWebServletAutoConfiguration.class)
@EnableAutoConfiguration
@Configuration(proxyBeanMethods = false)
public static class TestConfiguration {

View File

@@ -62,23 +62,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -51,6 +51,11 @@
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
@@ -61,13 +66,11 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-http-tests</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.eclipse.jetty</groupId>
@@ -78,32 +81,26 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

View File

@@ -0,0 +1,53 @@
/*
* Copyright 2013-2020 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
*
* https://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.brave.instrument.reactor;
import brave.sampler.Sampler;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class FlatMapTests extends org.springframework.cloud.sleuth.instrument.reactor.sample.FlatMapTests {
@Override
protected Class testConfiguration() {
return Config.class;
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
return new BraveTestSpanHandler(testSpanHandler);
}
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
brave.test.TestSpanHandler braveTestSpanHandler() {
return new brave.test.TestSpanHandler();
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2013-2020 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
*
* https://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.brave.instrument.reactor;
import org.springframework.cloud.sleuth.CurrentTraceContext;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
/**
* @author Marcin Grzejszczak
*/
public class FlowsScopePassingSpanSubscriberTests
extends org.springframework.cloud.sleuth.instrument.reactor.FlowsScopePassingSpanSubscriberTests {
brave.propagation.CurrentTraceContext traceContext = brave.propagation.CurrentTraceContext.Default.create();
CurrentTraceContext currentTraceContext = BraveAccessor.currentTraceContext(traceContext);
TraceContext context = BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build());
@Override
protected CurrentTraceContext currentTraceContext() {
return this.currentTraceContext;
}
@Override
protected TraceContext context() {
return this.context;
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2013-2020 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
*
* https://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.brave.instrument.reactor;
import brave.sampler.Sampler;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Like {@link ScopePassingSpanSubscriberTests}, except this tests wiring with spring boot
* config.
*/
@SpringBootTest(classes = ScopePassingSpanSubscriberSpringBootTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class ScopePassingSpanSubscriberSpringBootTests
extends org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriberSpringBootTests {
TraceContext context = BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build());
TraceContext context2 = BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
@Override
protected TraceContext context() {
return this.context;
}
@Override
protected TraceContext context2() {
return this.context2;
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class Config {
@Bean
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler) {
return new BraveTestSpanHandler(testSpanHandler);
}
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
brave.test.TestSpanHandler braveTestSpanHandler() {
return new brave.test.TestSpanHandler();
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2013-2020 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
*
* https://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.brave.instrument.reactor;
import brave.propagation.StrictCurrentTraceContext;
import org.springframework.cloud.sleuth.CurrentTraceContext;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
/**
* @author Marcin Grzejszczak
*/
public class ScopePassingSpanSubscriberTests
extends org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriberTests {
StrictCurrentTraceContext traceContext = StrictCurrentTraceContext.create();
CurrentTraceContext currentTraceContext = BraveAccessor.currentTraceContext(traceContext);
TraceContext context = BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build());
TraceContext context2 = BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
@Override
protected CurrentTraceContext currentTraceContext() {
return this.currentTraceContext;
}
@Override
protected TraceContext context() {
return this.context;
}
@Override
protected TraceContext context2() {
return this.context2;
}
}

View File

@@ -1,147 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor;
import java.util.Objects;
import java.util.function.Function;
import brave.propagation.CurrentTraceContext;
import brave.propagation.CurrentTraceContext.Scope;
import brave.propagation.TraceContext;
import org.assertj.core.presentation.StandardRepresentation;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.Hooks;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.sleuth.instrument.reactor.ReactorSleuth.scopePassingSpanOperator;
import static org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration.TraceReactorConfiguration.SLEUTH_TRACE_REACTOR_KEY;
/**
* @author Marcin Grzejszczak
*/
public class FlowsScopePassingSpanSubscriberTests {
static {
// AssertJ will recognise QueueSubscription implements queue and try to invoke
// iterator. That's not allowed, and will cause an exception
// Fuseable$QueueSubscription.NOT_SUPPORTED_MESSAGE.
// This ensures AssertJ uses normal toString.
StandardRepresentation.registerFormatterForType(ScopePassingSpanSubscriber.class, Objects::toString);
}
final CurrentTraceContext currentTraceContext = CurrentTraceContext.Default.create();
TraceContext context = TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build();
AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext();
@BeforeEach
public void setup() {
Hooks.resetOnEachOperator(SLEUTH_TRACE_REACTOR_KEY);
Hooks.resetOnLastOperator(SLEUTH_TRACE_REACTOR_KEY);
Schedulers.resetOnScheduleHooks();
}
@AfterEach
public void close() {
springContext.close();
}
@Test
public void should_not_trace_scalar_flows() {
springContext.registerBean(CurrentTraceContext.class, () -> currentTraceContext);
springContext.refresh();
Function<? super Publisher<Integer>, ? extends Publisher<Integer>> transformer = scopePassingSpanOperator(
this.springContext);
try (Scope ws = this.currentTraceContext.newScope(context)) {
Subscriber<Object> assertNoSpanSubscriber = new CoreSubscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
assertThat(s).isNotInstanceOf(ScopePassingSpanSubscriber.class);
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
Subscriber<Object> assertSpanSubscriber = new CoreSubscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
assertThat(s).isInstanceOf(ScopePassingSpanSubscriber.class);
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
transformer.apply(Mono.just(1).hide()).subscribe(assertSpanSubscriber);
transformer.apply(Mono.just(1)).subscribe(assertNoSpanSubscriber);
transformer.apply(Mono.<Integer>error(new Exception()).hide()).subscribe(assertSpanSubscriber);
transformer.apply(Mono.error(new Exception())).subscribe(assertNoSpanSubscriber);
transformer.apply(Mono.<Integer>empty().hide()).subscribe(assertSpanSubscriber);
transformer.apply(Mono.empty()).subscribe(assertNoSpanSubscriber);
}
Awaitility.await().untilAsserted(() -> then(this.currentTraceContext.get()).isNull());
}
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Marcin Grzejszczak
*/
@Configuration(proxyBeanMethods = false)
public class Issue866Configuration {
private static final Log log = LogFactory.getLog(Issue866Configuration.class);
// we don't want to force direct dependencies between components
// because Spring might just properly setup the context
// we want to ensure that the HRBDRPP is always executed before
// any other object is started
public static TestHook hook;
@Bean
HookRegisteringBeanDefinitionRegistryPostProcessor overridingProcessorForTests(
ConfigurableApplicationContext context) {
log.info("Registering a HookRegisteringBeanDefinitionRegistryPostProcessor for context [" + context + "]");
TestHook hook = new TestHook(context);
Issue866Configuration.hook = hook;
return hook;
}
public static class TestHook extends HookRegisteringBeanDefinitionRegistryPostProcessor {
public boolean executed = false;
public TestHook(ConfigurableApplicationContext context) {
super(context);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
super.postProcessBeanFactory(beanFactory);
this.executed = true;
}
}
}

View File

@@ -1,189 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicReference;
import brave.propagation.CurrentTraceContext;
import brave.propagation.CurrentTraceContext.Scope;
import brave.propagation.TraceContext;
import brave.sampler.Sampler;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.BDDAssertions.then;
/**
* Like {@link ScopePassingSpanSubscriberTests}, except this tests wiring with spring boot
* config.
*/
@SpringBootTest(classes = ScopePassingSpanSubscriberSpringBootTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class ScopePassingSpanSubscriberSpringBootTests {
@Autowired
CurrentTraceContext currentTraceContext;
TraceContext context = TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build();
TraceContext context2 = TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build();
@Test
public void should_pass_tracing_info_when_using_reactor() {
final AtomicReference<TraceContext> spanInOperation = new AtomicReference<>();
Publisher<Integer> traced = Flux.just(1, 2, 3);
try (Scope ws = this.currentTraceContext.newScope(context)) {
Flux.from(traced).map(d -> d + 1).map(d -> d + 1).map((d) -> {
spanInOperation.set(this.currentTraceContext.get());
return d + 1;
}).map(d -> d + 1).subscribe(d -> {
});
}
then(this.currentTraceContext.get()).isNull();
then(spanInOperation.get()).isEqualTo(context);
}
@Test
public void should_support_reactor_fusion_optimization() {
final AtomicReference<TraceContext> spanInOperation = new AtomicReference<>();
try (Scope ws = this.currentTraceContext.newScope(context)) {
Mono.just(1).flatMap(d -> Flux.just(d + 1).collectList().map(p -> p.get(0))).map(d -> d + 1).map((d) -> {
spanInOperation.set(this.currentTraceContext.get());
return d + 1;
}).map(d -> d + 1).subscribe(d -> {
});
}
then(this.currentTraceContext.get()).isNull();
then(spanInOperation.get()).isEqualTo(context);
}
@Test
public void should_pass_tracing_info_when_using_reactor_async() {
final AtomicReference<TraceContext> spanInOperation = new AtomicReference<>();
try (Scope ws = this.currentTraceContext.newScope(context)) {
Flux.just(1, 2, 3).publishOn(Schedulers.single()).log("reactor.1").map(d -> d + 1).map(d -> d + 1)
.publishOn(Schedulers.newSingle("secondThread")).log("reactor.2").map((d) -> {
spanInOperation.set(this.currentTraceContext.get());
return d + 1;
}).map(d -> d + 1).blockLast();
Awaitility.await().untilAsserted(() -> then(spanInOperation.get()).isEqualTo(context));
then(this.currentTraceContext.get()).isEqualTo(context);
}
then(this.currentTraceContext.get()).isNull();
try (Scope ws = this.currentTraceContext.newScope(context2)) {
Flux.just(1, 2, 3).publishOn(Schedulers.single()).log("reactor.").map(d -> d + 1).map(d -> d + 1)
.map((d) -> {
spanInOperation.set(this.currentTraceContext.get());
return d + 1;
}).map(d -> d + 1).blockLast();
then(this.currentTraceContext.get()).isEqualTo(context2);
then(spanInOperation.get()).isEqualTo(context2);
}
then(this.currentTraceContext.get()).isNull();
}
@Test
public void onlyConsidersContextDuringSubscribe() {
Mono<TraceContext> fromMono = Mono.fromCallable(this.currentTraceContext::get);
try (Scope ws = this.currentTraceContext.newScope(context)) {
then(fromMono.map(context -> context).block()).isNotNull();
}
}
@Test
public void checkTraceIdDuringZipOperation() {
final AtomicReference<TraceContext> spanInOperation = new AtomicReference<>();
final AtomicReference<TraceContext> spanInZipOperation = new AtomicReference<>();
try (Scope ws = this.currentTraceContext.newScope(context)) {
Mono.fromCallable(this.currentTraceContext::get).map(span -> span).doOnNext(spanInOperation::set)
.zipWith(Mono.fromCallable(this.currentTraceContext::get).map(span -> span)
.doOnNext(spanInZipOperation::set))
.block();
}
then(spanInZipOperation).hasValue(context);
then(spanInOperation).hasValue(context);
}
// #646
@Test
public void should_work_for_mono_just_with_flat_map() {
try (Scope ws = this.currentTraceContext.newScope(context)) {
Mono.just("value1").flatMap(request -> Mono.just("value2").then(Mono.just("foo"))).map(a -> "qwe").block();
}
}
// #1030
@Test
public void checkTraceIdFromSubscriberContext() {
final AtomicReference<TraceContext> spanInSubscriberContext = new AtomicReference<>();
try (Scope ws = this.currentTraceContext.newScope(context)) {
Mono.subscriberContext().map(context -> this.currentTraceContext.get())
.doOnNext(spanInSubscriberContext::set).block();
}
then(spanInSubscriberContext).hasValue(context); // ok here
}
@Test
public void should_pass_tracing_info_into_inner_publishers() {
final AtomicReference<TraceContext> spanInOperation = new AtomicReference<>();
try (Scope ws = this.currentTraceContext.newScope(context)) {
Flux.range(0, 5).flatMap(it -> Mono.delay(Duration.ofMillis(1))
.map(context -> this.currentTraceContext.get()).doOnNext(spanInOperation::set)).blockFirst();
}
then(spanInOperation.get()).isEqualTo(context);
}
@EnableAutoConfiguration
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -1,210 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor;
import java.util.Objects;
import java.util.function.Function;
import brave.propagation.StrictCurrentTraceContext;
import org.assertj.core.presentation.StandardRepresentation;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.reactivestreams.Publisher;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import reactor.core.CoreSubscriber;
import reactor.core.publisher.BaseSubscriber;
import reactor.core.publisher.Hooks;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.util.context.Context;
import org.springframework.cloud.sleuth.api.CurrentTraceContext;
import org.springframework.cloud.sleuth.api.TraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveCurrentTraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveTraceContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.cloud.sleuth.instrument.reactor.ReactorSleuth.scopePassingSpanOperator;
import static org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration.SLEUTH_REACTOR_EXECUTOR_SERVICE_KEY;
import static org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration.TraceReactorConfiguration.SLEUTH_TRACE_REACTOR_KEY;
/**
* @author Marcin Grzejszczak
*/
public class ScopePassingSpanSubscriberTests {
static {
// AssertJ will recognise QueueSubscription implements queue and try to invoke
// iterator. That's not allowed, and will cause an exception
// Fuseable$QueueSubscription.NOT_SUPPORTED_MESSAGE.
// This ensures AssertJ uses normal toString.
StandardRepresentation.registerFormatterForType(ScopePassingSpanSubscriber.class, Objects::toString);
}
StrictCurrentTraceContext traceContext = StrictCurrentTraceContext.create();
CurrentTraceContext currentTraceContext = BraveCurrentTraceContext.fromBrave(traceContext);
TraceContext context = BraveTraceContext
.fromBrave(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(1).sampled(true).build());
TraceContext context2 = BraveTraceContext
.fromBrave(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
Subscriber<Object> assertNotScopePassingSpanSubscriber = new CoreSubscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
assertThat(s).isNotInstanceOf(ScopePassingSpanSubscriber.class);
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
Subscriber<Object> assertScopePassingSpanSubscriber = new CoreSubscriber<Object>() {
@Override
public void onSubscribe(Subscription s) {
s.request(Long.MAX_VALUE);
assertThat(s).isInstanceOf(ScopePassingSpanSubscriber.class);
}
@Override
public void onNext(Object o) {
}
@Override
public void onError(Throwable t) {
}
@Override
public void onComplete() {
}
};
AnnotationConfigApplicationContext springContext = new AnnotationConfigApplicationContext();
@Before
public void resetHooks() {
// There's an assumption some other test is leaking hooks, so we clear them all to
// prevent should_not_scope_scalar_subscribe from being interfered with.
Hooks.resetOnEachOperator(SLEUTH_TRACE_REACTOR_KEY);
Hooks.resetOnLastOperator(SLEUTH_TRACE_REACTOR_KEY);
Schedulers.removeExecutorServiceDecorator(SLEUTH_REACTOR_EXECUTOR_SERVICE_KEY);
}
@After
public void close() {
springContext.close();
traceContext.close();
}
@Test
public void should_propagate_current_context() {
ScopePassingSpanSubscriber<?> subscriber = new ScopePassingSpanSubscriber<>(null, Context.of("foo", "bar"),
this.currentTraceContext, null);
then((String) subscriber.currentContext().get("foo")).isEqualTo("bar");
}
/**
* This ensures when the desired context is in the reactor context we don't copy it.
*/
@Test
public void should_not_redundantly_copy_context() {
Context initial = Context.of(TraceContext.class, context);
ScopePassingSpanSubscriber<?> subscriber = new ScopePassingSpanSubscriber<>(null, initial,
this.currentTraceContext, context);
then(initial.get(TraceContext.class)).isSameAs(subscriber.currentContext().get(TraceContext.class));
}
@Test
public void should_set_empty_context_when_context_is_null() {
ScopePassingSpanSubscriber<?> subscriber = new ScopePassingSpanSubscriber<>(null, Context.empty(),
this.currentTraceContext, null);
then(subscriber.currentContext().isEmpty()).isTrue();
}
@Test
public void should_put_current_span_to_context() {
try (CurrentTraceContext.Scope ws = this.currentTraceContext.newScope(context2)) {
CoreSubscriber<?> subscriber = new ScopePassingSpanSubscriber<>(new BaseSubscriber<Object>() {
}, Context.empty(), currentTraceContext, context);
then(subscriber.currentContext().get(TraceContext.class)).isEqualTo(context);
}
}
@Test
public void should_not_scope_scalar_subscribe() {
springContext.registerBean(CurrentTraceContext.class, () -> currentTraceContext);
springContext.refresh();
Function<? super Publisher<Integer>, ? extends Publisher<Integer>> transformer = scopePassingSpanOperator(
this.springContext);
try (CurrentTraceContext.Scope ws = this.currentTraceContext.newScope(context)) {
transformer.apply(Mono.just(1)).subscribe(assertNotScopePassingSpanSubscriber);
transformer.apply(Mono.error(new Exception())).subscribe(assertNotScopePassingSpanSubscriber);
transformer.apply(Mono.empty()).subscribe(assertNotScopePassingSpanSubscriber);
}
}
@Test
public void should_scope_scalar_hide_subscribe() {
springContext.registerBean(CurrentTraceContext.class, () -> currentTraceContext);
springContext.refresh();
Function<? super Publisher<Integer>, ? extends Publisher<Integer>> transformer = scopePassingSpanOperator(
this.springContext);
try (CurrentTraceContext.Scope ws = this.currentTraceContext.newScope(context)) {
transformer.apply(Mono.just(1).hide()).subscribe(assertScopePassingSpanSubscriber);
transformer.apply(Mono.<Integer>error(new Exception()).hide()).subscribe(assertScopePassingSpanSubscriber);
transformer.apply(Mono.<Integer>empty().hide()).subscribe(assertScopePassingSpanSubscriber);
}
}
}

View File

@@ -1,56 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Hooks;
import reactor.core.scheduler.Schedulers;
import org.springframework.context.ConfigurableApplicationContext;
import static org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration.SLEUTH_REACTOR_EXECUTOR_SERVICE_KEY;
import static org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration.TraceReactorConfiguration.SLEUTH_TRACE_REACTOR_KEY;
/**
* @author Marcin Grzejszczak
*/
public final class TraceReactorAutoConfigurationAccessorConfiguration {
private TraceReactorAutoConfigurationAccessorConfiguration() {
throw new IllegalStateException("Can't instantiate a utility class");
}
private static final Log log = LogFactory.getLog(TraceReactorAutoConfigurationAccessorConfiguration.class);
public static void close() {
if (log.isTraceEnabled()) {
log.trace("Cleaning up hooks");
}
Hooks.resetOnEachOperator(SLEUTH_TRACE_REACTOR_KEY);
Hooks.resetOnLastOperator(SLEUTH_TRACE_REACTOR_KEY);
Schedulers.removeExecutorServiceDecorator(SLEUTH_REACTOR_EXECUTOR_SERVICE_KEY);
}
public static void setup(ConfigurableApplicationContext context) {
if (log.isTraceEnabled()) {
log.trace("Setting up hooks");
}
HookRegisteringBeanDefinitionRegistryPostProcessor.setupHooks(context);
}
}

View File

@@ -1,325 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor.sample;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import brave.Span;
import brave.Tracer;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.sampler.Sampler;
import brave.test.TestSpanHandler;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.cloud.sleuth.api.CurrentTraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveSpan;
import org.springframework.cloud.sleuth.instrument.reactor.Issue866Configuration;
import org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfigurationAccessorConfiguration;
import org.springframework.cloud.sleuth.instrument.web.WebFluxSleuthOperators;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
// https://github.com/spring-cloud/spring-cloud-sleuth/issues/850
@ExtendWith(OutputCaptureExtension.class)
public class FlatMapTests {
private static final Logger LOGGER = LoggerFactory.getLogger(FlatMapTests.class);
@BeforeAll
public static void setup() {
TraceReactorAutoConfigurationAccessorConfiguration.close();
Issue866Configuration.hook = null;
}
@AfterAll
public static void cleanup() {
Issue866Configuration.hook = null;
}
@Test
public void should_work_with_flat_maps(CapturedOutput capture) {
// given
ConfigurableApplicationContext context = new SpringApplicationBuilder(FlatMapTests.TestConfiguration.class,
Issue866Configuration.class)
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.jmx.enabled=false",
"spring.application.name=TraceWebFluxTests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
assertReactorTracing(context, capture, () -> context.getBean(TestConfiguration.class).spanInFoo);
}
@Test
public void should_work_with_flat_maps_with_on_last_operator_instrumentation(CapturedOutput capture) {
// given
ConfigurableApplicationContext context = new SpringApplicationBuilder(FlatMapTests.TestConfiguration.class,
Issue866Configuration.class)
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.jmx.enabled=false",
"spring.sleuth.reactor.decorate-on-each=false",
"spring.application.name=TraceWebFlux2Tests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
assertReactorTracing(context, capture, () -> context.getBean(TestConfiguration.class).spanInFoo);
}
@Test
public void should_work_with_flat_maps_with_on_manual_operator_instrumentation(CapturedOutput capture) {
// given
ConfigurableApplicationContext context = new SpringApplicationBuilder(
FlatMapTests.TestManualConfiguration.class, Issue866Configuration.class)
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.jmx.enabled=false",
"spring.sleuth.reactor.instrumentation-type=MANUAL",
"spring.application.name=TraceWebFlux3Tests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
assertReactorTracing(context, capture, () -> context.getBean(TestManualConfiguration.class).spanInFoo);
}
private void assertReactorTracing(ConfigurableApplicationContext context, CapturedOutput capture,
SpanProvider spanProvider) {
TestSpanHandler spans = context.getBean(TestSpanHandler.class);
int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
RequestSender sender = context.getBean(RequestSender.class);
FactoryUser factoryUser = context.getBean(FactoryUser.class);
sender.port = port;
spans.clear();
Awaitility.await().untilAsserted(() -> {
// when
LOGGER.info("Start");
spans.clear();
String firstTraceId = flatMapTraceId(spans, callFlatMap(port).block());
// then
LOGGER.info("Checking first trace id");
thenAllWebClientCallsHaveSameTraceId(firstTraceId, sender);
thenSpanInFooHasSameTraceId(firstTraceId, spanProvider);
spans.clear();
LOGGER.info("All web client calls have same trace id");
// when
LOGGER.info("Second trace start");
String secondTraceId = flatMapTraceId(spans, callFlatMap(port).block());
// then
then(firstTraceId).as("Id will not be reused between calls").isNotEqualTo(secondTraceId);
LOGGER.info("Id was not reused between calls");
thenSpanInFooHasSameTraceId(secondTraceId, spanProvider);
LOGGER.info("Span in Foo has same trace id");
// and
List<String> requestUri = Arrays.stream(capture.toString().split("\n"))
.filter(s -> s.contains("Received a request to uri")).map(s -> s.split(",")[1])
.collect(Collectors.toList());
LOGGER.info("TracingFilter should not have any trace when receiving a request " + requestUri);
then(requestUri).as("TracingFilter should not have any trace when receiving a request").containsOnly("");
// and #866
then(factoryUser.wasSchedulerWrapped).isTrue();
LOGGER.info("Factory was wrapped");
});
}
private void thenAllWebClientCallsHaveSameTraceId(String traceId, RequestSender sender) {
then(sender.span.context().traceIdString()).isEqualTo(traceId);
}
private void thenSpanInFooHasSameTraceId(String traceId, SpanProvider spanProvider) {
then(spanProvider.get().context().traceIdString()).isEqualTo(traceId);
}
private Mono<ClientResponse> callFlatMap(int port) {
return WebClient.create().get().uri("http://localhost:" + port + "/withFlatMap").exchange();
}
private String flatMapTraceId(TestSpanHandler spans, ClientResponse response) {
then(response.statusCode().value()).isEqualTo(200);
then(spans).isNotEmpty();
LOGGER.info("Accumulated spans: " + spans);
List<String> traceIdOfFlatMap = spans.spans().stream().filter(
span -> span.tags().containsKey("http.path") && span.tags().get("http.path").equals("/withFlatMap"))
.map(MutableSpan::traceId).collect(Collectors.toList());
then(traceIdOfFlatMap).hasSize(1);
return traceIdOfFlatMap.get(0);
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class TestConfiguration {
brave.Span spanInFoo;
@Bean
RouterFunction<ServerResponse> handlers(Tracer tracer, RequestSender requestSender) {
return route(GET("/noFlatMap"), request -> {
LOGGER.info("noFlatMap");
Flux<Integer> one = requestSender.getAll().map(String::length);
return ServerResponse.ok().body(one, Integer.class);
}).andRoute(GET("/withFlatMap"), request -> {
LOGGER.info("withFlatMap");
Flux<Integer> one = requestSender.getAll().map(String::length);
Flux<Integer> response = one.flatMap(
size -> requestSender.getAll().doOnEach(sig -> LOGGER.info(sig.getContext().toString())))
.map(string -> {
LOGGER.info("WHATEVER YEAH");
return string.length();
});
return ServerResponse.ok().body(response, Integer.class);
}).andRoute(GET("/foo"), request -> {
LOGGER.info("foo");
this.spanInFoo = tracer.currentSpan();
return ServerResponse.ok().body(Flux.just(1), Integer.class);
});
}
@Bean
WebClient webClient() {
return WebClient.create();
}
@Bean
SpanHandler testSpanHandler() {
return new TestSpanHandler();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
RequestSender sender(WebClient client, Tracer tracer) {
return new RequestSender(client, tracer);
}
// https://github.com/spring-cloud/spring-cloud-sleuth/issues/866
@Bean
FactoryUser factoryUser() {
return new FactoryUser();
}
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class TestManualConfiguration {
brave.Span spanInFoo;
@Bean
RouterFunction<ServerResponse> handlers(org.springframework.cloud.sleuth.api.Tracer tracing,
CurrentTraceContext currentTraceContext, ManualRequestSender requestSender) {
return route(GET("/noFlatMap"), request -> {
ServerWebExchange exchange = request.exchange();
WebFluxSleuthOperators.withSpanInScope(tracing, currentTraceContext, exchange,
() -> LOGGER.info("noFlatMap"));
Flux<Integer> one = requestSender.getAll().map(String::length);
return ServerResponse.ok().body(one, Integer.class);
}).andRoute(GET("/withFlatMap"), request -> {
ServerWebExchange exchange = request.exchange();
WebFluxSleuthOperators.withSpanInScope(tracing, currentTraceContext, exchange,
() -> LOGGER.info("withFlatMap"));
Flux<Integer> one = requestSender.getAll().map(String::length);
Flux<Integer> response = one
.flatMap(size -> requestSender.getAll().doOnEach(sig -> WebFluxSleuthOperators
.withSpanInScope(sig.getContext(), () -> LOGGER.info(sig.getContext().toString()))))
.map(string -> {
WebFluxSleuthOperators.withSpanInScope(tracing, currentTraceContext, exchange,
() -> LOGGER.info("WHATEVER YEAH"));
return string.length();
});
return ServerResponse.ok().body(response, Integer.class);
}).andRoute(GET("/foo"), request -> {
ServerWebExchange exchange = request.exchange();
WebFluxSleuthOperators.withSpanInScope(tracing, currentTraceContext, exchange, () -> {
LOGGER.info("foo");
this.spanInFoo = BraveSpan.toBrave(tracing.currentSpan());
});
return ServerResponse.ok().body(Flux.just(1), Integer.class);
});
}
@Bean
WebClient webClient() {
return WebClient.create();
}
@Bean
SpanHandler testSpanHandler() {
return new TestSpanHandler();
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
ManualRequestSender sender(WebClient client, Tracer tracer) {
return new ManualRequestSender(client, tracer);
}
// https://github.com/spring-cloud/spring-cloud-sleuth/issues/866
@Bean
FactoryUser factoryUser() {
return new FactoryUser();
}
}
}
class FactoryUser {
boolean wasSchedulerWrapped = false;
FactoryUser() {
Issue866Configuration.TestHook hook = Issue866Configuration.hook;
this.wasSchedulerWrapped = hook != null && hook.executed;
}
}
interface SpanProvider extends Supplier<Span> {
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor.sample;
import brave.Tracer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.publisher.SignalType;
import org.springframework.cloud.sleuth.instrument.web.WebFluxSleuthOperators;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
class ManualRequestSender extends RequestSender {
private static final Logger LOGGER = LoggerFactory.getLogger(ManualRequestSender.class);
ManualRequestSender(WebClient webClient, Tracer tracer) {
super(webClient, tracer);
}
@Override
public Mono<String> get(Integer someParameterNotUsedNow) {
return Mono.just(this.webClient).doOnEach(WebFluxSleuthOperators.withSpanInScope(SignalType.ON_NEXT, () -> {
this.span = this.tracer.currentSpan();
LOGGER.info("getting for parameter {}", someParameterNotUsedNow);
})).flatMap(webClient -> Mono.subscriberContext()
.flatMap(ctx -> WebFluxSleuthOperators.withSpanInScope(ctx, () -> webClient.method(HttpMethod.GET)
.uri("http://localhost:" + port + "/foo").retrieve().bodyToMono(String.class))));
}
@Override
public Flux<String> getAll() {
return Flux.just("")
.flatMap(s -> Flux.deferWithContext(ctx -> Flux.just("")
.doOnNext(t -> WebFluxSleuthOperators.withSpanInScope(ctx, () -> LOGGER.info("before merge")))
.mergeWith(get(2)).mergeWith(get(3))
.doOnNext(t -> WebFluxSleuthOperators.withSpanInScope(ctx, () -> LOGGER.info("after merge")))));
}
}

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2013-2020 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
*
* https://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.reactor.sample;
import brave.Span;
import brave.Tracer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import org.springframework.http.HttpMethod;
import org.springframework.web.reactive.function.client.WebClient;
class RequestSender {
private static final Logger LOGGER = LoggerFactory.getLogger(RequestSender.class);
final WebClient webClient;
final Tracer tracer;
int port;
Span span;
RequestSender(WebClient webClient, Tracer tracer) {
this.webClient = webClient;
this.tracer = tracer;
}
public Mono<String> get(Integer someParameterNotUsedNow) {
LOGGER.info("getting for parameter {}", someParameterNotUsedNow);
this.span = this.tracer.currentSpan();
return this.webClient.method(HttpMethod.GET).uri("http://localhost:" + this.port + "/foo").retrieve()
.bodyToMono(String.class);
}
public Flux<String> getAll() {
LOGGER.info("Before merge");
Flux<String> merge = Flux.merge(get(1), get(2), get(3));
LOGGER.info("after merge");
return merge;
}
}

View File

@@ -37,7 +37,7 @@ import reactor.core.publisher.BaseSubscriber;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfigurationAccessorConfiguration;
import org.springframework.cloud.sleuth.autoconfig.instrument.reactor.TraceReactorAutoConfigurationAccessorConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static brave.Span.Kind.CLIENT;

View File

@@ -24,7 +24,7 @@ import reactor.netty.ByteBufFlux;
import reactor.netty.http.client.HttpClient;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfigurationAccessorConfiguration;
import org.springframework.cloud.sleuth.autoconfig.instrument.reactor.TraceReactorAutoConfigurationAccessorConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.web.reactive.function.client.WebClient;

View File

@@ -51,34 +51,34 @@
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

View File

@@ -38,9 +38,8 @@ import rx.plugins.RxJavaObservableExecutionHook;
import rx.plugins.RxJavaPlugins;
import rx.plugins.RxJavaSchedulersHook;
import org.springframework.cloud.sleuth.api.Tracer;
import org.springframework.cloud.sleuth.brave.bridge.BraveBaggageManager;
import org.springframework.cloud.sleuth.brave.bridge.BraveTracer;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import static org.assertj.core.api.BDDAssertions.then;
@@ -60,9 +59,7 @@ public class SleuthRxJavaSchedulersHookTests {
Tracing tracing = Tracing.newBuilder().currentTraceContext(this.currentTraceContext).addSpanHandler(this.spans)
.build();
BraveBaggageManager braveBaggageManager = new BraveBaggageManager();
Tracer tracer = BraveTracer.fromBrave(this.tracing.tracer(), this.braveBaggageManager);
Tracer tracer = BraveAccessor.tracer(this.tracing.tracer());
@AfterEach
public void clean() {

View File

@@ -57,23 +57,19 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -74,8 +74,7 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-brave</artifactId>
<scope>test</scope>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -92,17 +91,14 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@@ -16,16 +16,16 @@
package org.springframework.cloud.sleuth.brave.instrument.web.client;
import org.springframework.cloud.sleuth.api.TraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveTraceContext;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
public class HttpClientBeanPostProcessorTest
extends org.springframework.cloud.sleuth.instrument.web.client.HttpClientBeanPostProcessorTest {
@Override
public TraceContext traceContext() {
return BraveTraceContext
.fromBrave(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
return BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
}
}

View File

@@ -23,10 +23,10 @@ import brave.sampler.Sampler;
import org.assertj.core.api.Assertions;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.sleuth.api.TraceContext;
import org.springframework.cloud.sleuth.api.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
import org.springframework.cloud.sleuth.brave.bridge.BraveTraceContext;
import org.springframework.cloud.sleuth.brave.bridge.BraveAccessor;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -39,8 +39,8 @@ public class ReactorNettyHttpClientSpringBootTests
@Override
public TraceContext traceContext() {
return BraveTraceContext
.fromBrave(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
return BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
}
@Override

View File

@@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2020 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
~
~ https://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.
~
~
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-zipkin-tests</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Sleuth Brave Zipkin Tests</name>
<description>Spring Cloud Sleuth Brave Zipkin Tests</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests-brave</artifactId>
<version>3.0.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<sonar.skip>true</sonar.skip>
</properties>
<build>
<plugins>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.zipkin2</groupId>
<artifactId>zipkin</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-kafka</artifactId>
<exclusions>
<!-- assigned with spring-kafka -->
<exclusion>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-activemq-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-client</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-amqp-client</artifactId>
<exclusions>
<!-- assigned with spring-rabbit -->
<exclusion>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-tests</artifactId>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<!-- Kotlin... -->
<version>4.8.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2013-2020 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
*
* https://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.autoconfig.zipkin2;
/**
* @author Matcin Wielgus
*/
public class BraveDefaultEndpointLocatorConfigurationTest extends DefaultEndpointLocatorConfigurationTest {
}

View File

@@ -0,0 +1,148 @@
/*
* Copyright 2013-2020 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
*
* https://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.autoconfig.zipkin2;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.propagation.TraceContext;
import brave.sampler.Sampler;
import okhttp3.mockwebserver.RecordedRequest;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import zipkin2.reporter.AsyncReporter;
import zipkin2.reporter.Reporter;
import zipkin2.reporter.Sender;
import zipkin2.reporter.brave.ZipkinSpanHandler;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
import static org.mockito.Mockito.mock;
import static org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinBraveConfiguration.SPAN_HANDLER_COMPARATOR;
public class BraveZipkinAutoConfigurationTests
extends org.springframework.cloud.sleuth.autoconfig.zipkin2.ZipkinAutoConfigurationTests {
@Override
protected Class tracerZipkinConfiguration() {
return ZipkinBraveConfiguration.class;
}
@Override
protected Class tracerConfiguration() {
return BraveAutoConfiguration.class;
}
@Override
protected Class configurationClass() {
return Config.class;
}
@Test
public void supportsMultipleReporters() throws Exception {
zipkinRunner().withUserConfiguration(MultipleReportersConfig.class)
.withPropertyValues("spring.zipkin.base-url=" + this.server.url("/").toString()).run(context -> {
then(context.getBeansOfType(Sender.class)).hasSize(2);
then(context.getBeansOfType(Sender.class)).containsKeys(ZipkinAutoConfiguration.SENDER_BEAN_NAME,
"otherSender");
then(context.getBeansOfType(Reporter.class)).hasSize(2);
then(context.getBeansOfType(Reporter.class))
.containsKeys(ZipkinAutoConfiguration.REPORTER_BEAN_NAME, "otherReporter");
context.getBean(Tracer.class).nextSpan().name("foo").tag("foo", "bar").start().end();
context.getBean(ZipkinAutoConfiguration.REPORTER_BEAN_NAME, AsyncReporter.class).flush();
Awaitility.await().atMost(250, TimeUnit.MILLISECONDS)
.untilAsserted(() -> then(this.server.getRequestCount()).isGreaterThan(1));
Awaitility.await().atMost(5, TimeUnit.SECONDS).untilAsserted(() -> {
RecordedRequest request = this.server.takeRequest(1, TimeUnit.SECONDS);
then(request.getPath()).isEqualTo("/api/v2/spans");
then(request.getBody().readUtf8()).contains("localEndpoint");
});
MultipleReportersConfig.OtherSender sender = context
.getBean(MultipleReportersConfig.OtherSender.class);
Awaitility.await().atMost(250, TimeUnit.MILLISECONDS)
.untilAsserted(() -> then(sender.isSpanSent()).isTrue());
});
}
@Test
void span_handler_comparator() {
SpanHandler handler1 = mock(SpanHandler.class);
SpanHandler handler2 = mock(SpanHandler.class);
ZipkinSpanHandler zipkin1 = mock(ZipkinSpanHandler.class);
ZipkinSpanHandler zipkin2 = mock(ZipkinSpanHandler.class);
ArrayList<SpanHandler> spanHandlers = new ArrayList<>();
spanHandlers.add(handler1);
spanHandlers.add(zipkin1);
spanHandlers.add(handler2);
spanHandlers.add(zipkin2);
spanHandlers.sort(SPAN_HANDLER_COMPARATOR);
assertThat(spanHandlers).containsExactly(handler1, handler2, zipkin1, zipkin2);
}
@Configuration(proxyBeanMethods = false)
protected static class Config {
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
@Configuration(proxyBeanMethods = false)
protected static class HandlersConfig {
@Bean
SpanHandler handlerOne() {
return new SpanHandler() {
@Override
public boolean end(TraceContext traceContext, MutableSpan span, Cause cause) {
span.name("foo");
return true; // keep this span
}
};
}
@Bean
SpanHandler handlerTwo() {
return new SpanHandler() {
@Override
public boolean end(TraceContext traceContext, MutableSpan span, Cause cause) {
span.name(span.name() + " bar");
return true; // keep this span
}
};
}
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2013-2020 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
*
* https://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.autoconfig.zipkin2;
import brave.sampler.Sampler;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@SpringBootTest(classes = BraveZipkinDiscoveryClientTests.TestConfig.class)
public class BraveZipkinDiscoveryClientTests
extends org.springframework.cloud.sleuth.zipkin2.ZipkinDiscoveryClientTests {
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class TestConfig {
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
}

View File

@@ -0,0 +1,5 @@
logging.level.org.springframework.cloud: DEBUG
logging.level.com.netflix.discovery.InstanceInfoReplicator: ERROR
logging.level.org.springframework.cloud.sleuth.brave.instrument.web.client.feign: TRACE
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.cloud.gateway.config.GatewayAutoConfiguration, org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration, org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration