diff --git a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java index 5de057032..aa9a6214b 100644 --- a/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java +++ b/spring-cloud-sleuth-instrumentation/src/main/java/org/springframework/cloud/sleuth/instrument/messaging/TraceFunctionAroundWrapper.java @@ -37,6 +37,7 @@ import org.springframework.messaging.support.MessageHeaderAccessor; * Trace representation of a {@link FunctionAroundWrapper}. * * @author Marcin Grzejszczak + * @author Oleg Zhurakousky * @since 3.0.0 */ public class TraceFunctionAroundWrapper extends FunctionAroundWrapper @@ -73,7 +74,7 @@ public class TraceFunctionAroundWrapper extends FunctionAroundWrapper log.debug("Will retrieve the tracing headers from the message"); } MessageAndSpans wrappedInputMessage = traceMessageHandler.wrapInputMessage(message, - inputDestination(targetFunction)); + inputDestination(targetFunction.getFunctionDefinition())); if (log.isDebugEnabled()) { log.debug("Wrapped input msg " + wrappedInputMessage); } @@ -90,14 +91,12 @@ public class TraceFunctionAroundWrapper extends FunctionAroundWrapper traceMessageHandler.afterMessageHandled(wrappedInputMessage.childSpan, throwable); } if (result == null) { - if (log.isDebugEnabled()) { - log.debug("Returned message is null - we have a consumer"); - } + log.debug("Returned message is null - we have a consumer"); return null; } Message msgResult = toMessage(result); MessageAndSpan wrappedOutputMessage = traceMessageHandler.wrapOutputMessage(msgResult, - wrappedInputMessage.parentSpan, outputDestination(targetFunction)); + wrappedInputMessage.parentSpan, outputDestination(targetFunction.getFunctionDefinition())); if (log.isDebugEnabled()) { log.debug("Wrapped output msg " + wrappedOutputMessage); } @@ -112,23 +111,27 @@ public class TraceFunctionAroundWrapper extends FunctionAroundWrapper return (Message) result; } - private String inputDestination(SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction) { - String functionDefinition = targetFunction.getFunctionDefinition(); - return this.functionToDestinationCache.computeIfAbsent(functionDefinition, - s -> this.environment.getProperty("spring.cloud.stream.bindings." + s + "-in-0.destination", s)); + private String inputDestination(String functionDefinition) { + return this.functionToDestinationCache.computeIfAbsent(functionDefinition, s -> { + String bindingMappingProperty = "spring.cloud.stream.function.bindings." + s + "-in-0"; + String bindingProperty = this.environment.containsProperty(bindingMappingProperty) + ? this.environment.getProperty(bindingMappingProperty) : s + "-in-0"; + return this.environment.getProperty("spring.cloud.stream.bindings." + bindingProperty + ".destination", s); + }); } - private String outputDestination(SimpleFunctionRegistry.FunctionInvocationWrapper targetFunction) { - String functionDefinition = targetFunction.getFunctionDefinition(); - return functionToDestinationCache.computeIfAbsent(functionDefinition, - s -> this.environment.getProperty("spring.cloud.stream.bindings." + s + "-out-0.destination", s)); + private String outputDestination(String functionDefinition) { + return this.functionToDestinationCache.computeIfAbsent(functionDefinition, s -> { + String bindingMappingProperty = "spring.cloud.stream.function.bindings." + s + "-out-0"; + String bindingProperty = this.environment.containsProperty(bindingMappingProperty) + ? this.environment.getProperty(bindingMappingProperty) : s + "-out-0"; + return this.environment.getProperty("spring.cloud.stream.bindings." + bindingProperty + ".destination", s); + }); } @Override public void onApplicationEvent(RefreshScopeRefreshedEvent event) { - if (log.isDebugEnabled()) { - log.debug("Context refreshed, will reset the cache"); - } + log.debug("Context refreshed, will reset the cache"); this.functionToDestinationCache.clear(); } 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 3717a0a62..3d1e0f63c 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 @@ -16,8 +16,14 @@ package org.springframework.cloud.sleuth.instrument.messaging; +import java.lang.reflect.Method; + import org.junit.jupiter.api.Test; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.util.ReflectionUtils; + +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.BDDAssertions.then; class TraceFunctionAroundWrapperTests { @@ -33,4 +39,54 @@ class TraceFunctionAroundWrapperTests { then(wrapper.functionToDestinationCache).isEmpty(); } + @Test + void test_with_standard_bindings() throws Exception { + try (GenericApplicationContext context = new GenericApplicationContext()) { + System.setProperty("spring.cloud.stream.bindings.marcin-in-0.destination", "oleg"); + System.setProperty("spring.cloud.stream.bindings.marcin-out-0.destination", "bob"); + TraceFunctionAroundWrapper wrapper = new TraceFunctionAroundWrapper(context.getEnvironment(), null, null, + null, null); + + Method inputDestinationMethod = ReflectionUtils.findMethod(TraceFunctionAroundWrapper.class, + "inputDestination", String.class); + inputDestinationMethod.setAccessible(true); + assertThat(inputDestinationMethod.invoke(wrapper, "marcin")).isEqualTo("oleg"); // gross + // overestimation + // ;) + + wrapper.functionToDestinationCache.clear(); + Method outputDestinationMethod = ReflectionUtils.findMethod(TraceFunctionAroundWrapper.class, + "outputDestination", String.class); + outputDestinationMethod.setAccessible(true); + assertThat(outputDestinationMethod.invoke(wrapper, "marcin")).isEqualTo("bob"); + } + } + + @Test + void test_with_remapped_bindings() throws Exception { + try (GenericApplicationContext context = new GenericApplicationContext()) { + System.setProperty("spring.cloud.stream.function.bindings.marcin-in-0", "input"); + System.setProperty("spring.cloud.stream.bindings.input.destination", "oleg"); + System.setProperty("spring.cloud.stream.function.bindings.marcin-out-0", "output"); + System.setProperty("spring.cloud.stream.bindings.output.destination", "bob"); + TraceFunctionAroundWrapper wrapper = new TraceFunctionAroundWrapper(context.getEnvironment(), null, null, + null, null); + + Method inputDestinationMethod = ReflectionUtils.findMethod(TraceFunctionAroundWrapper.class, + "inputDestination", String.class); + inputDestinationMethod.setAccessible(true); + assertThat(inputDestinationMethod.invoke(wrapper, "marcin")).isEqualTo("oleg"); // that's + // a + // gross + // overestimation + // ;) + + wrapper.functionToDestinationCache.clear(); + Method outputDestinationMethod = ReflectionUtils.findMethod(TraceFunctionAroundWrapper.class, + "outputDestination", String.class); + outputDestinationMethod.setAccessible(true); + assertThat(outputDestinationMethod.invoke(wrapper, "marcin")).isEqualTo("bob"); + } + } + }