Ensure that BPP dependencies are not created too early
The FeignBeanPostProcessor was causing other things to misbehave by forcing early instantiation of all its dependencies. One of those is a @MessageEndpoint when Sleuth Stream is in use, and the annotation wasn't being processed because the bean was processed too early.
This commit is contained in:
@@ -61,7 +61,7 @@ public class TraceAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(Tracer.class)
|
||||
public DefaultTracer traceManager(Sampler sampler, Random random,
|
||||
public DefaultTracer sleuthTracer(Sampler sampler, Random random,
|
||||
SpanNamer spanNamer, SpanLogger spanLogger,
|
||||
SpanReporter spanReporter) {
|
||||
return new DefaultTracer(sampler, random, spanNamer, spanLogger,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
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;
|
||||
|
||||
@@ -34,25 +35,33 @@ import feign.codec.Decoder;
|
||||
*/
|
||||
final class FeignBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final Tracer tracer;
|
||||
private Tracer tracer;
|
||||
private final BeanFactory beanFactory;
|
||||
|
||||
FeignBeanPostProcessor(Tracer tracer) {
|
||||
this.tracer = tracer;
|
||||
FeignBeanPostProcessor(BeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
if (bean instanceof Decoder && !(bean instanceof TraceFeignDecoder)) {
|
||||
return new TraceFeignDecoder(this.tracer, (Decoder) bean);
|
||||
return new TraceFeignDecoder(getTracer(), (Decoder) bean);
|
||||
} else if (bean instanceof Retryer && !(bean instanceof TraceFeignRetryer)) {
|
||||
return new TraceFeignRetryer(this.tracer, (Retryer) bean);
|
||||
return new TraceFeignRetryer(getTracer(), (Retryer) bean);
|
||||
} else if (bean instanceof Client && !(bean instanceof TraceFeignClient)) {
|
||||
return new TraceFeignClient(this.tracer, (Client) bean);
|
||||
return new TraceFeignClient(getTracer(), (Client) bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private Tracer getTracer() {
|
||||
if (this.tracer==null) {
|
||||
this.tracer = this.beanFactory.getBean(Tracer.class);
|
||||
}
|
||||
return this.tracer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.cloud.sleuth.instrument.web.client.feign;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
@@ -49,8 +50,8 @@ import feign.Response;
|
||||
import feign.codec.Decoder;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration}
|
||||
* enables span information propagation when using Feign.
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* Auto-configuration} enables span information propagation when using Feign.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
@@ -74,33 +75,44 @@ public class TraceFeignClientAutoConfiguration {
|
||||
return SleuthFeignBuilder.builder(tracer);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true)
|
||||
FeignBeanPostProcessor feignBeanPostProcessor(Tracer tracer) {
|
||||
return new FeignBeanPostProcessor(tracer);
|
||||
@Configuration
|
||||
protected static class FeignBeanPostProcessorConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnProperty(name = "spring.sleuth.feign.processor.enabled", matchIfMissing = true)
|
||||
FeignBeanPostProcessor feignBeanPostProcessor(BeanFactory beanFactory) {
|
||||
return new FeignBeanPostProcessor(beanFactory);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
Decoder feignDecoder(final Tracer tracer) {
|
||||
return new TraceFeignDecoder(tracer, new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) {
|
||||
@Override
|
||||
public Object decode(Response response, Type type)
|
||||
throws IOException, FeignException {
|
||||
FeignRequestContext feignRequestContext = FeignRequestContext.getInstance();
|
||||
FeignResponseHeadersHolder feignResponseHeadersHolder =
|
||||
new FeignResponseHeadersHolder(response.headers());
|
||||
feignResponseHeadersInjector().inject(feignRequestContext.getCurrentSpan(), feignResponseHeadersHolder);
|
||||
return super.decode(Response.create(response.status(),
|
||||
response.reason(), feignResponseHeadersHolder.responseHeaders,
|
||||
response.body()), type);
|
||||
}
|
||||
});
|
||||
return new TraceFeignDecoder(tracer,
|
||||
new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)) {
|
||||
@Override
|
||||
public Object decode(Response response, Type type)
|
||||
throws IOException, FeignException {
|
||||
FeignRequestContext feignRequestContext = FeignRequestContext
|
||||
.getInstance();
|
||||
FeignResponseHeadersHolder feignResponseHeadersHolder = new FeignResponseHeadersHolder(
|
||||
response.headers());
|
||||
feignResponseHeadersInjector().inject(
|
||||
feignRequestContext.getCurrentSpan(),
|
||||
feignResponseHeadersHolder);
|
||||
return super.decode(
|
||||
Response.create(response.status(), response.reason(),
|
||||
feignResponseHeadersHolder.responseHeaders,
|
||||
response.body()),
|
||||
type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sleuth {@link feign.RequestInterceptor} that either starts a new Span
|
||||
* or continues an existing one if a retry takes place.
|
||||
* Sleuth {@link feign.RequestInterceptor} that either starts a new Span or continues
|
||||
* an existing one if a retry takes place.
|
||||
*/
|
||||
@Bean
|
||||
public RequestInterceptor traceIdRequestInterceptor(Tracer tracer) {
|
||||
|
||||
@@ -18,12 +18,10 @@ package org.springframework.cloud.sleuth.log;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.cloud.sleuth.Tracer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@@ -38,7 +36,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnBean(Tracer.class)
|
||||
@ConditionalOnProperty(value="spring.sleuth.enabled", matchIfMissing=true)
|
||||
public class SleuthLogAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -72,7 +72,7 @@ public class SleuthStreamAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StreamSpanListener sleuthTracer(HostLocator endpointLocator,
|
||||
public StreamSpanListener sleuthStreamSpanListener(HostLocator endpointLocator,
|
||||
SpanMetricReporter spanMetricReporter) {
|
||||
return new StreamSpanListener(endpointLocator, spanMetricReporter);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user