From 14529383038cea0ec15c36cc7e81939a5d46b935 Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Wed, 6 Sep 2023 16:05:38 -0700 Subject: [PATCH 1/4] allow user to customize propagators --- .../android/OpenTelemetryRumBuilder.java | 56 +++++++++++++++++++ .../android/OpenTelemetryRumBuilderTest.java | 38 +++++++++++++ 2 files changed, 94 insertions(+) diff --git a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java index b9e1b6361..9d9c67b83 100644 --- a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java +++ b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java @@ -7,6 +7,10 @@ import android.app.Application; import io.opentelemetry.android.instrumentation.InstrumentedApplication; +import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; +import io.opentelemetry.context.propagation.ContextPropagators; +import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.logs.SdkLoggerProvider; import io.opentelemetry.sdk.logs.SdkLoggerProviderBuilder; @@ -16,7 +20,9 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -39,8 +45,26 @@ public final class OpenTelemetryRumBuilder { loggerProviderCustomizers = new ArrayList<>(); private final List> instrumentationInstallers = new ArrayList<>(); + + private final Map, TextMapPropagator> propagators = + buildDefaultPropagators(); + private Resource resource; + private static Map, TextMapPropagator> + buildDefaultPropagators() { + Map, TextMapPropagator> result = new HashMap<>(); + putPropagator(result, W3CTraceContextPropagator.getInstance()); + putPropagator(result, W3CBaggagePropagator.getInstance()); + return result; + } + + private static void putPropagator( + Map, TextMapPropagator> propagators, + TextMapPropagator propagator) { + propagators.put(propagator.getClass(), propagator); + } + OpenTelemetryRumBuilder(Application application) { this.application = application; SessionIdTimeoutHandler timeoutHandler = new SessionIdTimeoutHandler(); @@ -142,6 +166,33 @@ public OpenTelemetryRumBuilder addInstrumentation( return this; } + /** + * Adds a new propagator to be used by the OpenTelemetry SDK. Calling this method will not + * remove any existing propagators, including the defaults: W3CTraceContextPropagator and + * W3CBaggagePropagator. For complete control over which propagators are used, call {@code + * setPropagator(TextMapPropagator propagator)}. + * + * @return {@code this} + */ + public OpenTelemetryRumBuilder addPropagator(TextMapPropagator propagator) { + putPropagator(propagators, propagator); + return this; + } + + /** + * This removes any existing propagators and configures a new one to by used by the + * OpenTelemetry SDK. If you need to configure more than one propagator, you should use {@code + * TextMapPropagator.composite()} and pass the composite propagator to this method. + * + * @param propagator The new TextMapPropagator to use when configuring the otel SDK. + * @return {@code this} + */ + public OpenTelemetryRumBuilder setPropagator(TextMapPropagator propagator) { + propagators.clear(); + putPropagator(propagators, propagator); + return this; + } + public SessionId getSessionId() { return sessionId; } @@ -161,6 +212,7 @@ public OpenTelemetryRum build() { .setTracerProvider(buildTracerProvider(sessionId, application)) .setMeterProvider(buildMeterProvider(application)) .setLoggerProvider(buildLoggerProvider(application)) + .setPropagators(buildFinalPropagators()) .build(); SdkPreconfiguredRumBuilder delegate = @@ -200,4 +252,8 @@ private SdkLoggerProvider buildLoggerProvider(Application application) { } return loggerProviderBuilder.build(); } + + private ContextPropagators buildFinalPropagators() { + return ContextPropagators.create(TextMapPropagator.composite(propagators.values())); + } } diff --git a/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java b/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java index 29f9550b1..9c9497d54 100644 --- a/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java +++ b/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java @@ -8,12 +8,18 @@ import static io.opentelemetry.android.RumConstants.SESSION_ID_KEY; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static java.util.Collections.singletonList; import static org.mockito.ArgumentMatchers.isA; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.Activity; import android.app.Application; import io.opentelemetry.android.instrumentation.ApplicationStateListener; +import io.opentelemetry.context.Context; +import io.opentelemetry.context.propagation.TextMapGetter; +import io.opentelemetry.context.propagation.TextMapPropagator; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.data.SpanData; @@ -92,4 +98,36 @@ void shouldInstallInstrumentation() { activityCallbacksCaptor.getValue().onActivityStopped(activity); verify(listener).onApplicationBackgrounded(); } + + @Test + void canAddPropagator() { + Context context = Context.root(); + Object carrier = new Object(); + + Context expected = mock(Context.class); + TextMapGetter getter = mock(TextMapGetter.class); + TextMapPropagator customPropagator = mock(TextMapPropagator.class); + + when(customPropagator.fields()).thenReturn(singletonList("beep")); + when(customPropagator.extract(context, carrier, getter)).thenReturn(expected); + + OpenTelemetryRum rum = + OpenTelemetryRum.builder(application).addPropagator(customPropagator).build(); + Context result = + rum.getOpenTelemetry() + .getPropagators() + .getTextMapPropagator() + .extract(context, carrier, getter); + assertThat(result).isSameAs(expected); + } + + @Test + void canSetPropagator() { + TextMapPropagator customPropagator = mock(TextMapPropagator.class); + + OpenTelemetryRum rum = + OpenTelemetryRum.builder(application).setPropagator(customPropagator).build(); + TextMapPropagator result = rum.getOpenTelemetry().getPropagators().getTextMapPropagator(); + assertThat(result).isSameAs(customPropagator); + } } From 3ab2b644495594aed40b43d87b908b0b5317f4dc Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Tue, 12 Sep 2023 11:48:23 -0700 Subject: [PATCH 2/4] standardize on addPropagatorCustomizer --- .../android/OpenTelemetryRumBuilder.java | 55 +++++++------------ 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java index 9d9c67b83..9b8e863ba 100644 --- a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java +++ b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.android; +import static java.util.Objects.requireNonNull; + import android.app.Application; import io.opentelemetry.android.instrumentation.InstrumentedApplication; import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; @@ -25,6 +27,7 @@ import java.util.Map; import java.util.function.BiFunction; import java.util.function.Consumer; +import java.util.function.Function; /** * A builder of {@link OpenTelemetryRum}. It enabled configuring the OpenTelemetry SDK and disabling @@ -46,23 +49,13 @@ public final class OpenTelemetryRumBuilder { private final List> instrumentationInstallers = new ArrayList<>(); - private final Map, TextMapPropagator> propagators = - buildDefaultPropagators(); + private Function propagatorCustomizer = (a) -> a; private Resource resource; - private static Map, TextMapPropagator> - buildDefaultPropagators() { + private static TextMapPropagator buildDefaultPropagator() { Map, TextMapPropagator> result = new HashMap<>(); - putPropagator(result, W3CTraceContextPropagator.getInstance()); - putPropagator(result, W3CBaggagePropagator.getInstance()); - return result; - } - - private static void putPropagator( - Map, TextMapPropagator> propagators, - TextMapPropagator propagator) { - propagators.put(propagator.getClass(), propagator); + return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()); } OpenTelemetryRumBuilder(Application application) { @@ -167,29 +160,20 @@ public OpenTelemetryRumBuilder addInstrumentation( } /** - * Adds a new propagator to be used by the OpenTelemetry SDK. Calling this method will not - * remove any existing propagators, including the defaults: W3CTraceContextPropagator and - * W3CBaggagePropagator. For complete control over which propagators are used, call {@code - * setPropagator(TextMapPropagator propagator)}. - * - * @return {@code this} - */ - public OpenTelemetryRumBuilder addPropagator(TextMapPropagator propagator) { - putPropagator(propagators, propagator); - return this; - } - - /** - * This removes any existing propagators and configures a new one to by used by the - * OpenTelemetry SDK. If you need to configure more than one propagator, you should use {@code - * TextMapPropagator.composite()} and pass the composite propagator to this method. + * Adds a {@link Function} to invoke with the default {@link TextMapPropagator} + * to allow customization. The return value of the {@link BiFunction} will replace + * the passed-in argument. To add new propagators, use {@code TextMapPropagator.composite()} + * with the existing propagator passed to your function. * - * @param propagator The new TextMapPropagator to use when configuring the otel SDK. - * @return {@code this} + *

Multiple calls will execute the customizers in order. */ - public OpenTelemetryRumBuilder setPropagator(TextMapPropagator propagator) { - propagators.clear(); - putPropagator(propagators, propagator); + public OpenTelemetryRumBuilder addPropagatorCustomizer( + Function propagatorCustomizer) { + requireNonNull(propagatorCustomizer, "propagatorCustomizer"); + this.propagatorCustomizer = propagator -> { + TextMapPropagator result = this.propagatorCustomizer.apply(propagator); + return propagatorCustomizer.apply(result); + }; return this; } @@ -254,6 +238,7 @@ private SdkLoggerProvider buildLoggerProvider(Application application) { } private ContextPropagators buildFinalPropagators() { - return ContextPropagators.create(TextMapPropagator.composite(propagators.values())); + TextMapPropagator defaultPropagator = buildDefaultPropagator(); + return ContextPropagators.create(propagatorCustomizer.apply(defaultPropagator)); } } From c55f852f5212461d2b0832bf9628e180fc18e8b1 Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Tue, 12 Sep 2023 11:56:46 -0700 Subject: [PATCH 3/4] spotless --- .../android/OpenTelemetryRumBuilder.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java index 9b8e863ba..4579da7ec 100644 --- a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java +++ b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java @@ -49,13 +49,15 @@ public final class OpenTelemetryRumBuilder { private final List> instrumentationInstallers = new ArrayList<>(); - private Function propagatorCustomizer = (a) -> a; + private Function propagatorCustomizer = + (a) -> a; private Resource resource; private static TextMapPropagator buildDefaultPropagator() { Map, TextMapPropagator> result = new HashMap<>(); - return TextMapPropagator.composite(W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()); + return TextMapPropagator.composite( + W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()); } OpenTelemetryRumBuilder(Application application) { @@ -160,20 +162,21 @@ public OpenTelemetryRumBuilder addInstrumentation( } /** - * Adds a {@link Function} to invoke with the default {@link TextMapPropagator} - * to allow customization. The return value of the {@link BiFunction} will replace - * the passed-in argument. To add new propagators, use {@code TextMapPropagator.composite()} - * with the existing propagator passed to your function. + * Adds a {@link Function} to invoke with the default {@link TextMapPropagator} to allow + * customization. The return value of the {@link BiFunction} will replace the passed-in + * argument. To add new propagators, use {@code TextMapPropagator.composite()} with the existing + * propagator passed to your function. * *

Multiple calls will execute the customizers in order. */ public OpenTelemetryRumBuilder addPropagatorCustomizer( Function propagatorCustomizer) { requireNonNull(propagatorCustomizer, "propagatorCustomizer"); - this.propagatorCustomizer = propagator -> { - TextMapPropagator result = this.propagatorCustomizer.apply(propagator); - return propagatorCustomizer.apply(result); - }; + this.propagatorCustomizer = + propagator -> { + TextMapPropagator result = this.propagatorCustomizer.apply(propagator); + return propagatorCustomizer.apply(result); + }; return this; } From e208d046383acfe97a6ceef2771b153efa190efc Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Tue, 12 Sep 2023 12:08:02 -0700 Subject: [PATCH 4/4] fix tests --- .../opentelemetry/android/OpenTelemetryRumBuilder.java | 4 +++- .../android/OpenTelemetryRumBuilderTest.java | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java index 4579da7ec..5fbfab191 100644 --- a/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java +++ b/instrumentation/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java @@ -172,9 +172,11 @@ public OpenTelemetryRumBuilder addInstrumentation( public OpenTelemetryRumBuilder addPropagatorCustomizer( Function propagatorCustomizer) { requireNonNull(propagatorCustomizer, "propagatorCustomizer"); + Function existing = + this.propagatorCustomizer; this.propagatorCustomizer = propagator -> { - TextMapPropagator result = this.propagatorCustomizer.apply(propagator); + TextMapPropagator result = existing.apply(propagator); return propagatorCustomizer.apply(result); }; return this; diff --git a/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java b/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java index 9c9497d54..50dcdbb96 100644 --- a/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java +++ b/instrumentation/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java @@ -8,7 +8,6 @@ import static io.opentelemetry.android.RumConstants.SESSION_ID_KEY; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; -import static java.util.Collections.singletonList; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -108,11 +107,12 @@ void canAddPropagator() { TextMapGetter getter = mock(TextMapGetter.class); TextMapPropagator customPropagator = mock(TextMapPropagator.class); - when(customPropagator.fields()).thenReturn(singletonList("beep")); when(customPropagator.extract(context, carrier, getter)).thenReturn(expected); OpenTelemetryRum rum = - OpenTelemetryRum.builder(application).addPropagator(customPropagator).build(); + OpenTelemetryRum.builder(application) + .addPropagatorCustomizer(x -> customPropagator) + .build(); Context result = rum.getOpenTelemetry() .getPropagators() @@ -126,7 +126,9 @@ void canSetPropagator() { TextMapPropagator customPropagator = mock(TextMapPropagator.class); OpenTelemetryRum rum = - OpenTelemetryRum.builder(application).setPropagator(customPropagator).build(); + OpenTelemetryRum.builder(application) + .addPropagatorCustomizer(x -> customPropagator) + .build(); TextMapPropagator result = rum.getOpenTelemetry().getPropagators().getTextMapPropagator(); assertThat(result).isSameAs(customPropagator); }