Removes modules in maintenance more.

Zuul, ribbon and hystrix
This commit is contained in:
Marcin Grzejszczak
2020-02-12 11:03:04 +01:00
parent 8f2823814f
commit 3813cf9dd4
80 changed files with 187 additions and 2952 deletions

View File

@@ -22,7 +22,7 @@
<name>Benchmarks</name>
<description>Benchmarks (JMH)</description>
<groupId>org.springframework.cloud</groupId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<artifactId>benchmarks</artifactId>
<properties>

View File

@@ -22,7 +22,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
</parent>
<artifactId>spring-cloud-sleuth-docs</artifactId>
<packaging>pom</packaging>

24
pom.xml
View File

@@ -21,7 +21,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Spring Cloud Sleuth</name>
<description>Spring Cloud Sleuth</description>
@@ -29,7 +29,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-build</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath/>
<!-- lookup parent from repository -->
</parent>
@@ -153,13 +153,6 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-dependencies</artifactId>
<version>${spring-cloud-aws.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-dependencies</artifactId>
@@ -250,16 +243,15 @@
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.testTarget>1.8</maven.compiler.testTarget>
<maven.compiler.testSource>1.8</maven.compiler.testSource>
<spring-cloud-build.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-build.version>
<spring-cloud-commons.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-gateway.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-gateway.version>
<spring-cloud-circuitbreaker.version>1.0.1.BUILD-SNAPSHOT</spring-cloud-circuitbreaker.version>
<spring-cloud-build.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-build.version>
<spring-cloud-commons.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-commons.version>
<spring-cloud-gateway.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-gateway.version>
<spring-cloud-circuitbreaker.version>2.0.0.BUILD-SNAPSHOT</spring-cloud-circuitbreaker.version>
<spring-cloud-stream.version>Horsham.SR1</spring-cloud-stream.version>
<spring-cloud-netflix.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-netflix.version>
<spring-cloud-openfeign.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-openfeign.version>
<spring-cloud-netflix.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-netflix.version>
<spring-cloud-openfeign.version>3.0.0.BUILD-SNAPSHOT</spring-cloud-openfeign.version>
<brave.version>5.9.3</brave.version>
<spring-security-boot-autoconfigure.version>2.1.7.RELEASE</spring-security-boot-autoconfigure.version>
<spring-cloud-aws.version>2.2.2.BUILD-SNAPSHOT</spring-cloud-aws.version>
<disable.nohttp.checks>false</disable.nohttp.checks>
<okhttp.version>3.14.6</okhttp.version>
<mockwebserver.version>3.14.6</mockwebserver.version>

View File

@@ -31,7 +31,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@@ -85,11 +85,6 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-messaging</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
@@ -105,17 +100,6 @@
<artifactId>spring-cloud-starter-openfeign</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
@@ -161,11 +145,6 @@
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
@@ -176,17 +155,6 @@
<artifactId>feign-form-spring</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.netflix.zuul</groupId>
<artifactId>zuul-core</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.reactivex</groupId>
<artifactId>rxjava</artifactId>
@@ -335,17 +303,6 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.netflix.archaius</groupId>
<artifactId>archaius-core</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver</artifactId>

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import brave.Tracing;
import com.netflix.hystrix.HystrixCommand;
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.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} that registers a custom Sleuth
* {@link com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy}.
*
* @author Marcin Grzejszczak
* @see SleuthHystrixConcurrencyStrategy
* @since 1.0.0
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(TraceAutoConfiguration.class)
@ConditionalOnClass(HystrixCommand.class)
@ConditionalOnBean(Tracing.class)
@ConditionalOnProperty(value = "spring.sleuth.hystrix.strategy.enabled",
matchIfMissing = true)
@EnableConfigurationProperties(SleuthHystrixConcurrencyStrategyProperties.class)
public class SleuthHystrixAutoConfiguration {
@Bean
SleuthHystrixConcurrencyStrategy sleuthHystrixConcurrencyStrategy(Tracing tracing,
SpanNamer spanNamer, SleuthHystrixConcurrencyStrategyProperties properties) {
return new SleuthHystrixConcurrencyStrategy(tracing, spanNamer,
properties.isPassthrough());
}
}

View File

@@ -1,164 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import brave.Tracing;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.sleuth.SpanNamer;
import org.springframework.cloud.sleuth.instrument.async.TraceCallable;
/**
* A {@link HystrixConcurrencyStrategy} that wraps a {@link Callable} in a
* {@link Callable} that either starts a new span or continues one if the tracing was
* already running before the command was executed.
*
* @author Marcin Grzejszczak
* @since 1.0.0
*/
public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private static final String HYSTRIX_COMPONENT = "hystrix";
private static final Log log = LogFactory
.getLog(SleuthHystrixConcurrencyStrategy.class);
private final Tracing tracing;
private final SpanNamer spanNamer;
private HystrixConcurrencyStrategy delegate;
private boolean passthrough;
public SleuthHystrixConcurrencyStrategy(Tracing tracing, SpanNamer spanNamer) {
this(tracing, spanNamer, false);
}
public SleuthHystrixConcurrencyStrategy(Tracing tracing, SpanNamer spanNamer,
boolean passthrough) {
this.tracing = tracing;
this.spanNamer = spanNamer;
this.passthrough = passthrough;
try {
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (this.delegate instanceof SleuthHystrixConcurrencyStrategy) {
// Welcome to singleton hell...
return;
}
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins
.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
.getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
.getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
.getPropertiesStrategy();
logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher,
propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance()
.registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
}
catch (Exception ex) {
log.error("Failed to register Sleuth Hystrix Concurrency Strategy", ex);
}
}
private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
HystrixMetricsPublisher metricsPublisher,
HystrixPropertiesStrategy propertiesStrategy) {
if (log.isDebugEnabled()) {
log.debug("Current Hystrix plugins configuration is ["
+ "concurrencyStrategy [" + this.delegate + "]," + "eventNotifier ["
+ eventNotifier + "]," + "metricPublisher [" + metricsPublisher + "],"
+ "propertiesStrategy [" + propertiesStrategy + "]," + "]");
log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
}
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
if (callable instanceof TraceCallable) {
return callable;
}
Callable<T> wrappedCallable = this.delegate != null
? this.delegate.wrapCallable(callable) : callable;
if (wrappedCallable instanceof TraceCallable) {
return wrappedCallable;
}
if (passthrough) {
return this.tracing.currentTraceContext().wrap(callable);
}
else {
return new TraceCallable<>(this.tracing, this.spanNamer, wrappedCallable,
HYSTRIX_COMPONENT);
}
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixProperty<Integer> corePoolSize,
HystrixProperty<Integer> maximumPoolSize,
HystrixProperty<Integer> keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize,
keepAliveTime, unit, workQueue);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
HystrixThreadPoolProperties threadPoolProperties) {
return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return this.delegate.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(
HystrixRequestVariableLifecycle<T> rv) {
return this.delegate.getRequestVariable(rv);
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Sleuth Hystrix settings.
*
* @author Daniel Albuquerque
*/
@ConfigurationProperties("spring.sleuth.hystrix.strategy")
public class SleuthHystrixConcurrencyStrategyProperties {
/**
* Enable custom HystrixConcurrencyStrategy that wraps all Callable instances into
* their Sleuth representative - the TraceCallable.
*/
private boolean enabled = true;
/**
* When enabled the tracing information is passed to the Hystrix execution threads but
* spans are not created for each execution.
*/
private boolean passthrough = false;
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isPassthrough() {
return passthrough;
}
public void setPassthrough(boolean passthrough) {
this.passthrough = passthrough;
}
}

View File

@@ -1,100 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracer;
import com.netflix.hystrix.HystrixCommand;
/**
* Abstraction over {@code HystrixCommand} that wraps command execution with Trace
* setting.
*
* @param <R> - return type of Hystrix Command
* @author Tomasz Nurkiewicz, 4financeIT
* @author Marcin Grzejszczak
* @author Spencer Gibb
* @since 1.0.0
* @see HystrixCommand
* @see Tracer
*/
public abstract class TraceCommand<R> extends HystrixCommand<R> {
private static final String COMMAND_KEY = "commandKey";
private static final String COMMAND_GROUP_KEY = "commandGroup";
private static final String THREAD_POOL_KEY = "threadPoolKey";
private static final String FALLBACK_METHOD_NAME_KEY = "fallbackMethodName";
private final Tracer tracer;
private final AtomicReference<Span> span;
protected TraceCommand(Tracer tracer, Setter setter) {
super(setter);
this.tracer = tracer;
this.span = new AtomicReference<>(this.tracer.nextSpan());
}
@Override
protected R run() throws Exception {
String commandKeyName = getCommandKey().name();
Span span = this.span.get().name(commandKeyName);
span.tag(COMMAND_KEY, commandKeyName);
span.tag(COMMAND_GROUP_KEY, getCommandGroup().name());
span.tag(THREAD_POOL_KEY, getThreadPoolKey().name());
Throwable throwable = null;
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) {
return doRun();
}
catch (Throwable t) {
throwable = t;
throw t;
}
finally {
if (throwable == null) {
span.finish();
this.span.set(null);
}
// else there will be fallback
}
}
public abstract R doRun() throws Exception;
@Override
protected R getFallback() {
Span span = this.span.get();
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span)) {
span.tag(FALLBACK_METHOD_NAME_KEY, getFallbackMethodName());
return doGetFallback();
}
finally {
span.finish();
this.span.set(null);
}
}
public R doGetFallback() {
return super.getFallback();
}
}

View File

@@ -18,7 +18,6 @@ package org.springframework.cloud.sleuth.instrument.messaging;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import brave.Span;
@@ -29,7 +28,6 @@ import brave.kafka.clients.KafkaTracing;
import brave.messaging.MessagingRequest;
import brave.messaging.MessagingTracing;
import brave.messaging.MessagingTracingCustomizer;
import brave.propagation.Propagation.Getter;
import brave.sampler.SamplerFunction;
import brave.spring.rabbit.SpringRabbitTracing;
import org.aopalliance.intercept.MethodInterceptor;
@@ -58,8 +56,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.aws.messaging.config.QueueMessageHandlerFactory;
import org.springframework.cloud.aws.messaging.listener.QueueMessageHandler;
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -73,11 +69,6 @@ import org.springframework.kafka.listener.MessageListener;
import org.springframework.kafka.listener.MessageListenerContainer;
import org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter;
import org.springframework.lang.Nullable;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
/**
@@ -215,28 +206,6 @@ public class TraceMessagingAutoConfiguration {
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.sleuth.messaging.sqs.enabled",
matchIfMissing = true)
@ConditionalOnClass(QueueMessageHandler.class)
protected static class SleuthSqsConfiguration {
@Bean
TracingMethodMessageHandlerAdapter tracingMethodMessageHandlerAdapter(
MessagingTracing messagingTracing,
Getter<MessageHeaderAccessor, String> traceMessagePropagationGetter) {
return new TracingMethodMessageHandlerAdapter(messagingTracing,
traceMessagePropagationGetter);
}
@Bean
QueueMessageHandlerFactory sqsQueueMessageHandlerFactory(
TracingMethodMessageHandlerAdapter tracingMethodMessageHandlerAdapter) {
return new SqsQueueMessageHandlerFactory(tracingMethodMessageHandlerAdapter);
}
}
}
class SleuthRabbitBeanPostProcessor implements BeanPostProcessor {
@@ -440,50 +409,3 @@ class TracingJmsBeanPostProcessor implements BeanPostProcessor {
}
}
class SqsQueueMessageHandlerFactory extends QueueMessageHandlerFactory {
private TracingMethodMessageHandlerAdapter handlerAdapter;
SqsQueueMessageHandlerFactory(TracingMethodMessageHandlerAdapter handlerAdapter) {
this.handlerAdapter = handlerAdapter;
}
@Override
public QueueMessageHandler createQueueMessageHandler() {
if (CollectionUtils.isEmpty(getMessageConverters())) {
return new SqsQueueMessageHandler(handlerAdapter, Collections.emptyList());
}
return new SqsQueueMessageHandler(handlerAdapter, getMessageConverters());
}
}
class SqsQueueMessageHandler extends QueueMessageHandler {
// copied from QueueMessageHandler
static final String LOGICAL_RESOURCE_ID = "LogicalResourceId";
private TracingMethodMessageHandlerAdapter handlerAdapter;
SqsQueueMessageHandler(TracingMethodMessageHandlerAdapter handlerAdapter,
List<MessageConverter> messageConverters) {
super(messageConverters);
this.handlerAdapter = handlerAdapter;
}
@Override
public void handleMessage(Message<?> message) throws MessagingException {
handlerAdapter.wrapMethodMessageHandler(message, super::handleMessage,
this::messageSpanTagger);
}
private void messageSpanTagger(Span span, Message<?> message) {
span.remoteServiceName("sqs");
if (message.getHeaders().get(LOGICAL_RESOURCE_ID) != null) {
span.tag("sqs.queue_url",
message.getHeaders().get(LOGICAL_RESOURCE_ID).toString());
}
}
}

View File

@@ -32,15 +32,12 @@ import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.MessageHeaderAccessor;
import static brave.Span.Kind.CONSUMER;
import static org.springframework.cloud.sleuth.instrument.messaging.SqsQueueMessageHandler.LOGICAL_RESOURCE_ID;
/**
* Adds tracing extraction to an instance of
* {@link org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler}
* in a reusable way. When sub-classing a provider specific class of that type you would
* wrap the <pre>super.handleMessage(...)</pre> call with a call to this. See
* {@link org.springframework.cloud.sleuth.instrument.messaging.SqsQueueMessageHandler}
* for an example.
* wrap the <pre>super.handleMessage(...)</pre> call with a call to this.
*
* This implementation also allows for supplying a {@link java.util.function.BiConsumer}
* instance that can be used to add queue specific tags and modifications to the span.
@@ -117,6 +114,8 @@ class TracingMethodMessageHandlerAdapter {
final class MessageConsumerRequest extends ConsumerRequest {
static final String LOGICAL_RESOURCE_ID = "LogicalResourceId";
static final Getter<MessageConsumerRequest, String> GETTER = new Getter<MessageConsumerRequest, String>() {
@Override
public String get(MessageConsumerRequest request, String name) {

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2013-2019 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.web.client.feign;
import brave.http.HttpTracing;
import feign.Client;
import feign.Feign;
import feign.Retryer;
import feign.hystrix.HystrixFeign;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
/**
* Contains {@link Feign.Builder} implementation that delegates execution
* {@link HystrixFeign} with tracing components that close spans upon completion of
* request processing.
*
* @author Marcin Grzejszczak
* @since 1.0.4
*/
final class SleuthHystrixFeignBuilder {
private SleuthHystrixFeignBuilder() {
}
static Feign.Builder builder(BeanFactory beanFactory) {
return HystrixFeign.builder().retryer(Retryer.NEVER_RETRY)
.client(client(beanFactory));
}
private static Client client(BeanFactory beanFactory) {
try {
Client client = beanFactory.getBean(Client.class);
return new LazyClient(beanFactory, client);
}
catch (BeansException ex) {
return TracingFeignClient.create(beanFactory.getBean(HttpTracing.class),
new Client.Default(null, null));
}
}
}

View File

@@ -53,7 +53,7 @@ class TraceFeignAspect {
log.debug("Executing feign client via TraceFeignAspect");
}
if (bean != wrappedBean) {
return executeTraceFeignClient(bean, pjp);
return executeTraceFeignClient(wrappedBean, pjp);
}
return pjp.proceed();
}

View File

@@ -21,7 +21,6 @@ import java.io.IOException;
import brave.Span;
import brave.Tracer;
import brave.http.HttpTracing;
import com.netflix.client.ClientException;
import feign.Client;
import feign.Request;
import feign.Response;
@@ -34,12 +33,10 @@ import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalance
/**
* A trace representation of {@link FeignBlockingLoadBalancerClient}. Needed due to casts
* in {@link org.springframework.cloud.openfeign.FeignClientFactoryBean}. Based on
* {@link TraceLoadBalancerFeignClient}.
* in {@link org.springframework.cloud.openfeign.FeignClientFactoryBean}.
*
* @author Olga Maciaszek-Sharma
* @since 2.2.0
* @see TraceLoadBalancerFeignClient
* @see FeignBlockingLoadBalancerClient
*/
public class TraceFeignBlockingLoadBalancerClient
@@ -80,10 +77,13 @@ public class TraceFeignBlockingLoadBalancerClient
if (LOG.isDebugEnabled()) {
LOG.debug("Exception thrown", e);
}
if (e instanceof IOException || e.getCause() != null
&& e.getCause() instanceof ClientException
&& ((ClientException) e.getCause())
.getErrorType() == ClientException.ErrorType.GENERAL) {
if (e instanceof IOException/*
* || e.getCause() != null && e.getCause()
* instanceof ClientException &&
* ((ClientException) e.getCause())
* .getErrorType() ==
* ClientException.ErrorType.GENERAL
*/) {
if (LOG.isDebugEnabled()) {
LOG.debug(
"General exception was thrown, so most likely the traced client wasn't called. Falling back to a manual span");

View File

@@ -30,7 +30,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration;
import org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -48,19 +47,9 @@ import org.springframework.context.annotation.Scope;
@ConditionalOnClass({ Client.class, FeignContext.class })
@ConditionalOnBean(HttpTracing.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@AutoConfigureAfter({ SleuthHystrixAutoConfiguration.class,
TraceHttpAutoConfiguration.class })
@AutoConfigureAfter({ TraceHttpAutoConfiguration.class })
public class TraceFeignClientAutoConfiguration {
@Bean
@Scope("prototype")
@ConditionalOnClass(
name = { "com.netflix.hystrix.HystrixCommand", "feign.hystrix.HystrixFeign" })
@ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true")
Feign.Builder feignHystrixBuilder(BeanFactory beanFactory) {
return SleuthHystrixFeignBuilder.builder(beanFactory);
}
@Bean
@ConditionalOnMissingBean
@Scope("prototype")

View File

@@ -25,10 +25,8 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.util.ProxyUtils;
import org.springframework.util.ClassUtils;
/**
@@ -42,8 +40,6 @@ final class TraceFeignObjectWrapper {
public static final String EXCEPTION_WARNING = "Exception occurred while trying to access the delegate's field. Will fallback to default instrumentation mechanism, which means that the delegate might not be instrumented";
private static final boolean ribbonPresent;
private static final Log log = LogFactory.getLog(TraceFeignObjectWrapper.class);
private static final boolean loadBalancerPresent;
@@ -51,12 +47,6 @@ final class TraceFeignObjectWrapper {
private static final String DELEGATE = "delegate";
static {
ribbonPresent = ClassUtils.isPresent(
"org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient",
null)
&& ClassUtils.isPresent(
"org.springframework.cloud.netflix.ribbon.SpringClientFactory",
null);
loadBalancerPresent = ClassUtils.isPresent(
"org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient",
null)
@@ -67,10 +57,6 @@ final class TraceFeignObjectWrapper {
private final BeanFactory beanFactory;
private CachingSpringLoadBalancerFactory cachingSpringLoadBalancerFactory;
private Object springClientFactory;
private Object loadBalancerClient;
TraceFeignObjectWrapper(BeanFactory beanFactory) {
@@ -79,20 +65,10 @@ final class TraceFeignObjectWrapper {
Object wrap(Object bean) {
if (bean instanceof Client && !(bean instanceof TracingFeignClient)) {
if (ribbonPresent && bean instanceof LoadBalancerFeignClient
&& !(bean instanceof TraceLoadBalancerFeignClient)) {
return instrumentedFeignRibbonClient(bean);
}
if (ribbonPresent && bean instanceof TraceLoadBalancerFeignClient) {
return bean;
}
if (loadBalancerPresent && bean instanceof FeignBlockingLoadBalancerClient
&& !(bean instanceof TraceFeignBlockingLoadBalancerClient)) {
return instrumentedFeignLoadBalancerClient(bean);
}
if (ribbonPresent && bean instanceof TraceFeignBlockingLoadBalancerClient) {
return bean;
}
return new LazyTracingFeignClient(this.beanFactory, (Client) bean);
}
return bean;
@@ -107,7 +83,7 @@ final class TraceFeignObjectWrapper {
(BlockingLoadBalancerClient) loadBalancerClient(), this.beanFactory);
}
else {
FeignBlockingLoadBalancerClient client = ((FeignBlockingLoadBalancerClient) bean);
FeignBlockingLoadBalancerClient client = ProxyUtils.getTargetObject(bean);
try {
Field delegate = FeignBlockingLoadBalancerClient.class
.getDeclaredField(DELEGATE);
@@ -124,47 +100,6 @@ final class TraceFeignObjectWrapper {
}
}
private Object instrumentedFeignRibbonClient(Object bean) {
if (AopUtils.getTargetClass(bean).equals(LoadBalancerFeignClient.class)) {
LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
return new TraceLoadBalancerFeignClient(
(Client) new TraceFeignObjectWrapper(this.beanFactory)
.wrap(client.getDelegate()),
factory(), (SpringClientFactory) clientFactory(), this.beanFactory);
}
else {
LoadBalancerFeignClient client = ((LoadBalancerFeignClient) bean);
try {
Field delegate = LoadBalancerFeignClient.class.getDeclaredField(DELEGATE);
delegate.setAccessible(true);
delegate.set(client, new TraceFeignObjectWrapper(this.beanFactory)
.wrap(client.getDelegate()));
}
catch (NoSuchFieldException | IllegalArgumentException
| IllegalAccessException | SecurityException e) {
log.warn(EXCEPTION_WARNING, e);
}
return new TraceLoadBalancerFeignClient(client, factory(),
(SpringClientFactory) clientFactory(), this.beanFactory);
}
}
private CachingSpringLoadBalancerFactory factory() {
if (this.cachingSpringLoadBalancerFactory == null) {
this.cachingSpringLoadBalancerFactory = this.beanFactory
.getBean(CachingSpringLoadBalancerFactory.class);
}
return this.cachingSpringLoadBalancerFactory;
}
private Object clientFactory() {
if (this.springClientFactory == null) {
this.springClientFactory = this.beanFactory
.getBean(SpringClientFactory.class);
}
return this.springClientFactory;
}
private Object loadBalancerClient() {
if (loadBalancerClient == null) {
loadBalancerClient = beanFactory.getBean(BlockingLoadBalancerClient.class);

View File

@@ -1,120 +0,0 @@
/*
* Copyright 2013-2019 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.web.client.feign;
import java.io.IOException;
import brave.Span;
import brave.Tracer;
import brave.http.HttpTracing;
import com.netflix.client.ClientException;
import feign.Client;
import feign.Request;
import feign.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
/**
* We need to wrap the {@link LoadBalancerFeignClient} into a trace representation due to
* casts in {@link org.springframework.cloud.openfeign.FeignClientFactoryBean}.
*
* @author Marcin Grzejszczak
* @since 1.0.7
*/
public class TraceLoadBalancerFeignClient extends LoadBalancerFeignClient {
private static final Log log = LogFactory.getLog(TraceLoadBalancerFeignClient.class);
private final BeanFactory beanFactory;
Tracer tracer;
HttpTracing httpTracing;
TracingFeignClient tracingFeignClient;
public TraceLoadBalancerFeignClient(Client delegate,
CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory, BeanFactory beanFactory) {
super(delegate, lbClientFactory, clientFactory);
this.beanFactory = beanFactory;
}
@Override
public Response execute(Request request, Request.Options options) throws IOException {
if (log.isDebugEnabled()) {
log.debug("Before send");
}
Response response = null;
Span fallbackSpan = tracer().nextSpan().start();
try {
response = super.execute(request, options);
if (log.isDebugEnabled()) {
log.debug("After receive");
}
return response;
}
catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Exception thrown", e);
}
if (e instanceof IOException || e.getCause() != null
&& e.getCause() instanceof ClientException
&& ((ClientException) e.getCause())
.getErrorType() == ClientException.ErrorType.GENERAL) {
if (log.isDebugEnabled()) {
log.debug(
"General exception was thrown, so most likely the traced client wasn't called. Falling back to a manual span");
}
tracingFeignClient().handleSendAndReceive(fallbackSpan, request, response,
e);
}
throw e;
}
finally {
fallbackSpan.abandon();
}
}
private Tracer tracer() {
if (this.tracer == null) {
this.tracer = this.beanFactory.getBean(Tracer.class);
}
return this.tracer;
}
private HttpTracing httpTracing() {
if (this.httpTracing == null) {
this.httpTracing = this.beanFactory.getBean(HttpTracing.class);
}
return this.httpTracing;
}
private TracingFeignClient tracingFeignClient() {
if (this.tracingFeignClient == null) {
this.tracingFeignClient = (TracingFeignClient) TracingFeignClient
.create(httpTracing(), getDelegate());
}
return this.tracingFeignClient;
}
}

View File

@@ -35,6 +35,8 @@ import feign.Response;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.util.ProxyUtils;
/**
* Feign client wrapper.
*
@@ -77,7 +79,9 @@ final class TracingFeignClient implements Client {
TracingFeignClient(HttpTracing httpTracing, Client delegate) {
this.tracer = httpTracing.tracing().tracer();
this.handler = HttpClientHandler.create(httpTracing);
this.delegate = delegate;
Client delegateTarget = ProxyUtils.getTargetObject(delegate);
this.delegate = delegateTarget instanceof TracingFeignClient
? ((TracingFeignClient) delegateTarget).delegate : delegateTarget;
}
static Client create(HttpTracing httpTracing, Client delegate) {

View File

@@ -1,132 +0,0 @@
/*
* Copyright 2013-2019 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.zuul;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import brave.Span;
import brave.Tracer;
import brave.http.HttpServerHandler;
import brave.http.HttpTracing;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;
/**
* A post request {@link ZuulFilter}.
*
* @author Dave Syer
* @since 1.0.0
*/
class TracePostZuulFilter extends ZuulFilter {
private static final Log log = LogFactory.getLog(TracePostZuulFilter.class);
final HttpServerHandler<brave.http.HttpServerRequest, brave.http.HttpServerResponse> handler;
final Tracer tracer;
TracePostZuulFilter(HttpTracing httpTracing) {
this.handler = HttpServerHandler.create(httpTracing);
this.tracer = httpTracing.tracing().tracer();
}
@Override
public boolean shouldFilter() {
return !httpStatusSuccessful(RequestContext.getCurrentContext().getResponse());
}
private boolean httpStatusSuccessful(HttpServletResponse response) {
if (response.getStatus() == 0) {
return false;
}
HttpStatus.Series httpStatusSeries = HttpStatus.Series
.valueOf(response.getStatus());
return httpStatusSeries == HttpStatus.Series.SUCCESSFUL
|| httpStatusSeries == HttpStatus.Series.REDIRECTION;
}
@Override
public Object run() {
if (log.isDebugEnabled()) {
log.debug("Marking current span as handled");
}
HttpServletRequest req = RequestContext.getCurrentContext().getRequest();
HttpServletResponse resp = RequestContext.getCurrentContext().getResponse();
HttpServerResponse request = resp != null ? new HttpServerResponse(req, resp)
: null;
Throwable exception = RequestContext.getCurrentContext().getThrowable();
Span currentSpan = this.tracer.currentSpan();
this.handler.handleSend(request, exception, currentSpan);
if (log.isDebugEnabled()) {
log.debug("Handled send of " + currentSpan);
}
return null;
}
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return 0;
}
// copy/paste for now https://github.com/openzipkin/brave/issues/1064
static final class HttpServerResponse extends brave.http.HttpServerResponse {
final HttpServletResponse delegate;
final String method;
final String httpRoute;
HttpServerResponse(HttpServletRequest req, HttpServletResponse resp) {
this.delegate = resp;
this.method = req.getMethod();
this.httpRoute = (String) req.getAttribute("http.route");
}
@Override
public String method() {
return method;
}
@Override
public String route() {
return httpRoute;
}
@Override
public HttpServletResponse unwrap() {
return delegate;
}
@Override
public int statusCode() {
return delegate.getStatus();
}
}
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2013-2019 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.zuul;
import brave.http.HttpTracing;
import com.netflix.zuul.ZuulFilter;
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.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
* Auto-configuration} enables span information propagation when using Zuul.
*
* @author Dave Syer
* @since 1.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "spring.sleuth.zuul.enabled", matchIfMissing = true)
@ConditionalOnWebApplication
@ConditionalOnClass(ZuulFilter.class)
@ConditionalOnBean(HttpTracing.class)
@AutoConfigureAfter(TraceWebServletAutoConfiguration.class)
public class TraceZuulAutoConfiguration {
@Bean
static TraceZuulHandlerMappingBeanPostProcessor traceHandlerMappingBeanPostProcessor(
BeanFactory beanFactory) {
return new TraceZuulHandlerMappingBeanPostProcessor(beanFactory);
}
@Bean
TracePostZuulFilter tracePostZuulFilter(HttpTracing httpTracing) {
return new TracePostZuulFilter(httpTracing);
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright 2013-2019 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.zuul;
import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping;
/**
* Bean post processor that wraps {@link ZuulHandlerMapping} in its trace representation.
*
* @author Marcin Grzejszczak
* @since 1.0.3
*/
class TraceZuulHandlerMappingBeanPostProcessor implements BeanPostProcessor {
private static final Log log = LogFactory
.getLog(TraceZuulHandlerMappingBeanPostProcessor.class);
private final BeanFactory beanFactory;
TraceZuulHandlerMappingBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof ZuulHandlerMapping) {
if (log.isDebugEnabled()) {
log.debug("Attaching trace interceptor to bean [" + beanName
+ "] of type [" + bean.getClass().getSimpleName() + "]");
}
ZuulHandlerMapping zuulHandlerMapping = (ZuulHandlerMapping) bean;
zuulHandlerMapping.setInterceptors(this.beanFactory
.getBean(SpanCustomizingAsyncHandlerInterceptor.class));
}
return bean;
}
}

View File

@@ -15,12 +15,10 @@ org.springframework.cloud.sleuth.instrument.async.AsyncCustomAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.async.AsyncDefaultAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.scheduling.TraceSchedulingAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.client.feign.TraceFeignClientAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.circuitbreaker.SleuthCircuitBreakerAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.rxjava.RxJavaAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.reactor.TraceReactorAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.web.TraceWebFluxAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.zuul.TraceZuulAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.rpc.TraceRpcAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.grpc.TraceGrpcAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.messaging.SleuthKafkaStreamsConfiguration,\

View File

@@ -27,7 +27,7 @@ import brave.Span;
import brave.Tracer;
import brave.propagation.TraceContext;
import brave.sampler.Sampler;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.StringUtils;
import org.awaitility.Awaitility;
import org.junit.Before;
import org.junit.Test;

View File

@@ -1,206 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import brave.Tracing;
import brave.propagation.CurrentTraceContext;
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.propagation.TraceContext;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixLifecycleForwardingRequestVariable;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.BDDMockito;
import org.mockito.Mockito;
import org.springframework.cloud.sleuth.DefaultSpanNamer;
import org.springframework.cloud.sleuth.instrument.async.TraceCallable;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
public class SleuthHystrixConcurrencyStrategyTest {
ArrayListSpanReporter reporter = new ArrayListSpanReporter();
Tracing tracing = Tracing.newBuilder()
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(StrictScopeDecorator.create()).build())
.spanReporter(this.reporter).build();
@Before
@After
public void setup() {
HystrixPlugins.reset();
this.reporter.clear();
}
@Test
public void should_not_override_existing_custom_strategies() {
HystrixPlugins.getInstance()
.registerCommandExecutionHook(new MyHystrixCommandExecutionHook());
HystrixPlugins.getInstance().registerEventNotifier(new MyHystrixEventNotifier());
HystrixPlugins.getInstance()
.registerMetricsPublisher(new MyHystrixMetricsPublisher());
HystrixPlugins.getInstance()
.registerPropertiesStrategy(new MyHystrixPropertiesStrategy());
new SleuthHystrixConcurrencyStrategy(this.tracing, new DefaultSpanNamer());
then(HystrixPlugins.getInstance().getCommandExecutionHook())
.isExactlyInstanceOf(MyHystrixCommandExecutionHook.class);
then(HystrixPlugins.getInstance().getEventNotifier())
.isExactlyInstanceOf(MyHystrixEventNotifier.class);
then(HystrixPlugins.getInstance().getMetricsPublisher())
.isExactlyInstanceOf(MyHystrixMetricsPublisher.class);
then(HystrixPlugins.getInstance().getPropertiesStrategy())
.isExactlyInstanceOf(MyHystrixPropertiesStrategy.class);
}
@Test
public void should_wrap_delegates_callable_in_trace_callable_when_delegate_is_present()
throws Exception {
HystrixPlugins.getInstance()
.registerConcurrencyStrategy(new MyHystrixConcurrencyStrategy());
SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy(
this.tracing, new DefaultSpanNamer());
Callable<String> callable = strategy.wrapCallable(() -> "hello");
then(callable).isInstanceOf(TraceCallable.class);
then(callable.call()).isEqualTo("executed_custom_callable");
}
@Test
public void should_wrap_callable_in_trace_callable_when_delegate_is_present()
throws Exception {
SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy(
this.tracing, new DefaultSpanNamer());
Callable<String> callable = strategy.wrapCallable(() -> "hello");
then(callable).isInstanceOf(TraceCallable.class);
}
@Test
public void should_add_trace_keys_when_span_is_created() throws Exception {
SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy(
this.tracing, new DefaultSpanNamer());
Callable<String> callable = strategy.wrapCallable(() -> "hello");
callable.call();
then(callable).isInstanceOf(TraceCallable.class);
then(this.reporter.getSpans()).hasSize(1);
}
@Test
public void should_propagate_trace_context_when_passthrough_is_enabled()
throws Exception {
SleuthHystrixConcurrencyStrategy strategy = new SleuthHystrixConcurrencyStrategy(
this.tracing, new DefaultSpanNamer(), true);
TraceContext traceContext = TraceContext.newBuilder().traceId(123L).spanId(456L)
.build();
CurrentTraceContext.Scope scope = tracing.currentTraceContext()
.newScope(traceContext);
Callable<TraceContext> callable = strategy
.wrapCallable(() -> tracing.currentTraceContext().get());
then(callable).isNotInstanceOf(TraceCallable.class);
then(callable.call()).isEqualTo(traceContext);
scope.close();
}
@Test
public void should_delegate_work_to_custom_hystrix_concurrency_strategy()
throws Exception {
HystrixConcurrencyStrategy strategy = Mockito
.mock(HystrixConcurrencyStrategy.class);
HystrixPlugins.getInstance().registerConcurrencyStrategy(strategy);
SleuthHystrixConcurrencyStrategy sleuthStrategy = new SleuthHystrixConcurrencyStrategy(
this.tracing, new DefaultSpanNamer());
sleuthStrategy.wrapCallable(() -> "foo");
sleuthStrategy.getThreadPool(HystrixThreadPoolKey.Factory.asKey(""),
Mockito.mock(HystrixThreadPoolProperties.class));
sleuthStrategy.getThreadPool(HystrixThreadPoolKey.Factory.asKey(""),
Mockito.mock(HystrixProperty.class), Mockito.mock(HystrixProperty.class),
Mockito.mock(HystrixProperty.class), TimeUnit.DAYS,
Mockito.mock(BlockingQueue.class));
sleuthStrategy.getBlockingQueue(10);
sleuthStrategy.getRequestVariable(
Mockito.mock(HystrixLifecycleForwardingRequestVariable.class));
BDDMockito.then(strategy).should().wrapCallable((Callable) BDDMockito.any());
BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(),
BDDMockito.any());
BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(),
BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any(),
BDDMockito.any());
BDDMockito.then(strategy).should().getThreadPool(BDDMockito.any(),
BDDMockito.any(), BDDMockito.any(), BDDMockito.any(), BDDMockito.any(),
BDDMockito.any());
BDDMockito.then(strategy).should().getBlockingQueue(10);
BDDMockito.then(strategy).should().getRequestVariable(BDDMockito.any());
}
static class MyHystrixCommandExecutionHook extends HystrixCommandExecutionHook {
}
@SuppressWarnings("unchecked")
static class MyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
return () -> (T) "executed_custom_callable";
}
}
static class MyHystrixEventNotifier extends HystrixEventNotifier {
}
static class MyHystrixMetricsPublisher extends HystrixMetricsPublisher {
}
static class MyHystrixPropertiesStrategy extends HystrixPropertiesStrategy {
}
}

View File

@@ -1,198 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.sampler.Sampler;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import org.assertj.core.api.BDDAssertions;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import static com.netflix.hystrix.HystrixCommand.Setter.withGroupKey;
import static com.netflix.hystrix.HystrixCommandGroupKey.Factory.asKey;
import static org.assertj.core.api.BDDAssertions.then;
public class TraceCommandTests {
ArrayListSpanReporter reporter = new ArrayListSpanReporter();
Tracing tracing = Tracing.newBuilder()
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(StrictScopeDecorator.create()).build())
.spanReporter(this.reporter).sampler(Sampler.ALWAYS_SAMPLE).build();
Tracer tracer = this.tracing.tracer();
@Before
public void setup() {
HystrixPlugins.reset();
this.reporter.clear();
}
@Test
public void should_remove_span_from_thread_local_after_finishing_work()
throws Exception {
Span firstSpanFromHystrix = givenACommandWasExecuted(traceReturningCommand());
Span secondSpanFromHystrix = whenCommandIsExecuted(traceReturningCommand());
then(secondSpanFromHystrix.context().traceId()).as("second trace id")
.isNotEqualTo(firstSpanFromHystrix.context().traceId())
.as("first trace id");
}
@Test
public void should_create_a_local_span_with_proper_tags_when_hystrix_command_gets_executed()
throws Exception {
whenCommandIsExecuted(traceReturningCommand());
then(this.reporter.getSpans()).hasSize(1);
then(this.reporter.getSpans().get(0).tags()).containsEntry("commandKey",
"traceCommandKey");
then(this.reporter.getSpans().get(0).duration()).isGreaterThan(0L);
}
@Test
public void should_run_Hystrix_command_with_span_passed_from_parent_thread() {
Span span = this.tracer.nextSpan();
try (Tracer.SpanInScope ws = this.tracer.withSpanInScope(span.start())) {
TraceCommand<Span> command = traceReturningCommand();
whenCommandIsExecuted(command);
}
finally {
span.finish();
}
List<zipkin2.Span> spans = this.reporter.getSpans();
then(spans).hasSize(2);
then(spans.get(0).traceId()).isEqualTo(span.context().traceIdString());
then(spans.get(0).tags()).containsEntry("commandKey", "traceCommandKey")
.containsEntry("commandGroup", "group")
.containsEntry("threadPoolKey", "group");
}
@Test
public void should_pass_tracing_information_when_using_Hystrix_commands() {
Tracer tracer = this.tracer;
HystrixCommand.Setter setter = withGroupKey(asKey("group"))
.andCommandKey(HystrixCommandKey.Factory.asKey("command"));
// tag::hystrix_command[]
HystrixCommand<String> hystrixCommand = new HystrixCommand<String>(setter) {
@Override
protected String run() throws Exception {
return someLogic();
}
};
// end::hystrix_command[]
// tag::trace_hystrix_command[]
TraceCommand<String> traceCommand = new TraceCommand<String>(tracer, setter) {
@Override
public String doRun() throws Exception {
return someLogic();
}
};
// end::trace_hystrix_command[]
String resultFromHystrixCommand = hystrixCommand.execute();
String resultFromTraceCommand = traceCommand.execute();
then(resultFromHystrixCommand).isEqualTo(resultFromTraceCommand);
}
@Test
public void should_pass_tracing_information_when_using_Hystrix_commands_with_fallback() {
Tracer tracer = this.tracer;
AtomicReference<Span> spanBeforeThrowingException = new AtomicReference<>();
HystrixCommand.Setter setter = withGroupKey(asKey("group"))
.andCommandKey(HystrixCommandKey.Factory.asKey("command"));
TraceCommand<Span> traceCommand = new TraceCommand<Span>(tracer, setter) {
@Override
public Span doRun() throws Exception {
spanBeforeThrowingException.set(tracer.currentSpan());
throw new FooException();
}
@Override
public Span doGetFallback() {
return tracer.currentSpan();
}
@Override
protected String getFallbackMethodName() {
return super.getFallbackMethodName() + "_foobar";
}
};
Span span = whenCommandIsExecuted(traceCommand);
BDDAssertions.then(span.context().traceIdString())
.isEqualTo(spanBeforeThrowingException.get().context().traceIdString());
List<zipkin2.Span> spans = this.reporter.getSpans();
then(spans).hasSize(1);
then(spans.get(0).traceId()).isEqualTo(span.context().traceIdString());
then(spans.get(0).tags()).containsEntry("commandKey", "command")
.containsEntry("commandGroup", "group")
.containsEntry("threadPoolKey", "group")
.containsEntry("fallbackMethodName", "getFallback_foobar");
}
private String someLogic() {
return "some logic";
}
private TraceCommand<Span> traceReturningCommand() {
return new TraceCommand<Span>(this.tracer, withGroupKey(asKey("group"))
.andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
.withCoreSize(1).withMaxQueueSize(1))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionTimeoutEnabled(false))
.andCommandKey(HystrixCommandKey.Factory.asKey("traceCommandKey"))) {
@Override
public Span doRun() throws Exception {
return TraceCommandTests.this.tracer.currentSpan();
}
};
}
private Span whenCommandIsExecuted(TraceCommand<Span> command) {
return command.execute();
}
private Span givenACommandWasExecuted(TraceCommand<Span> command) {
return whenCommandIsExecuted(command);
}
}
class FooException extends RuntimeException {
}

View File

@@ -1,135 +0,0 @@
/*
* Copyright 2013-2019 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.messaging;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import brave.Span;
import brave.Tracing;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.aws.messaging.listener.QueueMessageHandler;
import org.springframework.cloud.aws.messaging.listener.annotation.SqsListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
@SpringBootTest(
classes = ITTracingMethodMessageHandlerAdapterTests.TestingConfiguration.class,
webEnvironment = NONE)
@RunWith(SpringRunner.class)
public class ITTracingMethodMessageHandlerAdapterTests {
private static final String TRACE_ID = "12345678123456781234567812345678";
private static final String SPAN_ID = "1234567812345678";
@Autowired
ApplicationContext applicationContext;
@Autowired
SqsQueueMessageHandlerFactory messageHandlerFactory;
@Autowired
TestingMessageHandler testingMessageHandler;
@Autowired
Tracing tracing;
private QueueMessageHandler messageHandler;
@Before
public void setup() {
messageHandler = messageHandlerFactory.createQueueMessageHandler();
messageHandler.setApplicationContext(applicationContext);
messageHandler.afterPropertiesSet();
}
@Test
public void aSpanGetsPutIntoScopeWithoutHeadersOnTheMessage() {
AtomicReference<Span> probedSpan = new AtomicReference<>();
testingMessageHandler.withTestProbe(((headers, s) -> {
probedSpan.set(tracing.tracer().currentSpan());
}));
messageHandler.handleMessage(new GenericMessage<>("message",
Collections.singletonMap("LogicalResourceId", "test")));
assertThat(probedSpan.get()).isNotNull();
}
@Test
public void theSpanThatIsInTheHeadersIsUsedForTheTraceScope() {
AtomicReference<Span> probedSpan = new AtomicReference<>();
testingMessageHandler.withTestProbe(((headers, s) -> {
probedSpan.set(tracing.tracer().currentSpan());
}));
Map<String, Object> headers = new HashMap<>();
headers.put("LogicalResourceId", "test");
headers.put("X-B3-TraceId", TRACE_ID);
headers.put("X-B3-SpanId", SPAN_ID);
headers.put("X-B3-Sampled", "1");
messageHandler.handleMessage(new GenericMessage<>("message", headers));
assertThat(probedSpan.get()).isNotNull();
assertThat(probedSpan.get().context().traceIdString()).isEqualTo(TRACE_ID);
assertThat(probedSpan.get().context().sampled()).isTrue();
}
@EnableAutoConfiguration
@Configuration
static class TestingConfiguration {
@Bean
TestingMessageHandler testingMessageHandler() {
return new TestingMessageHandler();
}
}
static class TestingMessageHandler {
private BiConsumer<MessageHeaders, String> testProbe;
void withTestProbe(BiConsumer<MessageHeaders, String> consumer) {
this.testProbe = consumer;
}
@SqsListener("test")
public void handle(MessageHeaders header, String payload) {
testProbe.accept(header, payload);
}
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright 2013-2019 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.messaging;
import java.util.Collections;
import java.util.function.BiConsumer;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.quality.Strictness;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
import static org.assertj.core.api.Assertions.assertThat;
public class SqsQueueMessageHandlerTests {
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock
TracingMethodMessageHandlerAdapter adapter;
SqsQueueMessageHandler subject;
@Before
public void setup() {
subject = new SqsQueueMessageHandler(adapter, Collections.emptyList());
}
@Test
public void sqsQueueMessageHandlerDelegatesToAdapter() {
ArgumentCaptor<Message> messageCapture = ArgumentCaptor.forClass(Message.class);
ArgumentCaptor<MessageHandler> handlerCapture = ArgumentCaptor
.forClass(MessageHandler.class);
ArgumentCaptor<BiConsumer> spanTaggerCapture = ArgumentCaptor
.forClass(BiConsumer.class);
Mockito.doNothing().when(adapter).wrapMethodMessageHandler(
messageCapture.capture(), handlerCapture.capture(),
spanTaggerCapture.capture());
subject.handleMessage(new GenericMessage<>("a"));
Mockito.verify(adapter, Mockito.times(1)).wrapMethodMessageHandler(Mockito.any(),
Mockito.any(), Mockito.any());
assertThat(messageCapture.getValue().getPayload().toString()).isEqualTo("a");
assertThat(handlerCapture.getValue()).isNotNull();
assertThat(spanTaggerCapture.getValue()).isNotNull();
}
}

View File

@@ -22,7 +22,6 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.ConfigurableApplicationContext;
@@ -56,7 +55,6 @@ public class TraceNoWebEnvironmentTests {
@Configuration
@EnableAutoConfiguration
@EnableFeignClients(clients = Config.SomeFeignClient.class)
@EnableCircuitBreaker
public static class Config {
@FeignClient(name = "google", url = "https://www.google.com/")

View File

@@ -29,7 +29,6 @@ import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import brave.sampler.Sampler;
import brave.spring.web.TracingClientHttpRequestInterceptor;
import org.apache.commons.lang3.StringUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -200,7 +199,7 @@ public class TraceRestTemplateInterceptorTests {
then(spans).hasSize(2);
String spanName = spans.get(0).name();
then(spanName).isEqualTo("http:/cas~fs~%c3%a5%cb%86%e2%80%99");
then(StringUtils.isAsciiPrintable(spanName));
then(isAsciiPrintable(spanName));
}
@Test
@@ -223,7 +222,7 @@ public class TraceRestTemplateInterceptorTests {
then(spans).isNotEmpty();
String spanName = spans.get(0).name();
then(spanName).hasSize(50);
then(StringUtils.isAsciiPrintable(spanName));
then(isAsciiPrintable(spanName));
}
private String bigName() {
@@ -234,6 +233,23 @@ public class TraceRestTemplateInterceptorTests {
return sb.toString();
}
private static boolean isAsciiPrintable(String str) {
if (str == null) {
return false;
}
int sz = str.length();
for (int i = 0; i < sz; i++) {
if (!isAsciiPrintable(str.charAt(i))) {
return false;
}
}
return true;
}
private static boolean isAsciiPrintable(char ch) {
return ch >= 32 && ch < 127;
}
@RestController
public class TestController {

View File

@@ -17,6 +17,8 @@
package org.springframework.cloud.sleuth.instrument.web.client.discoveryexception;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -27,15 +29,18 @@ import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import reactor.core.publisher.Flux;
import zipkin2.reporter.Reporter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
@@ -134,7 +139,7 @@ public class WebClientDiscoveryExceptionTests {
TraceWebServletAutoConfiguration.class })
@EnableDiscoveryClient
@EnableFeignClients
@RibbonClient("exceptionservice")
@LoadBalancerClient("exceptionservice")
public static class TestConfiguration {
@LoadBalanced
@@ -153,6 +158,51 @@ public class WebClientDiscoveryExceptionTests {
return new ArrayListSpanReporter();
}
@Bean
ServiceInstanceListSupplier serviceInstanceListSupplier() {
return new ServiceInstanceListSupplier() {
@Override
public String getServiceId() {
return "exceptionservice";
}
@Override
public Flux<List<ServiceInstance>> get() {
return Flux.just(Collections.singletonList(new ServiceInstance() {
@Override
public String getServiceId() {
return "exceptionservice";
}
@Override
public String getHost() {
return "localhost";
}
@Override
public int getPort() {
return 1234;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public URI getUri() {
return null;
}
@Override
public Map<String, String> getMetadata() {
return null;
}
}));
}
};
}
}
}

View File

@@ -17,16 +17,12 @@
package org.springframework.cloud.sleuth.instrument.web.client.exception;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.sampler.Sampler;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.apache.commons.logging.Log;
@@ -42,12 +38,14 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.system.OutputCaptureRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.test.context.junit4.rules.SpringClassRule;
@@ -145,7 +143,7 @@ public class WebClientExceptionTests {
@Configuration
@EnableAutoConfiguration
@EnableFeignClients
@RibbonClient(value = "exceptionservice",
@LoadBalancerClient(value = "exceptionservice",
configuration = ExceptionServiceRibbonClientConfiguration.class)
public static class TestConfiguration {
@@ -174,11 +172,10 @@ public class WebClientExceptionTests {
public static class ExceptionServiceRibbonClientConfiguration {
@Bean
public ILoadBalancer exceptionServiceRibbonLoadBalancer() {
BaseLoadBalancer balancer = new BaseLoadBalancer();
balancer.setServersList(Collections
.singletonList(new Server("invalid.host.to.break.tests", 1234)));
return balancer;
public ServiceInstanceListSupplier serviceInstanceListSupplier(Environment env) {
return ServiceInstanceListSupplier.fixed(env)
.instance("invalid.host.to.break.tests", 1234, "exceptionservice")
.build();
}
}

View File

@@ -52,9 +52,6 @@ public class TraceFeignAspectTests {
@Mock
ProceedingJoinPoint pjp;
@Mock
TraceLoadBalancerFeignClient traceLoadBalancerFeignClient;
Tracing tracing = Tracing.newBuilder()
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(StrictScopeDecorator.create()).build())
@@ -96,14 +93,4 @@ public class TraceFeignAspectTests {
verify(this.pjp).proceed();
}
@Test
public void should_not_wrap_traced_load_balancer_feign_client_in_trace_representation()
throws Throwable {
given(this.pjp.getTarget()).willReturn(this.traceLoadBalancerFeignClient);
this.traceFeignAspect.feignClientWasCalled(this.pjp);
verify(this.pjp).proceed();
}
}

View File

@@ -17,7 +17,6 @@
package org.springframework.cloud.sleuth.instrument.web.client.integration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -35,9 +34,6 @@ import brave.Tracing;
import brave.propagation.SamplingFlags;
import brave.propagation.TraceContextOrSamplingFlags;
import brave.sampler.Sampler;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.apache.commons.logging.LogFactory;
@@ -73,13 +69,15 @@ import org.springframework.boot.web.servlet.error.ErrorAttributes;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.gateway.config.GatewayAutoConfiguration;
import org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.sleuth.instrument.web.TraceWebServletAutoConfiguration;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
@@ -550,8 +548,8 @@ public class WebClientTests {
GatewayClassPathWarningAutoConfiguration.class,
GatewayAutoConfiguration.class })
@EnableFeignClients
@RibbonClient(value = "fooservice",
configuration = SimpleRibbonClientConfiguration.class)
@LoadBalancerClient(value = "fooservice",
configuration = SimpleLoadBalancerClientConfiguration.class)
public static class TestConfiguration {
@Bean
@@ -720,17 +718,15 @@ public class WebClientTests {
}
@Configuration
public static class SimpleRibbonClientConfiguration {
public static class SimpleLoadBalancerClientConfiguration {
@Value("${local.server.port}")
private int port = 0;
@Bean
public ILoadBalancer ribbonLoadBalancer() {
BaseLoadBalancer balancer = new BaseLoadBalancer();
balancer.setServersList(
Collections.singletonList(new Server("localhost", this.port)));
return balancer;
public ServiceInstanceListSupplier serviceInstanceListSupplier(Environment env) {
return ServiceInstanceListSupplier.fixed(env)
.instance(this.port, "fooservice").build();
}
}

View File

@@ -1,125 +0,0 @@
/*
* Copyright 2013-2019 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.zuul;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import brave.ErrorParser;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.http.HttpTracing;
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.monitoring.TracerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.netflix.zuul.metrics.EmptyTracerFactory;
import org.springframework.cloud.sleuth.instrument.web.SleuthHttpParserAccessor;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Dave Syer
*
*/
@RunWith(MockitoJUnitRunner.class)
public class TracePostZuulFilterTests {
@Mock
HttpServletRequest httpServletRequest;
@Mock
HttpServletResponse httpServletResponse;
ArrayListSpanReporter reporter = new ArrayListSpanReporter();
Tracing tracing = Tracing.newBuilder()
.currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
.addScopeDecorator(StrictScopeDecorator.create()).build())
.spanReporter(this.reporter).build();
HttpTracing httpTracing = HttpTracing.newBuilder(this.tracing)
.clientParser(SleuthHttpParserAccessor.getClient())
.serverParser(SleuthHttpParserAccessor.getServer(new ErrorParser())).build();
RequestContext requestContext = new RequestContext();
private TracePostZuulFilter filter = new TracePostZuulFilter(this.httpTracing);
@After
public void clean() {
RequestContext.getCurrentContext().unset();
this.httpTracing.tracing().close();
RequestContext.testSetCurrentContext(null);
}
@Before
public void setup() {
BDDMockito.given(this.httpServletResponse.getStatus()).willReturn(200);
this.requestContext.setRequest(this.httpServletRequest);
this.requestContext.setResponse(this.httpServletResponse);
RequestContext.testSetCurrentContext(this.requestContext);
TracerFactory.initialize(new EmptyTracerFactory());
}
@Test
public void should_run_when_status_is_unsuccessful() throws Exception {
BDDMockito.given(this.httpServletResponse.getStatus()).willReturn(456);
then(this.filter.shouldFilter()).isTrue();
}
@Test
public void should_run_when_status_is_unknown() throws Exception {
BDDMockito.given(this.httpServletResponse.getStatus()).willReturn(0);
then(this.filter.shouldFilter()).isTrue();
}
@Test
public void should_handle_span_and_mark_it_as_handled() throws Exception {
Span span = this.tracing.tracer().nextSpan().name("http:start").start();
BDDMockito.given(this.httpServletResponse.getStatus()).willReturn(456);
try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span)) {
this.filter.runFilter();
}
finally {
span.finish();
}
List<zipkin2.Span> spans = this.reporter.getSpans();
then(spans).hasSize(1);
// initial span
then(spans.get(0).tags()).containsEntry("http.status_code", "456");
then(spans.get(0).name()).isEqualTo("http:start");
then(this.tracing.tracer().currentSpan()).isNull();
}
}

View File

@@ -1,16 +1,4 @@
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds: 5000
ribbon:
ConnectTimeout: 3000
ReadTimeout: 5000
exceptionService.ribbon:
MaxAutoRetries: 3
OkToRetryOnAllOperations: true
ConnectTimeout: 1
ReadTimeout: 1
eureka.client.enabled: false
ribbon.eureka.enabled: false
spring.sleuth.scheduled.skipPattern: "^org.*TestBeanWithScheduledMethodToBeIgnored$"

View File

@@ -22,11 +22,11 @@
<parent>
<artifactId>spring-cloud-dependencies-parent</artifactId>
<groupId>org.springframework.cloud</groupId>
<version>2.2.1.RELEASE</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath/>
</parent>
<artifactId>spring-cloud-sleuth-dependencies</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging>
<name>spring-cloud-sleuth-dependencies</name>
<description>Spring Cloud Sleuth Dependencies</description>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@@ -38,7 +38,6 @@
<module>spring-cloud-sleuth-sample-messaging</module>
<module>spring-cloud-sleuth-sample-websocket</module>
<module>spring-cloud-sleuth-sample-feign</module>
<module>spring-cloud-sleuth-sample-ribbon</module>
<module>spring-cloud-sleuth-sample-zipkin</module>
</modules>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -1,90 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2018 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-sample-ribbon</artifactId>
<packaging>jar</packaging>
<name>spring-cloud-sleuth-sample-ribbon</name>
<description>Spring Cloud Sleuth Sample</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<sonar.skip>true</sonar.skip>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2013-2019 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 sample;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
/**
* @author Spencer Gibb
* @author Dave Syer
*/
@RestController
public class SampleController {
@Autowired
private RestTemplate restTemplate;
private Random random = new Random();
@RequestMapping("/")
public String hi() throws InterruptedException {
Thread.sleep(this.random.nextInt(1000));
String s = this.restTemplate.getForObject("https://zipkin/hi2", String.class);
return "hi/" + s;
}
@RequestMapping("/call")
public String traced() {
String s = this.restTemplate.getForObject("https://zipkin/call", String.class);
return "call/" + s;
}
}

View File

@@ -1,63 +0,0 @@
/*
* Copyright 2013-2019 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 sample;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import zipkin2.Span;
import zipkin2.reporter.Reporter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.client.RestTemplate;
/**
* @author Spencer Gibb
*/
@SpringBootApplication
@EnableAsync
@EnableZuulProxy
public class SampleRibbonApplication {
private static final Log logger = LogFactory.getLog(SampleRibbonApplication.class);
public static void main(String[] args) {
SpringApplication.run(SampleRibbonApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// Use this for debugging (or if there is no Zipkin server running on port 9411)
@Bean
@ConditionalOnProperty(value = "sample.zipkin.enabled", havingValue = "false")
public Reporter<Span> spanReporter() {
return new Reporter<Span>() {
@Override
public void report(Span span) {
logger.info(span);
}
};
}
}

View File

@@ -1,36 +0,0 @@
server:
port: 3382
sample:
zipkin:
enabled: false
spring:
application:
name: testSleuthRibbon
zipkin:
ribbon:
listOfServers: localhost:3380
messaging:
ribbon:
listOfServers: localhost:3381
vanilla:
ribbon:
listOfServers: localhost:3379
# This doesn't do anything in this app (no service discovery), but it's here as a
# reminder that you need it if the routes are discovered
hystrix:
execution:
isolation:
strategy: SEMAPHORE
zuul:
routes:
zipkin:
url: http://localhost:3380
messaging:
url: http://localhost:3381
vanilla:
url: http://localhost:3379

View File

@@ -1,37 +0,0 @@
/*
* Copyright 2013-2019 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 sample;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SampleRibbonApplication.class)
@WebAppConfiguration
@TestPropertySource(properties = "sample.zipkin.enabled=false")
public class SampleRibbonApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-samples</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -22,7 +22,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-sleuth</artifactId>

View File

@@ -22,7 +22,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>spring-cloud-starter-zipkin</artifactId>

View File

@@ -30,14 +30,13 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modules>
<module>spring-cloud-sleuth-instrumentation-async-tests</module>
<module>spring-cloud-sleuth-instrumentation-grpc-tests</module>
<module>spring-cloud-sleuth-instrumentation-hystrix-tests</module>
<module>spring-cloud-sleuth-instrumentation-messaging-tests</module>
<module>spring-cloud-sleuth-instrumentation-reactor-tests</module>
<module>spring-cloud-sleuth-instrumentation-lettuce-tests</module>
@@ -47,7 +46,6 @@
<module>spring-cloud-sleuth-instrumentation-mvc-tests</module>
<module>spring-cloud-sleuth-instrumentation-webflux-tests</module>
<module>spring-cloud-sleuth-instrumentation-feign-tests</module>
<module>spring-cloud-sleuth-instrumentation-zuul-tests</module>
</modules>
<build>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@@ -65,11 +65,11 @@
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>

View File

@@ -36,11 +36,10 @@ import zipkin2.reporter.Reporter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -59,15 +58,15 @@ import static org.assertj.core.api.BDDAssertions.then;
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class ManuallyCreatedLoadBalancerFeignClientTests {
@Autowired
MyClient myClient;
@Autowired
MyNameRemote myNameRemote;
@Autowired
ArrayListSpanReporter reporter;
@Autowired
MyBlockingClient myClient;
@Autowired
Tracing tracer;
@@ -80,7 +79,7 @@ public class ManuallyCreatedLoadBalancerFeignClientTests {
public void should_reuse_custom_feign_client() {
String response = this.myNameRemote.get();
then(this.myClient.wasCalled()).isTrue();
// then(this.myClient.wasCalled()).isTrue();
then(response).isEqualTo("foo");
List<Span> spans = this.reporter.getSpans();
// retries
@@ -111,9 +110,8 @@ public class ManuallyCreatedLoadBalancerFeignClientTests {
class Application {
@Bean
public Client client(CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new MyClient(new MyDelegateClient(), cachingFactory, clientFactory);
public Client client(BlockingLoadBalancerClient blockingLoadBalancerClient) {
return new MyBlockingClient(new MyDelegateClient(), blockingLoadBalancerClient);
}
@Bean
@@ -128,11 +126,10 @@ class Application {
}
class MyClient extends LoadBalancerFeignClient {
class MyBlockingClient extends FeignBlockingLoadBalancerClient {
MyClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
MyBlockingClient(Client delegate, BlockingLoadBalancerClient loadBalancerClient) {
super(delegate, loadBalancerClient);
}
boolean wasCalled;
@@ -162,6 +159,10 @@ class MyDelegateClient implements Client {
.headers(new HashMap<>()).status(200).build();
}
boolean wasCalled() {
return wasCalled;
}
}
@FeignClient(name = "foo", url = "https://non.existing.url")

View File

@@ -16,7 +16,6 @@
package org.springframework.cloud.sleuth.instrument.feign.issues.issue1125delegates;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
@@ -41,11 +40,8 @@ import zipkin2.reporter.Reporter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.cloud.openfeign.ribbon.CachingSpringLoadBalancerFactory;
import org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -65,9 +61,6 @@ import static org.assertj.core.api.BDDAssertions.then;
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
@Autowired
MyClient myClient;
@Autowired
MyDelegateClient myDelegateClient;
@@ -77,6 +70,9 @@ public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
@Autowired
ArrayListSpanReporter reporter;
@Autowired
MyDelegateClient myClient;
@Autowired
Tracing tracer;
@@ -89,10 +85,10 @@ public class ManuallyCreatedDelegateLoadBalancerFeignClientTests {
public void should_reuse_custom_feign_client() {
String response = this.myNameRemote.get();
then(this.myClient.wasCalled()).isTrue();
// then(this.myClient.wasCalled()).isTrue();
then(this.myDelegateClient.wasCalled()).isTrue();
then(response).isEqualTo("foo");
System.out.println("this.myclient.wascalled: " + this.myClient.wasCalled());
// System.out.println("this.myclient.wascalled: " + this.myClient.wasCalled());
List<Span> spans = this.reporter.getSpans();
// retries
then(spans).hasSize(1);
@@ -127,13 +123,6 @@ class Application {
return new MyDelegateClient();
}
@Bean
public Client client(MyDelegateClient myDelegateClient,
CachingSpringLoadBalancerFactory cachingFactory,
SpringClientFactory clientFactory) {
return new MyClient(myDelegateClient, cachingFactory, clientFactory);
}
@Bean
public MyNameRemote myNameRemote(Client client, Decoder decoder, Encoder encoder,
Contract contract) {
@@ -154,27 +143,6 @@ class Application {
}
class MyClient extends LoadBalancerFeignClient {
MyClient(Client delegate, CachingSpringLoadBalancerFactory lbClientFactory,
SpringClientFactory clientFactory) {
super(delegate, lbClientFactory, clientFactory);
}
boolean wasCalled;
@Override
public Response execute(Request request, Request.Options options) throws IOException {
this.wasCalled = true;
return getDelegate().execute(request, options);
}
boolean wasCalled() {
return this.wasCalled;
}
}
class MyDelegateClient implements Client {
boolean wasCalled;

View File

@@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.List;
import brave.sampler.Sampler;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.ConfigurableApplicationContext;
@@ -67,7 +65,6 @@ public class Issue307Tests {
@Import({ ParticipantsBean.class })
@RestController
@EnableFeignClients
@EnableCircuitBreaker
class SleuthSampleApplication {
private static final Logger LOG = LoggerFactory
@@ -116,11 +113,6 @@ class ParticipantsBean {
@Autowired
private ParticipantsClient participantsClient;
@HystrixCommand(fallbackMethod = "defaultParticipants")
public List<Object> getParticipants(String raceId) {
return this.participantsClient.getParticipants(raceId);
}
public List<Object> defaultParticipants(String raceId) {
return new ArrayList<>();
}

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -1,79 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2019 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-instrumentation-hystrix-tests</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Sleuth Hystrix Instrumentation Tests</name>
<description>Spring Cloud Sleuth Hystrix Instrumentation Tests</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<sonar.skip>true</sonar.skip>
</properties>
<build>
<plugins>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,38 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration;
import org.springframework.context.annotation.Configuration;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@EnableAutoConfiguration(
exclude = { LoadBalancerAutoConfiguration.class, JmxAutoConfiguration.class })
// ,TraceSpringIntegrationAutoConfiguration.class,
// TraceWebSocketAutoConfiguration.class })
@Configuration
public @interface DefaultTestAutoConfiguration {
}

View File

@@ -1,124 +0,0 @@
/*
* Copyright 2013-2019 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.hystrix;
import java.util.concurrent.atomic.AtomicReference;
import brave.Span;
import brave.Tracing;
import brave.sampler.Sampler;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.strategy.HystrixPlugins;
import org.awaitility.Awaitility;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { HystrixAnnotationsIntegrationTests.TestConfig.class })
@DirtiesContext
public class HystrixAnnotationsIntegrationTests {
@Autowired
HystrixCommandInvocationSpanCatcher catcher;
@Autowired
Tracing tracer;
@BeforeClass
@AfterClass
public static void reset() {
HystrixPlugins.reset();
}
@Test
public void should_create_new_span_with_thread_name_when_executed_a_hystrix_command_annotated_method() {
whenHystrixCommandAnnotatedMethodGetsExecuted();
thenSpanInHystrixThreadIsCreated();
}
private void whenHystrixCommandAnnotatedMethodGetsExecuted() {
this.catcher.invokeLogicWrappedInHystrixCommand();
}
private void thenSpanInHystrixThreadIsCreated() {
Awaitility.await().atMost(5, SECONDS).untilAsserted(() -> {
then(HystrixAnnotationsIntegrationTests.this.catcher.getSpan()).isNotNull();
});
}
@DefaultTestAutoConfiguration
@EnableHystrix
@Configuration
static class TestConfig {
@Bean
HystrixCommandInvocationSpanCatcher spanCatcher(Tracing tracing) {
return new HystrixCommandInvocationSpanCatcher(tracing);
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
public static class HystrixCommandInvocationSpanCatcher {
private final Tracing tracing;
AtomicReference<Span> spanCaughtFromHystrixThread;
public HystrixCommandInvocationSpanCatcher(Tracing tracing) {
this.tracing = tracing;
}
@HystrixCommand
public void invokeLogicWrappedInHystrixCommand() {
this.spanCaughtFromHystrixThread = new AtomicReference<>(
this.tracing.tracer().currentSpan());
}
public Long getTraceId() {
if (this.spanCaughtFromHystrixThread == null
|| this.spanCaughtFromHystrixThread.get() == null) {
return null;
}
return this.spanCaughtFromHystrixThread.get().context().traceId();
}
public Span getSpan() {
return this.spanCaughtFromHystrixThread.get();
}
}
}

View File

@@ -1,3 +0,0 @@
logging.level.org.springframework.cloud: DEBUG
logging.level.com.netflix.discovery.InstanceInfoReplicator: ERROR
logging.level.org.springframework.cloud.sleuth.instrument.web.client.feign: TRACE

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -31,7 +31,7 @@ https://www.w3.org/2001/XMLSchema-instance ">
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@@ -64,6 +64,12 @@ https://www.w3.org/2001/XMLSchema-instance ">
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>

View File

@@ -28,10 +28,9 @@ import brave.Tracer;
import brave.Tracing;
import brave.propagation.StrictScopeDecorator;
import brave.propagation.ThreadLocalCurrentTraceContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -47,7 +46,6 @@ import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.MessageHeaderAccessor;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -61,7 +59,6 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
*/
@SpringBootTest(classes = ITTracingChannelInterceptorTests.App.class,
webEnvironment = WebEnvironment.NONE)
@RunWith(SpringRunner.class)
@DirtiesContext
public class ITTracingChannelInterceptorTests implements MessageHandler {
@@ -95,13 +92,13 @@ public class ITTracingChannelInterceptorTests implements MessageHandler {
}
}
@Before
@BeforeEach
public void init() {
this.directChannel.subscribe(this);
this.executorChannel.subscribe(this);
}
@After
@AfterEach
public void close() {
this.directChannel.unsubscribe(this);
this.executorChannel.unsubscribe(this);

View File

@@ -40,8 +40,7 @@ import org.apache.activemq.ra.ActiveMQActivationSpec;
import org.apache.activemq.ra.ActiveMQResourceAdapter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import zipkin2.Span;
import org.springframework.beans.factory.annotation.Autowired;
@@ -169,25 +168,6 @@ public class JmsTracingConfigurationTest {
});
}
@Test
@Ignore("flakey")
public void tracesListener_annotationMessageListener() {
this.contextRunner.withUserConfiguration(AnnotationJmsListenerConfiguration.class)
.run(ctx -> {
clearSpans(ctx);
ctx.getBean(JmsTemplate.class).convertAndSend("myQueue", "foo");
Callable<Span> takeSpan = ctx.getBean("takeSpan", Callable.class);
List<Span> trace = Arrays.asList(takeSpan.call(), takeSpan.call(),
takeSpan.call());
assertThat(trace).allSatisfy(s -> assertThat(s.traceId())
.isEqualTo(trace.get(0).traceId()));
assertThat(trace).isNotNull().extracting(Span::name)
.containsExactlyInAnyOrder("send", "receive", "on-message");
});
}
@Test
public void tracesListener_jcaMessageListener() {
this.contextRunner.withUserConfiguration(JcaJmsListenerConfiguration.class)
@@ -231,12 +211,12 @@ public class JmsTracingConfigurationTest {
SimpleJmsListenerEndpoint endpoint = new SimpleJmsListenerEndpoint();
endpoint.setId("myCustomEndpointId");
endpoint.setDestination("myQueue");
endpoint.setMessageListener(simpleMessageListener(this.current));
endpoint.setMessageListener(mySimpleMessageListener(this.current));
registrar.registerEndpoint(endpoint);
}
@Bean
MessageListener simpleMessageListener(CurrentTraceContext current) {
MessageListener mySimpleMessageListener(CurrentTraceContext current) {
return message -> {
log.info("Got message");
// Didn't restart the trace

View File

@@ -18,8 +18,7 @@ package org.springframework.cloud.sleuth.instrument.messaging;
import brave.Tracing;
import org.apache.kafka.streams.KafkaClientSupplier;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -28,14 +27,12 @@ import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.StreamsBuilderFactoryBean;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Tim te Beek
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SleuthKafkaStreamsConfigurationTest.Config.class,
webEnvironment = WebEnvironment.NONE)
public class SleuthKafkaStreamsConfigurationTest {

View File

@@ -20,9 +20,8 @@ import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.sampler.Sampler;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -37,14 +36,12 @@ import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Spencer Gibb
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TraceContextPropagationChannelInterceptorTests.App.class)
@DirtiesContext
public class TraceContextPropagationChannelInterceptorTests {
@@ -59,7 +56,7 @@ public class TraceContextPropagationChannelInterceptorTests {
@Autowired
private ArrayListSpanReporter reporter;
@After
@AfterEach
public void close() {
this.reporter.clear();
}

View File

@@ -28,8 +28,7 @@ import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.producer.Producer;
import org.aspectj.lang.ProceedingJoinPoint;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
@@ -48,14 +47,12 @@ import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.ProducerFactory;
import org.springframework.kafka.listener.MessageListenerContainer;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TraceMessagingAutoConfigurationTests.Config.class,
webEnvironment = SpringBootTest.WebEnvironment.NONE)
public class TraceMessagingAutoConfigurationTests {

View File

@@ -20,7 +20,7 @@ import java.util.stream.Collectors;
import brave.Span;
import brave.Tracer;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;

View File

@@ -17,8 +17,7 @@
package org.springframework.cloud.sleuth.instrument.messaging.websocket;
import brave.sampler.Sampler;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@@ -27,7 +26,6 @@ import org.springframework.cloud.sleuth.instrument.messaging.TracingChannelInter
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
@@ -38,7 +36,6 @@ import static org.assertj.core.api.BDDAssertions.then;
/**
* @author Marcin Grzejszczak
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TraceWebSocketAutoConfigurationTests.Config.class)
public class TraceWebSocketAutoConfigurationTests {

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -30,7 +30,7 @@
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<version>3.0.0.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2013-2019 the original author or authors.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ https://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
~
~
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-sleuth-instrumentation-zuul-tests</artifactId>
<packaging>jar</packaging>
<name>Spring Cloud Sleuth Zuul Instrumentation Tests</name>
<description>Spring Cloud Sleuth Zuul Instrumentation Tests</description>
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-tests</artifactId>
<version>2.2.2.BUILD-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<properties>
<sonar.skip>true</sonar.skip>
</properties>
<build>
<plugins>
<plugin>
<!--skip deploy -->
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -1,241 +0,0 @@
/*
* Copyright 2013-2019 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.zuul;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import brave.Span;
import brave.Tracer;
import brave.Tracing;
import brave.sampler.Sampler;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ServerList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.assertj.core.api.BDDAssertions;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.StaticServerList;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.discovery.DiscoveryClientRouteLocator;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.BDDAssertions.then;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SampleZuulProxyApplication.class,
properties = { "zuul.routes.simple: /simple/**" },
webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
public class TraceZuulIntegrationTests {
private static final Log log = LogFactory.getLog(TraceZuulIntegrationTests.class);
@Autowired
Tracing tracing;
@Autowired
ArrayListSpanReporter spanAccumulator;
@Autowired
RestTemplate restTemplate;
@Value("${local.server.port}")
private int port;
@Before
@After
public void cleanup() {
this.spanAccumulator.clear();
}
@Test
public void should_close_span_when_routing_to_service_via_discovery() {
Span span = this.tracing.tracer().nextSpan().name("foo").start();
try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span)) {
ResponseEntity<String> result = this.restTemplate.exchange(
"http://localhost:" + this.port + "/simple/foo", HttpMethod.GET,
new HttpEntity<>((Void) null), String.class);
then(result.getStatusCode()).isEqualTo(HttpStatus.OK);
then(result.getBody()).isEqualTo("Hello world");
}
catch (Exception e) {
log.error(e);
throw e;
}
finally {
span.finish();
}
then(this.tracing.tracer().currentSpan()).isNull();
List<zipkin2.Span> spans = this.spanAccumulator.getSpans();
then(spans).isNotEmpty();
everySpanHasTheSameTraceId(spans);
everyParentIdHasItsCorrespondingSpan(spans);
}
@Test
public void should_close_span_when_routing_to_service_via_discovery_to_a_non_existent_url() {
Span span = this.tracing.tracer().nextSpan().name("foo").start();
try (Tracer.SpanInScope ws = this.tracing.tracer().withSpanInScope(span)) {
ResponseEntity<String> result = this.restTemplate.exchange(
"http://localhost:" + this.port + "/simple/nonExistentUrl",
HttpMethod.GET, new HttpEntity<>((Void) null), String.class);
then(result.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
}
finally {
span.finish();
}
then(this.tracing.tracer().currentSpan()).isNull();
List<zipkin2.Span> spans = this.spanAccumulator.getSpans();
then(spans).isNotEmpty();
everySpanHasTheSameTraceId(spans);
everyParentIdHasItsCorrespondingSpan(spans);
}
void everySpanHasTheSameTraceId(List<zipkin2.Span> actual) {
BDDAssertions.assertThat(actual).isNotNull();
List<String> traceIds = actual.stream().map(zipkin2.Span::traceId).distinct()
.collect(toList());
log.info("Stored traceids " + traceIds);
assertThat(traceIds).hasSize(1);
}
void everyParentIdHasItsCorrespondingSpan(List<zipkin2.Span> actual) {
BDDAssertions.assertThat(actual).isNotNull();
List<String> parentSpanIds = actual.stream().map(zipkin2.Span::parentId)
.filter(Objects::nonNull).collect(toList());
List<String> spanIds = actual.stream().map(zipkin2.Span::id).distinct()
.collect(toList());
List<String> difference = new ArrayList<>(parentSpanIds);
difference.removeAll(spanIds);
log.info("Difference between parent ids and span ids " + difference.stream()
.map(span -> "id as hex [" + span + "]").collect(joining("\n")));
assertThat(spanIds).containsAll(parentSpanIds);
}
}
// Don't use @SpringBootApplication because we don't want to component scan
@Configuration
@EnableAutoConfiguration
@RestController
@EnableZuulProxy
@RibbonClient(name = "simple", configuration = SimpleRibbonClientConfiguration.class)
class SampleZuulProxyApplication {
@RequestMapping("/foo")
public String home() {
return "Hello world";
}
@RequestMapping("/exception")
public String exception() {
throw new RuntimeException();
}
@Bean
RouteLocator routeLocator(DiscoveryClient discoveryClient,
ZuulProperties zuulProperties) {
return new MyRouteLocator("/", discoveryClient, zuulProperties);
}
@Bean
ArrayListSpanReporter testSpanReporter() {
return new ArrayListSpanReporter();
}
@Bean
RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(5000);
RestTemplate restTemplate = new RestTemplate(factory);
restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
@Override
public void handleError(ClientHttpResponse response) throws IOException {
}
});
return restTemplate;
}
@Bean
Sampler alwaysSampler() {
return Sampler.ALWAYS_SAMPLE;
}
}
class MyRouteLocator extends DiscoveryClientRouteLocator {
MyRouteLocator(String servletPath, DiscoveryClient discovery,
ZuulProperties properties) {
super(servletPath, discovery, properties);
}
}
// Load balancer with fixed server list for "simple" pointing to localhost
@Configuration
class SimpleRibbonClientConfiguration {
@Value("${local.server.port}")
private int port;
@Bean
public ServerList<Server> ribbonServerList() {
return new StaticServerList<>(new Server("localhost", this.port));
}
}

View File

@@ -1,135 +0,0 @@
/*
* Copyright 2013-2019 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.zuul.issues.issue634;
import java.util.HashSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import brave.Tracing;
import brave.http.HttpTracing;
import brave.sampler.Sampler;
import com.netflix.zuul.ZuulFilter;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.cloud.sleuth.util.ArrayListSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.BDDAssertions.then;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestZuulApplication.class, webEnvironment = RANDOM_PORT,
properties = { "feign.hystrix.enabled=false", "zuul.routes.dp.path:/display/**",
"zuul.routes.dp.path.url: http://localhost:9987/unknown" })
@DirtiesContext
public class Issue634Tests {
@LocalServerPort
int port;
@Autowired
HttpTracing tracer;
@Autowired
TraceCheckingSpanFilter filter;
@Autowired
ArrayListSpanReporter reporter;
@Test
public void should_reuse_custom_feign_client() {
for (int i = 0; i < 15; i++) {
new TestRestTemplate().getForEntity(
"http://localhost:" + this.port + "/display/ddd", String.class);
then(this.tracer.tracing().tracer().currentSpan()).isNull();
}
then(new HashSet<>(this.filter.counter.values()))
.describedAs("trace id should not be reused from thread").hasSize(1);
then(this.reporter.getSpans()).isNotEmpty();
}
}
@EnableZuulProxy
@EnableAutoConfiguration
@Configuration
class TestZuulApplication {
@Bean
TraceCheckingSpanFilter traceCheckingSpanFilter(Tracing tracer) {
return new TraceCheckingSpanFilter(tracer);
}
@Bean
Sampler sampler() {
return Sampler.ALWAYS_SAMPLE;
}
@Bean
ArrayListSpanReporter reporter() {
return new ArrayListSpanReporter();
}
}
class TraceCheckingSpanFilter extends ZuulFilter {
final Map<Long, Integer> counter = new ConcurrentHashMap<>();
private final Tracing tracer;
TraceCheckingSpanFilter(Tracing tracer) {
this.tracer = tracer;
}
@Override
public String filterType() {
return "post";
}
@Override
public int filterOrder() {
return -1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
long trace = this.tracer.tracer().currentSpan().context().traceId();
Integer integer = this.counter.getOrDefault(trace, 0);
this.counter.put(trace, integer + 1);
return null;
}
}

View File

@@ -1,3 +0,0 @@
logging.level.org.springframework.cloud: DEBUG
logging.level.com.netflix.discovery.InstanceInfoReplicator: ERROR
logging.level.org.springframework.cloud.sleuth.instrument.web.client.feign: TRACE