diff --git a/reactor-core-micrometer/src/main/java/reactor/core/observability/micrometer/MicrometerObservationListener.java b/reactor-core-micrometer/src/main/java/reactor/core/observability/micrometer/MicrometerObservationListener.java index 29f05e7935..f8d1e5c791 100644 --- a/reactor-core-micrometer/src/main/java/reactor/core/observability/micrometer/MicrometerObservationListener.java +++ b/reactor-core-micrometer/src/main/java/reactor/core/observability/micrometer/MicrometerObservationListener.java @@ -97,21 +97,26 @@ final class MicrometerObservationListener implements SignalListener { //while doOnSubscription matches the moment where the Publisher acknowledges said subscription //NOTE: we don't use the `DocumentedObservation` features to create the Observation, even for the ANONYMOUS case, //because the discovered tags could be more than the documented defaults - tapObservation = defaultObservation(configuration, observationSupplier) - .contextualName(configuration.sequenceName) + tapObservation = supplyOrCreateObservation(configuration, observationSupplier) .lowCardinalityKeyValues(configuration.commonKeyValues); } - private static Observation defaultObservation( + private static Observation supplyOrCreateObservation( MicrometerObservationListenerConfiguration configuration, @Nullable Function observationSupplier) { if (observationSupplier != null) { final Observation observation = observationSupplier.apply(configuration.registry); if (observation != null) { - return observation; + if (observation.getContext().getContextualName() != null) { + return observation; + } + else { + return observation.contextualName(configuration.sequenceName); + } } } - return Observation.createNotStarted(configuration.sequenceName, configuration.registry); + return Observation.createNotStarted(configuration.sequenceName, configuration.registry) + .contextualName(configuration.sequenceName); } @Override diff --git a/reactor-core-micrometer/src/test/java/reactor/core/observability/micrometer/MicrometerObservationListenerTest.java b/reactor-core-micrometer/src/test/java/reactor/core/observability/micrometer/MicrometerObservationListenerTest.java index a0cf2ed107..148be1d3ba 100644 --- a/reactor-core-micrometer/src/test/java/reactor/core/observability/micrometer/MicrometerObservationListenerTest.java +++ b/reactor-core-micrometer/src/test/java/reactor/core/observability/micrometer/MicrometerObservationListenerTest.java @@ -68,12 +68,53 @@ public long monotonicTime() { }; configuration = new MicrometerObservationListenerConfiguration( "testName", - KeyValues.of("testTag1", "testTagValue1","testTag2", "testTagValue2"), + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), registry, false); subscriberContext = Context.of("contextKey", "contextValue"); } + @ParameterizedTestWithName + @ValueSource(booleans = {true, false}) + void whenStartedFluxWithDefaultNameWithCustomObservationSupplier(boolean automatic) { + if (automatic) { + Hooks.enableAutomaticContextPropagation(); + } + configuration = new MicrometerObservationListenerConfiguration( + MicrometerObservationListenerDocumentation.ANONYMOUS.getName(), + //note: "type" key is added by MicrometerObservationListenerConfiguration#fromFlux (which is tested separately) + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), + registry, + false); + + MicrometerObservationListener listener = + new MicrometerObservationListener<>(subscriberContext, configuration, + or -> Observation.createNotStarted("user.name", or) + .lowCardinalityKeyValue("userType", "admin") + .highCardinalityKeyValue("userId", "testId") + .contextualName("getting-user-name")); + + assertThat(listener.valued).as("valued").isFalse(); + assertThat(listener.tapObservation) + .as("subscribeToTerminalObservation field") + .isNotNull(); + assertThat(registry).as("before start").doesNotHaveAnyObservation(); + + listener.doFirst(); // forces observation start + + assertThat(registry) + .hasSingleObservationThat() + .hasNameEqualTo("user.name") + .hasContextualNameEqualTo("getting-user-name") + .as("subscribeToTerminalObservation") + .hasBeenStarted() + .isNotStopped() + .hasLowCardinalityKeyValue("testTag1", "testTagValue1") + .hasLowCardinalityKeyValue("testTag2", "testTagValue2") + .hasLowCardinalityKeyValue("userType", "admin") + .hasHighCardinalityKeyValue("userId", "testId"); + } + @ParameterizedTestWithName @ValueSource(booleans = {true, false}) void whenStartedFluxWithDefaultName(boolean automatic) { @@ -83,7 +124,7 @@ void whenStartedFluxWithDefaultName(boolean automatic) { configuration = new MicrometerObservationListenerConfiguration( MicrometerObservationListenerDocumentation.ANONYMOUS.getName(), //note: "type" key is added by MicrometerObservationListenerConfiguration#fromFlux (which is tested separately) - KeyValues.of("testTag1", "testTagValue1","testTag2", "testTagValue2"), + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), registry, false); @@ -116,7 +157,7 @@ void whenStartedFluxWithCustomName(boolean automatic) { configuration = new MicrometerObservationListenerConfiguration( "testName", //note: "type" key is added by MicrometerObservationListenerConfiguration#fromFlux (which is tested separately) - KeyValues.of("testTag1", "testTagValue1","testTag2", "testTagValue2"), + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), registry, false); @@ -150,7 +191,7 @@ void whenStartedMono(boolean automatic) { configuration = new MicrometerObservationListenerConfiguration( MicrometerObservationListenerDocumentation.ANONYMOUS.getName(), //note: "type" key is added by MicrometerObservationListenerConfiguration#fromMono (which is tested separately) - KeyValues.of("testTag1", "testTagValue1","testTag2", "testTagValue2"), + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), registry, true); @@ -644,7 +685,7 @@ void observationWithEmptyContextHasNoParent(boolean automatic) { configuration = new MicrometerObservationListenerConfiguration( MicrometerObservationListenerDocumentation.ANONYMOUS.getName(), //note: "type" key is added by MicrometerObservationListenerConfiguration#fromFlux (which is tested separately) - KeyValues.of("testTag1", "testTagValue1","testTag2", "testTagValue2"), + KeyValues.of("testTag1", "testTagValue1", "testTag2", "testTagValue2"), registry, false);