From 2b9b76e5dc735735e4807dbcc813d7bfdd4abfcf Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Wed, 2 Feb 2022 09:57:50 +0100 Subject: [PATCH] Ensures that sampler proxy gets eagerly resolved; fixes gh-2107 --- .../redis/TraceRedisAutoConfiguration.java | 15 ++++++++++- .../TraceFunctionAroundWrapperTests.java | 27 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/redis/TraceRedisAutoConfiguration.java b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/redis/TraceRedisAutoConfiguration.java index da8003d5d..b6e89a72d 100644 --- a/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/redis/TraceRedisAutoConfiguration.java +++ b/spring-cloud-sleuth-autoconfigure/src/main/java/org/springframework/cloud/sleuth/autoconfig/instrument/redis/TraceRedisAutoConfiguration.java @@ -16,6 +16,7 @@ package org.springframework.cloud.sleuth.autoconfig.instrument.redis; +import brave.sampler.Sampler; import io.lettuce.core.tracing.Tracing; import org.springframework.boot.autoconfigure.AutoConfigureBefore; @@ -51,10 +52,22 @@ public class TraceRedisAutoConfiguration { @Bean @ConditionalOnBean(Tracing.class) - TraceLettuceClientResourcesBuilderCustomizer traceLettuceClientResourcesBuilderCustomizer(Tracing tracing) { + TraceLettuceClientResourcesBuilderCustomizer traceLettuceClientResourcesBuilderCustomizer(Tracing tracing, + Sampler sampler) { + eagerlyInitializePotentiallyRefreshScopeSampler(sampler); return new TraceLettuceClientResourcesBuilderCustomizer(tracing); } + /** + * We need to do the eager method invocation. Since this might be @RefreshScope, a + * proxy is being created. Trying to resolve the proxy from a different thread + * than main can lead to cross thread locking. + * @param sampler potentially refresh scope sampler + */ + private void eagerlyInitializePotentiallyRefreshScopeSampler(Sampler sampler) { + sampler.isSampled(0L); + } + } } diff --git a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapperTests.java b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapperTests.java index 3c8a0f17c..ee86bc085 100644 --- a/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapperTests.java +++ b/spring-cloud-sleuth-instrumentation/src/test/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapperTests.java @@ -151,6 +151,19 @@ class TraceFunctionAroundWrapperTests { assertThat(tracer.spans).isEmpty(); } + @Test + void test_tracing_with_message_flux_to_flux_without_message() { + FunctionRegistration registration = new FunctionRegistration<>( + new MessageFluxToFluxFunction(), "greeter").type(FunctionType.of(MessageFluxToFluxFunction.class)); + catalog.register(registration); + FunctionInvocationWrapper function = catalog.lookup("greeter"); + + Object result = (Object) ((Flux) wrapper.apply("hello", function)).blockFirst(); + + assertThat(result).isEqualTo("hello"); + assertThat(tracer.spans).isEmpty(); + } + @Test void test_tracing_with_consumer() { GreeterConsumer consumer = new GreeterConsumer(); @@ -465,4 +478,18 @@ class TraceFunctionAroundWrapperTests { } + static class MessageFluxToFluxFunction implements Function>, Flux> { + + private static final Logger log = LoggerFactory.getLogger(MessageFluxToFluxFunction.class); + + @Override + public Flux apply(Flux> input) { + return input.map(s -> { + log.info("Logging [{}] from map", s); + return s.getPayload(); + }); + } + + } + }