Skip to content

Commit

Permalink
Instrumentation API part 9 (#486)
Browse files Browse the repository at this point in the history
* Moving InitializationEvents to the common api

* Adding auto service dependency

* Making SdkInitializationEvents a service

* Moving InitializationEvents to the agent

* Connecting StartupInstrumentation with SdkInitializationEvents

* Adding tests

* Adding tests

* Making InitializationEvents internal

* Removing autoService from java lib conventions
  • Loading branch information
LikeTheSalad authored Jul 29, 2024
1 parent 4b2181e commit 2bba3d7
Show file tree
Hide file tree
Showing 15 changed files with 267 additions and 106 deletions.
2 changes: 1 addition & 1 deletion android-agent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ android {

dependencies {
implementation(project(":common"))
implementation(project(":instrumentation:startup")) // todo remove during the initializationevents adaptation work.
implementation(project(":instrumentation:common-api"))
implementation(libs.androidx.core)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.lifecycle.process)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@
import io.opentelemetry.android.features.diskbuffering.SignalFromDiskExporter;
import io.opentelemetry.android.features.diskbuffering.scheduler.ExportScheduleHandler;
import io.opentelemetry.android.instrumentation.common.InstrumentedApplication;
import io.opentelemetry.android.instrumentation.startup.InitializationEvents;
import io.opentelemetry.android.instrumentation.startup.SdkInitializationEvents;
import io.opentelemetry.android.internal.features.networkattrs.NetworkAttributesSpanAppender;
import io.opentelemetry.android.internal.features.persistence.DiskManager;
import io.opentelemetry.android.internal.features.persistence.SimpleTemporaryFileProvider;
import io.opentelemetry.android.internal.initialization.InitializationEvents;
import io.opentelemetry.android.internal.processors.GlobalAttributesLogRecordAppender;
import io.opentelemetry.android.internal.services.CacheStorage;
import io.opentelemetry.android.internal.services.Preferences;
Expand Down Expand Up @@ -51,9 +50,7 @@
import io.opentelemetry.sdk.trace.export.SpanExporter;
import java.io.IOException;
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;
import java.util.function.Function;
Expand Down Expand Up @@ -89,7 +86,6 @@ public final class OpenTelemetryRumBuilder {
(a) -> a;

private Resource resource;
private InitializationEvents initializationEvents = InitializationEvents.NO_OP;

private static TextMapPropagator buildDefaultPropagator() {
return TextMapPropagator.composite(
Expand Down Expand Up @@ -277,7 +273,8 @@ public OpenTelemetryRum build() {
}

OpenTelemetryRum build(ServiceManager serviceManager) {
applyConfiguration(serviceManager);
InitializationEvents initializationEvents = InitializationEvents.get();
applyConfiguration(serviceManager, initializationEvents);

DiskBufferingConfiguration diskBufferingConfiguration =
config.getDiskBufferingConfiguration();
Expand Down Expand Up @@ -374,18 +371,10 @@ public OpenTelemetryRumBuilder addOtelSdkReadyListener(Consumer<OpenTelemetrySdk
}

/** Leverage the configuration to wire up various instrumentation components. */
private void applyConfiguration(ServiceManager serviceManager) {
private void applyConfiguration(
ServiceManager serviceManager, InitializationEvents initializationEvents) {
if (config.shouldGenerateSdkInitializationEvents()) {
if (initializationEvents == InitializationEvents.NO_OP) {
SdkInitializationEvents sdkInitEvents = new SdkInitializationEvents();
addOtelSdkReadyListener(sdkInitEvents::finish);
initializationEvents = sdkInitEvents;
}
Map<String, String> configMap = new HashMap<>();
// TODO: Convert config to map
// breedx-splk: Left incomplete for now, because I think Cesar is making changes around
// this
initializationEvents.recordConfiguration(configMap);
initializationEvents.recordConfiguration(config);
}
initializationEvents.sdkInitializationStarted();

Expand Down Expand Up @@ -485,9 +474,4 @@ private ContextPropagators buildFinalPropagators() {
TextMapPropagator defaultPropagator = buildDefaultPropagator();
return ContextPropagators.create(propagatorCustomizer.apply(defaultPropagator));
}

OpenTelemetryRumBuilder setInitializationEvents(InitializationEvents initializationEvents) {
this.initializationEvents = initializationEvents;
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.internal.initialization

import io.opentelemetry.android.config.OtelRumConfig
import io.opentelemetry.sdk.trace.export.SpanExporter
import java.util.ServiceLoader.load

/**
* This class is internal and not for public use. Its APIs are unstable and can change at any time.
*/
interface InitializationEvents {
fun sdkInitializationStarted()

fun recordConfiguration(config: OtelRumConfig)

fun currentNetworkProviderInitialized()

fun networkMonitorInitialized()

fun anrMonitorInitialized()

fun slowRenderingDetectorInitialized()

fun crashReportingInitialized()

fun spanExporterInitialized(spanExporter: SpanExporter)

companion object {
private var instance: InitializationEvents? = null

@JvmStatic
fun get(): InitializationEvents {
if (instance == null) {
val initializationEvents = load(InitializationEvents::class.java).firstOrNull()
if (initializationEvents != null) {
set(initializationEvents)
} else {
set(NO_OP)
}
}

return instance!!
}

@JvmStatic
fun set(initializationEvents: InitializationEvents) {
if (instance == null) {
instance = initializationEvents
}
}

@JvmStatic
fun resetForTest() {
instance = null
}

val NO_OP: InitializationEvents =
object : InitializationEvents {
override fun sdkInitializationStarted() {}

override fun recordConfiguration(config: OtelRumConfig) {}

override fun currentNetworkProviderInitialized() {}

override fun networkMonitorInitialized() {}

override fun anrMonitorInitialized() {}

override fun slowRenderingDetectorInitialized() {}

override fun crashReportingInitialized() {}

override fun spanExporterInitialized(spanExporter: SpanExporter) {}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import io.opentelemetry.android.features.diskbuffering.DiskBufferingConfiguration;
import io.opentelemetry.android.features.diskbuffering.SignalFromDiskExporter;
import io.opentelemetry.android.features.diskbuffering.scheduler.ExportScheduleHandler;
import io.opentelemetry.android.instrumentation.startup.InitializationEvents;
import io.opentelemetry.android.internal.initialization.InitializationEvents;
import io.opentelemetry.android.internal.services.CacheStorage;
import io.opentelemetry.android.internal.services.Preferences;
import io.opentelemetry.android.internal.services.ServiceManager;
Expand Down Expand Up @@ -105,12 +105,14 @@ public void setup() {
mocks = MockitoAnnotations.openMocks(this);
when(application.getApplicationContext()).thenReturn(applicationContext);
when(application.getMainLooper()).thenReturn(looper);
InitializationEvents.set(initializationEvents);
}

@After
public void tearDown() throws Exception {
SignalFromDiskExporter.resetForTesting();
mocks.close();
InitializationEvents.resetForTest();
}

@Test
Expand Down Expand Up @@ -302,9 +304,7 @@ public void diskBufferingEnabled() {
.build());
ArgumentCaptor<SpanExporter> exporterCaptor = ArgumentCaptor.forClass(SpanExporter.class);

OpenTelemetryRum.builder(application, config)
.setInitializationEvents(initializationEvents)
.build(serviceManager);
OpenTelemetryRum.builder(application, config).build(serviceManager);

assertThat(SignalFromDiskExporter.get()).isNotNull();
verify(scheduleHandler).enable();
Expand Down Expand Up @@ -333,9 +333,7 @@ public void diskBufferingEnabled_when_exception_thrown() {
.setExportScheduleHandler(scheduleHandler)
.build());

OpenTelemetryRum.builder(application, config)
.setInitializationEvents(initializationEvents)
.build(serviceManager);
OpenTelemetryRum.builder(application, config).build(serviceManager);

verify(initializationEvents).spanExporterInitialized(exporterCaptor.capture());
verify(scheduleHandler, never()).enable();
Expand Down Expand Up @@ -366,9 +364,7 @@ public void diskBufferingDisabled() {
.setExportScheduleHandler(scheduleHandler)
.build());

OpenTelemetryRum.builder(application, config)
.setInitializationEvents(initializationEvents)
.build();
OpenTelemetryRum.builder(application, config).build();

verify(initializationEvents).spanExporterInitialized(exporterCaptor.capture());
verify(scheduleHandler, never()).enable();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.internal.initialization

import io.mockk.mockk
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test

class InitializationEventsTest {
@AfterEach
fun tearDown() {
InitializationEvents.resetForTest()
}

@Test
fun `Verify service loading`() {
val initializationEvents = InitializationEvents.get()
assertThat(initializationEvents).isInstanceOf(TestInitializationEvents::class.java)
}

@Test
fun `Verify setting instance once`() {
val initializationEvents = mockk<InitializationEvents>()
InitializationEvents.set(initializationEvents)

assertThat(InitializationEvents.get()).isEqualTo(initializationEvents)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.internal.initialization

import io.opentelemetry.android.config.OtelRumConfig
import io.opentelemetry.sdk.trace.export.SpanExporter

class TestInitializationEvents : InitializationEvents {
override fun sdkInitializationStarted() {
}

override fun recordConfiguration(config: OtelRumConfig) {
}

override fun currentNetworkProviderInitialized() {
}

override fun networkMonitorInitialized() {
}

override fun anrMonitorInitialized() {
}

override fun slowRenderingDetectorInitialized() {
}

override fun crashReportingInitialized() {
}

override fun spanExporterInitialized(spanExporter: SpanExporter) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.opentelemetry.android.internal.initialization.TestInitializationEvents
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("otel.errorprone-conventions")
id("kotlin-kapt")
}

val javaVersion = rootProject.extra["java_version"] as JavaVersion
Expand Down Expand Up @@ -44,6 +45,8 @@ tasks.withType<Test> {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
implementation(libs.findLibrary("findbugs-jsr305").get())
compileOnly(libs.findLibrary("auto-service-annotations").get())
kapt(libs.findLibrary("auto-service-processor").get())
testImplementation(libs.findLibrary("assertj-core").get())
testImplementation(libs.findBundle("mocking").get())
testImplementation(libs.findBundle("junit").get())
Expand Down
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ spotless = "6.25.0"
kotlin = "2.0.0"
androidPlugin = "8.5.1"
junitKtx = "1.2.1"
autoService = "1.1.1"

[libraries]
opentelemetry-platform = { module = "io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom", version.ref = "opentelemetry-instrumentation" }
Expand All @@ -36,6 +37,8 @@ opentelemetry-exporter-logging = { module = "io.opentelemetry:opentelemetry-expo
opentelemetry-diskBuffering = { module = "io.opentelemetry.contrib:opentelemetry-disk-buffering", version.ref = "opentelemetry-contrib" }
opentelemetry-exporter-otlp = { module = "io.opentelemetry:opentelemetry-exporter-otlp", version.ref = "opentelemetry" }
volley = "com.android.volley:volley:1.2.1"
auto-service-annotations = { module = "com.google.auto.service:auto-service-annotations", version.ref = "autoService" }
auto-service-processor = { module = "com.google.auto.service:auto-service", version.ref = "autoService" }

#Test tools
opentelemetry-sdk-testing = { module = "io.opentelemetry:opentelemetry-sdk-testing", version.ref = "opentelemetry" }
Expand Down
2 changes: 1 addition & 1 deletion instrumentation/startup/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ android {
dependencies {
api(platform(libs.opentelemetry.platform))
api(libs.opentelemetry.api)
api(project(":android-agent"))
api(project(":common"))
api(project(":instrumentation:common-api"))
implementation(libs.androidx.core)
implementation(libs.opentelemetry.semconv)
implementation(libs.opentelemetry.sdk)
Expand Down

This file was deleted.

Loading

0 comments on commit 2bba3d7

Please sign in to comment.