This commit is contained in:
Marcin Grzejszczak
2021-05-05 08:51:34 +02:00
parent 674c323d17
commit e55ff59974
34 changed files with 2781 additions and 2781 deletions

View File

@@ -1,114 +1,114 @@
/*
* Copyright 2013-2021 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.exporter;
import java.util.Collection;
import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.lang.Nullable;
/**
* This API is inspired by OpenZipkin Brave (from {code MutableSpan}).
*
* Represents a span that has been finished and is ready to be sent to an external
* location (e.g. Zipkin).
*
* @author OpenZipkin Brave Authors
* @author Marcin Grzejszczak
* @since 3.0.0
*/
public interface FinishedSpan {
/**
* @return span's name
*/
String getName();
/**
* @return span's start timestamp
*/
long getStartTimestamp();
/**
* @return span's end timestamp
*/
long getEndTimestamp();
/**
* @return span's tags
*/
Map<String, String> getTags();
/**
* @return span's events as timestamp to value mapping
*/
Collection<Map.Entry<Long, String>> getEvents();
/**
* @return span's span id
*/
String getSpanId();
/**
* @return span's parent id or {@code null} if not set
*/
@Nullable
String getParentId();
/**
* @return span's remote ip
*/
@Nullable
String getRemoteIp();
/**
* @return span's local ip
*/
@Nullable
default String getLocalIp() {
return null;
}
/**
* @return span's remote port
*/
int getRemotePort();
/**
* @return span's trace id
*/
String getTraceId();
/**
* @return corresponding error or {@code null} if one was not thrown
*/
@Nullable
Throwable getError();
/**
* @return span's kind
*/
Span.Kind getKind();
/**
* @return remote service name or {@code null} if not set
*/
@Nullable
String getRemoteServiceName();
}
/*
* Copyright 2013-2021 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.exporter;
import java.util.Collection;
import java.util.Map;
import org.springframework.cloud.sleuth.Span;
import org.springframework.lang.Nullable;
/**
* This API is inspired by OpenZipkin Brave (from {code MutableSpan}).
*
* Represents a span that has been finished and is ready to be sent to an external
* location (e.g. Zipkin).
*
* @author OpenZipkin Brave Authors
* @author Marcin Grzejszczak
* @since 3.0.0
*/
public interface FinishedSpan {
/**
* @return span's name
*/
String getName();
/**
* @return span's start timestamp
*/
long getStartTimestamp();
/**
* @return span's end timestamp
*/
long getEndTimestamp();
/**
* @return span's tags
*/
Map<String, String> getTags();
/**
* @return span's events as timestamp to value mapping
*/
Collection<Map.Entry<Long, String>> getEvents();
/**
* @return span's span id
*/
String getSpanId();
/**
* @return span's parent id or {@code null} if not set
*/
@Nullable
String getParentId();
/**
* @return span's remote ip
*/
@Nullable
String getRemoteIp();
/**
* @return span's local ip
*/
@Nullable
default String getLocalIp() {
return null;
}
/**
* @return span's remote port
*/
int getRemotePort();
/**
* @return span's trace id
*/
String getTraceId();
/**
* @return corresponding error or {@code null} if one was not thrown
*/
@Nullable
Throwable getError();
/**
* @return span's kind
*/
Span.Kind getKind();
/**
* @return remote service name or {@code null} if not set
*/
@Nullable
String getRemoteServiceName();
}

View File

@@ -1,54 +1,54 @@
/*
* Copyright 2013-2021 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.instrument.batch;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} that registers instrumentation for Spring Batch.
*
* @author Marcin Grzejszczak
* @since 3.1.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(JobBuilderFactory.class)
@ConditionalOnBean(Tracer.class)
@ConditionalOnProperty(value = "spring.sleuth.batch.enabled", matchIfMissing = true)
@AutoConfigureAfter(BraveAutoConfiguration.class)
public class TraceBatchAutoConfiguration {
@Bean
static TraceJobBuilderFactoryBeanPostProcessor traceJobBuilderFactoryBeanPostProcessor(BeanFactory beanFactory) {
return new TraceJobBuilderFactoryBeanPostProcessor(beanFactory);
}
@Bean
static TraceStepBuilderFactoryBeanPostProcessor traceStepBuilderFactoryBeanPostProcessor(BeanFactory beanFactory) {
return new TraceStepBuilderFactoryBeanPostProcessor(beanFactory);
}
}
/*
* Copyright 2013-2021 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.instrument.batch;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.autoconfig.brave.BraveAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} that registers instrumentation for Spring Batch.
*
* @author Marcin Grzejszczak
* @since 3.1.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(JobBuilderFactory.class)
@ConditionalOnBean(Tracer.class)
@ConditionalOnProperty(value = "spring.sleuth.batch.enabled", matchIfMissing = true)
@AutoConfigureAfter(BraveAutoConfiguration.class)
public class TraceBatchAutoConfiguration {
@Bean
static TraceJobBuilderFactoryBeanPostProcessor traceJobBuilderFactoryBeanPostProcessor(BeanFactory beanFactory) {
return new TraceJobBuilderFactoryBeanPostProcessor(beanFactory);
}
@Bean
static TraceStepBuilderFactoryBeanPostProcessor traceStepBuilderFactoryBeanPostProcessor(BeanFactory beanFactory) {
return new TraceStepBuilderFactoryBeanPostProcessor(beanFactory);
}
}

View File

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = NullSpanTagAnnotationHandlerTests.Config.class)
public class NullSpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.instrument.annotation.NullSpanTagAnnotationHandlerTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = NullSpanTagAnnotationHandlerTests.Config.class)
public class NullSpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.instrument.annotation.NullSpanTagAnnotationHandlerTests {
@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

@@ -1,61 +1,61 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectFluxTests.Config.class)
public class SleuthSpanCreatorAspectFluxTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectFluxTests {
@Override
public TraceContext traceContext() {
return BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
}
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectFluxTests.Config.class)
public class SleuthSpanCreatorAspectFluxTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectFluxTests {
@Override
public TraceContext traceContext() {
return BraveAccessor
.traceContext(brave.propagation.TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build());
}
@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

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectMonoTests.Config.class)
public class SleuthSpanCreatorAspectMonoTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectMonoTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectMonoTests.Config.class)
public class SleuthSpanCreatorAspectMonoTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectMonoTests {
@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

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectNegativeTests.Config.class)
public class SleuthSpanCreatorAspectNegativeTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectNegativeTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectNegativeTests.Config.class)
public class SleuthSpanCreatorAspectNegativeTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectNegativeTests {
@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

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectTests.Config.class)
public class SleuthSpanCreatorAspectTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorAspectTests.Config.class)
public class SleuthSpanCreatorAspectTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorAspectTests {
@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

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorCircularDependencyTests.Config.class)
public class SleuthSpanCreatorCircularDependencyTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorCircularDependencyTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SleuthSpanCreatorCircularDependencyTests.Config.class)
public class SleuthSpanCreatorCircularDependencyTests
extends org.springframework.cloud.sleuth.instrument.annotation.SleuthSpanCreatorCircularDependencyTests {
@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

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SpanTagAnnotationHandlerTests.Config.class)
public class SpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.instrument.annotation.SpanTagAnnotationHandlerTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.annotation;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = SpanTagAnnotationHandlerTests.Config.class)
public class SpanTagAnnotationHandlerTests
extends org.springframework.cloud.sleuth.instrument.annotation.SpanTagAnnotationHandlerTests {
@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

@@ -1,24 +1,24 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class AsyncDisabledTests extends org.springframework.cloud.sleuth.instrument.async.AsyncDisabledTests {
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class AsyncDisabledTests extends org.springframework.cloud.sleuth.instrument.async.AsyncDisabledTests {
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class LazyTraceThreadPoolTaskSchedulerTests
extends org.springframework.cloud.sleuth.instrument.async.LazyTraceThreadPoolTaskSchedulerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class LazyTraceThreadPoolTaskSchedulerTests
extends org.springframework.cloud.sleuth.instrument.async.LazyTraceThreadPoolTaskSchedulerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,37 +1,37 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceAsyncAspectTest extends org.springframework.cloud.sleuth.instrument.async.TraceAsyncAspectTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceAsyncAspectTest extends org.springframework.cloud.sleuth.instrument.async.TraceAsyncAspectTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,158 +1,158 @@
/*
* Copyright 2013-2021 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.async;
import brave.Span;
import brave.SpanCustomizer;
import brave.Tracer;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.propagation.CurrentTraceContext;
import brave.propagation.TraceContext;
import brave.test.IntegrationTestSpanHandler;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.SpanName;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
classes = { TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class })
@DirtiesContext // flakey otherwise
public class TraceAsyncIntegrationTests {
private static final Logger log = LoggerFactory.getLogger(TraceAsyncIntegrationTests.class);
@ClassRule
public static IntegrationTestSpanHandler spans = new IntegrationTestSpanHandler();
TraceContext context = TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build();
@Autowired
AsyncLogic asyncLogic;
@Autowired
CurrentTraceContext currentTraceContext;
@Autowired
Tracer tracer;
@Test
public void should_set_span_on_an_async_annotated_method() {
Span parent = tracer.joinSpan(context);
try (Tracer.SpanInScope ws = tracer.withSpanInScope(parent.start())) {
log.info("HELLO");
asyncLogic.invokeAsync();
MutableSpan span = takeDesirableSpan("invoke-async");
assertThat(span.name()).isEqualTo("invoke-async");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic").containsEntry("method", "invokeAsync");
// continues the trace
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
finally {
parent.abandon();
}
}
@Test
public void should_set_span_with_custom_method_on_an_async_annotated_method() {
Span parent = tracer.joinSpan(context);
try (Tracer.SpanInScope ws = tracer.withSpanInScope(parent.start())) {
log.info("HELLO");
asyncLogic.invokeAsync_customName();
MutableSpan span = takeDesirableSpan("foo");
assertThat(span.name()).isEqualTo("foo");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic").containsEntry("method",
"invokeAsync_customName");
// continues the trace
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
finally {
parent.abandon();
}
}
// Sleuth adds spans named "async" with no tags when an executor is used.
// We don't want that one.
MutableSpan takeDesirableSpan(String name) {
MutableSpan span1 = spans.takeLocalSpan();
log.info("Span [" + span1 + "] found");
MutableSpan span = span1 != null && name.equals(span1.name()) ? span1 : null;
assertThat(span).as("No span with name <> was found", name).isNotNull();
return span;
}
@EnableAutoConfiguration
@EnableAsync
@Configuration(proxyBeanMethods = false)
static class TraceAsyncITestConfiguration {
@Bean
AsyncLogic asyncLogic(SpanCustomizer customizer) {
return new AsyncLogic(customizer);
}
@Bean
SpanHandler testSpanHandler() {
return spans;
}
}
static class AsyncLogic {
private static final Logger log = LoggerFactory.getLogger(AsyncLogic.class);
final SpanCustomizer customizer;
AsyncLogic(SpanCustomizer customizer) {
this.customizer = customizer;
}
@Async
public void invokeAsync() {
customizer.annotate("@Async"); // proves the handler is in scope
log.info("HELLO ASYNC");
}
@Async
@SpanName("foo")
public void invokeAsync_customName() {
customizer.annotate("@Async"); // proves the handler is in scope
log.info("HELLO ASYNC CUSTOM NAME");
}
}
}
/*
* Copyright 2013-2021 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.async;
import brave.Span;
import brave.SpanCustomizer;
import brave.Tracer;
import brave.handler.MutableSpan;
import brave.handler.SpanHandler;
import brave.propagation.CurrentTraceContext;
import brave.propagation.TraceContext;
import brave.test.IntegrationTestSpanHandler;
import org.junit.ClassRule;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.SpanName;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
classes = { TraceAsyncIntegrationTests.TraceAsyncITestConfiguration.class })
@DirtiesContext // flakey otherwise
public class TraceAsyncIntegrationTests {
private static final Logger log = LoggerFactory.getLogger(TraceAsyncIntegrationTests.class);
@ClassRule
public static IntegrationTestSpanHandler spans = new IntegrationTestSpanHandler();
TraceContext context = TraceContext.newBuilder().traceId(1).spanId(2).sampled(true).build();
@Autowired
AsyncLogic asyncLogic;
@Autowired
CurrentTraceContext currentTraceContext;
@Autowired
Tracer tracer;
@Test
public void should_set_span_on_an_async_annotated_method() {
Span parent = tracer.joinSpan(context);
try (Tracer.SpanInScope ws = tracer.withSpanInScope(parent.start())) {
log.info("HELLO");
asyncLogic.invokeAsync();
MutableSpan span = takeDesirableSpan("invoke-async");
assertThat(span.name()).isEqualTo("invoke-async");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic").containsEntry("method", "invokeAsync");
// continues the trace
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
finally {
parent.abandon();
}
}
@Test
public void should_set_span_with_custom_method_on_an_async_annotated_method() {
Span parent = tracer.joinSpan(context);
try (Tracer.SpanInScope ws = tracer.withSpanInScope(parent.start())) {
log.info("HELLO");
asyncLogic.invokeAsync_customName();
MutableSpan span = takeDesirableSpan("foo");
assertThat(span.name()).isEqualTo("foo");
assertThat(span.containsAnnotation("@Async")).isTrue();
assertThat(span.tags()).containsEntry("class", "AsyncLogic").containsEntry("method",
"invokeAsync_customName");
// continues the trace
assertThat(span.traceId()).isEqualTo(context.traceIdString());
}
finally {
parent.abandon();
}
}
// Sleuth adds spans named "async" with no tags when an executor is used.
// We don't want that one.
MutableSpan takeDesirableSpan(String name) {
MutableSpan span1 = spans.takeLocalSpan();
log.info("Span [" + span1 + "] found");
MutableSpan span = span1 != null && name.equals(span1.name()) ? span1 : null;
assertThat(span).as("No span with name <> was found", name).isNotNull();
return span;
}
@EnableAutoConfiguration
@EnableAsync
@Configuration(proxyBeanMethods = false)
static class TraceAsyncITestConfiguration {
@Bean
AsyncLogic asyncLogic(SpanCustomizer customizer) {
return new AsyncLogic(customizer);
}
@Bean
SpanHandler testSpanHandler() {
return spans;
}
}
static class AsyncLogic {
private static final Logger log = LoggerFactory.getLogger(AsyncLogic.class);
final SpanCustomizer customizer;
AsyncLogic(SpanCustomizer customizer) {
this.customizer = customizer;
}
@Async
public void invokeAsync() {
customizer.annotate("@Async"); // proves the handler is in scope
log.info("HELLO ASYNC");
}
@Async
@SpanName("foo")
public void invokeAsync_customName() {
customizer.annotate("@Async"); // proves the handler is in scope
log.info("HELLO ASYNC CUSTOM NAME");
}
}
}

View File

@@ -1,38 +1,38 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceAsyncListenableTaskExecutorTest
extends org.springframework.cloud.sleuth.instrument.async.TraceAsyncListenableTaskExecutorTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceAsyncListenableTaskExecutorTest
extends org.springframework.cloud.sleuth.instrument.async.TraceAsyncListenableTaskExecutorTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,34 +1,34 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceCallableTests extends org.springframework.cloud.sleuth.instrument.async.TraceCallableTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceCallableTests extends org.springframework.cloud.sleuth.instrument.async.TraceCallableTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,42 +1,42 @@
/*
* Copyright 2013-2021 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.async;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceRunnableTests extends org.springframework.cloud.sleuth.instrument.async.TraceRunnableTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
protected void assertThatThereIsNoParentId(Span secondSpan) {
BDDAssertions.then(secondSpan.context().parentId()).as("saved span as remnant of first span").isNull();
}
}
/*
* Copyright 2013-2021 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.async;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceRunnableTests extends org.springframework.cloud.sleuth.instrument.async.TraceRunnableTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
protected void assertThatThereIsNoParentId(Span secondSpan) {
BDDAssertions.then(secondSpan.context().parentId()).as("saved span as remnant of first span").isNull();
}
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceScheduledThreadPoolExecutorAnotherConstructorTests extends
org.springframework.cloud.sleuth.instrument.async.TraceScheduledThreadPoolExecutorAnotherConstructorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceScheduledThreadPoolExecutorAnotherConstructorTests extends
org.springframework.cloud.sleuth.instrument.async.TraceScheduledThreadPoolExecutorAnotherConstructorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceScheduledThreadPoolExecutorTests
extends org.springframework.cloud.sleuth.instrument.async.TraceScheduledThreadPoolExecutorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceScheduledThreadPoolExecutorTests
extends org.springframework.cloud.sleuth.instrument.async.TraceScheduledThreadPoolExecutorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceThreadPoolTaskExecutorTests
extends org.springframework.cloud.sleuth.instrument.async.TraceThreadPoolTaskExecutorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceThreadPoolTaskExecutorTests
extends org.springframework.cloud.sleuth.instrument.async.TraceThreadPoolTaskExecutorTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceThreadPoolTaskSchedulerTests
extends org.springframework.cloud.sleuth.instrument.async.TraceThreadPoolTaskSchedulerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceThreadPoolTaskSchedulerTests
extends org.springframework.cloud.sleuth.instrument.async.TraceThreadPoolTaskSchedulerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,35 +1,35 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceableExecutorServiceTests
extends org.springframework.cloud.sleuth.instrument.async.TraceableExecutorServiceTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class TraceableExecutorServiceTests
extends org.springframework.cloud.sleuth.instrument.async.TraceableExecutorServiceTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,38 +1,38 @@
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceableScheduledExecutorServiceTest
extends org.springframework.cloud.sleuth.instrument.async.TraceableScheduledExecutorServiceTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}
/*
* Copyright 2013-2021 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.async;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.test.TestTracingAware;
/**
* @author Marcin Grzejszczak
*/
public class TraceableScheduledExecutorServiceTest
extends org.springframework.cloud.sleuth.instrument.async.TraceableScheduledExecutorServiceTest {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
}

View File

@@ -1,182 +1,182 @@
/*
* Copyright 2013-2021 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.async.issues.issue1212;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Bertrand Renuart
*/
public class GH1212Tests {
@Test
public void defaultTaskExecutor() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
DefaultTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("defaultTaskExecutor");
}
}
@Test
public void singleTaskExecutor() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
SingleTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("singleTaskExecutor");
}
}
@Test
public void multipleTaskExecutors() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
MultipleTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).doesNotStartWith("multipleTaskExecutor");
assertThat(asyncThreadName).startsWith("SimpleAsyncTaskExecutor"); // <--
// comes
// from
// Sleuth's
// own
// AsyncConfigurer
}
}
@Test
public void customAsyncConfigurer() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
CustomAsyncConfigurerConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("customAsyncConfigurer");
}
}
private String getAsyncThreadName(ApplicationContext ctx) throws Exception {
return ctx.getBean(AsyncComponent.class).asyncMethod().get();
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableAsync
public static class App {
@Bean
AsyncComponent asyncComponent() {
return new AsyncComponent();
}
}
public static class AsyncComponent {
@Async
public CompletableFuture<String> asyncMethod() {
LoggerFactory.getLogger("test").info("asyncMethod invoked");
return CompletableFuture.completedFuture(Thread.currentThread().getName());
}
}
/*
* Configuration with a single Executor named `taskExecutor`
*/
@Configuration(proxyBeanMethods = false)
public static class DefaultTaskExecutorConfig {
@Bean(name = AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME)
public Executor taskExecutor() {
return new SimpleAsyncTaskExecutor("defaultTaskExecutor");
}
}
/*
* Configuration with a single TaskExecutor
*/
@Configuration(proxyBeanMethods = false)
public static class SingleTaskExecutorConfig {
@Bean
// there's the task
@Primary
public TaskExecutor singleTaskExecutor() {
return new SimpleAsyncTaskExecutor("singleTaskExecutor");
}
}
/*
* Configuration with a multiple TaskExecutors --> Spring won't pick any unless one
* is @Primary
*/
@Configuration(proxyBeanMethods = false)
public static class MultipleTaskExecutorConfig {
@Bean
public TaskExecutor multipleTaskExecutor1() {
return new SimpleAsyncTaskExecutor("multipleTaskExecutor1");
}
@Bean
public TaskExecutor multipleTaskExecutor2() {
return new SimpleAsyncTaskExecutor("multipleTaskExecutor2");
}
}
/*
* Configuration where a custom AsyncConfigurer is provided
*/
@Configuration(proxyBeanMethods = false)
public static class CustomAsyncConfigurerConfig {
@Bean
public AsyncConfigurer customAsyncConfigurer() {
return new AsyncConfigurerSupport() {
@Override
public Executor getAsyncExecutor() {
return new SimpleAsyncTaskExecutor("customAsyncConfigurer");
}
};
}
}
}
/*
* Copyright 2013-2021 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.async.issues.issue1212;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import org.junit.jupiter.api.Test;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncExecutionAspectSupport;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Bertrand Renuart
*/
public class GH1212Tests {
@Test
public void defaultTaskExecutor() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
DefaultTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("defaultTaskExecutor");
}
}
@Test
public void singleTaskExecutor() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
SingleTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("singleTaskExecutor");
}
}
@Test
public void multipleTaskExecutors() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
MultipleTaskExecutorConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).doesNotStartWith("multipleTaskExecutor");
assertThat(asyncThreadName).startsWith("SimpleAsyncTaskExecutor"); // <--
// comes
// from
// Sleuth's
// own
// AsyncConfigurer
}
}
@Test
public void customAsyncConfigurer() throws Exception {
try (ConfigurableApplicationContext ctx = new SpringApplicationBuilder(App.class,
CustomAsyncConfigurerConfig.class).web(WebApplicationType.NONE).run()) {
String asyncThreadName = getAsyncThreadName(ctx);
assertThat(asyncThreadName).startsWith("customAsyncConfigurer");
}
}
private String getAsyncThreadName(ApplicationContext ctx) throws Exception {
return ctx.getBean(AsyncComponent.class).asyncMethod().get();
}
@SpringBootConfiguration
@EnableAutoConfiguration
@EnableAsync
public static class App {
@Bean
AsyncComponent asyncComponent() {
return new AsyncComponent();
}
}
public static class AsyncComponent {
@Async
public CompletableFuture<String> asyncMethod() {
LoggerFactory.getLogger("test").info("asyncMethod invoked");
return CompletableFuture.completedFuture(Thread.currentThread().getName());
}
}
/*
* Configuration with a single Executor named `taskExecutor`
*/
@Configuration(proxyBeanMethods = false)
public static class DefaultTaskExecutorConfig {
@Bean(name = AsyncExecutionAspectSupport.DEFAULT_TASK_EXECUTOR_BEAN_NAME)
public Executor taskExecutor() {
return new SimpleAsyncTaskExecutor("defaultTaskExecutor");
}
}
/*
* Configuration with a single TaskExecutor
*/
@Configuration(proxyBeanMethods = false)
public static class SingleTaskExecutorConfig {
@Bean
// there's the task
@Primary
public TaskExecutor singleTaskExecutor() {
return new SimpleAsyncTaskExecutor("singleTaskExecutor");
}
}
/*
* Configuration with a multiple TaskExecutors --> Spring won't pick any unless one
* is @Primary
*/
@Configuration(proxyBeanMethods = false)
public static class MultipleTaskExecutorConfig {
@Bean
public TaskExecutor multipleTaskExecutor1() {
return new SimpleAsyncTaskExecutor("multipleTaskExecutor1");
}
@Bean
public TaskExecutor multipleTaskExecutor2() {
return new SimpleAsyncTaskExecutor("multipleTaskExecutor2");
}
}
/*
* Configuration where a custom AsyncConfigurer is provided
*/
@Configuration(proxyBeanMethods = false)
public static class CustomAsyncConfigurerConfig {
@Bean
public AsyncConfigurer customAsyncConfigurer() {
return new AsyncConfigurerSupport() {
@Override
public Executor getAsyncExecutor() {
return new SimpleAsyncTaskExecutor("customAsyncConfigurer");
}
};
}
}
}

View File

@@ -1,480 +1,480 @@
/*
* Copyright 2013-2021 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.async.issues.issue410;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracer;
import brave.sampler.Sampler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(classes = { AppConfig.class, Application.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
public class Issue410Tests {
private static final Log log = LogFactory.getLog(Issue410Tests.class);
@Autowired
Environment environment;
@Autowired
Tracer tracer;
@Autowired
AsyncTask asyncTask;
@Autowired
RestTemplate restTemplate;
/**
* Related to issue #445.
*/
@Autowired
Application.MyService executorService;
@Test
public void should_pass_tracing_info_for_tasks_running_without_a_pool() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/without_pool",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
@Test
public void should_pass_tracing_info_for_tasks_running_with_a_pool() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/with_pool", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #423.
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_executor() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/completable",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #423.
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_task_scheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/taskScheduler",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #1232
*/
@Test
public void should_pass_tracing_info_for_submitted_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_submit", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
@Test
public void should_pass_tracing_info_for_scheduled_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_schedule", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #1232
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_scheduledThreadPoolExecutor() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/scheduledThreadPoolExecutor", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
private int port() {
return this.environment.getProperty("local.server.port", Integer.class);
}
}
@Configuration(proxyBeanMethods = false)
@EnableAsync
class AppConfig {
@Bean
public Sampler testSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean("taskScheduler")
public Executor myScheduler() {
return Executors.newSingleThreadExecutor();
}
@Bean
public Executor poolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.initialize();
return executor;
}
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.initialize();
return executor;
}
@Bean
public ScheduledThreadPoolExecutor scheduledThreadPoolExecutor() {
return new ScheduledThreadPoolExecutor(10);
}
}
@Component
class AsyncTask {
private static final Log log = LogFactory.getLog(AsyncTask.class);
@Autowired
Tracer tracer;
@Autowired
@Qualifier("poolTaskExecutor")
Executor executor;
@Autowired
@Qualifier("taskScheduler")
Executor taskScheduler;
@Autowired
BeanFactory beanFactory;
@Autowired
ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Autowired
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private AtomicReference<Span> span = new AtomicReference<>();
@Async("poolTaskExecutor")
public void runWithPool() {
log.info("This task is running with a pool.");
this.span.set(this.tracer.currentSpan());
}
@Async
public void runWithoutPool() {
log.info("This task is running without a pool.");
this.span.set(this.tracer.currentSpan());
}
public Span completableFutures() throws ExecutionException, InterruptedException {
log.info("This task is running with completable future");
CompletableFuture<Span> span1 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("First completable future");
return AsyncTask.this.tracer.currentSpan();
}, AsyncTask.this.executor);
CompletableFuture<Span> span2 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("Second completable future");
return AsyncTask.this.tracer.currentSpan();
}, AsyncTask.this.executor);
CompletableFuture<Span> response = CompletableFuture.allOf(span1, span2).thenApply(ignoredVoid -> {
AsyncTask.log.info("Third completable future");
Span joinedSpan1 = span1.join();
Span joinedSpan2 = span2.join();
then(joinedSpan2).isNotNull();
then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId());
AsyncTask.log.info("TraceIds are correct");
return joinedSpan2;
});
this.span.set(response.get());
return this.span.get();
}
public Span taskScheduler() throws ExecutionException, InterruptedException {
log.info("This task is running with completable future");
CompletableFuture<Span> span1 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("First completable future");
return AsyncTask.this.tracer.currentSpan();
}, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler));
CompletableFuture<Span> span2 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("Second completable future");
return AsyncTask.this.tracer.currentSpan();
}, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler));
CompletableFuture<Span> response = CompletableFuture.allOf(span1, span2).thenApply(ignoredVoid -> {
AsyncTask.log.info("Third completable future");
Span joinedSpan1 = span1.join();
Span joinedSpan2 = span2.join();
then(joinedSpan2).isNotNull();
then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId());
AsyncTask.log.info("TraceIds are correct");
return joinedSpan2;
});
this.span.set(response.get());
return this.span.get();
}
public Span scheduledThreadPoolExecutor() throws ExecutionException, InterruptedException {
log.info("This task is running with ScheduledThreadPoolExecutor");
this.scheduledThreadPoolExecutor.submit(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}).get();
return this.span.get();
}
public Span threadPoolTaskSchedulerSubmit() throws ExecutionException, InterruptedException {
log.info("This task is running with ThreadPoolTaskScheduler");
this.threadPoolTaskScheduler.submit(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}).get();
return this.span.get();
}
public Span threadPoolTaskSchedulerSchedule() throws ExecutionException, InterruptedException {
log.info("This task is running with ThreadPoolTaskScheduler");
this.threadPoolTaskScheduler.schedule(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}, new Date()).get();
return this.span.get();
}
public AtomicReference<Span> getSpan() {
return this.span;
}
}
@SpringBootApplication(exclude = SpringDataWebAutoConfiguration.class)
@RestController
class Application {
private static final Log log = LogFactory.getLog(Application.class);
@Autowired
AsyncTask asyncTask;
@Autowired
Tracer tracer;
@RequestMapping("/with_pool")
public String withPool() {
log.info("Executing with pool.");
this.asyncTask.runWithPool();
return this.tracer.currentSpan().context().traceIdString();
}
@RequestMapping("/without_pool")
public String withoutPool() {
log.info("Executing without pool.");
this.asyncTask.runWithoutPool();
return this.tracer.currentSpan().context().traceIdString();
}
@RequestMapping("/completable")
public String completable() throws ExecutionException, InterruptedException {
log.info("Executing completable");
return this.asyncTask.completableFutures().context().traceIdString();
}
@RequestMapping("/taskScheduler")
public String taskScheduler() throws ExecutionException, InterruptedException {
log.info("Executing completable via task scheduler");
return this.asyncTask.taskScheduler().context().traceIdString();
}
@RequestMapping("/threadPoolTaskScheduler_submit")
public String threadPoolTaskSchedulerSubmit() throws ExecutionException, InterruptedException {
log.info("Executing completable via ThreadPoolTaskScheduler");
return this.asyncTask.threadPoolTaskSchedulerSubmit().context().traceIdString();
}
@RequestMapping("/threadPoolTaskScheduler_schedule")
public String threadPoolTaskSchedulerSchedule() throws ExecutionException, InterruptedException {
log.info("Executing completable via ThreadPoolTaskScheduler");
return this.asyncTask.threadPoolTaskSchedulerSchedule().context().traceIdString();
}
@RequestMapping("/scheduledThreadPoolExecutor")
public String scheduledThreadPoolExecutor() throws ExecutionException, InterruptedException {
log.info("Executing completable via ScheduledThreadPoolExecutor");
return this.asyncTask.scheduledThreadPoolExecutor().context().traceIdString();
}
/**
* Related to issue #445.
* @return service bean
*/
@Bean
public MyService executorService() {
return new MyService() {
@Override
public void execute(Runnable command) {
}
};
}
interface MyService extends Executor {
}
}
/*
* Copyright 2013-2021 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.async.issues.issue410;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracer;
import brave.sampler.Sampler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(classes = { AppConfig.class, Application.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
public class Issue410Tests {
private static final Log log = LogFactory.getLog(Issue410Tests.class);
@Autowired
Environment environment;
@Autowired
Tracer tracer;
@Autowired
AsyncTask asyncTask;
@Autowired
RestTemplate restTemplate;
/**
* Related to issue #445.
*/
@Autowired
Application.MyService executorService;
@Test
public void should_pass_tracing_info_for_tasks_running_without_a_pool() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/without_pool",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
@Test
public void should_pass_tracing_info_for_tasks_running_with_a_pool() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/with_pool", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #423.
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_executor() {
Span span = this.tracer.nextSpan().name("foo");
log.info("Starting test");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/completable",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #423.
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_task_scheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate.getForObject("http://localhost:" + port() + "/taskScheduler",
String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #1232
*/
@Test
public void should_pass_tracing_info_for_submitted_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_submit", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
@Test
public void should_pass_tracing_info_for_scheduled_tasks_with_threadPoolTaskScheduler() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/threadPoolTaskScheduler_schedule", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
/**
* Related to issue #1232
*/
@Test
public void should_pass_tracing_info_for_completable_futures_with_scheduledThreadPoolExecutor() {
Span span = this.tracer.nextSpan().name("foo");
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
log.info("Starting test");
String response = this.restTemplate
.getForObject("http://localhost:" + port() + "/scheduledThreadPoolExecutor", String.class);
then(response).isEqualTo(span.context().traceIdString());
Awaitility.await().untilAsserted(() -> {
then(this.asyncTask.getSpan().get()).isNotNull();
then(this.asyncTask.getSpan().get().context().traceId()).isEqualTo(span.context().traceId());
});
}
finally {
span.finish();
}
then(this.tracer.currentSpan()).isNull();
}
private int port() {
return this.environment.getProperty("local.server.port", Integer.class);
}
}
@Configuration(proxyBeanMethods = false)
@EnableAsync
class AppConfig {
@Bean
public Sampler testSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean("taskScheduler")
public Executor myScheduler() {
return Executors.newSingleThreadExecutor();
}
@Bean
public Executor poolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.initialize();
return executor;
}
@Bean
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.initialize();
return executor;
}
@Bean
public ScheduledThreadPoolExecutor scheduledThreadPoolExecutor() {
return new ScheduledThreadPoolExecutor(10);
}
}
@Component
class AsyncTask {
private static final Log log = LogFactory.getLog(AsyncTask.class);
@Autowired
Tracer tracer;
@Autowired
@Qualifier("poolTaskExecutor")
Executor executor;
@Autowired
@Qualifier("taskScheduler")
Executor taskScheduler;
@Autowired
BeanFactory beanFactory;
@Autowired
ThreadPoolTaskScheduler threadPoolTaskScheduler;
@Autowired
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
private AtomicReference<Span> span = new AtomicReference<>();
@Async("poolTaskExecutor")
public void runWithPool() {
log.info("This task is running with a pool.");
this.span.set(this.tracer.currentSpan());
}
@Async
public void runWithoutPool() {
log.info("This task is running without a pool.");
this.span.set(this.tracer.currentSpan());
}
public Span completableFutures() throws ExecutionException, InterruptedException {
log.info("This task is running with completable future");
CompletableFuture<Span> span1 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("First completable future");
return AsyncTask.this.tracer.currentSpan();
}, AsyncTask.this.executor);
CompletableFuture<Span> span2 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("Second completable future");
return AsyncTask.this.tracer.currentSpan();
}, AsyncTask.this.executor);
CompletableFuture<Span> response = CompletableFuture.allOf(span1, span2).thenApply(ignoredVoid -> {
AsyncTask.log.info("Third completable future");
Span joinedSpan1 = span1.join();
Span joinedSpan2 = span2.join();
then(joinedSpan2).isNotNull();
then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId());
AsyncTask.log.info("TraceIds are correct");
return joinedSpan2;
});
this.span.set(response.get());
return this.span.get();
}
public Span taskScheduler() throws ExecutionException, InterruptedException {
log.info("This task is running with completable future");
CompletableFuture<Span> span1 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("First completable future");
return AsyncTask.this.tracer.currentSpan();
}, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler));
CompletableFuture<Span> span2 = CompletableFuture.supplyAsync(() -> {
AsyncTask.log.info("Second completable future");
return AsyncTask.this.tracer.currentSpan();
}, new LazyTraceExecutor(AsyncTask.this.beanFactory, AsyncTask.this.taskScheduler));
CompletableFuture<Span> response = CompletableFuture.allOf(span1, span2).thenApply(ignoredVoid -> {
AsyncTask.log.info("Third completable future");
Span joinedSpan1 = span1.join();
Span joinedSpan2 = span2.join();
then(joinedSpan2).isNotNull();
then(joinedSpan1.context().traceId()).isEqualTo(joinedSpan2.context().traceId());
AsyncTask.log.info("TraceIds are correct");
return joinedSpan2;
});
this.span.set(response.get());
return this.span.get();
}
public Span scheduledThreadPoolExecutor() throws ExecutionException, InterruptedException {
log.info("This task is running with ScheduledThreadPoolExecutor");
this.scheduledThreadPoolExecutor.submit(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}).get();
return this.span.get();
}
public Span threadPoolTaskSchedulerSubmit() throws ExecutionException, InterruptedException {
log.info("This task is running with ThreadPoolTaskScheduler");
this.threadPoolTaskScheduler.submit(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}).get();
return this.span.get();
}
public Span threadPoolTaskSchedulerSchedule() throws ExecutionException, InterruptedException {
log.info("This task is running with ThreadPoolTaskScheduler");
this.threadPoolTaskScheduler.schedule(() -> {
log.info("Hello from runnable");
AsyncTask.this.span.set(AsyncTask.this.tracer.currentSpan());
}, new Date()).get();
return this.span.get();
}
public AtomicReference<Span> getSpan() {
return this.span;
}
}
@SpringBootApplication(exclude = SpringDataWebAutoConfiguration.class)
@RestController
class Application {
private static final Log log = LogFactory.getLog(Application.class);
@Autowired
AsyncTask asyncTask;
@Autowired
Tracer tracer;
@RequestMapping("/with_pool")
public String withPool() {
log.info("Executing with pool.");
this.asyncTask.runWithPool();
return this.tracer.currentSpan().context().traceIdString();
}
@RequestMapping("/without_pool")
public String withoutPool() {
log.info("Executing without pool.");
this.asyncTask.runWithoutPool();
return this.tracer.currentSpan().context().traceIdString();
}
@RequestMapping("/completable")
public String completable() throws ExecutionException, InterruptedException {
log.info("Executing completable");
return this.asyncTask.completableFutures().context().traceIdString();
}
@RequestMapping("/taskScheduler")
public String taskScheduler() throws ExecutionException, InterruptedException {
log.info("Executing completable via task scheduler");
return this.asyncTask.taskScheduler().context().traceIdString();
}
@RequestMapping("/threadPoolTaskScheduler_submit")
public String threadPoolTaskSchedulerSubmit() throws ExecutionException, InterruptedException {
log.info("Executing completable via ThreadPoolTaskScheduler");
return this.asyncTask.threadPoolTaskSchedulerSubmit().context().traceIdString();
}
@RequestMapping("/threadPoolTaskScheduler_schedule")
public String threadPoolTaskSchedulerSchedule() throws ExecutionException, InterruptedException {
log.info("Executing completable via ThreadPoolTaskScheduler");
return this.asyncTask.threadPoolTaskSchedulerSchedule().context().traceIdString();
}
@RequestMapping("/scheduledThreadPoolExecutor")
public String scheduledThreadPoolExecutor() throws ExecutionException, InterruptedException {
log.info("Executing completable via ScheduledThreadPoolExecutor");
return this.asyncTask.scheduledThreadPoolExecutor().context().traceIdString();
}
/**
* Related to issue #445.
* @return service bean
*/
@Bean
public MyService executorService() {
return new MyService() {
@Override
public void execute(Runnable command) {
}
};
}
interface MyService extends Executor {
}
}

View File

@@ -1,143 +1,143 @@
/*
* Copyright 2013-2021 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.async.issues.issue546;
import brave.Tracing;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(classes = Issue546TestsApp.class, properties = { "server.port=0" },
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Issue546Tests {
@Autowired
Environment environment;
@Test
public void should_pass_tracing_info_when_using_callbacks() {
new RestTemplate().getForObject("http://localhost:" + port() + "/trace-async-rest-template", String.class);
}
private int port() {
return this.environment.getProperty("local.server.port", Integer.class);
}
}
@SpringBootApplication
class Issue546TestsApp {
@Bean
AsyncRestTemplate asyncRestTemplate() {
return new AsyncRestTemplate();
}
}
@RestController
class Controller {
private static final Log log = LogFactory.getLog(Controller.class);
private final AsyncRestTemplate traceAsyncRestTemplate;
private final Tracing tracer;
@Value("${server.port}")
private String port;
Controller(AsyncRestTemplate traceAsyncRestTemplate, Tracing tracer) {
this.traceAsyncRestTemplate = traceAsyncRestTemplate;
this.tracer = tracer;
}
@RequestMapping("/bean")
public HogeBean bean() {
log.info("(/bean) I got a request!");
return new HogeBean("test", 18);
}
@RequestMapping("/trace-async-rest-template")
public void asyncTest(@RequestParam(required = false) boolean isSleep) throws InterruptedException {
log.info("(/trace-async-rest-template) I got a request!");
final long traceId = this.tracer.tracer().currentSpan().context().traceId();
ListenableFuture<ResponseEntity<HogeBean>> res = this.traceAsyncRestTemplate
.getForEntity("http://localhost:" + this.port + "/bean", HogeBean.class);
if (isSleep) {
Thread.sleep(1000);
}
res.addCallback(success -> {
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
log.info("(/trace-async-rest-template) success");
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
}, failure -> {
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
log.error("(/trace-async-rest-template) failure", failure);
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
});
}
}
class HogeBean {
private String name;
private int age;
HogeBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
/*
* Copyright 2013-2021 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.async.issues.issue546;
import brave.Tracing;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@SpringBootTest(classes = Issue546TestsApp.class, properties = { "server.port=0" },
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Issue546Tests {
@Autowired
Environment environment;
@Test
public void should_pass_tracing_info_when_using_callbacks() {
new RestTemplate().getForObject("http://localhost:" + port() + "/trace-async-rest-template", String.class);
}
private int port() {
return this.environment.getProperty("local.server.port", Integer.class);
}
}
@SpringBootApplication
class Issue546TestsApp {
@Bean
AsyncRestTemplate asyncRestTemplate() {
return new AsyncRestTemplate();
}
}
@RestController
class Controller {
private static final Log log = LogFactory.getLog(Controller.class);
private final AsyncRestTemplate traceAsyncRestTemplate;
private final Tracing tracer;
@Value("${server.port}")
private String port;
Controller(AsyncRestTemplate traceAsyncRestTemplate, Tracing tracer) {
this.traceAsyncRestTemplate = traceAsyncRestTemplate;
this.tracer = tracer;
}
@RequestMapping("/bean")
public HogeBean bean() {
log.info("(/bean) I got a request!");
return new HogeBean("test", 18);
}
@RequestMapping("/trace-async-rest-template")
public void asyncTest(@RequestParam(required = false) boolean isSleep) throws InterruptedException {
log.info("(/trace-async-rest-template) I got a request!");
final long traceId = this.tracer.tracer().currentSpan().context().traceId();
ListenableFuture<ResponseEntity<HogeBean>> res = this.traceAsyncRestTemplate
.getForEntity("http://localhost:" + this.port + "/bean", HogeBean.class);
if (isSleep) {
Thread.sleep(1000);
}
res.addCallback(success -> {
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
log.info("(/trace-async-rest-template) success");
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
}, failure -> {
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
log.error("(/trace-async-rest-template) failure", failure);
then(Controller.this.tracer.tracer().currentSpan().context().traceId()).isEqualTo(traceId);
});
}
}
class HogeBean {
private String name;
private int age;
HogeBean(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}

View File

@@ -1,57 +1,57 @@
/*
* Copyright 2013-2021 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.baggage;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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 = SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(classes = BaggageEntryTagSpanHandlerTest.Config.class)
public class BaggageEntryTagSpanHandlerTest
extends org.springframework.cloud.sleuth.baggage.BaggageEntryTagSpanHandlerTest {
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler, Environment environment) {
return new BraveTestSpanHandler(testSpanHandler);
}
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
brave.test.TestSpanHandler braveTestSpanHandler() {
return new brave.test.TestSpanHandler();
}
}
}
/*
* Copyright 2013-2021 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.baggage;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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 = SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(classes = BaggageEntryTagSpanHandlerTest.Config.class)
public class BaggageEntryTagSpanHandlerTest
extends org.springframework.cloud.sleuth.baggage.BaggageEntryTagSpanHandlerTest {
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean
TestSpanHandler testSpanHandlerSupplier(brave.test.TestSpanHandler testSpanHandler, Environment environment) {
return new BraveTestSpanHandler(testSpanHandler);
}
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
brave.test.TestSpanHandler braveTestSpanHandler() {
return new brave.test.TestSpanHandler();
}
}
}

View File

@@ -1,101 +1,101 @@
/*
* Copyright 2013-2021 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.baggage;
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.Span;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
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;
import org.springframework.test.context.ContextConfiguration;
import static java.util.Arrays.asList;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ContextConfiguration(classes = MultipleHopsIntegrationTests.Config.class)
public class MultipleHopsIntegrationTests
extends org.springframework.cloud.sleuth.baggage.multiple.MultipleHopsIntegrationTests {
static final BaggageField REQUEST_ID = BaggageField.create("x-vcap-request-id");
static final BaggageField COUNTRY_CODE = BaggageField.create("country-code");
static final BaggageField CASE_INSENSITIVE_ID = BaggageField.create("foo-id");
static final BaggageField NOT_PROPAGATED_HEADER = BaggageField.create("baz-id");
@Override
protected void assertSpanNames() {
then(this.spans).extracting(FinishedSpan::getName).containsAll(asList("GET /greeting", "send"));
}
@Override
protected void assertBaggage(Span initialSpan) {
// set with baggage api
then(this.application.allSpans()).as("All have request ID")
.allMatch(span -> "f4308d05-2228-4468-80f6-92a8377ba193"
.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))
// it propagates only and all the `spring.sleuth.baggage.remote-fields` in
// case insensitive way
.allMatch(span -> "FO".equals(COUNTRY_CODE.getValue(BraveAccessor.traceContext(span.context()))))
.allMatch(span -> "123"
.equalsIgnoreCase(CASE_INSENSITIVE_ID.getValue(BraveAccessor.traceContext(span.context()))))
.allMatch(span -> NOT_PROPAGATED_HEADER.getValue(BraveAccessor.traceContext(span.context())) == null);
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(
exclude = { MongoAutoConfiguration.class, QuartzAutoConfiguration.class, JmxAutoConfiguration.class })
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();
}
@Bean
BaggagePropagationConfig notInProperties() {
return BaggagePropagationConfig.SingleBaggageField.remote(BaggageField.create("bar"));
}
}
}
/*
* Copyright 2013-2021 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.baggage;
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.Span;
import org.springframework.cloud.sleuth.brave.BraveTestSpanHandler;
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;
import org.springframework.test.context.ContextConfiguration;
import static java.util.Arrays.asList;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@SpringBootTest(webEnvironment = RANDOM_PORT)
@ContextConfiguration(classes = MultipleHopsIntegrationTests.Config.class)
public class MultipleHopsIntegrationTests
extends org.springframework.cloud.sleuth.baggage.multiple.MultipleHopsIntegrationTests {
static final BaggageField REQUEST_ID = BaggageField.create("x-vcap-request-id");
static final BaggageField COUNTRY_CODE = BaggageField.create("country-code");
static final BaggageField CASE_INSENSITIVE_ID = BaggageField.create("foo-id");
static final BaggageField NOT_PROPAGATED_HEADER = BaggageField.create("baz-id");
@Override
protected void assertSpanNames() {
then(this.spans).extracting(FinishedSpan::getName).containsAll(asList("GET /greeting", "send"));
}
@Override
protected void assertBaggage(Span initialSpan) {
// set with baggage api
then(this.application.allSpans()).as("All have request ID")
.allMatch(span -> "f4308d05-2228-4468-80f6-92a8377ba193"
.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))
// it propagates only and all the `spring.sleuth.baggage.remote-fields` in
// case insensitive way
.allMatch(span -> "FO".equals(COUNTRY_CODE.getValue(BraveAccessor.traceContext(span.context()))))
.allMatch(span -> "123"
.equalsIgnoreCase(CASE_INSENSITIVE_ID.getValue(BraveAccessor.traceContext(span.context()))))
.allMatch(span -> NOT_PROPAGATED_HEADER.getValue(BraveAccessor.traceContext(span.context())) == null);
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration(
exclude = { MongoAutoConfiguration.class, QuartzAutoConfiguration.class, JmxAutoConfiguration.class })
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();
}
@Bean
BaggagePropagationConfig notInProperties() {
return BaggagePropagationConfig.SingleBaggageField.remote(BaggageField.create("bar"));
}
}
}

View File

@@ -1,55 +1,55 @@
/*
* Copyright 2013-2021 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.baggage;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
/**
* @author Taras Danylchuk
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(classes = W3CBaggageTests.Config.class)
public class W3CBaggageTests extends org.springframework.cloud.sleuth.baggage.W3CBaggageTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.baggage;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
/**
* @author Taras Danylchuk
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
@ContextConfiguration(classes = W3CBaggageTests.Config.class)
public class W3CBaggageTests extends org.springframework.cloud.sleuth.baggage.W3CBaggageTests {
@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

@@ -1,60 +1,60 @@
/*
* Copyright 2013-2021 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.circuitbreaker;
import brave.sampler.Sampler;
import org.assertj.core.api.BDDAssertions;
import org.springframework.boot.test.context.SpringBootTest;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = ReactiveCircuitBreakerIntegrationTests.Config.class)
public class ReactiveCircuitBreakerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.ReactiveCircuitBreakerIntegrationTests {
@Override
public void assertException(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom");
}
@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();
}
}
}
/*
* Copyright 2013-2021 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.circuitbreaker;
import brave.sampler.Sampler;
import org.assertj.core.api.BDDAssertions;
import org.springframework.boot.test.context.SpringBootTest;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = ReactiveCircuitBreakerIntegrationTests.Config.class)
public class ReactiveCircuitBreakerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.ReactiveCircuitBreakerIntegrationTests {
@Override
public void assertException(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom");
}
@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

@@ -1,43 +1,43 @@
/*
* Copyright 2013-2021 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.circuitbreaker;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class ReactiveCircuitBreakerTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.ReactiveCircuitBreakerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
public void additionalAssertions(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom2");
}
}
/*
* Copyright 2013-2021 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.circuitbreaker;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class ReactiveCircuitBreakerTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.ReactiveCircuitBreakerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
public void additionalAssertions(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom2");
}
}

View File

@@ -1,60 +1,60 @@
/*
* Copyright 2013-2021 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.circuitbreaker;
import brave.sampler.Sampler;
import org.assertj.core.api.BDDAssertions;
import org.springframework.boot.test.context.SpringBootTest;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = CircuitBreakerIntegrationTests.Config.class)
public class CircuitBreakerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.CircuitBreakerIntegrationTests {
@Override
public void assertException(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom");
}
@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();
}
}
}
/*
* Copyright 2013-2021 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.circuitbreaker;
import brave.sampler.Sampler;
import org.assertj.core.api.BDDAssertions;
import org.springframework.boot.test.context.SpringBootTest;
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;
import org.springframework.test.context.ContextConfiguration;
@SpringBootTest
@ContextConfiguration(classes = CircuitBreakerIntegrationTests.Config.class)
public class CircuitBreakerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.CircuitBreakerIntegrationTests {
@Override
public void assertException(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom");
}
@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

@@ -1,43 +1,43 @@
/*
* Copyright 2013-2021 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.circuitbreaker;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class CircuitBreakerTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.CircuitBreakerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
public void additionalAssertions(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom2");
}
}
/*
* Copyright 2013-2021 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.circuitbreaker;
import org.assertj.core.api.BDDAssertions;
import org.springframework.cloud.sleuth.brave.BraveTestTracing;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestTracingAware;
public class CircuitBreakerTests
extends org.springframework.cloud.sleuth.instrument.circuitbreaker.CircuitBreakerTests {
BraveTestTracing testTracing;
@Override
public TestTracingAware tracerTest() {
if (this.testTracing == null) {
this.testTracing = new BraveTestTracing();
}
return this.testTracing;
}
@Override
public void additionalAssertions(FinishedSpan finishedSpan) {
BDDAssertions.then(finishedSpan.getTags().get("error")).contains("boom2");
}
}

View File

@@ -1,53 +1,53 @@
/*
* Copyright 2013-2021 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.config;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = ConfigServerIntegrationTests.Config.class)
public class ConfigServerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.config.ConfigServerIntegrationTests {
@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();
}
}
}
/*
* Copyright 2013-2021 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.config;
import brave.sampler.Sampler;
import org.springframework.boot.test.context.SpringBootTest;
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.test.context.ContextConfiguration;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = ConfigServerIntegrationTests.Config.class)
public class ConfigServerIntegrationTests
extends org.springframework.cloud.sleuth.instrument.config.ConfigServerIntegrationTests {
@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

@@ -1,376 +1,376 @@
/*
* Copyright 2013-2021 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.rsocket;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import io.rsocket.frame.FrameType;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.context.ContextView;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
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.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketRequester.Builder;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.stereotype.Controller;
import org.springframework.util.MimeType;
import static org.assertj.core.api.BDDAssertions.then;
public abstract class TraceRSocketTests {
public static final String EXPECTED_TRACE_ID = "b919095138aa4c6e";
@Test
public void should_instrument_responder() throws Exception {
// setup
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyConfig.class, testConfiguration())
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.rsocket.server.transport=websocket",
"spring.rsocket.server.mapping-path=/rsocket", "spring.jmx.enabled=false",
"spring.application.name=TraceRSocketTests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
final TestSpanHandler spans = context.getBean(TestSpanHandler.class);
final int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
final TestController controller2 = context.getBean(TestController.class);
final RSocketStrategies strategies = context.getBean(RSocketStrategies.class);
final Builder rsocketRequesterBuilder = RSocketRequester.builder().rsocketStrategies(strategies);
final RSocketRequester rSocketRequester = rsocketRequesterBuilder
.websocket(URI.create("ws://localhost:" + port + "/rsocket"));
// REQUEST FNF
whenRequestFnFIsSent(rSocketRequester, "api.c2.fnf").block();
FrameType receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.fnf", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST RESPONSE
whenRequestResponseIsSent(rSocketRequester, "api.c2.rr").block();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rr", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST STREAM
whenRequestStreamIsSent(rSocketRequester, "api.c2.rs").blockLast();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rs", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST CHANNEL
whenRequestChannelIsSent(rSocketRequester, "api.c2.rc").blockLast();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rc", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST FNF
whenNonSampledRequestFnfIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST RESPONSE
whenNonSampledRequestResponseIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST STREAM
whenNonSampledRequestStreamIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST CHANNEL
whenNonSampledRequestChannelIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// cleanup
context.close();
}
protected String expectedTraceId() {
return EXPECTED_TRACE_ID;
}
protected String expectedSpanId() {
return EXPECTED_TRACE_ID;
}
@Test
public void should_instrument_requester_and_responder() throws Exception {
// setup
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyConfig.class, testConfiguration())
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.rsocket.server.transport=websocket",
"spring.rsocket.server.mapping-path=/rsocket", "spring.jmx.enabled=false",
"spring.application.name=TraceRSocketTests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
final org.springframework.cloud.sleuth.Tracer tracer = context
.getBean(org.springframework.cloud.sleuth.Tracer.class);
final TestSpanHandler spans = context.getBean(TestSpanHandler.class);
final int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
final TestController controller2 = context.getBean(TestController.class);
final Builder rsocketRequesterBuilder = context.getBean(Builder.class);
final RSocketRequester rSocketRequester = rsocketRequesterBuilder
.websocket(URI.create("ws://localhost:" + port + "/rsocket"));
// REQUEST FNF
final org.springframework.cloud.sleuth.Span nextSpanFnf = tracer.nextSpan().start();
whenRequestFnFIsSent(rSocketRequester, "api.c2.fnf")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanFnf.context()))
.doFinally(signalType -> nextSpanFnf.end()).block();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanFnf.context().traceId());
spans.clear();
controller2.reset();
// REQUEST RESPONSE
final org.springframework.cloud.sleuth.Span nextSpanRR = tracer.nextSpan().start();
whenRequestResponseIsSent(rSocketRequester, "api.c2.rr")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRR.context()))
.doFinally(signalType -> nextSpanRR.end()).block();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRR.context().traceId());
spans.clear();
controller2.reset();
// REQUEST STREAM
final org.springframework.cloud.sleuth.Span nextSpanRS = tracer.nextSpan().start();
whenRequestStreamIsSent(rSocketRequester, "api.c2.rs")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRS.context()))
.doFinally(signalType -> nextSpanRS.end()).blockLast();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRS.context().traceId());
spans.clear();
controller2.reset();
// REQUEST CHANNEL
final org.springframework.cloud.sleuth.Span nextSpanRC = tracer.nextSpan().start();
whenRequestChannelIsSent(rSocketRequester, "api.c2.rc")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRC.context()))
.doFinally(signalType -> nextSpanRC.end()).blockLast();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRC.context().traceId());
spans.clear();
controller2.reset();
// cleanup
context.close();
}
protected abstract Class testConfiguration();
private void thenSpanWasReportedWithTags(TestSpanHandler spans, String path, FrameType frameType) {
then(spans).hasSize(1);
// TODO: Preferred option would be : [api.c2.{name}]
FinishedSpan span = spans.get(0);
then(span.getName()).isEqualTo(frameType.name() + " " + path);
then(span.getTags()).containsEntry("messaging.controller.class",
"org.springframework.cloud.sleuth.instrument.rsocket.TraceRSocketTests$TestController");
then(span.getTags()).containsKey("messaging.controller.method");
}
private Mono<Void> whenRequestFnFIsSent(RSocketRequester requester, String path) {
return requester.route(path).send();
}
private Mono<String> whenRequestResponseIsSent(RSocketRequester requester, String path) {
return requester.route(path).retrieveMono(String.class);
}
private Flux<String> whenRequestStreamIsSent(RSocketRequester requester, String path) {
return requester.route(path).retrieveFlux(String.class);
}
private Flux<String> whenRequestChannelIsSent(RSocketRequester requester, String path) {
return requester.route(path).data(Flux.fromArray(new String[] { "test1", "test2" })).retrieveFlux(String.class);
}
private void whenNonSampledRequestFnfIsSent(RSocketRequester requester) {
requester.route("api.c2.fnf").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).send().block();
}
private void whenNonSampledRequestResponseIsSent(RSocketRequester requester) {
requester.route("api.c2.rr").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).retrieveMono(String.class).block();
}
private void whenNonSampledRequestStreamIsSent(RSocketRequester requester) {
requester.route("api.c2.rs").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).retrieveFlux(String.class).blockLast();
}
private void whenNonSampledRequestChannelIsSent(RSocketRequester requester) {
requester.route("api.c2.rc").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).data(Flux.fromArray(new String[] { "test1", "test2" })).retrieveFlux(String.class).blockLast();
}
private void thenNoSpanWasReported(TestSpanHandler spans, TestController controller2, String expectedTraceId) {
// then(spans).isEmpty(); // FIXME: does not work for request case
then(controller2.getSpan()).isNotNull();
then(controller2.getSpan().context().traceId()).isEqualTo(expectedTraceId);
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class MyConfig {
@Bean
TestController controller(Tracer tracer) {
return new TestController(tracer);
}
}
@Controller
@MessageMapping("api.c2")
static class TestController {
final Tracer tracer;
Span span;
ContextView interceptedContext;
BlockingQueue<FrameType> receivedFrames = new LinkedBlockingDeque<>();
TestController(Tracer tracer) {
this.tracer = tracer;
}
BlockingQueue<FrameType> getReceivedFrames() {
return this.receivedFrames;
}
Span getSpan() {
return this.span;
}
void reset() {
this.span = null;
}
@MessageMapping("fnf")
Mono<Void> testFnf() {
this.span = this.tracer.currentSpan();
return Mono.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_FNF);
return Mono.empty();
});
}
@MessageMapping("rr")
Mono<String> testRR() {
this.span = this.tracer.currentSpan();
return Mono.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_RESPONSE);
return Mono.just("response");
});
}
@MessageMapping("rs")
Flux<String> testRS() {
this.span = this.tracer.currentSpan();
return Flux.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_STREAM);
return Flux.just("stream");
});
}
@MessageMapping("rc")
Flux<String> testRC(@Payload Flux<String> inbound) {
this.span = this.tracer.currentSpan();
return Flux.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_CHANNEL);
return inbound;
});
}
}
}
/*
* Copyright 2013-2021 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.rsocket;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import io.rsocket.frame.FrameType;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.context.ContextView;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.TraceContext;
import org.springframework.cloud.sleuth.Tracer;
import org.springframework.cloud.sleuth.exporter.FinishedSpan;
import org.springframework.cloud.sleuth.test.TestSpanHandler;
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.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.messaging.rsocket.RSocketRequester.Builder;
import org.springframework.messaging.rsocket.RSocketStrategies;
import org.springframework.stereotype.Controller;
import org.springframework.util.MimeType;
import static org.assertj.core.api.BDDAssertions.then;
public abstract class TraceRSocketTests {
public static final String EXPECTED_TRACE_ID = "b919095138aa4c6e";
@Test
public void should_instrument_responder() throws Exception {
// setup
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyConfig.class, testConfiguration())
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.rsocket.server.transport=websocket",
"spring.rsocket.server.mapping-path=/rsocket", "spring.jmx.enabled=false",
"spring.application.name=TraceRSocketTests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
final TestSpanHandler spans = context.getBean(TestSpanHandler.class);
final int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
final TestController controller2 = context.getBean(TestController.class);
final RSocketStrategies strategies = context.getBean(RSocketStrategies.class);
final Builder rsocketRequesterBuilder = RSocketRequester.builder().rsocketStrategies(strategies);
final RSocketRequester rSocketRequester = rsocketRequesterBuilder
.websocket(URI.create("ws://localhost:" + port + "/rsocket"));
// REQUEST FNF
whenRequestFnFIsSent(rSocketRequester, "api.c2.fnf").block();
FrameType receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.fnf", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST RESPONSE
whenRequestResponseIsSent(rSocketRequester, "api.c2.rr").block();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rr", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST STREAM
whenRequestStreamIsSent(rSocketRequester, "api.c2.rs").blockLast();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rs", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST CHANNEL
whenRequestChannelIsSent(rSocketRequester, "api.c2.rc").blockLast();
receivedFrame = controller2.getReceivedFrames().take();
thenSpanWasReportedWithTags(spans, "api.c2.rc", receivedFrame);
spans.clear();
controller2.reset();
// REQUEST FNF
whenNonSampledRequestFnfIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST RESPONSE
whenNonSampledRequestResponseIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST STREAM
whenNonSampledRequestStreamIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// REQUEST CHANNEL
whenNonSampledRequestChannelIsSent(rSocketRequester);
controller2.getReceivedFrames().take();
// then
thenNoSpanWasReported(spans, controller2, expectedTraceId());
spans.clear();
controller2.reset();
// cleanup
context.close();
}
protected String expectedTraceId() {
return EXPECTED_TRACE_ID;
}
protected String expectedSpanId() {
return EXPECTED_TRACE_ID;
}
@Test
public void should_instrument_requester_and_responder() throws Exception {
// setup
ConfigurableApplicationContext context = new SpringApplicationBuilder(MyConfig.class, testConfiguration())
.web(WebApplicationType.REACTIVE)
.properties("server.port=0", "spring.rsocket.server.transport=websocket",
"spring.rsocket.server.mapping-path=/rsocket", "spring.jmx.enabled=false",
"spring.application.name=TraceRSocketTests", "security.basic.enabled=false",
"management.security.enabled=false")
.run();
final org.springframework.cloud.sleuth.Tracer tracer = context
.getBean(org.springframework.cloud.sleuth.Tracer.class);
final TestSpanHandler spans = context.getBean(TestSpanHandler.class);
final int port = context.getBean(Environment.class).getProperty("local.server.port", Integer.class);
final TestController controller2 = context.getBean(TestController.class);
final Builder rsocketRequesterBuilder = context.getBean(Builder.class);
final RSocketRequester rSocketRequester = rsocketRequesterBuilder
.websocket(URI.create("ws://localhost:" + port + "/rsocket"));
// REQUEST FNF
final org.springframework.cloud.sleuth.Span nextSpanFnf = tracer.nextSpan().start();
whenRequestFnFIsSent(rSocketRequester, "api.c2.fnf")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanFnf.context()))
.doFinally(signalType -> nextSpanFnf.end()).block();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanFnf.context().traceId());
spans.clear();
controller2.reset();
// REQUEST RESPONSE
final org.springframework.cloud.sleuth.Span nextSpanRR = tracer.nextSpan().start();
whenRequestResponseIsSent(rSocketRequester, "api.c2.rr")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRR.context()))
.doFinally(signalType -> nextSpanRR.end()).block();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRR.context().traceId());
spans.clear();
controller2.reset();
// REQUEST STREAM
final org.springframework.cloud.sleuth.Span nextSpanRS = tracer.nextSpan().start();
whenRequestStreamIsSent(rSocketRequester, "api.c2.rs")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRS.context()))
.doFinally(signalType -> nextSpanRS.end()).blockLast();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRS.context().traceId());
spans.clear();
controller2.reset();
// REQUEST CHANNEL
final org.springframework.cloud.sleuth.Span nextSpanRC = tracer.nextSpan().start();
whenRequestChannelIsSent(rSocketRequester, "api.c2.rc")
.contextWrite(ctx -> ctx.put(TraceContext.class, nextSpanRC.context()))
.doFinally(signalType -> nextSpanRC.end()).blockLast();
controller2.getReceivedFrames().take();
thenNoSpanWasReported(spans, controller2, nextSpanRC.context().traceId());
spans.clear();
controller2.reset();
// cleanup
context.close();
}
protected abstract Class testConfiguration();
private void thenSpanWasReportedWithTags(TestSpanHandler spans, String path, FrameType frameType) {
then(spans).hasSize(1);
// TODO: Preferred option would be : [api.c2.{name}]
FinishedSpan span = spans.get(0);
then(span.getName()).isEqualTo(frameType.name() + " " + path);
then(span.getTags()).containsEntry("messaging.controller.class",
"org.springframework.cloud.sleuth.instrument.rsocket.TraceRSocketTests$TestController");
then(span.getTags()).containsKey("messaging.controller.method");
}
private Mono<Void> whenRequestFnFIsSent(RSocketRequester requester, String path) {
return requester.route(path).send();
}
private Mono<String> whenRequestResponseIsSent(RSocketRequester requester, String path) {
return requester.route(path).retrieveMono(String.class);
}
private Flux<String> whenRequestStreamIsSent(RSocketRequester requester, String path) {
return requester.route(path).retrieveFlux(String.class);
}
private Flux<String> whenRequestChannelIsSent(RSocketRequester requester, String path) {
return requester.route(path).data(Flux.fromArray(new String[] { "test1", "test2" })).retrieveFlux(String.class);
}
private void whenNonSampledRequestFnfIsSent(RSocketRequester requester) {
requester.route("api.c2.fnf").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).send().block();
}
private void whenNonSampledRequestResponseIsSent(RSocketRequester requester) {
requester.route("api.c2.rr").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).retrieveMono(String.class).block();
}
private void whenNonSampledRequestStreamIsSent(RSocketRequester requester) {
requester.route("api.c2.rs").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).retrieveFlux(String.class).blockLast();
}
private void whenNonSampledRequestChannelIsSent(RSocketRequester requester) {
requester.route("api.c2.rc").metadata(expectedTraceId() + "-" + expectedSpanId() + "-0", new MimeType("b3") {
@Override
public String toString() {
return "b3";
}
}).data(Flux.fromArray(new String[] { "test1", "test2" })).retrieveFlux(String.class).blockLast();
}
private void thenNoSpanWasReported(TestSpanHandler spans, TestController controller2, String expectedTraceId) {
// then(spans).isEmpty(); // FIXME: does not work for request case
then(controller2.getSpan()).isNotNull();
then(controller2.getSpan().context().traceId()).isEqualTo(expectedTraceId);
}
@Configuration(proxyBeanMethods = false)
@EnableAutoConfiguration
static class MyConfig {
@Bean
TestController controller(Tracer tracer) {
return new TestController(tracer);
}
}
@Controller
@MessageMapping("api.c2")
static class TestController {
final Tracer tracer;
Span span;
ContextView interceptedContext;
BlockingQueue<FrameType> receivedFrames = new LinkedBlockingDeque<>();
TestController(Tracer tracer) {
this.tracer = tracer;
}
BlockingQueue<FrameType> getReceivedFrames() {
return this.receivedFrames;
}
Span getSpan() {
return this.span;
}
void reset() {
this.span = null;
}
@MessageMapping("fnf")
Mono<Void> testFnf() {
this.span = this.tracer.currentSpan();
return Mono.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_FNF);
return Mono.empty();
});
}
@MessageMapping("rr")
Mono<String> testRR() {
this.span = this.tracer.currentSpan();
return Mono.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_RESPONSE);
return Mono.just("response");
});
}
@MessageMapping("rs")
Flux<String> testRS() {
this.span = this.tracer.currentSpan();
return Flux.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_STREAM);
return Flux.just("stream");
});
}
@MessageMapping("rc")
Flux<String> testRC(@Payload Flux<String> inbound) {
this.span = this.tracer.currentSpan();
return Flux.deferContextual(c -> {
interceptedContext = c;
receivedFrames.offer(FrameType.REQUEST_CHANNEL);
return inbound;
});
}
}
}