Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instrumentation API part 10 #498

Merged
merged 13 commits into from
Jul 31, 2024
Merged
89 changes: 15 additions & 74 deletions android-agent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,24 @@ plugins {
}

android {
namespace = "io.opentelemetry.android"

buildToolsVersion = "34.0.0"

defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
buildConfigField("String", "OTEL_ANDROID_VERSION", "\"$version\"")
}

buildTypes {
all {
resValue("string", "rum.version", "${project.version}")
}
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}

androidComponents {
onVariants {
if (it.buildType == "release") { // The one we choose to release
project.tasks.register("createReleaseBuild", Copy::class) {
from(it.artifacts.get(com.android.build.api.artifact.SingleArtifact.AAR))
into(project.layout.buildDirectory.dir("outputs/aar"))
rename(".+", "opentelemetry-android.aar")
}
}
}
}

project.afterEvaluate {
tasks.named("assembleRelease") {
finalizedBy("createReleaseBuild")
}
}

testOptions {
unitTests.isReturnDefaultValues = true
unitTests.isIncludeAndroidResources = true
}

buildFeatures {
buildConfig = true
}

sourceSets {
getByName("test") {
kotlin.srcDirs("src/integrationTest/kotlin")
}
}
namespace = "io.opentelemetry.android.agent"
}

dependencies {
implementation(project(":common"))
implementation(project(":instrumentation:common-api"))
implementation(libs.androidx.core)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.lifecycle.process)

api(platform(libs.opentelemetry.platform))
api(libs.opentelemetry.api)
implementation(libs.opentelemetry.sdk)
implementation(libs.opentelemetry.exporter.logging)
api(project(":core"))
implementation(libs.opentelemetry.instrumentation.api)
implementation(libs.opentelemetry.semconv.incubating)
implementation(libs.opentelemetry.diskBuffering)
testImplementation(libs.opentelemetry.api.incubator)
testImplementation(libs.androidx.test.core)
testImplementation(libs.awaitility)
testImplementation(libs.robolectric)
testImplementation(libs.androidx.junit.ktx)

// Default instrumentations:
api(project(":instrumentation:activity"))
api(project(":instrumentation:fragment"))
api(project(":instrumentation:crash"))
api(project(":instrumentation:startup"))
api(project(":instrumentation:slowrendering"))
api(project(":instrumentation:anr"))
api(project(":instrumentation:network"))
}

extra["pomName"] = "OpenTelemetry Android Instrumentation"
description = "A library for instrumenting Android applications with OpenTelemetry"
extra["pomName"] = "OpenTelemetry Android Agent"
description =
"A library that contains all the commonly needed instrumentation for Android apps in a " +
"convenient way with minimum configuration needed."
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.agent

import io.opentelemetry.android.config.OtelRumConfig
import io.opentelemetry.android.instrumentation.AndroidInstrumentationRegistry
import io.opentelemetry.android.instrumentation.activity.ActivityLifecycleInstrumentation
import io.opentelemetry.android.instrumentation.anr.AnrInstrumentation
import io.opentelemetry.android.instrumentation.common.ScreenNameExtractor
import io.opentelemetry.android.instrumentation.crash.CrashDetails
import io.opentelemetry.android.instrumentation.crash.CrashReporterInstrumentation
import io.opentelemetry.android.instrumentation.fragment.FragmentLifecycleInstrumentation
import io.opentelemetry.android.instrumentation.network.NetworkChangeInstrumentation
import io.opentelemetry.android.instrumentation.slowrendering.SlowRenderingInstrumentation
import io.opentelemetry.android.internal.services.network.data.CurrentNetwork
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor
import java.time.Duration

/**
Copy link
Contributor Author

@LikeTheSalad LikeTheSalad Jul 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file isn't really needed, I added it because it seemed handy to have those options in OtelRumConfig.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah interesting, I hadn't thought of doing it with extension methods.... 🤔

* Convenience functions to allow configuring the default instrumentations through the [OtelRumConfig] object, for example:
*
* ```
* OtelRumConfig()
* .setSessionTimeout(Duration.ofSeconds(10)) // Real OtelRumConfig function
* .setSlowRenderingDetectionPollInterval(Duration.ofSeconds(5)) // Extension function
* .disableScreenAttributes() // Real OtelRumConfig function
* ```
*/

fun OtelRumConfig.setActivityTracerCustomizer(customizer: (Tracer) -> Tracer): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(ActivityLifecycleInstrumentation::class.java)
?.setTracerCustomizer(customizer)
return this
}

fun OtelRumConfig.setActivityNameExtractor(screenNameExtractor: ScreenNameExtractor): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(ActivityLifecycleInstrumentation::class.java)
?.setScreenNameExtractor(screenNameExtractor)
return this
}

fun OtelRumConfig.setFragmentTracerCustomizer(customizer: (Tracer) -> Tracer): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(FragmentLifecycleInstrumentation::class.java)
?.setTracerCustomizer(customizer)
return this
}

fun OtelRumConfig.setFragmentNameExtractor(screenNameExtractor: ScreenNameExtractor): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(FragmentLifecycleInstrumentation::class.java)
?.setScreenNameExtractor(screenNameExtractor)
return this
}

fun OtelRumConfig.addAnrAttributesExtractor(extractor: AttributesExtractor<Array<StackTraceElement>, Void>): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(AnrInstrumentation::class.java)
?.addAttributesExtractor(extractor)
return this
}

fun OtelRumConfig.addCrashAttributesExtractor(extractor: AttributesExtractor<CrashDetails, Void>): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(CrashReporterInstrumentation::class.java)
?.addAttributesExtractor(extractor)
return this
}

fun OtelRumConfig.addNetworkChangeAttributesExtractor(extractor: AttributesExtractor<CurrentNetwork, Void>): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(NetworkChangeInstrumentation::class.java)
?.addAttributesExtractor(extractor)
return this
}

fun OtelRumConfig.setSlowRenderingDetectionPollInterval(interval: Duration): OtelRumConfig {
AndroidInstrumentationRegistry.get().get(SlowRenderingInstrumentation::class.java)
?.setSlowRenderingDetectionPollInterval(interval)
return this
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ tasks.withType<Test> {
val libs = extensions.getByType<VersionCatalogsExtension>().named("libs")
dependencies {
implementation(libs.findLibrary("findbugs-jsr305").get())
compileOnly(libs.findLibrary("auto-service-annotations").get())
implementation(libs.findLibrary("auto-service-annotations").get())
kapt(libs.findLibrary("auto-service-processor").get())
testImplementation(libs.findLibrary("assertj-core").get())
testImplementation(libs.findBundle("mocking").get())
Expand Down
20 changes: 0 additions & 20 deletions common/build.gradle.kts

This file was deleted.

84 changes: 84 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
plugins {
id("otel.android-library-conventions")
id("otel.publish-conventions")
}

android {
namespace = "io.opentelemetry.android"

buildToolsVersion = "34.0.0"

defaultConfig {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
buildConfigField("String", "OTEL_ANDROID_VERSION", "\"$version\"")
}

buildTypes {
all {
resValue("string", "rum.version", "${project.version}")
}
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}

androidComponents {
onVariants {
if (it.buildType == "release") { // The one we choose to release
project.tasks.register("createReleaseBuild", Copy::class) {
from(it.artifacts.get(com.android.build.api.artifact.SingleArtifact.AAR))
into(project.layout.buildDirectory.dir("outputs/aar"))
rename(".+", "opentelemetry-android.aar")
}
}
}
}

project.afterEvaluate {
tasks.named("assembleRelease") {
finalizedBy("createReleaseBuild")
}
}

testOptions {
unitTests.isReturnDefaultValues = true
unitTests.isIncludeAndroidResources = true
}

buildFeatures {
buildConfig = true
}

sourceSets {
getByName("test") {
kotlin.srcDirs("src/integrationTest/kotlin")
}
}
}

dependencies {
implementation(libs.androidx.core)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.lifecycle.process)

api(platform(libs.opentelemetry.platform))
api(libs.opentelemetry.api)
implementation(libs.opentelemetry.sdk)
implementation(libs.opentelemetry.exporter.logging)
implementation(libs.opentelemetry.instrumentation.api)
implementation(libs.opentelemetry.semconv.incubating)
implementation(libs.opentelemetry.diskBuffering)
testImplementation(libs.opentelemetry.api.incubator)
testImplementation(libs.androidx.test.core)
testImplementation(libs.awaitility)
testImplementation(libs.robolectric)
testImplementation(libs.androidx.junit.ktx)
}

extra["pomName"] = "OpenTelemetry Android Instrumentation"
description = "A library for instrumenting Android applications with OpenTelemetry"
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ static OpenTelemetryRumBuilder builder(Application application) {
* SDK as a parameter.
*/
static OpenTelemetryRumBuilder builder(Application application, OtelRumConfig config) {
return new OpenTelemetryRumBuilder(application, config);
return OpenTelemetryRumBuilder.create(application, config);
}

/**
Expand All @@ -58,10 +58,15 @@ static OpenTelemetryRumBuilder builder(Application application, OtelRumConfig co
*
* @param application The {@link Application} that is being instrumented.
* @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.
*/
static SdkPreconfiguredRumBuilder builder(
Application application, OpenTelemetrySdk openTelemetrySdk) {
return new SdkPreconfiguredRumBuilder(application, openTelemetrySdk);
Application application,
OpenTelemetrySdk openTelemetrySdk,
boolean discoverInstrumentations) {
return new SdkPreconfiguredRumBuilder(
application, openTelemetrySdk, discoverInstrumentations);
}

/** Returns a no-op implementation of {@link OpenTelemetryRum}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,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.common.InstrumentedApplication;
import io.opentelemetry.android.instrumentation.AndroidInstrumentation;
import io.opentelemetry.android.internal.features.networkattrs.NetworkAttributesSpanAppender;
import io.opentelemetry.android.internal.features.persistence.DiskManager;
import io.opentelemetry.android.internal.features.persistence.SimpleTemporaryFileProvider;
Expand Down Expand Up @@ -74,10 +74,7 @@ public final class OpenTelemetryRumBuilder {
private final List<BiFunction<SdkLoggerProviderBuilder, Application, SdkLoggerProviderBuilder>>
loggerProviderCustomizers = new ArrayList<>();
private final OtelRumConfig config;

private final List<Consumer<InstrumentedApplication>> instrumentationInstallers =
new ArrayList<>();

private final List<AndroidInstrumentation> instrumentations = new ArrayList<>();
private final List<Consumer<OpenTelemetrySdk>> otelSdkReadyListeners = new ArrayList<>();
private Function<? super SpanExporter, ? extends SpanExporter> spanExporterCustomizer = a -> a;
private Function<? super LogRecordExporter, ? extends LogRecordExporter>
Expand All @@ -92,10 +89,14 @@ private static TextMapPropagator buildDefaultPropagator() {
W3CTraceContextPropagator.getInstance(), W3CBaggagePropagator.getInstance());
}

OpenTelemetryRumBuilder(Application application, OtelRumConfig config) {
public static OpenTelemetryRumBuilder create(Application application, OtelRumConfig config) {
return new OpenTelemetryRumBuilder(
application, config, new SessionIdTimeoutHandler(config.getSessionTimeout()));
}

OpenTelemetryRumBuilder(
Application application, OtelRumConfig config, SessionIdTimeoutHandler timeoutHandler) {
this.application = application;
final SessionIdTimeoutHandler timeoutHandler =
new SessionIdTimeoutHandler(config.getSessionTimeout());
this.sessionId = new SessionId(timeoutHandler);
this.resource = AndroidResource.createDefault(application);
this.config = config;
Expand Down Expand Up @@ -184,14 +185,12 @@ public OpenTelemetryRumBuilder addLoggerProviderCustomizer(
}

/**
* Adds an instrumentation installer function that will be run on an {@link
* InstrumentedApplication} instance as a part of the {@link #build()} method call.
* Adds an instrumentation to be applied as a part of the {@link #build()} method call.
*
* @return {@code this}
*/
public OpenTelemetryRumBuilder addInstrumentation(
Consumer<InstrumentedApplication> instrumentationInstaller) {
instrumentationInstallers.add(instrumentationInstaller);
public OpenTelemetryRumBuilder addInstrumentation(AndroidInstrumentation instrumentation) {
instrumentations.add(instrumentation);
return this;
}

Expand Down Expand Up @@ -319,8 +318,12 @@ OpenTelemetryRum build(ServiceManager serviceManager) {

SdkPreconfiguredRumBuilder delegate =
new SdkPreconfiguredRumBuilder(
application, sdk, sessionId, serviceManager::getAppLifecycleService);
instrumentationInstallers.forEach(delegate::addInstrumentation);
application,
sdk,
sessionId,
serviceManager::getAppLifecycleService,
config.shouldDiscoverInstrumentations());
instrumentations.forEach(delegate::addInstrumentation);
serviceManager.start();
return delegate.build();
}
Expand Down
Loading