From c241a4cd624e00563dd53e37d642cfcef4d01a44 Mon Sep 17 00:00:00 2001 From: Debashismitra01 Date: Tue, 7 Jul 2026 03:00:24 +0530 Subject: [PATCH 1/5] Add shutdown lifecycle method to Sampler --- .../io/opentelemetry/sdk/trace/samplers/Sampler.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java index 73edba3b6f1..0b987d0ac53 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java @@ -11,6 +11,7 @@ import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.api.trace.TraceId; import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.data.LinkData; import java.util.List; import javax.annotation.concurrent.ThreadSafe; @@ -119,4 +120,15 @@ SamplingResult shouldSample( * @return the description of this {@code Sampler}. */ String getDescription(); + + /** + * Shuts down the sampler, releasing any resources held by it. + * + *

This method is called when the {@code SdkTracerProvider} is shut down. + * + * @return a {@link CompletableResultCode} which is completed when shutdown is finished. + */ + default CompletableResultCode shutdown() { + return CompletableResultCode.ofSuccess(); + } } From 993c6bd1823deacf69676e02a358236d5f188d77 Mon Sep 17 00:00:00 2001 From: Debashismitra01 Date: Tue, 7 Jul 2026 03:00:50 +0530 Subject: [PATCH 2/5] Shutdown sampler from SdkTracerProvider --- .../sdk/trace/SdkTracerProvider.java | 15 +++++++++------ .../sdk/trace/SdkTracerProviderTest.java | 13 +++++++++++++ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java index 7a555ea128b..6ef5f40000a 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java @@ -135,25 +135,28 @@ void setTracerConfigurator(ScopeConfigurator tracerConfigurator) { /** * Attempts to stop all the activity for {@link Tracer}s created by this provider. Calls {@link - * SpanProcessor#shutdown()} for all registered {@link SpanProcessor}s. + * SpanProcessor#shutdown()} for all registered {@link SpanProcessor}s and {@link + * Sampler#shutdown()} for the configured {@link Sampler}. * - *

The returned {@link CompletableResultCode} will be completed when all the Spans are - * processed. + *

The returned {@link CompletableResultCode} will be completed when shutdown processing is + * finished. * *

After this is called, newly created {@code Span}s will be no-ops. * *

After this is called, further attempts at re-using this instance will result in undefined * behavior. It should be considered a terminal operation for the SDK. * - * @return a {@link CompletableResultCode} which is completed when all the span processors have - * been shut down. + * @return a {@link CompletableResultCode} which is completed when all span processors and the + * sampler have been shut down. */ public CompletableResultCode shutdown() { if (sharedState.hasBeenShutdown()) { logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } - return sharedState.shutdown(); + + return CompletableResultCode.ofAll( + List.of(sharedState.shutdown(), sharedState.getSampler().shutdown())); } /** diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkTracerProviderTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkTracerProviderTest.java index b007fe06b22..4ba416c4f88 100644 --- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkTracerProviderTest.java +++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/SdkTracerProviderTest.java @@ -237,6 +237,19 @@ void shutdown() { Mockito.verify(spanProcessor, Mockito.times(1)).shutdown(); } + @Test + void shutdown_ShutsDownSampler() { + Sampler sampler = mock(Sampler.class); + + when(sampler.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + + SdkTracerProvider tracerProvider = SdkTracerProvider.builder().setSampler(sampler).build(); + + tracerProvider.shutdown(); + + verify(sampler).shutdown(); + } + @Test void close() { tracerProvider.close(); From 3206df2b419bccd5973116a2d54d155db3a73f6c Mon Sep 17 00:00:00 2001 From: Debashismitra01 Date: Tue, 7 Jul 2026 03:01:19 +0530 Subject: [PATCH 3/5] Shutdown JaegerRemoteSampler resources --- CHANGELOG.md | 5 +++++ .../jaeger/sampler/JaegerRemoteSampler.java | 12 +++++++++--- .../sampler/JaegerRemoteSamplerTest.java | 14 ++++++++++++++ .../sdk/trace/SdkTracerProvider.java | 15 ++++++--------- .../sdk/trace/TracerSharedState.java | 19 +++++++++++++++---- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ccd002c3dd..4dbf4ee6eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +<<<<<<< HEAD ## Version 1.64.0 (2026-07-10) ### API @@ -93,6 +94,10 @@ ([#8469](https://github.com/open-telemetry/opentelemetry-java/pull/8469)) * Make benchmark path configurable ([#8557](https://github.com/open-telemetry/opentelemetry-java/pull/8557)) +======= +* Add shutdown lifecycle method to `Sampler` to allow resource cleanup for stateful samplers. + ([#8574](https://github.com/open-telemetry/opentelemetry-java/pull/8574)) +>>>>>>> 83b70e5ee (Shutdown JaegerRemoteSampler resources) ## Version 1.63.0 (2026-06-05) diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java index 2e32f566273..e26dcabbd46 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java @@ -8,6 +8,7 @@ import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.context.Context; +import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.GrpcResponse; import io.opentelemetry.sdk.common.export.GrpcSender; import io.opentelemetry.sdk.common.export.GrpcStatusCode; @@ -175,11 +176,16 @@ public static JaegerRemoteSamplerBuilder builder() { return new JaegerRemoteSamplerBuilder(); } + @Override + public CompletableResultCode shutdown() { + pollFuture.cancel(false); + pollExecutor.shutdownNow(); + return grpcSender.shutdown(); + } + @Override @SuppressWarnings("Interruption") public void close() { - pollFuture.cancel(true); - pollExecutor.shutdownNow(); - grpcSender.shutdown().join(10, TimeUnit.SECONDS); + shutdown().join(10, TimeUnit.SECONDS); } } diff --git a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java index e646a0d4921..969bf04a934 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java +++ b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java @@ -160,6 +160,20 @@ void connectionWorks() { } } + @Test + void shutdown() { + JaegerRemoteSampler sampler = + JaegerRemoteSampler.builder() + .setEndpoint(server.httpUri().toString()) + .setPollingInterval(1, TimeUnit.SECONDS) + .setServiceName(SERVICE_NAME) + .build(); + + assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); + + assertThat(sampler.shutdown().join(10, TimeUnit.SECONDS).isSuccess()).isTrue(); + } + @Test void tlsConnectionWorks() throws IOException { try (JaegerRemoteSampler sampler = diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java index 6ef5f40000a..7a555ea128b 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/SdkTracerProvider.java @@ -135,28 +135,25 @@ void setTracerConfigurator(ScopeConfigurator tracerConfigurator) { /** * Attempts to stop all the activity for {@link Tracer}s created by this provider. Calls {@link - * SpanProcessor#shutdown()} for all registered {@link SpanProcessor}s and {@link - * Sampler#shutdown()} for the configured {@link Sampler}. + * SpanProcessor#shutdown()} for all registered {@link SpanProcessor}s. * - *

The returned {@link CompletableResultCode} will be completed when shutdown processing is - * finished. + *

The returned {@link CompletableResultCode} will be completed when all the Spans are + * processed. * *

After this is called, newly created {@code Span}s will be no-ops. * *

After this is called, further attempts at re-using this instance will result in undefined * behavior. It should be considered a terminal operation for the SDK. * - * @return a {@link CompletableResultCode} which is completed when all span processors and the - * sampler have been shut down. + * @return a {@link CompletableResultCode} which is completed when all the span processors have + * been shut down. */ public CompletableResultCode shutdown() { if (sharedState.hasBeenShutdown()) { logger.log(Level.INFO, "Calling shutdown() multiple times."); return CompletableResultCode.ofSuccess(); } - - return CompletableResultCode.ofAll( - List.of(sharedState.shutdown(), sharedState.getSampler().shutdown())); + return sharedState.shutdown(); } /** diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java index 254d78fd254..78c7b48d43a 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java @@ -10,6 +10,7 @@ import io.opentelemetry.sdk.common.internal.ExceptionAttributeResolver; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.util.Arrays; import java.util.List; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -106,18 +107,28 @@ SdkTracerInstrumentation getTracerInstrumentation() { } /** - * Stops tracing, including shutting down processors and set to {@code true} {@link + * Stops tracing, including shutting down processors and sampler and set to {@code true} {@link * #hasBeenShutdown()}. * - * @return a {@link CompletableResultCode} that will be completed when the span processor is shut - * down. + * @return a {@link CompletableResultCode} that will be completed when the span processor and + * sampler are shut down. */ CompletableResultCode shutdown() { synchronized (lock) { if (shutdownResult != null) { return shutdownResult; } - shutdownResult = activeSpanProcessor.shutdown(); + + CompletableResultCode samplerShutdownResult = sampler.shutdown(); + + shutdownResult = + CompletableResultCode.ofAll( + Arrays.asList( + activeSpanProcessor.shutdown(), + samplerShutdownResult == null + ? CompletableResultCode.ofSuccess() + : samplerShutdownResult)); + return shutdownResult; } } From 0bcbbec8c85af8c62314ab5489619c08c1ea2963 Mon Sep 17 00:00:00 2001 From: Debashismitra01 Date: Tue, 7 Jul 2026 04:46:25 +0530 Subject: [PATCH 4/5] Update API compatibility reports --- .../opentelemetry-sdk-extension-jaeger-remote-sampler.txt | 6 ++++-- docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt index 0d80e31c1f9..0ca5622ab3a 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt @@ -1,2 +1,4 @@ -Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.65.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.63.0.jar -No changes. \ No newline at end of file +Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.64.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.63.0.jar +*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler (not serializable) + === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown() diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt index 583ee29da68..29677806989 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt @@ -1,4 +1,4 @@ -Comparing source compatibility of opentelemetry-sdk-trace-1.65.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.63.0.jar -*** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.trace.export.BatchSpanProcessor (not serializable) +Comparing source compatibility of opentelemetry-sdk-trace-1.64.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.63.0.jar +*** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.trace.samplers.Sampler (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 - +++ NEW METHOD: PUBLIC(+) STATIC(+) io.opentelemetry.sdk.trace.export.BatchSpanProcessor create(io.opentelemetry.sdk.trace.export.SpanExporter) + +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown() From 2675bec82624d3a000ee77a92842ec0153f0f824 Mon Sep 17 00:00:00 2001 From: Debashismitra01 Date: Sat, 11 Jul 2026 07:50:44 +0530 Subject: [PATCH 5/5] Address review feedback for sampler shutdown lifecycle --- ...etry-sdk-extension-jaeger-remote-sampler.txt | 4 +++- .../opentelemetry-sdk-trace.txt | 5 ++++- .../declarativeconfig/SamplerFactoryTest.java | 6 ++---- .../jaeger/sampler/JaegerRemoteSampler.java | 17 ++++++++++++----- .../jaeger/sampler/JaegerRemoteSamplerTest.java | 7 +++++-- .../sdk/trace/TracerSharedState.java | 8 +------- .../sdk/trace/samplers/Sampler.java | 9 ++++++++- .../trace/export/BatchSpanProcessorTest.java | 2 ++ .../trace/export/SimpleSpanProcessorTest.java | 2 ++ 9 files changed, 39 insertions(+), 21 deletions(-) diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt index 0ca5622ab3a..8052854dd9d 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-extension-jaeger-remote-sampler.txt @@ -1,4 +1,6 @@ -Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.64.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.63.0.jar +Comparing source compatibility of opentelemetry-sdk-extension-jaeger-remote-sampler-1.65.0-SNAPSHOT.jar against opentelemetry-sdk-extension-jaeger-remote-sampler-1.64.0.jar *** MODIFIED CLASS: PUBLIC FINAL io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + === UNCHANGED METHOD: PUBLIC void close() + +++ NEW ANNOTATION: java.lang.Deprecated +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown() diff --git a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt index 29677806989..b5b3a82f5bd 100644 --- a/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt +++ b/docs/apidiffs/current_vs_latest/opentelemetry-sdk-trace.txt @@ -1,4 +1,7 @@ -Comparing source compatibility of opentelemetry-sdk-trace-1.64.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.63.0.jar +Comparing source compatibility of opentelemetry-sdk-trace-1.65.0-SNAPSHOT.jar against opentelemetry-sdk-trace-1.64.0.jar *** MODIFIED INTERFACE: PUBLIC ABSTRACT io.opentelemetry.sdk.trace.samplers.Sampler (not serializable) === CLASS FILE FORMAT VERSION: 52.0 <- 52.0 + +++ NEW INTERFACE: java.io.Closeable + +++ NEW INTERFACE: java.lang.AutoCloseable + +++ NEW METHOD: PUBLIC(+) void close() +++ NEW METHOD: PUBLIC(+) io.opentelemetry.sdk.common.CompletableResultCode shutdown() diff --git a/sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/SamplerFactoryTest.java b/sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/SamplerFactoryTest.java index 110845bea71..9a6a1f599bf 100644 --- a/sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/SamplerFactoryTest.java +++ b/sdk-extensions/declarative-config/src/test/java/io/opentelemetry/sdk/autoconfigure/declarativeconfig/SamplerFactoryTest.java @@ -58,10 +58,8 @@ class SamplerFactoryTest { @ParameterizedTest @MethodSource("createArguments") void create(@Nullable SamplerModel model, Sampler expectedSampler) { - // Some samplers like JaegerRemoteSampler are Closeable - ensure these get cleaned up - if (expectedSampler instanceof Closeable) { - cleanup.addCloseable((Closeable) expectedSampler); - } + // // All samplers are Closeable - ensure these get cleaned up + cleanup.addCloseable(expectedSampler); List closeables = new ArrayList<>(); Sampler sampler = SamplerFactory.getInstance().create(model, context); diff --git a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java index e26dcabbd46..52a8b350e7c 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java +++ b/sdk-extensions/jaeger-remote-sampler/src/main/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSampler.java @@ -17,19 +17,19 @@ import io.opentelemetry.sdk.trace.data.LinkData; import io.opentelemetry.sdk.trace.samplers.Sampler; import io.opentelemetry.sdk.trace.samplers.SamplingResult; -import java.io.Closeable; import java.io.IOException; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; /** Remote sampler that gets sampling configuration from remote Jaeger server. */ -public final class JaegerRemoteSampler implements Sampler, Closeable { +public final class JaegerRemoteSampler implements Sampler { private static final Logger logger = Logger.getLogger(JaegerRemoteSampler.class.getName()); private static final String WORKER_THREAD_NAME = @@ -42,6 +42,8 @@ public final class JaegerRemoteSampler implements Sampler, Closeable { private volatile Sampler sampler; + private final AtomicBoolean isShutdown = new AtomicBoolean(); + private final GrpcSender grpcSender; JaegerRemoteSampler( @@ -177,15 +179,20 @@ public static JaegerRemoteSamplerBuilder builder() { } @Override + @SuppressWarnings("Interruption") public CompletableResultCode shutdown() { - pollFuture.cancel(false); + if (isShutdown.getAndSet(true)) { + return CompletableResultCode.ofSuccess(); + } + + pollFuture.cancel(true); pollExecutor.shutdownNow(); return grpcSender.shutdown(); } @Override - @SuppressWarnings("Interruption") + @Deprecated public void close() { - shutdown().join(10, TimeUnit.SECONDS); + shutdown(); } } diff --git a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java index 969bf04a934..88047b9f92d 100644 --- a/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java +++ b/sdk-extensions/jaeger-remote-sampler/src/test/java/io/opentelemetry/sdk/extension/trace/jaeger/sampler/JaegerRemoteSamplerTest.java @@ -24,6 +24,7 @@ import io.opentelemetry.exporter.internal.TlsUtil; import io.opentelemetry.exporter.sender.okhttp.internal.OkHttpGrpcSender; import io.opentelemetry.internal.testing.slf4j.SuppressLogger; +import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.common.export.GrpcStatusCode; import io.opentelemetry.sdk.extension.trace.jaeger.proto.api_v2.Sampling; import io.opentelemetry.sdk.extension.trace.jaeger.proto.api_v2.Sampling.RateLimitingSamplingStrategy; @@ -169,9 +170,11 @@ void shutdown() { .setServiceName(SERVICE_NAME) .build(); - assertThat(sampler).extracting("grpcSender").isInstanceOf(OkHttpGrpcSender.class); + CompletableResultCode first = sampler.shutdown(); + CompletableResultCode second = sampler.shutdown(); - assertThat(sampler.shutdown().join(10, TimeUnit.SECONDS).isSuccess()).isTrue(); + assertThat(first.join(10, TimeUnit.SECONDS).isSuccess()).isTrue(); + assertThat(second.isSuccess()).isTrue(); } @Test diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java index 78c7b48d43a..790933215c2 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/TracerSharedState.java @@ -119,15 +119,9 @@ CompletableResultCode shutdown() { return shutdownResult; } - CompletableResultCode samplerShutdownResult = sampler.shutdown(); - shutdownResult = CompletableResultCode.ofAll( - Arrays.asList( - activeSpanProcessor.shutdown(), - samplerShutdownResult == null - ? CompletableResultCode.ofSuccess() - : samplerShutdownResult)); + Arrays.asList(activeSpanProcessor.shutdown(), sampler.shutdown())); return shutdownResult; } diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java index 0b987d0ac53..17837cab691 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/samplers/Sampler.java @@ -13,12 +13,14 @@ import io.opentelemetry.context.Context; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.trace.data.LinkData; +import java.io.Closeable; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.annotation.concurrent.ThreadSafe; /** A Sampler is used to make decisions on {@link Span} sampling. */ @ThreadSafe -public interface Sampler { +public interface Sampler extends Closeable { /** * Returns a {@link Sampler} that always makes a "yes" {@link SamplingResult} for {@link Span} @@ -131,4 +133,9 @@ SamplingResult shouldSample( default CompletableResultCode shutdown() { return CompletableResultCode.ofSuccess(); } + + @Override + default void close() { + shutdown().join(10, TimeUnit.SECONDS); + } } diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorTest.java index b83e48efad8..5e9bc38ff78 100644 --- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorTest.java +++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorTest.java @@ -72,6 +72,8 @@ class BatchSpanProcessorTest { void setUp() { when(mockSpanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); when(mockSpanExporter.export(anyList())).thenReturn(CompletableResultCode.ofSuccess()); + + when(mockSampler.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); } @AfterEach diff --git a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/SimpleSpanProcessorTest.java b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/SimpleSpanProcessorTest.java index 62b1d59a84f..e5c860db4a7 100644 --- a/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/SimpleSpanProcessorTest.java +++ b/sdk/trace/src/test/java/io/opentelemetry/sdk/trace/export/SimpleSpanProcessorTest.java @@ -73,6 +73,8 @@ void setUp() { simpleSampledSpansProcessor = SimpleSpanProcessor.create(spanExporter); when(spanExporter.export(anyCollection())).thenReturn(CompletableResultCode.ofSuccess()); when(spanExporter.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); + + when(mockSampler.shutdown()).thenReturn(CompletableResultCode.ofSuccess()); } @Test