diff --git a/core/src/main/java/io/opentelemetry/android/OpenTelemetryRum.java b/core/src/main/java/io/opentelemetry/android/OpenTelemetryRum.java index 2810f8de..1d72b07e 100644 --- a/core/src/main/java/io/opentelemetry/android/OpenTelemetryRum.java +++ b/core/src/main/java/io/opentelemetry/android/OpenTelemetryRum.java @@ -61,14 +61,16 @@ static OpenTelemetryRumBuilder builder(Application application, OtelRumConfig co * @param openTelemetrySdk The {@link OpenTelemetrySdk} that the user has already created. * @param discoverInstrumentations TRUE to look for instrumentations in the classpath and * applying them automatically. + * @param serviceManager The ServiceManager instance */ static SdkPreconfiguredRumBuilder builder( Application application, OpenTelemetrySdk openTelemetrySdk, - boolean discoverInstrumentations) { - ServiceManager.initialize(application); + boolean discoverInstrumentations, + ServiceManager serviceManager) { + return new SdkPreconfiguredRumBuilder( - application, openTelemetrySdk, discoverInstrumentations, ServiceManager.get()); + application, openTelemetrySdk, discoverInstrumentations, serviceManager); } /** Returns a no-op implementation of {@link OpenTelemetryRum}. */ diff --git a/core/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java b/core/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java index 1b33bd02..ef686706 100644 --- a/core/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java +++ b/core/src/main/java/io/opentelemetry/android/OpenTelemetryRumBuilder.java @@ -9,10 +9,13 @@ import android.app.Application; import android.util.Log; +import androidx.annotation.NonNull; import io.opentelemetry.android.common.RumConstants; import io.opentelemetry.android.config.OtelRumConfig; import io.opentelemetry.android.features.diskbuffering.DiskBufferingConfiguration; import io.opentelemetry.android.features.diskbuffering.SignalFromDiskExporter; +import io.opentelemetry.android.features.diskbuffering.scheduler.DefaultExportScheduleHandler; +import io.opentelemetry.android.features.diskbuffering.scheduler.DefaultExportScheduler; import io.opentelemetry.android.features.diskbuffering.scheduler.ExportScheduleHandler; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; import io.opentelemetry.android.internal.features.networkattrs.NetworkAttributesSpanAppender; @@ -23,6 +26,8 @@ import io.opentelemetry.android.internal.services.CacheStorage; import io.opentelemetry.android.internal.services.Preferences; import io.opentelemetry.android.internal.services.ServiceManager; +import io.opentelemetry.android.internal.services.ServiceManagerImpl; +import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService; import io.opentelemetry.android.session.SessionManager; import io.opentelemetry.android.session.SessionProvider; import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; @@ -57,6 +62,7 @@ import java.util.function.Consumer; import java.util.function.Function; import javax.annotation.Nullable; +import kotlin.jvm.functions.Function0; /** * A builder of {@link OpenTelemetryRum}. It enabled configuring the OpenTelemetry SDK and disabling @@ -86,6 +92,9 @@ public final class OpenTelemetryRumBuilder { private Resource resource; + @Nullable private ServiceManager serviceManager; + @Nullable private ExportScheduleHandler exportScheduleHandler; + private static TextMapPropagator buildDefaultPropagator() { return TextMapPropagator.composite( W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance()); @@ -265,13 +274,8 @@ public OpenTelemetryRumBuilder addLogRecordExporterCustomizer( * @return A new {@link OpenTelemetryRum} instance. */ public OpenTelemetryRum build() { - ServiceManager.initialize(application); - return build(ServiceManager.get()); - } - - OpenTelemetryRum build(ServiceManager serviceManager) { InitializationEvents initializationEvents = InitializationEvents.get(); - applyConfiguration(serviceManager, initializationEvents); + applyConfiguration(initializationEvents); DiskBufferingConfiguration diskBufferingConfiguration = config.getDiskBufferingConfiguration(); @@ -280,8 +284,7 @@ OpenTelemetryRum build(ServiceManager serviceManager) { SignalFromDiskExporter signalFromDiskExporter = null; if (diskBufferingConfiguration.isEnabled()) { try { - StorageConfiguration storageConfiguration = - createStorageConfiguration(serviceManager); + StorageConfiguration storageConfiguration = createStorageConfiguration(); final SpanExporter originalSpanExporter = spanExporter; spanExporter = SpanToDiskExporter.create(originalSpanExporter, storageConfiguration); @@ -315,7 +318,7 @@ OpenTelemetryRum build(ServiceManager serviceManager) { otelSdkReadyListeners.forEach(listener -> listener.accept(sdk)); - scheduleDiskTelemetryReader(signalFromDiskExporter, diskBufferingConfiguration); + scheduleDiskTelemetryReader(signalFromDiskExporter); SdkPreconfiguredRumBuilder delegate = new SdkPreconfiguredRumBuilder( @@ -324,15 +327,37 @@ OpenTelemetryRum build(ServiceManager serviceManager) { timeoutHandler, sessionManager, config.shouldDiscoverInstrumentations(), - serviceManager); + getServiceManager()); instrumentations.forEach(delegate::addInstrumentation); return delegate.build(); } - private StorageConfiguration createStorageConfiguration(ServiceManager serviceManager) - throws IOException { - Preferences preferences = serviceManager.getPreferences(); - CacheStorage storage = serviceManager.getCacheStorage(); + @NonNull + private ServiceManager getServiceManager() { + if (serviceManager == null) { + serviceManager = ServiceManagerImpl.Companion.create(application); + } + return serviceManager; + } + + public OpenTelemetryRumBuilder setServiceManager(ServiceManager serviceManager) { + this.serviceManager = serviceManager; + return this; + } + + /** + * Sets a scheduler that will take care of periodically read data stored in disk and export it. + * If not specified, the default schedule exporter will be used. + */ + public OpenTelemetryRumBuilder setExportScheduleHandler( + ExportScheduleHandler exportScheduleHandler) { + this.exportScheduleHandler = exportScheduleHandler; + return this; + } + + private StorageConfiguration createStorageConfiguration() throws IOException { + Preferences preferences = getServiceManager().getPreferences(); + CacheStorage storage = getServiceManager().getCacheStorage(); DiskBufferingConfiguration config = this.config.getDiskBufferingConfiguration(); DiskManager diskManager = new DiskManager(storage, preferences, config); return StorageConfiguration.builder() @@ -347,11 +372,18 @@ private StorageConfiguration createStorageConfiguration(ServiceManager serviceMa .build(); } - private void scheduleDiskTelemetryReader( - @Nullable SignalFromDiskExporter signalExporter, - DiskBufferingConfiguration diskBufferingConfiguration) { - ExportScheduleHandler exportScheduleHandler = - diskBufferingConfiguration.getExportScheduleHandler(); + private void scheduleDiskTelemetryReader(@Nullable SignalFromDiskExporter signalExporter) { + + if (exportScheduleHandler == null) { + ServiceManager serviceManager = getServiceManager(); + // TODO: Is it safe to get the work service yet here? If so, we can + // avoid all this lazy supplier stuff.... + Function0 getWorkService = serviceManager::getPeriodicWorkService; + exportScheduleHandler = + new DefaultExportScheduleHandler( + new DefaultExportScheduler(getWorkService), getWorkService); + } + if (signalExporter == null) { // Disabling here allows to cancel previously scheduled exports using tools that // can run even after the app has been terminated (such as WorkManager). @@ -378,8 +410,7 @@ public OpenTelemetryRumBuilder addOtelSdkReadyListener(Consumer { SpanProcessor networkAttributesSpanAppender = NetworkAttributesSpanAppender.create( - serviceManager.getCurrentNetworkProvider()); + getServiceManager().getCurrentNetworkProvider()); return tracerProviderBuilder.addSpanProcessor( networkAttributesSpanAppender); }); @@ -415,7 +446,7 @@ private void applyConfiguration( (tracerProviderBuilder, app) -> { SpanProcessor screenAttributesAppender = new ScreenAttributesSpanProcessor( - serviceManager.getVisibleScreenService()); + getServiceManager().getVisibleScreenService()); return tracerProviderBuilder.addSpanProcessor(screenAttributesAppender); }); } diff --git a/core/src/main/java/io/opentelemetry/android/SdkPreconfiguredRumBuilder.kt b/core/src/main/java/io/opentelemetry/android/SdkPreconfiguredRumBuilder.kt index a6ae00ba..7bf92695 100644 --- a/core/src/main/java/io/opentelemetry/android/SdkPreconfiguredRumBuilder.kt +++ b/core/src/main/java/io/opentelemetry/android/SdkPreconfiguredRumBuilder.kt @@ -8,6 +8,7 @@ package io.opentelemetry.android import android.app.Application import io.opentelemetry.android.instrumentation.AndroidInstrumentation import io.opentelemetry.android.instrumentation.AndroidInstrumentationLoader +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.android.session.SessionManager import io.opentelemetry.sdk.OpenTelemetrySdk @@ -53,8 +54,9 @@ class SdkPreconfiguredRumBuilder val openTelemetryRum = OpenTelemetryRumImpl(sdk, sessionManager) // Install instrumentations + val ctx = InstallationContext(application, openTelemetryRum.openTelemetry, serviceManager) for (instrumentation in getInstrumentations()) { - instrumentation.install(application, openTelemetryRum.openTelemetry) + instrumentation.install(ctx) } return openTelemetryRum diff --git a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/DiskBufferingConfiguration.java b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/DiskBufferingConfiguration.java index ab4d5a66..258037b4 100644 --- a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/DiskBufferingConfiguration.java +++ b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/DiskBufferingConfiguration.java @@ -5,8 +5,6 @@ package io.opentelemetry.android.features.diskbuffering; -import io.opentelemetry.android.features.diskbuffering.scheduler.DefaultExportScheduleHandler; -import io.opentelemetry.android.features.diskbuffering.scheduler.ExportScheduleHandler; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -18,7 +16,6 @@ public final class DiskBufferingConfiguration { private final boolean enabled; private final int maxCacheSize; - private final ExportScheduleHandler exportScheduleHandler; private final long maxFileAgeForWriteMillis; private final long minFileAgeForReadMillis; private final long maxFileAgeForReadMillis; @@ -26,7 +23,6 @@ public final class DiskBufferingConfiguration { private DiskBufferingConfiguration(Builder builder) { enabled = builder.enabled; maxCacheSize = builder.maxCacheSize; - exportScheduleHandler = builder.exportScheduleHandler; maxFileAgeForWriteMillis = builder.maxFileAgeForWriteMillis; minFileAgeForReadMillis = builder.minFileAgeForReadMillis; maxFileAgeForReadMillis = builder.maxFileAgeForReadMillis; @@ -48,10 +44,6 @@ public int getMaxCacheFileSize() { return MAX_FILE_SIZE; } - public ExportScheduleHandler getExportScheduleHandler() { - return exportScheduleHandler; - } - public long getMaxFileAgeForWriteMillis() { return maxFileAgeForWriteMillis; } @@ -71,8 +63,6 @@ public static final class Builder { private long minFileAgeForReadMillis = TimeUnit.SECONDS.toMillis(33); private long maxFileAgeForReadMillis = TimeUnit.HOURS.toMillis(18); - private ExportScheduleHandler exportScheduleHandler = DefaultExportScheduleHandler.create(); - /** Enables or disables disk buffering. */ public Builder setEnabled(boolean enabled) { this.enabled = enabled; @@ -113,15 +103,6 @@ public Builder setMaxCacheSize(int maxCacheSize) { return this; } - /** - * Sets a scheduler that will take care of periodically read data stored in disk and export - * it. - */ - public Builder setExportScheduleHandler(ExportScheduleHandler exportScheduleHandler) { - this.exportScheduleHandler = exportScheduleHandler; - return this; - } - public DiskBufferingConfiguration build() { // See note in StorageConfiguration.getMinFileAgeForReadMillis() if (minFileAgeForReadMillis <= maxFileAgeForWriteMillis) { diff --git a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduleHandler.kt b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduleHandler.kt index 4f4b0bb4..e2527778 100644 --- a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduleHandler.kt +++ b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduleHandler.kt @@ -5,7 +5,6 @@ package io.opentelemetry.android.features.diskbuffering.scheduler -import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService import java.util.concurrent.atomic.AtomicBoolean @@ -22,15 +21,4 @@ class DefaultExportScheduleHandler( periodicWorkService.enqueue(exportScheduler) } } - - companion object { - @JvmStatic - fun create(): DefaultExportScheduleHandler { - return DefaultExportScheduleHandler( - DefaultExportScheduler.create(), - ) { - ServiceManager.get().getPeriodicWorkService() - } - } - } } diff --git a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduler.kt b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduler.kt index f4beb661..a508fdfe 100644 --- a/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduler.kt +++ b/core/src/main/java/io/opentelemetry/android/features/diskbuffering/scheduler/DefaultExportScheduler.kt @@ -8,7 +8,6 @@ package io.opentelemetry.android.features.diskbuffering.scheduler import android.util.Log import io.opentelemetry.android.common.RumConstants.OTEL_RUM_LOG_TAG import io.opentelemetry.android.features.diskbuffering.SignalFromDiskExporter -import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.android.internal.services.periodicwork.PeriodicRunnable import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService import java.io.IOException @@ -18,12 +17,6 @@ class DefaultExportScheduler(periodicWorkServiceProvider: () -> PeriodicWorkServ PeriodicRunnable(periodicWorkServiceProvider) { companion object { private val DELAY_BEFORE_NEXT_EXPORT_IN_MILLIS = TimeUnit.SECONDS.toMillis(10) - - fun create(): DefaultExportScheduler { - return DefaultExportScheduler { - ServiceManager.get().getPeriodicWorkService() - } - } } override fun onRun() { diff --git a/core/src/main/java/io/opentelemetry/android/instrumentation/AndroidInstrumentation.kt b/core/src/main/java/io/opentelemetry/android/instrumentation/AndroidInstrumentation.kt index a6b01806..c3934bfe 100644 --- a/core/src/main/java/io/opentelemetry/android/instrumentation/AndroidInstrumentation.kt +++ b/core/src/main/java/io/opentelemetry/android/instrumentation/AndroidInstrumentation.kt @@ -5,9 +5,7 @@ package io.opentelemetry.android.instrumentation -import android.app.Application import io.opentelemetry.android.OpenTelemetryRum -import io.opentelemetry.api.OpenTelemetry /** * This interface defines a tool that automatically generates telemetry for a specific use-case, @@ -30,11 +28,7 @@ interface AndroidInstrumentation { * only be called from [OpenTelemetryRum]'s builder once the [OpenTelemetryRum] instance is initialized and ready * to use for generating telemetry. * - * @param application The Android application being instrumented. - * @param openTelemetry The [OpenTelemetry] instance to use for creating signals. + * @param ctx The InstallationContext under which the instrumentation is being installed. */ - fun install( - application: Application, - openTelemetry: OpenTelemetry, - ) + fun install(ctx: InstallationContext) } diff --git a/core/src/main/java/io/opentelemetry/android/instrumentation/InstallationContext.kt b/core/src/main/java/io/opentelemetry/android/instrumentation/InstallationContext.kt new file mode 100644 index 00000000..826a24a4 --- /dev/null +++ b/core/src/main/java/io/opentelemetry/android/instrumentation/InstallationContext.kt @@ -0,0 +1,16 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.android.instrumentation + +import android.app.Application +import io.opentelemetry.android.internal.services.ServiceManager +import io.opentelemetry.api.OpenTelemetry + +data class InstallationContext( + val application: Application, + val openTelemetry: OpenTelemetry, + val serviceManager: ServiceManager, +) diff --git a/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManager.kt b/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManager.kt index 647cd450..96034be7 100644 --- a/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManager.kt +++ b/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManager.kt @@ -5,7 +5,6 @@ package io.opentelemetry.android.internal.services -import android.app.Application import io.opentelemetry.android.internal.services.applifecycle.AppLifecycleService import io.opentelemetry.android.internal.services.network.CurrentNetworkProvider import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService @@ -26,39 +25,4 @@ interface ServiceManager : Startable { fun getAppLifecycleService(): AppLifecycleService fun getVisibleScreenService(): VisibleScreenService - - companion object { - private var instance: ServiceManager? = null - - @JvmStatic - fun initialize(application: Application) { - if (instance != null) { - return - } - instance = - ServiceManagerImpl( - listOf( - Preferences.create(application), - CacheStorage( - application, - ), - PeriodicWorkService(), - CurrentNetworkProvider.create(application), - AppLifecycleService.create(), - VisibleScreenService.create(application), - ), - ) - } - - @JvmStatic - fun get(): ServiceManager { - checkNotNull(instance) { "Services haven't been initialized" } - return instance!! - } - - @JvmStatic - fun resetForTest() { - instance = null - } - } } diff --git a/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManagerImpl.kt b/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManagerImpl.kt index c6ffeaf3..9b63727e 100644 --- a/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManagerImpl.kt +++ b/core/src/main/java/io/opentelemetry/android/internal/services/ServiceManagerImpl.kt @@ -5,6 +5,7 @@ package io.opentelemetry.android.internal.services +import android.app.Application import io.opentelemetry.android.internal.services.applifecycle.AppLifecycleService import io.opentelemetry.android.internal.services.network.CurrentNetworkProvider import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService @@ -22,6 +23,22 @@ internal class ServiceManagerImpl(services: List) : ServiceManager { this.services = Collections.unmodifiableMap(map) } + companion object { + @JvmStatic + fun create(application: Application): ServiceManager { + return ServiceManagerImpl( + listOf( + Preferences.create(application), + CacheStorage(application), + PeriodicWorkService(), + CurrentNetworkProvider.create(application), + AppLifecycleService.create(), + VisibleScreenService.create(application), + ), + ) + } + } + override fun getPreferences(): Preferences { return getService(Preferences::class.java) } diff --git a/core/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java b/core/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java index 6ada4aba..7d2e066c 100644 --- a/core/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java +++ b/core/src/test/java/io/opentelemetry/android/OpenTelemetryRumBuilderTest.java @@ -10,12 +10,10 @@ import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static org.awaitility.Awaitility.await; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyCollection; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isA; -import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -34,22 +32,19 @@ import io.opentelemetry.android.features.diskbuffering.scheduler.ExportScheduleHandler; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; import io.opentelemetry.android.instrumentation.AndroidInstrumentationLoader; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.android.internal.initialization.InitializationEvents; import io.opentelemetry.android.internal.instrumentation.AndroidInstrumentationLoaderImpl; import io.opentelemetry.android.internal.services.CacheStorage; import io.opentelemetry.android.internal.services.Preferences; import io.opentelemetry.android.internal.services.ServiceManager; -import io.opentelemetry.android.internal.services.ServiceManagerImpl; import io.opentelemetry.android.internal.services.applifecycle.AppLifecycleService; import io.opentelemetry.android.internal.services.applifecycle.ApplicationStateListener; -import io.opentelemetry.android.internal.services.visiblescreen.VisibleScreenService; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.common.KeyValue; import io.opentelemetry.api.common.Value; import io.opentelemetry.api.incubator.events.EventLogger; import io.opentelemetry.api.logs.Logger; -import io.opentelemetry.api.logs.LoggerBuilder; -import io.opentelemetry.api.logs.LoggerProvider; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.Span; import io.opentelemetry.context.Context; @@ -72,7 +67,6 @@ import io.opentelemetry.semconv.incubating.SessionIncubatingAttributes; import java.io.IOException; import java.time.Duration; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -115,7 +109,6 @@ public void tearDown() throws Exception { SignalFromDiskExporter.resetForTesting(); InitializationEvents.resetForTest(); AndroidInstrumentationLoader.resetForTest(); - ServiceManager.resetForTest(); mocks.close(); } @@ -124,7 +117,7 @@ public void shouldRegisterApplicationStateWatcher() { ServiceManager serviceManager = createServiceManager(); AppLifecycleService appLifecycleService = serviceManager.getAppLifecycleService(); - makeBuilder().build(serviceManager); + makeBuilder().setServiceManager(serviceManager).build(); verify(appLifecycleService).registerListener(isA(ApplicationStateListener.class)); } @@ -201,14 +194,18 @@ public void shouldInstallInstrumentation() { (AndroidInstrumentationLoaderImpl) AndroidInstrumentationLoader.get(); androidInstrumentationServices.registerForTest(classpathInstrumentation); - new OpenTelemetryRumBuilder(application, buildConfig(), timeoutHandler) - .addInstrumentation(localInstrumentation) - .build(serviceManager); + OpenTelemetryRum rum = + new OpenTelemetryRumBuilder(application, buildConfig(), timeoutHandler) + .addInstrumentation(localInstrumentation) + .setServiceManager(serviceManager) + .build(); verify(serviceManager.getAppLifecycleService()).registerListener(timeoutHandler); - verify(localInstrumentation).install(eq(application), notNull()); - verify(classpathInstrumentation).install(eq(application), notNull()); + InstallationContext expectedCtx = + new InstallationContext(application, rum.getOpenTelemetry(), serviceManager); + verify(localInstrumentation).install(eq(expectedCtx)); + verify(classpathInstrumentation).install(eq(expectedCtx)); } @Test @@ -221,16 +218,20 @@ public void shouldInstallInstrumentation_excludingClasspathImplsWhenRequestedInC (AndroidInstrumentationLoaderImpl) AndroidInstrumentationLoader.get(); androidInstrumentationServices.registerForTest(classpathInstrumentation); - new OpenTelemetryRumBuilder( - application, - buildConfig().disableInstrumentationDiscovery(), - timeoutHandler) - .addInstrumentation(localInstrumentation) - .build(serviceManager); + OpenTelemetryRum rum = + new OpenTelemetryRumBuilder( + application, + buildConfig().disableInstrumentationDiscovery(), + timeoutHandler) + .addInstrumentation(localInstrumentation) + .setServiceManager(serviceManager) + .build(); verify(serviceManager.getAppLifecycleService()).registerListener(timeoutHandler); - verify(localInstrumentation).install(eq(application), notNull()); + InstallationContext expectedCtx = + new InstallationContext(application, rum.getOpenTelemetry(), serviceManager); + verify(localInstrumentation).install(eq(expectedCtx)); verifyNoInteractions(classpathInstrumentation); } @@ -322,13 +323,13 @@ public void diskBufferingEnabled() { OtelRumConfig config = buildConfig(); ExportScheduleHandler scheduleHandler = mock(); config.setDiskBufferingConfiguration( - DiskBufferingConfiguration.builder() - .setEnabled(true) - .setExportScheduleHandler(scheduleHandler) - .build()); + DiskBufferingConfiguration.builder().setEnabled(true).build()); ArgumentCaptor exporterCaptor = ArgumentCaptor.forClass(SpanExporter.class); - OpenTelemetryRum.builder(application, config).build(serviceManager); + OpenTelemetryRum.builder(application, config) + .setExportScheduleHandler(scheduleHandler) + .setServiceManager(serviceManager) + .build(); assertThat(SignalFromDiskExporter.get()).isNotNull(); verify(scheduleHandler).enable(); @@ -352,12 +353,12 @@ public void diskBufferingEnabled_when_exception_thrown() { ArgumentCaptor exporterCaptor = ArgumentCaptor.forClass(SpanExporter.class); OtelRumConfig config = buildConfig(); config.setDiskBufferingConfiguration( - DiskBufferingConfiguration.builder() - .setEnabled(true) - .setExportScheduleHandler(scheduleHandler) - .build()); + DiskBufferingConfiguration.builder().setEnabled(true).build()); - OpenTelemetryRum.builder(application, config).build(serviceManager); + OpenTelemetryRum.builder(application, config) + .setServiceManager(serviceManager) + .setExportScheduleHandler(scheduleHandler) + .build(); verify(initializationEvents).spanExporterInitialized(exporterCaptor.capture()); verify(scheduleHandler, never()).enable(); @@ -372,7 +373,8 @@ public void sdkReadyListeners() { AtomicReference seen = new AtomicReference<>(); OpenTelemetryRum.builder(application, config) .addOtelSdkReadyListener(seen::set) - .build(createServiceManager()); + .setServiceManager(createServiceManager()) + .build(); assertThat(seen.get()).isNotNull(); } @@ -383,12 +385,11 @@ public void diskBufferingDisabled() { OtelRumConfig config = buildConfig(); config.setDiskBufferingConfiguration( - DiskBufferingConfiguration.builder() - .setEnabled(false) - .setExportScheduleHandler(scheduleHandler) - .build()); + DiskBufferingConfiguration.builder().setEnabled(false).build()); - OpenTelemetryRum.builder(application, config).build(); + OpenTelemetryRum.builder(application, config) + .setExportScheduleHandler(scheduleHandler) + .build(); verify(initializationEvents).spanExporterInitialized(exporterCaptor.capture()); verify(scheduleHandler, never()).enable(); @@ -426,46 +427,36 @@ public void verifyGlobalAttrsForLogs() { } @Test - public void verifyServicesAreInitialized() { - makeBuilder().build(); - - assertThat(ServiceManager.get()).isNotNull(); + public void verifyDefaultServicesAreCreated() { + AtomicReference serviceManagerHolder = new AtomicReference<>(); + AndroidInstrumentation instrumentationTrap = + ctx -> serviceManagerHolder.set(ctx.getServiceManager()); + makeBuilder().addInstrumentation(instrumentationTrap).build(); + assertThat(serviceManagerHolder.get()).isNotNull(); + assertThat(serviceManagerHolder.get().getAppLifecycleService()).isNotNull(); + assertThat(serviceManagerHolder.get().getCacheStorage()).isNotNull(); + assertThat(serviceManagerHolder.get().getCurrentNetworkProvider()).isNotNull(); + assertThat(serviceManagerHolder.get().getPeriodicWorkService()).isNotNull(); + assertThat(serviceManagerHolder.get().getPreferences()).isNotNull(); + assertThat(serviceManagerHolder.get().getVisibleScreenService()).isNotNull(); } @Test - public void verifyServicesAreStarted() { - ServiceManager serviceManager = mock(); - doReturn(mock(AppLifecycleService.class)).when(serviceManager).getAppLifecycleService(); - - makeBuilder().build(serviceManager); - + public void verifyServiceManagerIsStarted() { + ServiceManager serviceManager = createServiceManager(); + makeBuilder().setServiceManager(serviceManager).build(); verify(serviceManager).start(); } - @Test - public void verifyPreconfiguredServicesInitialization() { - OpenTelemetrySdk openTelemetrySdk = mock(); - // Work around sdk EventLogger api limitations - LoggerProvider logsBridge = mock(LoggerProvider.class); - LoggerBuilder loggerBuilder = mock(); - when(openTelemetrySdk.getLogsBridge()).thenReturn(logsBridge); - when(logsBridge.loggerBuilder(any())).thenReturn(loggerBuilder); - - OpenTelemetryRum.builder(application, openTelemetrySdk, true).build(); - - assertThat(ServiceManager.get()).isNotNull(); - } - /** * @noinspection KotlinInternalInJava */ private static ServiceManager createServiceManager() { - return new ServiceManagerImpl( - Arrays.asList( - mock(Preferences.class), - mock(CacheStorage.class), - mock(AppLifecycleService.class), - mock(VisibleScreenService.class))); + ServiceManager serviceManager = mock(ServiceManager.class); + when(serviceManager.getAppLifecycleService()).thenReturn(mock(AppLifecycleService.class)); + when(serviceManager.getCacheStorage()).thenReturn(mock(CacheStorage.class)); + when(serviceManager.getPreferences()).thenReturn(mock(Preferences.class)); + return serviceManager; } @NonNull diff --git a/core/src/test/java/io/opentelemetry/android/instrumentation/TestAndroidInstrumentation.kt b/core/src/test/java/io/opentelemetry/android/instrumentation/TestAndroidInstrumentation.kt index 60a11ff6..deec8cab 100644 --- a/core/src/test/java/io/opentelemetry/android/instrumentation/TestAndroidInstrumentation.kt +++ b/core/src/test/java/io/opentelemetry/android/instrumentation/TestAndroidInstrumentation.kt @@ -5,17 +5,11 @@ package io.opentelemetry.android.instrumentation -import android.app.Application -import io.opentelemetry.api.OpenTelemetry - class TestAndroidInstrumentation : AndroidInstrumentation { var installed = false private set - override fun install( - application: Application, - openTelemetry: OpenTelemetry, - ) { + override fun install(ctx: InstallationContext) { installed = true } } diff --git a/core/src/test/java/io/opentelemetry/android/internal/instrumentation/AndroidInstrumentationLoaderImplTest.kt b/core/src/test/java/io/opentelemetry/android/internal/instrumentation/AndroidInstrumentationLoaderImplTest.kt index a8e1a1b6..a4374859 100644 --- a/core/src/test/java/io/opentelemetry/android/internal/instrumentation/AndroidInstrumentationLoaderImplTest.kt +++ b/core/src/test/java/io/opentelemetry/android/internal/instrumentation/AndroidInstrumentationLoaderImplTest.kt @@ -25,7 +25,7 @@ class AndroidInstrumentationLoaderImplTest { assertThat(instrumentation.installed).isFalse() - instrumentation.install(mockk(), mockk()) + instrumentation.install(mockk()) assertThat(loader.getByType(TestAndroidInstrumentation::class.java)!!.installed).isTrue() } diff --git a/core/src/test/java/io/opentelemetry/android/internal/services/ServiceManagerImplTest.kt b/core/src/test/java/io/opentelemetry/android/internal/services/ServiceManagerImplTest.kt index e76a7dcc..79c61347 100644 --- a/core/src/test/java/io/opentelemetry/android/internal/services/ServiceManagerImplTest.kt +++ b/core/src/test/java/io/opentelemetry/android/internal/services/ServiceManagerImplTest.kt @@ -5,7 +5,6 @@ package io.opentelemetry.android.internal.services -import io.opentelemetry.android.internal.services.ServiceManager.Companion.initialize import io.opentelemetry.android.internal.services.network.CurrentNetworkProvider import io.opentelemetry.android.internal.services.periodicwork.PeriodicWorkService import org.assertj.core.api.Assertions.assertThat @@ -21,10 +20,10 @@ import org.robolectric.RuntimeEnvironment @RunWith(RobolectricTestRunner::class) class ServiceManagerImplTest { @Test - fun verifyAvailableServices() { - initialize(RuntimeEnvironment.getApplication()) + fun verifyAvailableDefaultServices() { + val app = RuntimeEnvironment.getApplication() - val serviceManager = ServiceManager.get() + val serviceManager = ServiceManagerImpl.create(app) assertThat(serviceManager.getPeriodicWorkService()).isInstanceOf(PeriodicWorkService::class.java) assertThat(serviceManager.getCacheStorage()).isInstanceOf(CacheStorage::class.java) diff --git a/instrumentation/activity/src/main/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentation.kt b/instrumentation/activity/src/main/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentation.kt index b7d3e334..3b506116 100644 --- a/instrumentation/activity/src/main/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentation.kt +++ b/instrumentation/activity/src/main/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentation.kt @@ -5,16 +5,14 @@ package io.opentelemetry.android.instrumentation.activity -import android.app.Application import android.os.Build import com.google.auto.service.AutoService import io.opentelemetry.android.instrumentation.AndroidInstrumentation +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.android.instrumentation.activity.startup.AppStartupTimer import io.opentelemetry.android.instrumentation.common.Constants.INSTRUMENTATION_SCOPE import io.opentelemetry.android.instrumentation.common.ScreenNameExtractor -import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.android.internal.services.visiblescreen.activities.DefaultingActivityLifecycleCallbacks -import io.opentelemetry.api.OpenTelemetry import io.opentelemetry.api.trace.Tracer @AutoService(AndroidInstrumentation::class) @@ -31,18 +29,15 @@ class ActivityLifecycleInstrumentation : AndroidInstrumentation { this.screenNameExtractor = screenNameExtractor } - override fun install( - application: Application, - openTelemetry: OpenTelemetry, - ) { - startupTimer.start(openTelemetry.getTracer(INSTRUMENTATION_SCOPE)) - application.registerActivityLifecycleCallbacks(startupTimer.createLifecycleCallback()) - application.registerActivityLifecycleCallbacks(buildActivityLifecycleTracer(openTelemetry)) + override fun install(ctx: InstallationContext) { + startupTimer.start(ctx.openTelemetry.getTracer(INSTRUMENTATION_SCOPE)) + ctx.application.registerActivityLifecycleCallbacks(startupTimer.createLifecycleCallback()) + ctx.application.registerActivityLifecycleCallbacks(buildActivityLifecycleTracer(ctx)) } - private fun buildActivityLifecycleTracer(openTelemetry: OpenTelemetry): DefaultingActivityLifecycleCallbacks { - val visibleScreenService = ServiceManager.get().getVisibleScreenService() - val delegateTracer: Tracer = openTelemetry.getTracer(INSTRUMENTATION_SCOPE) + private fun buildActivityLifecycleTracer(ctx: InstallationContext): DefaultingActivityLifecycleCallbacks { + val visibleScreenService = ctx.serviceManager.getVisibleScreenService() + val delegateTracer: Tracer = ctx.openTelemetry.getTracer(INSTRUMENTATION_SCOPE) val tracers = ActivityTracerCache( tracerCustomizer.invoke(delegateTracer), diff --git a/instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityInstrumentationTest.kt b/instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentationTest.kt similarity index 79% rename from instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityInstrumentationTest.kt rename to instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentationTest.kt index af5581e3..20e7c195 100644 --- a/instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityInstrumentationTest.kt +++ b/instrumentation/activity/src/test/java/io/opentelemetry/android/instrumentation/activity/ActivityLifecycleInstrumentationTest.kt @@ -10,9 +10,10 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.mockk.every import io.mockk.mockk import io.mockk.verify -import io.opentelemetry.android.OpenTelemetryRum import io.opentelemetry.android.common.RumConstants -import io.opentelemetry.android.internal.services.ServiceManager.Companion +import io.opentelemetry.android.instrumentation.InstallationContext +import io.opentelemetry.android.internal.services.ServiceManager +import io.opentelemetry.android.internal.services.visiblescreen.VisibleScreenService import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.SpanBuilder import io.opentelemetry.api.trace.Tracer @@ -23,19 +24,19 @@ import org.junit.runner.RunWith import org.robolectric.RuntimeEnvironment @RunWith(AndroidJUnit4::class) -class ActivityInstrumentationTest { +class ActivityLifecycleInstrumentationTest { private lateinit var activityLifecycleInstrumentation: ActivityLifecycleInstrumentation private lateinit var application: Application - private lateinit var openTelemetryRum: OpenTelemetryRum private lateinit var openTelemetry: OpenTelemetrySdk + private lateinit var serviceManager: ServiceManager @Before fun setUp() { application = RuntimeEnvironment.getApplication() openTelemetry = mockk() activityLifecycleInstrumentation = ActivityLifecycleInstrumentation() - - Companion.initialize(application) + serviceManager = mockk() + every { serviceManager.getVisibleScreenService() }.returns(mockk()) } @Test @@ -52,7 +53,8 @@ class ActivityInstrumentationTest { ) every { startupSpanBuilder.startSpan() }.returns(startupSpan) - activityLifecycleInstrumentation.install(application, openTelemetry) + val ctx = InstallationContext(application, openTelemetry, serviceManager) + activityLifecycleInstrumentation.install(ctx) verify { tracer.spanBuilder("AppStart") diff --git a/instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrInstrumentation.java b/instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrInstrumentation.java index 81140be9..303df35d 100644 --- a/instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrInstrumentation.java +++ b/instrumentation/anr/src/main/java/io/opentelemetry/android/instrumentation/anr/AnrInstrumentation.java @@ -5,13 +5,11 @@ package io.opentelemetry.android.instrumentation.anr; -import android.app.Application; import android.os.Looper; import androidx.annotation.NonNull; import com.google.auto.service.AutoService; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.android.internal.services.ServiceManager; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import java.util.ArrayList; import java.util.List; @@ -47,14 +45,14 @@ AnrInstrumentation setScheduler(ScheduledExecutorService scheduler) { } @Override - public void install(@NonNull Application application, @NonNull OpenTelemetry openTelemetry) { + public void install(@NonNull InstallationContext ctx) { AnrDetector anrDetector = new AnrDetector( additionalExtractors, mainLooper, scheduler, - ServiceManager.get().getAppLifecycleService(), - openTelemetry); + ctx.getServiceManager().getAppLifecycleService(), + ctx.getOpenTelemetry()); anrDetector.start(); } } diff --git a/instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporterInstrumentation.java b/instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporterInstrumentation.java index 880de041..13dd2fe9 100644 --- a/instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporterInstrumentation.java +++ b/instrumentation/crash/src/main/java/io/opentelemetry/android/instrumentation/crash/CrashReporterInstrumentation.java @@ -5,12 +5,11 @@ package io.opentelemetry.android.instrumentation.crash; -import android.app.Application; import androidx.annotation.NonNull; import com.google.auto.service.AutoService; import io.opentelemetry.android.RuntimeDetailsExtractor; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.sdk.OpenTelemetrySdk; import java.util.ArrayList; @@ -28,9 +27,9 @@ public void addAttributesExtractor(AttributesExtractor extra } @Override - public void install(@NonNull Application application, @NonNull OpenTelemetry openTelemetry) { - addAttributesExtractor(RuntimeDetailsExtractor.create(application)); + public void install(@NonNull InstallationContext ctx) { + addAttributesExtractor(RuntimeDetailsExtractor.create(ctx.getApplication())); CrashReporter crashReporter = new CrashReporter(additionalExtractors); - crashReporter.install((OpenTelemetrySdk) openTelemetry); + crashReporter.install((OpenTelemetrySdk) ctx.getOpenTelemetry()); } } diff --git a/instrumentation/crash/src/test/java/io/opentelemetry/android/instrumentation/crash/CrashReporterTest.java b/instrumentation/crash/src/test/java/io/opentelemetry/android/instrumentation/crash/CrashReporterTest.java index fc20cde2..da6de01d 100644 --- a/instrumentation/crash/src/test/java/io/opentelemetry/android/instrumentation/crash/CrashReporterTest.java +++ b/instrumentation/crash/src/test/java/io/opentelemetry/android/instrumentation/crash/CrashReporterTest.java @@ -8,8 +8,11 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor.constant; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; import androidx.test.ext.junit.runners.AndroidJUnit4; +import io.opentelemetry.android.instrumentation.InstallationContext; +import io.opentelemetry.android.internal.services.ServiceManager; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.logs.SdkLoggerProvider; @@ -57,7 +60,12 @@ public void tearDown() { public void integrationTest() throws InterruptedException { CrashReporterInstrumentation instrumentation = new CrashReporterInstrumentation(); instrumentation.addAttributesExtractor(constant(stringKey("test.key"), "abc")); - instrumentation.install(RuntimeEnvironment.getApplication(), openTelemetrySdk); + InstallationContext ctx = + new InstallationContext( + RuntimeEnvironment.getApplication(), + openTelemetrySdk, + mock(ServiceManager.class)); + instrumentation.install(ctx); String exceptionMessage = "boooom!"; RuntimeException crash = new RuntimeException(exceptionMessage); diff --git a/instrumentation/fragment/src/main/java/io/opentelemetry/android/instrumentation/fragment/FragmentLifecycleInstrumentation.kt b/instrumentation/fragment/src/main/java/io/opentelemetry/android/instrumentation/fragment/FragmentLifecycleInstrumentation.kt index 22a74c54..cf4a618f 100644 --- a/instrumentation/fragment/src/main/java/io/opentelemetry/android/instrumentation/fragment/FragmentLifecycleInstrumentation.kt +++ b/instrumentation/fragment/src/main/java/io/opentelemetry/android/instrumentation/fragment/FragmentLifecycleInstrumentation.kt @@ -5,16 +5,14 @@ package io.opentelemetry.android.instrumentation.fragment -import android.app.Application import android.app.Application.ActivityLifecycleCallbacks import android.os.Build import com.google.auto.service.AutoService import io.opentelemetry.android.instrumentation.AndroidInstrumentation +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.android.instrumentation.common.Constants.INSTRUMENTATION_SCOPE import io.opentelemetry.android.instrumentation.common.ScreenNameExtractor -import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.android.internal.services.visiblescreen.fragments.RumFragmentActivityRegisterer -import io.opentelemetry.api.OpenTelemetry import io.opentelemetry.api.trace.Tracer @AutoService(AndroidInstrumentation::class) @@ -30,16 +28,13 @@ class FragmentLifecycleInstrumentation : AndroidInstrumentation { this.screenNameExtractor = screenNameExtractor } - override fun install( - application: Application, - openTelemetry: OpenTelemetry, - ) { - application.registerActivityLifecycleCallbacks(buildFragmentRegisterer(openTelemetry)) + override fun install(ctx: InstallationContext) { + ctx.application.registerActivityLifecycleCallbacks(buildFragmentRegisterer(ctx)) } - private fun buildFragmentRegisterer(openTelemetry: OpenTelemetry): ActivityLifecycleCallbacks { - val visibleScreenService = ServiceManager.get().getVisibleScreenService() - val delegateTracer: Tracer = openTelemetry.getTracer(INSTRUMENTATION_SCOPE) + private fun buildFragmentRegisterer(ctx: InstallationContext): ActivityLifecycleCallbacks { + val visibleScreenService = ctx.serviceManager.getVisibleScreenService() + val delegateTracer: Tracer = ctx.openTelemetry.getTracer(INSTRUMENTATION_SCOPE) val fragmentLifecycle = RumFragmentLifecycleCallbacks( tracerCustomizer.invoke(delegateTracer), diff --git a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java index aebd2d0c..3a0e109c 100644 --- a/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java +++ b/instrumentation/httpurlconnection/library/src/main/java/io/opentelemetry/instrumentation/library/httpurlconnection/HttpUrlInstrumentation.java @@ -5,10 +5,9 @@ package io.opentelemetry.instrumentation.library.httpurlconnection; -import android.app.Application; import com.google.auto.service.AutoService; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; import io.opentelemetry.instrumentation.api.internal.HttpConstants; import io.opentelemetry.instrumentation.library.httpurlconnection.internal.HttpUrlConnectionSingletons; @@ -123,8 +122,8 @@ public boolean emitExperimentalHttpClientMetrics() { } @Override - public void install(@NotNull Application application, @NotNull OpenTelemetry openTelemetry) { - HttpUrlConnectionSingletons.configure(this, openTelemetry); + public void install(@NotNull InstallationContext ctx) { + HttpUrlConnectionSingletons.configure(this, ctx.getOpenTelemetry()); } /** diff --git a/instrumentation/network/src/main/java/io/opentelemetry/android/instrumentation/network/NetworkChangeInstrumentation.java b/instrumentation/network/src/main/java/io/opentelemetry/android/instrumentation/network/NetworkChangeInstrumentation.java index 88fe82b6..d0245db1 100644 --- a/instrumentation/network/src/main/java/io/opentelemetry/android/instrumentation/network/NetworkChangeInstrumentation.java +++ b/instrumentation/network/src/main/java/io/opentelemetry/android/instrumentation/network/NetworkChangeInstrumentation.java @@ -5,13 +5,11 @@ package io.opentelemetry.android.instrumentation.network; -import android.app.Application; import androidx.annotation.NonNull; import com.google.auto.service.AutoService; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.android.internal.services.ServiceManager; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.android.internal.services.network.data.CurrentNetwork; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import java.util.ArrayList; import java.util.Collections; @@ -31,12 +29,12 @@ public NetworkChangeInstrumentation addAttributesExtractor( } @Override - public void install(@NonNull Application application, @NonNull OpenTelemetry openTelemetry) { + public void install(@NonNull InstallationContext ctx) { NetworkChangeMonitor networkChangeMonitor = new NetworkChangeMonitor( - openTelemetry, - ServiceManager.get().getAppLifecycleService(), - ServiceManager.get().getCurrentNetworkProvider(), + ctx.getOpenTelemetry(), + ctx.getServiceManager().getAppLifecycleService(), + ctx.getServiceManager().getCurrentNetworkProvider(), Collections.unmodifiableList(additionalExtractors)); networkChangeMonitor.start(); } diff --git a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/library/okhttp/v3_0/OkHttpInstrumentation.java b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/library/okhttp/v3_0/OkHttpInstrumentation.java index b2983aeb..2fa23923 100644 --- a/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/library/okhttp/v3_0/OkHttpInstrumentation.java +++ b/instrumentation/okhttp/okhttp-3.0/library/src/main/java/io/opentelemetry/instrumentation/library/okhttp/v3_0/OkHttpInstrumentation.java @@ -5,10 +5,9 @@ package io.opentelemetry.instrumentation.library.okhttp.v3_0; -import android.app.Application; import com.google.auto.service.AutoService; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.android.instrumentation.InstallationContext; import io.opentelemetry.instrumentation.api.incubator.semconv.net.PeerServiceResolver; import io.opentelemetry.instrumentation.api.internal.HttpConstants; import io.opentelemetry.instrumentation.library.okhttp.v3_0.internal.OkHttp3Singletons; @@ -123,7 +122,7 @@ public boolean emitExperimentalHttpClientMetrics() { } @Override - public void install(@NotNull Application application, @NotNull OpenTelemetry openTelemetry) { - OkHttp3Singletons.configure(this, openTelemetry); + public void install(@NotNull InstallationContext ctx) { + OkHttp3Singletons.configure(this, ctx.getOpenTelemetry()); } } diff --git a/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentation.java b/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentation.java index d140d773..aae35853 100644 --- a/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentation.java +++ b/instrumentation/slowrendering/src/main/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentation.java @@ -5,7 +5,6 @@ package io.opentelemetry.android.instrumentation.slowrendering; -import android.app.Application; import android.os.Build; import android.util.Log; import androidx.annotation.NonNull; @@ -13,7 +12,7 @@ import com.google.auto.service.AutoService; import io.opentelemetry.android.common.RumConstants; import io.opentelemetry.android.instrumentation.AndroidInstrumentation; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.android.instrumentation.InstallationContext; import java.time.Duration; /** Entrypoint for installing the slow rendering detection instrumentation. */ @@ -43,7 +42,7 @@ public SlowRenderingInstrumentation setSlowRenderingDetectionPollInterval(Durati @RequiresApi(Build.VERSION_CODES.N) @Override - public void install(@NonNull Application application, @NonNull OpenTelemetry openTelemetry) { + public void install(@NonNull InstallationContext ctx) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.w( RumConstants.OTEL_RUM_LOG_TAG, @@ -53,10 +52,10 @@ public void install(@NonNull Application application, @NonNull OpenTelemetry ope SlowRenderListener detector = new SlowRenderListener( - openTelemetry.getTracer("io.opentelemetry.slow-rendering"), + ctx.getOpenTelemetry().getTracer("io.opentelemetry.slow-rendering"), slowRenderingDetectionPollInterval); - application.registerActivityLifecycleCallbacks(detector); + ctx.getApplication().registerActivityLifecycleCallbacks(detector); detector.start(); } } diff --git a/instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentationTest.kt b/instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentationTest.kt index c4562df3..973b3880 100644 --- a/instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentationTest.kt +++ b/instrumentation/slowrendering/src/test/java/io/opentelemetry/android/instrumentation/slowrendering/SlowRenderingInstrumentationTest.kt @@ -14,6 +14,7 @@ import io.mockk.just import io.mockk.mockk import io.mockk.slot import io.mockk.verify +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.sdk.OpenTelemetrySdk import org.assertj.core.api.Assertions.assertThat import org.junit.Before @@ -63,7 +64,8 @@ class SlowRenderingInstrumentationTest { @Config(sdk = [23]) @Test fun `Not installing instrumentation on devices with API level lower than 24`() { - slowRenderingInstrumentation.install(application, openTelemetry) + val ctx = InstallationContext(application, openTelemetry, mockk()) + slowRenderingInstrumentation.install(ctx) verify { application wasNot Called @@ -79,8 +81,8 @@ class SlowRenderingInstrumentationTest { val capturedListener = slot() every { openTelemetry.getTracer(any()) }.returns(mockk()) every { application.registerActivityLifecycleCallbacks(any()) } just Runs - - slowRenderingInstrumentation.install(application, openTelemetry) + val ctx = InstallationContext(application, openTelemetry, mockk()) + slowRenderingInstrumentation.install(ctx) verify { openTelemetry.getTracer("io.opentelemetry.slow-rendering") } verify { application.registerActivityLifecycleCallbacks(capture(capturedListener)) } diff --git a/instrumentation/startup/src/main/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentation.kt b/instrumentation/startup/src/main/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentation.kt index 25a8763f..7ab8ccdf 100644 --- a/instrumentation/startup/src/main/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentation.kt +++ b/instrumentation/startup/src/main/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentation.kt @@ -5,21 +5,17 @@ package io.opentelemetry.android.instrumentation.startup -import android.app.Application import com.google.auto.service.AutoService import io.opentelemetry.android.instrumentation.AndroidInstrumentation +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.android.internal.initialization.InitializationEvents -import io.opentelemetry.api.OpenTelemetry @AutoService(AndroidInstrumentation::class) class StartupInstrumentation : AndroidInstrumentation { - override fun install( - application: Application, - openTelemetry: OpenTelemetry, - ) { + override fun install(ctx: InstallationContext) { val events = InitializationEvents.get() if (events is SdkInitializationEvents) { - events.finish(openTelemetry) + events.finish(ctx.openTelemetry) } } } diff --git a/instrumentation/startup/src/test/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentationTest.kt b/instrumentation/startup/src/test/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentationTest.kt index ab19df69..98f0eb6f 100644 --- a/instrumentation/startup/src/test/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentationTest.kt +++ b/instrumentation/startup/src/test/java/io/opentelemetry/android/instrumentation/startup/StartupInstrumentationTest.kt @@ -5,14 +5,16 @@ package io.opentelemetry.android.instrumentation.startup +import android.app.Application import io.mockk.Called import io.mockk.Runs import io.mockk.every import io.mockk.just import io.mockk.mockk import io.mockk.verify -import io.opentelemetry.android.OpenTelemetryRum +import io.opentelemetry.android.instrumentation.InstallationContext import io.opentelemetry.android.internal.initialization.InitializationEvents +import io.opentelemetry.android.internal.services.ServiceManager import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach @@ -41,7 +43,7 @@ class StartupInstrumentationTest { every { sdkInitializationEvents.finish(any()) } just Runs InitializationEvents.set(sdkInitializationEvents) - instrumentation.install(mockk(), otelTesting.openTelemetry) + instrumentation.install(makeContext()) verify { sdkInitializationEvents.finish(otelTesting.openTelemetry) @@ -51,11 +53,18 @@ class StartupInstrumentationTest { @Test fun `No action when the InitializationEvents instance is not SdkInitializationEvents`() { val initializationEvents = mockk() - val openTelemetryRum = mockk() InitializationEvents.set(initializationEvents) - instrumentation.install(mockk(), otelTesting.openTelemetry) + instrumentation.install(makeContext()) verify { initializationEvents wasNot Called } } + + private fun makeContext(): InstallationContext { + return InstallationContext( + mockk(), + otelTesting.openTelemetry, + mockk(), + ) + } }