diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc index 63725e19b..55bcbddd1 100644 --- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc +++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc @@ -88,6 +88,8 @@ 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. +By default samplers will work with the refresh scope mechanism. That means that you can change the sampling properties at runtime, refresh the application and the changes will be reflected. However, sometimes the fact of creating a proxy around samplers and calling it from too early (from `@PostConstruct` annotated method) may lead to dead locks. In such a case either create a sampler bean explicitly, or set the property `spring.sleuth.sampler.refresh.enabled` to `false` to disable the refresh scope support. + == 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/instrument/web/client/TraceGatewayEnvironmentPostProcessor.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceGatewayEnvironmentPostProcessor.java index e73d7b645..2f656651d 100644 --- a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceGatewayEnvironmentPostProcessor.java +++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/web/client/TraceGatewayEnvironmentPostProcessor.java @@ -39,7 +39,8 @@ import org.springframework.util.StringUtils; */ class TraceGatewayEnvironmentPostProcessor implements EnvironmentPostProcessor { - private static final Log log = LogFactory.getLog(TraceGatewayEnvironmentPostProcessor.class); + private static final Log log = LogFactory + .getLog(TraceGatewayEnvironmentPostProcessor.class); private static final String PROPERTY_SOURCE_NAME = "defaultProperties"; @@ -51,12 +52,14 @@ class TraceGatewayEnvironmentPostProcessor implements EnvironmentPostProcessor { String instrumentationType = environment .getProperty("spring.sleuth.reactor.instrumentation-type"); if (log.isDebugEnabled()) { - log.debug("Found the following instrumentation type [" + instrumentationType + "]"); + log.debug("Found the following instrumentation type [" + + instrumentationType + "]"); } if (StringUtils.isEmpty(instrumentationType)) { instrumentationType = "manual"; if (log.isDebugEnabled()) { - log.debug("No instrumentation type passed, will force it to [" + instrumentationType + "]"); + log.debug("No instrumentation type passed, will force it to [" + + instrumentationType + "]"); } } map.put("spring.sleuth.reactor.instrumentation-type", instrumentationType); 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 e85438190..eeb451160 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 @@ -18,9 +18,11 @@ package org.springframework.cloud.sleuth.sampler; import brave.sampler.CountingSampler; import brave.sampler.Sampler; +import org.jetbrains.annotations.NotNull; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Bean; @@ -65,7 +67,22 @@ public class SamplerAutoConfiguration { @Bean @RefreshScope @ConditionalOnMissingBean + @ConditionalOnProperty(value = "spring.sleuth.sampler.refresh.enabled", + matchIfMissing = true) public Sampler defaultTraceSampler(SamplerProperties config) { + return sampler(config); + } + + @Bean + @ConditionalOnMissingBean + @ConditionalOnProperty(value = "spring.sleuth.sampler.refresh.enabled", + havingValue = "false") + public Sampler defaultNonRefreshScopeTraceSampler(SamplerProperties config) { + return sampler(config); + } + + @NotNull + private Sampler sampler(SamplerProperties config) { // TODO: Rewrite: refresh should replace the sampler, not change its state // internally if (config.getProbability() != null) { diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json index a0332b815..40968741e 100644 --- a/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -83,6 +83,12 @@ "type": "java.lang.Boolean", "description": "Enable tracing of RPC.", "defaultValue": true + }, + { + "name": "spring.sleuth.sampler.refresh.enabled", + "type": "java.lang.Boolean", + "description": "Enable refresh scope for sampler.", + "defaultValue": true } ] } 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 c6ce65b5c..f1cbf6c6f 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 @@ -28,6 +28,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.cloud.context.scope.refresh.RefreshScope; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -59,10 +60,30 @@ public class SamplerAutoConfigurationTests { @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); + this.contextRunner.withUserConfiguration(WithTracingCustomizer.class).run((context -> { + final Sampler bean = context.getBean(Sampler.class); + BDDAssertions.then(bean).isInstanceOf(RateLimitingSampler.class); + })); + } + + @Test + void should_use_refresh_scope_sampler_when_no_property_passed_and_refresh_scope_present() { + this.contextRunner.withUserConfiguration(WithTracingCustomizer.class, WithRefreshScope.class).run((context -> { + BDDAssertions.then(context.containsBean("defaultTraceSampler")).as("refresh scope bean should be set") + .isTrue(); + BDDAssertions.then(context.containsBean("defaultNonRefreshScopeTraceSampler")) + .as("non refresh scope bean should not be picked").isFalse(); + })); + } + + @Test + void should_use_non_refresh_scope_sampler_when_property_passed_and_refresh_scope_present() { + this.contextRunner.withUserConfiguration(WithTracingCustomizer.class, WithRefreshScope.class) + .withPropertyValues("spring.sleuth.sampler.refresh.enabled=false").run((context -> { + BDDAssertions.then(context.containsBean("defaultNonRefreshScopeTraceSampler")) + .as("non refresh scope bean should be picked").isTrue(); + BDDAssertions.then(context.containsBean("defaultTraceSampler")) + .as("refresh scope bean should not be set").isFalse(); })); } @@ -142,4 +163,14 @@ public class SamplerAutoConfigurationTests { } + @Configuration + static class WithRefreshScope { + + @Bean + RefreshScope refreshScope() { + return new RefreshScope(); + } + + } + }