diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfiguration.java index c247b1a9c0..9323e6eca4 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfiguration.java @@ -27,14 +27,14 @@ import org.springframework.context.annotation.Configuration; * {@link EnableAutoConfiguration Auto-configuration} for Reactor. * * @author Brian Clozel - * @since 3.0.2 + * @since 3.2.0 */ @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Hooks.class) @EnableConfigurationProperties(ReactorProperties.class) public class ReactorAutoConfiguration { - public ReactorAutoConfiguration(ReactorProperties properties) { + ReactorAutoConfiguration(ReactorProperties properties) { if (properties.getContextPropagation() == ReactorProperties.ContextPropagationMode.AUTO) { Hooks.enableAutomaticContextPropagation(); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorProperties.java index 6725ee1ba4..c82da8b523 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/reactor/ReactorProperties.java @@ -22,7 +22,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; * Configuration properties for Reactor. * * @author Brian Clozel - * @since 3.0.3 + * @since 3.2.0 */ @ConfigurationProperties(prefix = "spring.reactor") public class ReactorProperties { @@ -30,7 +30,7 @@ public class ReactorProperties { /** * Context Propagation support mode for Reactor operators. */ - private ContextPropagationMode contextPropagation = ContextPropagationMode.AUTO; + private ContextPropagationMode contextPropagation = ContextPropagationMode.LIMITED; public ContextPropagationMode getContextPropagation() { return this.contextPropagation; diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index f12c04ea45..bfd976e9b9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -2092,7 +2092,7 @@ }, { "name": "spring.reactor.context-propagation", - "defaultValue": "auto" + "defaultValue": "limited" }, { "name": "spring.reactor.stacktrace-mode.enabled", diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfigurationTests.java index 73642c5883..32897e1b3a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/reactor/ReactorAutoConfigurationTests.java @@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.reactor; import java.util.concurrent.atomic.AtomicReference; import io.micrometer.context.ContextRegistry; +import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; @@ -33,6 +34,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link ReactorAutoConfiguration}. * * @author Brian Clozel + * @author Moritz Halbritter */ class ReactorAutoConfigurationTests { @@ -41,7 +43,7 @@ class ReactorAutoConfigurationTests { private static final String THREADLOCAL_KEY = "ReactorAutoConfigurationTests"; - private static final ThreadLocal THREADLOCAL_VALUE = ThreadLocal.withInitial(() -> "failure"); + private static final ThreadLocal THREADLOCAL_VALUE = ThreadLocal.withInitial(() -> "initial"); @BeforeAll static void initializeThreadLocalAccessors() { @@ -49,15 +51,33 @@ class ReactorAutoConfigurationTests { globalRegistry.registerThreadLocalAccessor(THREADLOCAL_KEY, THREADLOCAL_VALUE); } + @AfterAll + static void removeThreadLocalAccessors() { + ContextRegistry globalRegistry = ContextRegistry.getInstance(); + globalRegistry.removeThreadLocalAccessor(THREADLOCAL_KEY); + } + @Test - void shouldConfigureAutomaticContextPropagation() { + void shouldNotConfigurePropagationByDefault() { AtomicReference threadLocalValue = new AtomicReference<>(); this.contextRunner.run((applicationContext) -> { Mono.just("test") .doOnNext((element) -> threadLocalValue.set(THREADLOCAL_VALUE.get())) - .contextWrite(Context.of(THREADLOCAL_KEY, "success")) + .contextWrite(Context.of(THREADLOCAL_KEY, "updated")) + .block(); + assertThat(threadLocalValue.get()).isEqualTo("initial"); + }); + } + + @Test + void shouldConfigurePropagationIfSetToAuto() { + AtomicReference threadLocalValue = new AtomicReference<>(); + this.contextRunner.withPropertyValues("spring.reactor.context-propagation=auto").run((applicationContext) -> { + Mono.just("test") + .doOnNext((element) -> threadLocalValue.set(THREADLOCAL_VALUE.get())) + .contextWrite(Context.of(THREADLOCAL_KEY, "updated")) .block(); - assertThat(threadLocalValue.get()).isEqualTo("success"); + assertThat(threadLocalValue.get()).isEqualTo("updated"); }); } diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc index b1256b684e..dbf2e32597 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/observability.adoc @@ -14,7 +14,11 @@ NOTE: Low cardinality key-values will be added to metrics and traces, while high Beans of type `ObservationPredicate`, `GlobalObservationConvention`, `ObservationFilter` and `ObservationHandler` will be automatically registered on the `ObservationRegistry`. You can additionally register any number of `ObservationRegistryCustomizer` beans to further configure the registry. -For more details please see the https://micrometer.io/docs/observation[Micrometer Observation documentation]. +Observability support relies on the https://github.com/micrometer-metrics/context-propagation[Context Propagation library] for forwarding the current observation across threads and reactive pipelines. +By default, `ThreadLocal` values are not automatically reinstated in reactive operators. +This behavior is controlled with the configprop:spring.reactor.context-propagation[] property, which can be set to `auto` to enable automatic propagation. + +For more details about observations please see the https://micrometer.io/docs/observation[Micrometer Observation documentation]. TIP: Observability for JDBC can be configured using a separate project. The https://github.com/jdbc-observations/datasource-micrometer[Datasource Micrometer project] provides a Spring Boot starter which automatically creates observations when JDBC operations are invoked. @@ -80,7 +84,4 @@ The attributes of the `Resource` can be configured via the configprop:management NOTE: Spring Boot does not provide auto-configuration for OpenTelemetry metrics or logging. OpenTelemetry tracing is only auto-configured when used together with <>. -Observability support relies on the https://github.com/micrometer-metrics/context-propagation[Context Propagation library] for forwarding the current observation across threads and reactive pipelines. -`ThreadLocal` values are automatically reinstated in reactive operators, this behavior is controlled with the configprop:spring.reactor.context-propagation[] property. - The next sections will provide more details about logging, metrics and traces. diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index 0c0f26a225..85e291bf4f 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -138,7 +138,7 @@ bom { ] } } - library("Micrometer Context Propagation", "1.0.2") { + library("Micrometer Context Propagation", "1.0.5") { group("io.micrometer") { modules = [ "context-propagation"