diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java index 059ca3b4c..1e9c3dfde 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategy.java @@ -16,21 +16,28 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import java.lang.invoke.MethodHandles; -import java.util.concurrent.Callable; - +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.Span; import org.springframework.cloud.sleuth.TraceKeys; import org.springframework.cloud.sleuth.Tracer; -import com.netflix.hystrix.strategy.HystrixPlugins; -import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; -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 java.lang.invoke.MethodHandles; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * A {@link HystrixConcurrencyStrategy} that wraps a {@link Callable} in a @@ -107,6 +114,33 @@ public class SleuthHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy return new HystrixTraceCallable<>(this.tracer, this.traceKeys, wrappedCallable); } + @Override + public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, + HystrixProperty corePoolSize, + HystrixProperty maximumPoolSize, + HystrixProperty keepAliveTime, TimeUnit unit, + BlockingQueue 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 getBlockingQueue(int maxQueueSize) { + return this.delegate.getBlockingQueue(maxQueueSize); + } + + @Override + public HystrixRequestVariable getRequestVariable( + HystrixRequestVariableLifecycle rv) { + return this.delegate.getRequestVariable(rv); + } + // Visible for testing static class HystrixTraceCallable implements Callable { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java index b949d91bc..429c19a97 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/hystrix/SleuthHystrixConcurrencyStrategyTest.java @@ -16,12 +16,21 @@ package org.springframework.cloud.sleuth.instrument.hystrix; -import java.util.Random; -import java.util.concurrent.Callable; - +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.Span; import org.springframework.cloud.sleuth.TraceKeys; @@ -33,12 +42,10 @@ import org.springframework.cloud.sleuth.trace.DefaultTracer; import org.springframework.cloud.sleuth.util.ArrayListSpanAccumulator; import org.springframework.cloud.sleuth.util.ExceptionUtils; -import com.netflix.hystrix.strategy.HystrixPlugins; -import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy; -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 java.util.Random; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; import static org.springframework.cloud.sleuth.assertions.SleuthAssertions.then; /** @@ -154,6 +161,35 @@ public class SleuthHystrixConcurrencyStrategyTest { .hasATag(asyncKey, "bar"); } + @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.tracer, this.traceKeys); + + 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 {