Skip to content
Open
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
35 changes: 35 additions & 0 deletions android-agent/api/android-agent.api
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ public final class io/opentelemetry/android/agent/connectivity/Compression : jav
public static fun values ()[Lio/opentelemetry/android/agent/connectivity/Compression;
}

public final class io/opentelemetry/android/agent/connectivity/ExportProtocol : java/lang/Enum {
public static final field GRPC Lio/opentelemetry/android/agent/connectivity/ExportProtocol;
public static final field HTTP Lio/opentelemetry/android/agent/connectivity/ExportProtocol;
public static fun valueOf (Ljava/lang/String;)Lio/opentelemetry/android/agent/connectivity/ExportProtocol;
public static fun values ()[Lio/opentelemetry/android/agent/connectivity/ExportProtocol;
}

public final class io/opentelemetry/android/agent/dsl/DiskBufferingConfigurationSpec : io/opentelemetry/android/agent/dsl/instrumentation/CanBeEnabledAndDisabled {
public fun enabled (Z)V
}
Expand All @@ -27,6 +34,32 @@ public final class io/opentelemetry/android/agent/dsl/EndpointConfiguration {
public final fun setUrl (Ljava/lang/String;)V
}

public final class io/opentelemetry/android/agent/dsl/ExportConfiguration {
public final fun getCompression ()Lio/opentelemetry/android/agent/connectivity/Compression;
public final fun getEndpoint ()Ljava/lang/String;
public final fun getHeaders ()Ljava/util/Map;
public final fun getProtocol ()Lio/opentelemetry/android/agent/connectivity/ExportProtocol;
public final fun logs (Lkotlin/jvm/functions/Function1;)V
public final fun metrics (Lkotlin/jvm/functions/Function1;)V
public final fun setCompression (Lio/opentelemetry/android/agent/connectivity/Compression;)V
public final fun setEndpoint (Ljava/lang/String;)V
public final fun setHeaders (Ljava/util/Map;)V
public final fun setProtocol (Lio/opentelemetry/android/agent/connectivity/ExportProtocol;)V
public final fun spans (Lkotlin/jvm/functions/Function1;)V
}

public final class io/opentelemetry/android/agent/dsl/GrpcExportConfiguration {
public final fun getCompression ()Lio/opentelemetry/android/agent/connectivity/Compression;
public final fun getEndpoint ()Ljava/lang/String;
public final fun getHeaders ()Ljava/util/Map;
public final fun logs (Lkotlin/jvm/functions/Function1;)V
public final fun metrics (Lkotlin/jvm/functions/Function1;)V
public final fun setCompression (Lio/opentelemetry/android/agent/connectivity/Compression;)V
public final fun setEndpoint (Ljava/lang/String;)V
public final fun setHeaders (Ljava/util/Map;)V
public final fun spans (Lkotlin/jvm/functions/Function1;)V
}

public final class io/opentelemetry/android/agent/dsl/HttpExportConfiguration {
public final fun getBaseHeaders ()Ljava/util/Map;
public final fun getBaseUrl ()Ljava/lang/String;
Expand All @@ -42,8 +75,10 @@ public final class io/opentelemetry/android/agent/dsl/HttpExportConfiguration {
public final class io/opentelemetry/android/agent/dsl/OpenTelemetryConfiguration {
public fun <init> ()V
public final fun diskBuffering (Lkotlin/jvm/functions/Function1;)V
public final fun export (Lkotlin/jvm/functions/Function1;)V
public final fun getClock ()Lio/opentelemetry/sdk/common/Clock;
public final fun globalAttributes (Lkotlin/jvm/functions/Function0;)V
public final fun grpcExport (Lkotlin/jvm/functions/Function1;)V
public final fun httpExport (Lkotlin/jvm/functions/Function1;)V
public final fun instrumentations (Lkotlin/jvm/functions/Function1;)V
public final fun resource (Lkotlin/jvm/functions/Function1;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import io.opentelemetry.android.Incubating
import io.opentelemetry.android.OpenTelemetryRum
import io.opentelemetry.android.RumBuilder
import io.opentelemetry.android.agent.connectivity.Compression
import io.opentelemetry.android.agent.connectivity.EndpointConnectivity
import io.opentelemetry.android.agent.connectivity.ExportProtocol
import io.opentelemetry.android.agent.dsl.OpenTelemetryConfiguration
import io.opentelemetry.android.agent.session.SessionConfig
import io.opentelemetry.android.agent.session.SessionIdTimeoutHandler
Expand All @@ -21,19 +23,15 @@ import io.opentelemetry.android.session.SessionProvider
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.sdk.logs.export.LogRecordExporter
import io.opentelemetry.sdk.metrics.export.MetricExporter
import io.opentelemetry.sdk.trace.export.SpanExporter

@OptIn(Incubating::class)
object OpenTelemetryRumInitializer {
/**
* Opinionated [io.opentelemetry.android.OpenTelemetryRum] initialization.
*
* @param context Your android app's application context. This should be from your Application
* subclass or an appropriate context that allows retrieving the application context. If you
* supply an inappropriate context (e.g. from attachBaseContext) then instrumentation relying
* on activity lifecycle callbacks will not function correctly.
* @param configuration Type-safe config DSL that controls how OpenTelemetry
* should behave.
*/
@JvmStatic
fun initialize(
context: Context,
Expand All @@ -42,18 +40,13 @@ object OpenTelemetryRumInitializer {
val cfg = OpenTelemetryConfiguration()
configuration(cfg)

// ensure we're using the Application Context to prevent potential leaks.
// if context.applicationContext is null (e.g. called from within attachBaseContext),
// fallback to the supplied context.
val ctx =
when (context) {
is Application -> context
else -> context.applicationContext ?: context
}

val spansEndpoint = cfg.exportConfig.spansEndpoint()
val logsEndpoints = cfg.exportConfig.logsEndpoint()
val metricsEndpoint = cfg.exportConfig.metricsEndpoint()
val exportEndpoints = resolveExportEndpoints(cfg)

val resourceBuilder = AndroidResource.createDefault(ctx).toBuilder()
cfg.resourceAction(resourceBuilder)
Expand All @@ -65,28 +58,119 @@ object OpenTelemetryRumInitializer {
.setResource(resource)
.setClock(cfg.clock)
.addSpanExporterCustomizer {
createSpanExporter(exportEndpoints.spans, exportEndpoints.protocol)
}.addLogRecordExporterCustomizer {
createLogRecordExporter(exportEndpoints.logs, exportEndpoints.protocol)
}.addMetricExporterCustomizer {
createMetricExporter(exportEndpoints.metrics, exportEndpoints.protocol)
}.build()
}

private data class ExportEndpoints(
val spans: EndpointConnectivity,
val logs: EndpointConnectivity,
val metrics: EndpointConnectivity,
val protocol: ExportProtocol,
)

private fun resolveExportEndpoints(cfg: OpenTelemetryConfiguration): ExportEndpoints {
cfg.unifiedExportConfig?.let { unified ->
return ExportEndpoints(
spans = unified.spansEndpoint(),
logs = unified.logsEndpoint(),
metrics = unified.metricsEndpoint(),
protocol = unified.protocol,
)
}

cfg.grpcExportConfig?.let { grpc ->
return ExportEndpoints(
spans = grpc.spansEndpoint(),
logs = grpc.logsEndpoint(),
metrics = grpc.metricsEndpoint(),
protocol = ExportProtocol.GRPC,
)
}

return ExportEndpoints(
spans = cfg.exportConfig.spansEndpoint(),
logs = cfg.exportConfig.logsEndpoint(),
metrics = cfg.exportConfig.metricsEndpoint(),
protocol = ExportProtocol.HTTP,
)
}

private fun createSpanExporter(
endpoint: EndpointConnectivity,
protocol: ExportProtocol,
): SpanExporter =
when (protocol) {
ExportProtocol.HTTP -> {
OtlpHttpSpanExporter
.builder()
.setEndpoint(spansEndpoint.getUrl())
.setHeaders(spansEndpoint::getHeaders)
.setCompression(spansEndpoint.getCompression().getUpstreamName())
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}.addLogRecordExporterCustomizer {
}

ExportProtocol.GRPC -> {
OtlpGrpcSpanExporter
.builder()
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}
}

private fun createLogRecordExporter(
endpoint: EndpointConnectivity,
protocol: ExportProtocol,
): LogRecordExporter =
when (protocol) {
ExportProtocol.HTTP -> {
OtlpHttpLogRecordExporter
.builder()
.setEndpoint(logsEndpoints.getUrl())
.setHeaders(logsEndpoints::getHeaders)
.setCompression(logsEndpoints.getCompression().getUpstreamName())
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}.addMetricExporterCustomizer {
}

ExportProtocol.GRPC -> {
OtlpGrpcLogRecordExporter
.builder()
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}
}

private fun createMetricExporter(
endpoint: EndpointConnectivity,
protocol: ExportProtocol,
): MetricExporter =
when (protocol) {
ExportProtocol.HTTP -> {
OtlpHttpMetricExporter
.builder()
.setEndpoint(metricsEndpoint.getUrl())
.setHeaders(metricsEndpoint::getHeaders)
.setCompression(metricsEndpoint.getCompression().getUpstreamName())
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}.build()
}
}

ExportProtocol.GRPC -> {
OtlpGrpcMetricExporter
.builder()
.setEndpoint(endpoint.getUrl())
.setHeaders(endpoint::getHeaders)
.setCompression(endpoint.getCompression().getUpstreamName())
.build()
}
}

private fun Compression.getUpstreamName(): String =
when (this) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.connectivity

enum class ExportProtocol {
HTTP,
GRPC,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.android.agent.connectivity

internal class GrpcEndpointConnectivity private constructor(
private val endpoint: String,
private val headers: Map<String, String>,
private val compression: Compression,
) : EndpointConnectivity {
companion object {
fun create(
endpoint: String,
headers: Map<String, String>,
compression: Compression,
): GrpcEndpointConnectivity = GrpcEndpointConnectivity(endpoint, headers, compression)
}

override fun getUrl(): String = endpoint

override fun getHeaders(): Map<String, String> = headers

override fun getCompression(): Compression = compression
}
Loading
Loading