diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc index cd14619e9..f5daa40ea 100644 --- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc +++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc @@ -68,15 +68,15 @@ Here are the most relevant links from the OpenZipkin Brave project: == Sampling -By default Spring Cloud Sleuth doesn't sample spans. -That means that traces appear in logs but not in any remote store. -For testing the default is often enough, and it probably is all you need if you use only the logs (for example, with an ELK aggregator). -If you export span data to Zipkin, there is also an `Sampler.ALWAYS_SAMPLE` setting that exports everything, `RateLimitingSampler` setting that samples X transactions per second (defaults to `1000`) or `ProbabilityBasedSampler` setting that samples a fixed fraction of spans. +Sampling only applies to tracing backends, such as Zipkin. Trace IDs appear in logs regardless of +sample rate. Sampling is a way to prevent overloading the system, by consistently tracing some, but +not all requests. -NOTE: The `RateLimitingSampler` is the default if you use `spring-cloud-sleuth-zipkin`. -You can configure the rate limit by setting `spring.sleuth.sampler.rate`. +The default rate of 10 traces per second is controlled by the `spring.sleuth.sampler.rate` +property and applies when we know Sleuth is used for reasons besides logging. Use a rate above 100 +traces per second with extreme caution as it can overload your tracing system. -A sampler can be installed by creating a bean definition, as shown in the following example: +The sampler can be set by Java Config also, as shown in the following example: [source,java] ---- @@ -86,8 +86,6 @@ include::{project-root}/spring-cloud-sleuth-core/src/test/java/org/springframewo TIP: You can set the HTTP header `b3` to `1`, or, when doing messaging, you can set the `spanFlags` header to `1`. Doing so forces the current request to be sampled regardless of configuration. -In order to use the rate-limited sampler set the `spring.sleuth.sampler.rate` property to choose an amount of traces to accept on a per-second interval. The minimum number is 0 and the max is 2,147,483,647 (max int). - == Baggage Baggage are fields that are propagated with the trace, optionally out of process. You can use properties to define fields that have no special configuration such as name mapping: diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java index d3d71d265..f089cfb76 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfiguration.java @@ -42,7 +42,6 @@ import zipkin2.reporter.ReporterMetrics; import zipkin2.reporter.metrics.micrometer.MicrometerReporterMetrics; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -52,7 +51,7 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.cloud.sleuth.DefaultSpanNamer; import org.springframework.cloud.sleuth.LocalServiceName; import org.springframework.cloud.sleuth.SpanNamer; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; +import org.springframework.cloud.sleuth.baggage.TraceBaggageConfiguration; import org.springframework.cloud.sleuth.sampler.SamplerAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -72,8 +71,7 @@ import org.springframework.util.StringUtils; @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true) @EnableConfigurationProperties(SleuthProperties.class) -@AutoConfigureAfter(TraceBaggageAutoConfiguration.class) -@Import(SamplerAutoConfiguration.class) +@Import({ TraceBaggageConfiguration.class, SamplerAutoConfiguration.class }) public class TraceAutoConfiguration { /** diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfiguration.java similarity index 56% rename from spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfiguration.java rename to spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfiguration.java index 1279926fd..92f59bded 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfiguration.java @@ -38,20 +38,20 @@ import org.apache.commons.logging.LogFactory; import org.slf4j.MDC; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; 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.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; /** - * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration - * Auto-configuration} for {@link BaggagePropagation}. + * {@link Configuration} for {@link BaggagePropagation}. *

* * @author Spencer Gibb @@ -59,12 +59,43 @@ import org.springframework.context.annotation.Configuration; * @since 2.0.0 */ @Configuration(proxyBeanMethods = false) -@ConditionalOnProperty(value = "spring.sleuth.enabled", matchIfMissing = true) -@AutoConfigureBefore(TraceAutoConfiguration.class) @EnableConfigurationProperties(SleuthBaggageProperties.class) -public class TraceBaggageAutoConfiguration { +public class TraceBaggageConfiguration { - static final Log logger = LogFactory.getLog(TraceBaggageAutoConfiguration.class); + static final Log logger = LogFactory.getLog(TraceBaggageConfiguration.class); + + static final String LOCAL_KEYS = "spring.sleuth.local-keys"; + static final String BAGGAGE_KEYS = "spring.sleuth.baggage-keys"; + static final String PROPAGATION_KEYS = "spring.sleuth.propagation-keys"; + static final String WHITELISTED_KEYS = "spring.sleuth.propagation.tag.whitelisted-keys"; + static final String WHITELISTED_MDC_KEYS = "spring.sleuth.log.slf4j.whitelisted-mdc-keys"; + + // These List beans allow us to get deprecated property values, regardless of + // if they were comma or yaml encoded. This keeps them out of SleuthBaggageProperties + + @Bean(BAGGAGE_KEYS) + @ConfigurationProperties(BAGGAGE_KEYS) + List baggageKeys() { + return new ArrayList<>(); + } + + @Bean(LOCAL_KEYS) + @ConfigurationProperties(LOCAL_KEYS) + List localKeys() { + return new ArrayList<>(); + } + + @Bean(PROPAGATION_KEYS) + @ConfigurationProperties(PROPAGATION_KEYS) + List propagationKeys() { + return new ArrayList<>(); + } + + @Bean(WHITELISTED_MDC_KEYS) + @ConfigurationProperties(WHITELISTED_MDC_KEYS) + List whiteListedMDCKeys() { + return new ArrayList<>(); + } @Autowired(required = false) List baggagePropagationCustomizers = new ArrayList<>(); @@ -92,35 +123,31 @@ public class TraceBaggageAutoConfiguration { @ConditionalOnMissingBean Propagation.Factory sleuthPropagation( BaggagePropagation.FactoryBuilder factoryBuilder, - @Value("${spring.sleuth.baggage-keys:}") String baggageKeys, - @Value("${spring.sleuth.local-keys:}") String localKeys, - @Value("${spring.sleuth.propagation-keys:}") String propagationKeys, + @Qualifier(BAGGAGE_KEYS) List baggageKeys, + @Qualifier(LOCAL_KEYS) List localKeys, + @Qualifier(PROPAGATION_KEYS) List propagationKeys, SleuthBaggageProperties sleuthBaggageProperties) { - Set localFields = redirectOldPropertyToNew("spring.sleuth.local-keys", - collectFieldsFromProperty(localKeys), + Set localFields = redirectOldPropertyToNew(LOCAL_KEYS, localKeys, "spring.sleuth.baggage.local-fields", sleuthBaggageProperties.getLocalFields()); for (String fieldName : localFields) { factoryBuilder.add(SingleBaggageField.local(BaggageField.create(fieldName))); } - Set remoteFields = redirectOldPropertyToNew( - "spring.sleuth.propagation-keys", - collectFieldsFromProperty(propagationKeys), - "spring.sleuth.baggage.remote-fields", + Set remoteFields = redirectOldPropertyToNew(PROPAGATION_KEYS, + propagationKeys, "spring.sleuth.baggage.remote-fields", sleuthBaggageProperties.getRemoteFields()); for (String fieldName : remoteFields) { factoryBuilder.add(SingleBaggageField.remote(BaggageField.create(fieldName))); } if (!baggageKeys.isEmpty()) { - logger.warn( - "'spring.sleuth.baggage-keys' will be removed in a future release.\n" - + "To change header names define a @Bean of type " - + SingleBaggageField.class.getName()); + logger.warn("'" + BAGGAGE_KEYS + "' will be removed in a future release.\n" + + "To change header names define a @Bean of type " + + SingleBaggageField.class.getName()); - for (String key : collectFieldsFromProperty(baggageKeys)) { + for (String key : baggageKeys) { factoryBuilder.add(SingleBaggageField.newBuilder(BaggageField.create(key)) .addKeyName("baggage-" + key) // for HTTP .addKeyName("baggage_" + key) // for messaging @@ -134,26 +161,7 @@ public class TraceBaggageAutoConfiguration { return factoryBuilder.build(); } - @Bean - FinishedSpanHandler baggageTagFinishedSpanHandler( - @Value("${spring.sleuth.propagation.tag.whitelisted-keys:}") String whitelistedKeys, - SleuthBaggageProperties sleuthBaggageProperties) { - - Set tagFields = redirectOldPropertyToNew( - "spring.sleuth.propagation.tag.whitelisted-keys", - collectFieldsFromProperty(whitelistedKeys), - "spring.sleuth.baggage.tag-fields", - sleuthBaggageProperties.getTagFields()); - - if (tagFields.isEmpty()) { - return FinishedSpanHandler.NOOP; // Brave ignores these - } - - return new BaggageTagFinishedSpanHandler(tagFields.stream() - .map(BaggageField::create).toArray(BaggageField[]::new)); - } - - static Set redirectOldPropertyToNew(String oldProperty, Set oldValue, + static Set redirectOldPropertyToNew(String oldProperty, List oldValue, String newProperty, List newValue) { Set result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); result.addAll(newValue); @@ -178,13 +186,11 @@ public class TraceBaggageAutoConfiguration { @ConditionalOnProperty(value = "spring.sleuth.baggage.correlation-enabled", matchIfMissing = true) ScopeDecorator correlationScopeDecorator( - @Value("${spring.sleuth.log.slf4j.whitelisted-mdc-keys:}") String whitelistedKeys, + @Qualifier(WHITELISTED_MDC_KEYS) List whiteListedMDCKeys, SleuthBaggageProperties sleuthBaggageProperties) { - Set correlationFields = redirectOldPropertyToNew( - "spring.sleuth.log.slf4j.whitelisted-mdc-keys", - collectFieldsFromProperty(whitelistedKeys), - "spring.sleuth.baggage.correlation-fields", + Set correlationFields = redirectOldPropertyToNew(WHITELISTED_MDC_KEYS, + whiteListedMDCKeys, "spring.sleuth.baggage.correlation-fields", sleuthBaggageProperties.getCorrelationFields()); // Add fields from properties @@ -201,19 +207,74 @@ public class TraceBaggageAutoConfiguration { return builder.build(); } - static Set collectFieldsFromProperty(String value) { - Set result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); - for (String fieldName : value.split(",")) { - if (fieldName == null) { - continue; - } - fieldName = fieldName.trim(); - if (fieldName.isEmpty()) { - continue; - } - result.add(fieldName); + /** + * This has to be conditional as it creates a bean of type + * {@link FinishedSpanHandler}. + * + *

+ * {@link FinishedSpanHandler} beans, even if {@link FinishedSpanHandler#NOOP}, can + * trigger {@code org.springframework.cloud.sleuth.sampler.SamplerCondition} + */ + @Configuration + @Conditional(BaggageTagFinishedSpanHandlerCondition.class) + @EnableConfigurationProperties(SleuthBaggageProperties.class) + static class BaggageTagFinishedSpanHandlerConfiguration { + + @Bean(WHITELISTED_KEYS) + @ConfigurationProperties(WHITELISTED_KEYS) + List whiteListedKeys() { + return new ArrayList<>(); } - return result; + + @Bean + FinishedSpanHandler baggageTagFinishedSpanHandler( + @Qualifier(WHITELISTED_KEYS) List whiteListedKeys, + SleuthBaggageProperties sleuthBaggageProperties) { + + Set tagFields = redirectOldPropertyToNew(WHITELISTED_KEYS, + whiteListedKeys, "spring.sleuth.baggage.tag-fields", + sleuthBaggageProperties.getTagFields()); + + if (tagFields.isEmpty()) { + return FinishedSpanHandler.NOOP; // Brave ignores these + } + + return new BaggageTagFinishedSpanHandler(tagFields.stream() + .map(BaggageField::create).toArray(BaggageField[]::new)); + } + + } + + /** + * We need a special condition as it users could use either comma or yaml encoding, + * possibly with a deprecated prefix. + */ + static class BaggageTagFinishedSpanHandlerCondition extends AnyNestedCondition { + + BaggageTagFinishedSpanHandlerCondition() { + super(ConfigurationPhase.PARSE_CONFIGURATION); + } + + @ConditionalOnProperty("spring.sleuth.baggage.tag-fields") + static class TagFieldsProperty { + + } + + @ConditionalOnProperty("spring.sleuth.baggage.tag-fields[0]") + static class TagFieldsYamlListProperty { + + } + + @ConditionalOnProperty(WHITELISTED_KEYS) + static class WhitelistedKeysProperty { + + } + + @ConditionalOnProperty(WHITELISTED_KEYS + "[0]") + static class WhitelistedKeysYamlListProperty { + + } + } } diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfiguration.java index 25270732d..473fbdd5e 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfiguration.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.sleuth.sampler; +import brave.sampler.CountingSampler; import brave.sampler.Sampler; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; @@ -23,12 +24,14 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; /** * {@linkplain Configuration configuration} for {@link Sampler}. * * @author Marcin Grzejszczak + * @see SamplerCondition * @since 2.1.0 */ @Configuration(proxyBeanMethods = false) @@ -44,14 +47,17 @@ public class SamplerAutoConfiguration { return Sampler.NEVER_SAMPLE; } + // NOTE: Brave's default samplers return Sampler.NEVER_SAMPLE if the config implies + // that static Sampler samplerFromProps(SamplerProperties config) { if (config.getProbability() != null) { - return new ProbabilityBasedSampler(config); + return CountingSampler.create(config.getProbability()); } - return new RateLimitingSampler(config); + return brave.sampler.RateLimitingSampler.create(config.getRate()); } @Configuration(proxyBeanMethods = false) + @Conditional(SamplerCondition.class) @ConditionalOnBean( type = "org.springframework.cloud.context.scope.refresh.RefreshScope") protected static class RefreshScopedSamplerConfiguration { @@ -60,12 +66,18 @@ public class SamplerAutoConfiguration { @RefreshScope @ConditionalOnMissingBean public Sampler defaultTraceSampler(SamplerProperties config) { - return samplerFromProps(config); + // TODO: Rewrite: refresh should replace the sampler, not change its state + // internally + if (config.getProbability() != null) { + return new ProbabilityBasedSampler(config); + } + return new RateLimitingSampler(config); } } @Configuration(proxyBeanMethods = false) + @Conditional(SamplerCondition.class) @ConditionalOnMissingBean( type = "org.springframework.cloud.context.scope.refresh.RefreshScope") protected static class NonRefreshScopeSamplerConfiguration { diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerCondition.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerCondition.java new file mode 100644 index 000000000..77c6164d9 --- /dev/null +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/sampler/SamplerCondition.java @@ -0,0 +1,82 @@ +/* + * 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 + * + * https://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.sampler; + +import brave.TracingCustomizer; +import brave.handler.FinishedSpanHandler; +import brave.sampler.Sampler; + +import org.springframework.boot.autoconfigure.condition.AnyNestedCondition; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; + +/** + * Sleuth 1.x optimized for log-correlation only. Unless "spring-cloud-sleuth-zipkin" was + * present, the sampler defaulted to {@link Sampler#NEVER_SAMPLE}. This was to ensure the + * log only nodes never set the sampled flag. + * + *

+ * "spring-cloud-sleuth-zipkin" obviated the {@link Sampler#NEVER_SAMPLE} default by + * importing {@link SamplerAutoConfiguration}. Nothing else did, so sampling properties + * were effectively ignored unless "spring-cloud-sleuth-zipkin" was in use, or something + * else similarly imported {@link SamplerAutoConfiguration}. + * + *

+ * During a review of Wavefront integration, it was considered not correct to have other + * code import {@link SamplerAutoConfiguration}. To avoid that, retain the old behaviour + * about log only nodes, and also not pin configuration to Zipkin involves a more complex + * condition. + * + *

+ * This condition looks for signs of non-default setup which likely requires sampling + * configuration. It passes on one of the following beans exist: + * + *

+ *

+ * + *

+ * An integrated test that shows {@link Sampler#NEVER_SAMPLE} is default on fail exists in + * {@code TraceAutoConfigurationTests} intentionally, as users now needn't import + * {@link SamplerAutoConfiguration} directly. + */ +final class SamplerCondition extends AnyNestedCondition { + + SamplerCondition() { + super(ConfigurationPhase.REGISTER_BEAN); + } + + // zipkin2.reporter.Reporter is in the classpath here, but technically it is optional + @ConditionalOnBean(type = "zipkin2.reporter.Reporter") + static final class ReporterAvailable { + + } + + @ConditionalOnBean(FinishedSpanHandler.class) + static final class FinishedSpanHandlerAvailable { + + } + + @ConditionalOnBean(TracingCustomizer.class) + static final class TracingCustomizerAvailable { + + } + +} diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories index 8225a7b06..94c730542 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories @@ -1,7 +1,6 @@ # Auto Configuration org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.sleuth.annotation.SleuthAnnotationAutoConfiguration,\ -org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration,\ org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration,\ org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration,\ diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationCustomizersTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationCustomizersTests.java index 1b39e7633..b384abf97 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationCustomizersTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationCustomizersTests.java @@ -29,7 +29,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.cloud.sleuth.instrument.messaging.TraceMessagingAutoConfiguration; import org.springframework.cloud.sleuth.instrument.rpc.TraceRpcAutoConfiguration; import org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration; @@ -44,8 +43,8 @@ public class TraceAutoConfigurationCustomizersTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceWebAutoConfiguration.class, - TraceHttpAutoConfiguration.class, TraceRpcAutoConfiguration.class, + TraceWebAutoConfiguration.class, TraceHttpAutoConfiguration.class, + TraceRpcAutoConfiguration.class, FakeSpringMessagingAutoConfiguration.class, TraceMessagingAutoConfiguration.class)) .withUserConfiguration(Customizers.class); diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationPropagationCustomizationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationPropagationCustomizationTests.java index 98c1e35f7..2428cf916 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationPropagationCustomizationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationPropagationCustomizationTests.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.cloud.sleuth.instrument.web.TraceHttpAutoConfiguration; import org.springframework.cloud.sleuth.instrument.web.TraceWebAutoConfiguration; import org.springframework.context.annotation.Bean; @@ -36,8 +35,7 @@ import org.springframework.context.support.GenericApplicationContext; public class TraceAutoConfigurationPropagationCustomizationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class)); @Test public void stillCreatesDefault() { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTests.java index df57188e7..cef306f1a 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationTests.java @@ -26,11 +26,14 @@ import brave.baggage.BaggagePropagationCustomizer; import brave.propagation.B3SinglePropagation; import brave.propagation.Propagation; import brave.propagation.TraceContextOrSamplingFlags; +import brave.sampler.RateLimitingSampler; +import brave.sampler.Sampler; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.simple.SimpleMeterRegistry; import org.assertj.core.api.BDDAssertions; import org.junit.jupiter.api.Test; import zipkin2.reporter.InMemoryReporterMetrics; +import zipkin2.reporter.Reporter; import zipkin2.reporter.ReporterMetrics; import zipkin2.reporter.metrics.micrometer.MicrometerReporterMetrics; @@ -38,18 +41,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; public class TraceAutoConfigurationTests { private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class)); @Test - public void should_apply_micrometer_reporter_metrics_when_meter_registry_bean_present() { + void should_apply_micrometer_reporter_metrics_when_meter_registry_bean_present() { this.contextRunner.withUserConfiguration(WithMeterRegistry.class) .run((context) -> { ReporterMetrics bean = context.getBean(ReporterMetrics.class); @@ -60,7 +61,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_apply_in_memory_metrics_when_meter_registry_bean_missing() { + void should_apply_in_memory_metrics_when_meter_registry_bean_missing() { this.contextRunner.run((context) -> { ReporterMetrics bean = context.getBean(ReporterMetrics.class); @@ -69,7 +70,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_apply_in_memory_metrics_when_meter_registry_class_missing() { + void should_apply_in_memory_metrics_when_meter_registry_class_missing() { this.contextRunner.withClassLoader(new FilteredClassLoader(MeterRegistry.class)) .run((context) -> { ReporterMetrics bean = context.getBean(ReporterMetrics.class); @@ -78,8 +79,48 @@ public class TraceAutoConfigurationTests { }); } + /** + * Duplicates + * {@link org.springframework.cloud.sleuth.sampler.SamplerAutoConfigurationTests} + * intentionally, to ensure configuration condition bugs do not exist. + */ @Test - public void should_use_B3Propagation_factory_if_no_have_any_config() { + void should_use_NEVER_SAMPLER_when_only_logging() { + this.contextRunner.run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isSameAs(Sampler.NEVER_SAMPLE); + })); + } + + /** + * Duplicates + * {@link org.springframework.cloud.sleuth.sampler.SamplerAutoConfigurationTests} + * intentionally, to ensure configuration condition bugs do not exist. + */ + @Test + void should_use_RateLimitedSampler_when_reporting() { + this.contextRunner.withUserConfiguration(WithReporter.class).run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isInstanceOf(RateLimitingSampler.class); + })); + } + + /** + * Duplicates + * {@link org.springframework.cloud.sleuth.sampler.SamplerAutoConfigurationTests} + * intentionally, to ensure configuration condition bugs do not exist. + */ + @Test + void should_override_sampler() { + this.contextRunner.withUserConfiguration(WithReporter.class, WithSampler.class) + .run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isSameAs(Sampler.ALWAYS_SAMPLE); + })); + } + + @Test + void should_use_B3Propagation_factory_by_default() { this.contextRunner.run((context -> { final Propagation.Factory bean = context.getBean(Propagation.Factory.class); BDDAssertions.then(bean).isInstanceOf(Propagation.Factory.class); @@ -87,7 +128,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_use_baggageBean() { + void should_use_baggageBean() { this.contextRunner.withUserConfiguration(WithBaggageBeans.class, Baggage.class) .run((context -> { final Baggage bean = context.getBean(Baggage.class); @@ -98,7 +139,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_use_local_keys_from_properties() { + void should_use_local_keys_from_properties() { this.contextRunner.withPropertyValues("spring.sleuth.baggage.local-fields=bp") .withUserConfiguration(Baggage.class).run((context -> { final Baggage bean = context.getBean(Baggage.class); @@ -108,7 +149,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_combine_baggage_beans_and_properties() { + void should_combine_baggage_beans_and_properties() { this.contextRunner.withPropertyValues("spring.sleuth.baggage.local-fields=bp") .withUserConfiguration(WithBaggageBeans.class, Baggage.class) .run((context -> { @@ -121,7 +162,7 @@ public class TraceAutoConfigurationTests { } @Test - public void should_use_baggagePropagationFactoryBuilder_bean() { + void should_use_baggagePropagationFactoryBuilder_bean() { // BaggagePropagation.FactoryBuilder unwraps itself if there are no baggage fields // defined this.contextRunner @@ -174,6 +215,36 @@ public class TraceAutoConfigurationTests { } + @Configuration + static class WithReporter { + + @Bean + Reporter spanReporter() { + return zipkin2.Span::toString; + } + + } + + @Configuration + static class WithSampler { + + @Bean + Sampler alwaysSampler() { + return Sampler.ALWAYS_SAMPLE; + } + + } + + @Configuration + static class WithLocalKeys { + + @Bean + MeterRegistry meterRegistry() { + return new SimpleMeterRegistry(); + } + + } + @Configuration static class WithBaggagePropagationFactoryBuilderBean { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java index c407fe242..2fcc7e8ab 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/autoconfig/TraceAutoConfigurationWithDisabledSleuthTests.java @@ -16,8 +16,6 @@ package org.springframework.cloud.sleuth.autoconfig; -import java.security.SecureRandom; - import brave.Tracing; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -25,22 +23,22 @@ import org.assertj.core.api.BDDAssertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.system.CapturedOutput; import org.springframework.boot.test.system.OutputCaptureExtension; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ActiveProfiles; -@SpringBootTest(classes = TraceAutoConfigurationWithDisabledSleuthTests.Config.class, - properties = "spring.sleuth.enabled=false", - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest( + // WebEnvironment.NONE will not read a Yaml profile + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = TraceAutoConfigurationWithDisabledSleuthTests.Config.class) @ActiveProfiles("disabled") -@DirtiesContext @ExtendWith(OutputCaptureExtension.class) public class TraceAutoConfigurationWithDisabledSleuthTests { @@ -50,6 +48,10 @@ public class TraceAutoConfigurationWithDisabledSleuthTests { @Autowired(required = false) Tracing tracing; + @Autowired + @Value("${spring.application.name:}") + String applicationName; + @Test public void shouldStartContext() { BDDAssertions.then(this.tracing).isNull(); @@ -59,6 +61,12 @@ public class TraceAutoConfigurationWithDisabledSleuthTests { public void shouldNotContainAnyTracingInfoInTheLogs(CapturedOutput capture) { log.info("hello"); + assertThat(applicationName).isEqualTo("foo"); // prove bootstrap-disabled.yml + // loaded + + // spring.application.name is put in the log format by + // TraceEnvironmentPostProcessor + // checking for the service name here ensures this isn't accidentally loaded BDDAssertions.then(capture.toString()).doesNotContain("[foo"); } @@ -66,27 +74,6 @@ public class TraceAutoConfigurationWithDisabledSleuthTests { @Configuration static class Config { - @Bean - public FactoryBean secureRandom() { - return new FactoryBean() { - - @Override - public SecureRandom getObject() throws Exception { - return new SecureRandom(); - } - - @Override - public Class getObjectType() { - return SecureRandom.class; - } - - @Override - public boolean isSingleton() { - return true; - } - }; - } - } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/BaggageTagFinishedSpanHandlerTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/BaggageTagFinishedSpanHandlerTest.java index b0c0c44de..7f7c67af1 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/BaggageTagFinishedSpanHandlerTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/BaggageTagFinishedSpanHandlerTest.java @@ -23,26 +23,27 @@ import brave.ScopedSpan; import brave.Tracer; import brave.baggage.BaggageField; import brave.propagation.TraceContext; -import brave.sampler.Sampler; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.sleuth.util.ArrayListSpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ActiveProfiles; import static org.assertj.core.api.Assertions.assertThat; /** * @author Taras Danylchuk */ -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { "spring.profiles.active=baggage" }, // intentionally test yaml - classes = BaggageTagFinishedSpanHandlerTest.TestConfiguration.class) +@SpringBootTest( + // WebEnvironment.NONE will not read a Yaml profile + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = BaggageTagFinishedSpanHandlerTest.Config.class) +@ActiveProfiles("baggage") // application-baggage.yml public class BaggageTagFinishedSpanHandlerTest { static final BaggageField COUNTRY_CODE = BaggageField.create("country-code"); @@ -76,22 +77,15 @@ public class BaggageTagFinishedSpanHandlerTest { assertThat(tags).containsEntry(COUNTRY_CODE.name(), "FO"); } - @Configuration @EnableAutoConfiguration - @EnableConfigurationProperties(SleuthBaggageProperties.class) - public static class TestConfiguration { + @Configuration + static class Config { @Bean - public ArrayListSpanReporter arrayListSpanReporter( - SleuthBaggageProperties properties) { + ArrayListSpanReporter spanReporter() { return new ArrayListSpanReporter(); } - @Bean - public Sampler alwaysSampler() { - return Sampler.ALWAYS_SAMPLE; - } - } } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfigurationTests.java similarity index 90% rename from spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfigurationTests.java rename to spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfigurationTests.java index ed749cdb3..52f66aa3a 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/baggage/TraceBaggageConfigurationTests.java @@ -46,13 +46,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.assertj.core.api.InstanceOfAssertFactories.array; -public class TraceBaggageAutoConfigurationTests { +public class TraceBaggageConfigurationTests { static final String[] EMPTY_ARRAY = {}; private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration( - AutoConfigurations.of(TraceBaggageAutoConfiguration.class)); + .withConfiguration(AutoConfigurations.of(TraceBaggageConfiguration.class)); @Test public void shouldCreateLocalFields() { @@ -125,6 +124,16 @@ public class TraceBaggageAutoConfigurationTests { .containsOnly("x-vcap-request-id", "country-code")); } + @Test + public void shouldCreateTagHandler_yaml() { + this.contextRunner + .withPropertyValues( + "spring.sleuth.baggage.tag-fields[0]=x-vcap-request-id", + "spring.sleuth.baggage.tag-fields[1]=country-code") + .run((context) -> assertThatFieldNamesToTag(context) + .containsOnly("x-vcap-request-id", "country-code")); + } + @Test public void shouldCreateTagHandler_oldProperty() { this.contextRunner.withPropertyValues( @@ -133,6 +142,15 @@ public class TraceBaggageAutoConfigurationTests { .containsOnly("x-vcap-request-id", "country-code")); } + @Test + public void shouldCreateTagHandler_oldProperty_yaml() { + this.contextRunner.withPropertyValues( + "spring.sleuth.propagation.tag.whitelisted-keys[0]=x-vcap-request-id", + "spring.sleuth.propagation.tag.whitelisted-keys[1]=country-code") + .run((context) -> assertThatFieldNamesToTag(context) + .containsOnly("x-vcap-request-id", "country-code")); + } + static AbstractListAssert, String, ObjectAssert> assertThatFieldNamesToTag( AssertableApplicationContext context) { return assertThat(context.getBean(FinishedSpanHandler.class)) diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rpc/TraceRpcAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rpc/TraceRpcAutoConfigurationTests.java index 0ae7b6b3d..8892783b7 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rpc/TraceRpcAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/rpc/TraceRpcAutoConfigurationTests.java @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -78,8 +77,6 @@ public class TraceRpcAutoConfigurationTests { private ApplicationContextRunner contextRunner(String... propertyValues) { return new ApplicationContextRunner().withPropertyValues(propertyValues) .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, - TraceRpcAutoConfiguration.class, TraceRpcAutoConfiguration.class)); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java index b3aa11894..88e077b7a 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/SkipPatternProviderConfigTest.java @@ -41,7 +41,6 @@ import org.springframework.boot.context.annotation.UserConfigurations; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Configuration; @@ -58,8 +57,7 @@ public class SkipPatternProviderConfigTest { InfoEndpointAutoConfiguration.class, HealthEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceAutoConfiguration.class, - TraceWebAutoConfiguration.class)); + TraceAutoConfiguration.class, TraceWebAutoConfiguration.class)); @Test public void should_return_null_when_cleared() throws Exception { diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfigurationTests.java index 2f4162cb3..79b07d241 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceHttpAutoConfigurationTests.java @@ -29,7 +29,6 @@ import org.springframework.boot.test.context.assertj.AssertableApplicationContex import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ContextConsumer; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -195,7 +194,6 @@ public class TraceHttpAutoConfigurationTests { private ApplicationContextRunner contextRunner(String... propertyValues) { return new ApplicationContextRunner().withPropertyValues(propertyValues) .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceHttpAutoConfiguration.class, TraceWebAutoConfiguration.class)); } diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfigurationTests.java index edaa8d2fc..c9cf66dee 100644 --- a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfigurationTests.java +++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/sampler/SamplerAutoConfigurationTests.java @@ -16,44 +16,170 @@ package org.springframework.cloud.sleuth.sampler; +import brave.Tracing; +import brave.TracingCustomizer; +import brave.handler.FinishedSpanHandler; +import brave.handler.MutableSpan; +import brave.propagation.TraceContext; +import brave.sampler.RateLimitingSampler; import brave.sampler.Sampler; import org.assertj.core.api.BDDAssertions; import org.junit.jupiter.api.Test; +import zipkin2.Span; +import zipkin2.reporter.Reporter; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; /** * @author Marcin Grzejszczak * @since */ +// TODO: missing spring cloud context tests public class SamplerAutoConfigurationTests { + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(SamplerAutoConfiguration.class)); + @Test - public void should_use_probability_sampler_when_property_set() { - SamplerProperties properties = new SamplerProperties(); - properties.setProbability(10f); - - Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); - - BDDAssertions.then(sampler).isInstanceOf(ProbabilityBasedSampler.class); + void should_use_NEVER_SAMPLER_when_only_logging() { + this.contextRunner.run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isSameAs(Sampler.NEVER_SAMPLE); + })); } @Test - public void should_use_rate_limiting_sampler_when_probability_not_set() { + void should_use_RateLimitedSampler_withFinishedSpanHandler() { + this.contextRunner.withUserConfiguration(WithFinishedSpanHandler.class) + .run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isInstanceOf(RateLimitingSampler.class); + })); + } + + @Test + void should_use_RateLimitedSampler_withReporter() { + this.contextRunner.withUserConfiguration(WithReporter.class).run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isInstanceOf(RateLimitingSampler.class); + })); + } + + @Test + void should_use_RateLimitedSampler_withTracingCustomizer() { + this.contextRunner.withUserConfiguration(WithTracingCustomizer.class) + .run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isInstanceOf(RateLimitingSampler.class); + })); + } + + @Test + void should_override_sampler() { + this.contextRunner.withUserConfiguration(WithReporter.class, WithSampler.class) + .run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isSameAs(Sampler.ALWAYS_SAMPLE); + })); + } + + @Test + void samplerFromProps_probability() { + SamplerProperties properties = new SamplerProperties(); + properties.setProbability(0.01f); + + Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); + + BDDAssertions.then(sampler).isInstanceOf(brave.sampler.CountingSampler.class); + } + + @Test + void samplerFromProps_rateLimit() { SamplerProperties properties = new SamplerProperties(); Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); - BDDAssertions.then(sampler).isInstanceOf(RateLimitingSampler.class); + BDDAssertions.then(sampler).isInstanceOf(brave.sampler.RateLimitingSampler.class); } @Test - public void should_use_probability_sampler_when_both_rate_and_probability_is_set() { + void samplerFromProps_rateLimitZero() { SamplerProperties properties = new SamplerProperties(); - properties.setProbability(10f); + properties.setRate(0); + + Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); + + BDDAssertions.then(sampler).isSameAs(Sampler.NEVER_SAMPLE); + } + + @Test + void samplerFromProps_prefersProbability() { + SamplerProperties properties = new SamplerProperties(); + properties.setProbability(0.01f); properties.setRate(20); Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); - BDDAssertions.then(sampler).isInstanceOf(ProbabilityBasedSampler.class); + BDDAssertions.then(sampler).isInstanceOf(brave.sampler.CountingSampler.class); + } + + @Test + void samplerFromProps_prefersZeroProbability() { + SamplerProperties properties = new SamplerProperties(); + properties.setProbability(0.0f); + properties.setRate(20); + + Sampler sampler = SamplerAutoConfiguration.samplerFromProps(properties); + + BDDAssertions.then(sampler).isSameAs(Sampler.NEVER_SAMPLE); + } + + @Configuration + static class WithFinishedSpanHandler { + + @Bean + FinishedSpanHandler finishedSpanHandler() { + return new FinishedSpanHandler() { + @Override + public boolean handle(TraceContext context, MutableSpan span) { + return true; + } + }; + } + + } + + @Configuration + static class WithReporter { + + @Bean + Reporter spanReporter() { + return zipkin2.Span::toString; + } + + } + + @Configuration + static class WithSampler { + + @Bean + Sampler alwaysSampler() { + return Sampler.ALWAYS_SAMPLE; + } + + } + + @Configuration + static class WithTracingCustomizer { + + @Bean + TracingCustomizer tracingCustomizer() { + return Tracing.Builder::toString; + } + } } diff --git a/spring-cloud-sleuth-core/src/test/resources/application-baggage.yml b/spring-cloud-sleuth-core/src/test/resources/application-baggage.yml index af0dc7fd9..0b0c68731 100644 --- a/spring-cloud-sleuth-core/src/test/resources/application-baggage.yml +++ b/spring-cloud-sleuth-core/src/test/resources/application-baggage.yml @@ -1,6 +1,7 @@ spring: sleuth: baggage: + foo: bar remoteFields: - country-code - x-vcap-request-id diff --git a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java index 09c7ca86c..7c1980ce3 100644 --- a/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java +++ b/spring-cloud-sleuth-zipkin/src/test/java/org/springframework/cloud/sleuth/zipkin2/ZipkinAutoConfigurationTests.java @@ -46,7 +46,6 @@ import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfigura import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -91,7 +90,7 @@ public class ZipkinAutoConfigurationTests { this.server.url("/").toString()); this.context.register(ZipkinAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, Config.class); + Config.class); this.context.refresh(); Span span = this.context.getBean(Tracing.class).tracer().nextSpan().name("foo") .tag("foo", "bar").start(); @@ -121,7 +120,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.encoder", "JSON_V1"); this.context.register(ZipkinAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, Config.class); + Config.class); this.context.refresh(); Span span = this.context.getBean(Tracing.class).tracer().nextSpan().name("foo") .tag("foo", "bar").start(); @@ -145,7 +144,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "rabbit"); this.context.register(PropertyPlaceholderAutoConfiguration.class, RabbitAutoConfiguration.class, ZipkinAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceAutoConfiguration.class); + TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class)).isInstanceOf(RabbitMQSender.class); @@ -160,7 +159,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "kafka"); this.context.register(PropertyPlaceholderAutoConfiguration.class, KafkaAutoConfiguration.class, ZipkinAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceAutoConfiguration.class); + TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class)).isInstanceOf(KafkaSender.class); @@ -177,7 +176,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "activemq"); this.context.register(PropertyPlaceholderAutoConfiguration.class, ActiveMQAutoConfiguration.class, ZipkinAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceAutoConfiguration.class); + TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class)).isInstanceOf(ActiveMQSender.class); @@ -191,8 +190,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "web"); this.context.register(PropertyPlaceholderAutoConfiguration.class, RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, - ZipkinAutoConfiguration.class, TraceBaggageAutoConfiguration.class, - TraceAutoConfiguration.class); + ZipkinAutoConfiguration.class, TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class).getClass().getName()) @@ -207,8 +205,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "WEB"); this.context.register(PropertyPlaceholderAutoConfiguration.class, RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, - ZipkinAutoConfiguration.class, TraceBaggageAutoConfiguration.class, - TraceAutoConfiguration.class); + ZipkinAutoConfiguration.class, TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class).getClass().getName()) @@ -223,8 +220,7 @@ public class ZipkinAutoConfigurationTests { environment().setProperty("spring.zipkin.sender.type", "rabbit"); this.context.register(PropertyPlaceholderAutoConfiguration.class, RabbitAutoConfiguration.class, KafkaAutoConfiguration.class, - ZipkinAutoConfiguration.class, TraceBaggageAutoConfiguration.class, - TraceAutoConfiguration.class); + ZipkinAutoConfiguration.class, TraceAutoConfiguration.class); this.context.refresh(); then(this.context.getBean(Sender.class)).isInstanceOf(RabbitMQSender.class); @@ -239,8 +235,7 @@ public class ZipkinAutoConfigurationTests { this.server.url("/").toString()); this.context.register(ZipkinAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, Config.class, - MultipleReportersConfig.class); + Config.class, MultipleReportersConfig.class); this.context.refresh(); then(this.context.getBeansOfType(Sender.class)).hasSize(2); @@ -275,7 +270,7 @@ public class ZipkinAutoConfigurationTests { this.context = new AnnotationConfigApplicationContext(); this.context.register(ZipkinAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, Config.class, MyConfig.class); + Config.class, MyConfig.class); this.context.refresh(); then(this.context.getBeansOfType(Sender.class)).hasSize(1); diff --git a/tests/spring-cloud-sleuth-instrumentation-messaging-tests/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java b/tests/spring-cloud-sleuth-instrumentation-messaging-tests/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java index d8811d8b6..4b5aa526c 100644 --- a/tests/spring-cloud-sleuth-instrumentation-messaging-tests/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java +++ b/tests/spring-cloud-sleuth-instrumentation-messaging-tests/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceMessagingAutoConfigurationTests.java @@ -40,7 +40,6 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import org.springframework.cloud.sleuth.util.ArrayListSpanReporter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -147,8 +146,6 @@ public class TraceMessagingAutoConfigurationTests { private ApplicationContextRunner contextRunner(String... propertyValues) { return new ApplicationContextRunner().withPropertyValues(propertyValues) .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, - TraceMessagingAutoConfiguration.class, TraceMessagingAutoConfiguration.class)); } diff --git a/tests/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfigurationTests.java b/tests/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfigurationTests.java index 85b341e13..37a1e970a 100644 --- a/tests/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfigurationTests.java +++ b/tests/spring-cloud-sleuth-instrumentation-mvc-tests/src/test/java/org/springframework/cloud/sleuth/instrument/web/TraceWebServletAutoConfigurationTests.java @@ -21,7 +21,6 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration; -import org.springframework.cloud.sleuth.baggage.TraceBaggageAutoConfiguration; import static org.assertj.core.api.Assertions.assertThat; @@ -34,8 +33,7 @@ public class TraceWebServletAutoConfigurationTests { private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() .withConfiguration(AutoConfigurations.of(TraceAutoConfiguration.class, - TraceBaggageAutoConfiguration.class, TraceHttpAutoConfiguration.class, - TraceWebAutoConfiguration.class, + TraceHttpAutoConfiguration.class, TraceWebAutoConfiguration.class, TraceWebServletAutoConfiguration.class)); @Test