Adapted new configuration to support backwards compatibility in case another tracing system extends from spring-cloud-sleuth-zipkin (like spring-cloud-gcp-trace)
This commit is contained in:
@@ -19,9 +19,7 @@ package org.springframework.cloud.sleuth.zipkin2;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import zipkin2.Span;
|
||||
import zipkin2.codec.BytesEncoder;
|
||||
import zipkin2.reporter.AsyncReporter;
|
||||
import zipkin2.reporter.InMemoryReporterMetrics;
|
||||
import zipkin2.reporter.Reporter;
|
||||
import zipkin2.reporter.ReporterMetrics;
|
||||
import zipkin2.reporter.Sender;
|
||||
@@ -86,18 +84,11 @@ public class ZipkinAutoConfiguration {
|
||||
@Bean(REPORTER_BEAN_NAME)
|
||||
@ConditionalOnMissingBean(name = REPORTER_BEAN_NAME)
|
||||
public Reporter<Span> reporter(ReporterMetrics reporterMetrics,
|
||||
ZipkinProperties zipkin, @Qualifier(SENDER_BEAN_NAME) Sender sender,
|
||||
BytesEncoder<Span> spanBytesEncoder) {
|
||||
ZipkinProperties zipkin, @Qualifier(SENDER_BEAN_NAME) Sender sender) {
|
||||
// historical constraint. Note: AsyncReporter supports memory bounds
|
||||
return AsyncReporter.builder(sender).queuedMaxSpans(1000)
|
||||
.messageTimeout(zipkin.getMessageTimeout(), TimeUnit.SECONDS)
|
||||
.metrics(reporterMetrics).build(spanBytesEncoder);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BytesEncoder<Span> spanBytesEncoder(ZipkinProperties zipkinProperties) {
|
||||
return zipkinProperties.getEncoder();
|
||||
.metrics(reporterMetrics).build(zipkin.getEncoder());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -107,18 +98,6 @@ public class ZipkinAutoConfiguration {
|
||||
return new DefaultZipkinRestTemplateCustomizer(zipkinProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated because this is moved to {@link TraceAutoConfiguration}. Left for
|
||||
* backwards compatibility reasons.
|
||||
* @deprecated
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Deprecated
|
||||
ReporterMetrics zipkinReporterMetrics() {
|
||||
return new InMemoryReporterMetrics();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EndpointLocator.class)
|
||||
@ConditionalOnProperty(value = "spring.zipkin.locator.discovery.enabled", havingValue = "false", matchIfMissing = true)
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* http://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.zipkin2;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import zipkin2.Span;
|
||||
import zipkin2.codec.BytesEncoder;
|
||||
import zipkin2.reporter.AsyncReporter;
|
||||
import zipkin2.reporter.InMemoryReporterMetrics;
|
||||
import zipkin2.reporter.Reporter;
|
||||
import zipkin2.reporter.ReporterMetrics;
|
||||
import zipkin2.reporter.Sender;
|
||||
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationCondition;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
|
||||
* Auto-configuration} that will provide backwards compatibility to be able to support
|
||||
* multiple tracing systems on the classpath.
|
||||
*
|
||||
* Needs to be auto-configured before {@link ZipkinAutoConfiguration} in order to create a
|
||||
* {@link Reporter<Span> span reporter} if needed.
|
||||
*
|
||||
* @author Tim Ysewyn
|
||||
* @since 2.1.0
|
||||
* @see ZipkinAutoConfiguration
|
||||
* @deprecated
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(value = { "spring.sleuth.enabled",
|
||||
"spring.zipkin.enabled" }, matchIfMissing = true)
|
||||
@AutoConfigureAfter({ ZipkinAutoConfiguration.class })
|
||||
@Deprecated
|
||||
public class ZipkinBackwardsCompatibilityAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Reporter that is depending on a {@link Sender} bean which is created in another
|
||||
* auto-configuration than {@link ZipkinAutoConfiguration}.
|
||||
*/
|
||||
@Bean
|
||||
@Conditional(BackwardsCompatibilityCondition.class)
|
||||
@Deprecated
|
||||
public Reporter<Span> reporter(ReporterMetrics reporterMetrics,
|
||||
ZipkinProperties zipkin, BytesEncoder<Span> spanBytesEncoder,
|
||||
DefaultListableBeanFactory beanFactory) {
|
||||
List<String> beanNames = new ArrayList<>(
|
||||
Arrays.asList(beanFactory.getBeanNamesForType(Sender.class)));
|
||||
beanNames.remove(ZipkinAutoConfiguration.SENDER_BEAN_NAME);
|
||||
Sender sender = (Sender) beanFactory.getBean(beanNames.get(0));
|
||||
// historical constraint. Note: AsyncReporter supports memory bounds
|
||||
return AsyncReporter.builder(sender).queuedMaxSpans(1000)
|
||||
.messageTimeout(zipkin.getMessageTimeout(), TimeUnit.SECONDS)
|
||||
.metrics(reporterMetrics).build(spanBytesEncoder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only used for creating a reporter bean with the method above
|
||||
* @deprecated
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Deprecated
|
||||
public BytesEncoder<Span> spanBytesEncoder(ZipkinProperties zipkinProperties) {
|
||||
return zipkinProperties.getEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated because this is moved to {@link TraceAutoConfiguration}. Left for
|
||||
* backwards compatibility reasons.
|
||||
* @deprecated
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Deprecated
|
||||
ReporterMetrics zipkinReporterMetrics() {
|
||||
return new InMemoryReporterMetrics();
|
||||
}
|
||||
|
||||
static class BackwardsCompatibilityCondition extends SpringBootCondition
|
||||
implements ConfigurationCondition {
|
||||
|
||||
@Override
|
||||
public ConfigurationPhase getConfigurationPhase() {
|
||||
return ConfigurationPhase.REGISTER_BEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
Assert.isInstanceOf(DefaultListableBeanFactory.class,
|
||||
context.getBeanFactory());
|
||||
DefaultListableBeanFactory listableBeanFactory = (DefaultListableBeanFactory) context
|
||||
.getBeanFactory();
|
||||
int foundSenders = listableBeanFactory
|
||||
.getBeanNamesForType(Sender.class).length;
|
||||
|
||||
// Previously we supported 1 Sender bean at a time
|
||||
// which could be overridden by another auto-configuration.
|
||||
// Now we support both the overridden bean and our default zipkinSender bean.
|
||||
if (foundSenders < 2) {
|
||||
return ConditionOutcome.noMatch(
|
||||
"We don't support backwards compatibility for more than 2 Sender beans");
|
||||
}
|
||||
int foundReporters = listableBeanFactory
|
||||
.getBeanNamesForType(Reporter.class).length;
|
||||
// Check if we need to provide a Reporter bean for the overridden Sender bean
|
||||
if (foundReporters == foundSenders) {
|
||||
return ConditionOutcome.noMatch(
|
||||
"Both tracing systems already define their own Reporter bean");
|
||||
}
|
||||
return ConditionOutcome.match();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import zipkin2.reporter.kafka11.KafkaSender;
|
||||
@Configuration
|
||||
@ConditionalOnClass(ByteArraySerializer.class)
|
||||
@ConditionalOnBean(KafkaProperties.class)
|
||||
@ConditionalOnMissingBean(Sender.class)
|
||||
@ConditionalOnMissingBean(name = ZipkinAutoConfiguration.SENDER_BEAN_NAME)
|
||||
@Conditional(ZipkinSenderCondition.class)
|
||||
@ConditionalOnProperty(value = "spring.zipkin.sender.type", havingValue = "kafka")
|
||||
class ZipkinKafkaSenderConfiguration {
|
||||
|
||||
@@ -30,7 +30,7 @@ import zipkin2.reporter.amqp.RabbitMQSender;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnBean(CachingConnectionFactory.class)
|
||||
@ConditionalOnMissingBean(Sender.class)
|
||||
@ConditionalOnMissingBean(name = ZipkinAutoConfiguration.SENDER_BEAN_NAME)
|
||||
@Conditional(ZipkinSenderCondition.class)
|
||||
class ZipkinRabbitSenderConfiguration {
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import org.springframework.web.client.RestTemplate;
|
||||
import zipkin2.reporter.Sender;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(Sender.class)
|
||||
@ConditionalOnMissingBean(name = ZipkinAutoConfiguration.SENDER_BEAN_NAME)
|
||||
@Conditional(ZipkinSenderCondition.class)
|
||||
@EnableConfigurationProperties(ZipkinSenderProperties.class)
|
||||
class ZipkinRestTemplateSenderConfiguration {
|
||||
@@ -52,7 +52,6 @@ class ZipkinRestTemplateSenderConfiguration {
|
||||
ZipkinUrlExtractor extractor;
|
||||
|
||||
@Bean(ZipkinAutoConfiguration.SENDER_BEAN_NAME)
|
||||
@ConditionalOnMissingBean(name = ZipkinAutoConfiguration.SENDER_BEAN_NAME)
|
||||
public Sender restTemplateSender(ZipkinProperties zipkin,
|
||||
ZipkinRestTemplateCustomizer zipkinRestTemplateCustomizer) {
|
||||
RestTemplate restTemplate = new ZipkinRestTemplateWrapper(zipkin, this.extractor);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# Auto Configuration
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.sleuth.zipkin2.ZipkinAutoConfiguration
|
||||
org.springframework.cloud.sleuth.zipkin2.ZipkinAutoConfiguration,\
|
||||
org.springframework.cloud.sleuth.zipkin2.ZipkinBackwardsCompatibilityAutoConfiguration
|
||||
@@ -79,7 +79,7 @@ public class ZipkinAutoConfigurationTests {
|
||||
this.server.url("/").toString());
|
||||
this.context.register(ZipkinAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
Config.class);
|
||||
Config.class, ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
Span span = this.context.getBean(Tracing.class).tracer().nextSpan().name("foo")
|
||||
.tag("foo", "bar").start();
|
||||
@@ -106,7 +106,7 @@ public class ZipkinAutoConfigurationTests {
|
||||
environment().setProperty("spring.zipkin.encoder", "JSON_V1");
|
||||
this.context.register(ZipkinAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
Config.class);
|
||||
Config.class, ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
Span span = this.context.getBean(Tracing.class).tracer().nextSpan().name("foo")
|
||||
.tag("foo", "bar").start();
|
||||
@@ -124,9 +124,11 @@ public class ZipkinAutoConfigurationTests {
|
||||
public void overrideRabbitMQQueue() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
environment().setProperty("spring.zipkin.rabbitmq.queue", "zipkin2");
|
||||
environment().setProperty("spring.zipkin.sender.type", "rabbit");
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
RabbitAutoConfiguration.class, ZipkinAutoConfiguration.class,
|
||||
TraceAutoConfiguration.class);
|
||||
TraceAutoConfiguration.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBean(Sender.class)).isInstanceOf(RabbitMQSender.class);
|
||||
@@ -141,7 +143,8 @@ public class ZipkinAutoConfigurationTests {
|
||||
environment().setProperty("spring.zipkin.sender.type", "kafka");
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class,
|
||||
TraceAutoConfiguration.class);
|
||||
TraceAutoConfiguration.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBean(Sender.class)).isInstanceOf(KafkaSender.class);
|
||||
@@ -155,7 +158,8 @@ public class ZipkinAutoConfigurationTests {
|
||||
environment().setProperty("spring.zipkin.sender.type", "web");
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
RabbitAutoConfiguration.class, KafkaAutoConfiguration.class,
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class);
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBean(Sender.class).getClass().getName())
|
||||
@@ -170,7 +174,8 @@ public class ZipkinAutoConfigurationTests {
|
||||
environment().setProperty("spring.zipkin.sender.type", "WEB");
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
RabbitAutoConfiguration.class, KafkaAutoConfiguration.class,
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class);
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBean(Sender.class).getClass().getName())
|
||||
@@ -184,7 +189,8 @@ public class ZipkinAutoConfigurationTests {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(PropertyPlaceholderAutoConfiguration.class,
|
||||
RabbitAutoConfiguration.class, KafkaAutoConfiguration.class,
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class);
|
||||
ZipkinAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBean(Sender.class)).isInstanceOf(RabbitMQSender.class);
|
||||
@@ -199,7 +205,8 @@ public class ZipkinAutoConfigurationTests {
|
||||
this.server.url("/").toString());
|
||||
this.context.register(ZipkinAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
Config.class, MultipleReportersConfig.class);
|
||||
Config.class, MultipleReportersConfig.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBeansOfType(Sender.class)).hasSize(2);
|
||||
@@ -226,12 +233,33 @@ public class ZipkinAutoConfigurationTests {
|
||||
Awaitility.await().untilAsserted(() -> then(sender.isSpanSent()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void supportsMultipleReportersWithBackwardsCompatibilty() throws Exception {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
environment().setProperty("spring.zipkin.base-url",
|
||||
this.server.url("/").toString());
|
||||
this.context.register(ZipkinAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
Config.class, BackwardsCompatibilityConfig.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBeansOfType(Sender.class)).hasSize(2);
|
||||
then(this.context.getBeansOfType(Sender.class))
|
||||
.containsKeys(ZipkinAutoConfiguration.SENDER_BEAN_NAME, "rabbitSender");
|
||||
|
||||
then(this.context.getBeansOfType(Reporter.class)).hasSize(2);
|
||||
then(this.context.getBeansOfType(Reporter.class))
|
||||
.containsKeys(ZipkinAutoConfiguration.REPORTER_BEAN_NAME, "reporter");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldOverrideDefaultBeans() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
this.context.register(ZipkinAutoConfiguration.class,
|
||||
PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class,
|
||||
Config.class, MyConfig.class);
|
||||
Config.class, MyConfig.class,
|
||||
ZipkinBackwardsCompatibilityAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
|
||||
then(this.context.getBeansOfType(Sender.class)).hasSize(1);
|
||||
@@ -337,6 +365,16 @@ public class ZipkinAutoConfigurationTests {
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class BackwardsCompatibilityConfig {
|
||||
|
||||
@Bean
|
||||
Sender rabbitSender() {
|
||||
return RabbitMQSender.create("localhost");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tag::override_default_beans[]
|
||||
|
||||
@Configuration
|
||||
|
||||
Reference in New Issue
Block a user