diff --git a/micrometer-observation/src/main/java/io/micrometer/observation/docs/DocumentedObservation.java b/micrometer-observation/src/main/java/io/micrometer/observation/docs/DocumentedObservation.java index 0f6f41037d..90ab8642d7 100644 --- a/micrometer-observation/src/main/java/io/micrometer/observation/docs/DocumentedObservation.java +++ b/micrometer-observation/src/main/java/io/micrometer/observation/docs/DocumentedObservation.java @@ -19,11 +19,13 @@ import io.micrometer.common.lang.NonNull; import io.micrometer.common.lang.Nullable; import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationPredicate; import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.GlobalObservationConvention; import io.micrometer.observation.ObservationConvention; import java.util.Objects; +import java.util.function.Supplier; /** * In order to describe your samples via e.g. enums instead of Strings you can use this @@ -187,6 +189,32 @@ default Observation observation(@Nullable Observ return observation; } + /** + * Creates an {@link Observation} for the given {@link ObservationConvention}. You + * need to manually start it. When the {@link ObservationRegistry} is a no-op, this + * method fast returns a no-op {@link Observation} and skips the creation of the + * {@link Observation.Context}. This quick check avoids unnecessary + * {@link Observation.Context} creations. More detailed check, such as + * {@link ObservationPredicate}, is performed at the later stage after + * {@link Observation.Context} creation. + * @param customConvention convention that (if not {@code null}) will override any + * pre-configured conventions + * @param defaultConvention default convention that will be picked if there was + * neither custom convention nor a pre-configured one via + * {@link ObservationRegistry.ObservationConfig#observationConvention(GlobalObservationConvention[])} + * @param contextSupplier observation context supplier + * @param registry observation registry + * @return observation + */ + default Observation createNotStarted( + @Nullable ObservationConvention customConvention, @NonNull ObservationConvention defaultConvention, + @NonNull Supplier contextSupplier, @NonNull ObservationRegistry registry) { + if (registry.isNoop()) { + return Observation.NOOP; + } + return observation(customConvention, defaultConvention, contextSupplier.get(), registry); + } + /** * Creates and starts an {@link Observation}. * @param registry observation registry diff --git a/micrometer-observation/src/test/java/io/micrometer/observation/docs/DocumentedObservationTests.java b/micrometer-observation/src/test/java/io/micrometer/observation/docs/DocumentedObservationTests.java index 099ab2dfdf..6dd17acfd3 100644 --- a/micrometer-observation/src/test/java/io/micrometer/observation/docs/DocumentedObservationTests.java +++ b/micrometer-observation/src/test/java/io/micrometer/observation/docs/DocumentedObservationTests.java @@ -15,9 +15,13 @@ */ package io.micrometer.observation.docs; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Supplier; + import io.micrometer.common.KeyValue; import io.micrometer.common.KeyValues; import io.micrometer.observation.Observation; +import io.micrometer.observation.Observation.Context; import io.micrometer.observation.ObservationFilter; import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.GlobalObservationConvention; @@ -116,6 +120,22 @@ void keyValuesShouldBeAlwaysAdded() { assertThat(context.getHighCardinalityKeyValues()).containsOnly(KeyValue.of("global", "high cardinality")); } + @Test + void createNotStartedShouldNotCreateContextWithNoopRegistry() { + ObservationRegistry registry = ObservationRegistry.NOOP; + + AtomicBoolean isCalled = new AtomicBoolean(); + Supplier supplier = () -> { + isCalled.set(true); + return new Observation.Context(); + }; + + Observation observation = TestConventionObservation.CONTEXTUAL_NAME.createNotStarted(null, + new FirstObservationConvention(), supplier, registry); + assertThat(observation.isNoop()).isTrue(); + assertThat(isCalled).isFalse(); + } + private ObservationRegistry observationRegistry() { ObservationRegistry registry = ObservationRegistry.create(); registry.observationConfig().observationHandler(context -> true);