Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions android-agent/api/android-agent.api
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ public abstract interface annotation class io/opentelemetry/android/Incubating :

public final class io/opentelemetry/android/agent/OpenTelemetryRumInitializer {
public static final field INSTANCE Lio/opentelemetry/android/agent/OpenTelemetryRumInitializer;
public static final fun initialize (Landroid/app/Application;Ljava/lang/String;Ljava/util/Map;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/session/SessionConfig;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lio/opentelemetry/android/OpenTelemetryRum;
public static synthetic fun initialize$default (Landroid/app/Application;Ljava/lang/String;Ljava/util/Map;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/connectivity/EndpointConnectivity;Lio/opentelemetry/android/agent/session/SessionConfig;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/opentelemetry/android/OpenTelemetryRum;
public static final fun initialize (Landroid/app/Application;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lio/opentelemetry/android/OpenTelemetryRum;
public static synthetic fun initialize$default (Landroid/app/Application;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lio/opentelemetry/android/OpenTelemetryRum;
}

public abstract interface class io/opentelemetry/android/agent/connectivity/EndpointConnectivity {
Expand Down Expand Up @@ -32,6 +32,38 @@ public final class io/opentelemetry/android/agent/dsl/DiskBufferingConfiguration
public fun enabled (Z)V
}

public final class io/opentelemetry/android/agent/dsl/EndpointConfiguration {
public final fun getHeaders ()Ljava/util/Map;
public final fun getUrl ()Ljava/lang/String;
public final fun setHeaders (Ljava/util/Map;)V
public final fun setUrl (Ljava/lang/String;)V
}

public final class io/opentelemetry/android/agent/dsl/HttpExportConfiguration {
public final fun getBaseHeaders ()Ljava/util/Map;
public final fun getBaseUrl ()Ljava/lang/String;
public final fun logs (Lkotlin/jvm/functions/Function1;)V
public final fun metrics (Lkotlin/jvm/functions/Function1;)V
public final fun setBaseHeaders (Ljava/util/Map;)V
public final fun setBaseUrl (Ljava/lang/String;)V
public final fun spans (Lkotlin/jvm/functions/Function1;)V
}

public final class io/opentelemetry/android/agent/dsl/OpenTelemetryConfiguration {
public fun <init> ()V
public final fun httpExport (Lkotlin/jvm/functions/Function1;)V
public final fun instrumentations (Lkotlin/jvm/functions/Function1;)V
public final fun session (Lkotlin/jvm/functions/Function1;)V
}

public final class io/opentelemetry/android/agent/dsl/SessionConfiguration {
public synthetic fun <init> (JJILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getBackgroundInactivityTimeout-UwyO8pc ()J
public final fun getMaxLifetime-UwyO8pc ()J
public final fun setBackgroundInactivityTimeout-LRDsOJo (J)V
public final fun setMaxLifetime-LRDsOJo (J)V
}

public final class io/opentelemetry/android/agent/dsl/instrumentation/ActivityLifecycleConfiguration : io/opentelemetry/android/agent/dsl/instrumentation/CanBeEnabledAndDisabled, io/opentelemetry/android/agent/dsl/instrumentation/ScreenLifecycleConfigurable {
public fun enabled (Z)V
public fun screenNameExtractor (Lio/opentelemetry/android/instrumentation/common/ScreenNameExtractor;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ package io.opentelemetry.android.agent
import android.app.Application
import io.opentelemetry.android.Incubating
import io.opentelemetry.android.OpenTelemetryRum
import io.opentelemetry.android.agent.connectivity.EndpointConnectivity
import io.opentelemetry.android.agent.connectivity.HttpEndpointConnectivity
import io.opentelemetry.android.agent.dsl.DiskBufferingConfigurationSpec
import io.opentelemetry.android.agent.dsl.instrumentation.InstrumentationConfiguration
import io.opentelemetry.android.agent.dsl.OpenTelemetryConfiguration
import io.opentelemetry.android.agent.session.SessionConfig
import io.opentelemetry.android.agent.session.SessionIdTimeoutHandler
import io.opentelemetry.android.agent.session.SessionManager
Expand All @@ -30,47 +28,21 @@ object OpenTelemetryRumInitializer {
* Opinionated [OpenTelemetryRum] initialization.
*
* @param application Your android app's application object.
* @param endpointBaseUrl The base endpoint for exporting all your signals.
* @param endpointHeaders These will be added to each signal export request.
* @param spanEndpointConnectivity Span-specific endpoint configuration.
* @param logEndpointConnectivity Log-specific endpoint configuration.
* @param metricEndpointConnectivity Metric-specific endpoint configuration.
* @param sessionConfig The session configuration, which includes inactivity timeout and maximum lifetime durations.
* @param globalAttributes Configures the set of global attributes to emit with every span and event.
* @param diskBuffering Configures the disk buffering feature.
* @param instrumentations Configurations for all the default instrumentations.
* @param configuration Type-safe config DSL that controls how OpenTelemetry
* should behave.
*/
@Suppress("LongParameterList")
@JvmStatic
fun initialize(
application: Application,
endpointBaseUrl: String,
endpointHeaders: Map<String, String> = emptyMap(),
spanEndpointConnectivity: EndpointConnectivity =
HttpEndpointConnectivity.forTraces(
endpointBaseUrl,
endpointHeaders,
),
logEndpointConnectivity: EndpointConnectivity =
HttpEndpointConnectivity.forLogs(
endpointBaseUrl,
endpointHeaders,
),
metricEndpointConnectivity: EndpointConnectivity =
HttpEndpointConnectivity.forMetrics(
endpointBaseUrl,
endpointHeaders,
),
sessionConfig: SessionConfig = SessionConfig.withDefaults(),
globalAttributes: (() -> Attributes)? = null,
diskBuffering: (DiskBufferingConfigurationSpec.() -> Unit)? = null,
Comment on lines 39 to 40
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe a discussion for another PR, though I'm curious about the decision process to decide which parameters are left on the initializer method's arguments, vs which ones are placed into the Configuration dsl?

Copy link
Member Author

Choose a reason for hiding this comment

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

@LikeTheSalad I'd like to move basically every parameter apart from Application onto the Configuration DSL. I wanted to keep the PR size small particularly as other folks had PRs in flight, and should be able to open another PR towards the end of the week that moves the rest.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good to me, thanks for the clarification.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've moved the rest over in #1313

instrumentations: (InstrumentationConfiguration.() -> Unit)? = null,
configuration: (OpenTelemetryConfiguration.() -> Unit) = {},
): OpenTelemetryRum {
val rumConfig = OtelRumConfig()

instrumentations?.let { configure ->
InstrumentationConfiguration(rumConfig).configure()
}
val cfg = OpenTelemetryConfiguration(rumConfig)
configuration(cfg)

val diskBufferingConfigurationSpec = DiskBufferingConfigurationSpec()
diskBuffering?.invoke(diskBufferingConfigurationSpec)
Expand All @@ -79,26 +51,32 @@ object OpenTelemetryRumInitializer {
globalAttributes?.let {
rumConfig.setGlobalAttributes(it::invoke)
}

val sessionConfig =
SessionConfig(
cfg.sessionConfig.backgroundInactivityTimeout,
cfg.sessionConfig.maxLifetime,
)
return OpenTelemetryRum
.builder(application, rumConfig)
.builder(application, cfg.rumConfig)
.setSessionProvider(createSessionProvider(application, sessionConfig))
.addSpanExporterCustomizer {
OtlpHttpSpanExporter
.builder()
.setEndpoint(spanEndpointConnectivity.getUrl())
.setHeaders(spanEndpointConnectivity::getHeaders)
.setEndpoint(cfg.exportConfig.spansConfig.url)
.setHeaders(cfg.exportConfig.spansConfig::headers)
.build()
}.addLogRecordExporterCustomizer {
OtlpHttpLogRecordExporter
.builder()
.setEndpoint(logEndpointConnectivity.getUrl())
.setHeaders(logEndpointConnectivity::getHeaders)
.setEndpoint(cfg.exportConfig.logsConfig.url)
.setHeaders(cfg.exportConfig.logsConfig::headers)
.build()
}.addMetricExporterCustomizer {
OtlpHttpMetricExporter
.builder()
.setEndpoint(metricEndpointConnectivity.getUrl())
.setHeaders(metricEndpointConnectivity::getHeaders)
.setEndpoint(cfg.exportConfig.metricsConfig.url)
.setHeaders(cfg.exportConfig.metricsConfig::headers)
.build()
}.build()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.dsl

@OpenTelemetryDslMarker
class EndpointConfiguration internal constructor(
var url: String,
var headers: Map<String, String> = emptyMap(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.dsl

import io.opentelemetry.android.agent.connectivity.HttpEndpointConnectivity

@OpenTelemetryDslMarker
class HttpExportConfiguration internal constructor() {
/**
* Global URL for HTTP export requests.
*/
var baseUrl: String = ""

/**
* Global headers that should be attached to any HTTP export requests.
*/
var baseHeaders: Map<String, String> = emptyMap()

internal val spansConfig: EndpointConfiguration =
HttpEndpointConnectivity
.forTraces(
baseUrl,
baseHeaders,
).let(::toEndpointConfiguration)

internal val logsConfig: EndpointConfiguration =
HttpEndpointConnectivity
.forLogs(
baseUrl,
baseHeaders,
).let(::toEndpointConfiguration)

internal val metricsConfig: EndpointConfiguration =
HttpEndpointConnectivity
.forMetrics(
baseUrl,
baseHeaders,
).let(::toEndpointConfiguration)

fun spans(action: EndpointConfiguration.() -> Unit) {
spansConfig.action()
}

fun logs(action: EndpointConfiguration.() -> Unit) {
logsConfig.action()
}

fun metrics(action: EndpointConfiguration.() -> Unit) {
metricsConfig.action()
}

private fun toEndpointConfiguration(connectivity: HttpEndpointConnectivity): EndpointConfiguration =
EndpointConfiguration(connectivity.getUrl(), connectivity.getHeaders())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.dsl

import io.opentelemetry.android.Incubating
import io.opentelemetry.android.agent.dsl.instrumentation.InstrumentationConfiguration
import io.opentelemetry.android.config.OtelRumConfig

/**
* Type-safe config DSL that controls how OpenTelemetry should behave.
*/
@OptIn(Incubating::class)
@OpenTelemetryDslMarker
class OpenTelemetryConfiguration internal constructor(
internal val rumConfig: OtelRumConfig = OtelRumConfig(),
) {
internal val exportConfig: HttpExportConfiguration = HttpExportConfiguration()

internal val sessionConfig: SessionConfiguration = SessionConfiguration()

/**
* Configures individual instrumentations.
*/
internal val instrumentations: InstrumentationConfiguration =
InstrumentationConfiguration(rumConfig)

/**
* Configures how OpenTelemetry should export telemetry over HTTP.
*/
fun httpExport(action: HttpExportConfiguration.() -> Unit) {
exportConfig.action()
}

/**
* Configures individual instrumentations.
*/
fun instrumentations(action: InstrumentationConfiguration.() -> Unit) {
instrumentations.action()
}

/**
* Configures session behavior.
*/
fun session(action: SessionConfiguration.() -> Unit) {
sessionConfig.action()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.dsl

import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.minutes

@OpenTelemetryDslMarker
class SessionConfiguration internal constructor(
var backgroundInactivityTimeout: Duration = 15.minutes,
var maxLifetime: Duration = 4.hours,
)
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ class OpenTelemetryRumInitializerTest {
fun `Verify timeoutHandler initialization`() {
createAndSetServiceManager()

OpenTelemetryRumInitializer.initialize(
RuntimeEnvironment.getApplication(),
"http://127.0.0.1:4318",
)
OpenTelemetryRumInitializer.initialize(RuntimeEnvironment.getApplication()) {
httpExport {
baseUrl = "http://127.0.0.1:4318"
}
}

verify {
appLifecycle.registerListener(any<SessionIdTimeoutHandler>())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,16 @@ class OtelDemoApplication : Application() {

Log.i(TAG, "Initializing the opentelemetry-android-agent")

// 10.0.2.2 is apparently a special binding to the host running the emulator
// 10.0.2.2 is a special binding to the host running the emulator
try {
rum = OpenTelemetryRumInitializer.initialize(
application = this,
endpointBaseUrl = "http://10.0.2.2:4318",
globalAttributes = { Attributes.of(stringKey("toolkit"), "jetpack compose") }
globalAttributes = { Attributes.of(stringKey("toolkit"), "jetpack compose") },
configuration = {
httpExport {
baseUrl = "http://10.0.2.2:4318"
}
}
)
Log.d(TAG, "RUM session started: " + rum?.getRumSessionId())
} catch (e: Exception) {
Expand Down Expand Up @@ -72,7 +76,8 @@ class OtelDemoApplication : Application() {
}

fun counter(name: String): LongCounter? {
return rum?.getOpenTelemetry()?.meterProvider?.get("demo.app")?.counterBuilder(name)?.build()
return rum?.getOpenTelemetry()?.meterProvider?.get("demo.app")?.counterBuilder(name)
?.build()
}

fun eventBuilder(scopeName: String, eventName: String): LogRecordBuilder {
Expand Down