diff --git a/instrumentation/httpurlconnection/README.md b/instrumentation/httpurlconnection/README.md index eaff39f04..840085e6f 100644 --- a/instrumentation/httpurlconnection/README.md +++ b/instrumentation/httpurlconnection/README.md @@ -64,15 +64,28 @@ byteBuddy("io.opentelemetry.android:httpurlconnection-agent:AUTO_HTTP_URL_INSTRU To schedule a periodically running thread to conclude/report spans on any unreported, idle connections, add the below code in the function where your application starts ( that could be onCreate() method of first Activity/Fragment/Service): ```Java -HttpUrlInstrumentationConfig.setConnectionInactivityTimeoutMs(customTimeoutValue); //This is optional. Replace customTimeoutValue with a long data type value which denotes the connection inactivity timeout in milli seconds. Defaults to 10000ms -Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(HttpUrlInstrumentationConfig.getReportIdleConnectionRunnable(), 0, HttpUrlInstrumentationConfig.getReportIdleConnectionInterval(), TimeUnit.MILLISECONDS); +HttpUrlInstrumentation instrumentation = AndroidInstrumentationLoader.getInstrumentation(HttpUrlInstrumentation.class); +instrumentation.setConnectionInactivityTimeoutMs(customTimeoutValue); //This is optional. Replace customTimeoutValue with a long data type value which denotes the connection inactivity timeout in milli seconds. Defaults to 10000ms +Executors.newSingleThreadScheduledExecutor().scheduleWithFixedDelay(instrumentation.getReportIdleConnectionRunnable(), 0, instrumentation.getReportIdleConnectionInterval(), TimeUnit.MILLISECONDS); ``` -- `HttpUrlInstrumentationConfig.getReportIdleConnectionRunnable()` is the API to get the runnable. -- By default, connections inactive for 10000ms are reported. To optionally change the connection inactivity timeout call `HttpUrlInstrumentationConfig.setConnectionInactivityTimeoutMs(customTimeoutValue)` API as shown in above code snippet. -- It is efficient to run the harvester thread at the same time interval as the connection inactivity timeout used to identify the connections to be reported. `HttpUrlInstrumentationConfig.getReportIdleConnectionInterval()` is the API to get the same connection inactivity timeout interval (milliseconds) you have configured or the default value of 10000ms if not configured. +- `instrumentation.getReportIdleConnectionRunnable()` is the API to get the runnable. +- By default, connections inactive for 10000ms are reported. To optionally change the connection inactivity timeout call `instrumentation.setConnectionInactivityTimeoutMs(customTimeoutValue)` API as shown in above code snippet. +- It is efficient to run the harvester thread at the same time interval as the connection inactivity timeout used to identify the connections to be reported. `instrumentation.getReportIdleConnectionInterval()` is the API to get the same connection inactivity timeout interval (milliseconds) you have configured or the default value of 10000ms if not configured. #### Other Optional Configurations -You can optionally configure the automatic instrumentation by using the setters in [HttpUrlInstrumentationConfig](library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentationConfig.java). +You can optionally configure the automatic instrumentation by using the setters from [HttpUrlInstrumentation](library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java) +instance provided via the AndroidInstrumentationLoader as shown below: + +```java +HttpUrlInstrumentation instrumentation = AndroidInstrumentationLoader.getInstrumentation(HttpUrlInstrumentation.class); + +// Call `instrumentation` setters. +``` + +> [!NOTE] +> You must make sure to apply any configurations **before** initializing your OpenTelemetryRum +> instance (i.e. calling OpenTelemetryRum.builder()...build()). Otherwise your configs won't be +> taken into account during the RUM initialization process. After adding the plugin and the dependencies to your project, and after doing the required configurations, your requests will be traced automatically. diff --git a/instrumentation/httpurlconnection/library/build.gradle.kts b/instrumentation/httpurlconnection/library/build.gradle.kts index e1204c772..5a18dbd73 100644 --- a/instrumentation/httpurlconnection/library/build.gradle.kts +++ b/instrumentation/httpurlconnection/library/build.gradle.kts @@ -13,6 +13,7 @@ dependencies { api(platform(libs.opentelemetry.platform)) api(libs.opentelemetry.api) api(libs.opentelemetry.context) + api(project(":core")) implementation(libs.opentelemetry.instrumentation.apiSemconv) implementation(libs.opentelemetry.instrumentation.api) } diff --git a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentationConfig.java b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java similarity index 71% rename from instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentationConfig.java rename to instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java index 63976365a..a48cfc751 100644 --- a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentationConfig.java +++ b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java @@ -5,28 +5,33 @@ package io.opentelemetry.instrumentation.library.httpurlconnection; +import android.app.Application; +import com.google.auto.service.AutoService; +import io.opentelemetry.android.OpenTelemetryRum; +import io.opentelemetry.android.instrumentation.AndroidInstrumentation; import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; import io.opentelemetry.instrumentation.api.internal.HttpConstants; +import io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import org.jetbrains.annotations.NotNull; -/** Configuration for automatic instrumentation of HttpURLConnection/HttpsURLConnection requests. */ -public final class HttpUrlInstrumentationConfig { - private static List capturedRequestHeaders = new ArrayList<>(); - private static List capturedResponseHeaders = new ArrayList<>(); - private static Set knownMethods = HttpConstants.KNOWN_METHODS; - private static Map peerServiceMapping = new HashMap<>(); - private static boolean emitExperimentalHttpClientMetrics; +/** Instrumentation for HttpURLConnection requests. */ +@AutoService(AndroidInstrumentation.class) +public class HttpUrlInstrumentation implements AndroidInstrumentation { + private List capturedRequestHeaders = new ArrayList<>(); + private List capturedResponseHeaders = new ArrayList<>(); + private Set knownMethods = HttpConstants.KNOWN_METHODS; + private Map peerServiceMapping = new HashMap<>(); + private boolean emitExperimentalHttpClientMetrics; // Time (ms) to wait before assuming that an idle connection is no longer // in use and should be reported. - private static long connectionInactivityTimeoutMs = 10000; - - private HttpUrlInstrumentationConfig() {} + private long connectionInactivityTimeoutMs = 10000; /** * Configures the HTTP request headers that will be captured as span attributes as described in @@ -40,11 +45,11 @@ private HttpUrlInstrumentationConfig() {} * * @param requestHeaders A list of HTTP header names. */ - public static void setCapturedRequestHeaders(List requestHeaders) { - HttpUrlInstrumentationConfig.capturedRequestHeaders = new ArrayList<>(requestHeaders); + public void setCapturedRequestHeaders(List requestHeaders) { + capturedRequestHeaders = new ArrayList<>(requestHeaders); } - public static List getCapturedRequestHeaders() { + public List getCapturedRequestHeaders() { return capturedRequestHeaders; } @@ -60,11 +65,11 @@ public static List getCapturedRequestHeaders() { * * @param responseHeaders A list of HTTP header names. */ - public static void setCapturedResponseHeaders(List responseHeaders) { - HttpUrlInstrumentationConfig.capturedResponseHeaders = new ArrayList<>(responseHeaders); + public void setCapturedResponseHeaders(List responseHeaders) { + capturedResponseHeaders = new ArrayList<>(responseHeaders); } - public static List getCapturedResponseHeaders() { + public List getCapturedResponseHeaders() { return capturedResponseHeaders; } @@ -83,11 +88,11 @@ public static List getCapturedResponseHeaders() { * * @param knownMethods A set of recognized HTTP request methods. */ - public static void setKnownMethods(Set knownMethods) { - HttpUrlInstrumentationConfig.knownMethods = new HashSet<>(knownMethods); + public void setKnownMethods(Set knownMethods) { + this.knownMethods = new HashSet<>(knownMethods); } - public static Set getKnownMethods() { + public Set getKnownMethods() { return knownMethods; } @@ -96,11 +101,11 @@ public static Set getKnownMethods() { * href="https://github.com/open-telemetry/opentelemetry-specification/blob/4f23dce407b6fcaba34a049df7c3d41cdd58cb77/specification/trace/semantic_conventions/span-general.md#general-remote-service-attributes">the * specification. */ - public static void setPeerServiceMapping(Map peerServiceMapping) { - HttpUrlInstrumentationConfig.peerServiceMapping = new HashMap<>(peerServiceMapping); + public void setPeerServiceMapping(Map peerServiceMapping) { + this.peerServiceMapping = new HashMap<>(peerServiceMapping); } - public static PeerServiceResolver newPeerServiceResolver() { + public PeerServiceResolver newPeerServiceResolver() { return PeerServiceResolver.create(peerServiceMapping); } @@ -109,16 +114,20 @@ public static PeerServiceResolver newPeerServiceResolver() { * href="https://github.com/open-telemetry/opentelemetry-specification/blob/4f23dce407b6fcaba34a049df7c3d41cdd58cb77/specification/metrics/semantic_conventions/http-metrics.md#http-client">the * experimental HTTP client metrics. */ - public static void setEmitExperimentalHttpClientMetrics( - boolean emitExperimentalHttpClientMetrics) { - HttpUrlInstrumentationConfig.emitExperimentalHttpClientMetrics = - emitExperimentalHttpClientMetrics; + public void setEmitExperimentalHttpClientMetrics(boolean emitExperimentalHttpClientMetrics) { + this.emitExperimentalHttpClientMetrics = emitExperimentalHttpClientMetrics; } - public static boolean emitExperimentalHttpClientMetrics() { + public boolean emitExperimentalHttpClientMetrics() { return emitExperimentalHttpClientMetrics; } + @Override + public void install( + @NotNull Application application, @NotNull OpenTelemetryRum openTelemetryRum) { + HttpUrlConnectionSingletons.configure(this, openTelemetryRum.getOpenTelemetry()); + } + /** * Configures the connection inactivity timeout in milliseconds. * @@ -135,11 +144,11 @@ public static boolean emitExperimentalHttpClientMetrics() { * @param timeoutMs the timeout period in milliseconds. Must be non-negative. * @throws IllegalArgumentException if {@code timeoutMs} is negative. */ - public static void setConnectionInactivityTimeoutMs(long timeoutMs) { + public void setConnectionInactivityTimeoutMs(long timeoutMs) { if (timeoutMs < 0) { throw new IllegalArgumentException("timeoutMs must be non-negative"); } - HttpUrlInstrumentationConfig.connectionInactivityTimeoutMs = timeoutMs; + connectionInactivityTimeoutMs = timeoutMs; } /** @@ -150,8 +159,8 @@ public static void setConnectionInactivityTimeoutMs(long timeoutMs) { * * @param timeoutMsForTesting the timeout period in milliseconds. */ - public static void setConnectionInactivityTimeoutMsForTesting(long timeoutMsForTesting) { - HttpUrlInstrumentationConfig.connectionInactivityTimeoutMs = timeoutMsForTesting; + public void setConnectionInactivityTimeoutMsForTesting(long timeoutMsForTesting) { + connectionInactivityTimeoutMs = timeoutMsForTesting; } /** @@ -161,7 +170,7 @@ public static void setConnectionInactivityTimeoutMsForTesting(long timeoutMsForT * * @return The idle connection reporting runnable */ - public static Runnable getReportIdleConnectionRunnable() { + public Runnable getReportIdleConnectionRunnable() { return new Runnable() { @Override public void run() { @@ -181,7 +190,7 @@ public String toString() { * * @return The interval duration in ms */ - public static long getReportIdleConnectionInterval() { + public long getReportIdleConnectionInterval() { return connectionInactivityTimeoutMs; } } diff --git a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java index 7d144a78e..e2d67a180 100644 --- a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java +++ b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlReplacements.java @@ -5,12 +5,10 @@ package io.opentelemetry.instrumentation.library.httpurlconnection; -import static io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons.instrumenter; -import static io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons.openTelemetryInstance; - import android.annotation.SuppressLint; import android.os.SystemClock; import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons; import io.opentelemetry.instrumentation.library.httpurlconnection.internal.RequestPropertySetter; import java.io.IOException; import java.io.InputStream; @@ -268,7 +266,8 @@ private static void endTracing(URLConnection connection, int responseCode, Throw HttpURLConnectionInfo info = activeURLConnections.get(connection); if (info != null && !info.reported) { Context context = info.context; - instrumenter().end(context, connection, responseCode, error); + HttpUrlConnectionSingletons.instrumenter() + .end(context, connection, responseCode, error); info.reported = true; activeURLConnections.remove(connection); } @@ -276,12 +275,13 @@ private static void endTracing(URLConnection connection, int responseCode, Throw private static void startTracingAtFirstConnection(URLConnection connection) { Context parentContext = Context.current(); - if (!instrumenter().shouldStart(parentContext, connection)) { + if (!HttpUrlConnectionSingletons.instrumenter().shouldStart(parentContext, connection)) { return; } if (!activeURLConnections.containsKey(connection)) { - Context context = instrumenter().start(parentContext, connection); + Context context = + HttpUrlConnectionSingletons.instrumenter().start(parentContext, connection); activeURLConnections.put(connection, new HttpURLConnectionInfo(context)); try { injectContextToRequest(connection, context); @@ -301,7 +301,7 @@ private static void startTracingAtFirstConnection(URLConnection connection) { } private static void injectContextToRequest(URLConnection connection, Context context) { - openTelemetryInstance() + HttpUrlConnectionSingletons.openTelemetryInstance() .getPropagators() .getTextMapPropagator() .inject(context, connection, RequestPropertySetter.INSTANCE); diff --git a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/internal/HttpUrlConnectionSingletons.java b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/internal/HttpUrlConnectionSingletons.java index 052a98884..e55c4c823 100644 --- a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/internal/HttpUrlConnectionSingletons.java +++ b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/internal/HttpUrlConnectionSingletons.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.library.httpurlconnection.internal; -import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientExperimentalMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.http.HttpClientPeerServiceAttributesExtractor; @@ -18,41 +17,40 @@ import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractor; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanNameExtractorBuilder; import io.opentelemetry.instrumentation.api.semconv.http.HttpSpanStatusExtractor; -import io.opentelemetry.instrumentation.library.httpurlconnection.HttpUrlInstrumentationConfig; +import io.opentelemetry.instrumentation.library.httpurlconnection.HttpUrlInstrumentation; import java.net.URLConnection; public final class HttpUrlConnectionSingletons { - private static volatile Instrumenter instrumenter; + private static Instrumenter instrumenter; private static final String INSTRUMENTATION_NAME = "io.opentelemetry.android.http-url-connection"; - private static final Object lock = new Object(); private static OpenTelemetry openTelemetryInstance; - public static Instrumenter createInstrumenter() { + public static void configure( + HttpUrlInstrumentation instrumentation, OpenTelemetry openTelemetry) { HttpUrlHttpAttributesGetter httpAttributesGetter = new HttpUrlHttpAttributesGetter(); HttpSpanNameExtractorBuilder httpSpanNameExtractorBuilder = HttpSpanNameExtractor.builder(httpAttributesGetter) - .setKnownMethods(HttpUrlInstrumentationConfig.getKnownMethods()); + .setKnownMethods(instrumentation.getKnownMethods()); HttpClientAttributesExtractorBuilder httpClientAttributesExtractorBuilder = HttpClientAttributesExtractor.builder(httpAttributesGetter) .setCapturedRequestHeaders( - HttpUrlInstrumentationConfig.getCapturedRequestHeaders()) + instrumentation.getCapturedRequestHeaders()) .setCapturedResponseHeaders( - HttpUrlInstrumentationConfig.getCapturedResponseHeaders()) - .setKnownMethods(HttpUrlInstrumentationConfig.getKnownMethods()); + instrumentation.getCapturedResponseHeaders()) + .setKnownMethods(instrumentation.getKnownMethods()); HttpClientPeerServiceAttributesExtractor httpClientPeerServiceAttributesExtractor = HttpClientPeerServiceAttributesExtractor.create( - httpAttributesGetter, - HttpUrlInstrumentationConfig.newPeerServiceResolver()); + httpAttributesGetter, instrumentation.newPeerServiceResolver()); - openTelemetryInstance = GlobalOpenTelemetry.get(); + openTelemetryInstance = openTelemetry; InstrumenterBuilder builder = Instrumenter.builder( @@ -65,23 +63,16 @@ public static Instrumenter createInstrumenter() { .addAttributesExtractor(httpClientPeerServiceAttributesExtractor) .addOperationMetrics(HttpClientMetrics.get()); - if (HttpUrlInstrumentationConfig.emitExperimentalHttpClientMetrics()) { + if (instrumentation.emitExperimentalHttpClientMetrics()) { builder.addAttributesExtractor( HttpExperimentalAttributesExtractor.create(httpAttributesGetter)) .addOperationMetrics(HttpClientExperimentalMetrics.get()); } - return builder.buildClientInstrumenter(RequestPropertySetter.INSTANCE); + instrumenter = builder.buildClientInstrumenter(RequestPropertySetter.INSTANCE); } public static Instrumenter instrumenter() { - if (instrumenter == null) { - synchronized (lock) { - if (instrumenter == null) { - instrumenter = createInstrumenter(); - } - } - } return instrumenter; } diff --git a/instrumentation/httpurlconnection/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/httpurlconnection/InstrumentationTest.kt b/instrumentation/httpurlconnection/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/httpurlconnection/InstrumentationTest.kt index 5796ff599..fe90695a6 100644 --- a/instrumentation/httpurlconnection/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/httpurlconnection/InstrumentationTest.kt +++ b/instrumentation/httpurlconnection/testing/src/androidTest/kotlin/io/opentelemetry/instrumentation/library/httpurlconnection/InstrumentationTest.kt @@ -5,55 +5,43 @@ package io.opentelemetry.instrumentation.library.httpurlconnection -import io.opentelemetry.android.test.common.OpenTelemetryTestUtils +import io.opentelemetry.android.instrumentation.AndroidInstrumentationLoader.Companion.getInstrumentation +import io.opentelemetry.android.test.common.OpenTelemetryRumRule import io.opentelemetry.instrumentation.library.httpurlconnection.HttpUrlConnectionTestUtil.executeGet import io.opentelemetry.instrumentation.library.httpurlconnection.HttpUrlConnectionTestUtil.post -import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter import org.assertj.core.api.Assertions.assertThat -import org.junit.After -import org.junit.BeforeClass +import org.junit.Rule import org.junit.Test import java.util.concurrent.Executors import java.util.concurrent.TimeUnit class InstrumentationTest { - companion object { - private val inMemorySpanExporter: InMemorySpanExporter = InMemorySpanExporter.create() - - @JvmStatic - @BeforeClass - fun setUpClass() { - OpenTelemetryTestUtils.setUpSpanExporter(inMemorySpanExporter) - } - } - - @After - fun tearDown() { - inMemorySpanExporter.reset() - } + @JvmField + @Rule + var openTelemetryRumRule: OpenTelemetryRumRule = OpenTelemetryRumRule() @Test fun testHttpUrlConnectionGetRequest_ShouldBeTraced() { executeGet("http://httpbin.org/get") - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) } @Test fun testHttpUrlConnectionPostRequest_ShouldBeTraced() { post("http://httpbin.org/post") - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) } @Test fun testHttpUrlConnectionGetRequest_WhenNoStreamFetchedAndNoDisconnectCalled_ShouldNotBeTraced() { executeGet("http://httpbin.org/get", false, false) - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(0) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(0) } @Test fun testHttpUrlConnectionGetRequest_WhenNoStreamFetchedButDisconnectCalled_ShouldBeTraced() { executeGet("http://httpbin.org/get", false) - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) } @Test @@ -72,7 +60,7 @@ class InstrumentationTest { .withFailMessage("Test could not be completed as tasks did not complete within the 2s timeout period.") .isTrue() - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(4) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(4) } finally { if (!executor.isShutdown) { executor.shutdownNow() @@ -82,11 +70,11 @@ class InstrumentationTest { @Test fun testHttpUrlConnectionRequest_ContextPropagationHappensAsExpected() { - val parentSpan = OpenTelemetryTestUtils.getSpan() + val parentSpan = openTelemetryRumRule.getSpan() parentSpan.makeCurrent().use { executeGet("http://httpbin.org/get") - val spanDataList = inMemorySpanExporter.finishedSpanItems + val spanDataList = openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems if (spanDataList.isNotEmpty()) { val currentSpanData = spanDataList[0] assertThat(currentSpanData.traceId).isEqualTo(parentSpan.spanContext.traceId) @@ -94,20 +82,30 @@ class InstrumentationTest { } parentSpan.end() - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(2) + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(2) } @Test fun testHttpUrlConnectionGetRequest_WhenNoStreamFetchedAndNoDisconnectCalledButHarvesterScheduled_ShouldBeTraced() { executeGet("http://httpbin.org/get", false, false) + + // no span created without harvester thread + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(0) + + val instrumentation = + getInstrumentation( + HttpUrlInstrumentation::class.java, + ) // setting a -1ms connection inactivity timeout for testing to ensure harvester sees it as 1ms elapsed // and we don't have to include any wait timers in the test. 0ms does not work as the time difference // between last connection activity and harvester time elapsed check is much lesser than 1ms due to // our high speed modern CPUs. - HttpUrlInstrumentationConfig.setConnectionInactivityTimeoutMsForTesting(-1) + instrumentation?.setConnectionInactivityTimeoutMsForTesting(-1) // Running the harvester runnable once instead of scheduling it to run periodically, // so we can synchronously assert instead of waiting for another threads execution to finish - HttpUrlInstrumentationConfig.getReportIdleConnectionRunnable().run() - assertThat(inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) + instrumentation?.getReportIdleConnectionRunnable()?.run() + + // span created with harvester thread + assertThat(openTelemetryRumRule.inMemorySpanExporter.finishedSpanItems.size).isEqualTo(1) } } diff --git a/test-common/src/main/kotlin/io/opentelemetry/android/test/common/OpenTelemetryTestUtils.kt b/test-common/src/main/kotlin/io/opentelemetry/android/test/common/OpenTelemetryTestUtils.kt deleted file mode 100644 index bd1e07f5a..000000000 --- a/test-common/src/main/kotlin/io/opentelemetry/android/test/common/OpenTelemetryTestUtils.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package io.opentelemetry.android.test.common - -import io.opentelemetry.api.GlobalOpenTelemetry -import io.opentelemetry.api.OpenTelemetry -import io.opentelemetry.api.trace.Span -import io.opentelemetry.sdk.OpenTelemetrySdk -import io.opentelemetry.sdk.trace.SdkTracerProvider -import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor -import io.opentelemetry.sdk.trace.export.SpanExporter - -object OpenTelemetryTestUtils { - lateinit var openTelemetry: OpenTelemetry - - @JvmStatic - fun getSpan(): Span { - return openTelemetry.getTracer("TestTracer").spanBuilder("A Span").startSpan() - } - - @JvmStatic - fun setUpSpanExporter(spanExporter: SpanExporter) { - openTelemetry = - OpenTelemetrySdk.builder() - .setTracerProvider(getSimpleTracerProvider(spanExporter)) - .build() - - GlobalOpenTelemetry.resetForTest() - GlobalOpenTelemetry.set(openTelemetry) - } - - private fun getSimpleTracerProvider(spanExporter: SpanExporter): SdkTracerProvider { - return SdkTracerProvider.builder() - .addSpanProcessor(SimpleSpanProcessor.create(spanExporter)) - .build() - } -}