diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index c561f204a..4f737f5c7 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -11,7 +11,7 @@ |spring.sleuth.feign.processor.enabled | true | Enable post processor that wraps Feign Context in its tracing representations. |spring.sleuth.grpc.enabled | true | Enable span information propagation when using GRPC. |spring.sleuth.http.enabled | true | -|spring.sleuth.http.legacy.enabled | false | Enables the legacy Sleuth setup. +|spring.sleuth.http.legacy.enabled | false | |spring.sleuth.hystrix.strategy.enabled | true | Enable custom HystrixConcurrencyStrategy that wraps all Callable instances into their Sleuth representative - the TraceCallable. |spring.sleuth.hystrix.strategy.passthrough | false | When enabled the tracing information is passed to the Hystrix execution threads but spans are not created for each execution. |spring.sleuth.integration.enabled | true | Enable Spring Integration sleuth instrumentation. diff --git a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java index b26aede07..764060bd2 100644 --- a/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java +++ b/spring-cloud-sleuth-zipkin/src/main/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfiguration.java @@ -18,6 +18,7 @@ package org.springframework.cloud.sleuth.zipkin2.sender; import java.net.URI; import java.net.URISyntaxException; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -51,6 +52,9 @@ import org.springframework.web.client.RestTemplate; @EnableConfigurationProperties(ZipkinSenderProperties.class) class ZipkinRestTemplateSenderConfiguration { + private static final Log log = LogFactory + .getLog(ZipkinRestTemplateSenderConfiguration.class); + @Autowired ZipkinUrlExtractor extractor; @@ -65,12 +69,60 @@ class ZipkinRestTemplateSenderConfiguration { @Bean ZipkinUrlExtractor zipkinUrlExtractor(final ZipkinLoadBalancer zipkinLoadBalancer) { - return new ZipkinUrlExtractor() { - @Override - public URI zipkinUrl(ZipkinProperties zipkinProperties) { - return zipkinLoadBalancer.instance(); + return new CachingZipkinUrlExtractor(zipkinLoadBalancer); + } + + static class CachingZipkinUrlExtractor implements ZipkinUrlExtractor { + + final AtomicInteger zipkinPort = new AtomicInteger(); + + private final ZipkinLoadBalancer zipkinLoadBalancer; + + CachingZipkinUrlExtractor(ZipkinLoadBalancer zipkinLoadBalancer) { + this.zipkinLoadBalancer = zipkinLoadBalancer; + } + + @Override + public URI zipkinUrl(ZipkinProperties zipkinProperties) { + int cachedZipkinPort = zipkinPort(zipkinProperties); + if (cachedZipkinPort == -1) { + if (log.isDebugEnabled()) { + log.debug("The port in Zipkin's URL [" + zipkinProperties.getBaseUrl() + + "] wasn't provided - that means that load balancing might take place"); + } + return this.zipkinLoadBalancer.instance(); } - }; + if (log.isDebugEnabled()) { + log.debug("The port in Zipkin's URL [" + zipkinProperties.getBaseUrl() + + "] is provided - that means that load balancing will not take place"); + } + return noOpZipkinLoadBalancer(zipkinProperties).instance(); + } + + NoOpZipkinLoadBalancer noOpZipkinLoadBalancer(ZipkinProperties zipkinProperties) { + return new NoOpZipkinLoadBalancer(zipkinProperties); + } + + private int zipkinPort(ZipkinProperties zipkinProperties) { + int cachedZipkinPort = this.zipkinPort.get(); + if (cachedZipkinPort != 0) { + return cachedZipkinPort; + } + return calculatePort(zipkinProperties); + } + + int calculatePort(ZipkinProperties zipkinProperties) { + String baseUrl = zipkinProperties.getBaseUrl(); + URI uri = createUri(baseUrl); + int zipkinPort = uri.getPort(); + this.zipkinPort.set(zipkinPort); + return zipkinPort; + } + + URI createUri(String baseUrl) { + return URI.create(baseUrl); + } + } @Configuration diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfigurationTest.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfigurationTest.java index 2a0e648e4..95c07cc6c 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfigurationTest.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/sender/ZipkinRestTemplateSenderConfigurationTest.java @@ -16,6 +16,9 @@ package org.springframework.cloud.sleuth.zipkin2.sender; +import java.net.URI; +import java.util.concurrent.atomic.AtomicBoolean; + import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -59,6 +62,52 @@ public class ZipkinRestTemplateSenderConfigurationTest { ctxt.close(); } + @Test + public void shouldReturnCachedPortValueIfPresent() { + final AtomicBoolean portCalculated = new AtomicBoolean(); + ZipkinProperties zipkinProperties = new ZipkinProperties(); + ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor extractor = new ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor( + new NoOpZipkinLoadBalancer(zipkinProperties)) { + @Override + int calculatePort(ZipkinProperties zipkinProperties) { + portCalculated.set(true); + return super.calculatePort(zipkinProperties); + } + }; + extractor.zipkinPort.set(9411); + + URI uri = extractor.zipkinUrl(zipkinProperties); + + assertThat(uri.toString()) + .isEqualTo(URI.create(zipkinProperties.getBaseUrl()).toString()); + assertThat(portCalculated).isFalse(); + } + + @Test + public void shouldDelegateToLoadBalancingWhenNoPortPresent() { + ZipkinProperties zipkinProperties = new ZipkinProperties(); + zipkinProperties.setBaseUrl("https://somehostnamewithnoport/endpoint"); + ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor extractor = new ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor( + () -> URI.create("https://example.com")); + + URI uri = extractor.zipkinUrl(zipkinProperties); + + assertThat(uri.toString()) + .isEqualTo(URI.create("https://example.com").toString()); + } + + @Test + public void shouldDelegateToNonLoadBalancingWhenPortPresent() { + ZipkinProperties zipkinProperties = new ZipkinProperties(); + ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor extractor = new ZipkinRestTemplateSenderConfiguration.CachingZipkinUrlExtractor( + () -> URI.create("https://example.com")); + + URI uri = extractor.zipkinUrl(zipkinProperties); + + assertThat(uri.toString()) + .isEqualTo(URI.create(zipkinProperties.getBaseUrl()).toString()); + } + @Configuration @ConditionalOnClass(LoadBalancerClient.class) static class MyDiscoveryClientZipkinUrlExtractorConfiguration {