From 0357414c4c1ad383c517274b47236bbe34fc4e78 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Wed, 17 Mar 2021 14:38:06 +0900 Subject: [PATCH 1/7] Replace ArrayBlockingQueue with jctools queue. --- dependencyManagement/build.gradle.kts | 1 + sdk/trace-shaded-deps/build.gradle.kts | 22 +++++++++++++++++++ .../sdk/trace/internal/JcTools.java | 17 ++++++++++++++ sdk/trace/build.gradle.kts | 8 +++++++ .../sdk/trace/export/BatchSpanProcessor.java | 15 +++++++------ settings.gradle.kts | 1 + 6 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 sdk/trace-shaded-deps/build.gradle.kts create mode 100644 sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java diff --git a/dependencyManagement/build.gradle.kts b/dependencyManagement/build.gradle.kts index b328435b1c2..3cc3efba984 100644 --- a/dependencyManagement/build.gradle.kts +++ b/dependencyManagement/build.gradle.kts @@ -92,6 +92,7 @@ val DEPENDENCIES = listOf( "org.awaitility:awaitility:4.0.3", "org.codehaus.mojo:animal-sniffer-annotations:1.20", "org.curioswitch.curiostack:protobuf-jackson:1.2.0", + "org.jctools:jctools-core:3.3.0", "org.junit-pioneer:junit-pioneer:1.3.8", "org.skyscreamer:jsonassert:1.5.0", "org.slf4j:slf4j-simple:1.7.30" diff --git a/sdk/trace-shaded-deps/build.gradle.kts b/sdk/trace-shaded-deps/build.gradle.kts new file mode 100644 index 00000000000..6ca21397386 --- /dev/null +++ b/sdk/trace-shaded-deps/build.gradle.kts @@ -0,0 +1,22 @@ +plugins { + `java-library` + + id("com.github.johnrengelman.shadow") +} + +// This project is not published, it is bundled into :sdk:trace + +description = "Internal use only - shaded dependencies of OpenTelemetry SDK for Tracing" +extra["moduleName"] = "io.opentelemetry.sdk.trace.internal" + +dependencies { + implementation("org.jctools:jctools-core") +} + +tasks { + shadowJar { + minimize() + + relocate("org.jctools", "io.opentelemetry.internal.shaded.jctools") + } +} diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java new file mode 100644 index 00000000000..611fad8c548 --- /dev/null +++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java @@ -0,0 +1,17 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.sdk.trace.internal; + +import org.jctools.queues.MpscCompoundQueue; + +public final class JcTools { + + public static MpscCompoundQueue newMpscCompoundQueue(int capacity) { + return new MpscCompoundQueue<>(capacity); + } + + private JcTools() {} +} diff --git a/sdk/trace/build.gradle.kts b/sdk/trace/build.gradle.kts index e0658542c22..e47166d8584 100644 --- a/sdk/trace/build.gradle.kts +++ b/sdk/trace/build.gradle.kts @@ -9,10 +9,14 @@ plugins { description = "OpenTelemetry SDK For Tracing" extra["moduleName"] = "io.opentelemetry.sdk.trace" +evaluationDependsOn(":sdk:trace-shaded-deps") + dependencies { api(project(":api:all")) api(project(":sdk:common")) + compileOnly(project(path=":sdk:trace-shaded-deps", configuration="shadow")) + implementation(project(":api:metrics")) implementation(project(":semconv")) @@ -62,4 +66,8 @@ tasks { File(propertiesDir, "version.properties").writeText("sdk.version=${project.version}") } } + + jar { + from(zipTree(project(":sdk:trace-shaded-deps").tasks.named("shadowJar").get().archiveFile)) + } } diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java index 403e3ec4dfe..9652413a44c 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java @@ -11,16 +11,16 @@ import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.common.Labels; import io.opentelemetry.context.Context; +import io.opentelemetry.internal.shaded.jctools.queues.MessagePassingQueue; import io.opentelemetry.sdk.common.CompletableResultCode; import io.opentelemetry.sdk.internal.DaemonThreadFactory; import io.opentelemetry.sdk.trace.ReadWriteSpan; import io.opentelemetry.sdk.trace.ReadableSpan; import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.internal.JcTools; import java.util.ArrayList; import java.util.Collections; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -72,7 +72,7 @@ public static BatchSpanProcessorBuilder builder(SpanExporter spanExporter) { scheduleDelayNanos, maxExportBatchSize, exporterTimeoutNanos, - new ArrayBlockingQueue<>(maxQueueSize)); + JcTools.newMpscCompoundQueue(maxQueueSize)); Thread workerThread = new DaemonThreadFactory(WORKER_THREAD_NAME).newThread(worker); workerThread.start(); } @@ -131,7 +131,7 @@ private static final class Worker implements Runnable { private long nextExportTime; - private final BlockingQueue queue; + private final MessagePassingQueue queue; private final AtomicReference flushRequested = new AtomicReference<>(); private volatile boolean continueWork = true; @@ -142,7 +142,7 @@ private Worker( long scheduleDelayNanos, int maxExportBatchSize, long exporterTimeoutNanos, - BlockingQueue queue) { + MessagePassingQueue queue) { this.spanExporter = spanExporter; this.scheduleDelayNanos = scheduleDelayNanos; this.maxExportBatchSize = maxExportBatchSize; @@ -193,11 +193,12 @@ public void run() { } try { - ReadableSpan lastElement = queue.poll(100, TimeUnit.MILLISECONDS); + // DO NOT SUBMIT + ReadableSpan lastElement = queue.poll(); if (lastElement != null) { batch.add(lastElement.toSpanData()); } - } catch (InterruptedException e) { + } catch (Throwable e) { Thread.currentThread().interrupt(); return; } diff --git a/settings.gradle.kts b/settings.gradle.kts index 77306ff0dc5..568b6079ad0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -62,6 +62,7 @@ include(":sdk:common") include(":sdk:metrics") include(":sdk:testing") include(":sdk:trace") +include(":sdk:trace-shaded-deps") include(":sdk-extensions:async-processor") include(":sdk-extensions:autoconfigure") include(":sdk-extensions:aws") From c545b2fc61714865f270b1e86d58f5d1ae22e997 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 19 Mar 2021 12:17:34 +0900 Subject: [PATCH 2/7] Finish --- sdk-extensions/autoconfigure/build.gradle.kts | 2 ++ .../TracerProviderConfigurationTest.java | 9 ++++----- .../sdk/trace/internal/JcTools.java | 19 +++++++++++++++++++ sdk/trace/build.gradle.kts | 3 ++- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/sdk-extensions/autoconfigure/build.gradle.kts b/sdk-extensions/autoconfigure/build.gradle.kts index d660ed39a87..e104346eeb1 100644 --- a/sdk-extensions/autoconfigure/build.gradle.kts +++ b/sdk-extensions/autoconfigure/build.gradle.kts @@ -35,6 +35,8 @@ dependencies { compileOnly("io.prometheus:simpleclient_httpserver") compileOnly(project(":exporters:zipkin")) + testImplementation(project(path=":sdk:trace-shaded-deps")) + testImplementation(project(":proto")) testImplementation(project(":sdk:testing")) testImplementation("com.linecorp.armeria:armeria-junit5") diff --git a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java index ad590824048..04dfb55dc8d 100644 --- a/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java +++ b/sdk-extensions/autoconfigure/src/test/java/io/opentelemetry/sdk/autoconfigure/TracerProviderConfigurationTest.java @@ -17,11 +17,12 @@ import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.sdk.trace.export.SpanExporter; +import io.opentelemetry.sdk.trace.internal.JcTools; import io.opentelemetry.sdk.trace.samplers.Sampler; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ArrayBlockingQueue; +import java.util.Queue; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -97,8 +98,7 @@ void configureSpanProcessor_empty() { assertThat(worker) .extracting("queue") .isInstanceOfSatisfying( - ArrayBlockingQueue.class, - queue -> assertThat(queue.remainingCapacity()).isEqualTo(2048)); + Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2048)); assertThat(worker).extracting("spanExporter").isEqualTo(mockSpanExporter); }); } finally { @@ -133,8 +133,7 @@ void configureSpanProcessor_configured() { assertThat(worker) .extracting("queue") .isInstanceOfSatisfying( - ArrayBlockingQueue.class, - queue -> assertThat(queue.remainingCapacity()).isEqualTo(2)); + Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2)); assertThat(worker).extracting("spanExporter").isEqualTo(mockSpanExporter); }); } finally { diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java index 586dcbf058c..53ef941b1f9 100644 --- a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java +++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java @@ -6,13 +6,32 @@ package io.opentelemetry.sdk.trace.internal; import java.util.Queue; +import org.jctools.queues.MessagePassingQueue; +import org.jctools.queues.MpscArrayQueue; import org.jctools.queues.MpscCompoundQueue; +/** Internal accessor of JCTools package for fast queues. */ public final class JcTools { + /** + * Returns a new {@link Queue} appopriate for use with multiple producers and a single consumer + * when items do not need to be strictly ordered. + */ public static Queue newMpscCompoundQueue(int capacity) { + if (capacity < Runtime.getRuntime().availableProcessors()) { + // This should only be true in tests. + return new MpscArrayQueue<>(capacity); + } return new MpscCompoundQueue<>(capacity); } + /** + * Returns the capacity of the {@link Queue}, which must be a JcTools queue. We cast to the + * implementation so callers do not need to use the shaded classes. + */ + public static long capacity(Queue queue) { + return ((MessagePassingQueue) queue).capacity(); + } + private JcTools() {} } diff --git a/sdk/trace/build.gradle.kts b/sdk/trace/build.gradle.kts index e47166d8584..5e1b6d28aec 100644 --- a/sdk/trace/build.gradle.kts +++ b/sdk/trace/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { api(project(":api:all")) api(project(":sdk:common")) - compileOnly(project(path=":sdk:trace-shaded-deps", configuration="shadow")) + compileOnly(project(":sdk:trace-shaded-deps")) implementation(project(":api:metrics")) implementation(project(":semconv")) @@ -68,6 +68,7 @@ tasks { } jar { + inputs.files(project(":sdk:trace-shaded-deps").file("src")) from(zipTree(project(":sdk:trace-shaded-deps").tasks.named("shadowJar").get().archiveFile)) } } From 3552fbee64c0eb15da49d911c30b1b76d39d48a5 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 19 Mar 2021 12:45:33 +0900 Subject: [PATCH 3/7] ArrayQueue --- .../java/io/opentelemetry/sdk/trace/internal/JcTools.java | 7 +------ sdk/trace/build.gradle.kts | 1 + .../export/BatchSpanProcessorMultiThreadBenchmark.java | 2 +- .../sdk/trace/export/DelayingSpanExporter.java | 1 + 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java index 53ef941b1f9..b571b86a4ca 100644 --- a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java +++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java @@ -8,7 +8,6 @@ import java.util.Queue; import org.jctools.queues.MessagePassingQueue; import org.jctools.queues.MpscArrayQueue; -import org.jctools.queues.MpscCompoundQueue; /** Internal accessor of JCTools package for fast queues. */ public final class JcTools { @@ -18,11 +17,7 @@ public final class JcTools { * when items do not need to be strictly ordered. */ public static Queue newMpscCompoundQueue(int capacity) { - if (capacity < Runtime.getRuntime().availableProcessors()) { - // This should only be true in tests. - return new MpscArrayQueue<>(capacity); - } - return new MpscCompoundQueue<>(capacity); + return new MpscArrayQueue<>(capacity); } /** diff --git a/sdk/trace/build.gradle.kts b/sdk/trace/build.gradle.kts index 5e1b6d28aec..f868b7fdf85 100644 --- a/sdk/trace/build.gradle.kts +++ b/sdk/trace/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { testImplementation("com.google.guava:guava") jmh(project(":sdk:metrics")) + jmh(project(":sdk:trace-shaded-deps")) jmh(project(":sdk:testing")) { // JMH doesn"t handle dependencies that are duplicated between the main and jmh // configurations properly, but luckily here it"s simple enough to just exclude transitive diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java index 69fa730fe75..6284fae5dfe 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java @@ -42,7 +42,7 @@ public static class BenchmarkState { private long exportedSpans; private long droppedSpans; - @Setup(Level.Iteration) + @Setup(Level.Trial) public final void setup() { sdkMeterProvider = SdkMeterProvider.builder().buildAndRegisterGlobal(); SpanExporter exporter = new DelayingSpanExporter(delayMs); diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/DelayingSpanExporter.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/DelayingSpanExporter.java index ff0b2815959..40998ac42af 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/DelayingSpanExporter.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/DelayingSpanExporter.java @@ -38,6 +38,7 @@ public CompletableResultCode flush() { @Override public CompletableResultCode shutdown() { + executor.shutdown(); return CompletableResultCode.ofSuccess(); } } From 73aac08bcf0b9bbac871041488d7c2e23b525612 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 19 Mar 2021 12:56:34 +0900 Subject: [PATCH 4/7] Fix dependency --- sdk/trace/build.gradle.kts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdk/trace/build.gradle.kts b/sdk/trace/build.gradle.kts index f868b7fdf85..476eaeeddd1 100644 --- a/sdk/trace/build.gradle.kts +++ b/sdk/trace/build.gradle.kts @@ -70,6 +70,8 @@ tasks { jar { inputs.files(project(":sdk:trace-shaded-deps").file("src")) - from(zipTree(project(":sdk:trace-shaded-deps").tasks.named("shadowJar").get().archiveFile)) + val shadowJar = project(":sdk:trace-shaded-deps").tasks.named("shadowJar") + from(zipTree(shadowJar.get().archiveFile)) + dependsOn(shadowJar) } } From 8573ef77eb7f2c2c7754711bbade2635dd3fe1b2 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Fri, 19 Mar 2021 12:58:36 +0900 Subject: [PATCH 5/7] Drift --- .../java/io/opentelemetry/sdk/trace/internal/JcTools.java | 5 ++--- .../opentelemetry/sdk/trace/export/BatchSpanProcessor.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java index b571b86a4ca..255d04138c8 100644 --- a/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java +++ b/sdk/trace-shaded-deps/src/main/java/io/opentelemetry/sdk/trace/internal/JcTools.java @@ -13,10 +13,9 @@ public final class JcTools { /** - * Returns a new {@link Queue} appopriate for use with multiple producers and a single consumer - * when items do not need to be strictly ordered. + * Returns a new {@link Queue} appropriate for use with multiple producers and a single consumer. */ - public static Queue newMpscCompoundQueue(int capacity) { + public static Queue newMpscArrayQueue(int capacity) { return new MpscArrayQueue<>(capacity); } diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java index 92a4fe57c00..fd9865b0334 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java @@ -75,7 +75,7 @@ public static BatchSpanProcessorBuilder builder(SpanExporter spanExporter) { scheduleDelayNanos, maxExportBatchSize, exporterTimeoutNanos, - JcTools.newMpscCompoundQueue(maxQueueSize)); + JcTools.newMpscArrayQueue(maxQueueSize)); Thread workerThread = new DaemonThreadFactory(WORKER_THREAD_NAME).newThread(worker); workerThread.start(); } From 1f22b514a0e602ca7b8c78434bdfd9fb10b07bdc Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Wed, 31 Mar 2021 10:36:03 +0900 Subject: [PATCH 6/7] Memory note --- .../io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java | 3 --- .../sdk/trace/export/BatchSpanProcessorBuilder.java | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java index 3d48f0af7f2..965e9fcb89d 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessor.java @@ -38,9 +38,6 @@ * {@code maxQueueSize} maximum size, if queue is full spans are dropped). Spans are exported either * when there are {@code maxExportBatchSize} pending spans or {@code scheduleDelayNanos} has passed * since the last export finished. - * - *

This batch {@link SpanProcessor} can cause high contention in a very high traffic service. - * TODO: Add a link to the SpanProcessor that uses Disruptor as alternative with low contention. */ public final class BatchSpanProcessor implements SpanProcessor { diff --git a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorBuilder.java b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorBuilder.java index 428623def21..90e012fe916 100644 --- a/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorBuilder.java +++ b/sdk/trace/src/main/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorBuilder.java @@ -86,7 +86,8 @@ long getExporterTimeoutNanos() { } /** - * Sets the maximum number of Spans that are kept in the queue before start dropping. + * Sets the maximum number of Spans that are kept in the queue before start dropping. More memory + * than this value may be allocated to optimize queue access. * *

See the BatchSampledSpansProcessor class description for a high-level design description of * this class. From 029390f5742f9f8954cc871aa5e70819a8019285 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Wed, 31 Mar 2021 11:51:32 +0900 Subject: [PATCH 7/7] Iteration --- .../export/BatchSpanProcessorMultiThreadBenchmark.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java index 6284fae5dfe..ba6a05b2092 100644 --- a/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java +++ b/sdk/trace/src/jmh/java/io/opentelemetry/sdk/trace/export/BatchSpanProcessorMultiThreadBenchmark.java @@ -42,7 +42,7 @@ public static class BenchmarkState { private long exportedSpans; private long droppedSpans; - @Setup(Level.Trial) + @Setup(Level.Iteration) public final void setup() { sdkMeterProvider = SdkMeterProvider.builder().buildAndRegisterGlobal(); SpanExporter exporter = new DelayingSpanExporter(delayMs); @@ -57,10 +57,6 @@ public final void recordMetrics() { new BatchSpanProcessorMetrics(sdkMeterProvider.collectAllMetrics(), numThreads); exportedSpans = metrics.exportedSpans(); droppedSpans = metrics.droppedSpans(); - } - - @TearDown(Level.Trial) - public final void tearDown() { processor.shutdown().join(10, TimeUnit.SECONDS); } }