After this change a custom FeignContext is created that before returning instance or instances of beans will wrap, if necessary, that bean into a tracing representation. That way all the custom Feign configurations will have wrapped beans and tracing will get propagated. Fixes #286
This commit is contained in:
@@ -17,18 +17,10 @@
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
import feign.Client;
|
||||
import feign.Retryer;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.ErrorDecoder;
|
||||
|
||||
/**
|
||||
* Post processor that wraps Feign related classes {@link Decoder},
|
||||
* {@link Retryer}
|
||||
* Post processor that wraps Feign related classes in their tracing representations.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
@@ -36,33 +28,16 @@ import feign.codec.ErrorDecoder;
|
||||
*/
|
||||
final class FeignBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private Tracer tracer;
|
||||
private final BeanFactory beanFactory;
|
||||
private final TraceFeignObjectWrapper traceFeignObjectWrapper;
|
||||
|
||||
FeignBeanPostProcessor(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
FeignBeanPostProcessor(TraceFeignObjectWrapper traceFeignObjectWrapper) {
|
||||
this.traceFeignObjectWrapper = traceFeignObjectWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof Decoder && !(bean instanceof TraceFeignDecoder)) {
|
||||
return new TraceFeignDecoder(getTracer(), (Decoder) bean);
|
||||
} else if (bean instanceof Retryer && !(bean instanceof TraceFeignRetryer)) {
|
||||
return new TraceFeignRetryer(getTracer(), (Retryer) bean);
|
||||
} else if (bean instanceof Client && !(bean instanceof TraceFeignClient)) {
|
||||
return new TraceFeignClient(getTracer(), (Client) bean);
|
||||
} else if (bean instanceof ErrorDecoder && !(bean instanceof TraceFeignErrorDecoder)) {
|
||||
return new TraceFeignErrorDecoder(getTracer(), (ErrorDecoder) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private Tracer getTracer() {
|
||||
if (this.tracer==null) {
|
||||
this.tracer = this.beanFactory.getBean(Tracer.class);
|
||||
}
|
||||
return this.tracer;
|
||||
return this.traceFeignObjectWrapper.wrap(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
import feign.Client;
|
||||
import feign.Feign;
|
||||
import feign.FeignException;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -29,6 +34,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.feign.FeignClientSpecification;
|
||||
import org.springframework.cloud.netflix.feign.FeignContext;
|
||||
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
|
||||
import org.springframework.cloud.netflix.feign.support.SpringDecoder;
|
||||
import org.springframework.cloud.sleuth.SpanInjector;
|
||||
@@ -40,15 +47,10 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
|
||||
import com.netflix.hystrix.HystrixCommand;
|
||||
|
||||
import feign.Client;
|
||||
import feign.Feign;
|
||||
import feign.FeignException;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
@@ -81,12 +83,17 @@ public class TraceFeignClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true)
|
||||
FeignBeanPostProcessor feignBeanPostProcessor(BeanFactory beanFactory) {
|
||||
return new FeignBeanPostProcessor(beanFactory);
|
||||
FeignBeanPostProcessor feignBeanPostProcessor(TraceFeignObjectWrapper traceFeignObjectWrapper) {
|
||||
return new FeignBeanPostProcessor(traceFeignObjectWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
TraceFeignObjectWrapper traceFeignObjectWrapper(BeanFactory beanFactory) {
|
||||
return new TraceFeignObjectWrapper(beanFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
Decoder feignDecoder(final Tracer tracer) {
|
||||
@@ -120,6 +127,17 @@ public class TraceFeignClientAutoConfiguration {
|
||||
return new TraceFeignRequestInterceptor(tracer, feignRequestTemplateInjector());
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<FeignClientSpecification> configurations = new ArrayList<>();
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
FeignContext sleuthFeignContext(TraceFeignObjectWrapper traceFeignObjectWrapper) {
|
||||
FeignContext feignContext = new TraceFeignContext(traceFeignObjectWrapper);
|
||||
feignContext.setConfigurations(this.configurations);
|
||||
return feignContext;
|
||||
}
|
||||
|
||||
private SpanInjector<RequestTemplate> feignRequestTemplateInjector() {
|
||||
return new FeignRequestTemplateInjector();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import org.springframework.cloud.netflix.feign.FeignContext;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Custom FeignContext that wraps beans in custom Feign configurations in their
|
||||
* tracing representations.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public class TraceFeignContext extends FeignContext {
|
||||
|
||||
private final TraceFeignObjectWrapper traceFeignObjectWrapper;
|
||||
|
||||
public TraceFeignContext(TraceFeignObjectWrapper traceFeignObjectWrapper) {
|
||||
this.traceFeignObjectWrapper = traceFeignObjectWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getInstance(String name, Class<T> type) {
|
||||
T object = super.getInstance(name, type);
|
||||
return (T) this.traceFeignObjectWrapper.wrap(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Map<String, T> getInstances(String name, Class<T> type) {
|
||||
Map<String, T> instances = super.getInstances(name, type);
|
||||
Map<String, T> convertedInstances = new HashMap<>();
|
||||
for (Map.Entry<String, T> entry : instances.entrySet()) {
|
||||
convertedInstances.put(entry.getKey(), (T) this.traceFeignObjectWrapper.wrap(entry.getValue()));
|
||||
}
|
||||
return convertedInstances;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import feign.Client;
|
||||
import feign.Retryer;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.ErrorDecoder;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
/**
|
||||
* Class that wraps Feign related classes into their Trace representative
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.1
|
||||
*/
|
||||
final class TraceFeignObjectWrapper {
|
||||
|
||||
private final BeanFactory beanFactory;
|
||||
private Tracer tracer;
|
||||
|
||||
TraceFeignObjectWrapper(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
Object wrap(Object bean) {
|
||||
if (bean instanceof Decoder && !(bean instanceof TraceFeignDecoder)) {
|
||||
return new TraceFeignDecoder(getTracer(), (Decoder) bean);
|
||||
} else if (bean instanceof Retryer && !(bean instanceof TraceFeignRetryer)) {
|
||||
return new TraceFeignRetryer(getTracer(), (Retryer) bean);
|
||||
} else if (bean instanceof Client && !(bean instanceof TraceFeignClient)) {
|
||||
return new TraceFeignClient(getTracer(), (Client) bean);
|
||||
} else if (bean instanceof ErrorDecoder && !(bean instanceof TraceFeignErrorDecoder)) {
|
||||
return new TraceFeignErrorDecoder(getTracer(), (ErrorDecoder) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private Tracer getTracer() {
|
||||
if (this.tracer==null) {
|
||||
this.tracer = this.beanFactory.getBean(Tracer.class);
|
||||
}
|
||||
return this.tracer;
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.netflix.hystrix.exception.HystrixRuntimeException;
|
||||
import com.netflix.loadbalancer.BaseLoadBalancer;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.ErrorDecoder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -34,6 +36,7 @@ import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClient;
|
||||
import org.springframework.cloud.netflix.ribbon.RibbonClients;
|
||||
import org.springframework.cloud.sleuth.Span;
|
||||
import org.springframework.cloud.sleuth.SpanReporter;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
@@ -50,10 +53,9 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import com.netflix.hystrix.exception.HystrixRuntimeException;
|
||||
import com.netflix.loadbalancer.BaseLoadBalancer;
|
||||
import com.netflix.loadbalancer.ILoadBalancer;
|
||||
import com.netflix.loadbalancer.Server;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
@@ -62,23 +64,26 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
*
|
||||
* @author ryarabori
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(
|
||||
classes = { FeignClientServerErrorTests.TestConfiguration.class })
|
||||
@WebIntegrationTest(value = { "spring.application.name=fooservice" }, randomPort = true)
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(
|
||||
classes = {FeignClientServerErrorTests.TestConfiguration.class})
|
||||
@WebIntegrationTest(value = {"spring.application.name=fooservice"}, randomPort = true)
|
||||
public class FeignClientServerErrorTests {
|
||||
|
||||
@Autowired TestFeignInterface feignInterface;
|
||||
@Autowired TestFeignWithCustomConfInterface customConfFeignInterface;
|
||||
@Rule public OutputCapture capture = new OutputCapture();
|
||||
|
||||
@Before public void setup() {
|
||||
@Before
|
||||
public void setup() {
|
||||
ExceptionUtils.setFail(true);
|
||||
}
|
||||
|
||||
@Test public void shouldCloseSpanOnInternalServerError() throws InterruptedException {
|
||||
@Test
|
||||
public void shouldCloseSpanOnInternalServerError() throws InterruptedException {
|
||||
try {
|
||||
this.feignInterface.internalError();
|
||||
}
|
||||
catch (HystrixRuntimeException e) {
|
||||
} catch (HystrixRuntimeException e) {
|
||||
}
|
||||
|
||||
// ugly :/ waiting for rx thread to complete
|
||||
@@ -87,11 +92,11 @@ public class FeignClientServerErrorTests {
|
||||
.doesNotContain("Tried to close span but it is not the current span");
|
||||
}
|
||||
|
||||
@Test public void shouldCloseSpanOnNotFound() throws InterruptedException {
|
||||
@Test
|
||||
public void shouldCloseSpanOnNotFound() throws InterruptedException {
|
||||
try {
|
||||
this.feignInterface.notFound();
|
||||
}
|
||||
catch (HystrixRuntimeException e) {
|
||||
} catch (HystrixRuntimeException e) {
|
||||
}
|
||||
|
||||
// ugly :/ waiting for rx thread to complete
|
||||
@@ -100,26 +105,74 @@ public class FeignClientServerErrorTests {
|
||||
.doesNotContain("Tried to close span but it is not the current span");
|
||||
}
|
||||
|
||||
@Configuration @EnableAutoConfiguration @EnableFeignClients
|
||||
@RibbonClient(value = "fooservice",
|
||||
configuration = SimpleRibbonClientConfiguration.class)
|
||||
@Test
|
||||
public void shouldCloseSpanOnOk() throws InterruptedException {
|
||||
try {
|
||||
this.feignInterface.ok();
|
||||
} catch (HystrixRuntimeException e) {
|
||||
}
|
||||
|
||||
// ugly :/ waiting for rx thread to complete
|
||||
Thread.sleep(100);
|
||||
then(this.capture.toString())
|
||||
.doesNotContain("Tried to close span but it is not the current span");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCloseSpanOnOkWithCustomFeignConfiguration() throws InterruptedException {
|
||||
try {
|
||||
this.customConfFeignInterface.ok();
|
||||
} catch (HystrixRuntimeException e) {
|
||||
}
|
||||
|
||||
// ugly :/ waiting for rx thread to complete
|
||||
Thread.sleep(100);
|
||||
then(this.capture.toString())
|
||||
.doesNotContain("Tried to close span but it is not the current span");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCloseSpanOnNotFoundWithCustomFeignConfiguration() throws InterruptedException {
|
||||
try {
|
||||
this.customConfFeignInterface.notFound();
|
||||
} catch (HystrixRuntimeException e) {
|
||||
}
|
||||
|
||||
// ugly :/ waiting for rx thread to complete
|
||||
Thread.sleep(100);
|
||||
then(this.capture.toString())
|
||||
.doesNotContain("Tried to close span but it is not the current span");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableFeignClients
|
||||
@RibbonClients({@RibbonClient(value = "fooservice",
|
||||
configuration = SimpleRibbonClientConfiguration.class),
|
||||
@RibbonClient(value = "customConfFooService",
|
||||
configuration = SimpleRibbonClientConfiguration.class)})
|
||||
public static class TestConfiguration {
|
||||
|
||||
@Bean FooController fooController() {
|
||||
@Bean
|
||||
FooController fooController() {
|
||||
return new FooController();
|
||||
}
|
||||
|
||||
@Bean Listener listener() {
|
||||
@Bean
|
||||
Listener listener() {
|
||||
return new Listener();
|
||||
}
|
||||
|
||||
@LoadBalanced @Bean public RestTemplate restTemplate() {
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@FeignClient(value = "fooservice") public interface TestFeignInterface {
|
||||
@FeignClient(value = "fooservice")
|
||||
public interface TestFeignInterface {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/internalerror")
|
||||
ResponseEntity<String> internalError();
|
||||
@@ -127,25 +180,56 @@ public class FeignClientServerErrorTests {
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/notfound")
|
||||
ResponseEntity<String> notFound();
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/ok")
|
||||
ResponseEntity<String> ok();
|
||||
}
|
||||
|
||||
@Component public static class Listener implements SpanReporter {
|
||||
@FeignClient(value = "customConfFooService", configuration = CustomFeignClientConfiguration.class)
|
||||
public interface TestFeignWithCustomConfInterface {
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/notfound")
|
||||
ResponseEntity<String> notFound();
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/ok")
|
||||
ResponseEntity<String> ok();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
public static class CustomFeignClientConfiguration {
|
||||
@Bean
|
||||
Decoder decoder() {
|
||||
return new Decoder.Default();
|
||||
}
|
||||
|
||||
@Bean
|
||||
ErrorDecoder errorDecoder() {
|
||||
return new ErrorDecoder.Default();
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
public static class Listener implements SpanReporter {
|
||||
private List<Span> events = new ArrayList<>();
|
||||
|
||||
public List<Span> getEvents() {
|
||||
return this.events;
|
||||
}
|
||||
|
||||
@Override public void report(Span span) {
|
||||
@Override
|
||||
public void report(Span span) {
|
||||
this.events.add(span);
|
||||
}
|
||||
}
|
||||
|
||||
@RestController public static class FooController {
|
||||
@RestController
|
||||
public static class FooController {
|
||||
|
||||
@Autowired Tracer tracer;
|
||||
@Autowired
|
||||
Tracer tracer;
|
||||
|
||||
@RequestMapping("/internalerror") public ResponseEntity<String> internalError(
|
||||
@RequestMapping("/internalerror")
|
||||
public ResponseEntity<String> internalError(
|
||||
@RequestHeader(Span.TRACE_ID_NAME) String traceId,
|
||||
@RequestHeader(Span.SPAN_ID_NAME) String spanId,
|
||||
@RequestHeader(Span.PARENT_ID_NAME) String parentId) {
|
||||
@@ -153,19 +237,31 @@ public class FeignClientServerErrorTests {
|
||||
HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@RequestMapping("/notfound") public ResponseEntity<String> notFound(
|
||||
@RequestMapping("/notfound")
|
||||
public ResponseEntity<String> notFound(
|
||||
@RequestHeader(Span.TRACE_ID_NAME) String traceId,
|
||||
@RequestHeader(Span.SPAN_ID_NAME) String spanId,
|
||||
@RequestHeader(Span.PARENT_ID_NAME) String parentId) {
|
||||
return new ResponseEntity<>("not found", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
@RequestMapping("/ok")
|
||||
public ResponseEntity<String> ok(
|
||||
@RequestHeader(Span.TRACE_ID_NAME) String traceId,
|
||||
@RequestHeader(Span.SPAN_ID_NAME) String spanId,
|
||||
@RequestHeader(Span.PARENT_ID_NAME) String parentId) {
|
||||
return new ResponseEntity<>("ok", HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration public static class SimpleRibbonClientConfiguration {
|
||||
@Configuration
|
||||
public static class SimpleRibbonClientConfiguration {
|
||||
|
||||
@Value("${local.server.port}") private int port = 0;
|
||||
@Value("${local.server.port}")
|
||||
private int port = 0;
|
||||
|
||||
@Bean public ILoadBalancer ribbonLoadBalancer() {
|
||||
@Bean
|
||||
public ILoadBalancer ribbonLoadBalancer() {
|
||||
BaseLoadBalancer balancer = new BaseLoadBalancer();
|
||||
balancer.setServersList(
|
||||
Collections.singletonList(new Server("localhost", this.port)));
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
|
||||
import feign.Client;
|
||||
import feign.Retryer;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.ErrorDecoder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class TraceFeignObjectWrapperTests {
|
||||
|
||||
@Mock Tracer tracer;
|
||||
@Mock BeanFactory beanFactory;
|
||||
@InjectMocks TraceFeignObjectWrapper traceFeignObjectWrapper;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
given(this.beanFactory.getBean(Tracer.class)).willReturn(this.tracer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_wrap_a_decoder_into_trace_decoder() throws Exception {
|
||||
then(this.traceFeignObjectWrapper.wrap(mock(Decoder.class))).isExactlyInstanceOf(TraceFeignDecoder.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_wrap_a_retryer_into_trace_retryer() throws Exception {
|
||||
then(this.traceFeignObjectWrapper.wrap(mock(Retryer.class))).isExactlyInstanceOf(TraceFeignRetryer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_wrap_a_client_into_trace_client() throws Exception {
|
||||
then(this.traceFeignObjectWrapper.wrap(mock(Client.class))).isExactlyInstanceOf(TraceFeignClient.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_wrap_a_error_decoder_into_trace_error_decoder() throws Exception {
|
||||
then(this.traceFeignObjectWrapper.wrap(mock(ErrorDecoder.class))).isExactlyInstanceOf(TraceFeignErrorDecoder.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_not_wrap_a_bean_that_is_not_feign_related() throws Exception {
|
||||
String notFeignRelatedObject = "object";
|
||||
then(this.traceFeignObjectWrapper.wrap(notFeignRelatedObject)).isSameAs(notFeignRelatedObject);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<logger name="org.springframework.cloud.sleuth" level="DEBUG"/>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
<logger name="org.springframework.cloud.sleuth" level="DEBUG"/>
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="FILE" />
|
||||
</root>
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user