> ## Documentation Index
> Fetch the complete documentation index at: https://docs.honeycomb.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Send Android Data to Honeycomb

> Instrument your Android application with the Honeycomb OpenTelemetry Android SDK and send telemetry to Honeycomb to monitor real device performance.

The [Honeycomb OpenTelemetry Android SDK](https://github.com/honeycombio/honeycomb-opentelemetry-android) is Honeycomb's [OpenTelemetry Android](https://github.com/open-telemetry/opentelemetry-android) distribution.
It simplifies adding instrumentation to your Android applications and sending telemetry to Honeycomb.

This page briefly covers usage of the SDK.
If you just want to see some code, check out the [examples on GitHub](https://github.com/honeycombio/honeycomb-opentelemetry-android/tree/main/example).

## Before You Begin

Before you can add instrumentation to your Android application, you will need to do a few things.

### Get Your Honeycomb API Key

To send data to Honeycomb, you need to:

1. Sign up for a Honeycomb account.
   To sign up, decide whether you would like Honeycomb to store your data in a US-based or EU-based location, then [create a Honeycomb account in the US](https://ui.honeycomb.io/signup) or [create a Honeycomb account in the EU](https://ui.eu1.honeycomb.io/signup).

2. [Create a Honeycomb Ingest API Key](/configure/environments/manage-api-keys/#create-api-key).
   To get started, you can create a key that you expect to swap out when you deploy to production.
   Name it something helpful, perhaps noting that it's a Getting Started key.
   Make note of your API key; for security reasons, you will not be able to see the key again, and you will need it later!

<Tip>
  For setup, make sure you select the "Can create datasets" checkbox so that your data will show up in Honeycomb.
  Later, when you replace this key with a permanent one, you can uncheck that box.
</Tip>

### Install the Honeycomb Android SDK

Add the Honeycomb and OpenTelemetry Android SDKs to your application's `build.gradle.kts`.
When adding OpenTelemetry dependencies, make sure [the library is compatible with the Honeycomb Android SDK](https://github.com/honeycombio/honeycomb-opentelemetry-android/?tab=readme-ov-file#honeycomb-opentelemetry-android).

```kotlin theme={}
dependencies {
    implementation("io.opentelemetry.android:android-agent:0.11.0-alpha")
    implementation("io.honeycomb.android:honeycomb-opentelemetry-android:0.0.20")
}
```

If your application's `minSDK` is lower than 26, enable [corelib desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring):

```kotlin theme={}
android {
    // ...
    compileOptions {
        isCoreLibraryDesugaringEnabled = true
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}


dependencies {
    coreLibraryDesugaring(libs.desugar.jdk.libs)
}
```

If your application's `minSdk` is lower than 24, running instrumentation tests or debug application builds requires that you:

* Use [Android Gradle Plugin (AGP) 8.3.0+](https://developer.android.com/build/releases/gradle-plugin#updating-plugin)
* Add `android.useFullClasspathForDexingTransform=true` to your `gradle.properties`.

## Configuration

| Option                | Description                                                                                                                                                                                                                                                                                                                                                         |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| apiKey                | `String`<br />Your [Honeycomb Ingest API Key](/configure/environments/manage-api-keys/#create-api-key).<br />**Required** if sending telemetry directly to Honeycomb.                                                                                                                                                                                               |
| tracesApiKey          | `String`<br />Ingest API Key to use when sending traces. Overrides `apiKey` for traces.                                                                                                                                                                                                                                                                             |
| metricsApiKey         | `String`<br />Ingest API Key to use when sending metrics. Overrides `apiKey` for metrics.                                                                                                                                                                                                                                                                           |
| logsApiKey            | `String`<br />Ingest API Key to use when sending logs. Overrides `apiKey` for logs.                                                                                                                                                                                                                                                                                 |
| dataset               | `String`<br />Name of the [dataset](/configure/datasets/manage/) to send telemetry data to. <br />**Required** if using Honeycomb Classic.                                                                                                                                                                                                                          |
| metricsDataset        | `String`<br />Name of the dataset to send metrics to. Overrides `dataset` for metrics.                                                                                                                                                                                                                                                                              |
| apiEndpoint           | `String`<br />Telemetry is sent to this URL. For Honeycomb EU instances, set this to `https://api.eu1.honeycomb.io:443`. If you're using an OpenTelemetry Collector, provide your collector URL instead.<br />Default: `https://api.honeycomb.io:443` (US instance)                                                                                                 |
| tracesEndpoint        | `String`<br />API endpoint to send traces to.                                                                                                                                                                                                                                                                                                                       |
| metricsEndpoint       | `String`<br />API endpoint to send metrics to.                                                                                                                                                                                                                                                                                                                      |
| logsEndpoint          | `String`<br />API endpoint to send logs to.                                                                                                                                                                                                                                                                                                                         |
| spanProcessor         | `io.opentelemetry.sdk.trace.SpanProcessor`<br />Additional span processor to use.                                                                                                                                                                                                                                                                                   |
| sampleRate            | `Int`<br />Sample rate to apply. For example, a `sampleRate` of `40` means 1 in 40 traces will be exported.<br />Default: `1`                                                                                                                                                                                                                                       |
| debug                 | `Boolean`<br />Whether to enable debug logging.<br />Default: `false`.                                                                                                                                                                                                                                                                                              |
| serviceName           | `String`<br />The name of your application. Used as the value for `service.name` resource attribute. <br />Default: `"unknown_service"`                                                                                                                                                                                                                             |
| serviceVersion        | `String`<br />Current version of your application. Used as the value for `service.version` resource attribute.                                                                                                                                                                                                                                                      |
| resourceAttributes    | `Map<String, String>`<br />Attributes to attach to outgoing resources.                                                                                                                                                                                                                                                                                              |
| headers               | `Map<String, String>`<br />Headers to add to exported telemetry data.                                                                                                                                                                                                                                                                                               |
| tracesHeaders         | `Map<String, String>`<br />Headers to add to exported trace data.                                                                                                                                                                                                                                                                                                   |
| metricsHeaders        | `Map<String, String>`<br />Headers to add to exported metrics data.                                                                                                                                                                                                                                                                                                 |
| logsHeaders           | `Map<String, String>`<br />Headers to add to exported logs data.                                                                                                                                                                                                                                                                                                    |
| timeout               | `Duration`<br />Timeout used by exporter when sending data.<br />Default: `Duration = 10.seconds`                                                                                                                                                                                                                                                                   |
| tracesTimeout         | `Duration`<br />Timeout used by traces exporter. Overrides `timeout` for trace data.                                                                                                                                                                                                                                                                                |
| metricsTimeout        | `Duration`<br />Timeout used by metrics exporter. Overrides `timeout` for metrics data.                                                                                                                                                                                                                                                                             |
| logsTimeout           | `Duration`<br />Timeout used by logs exporter. Overrides `timeout` for logs data.                                                                                                                                                                                                                                                                                   |
| protocol              | `OtlpProtocol`<br />Protocol to use when sending data.<br />Can be one of: `OtlpProtocol.GRPC`, `OtlpProtocol.HTTP_PROTOBUF`, `OtlpProtocol.HTTP_JSON`.<br />Default: `OtlpProtocol.HTTP_PROTOBUF`                                                                                                                                                                  |
| tracesProtocol        | `OtlpProtocol`<br />Overrides `protocol` for trace data.                                                                                                                                                                                                                                                                                                            |
| metricsProtocol       | `OtlpProtocol`<br />Overrides `protocol` for metrics data.                                                                                                                                                                                                                                                                                                          |
| logsProtocol          | `OtlpProtocol`<br />Overrides `protocol` for logs data.                                                                                                                                                                                                                                                                                                             |
| offlineCachingEnabled | `Boolean`<br />Enable offline caching for telemetry. When offline caching is enabled, telemetry is cached during network failures. The SDK will retry exporting telemetry for up to 18 hours. Offline caching also adds a minimum delay of 30 seconds to telemetry exports.<br />**Offline caching is an alpha feature and may be unstable.**<br />Default: `false` |

### Sending to OpenTelemetry Collector

In production, we recommend running an [OpenTelemetry Collector](/send-data/opentelemetry/collector/).
Your application sends telemetry to your Collector instead of directly to Honeycomb.
Your Collector then forwards the telemetry data to Honeycomb, keeping your API key stored securely in the Collector's configuration.

Call `setApiEndpoint()` with your Collector's URL when initializing the SDK:

```kotlin theme={}
import io.honeycomb.opentelemetry.android.Honeycomb
import io.honeycomb.opentelemetry.android.HoneycombOptions
import io.opentelemetry.android.OpenTelemetryRum

class ExampleApp: Application() {
    var otelRum: OpenTelemetryRum? = null

    override fun onCreate() {
        super.onCreate()

        val options = HoneycombOptions.builder(this)
            .setApiEndpoint("http(s)://YOUR-COLLECTOR-URL")
            .setServiceName("YOUR-SERVICE-NAME")
            .setServiceVersion("0.0.1")
            .build()

        otelRum = Honeycomb.configure(this, options)
    }
}
```

### Sending to Honeycomb

To send telemetry data directly to Honeycomb, call `setApiKey()` with your [Ingest API Key](/configure/environments/manage-api-keys/#create-api-key) value.

```kotlin theme={}
import io.honeycomb.opentelemetry.android.Honeycomb
import io.honeycomb.opentelemetry.android.HoneycombOptions
import io.opentelemetry.android.OpenTelemetryRum

class ExampleApp: Application() {
    var otelRum: OpenTelemetryRum? = null

    override fun onCreate() {
        super.onCreate()

        val options = HoneycombOptions.builder(this)
            // Uncomment the line below to send to EU instance. Defaults to US.
            // .setApiEndpoint("https://api.eu1.honeycomb.io:443")
            .setApiKey("YOUR-API-KEY")
            .setServiceName("YOUR-SERVICE-NAME")
            .setServiceVersion("0.0.1")
            .build()

        otelRum = Honeycomb.configure(this, options)
    }
}
```

### Add Resource Attributes

Resource attributes are available on every span your instrumentation emits.
Adding custom, application-specific attributes makes it easier to correlate your data to important business information.

You can add extra resource attributes during SDK configuration with the `.setResourceAttributes()` method.

```kotlin theme={}
import android.app.Application
import io.honeycomb.opentelemetry.android.Honeycomb
import io.honeycomb.opentelemetry.android.HoneycombOptions
import io.opentelemetry.android.OpenTelemetryRum

class ExampleApp: Application() {
    var otelRum: OpenTelemetryRum? = null

    override fun onCreate() {
        super.onCreate()

        val options = HoneycombOptions.builder(this)
            .setApiKey("YOUR-API-KEY")
            .setServiceName("YOUR-SERVICE-NAME")
            .setServiceVersion("0.0.1")
            .setResourceAttributes(mapOf("app.ab_test" to "test c"))
            .setDebug(true)
            .build()

        otelRum = Honeycomb.configure(this, options)
    }
}
```

### Enable Sampling

The Honeycomb Android SDK includes optional [deterministic head sampling](/manage-data-volume/sample/).
To enable sampling, call `.setSampleRate()` with your desired sample rate as an `Int` value.
The sample rate is `1` by default, meaning every trace is exported.

The example below sets a `sampleRate` of `40`, meaning 1 in 40 traces will be exported.

```kotlin theme={}
// ...
val options = HoneycombOptions.Builder(this)
        .setApiKey("YOUR-API-KEY")
        .setServiceName("YOUR-SERVICE-NAME")
        .setServiceVersion("0.0.1")
        .setSampleRate(40)
        .setDebug(true)
        .build()
// ...
```

## Add Automatic Instrumentation

Enable all OpenTelemetry auto-instrumentations by including the OpenTelemetry [android-agent](https://github.com/open-telemetry/opentelemetry-android):

```kotlin theme={}
dependencies {
    implementation("io.opentelemetry.android:android-agent:0.11.0-alpha")
    implementation("io.honeycomb.android:honeycomb-opentelemetry-android:0.0.20")
}
```

If you don't need all of them, you can instead add dependencies for each instrumentation you want to include:

* [Activity navigation](https://github.com/open-telemetry/opentelemetry-android/tree/main/instrumentation/activity): `io.opentelemetry.android:instrumentation-activity`
* [Application Not Responding (ANR)](https://github.com/open-telemetry/opentelemetry-android/tree/main/instrumentation/anr): `io.opentelemetry.android:instrumentation-anr`
* [Crash (uncaught exception)](https://github.com/open-telemetry/opentelemetry-android/tree/main/instrumentation/crash): `io.opentelemetry.android:instrumentation-crash`
* [Fragment navigation](https://github.com/open-telemetry/opentelemetry-android/tree/main/instrumentation/fragment): `io.opentelemetry.android:instrumentation-fragment`
* [Slow Rendering](https://github.com/open-telemetry/opentelemetry-android/tree/main/instrumentation/slowrendering): `io.opentelemetry.android:instrumentation-slowrendering`
* [UI interactions](https://github.com/honeycombio/honeycomb-opentelemetry-android/tree/main/interaction): `io.honeycomb.android:honeycomb-opentelemetry-android-interaction`

## Custom Instrumentation

Automatic instrumentation is a fast way to instrument your code, but you get more insight into your application by adding custom, or manual, instrumentation.

To add your own custom instrumentation, import the OpenTelemetry API in to your application.

```kotlin theme={}
import io.opentelemetry.api.OpenTelemetry
```

### Add Attributes to an Active Span

You can retrieve the currently active span in a trace and add attributes to it.
This lets you add more context to traces and gives you more ways to group or filter traces in your queries:

```kotlin theme={}
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.common.Attributes

fun applyDiscountCode(discountCode: String) {
  val currentSpan = Span.current()

  currentSpan.setAttribute("app.cart.discount_code", discountCode)
}
```

In the above example, we add an `app.cart.discount_code` attribute to the current span.
This lets us use the `app.cart.discount_code` field in `WHERE` or `GROUP BY` clauses in the Honeycomb query builder.

### Acquire a Tracer

To create custom spans, you need to acquire a tracer:

```kotlin theme={}
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.android.OpenTelemetryRum

// ...

val otelRum = app.otelRum as OpenTelemetryRum
val tracer = otelRum.tracerProvider.tracerBuilder("my-application-tracer").build()
```

### Create Spans

Create custom spans to get a clear view of the critical parts in your application.

```kotlin theme={}
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.android.OpenTelemetryRum

// ...

val otelRum = app.otelRum as OpenTelemetryRum
val tracer = otelRum.tracerProvider.tracerBuilder("my-application-tracer").build()

fun generateNewLevel() {
  val span = tracer.spanBuilder("newLevel").startSpan()
  // do some work
  span.end()
}
```

## Custom Span Processing

Span processors provide hooks for when a span starts and when it ends.
This lets you mutate spans after they have been created by automatic or manual instrumentation.

Here's a basic example of a span processor that adds an attribute to spans when they start:

```kotlin theme={}
import io.opentelemetry.context.Context
import io.opentelemetry.sdk.trace.ReadWriteSpan
import io.opentelemetry.sdk.trace.ReadableSpan
import io.opentelemetry.sdk.trace.SpanProcessor

class BasicSpanProcessor : SpanProcessor {
    override fun onStart(
        parentContext: Context,
        span: ReadWriteSpan,
    ) {
        span.setAttribute("app.metadata", "extra metadata")
    }

    override fun isStartRequired(): Boolean {
        return true
    }

    override fun onEnd(span: ReadableSpan) {}

    override fun isEndRequired(): Boolean {
        return false
    }
}
```

Add the span processor as part of your SDK configuration to use it:

```kotlin theme={}
// ...
val options = HoneycombOptions.builder(this)
    .setApiKey("YOUR-API-KEY")
    .setServiceName("YOUR-SERVICE-NAME")
    .setSpanProcessor(BasicSpanProcessor())
    .setServiceVersion("0.0.1")
    .setDebug(true)
    .build()
// ...
```

## Manual Context Propagation

Kotlin Coroutines may operate across multiple threads, and do not automatically inherit the correct OpenTelemetry context.

Instead, context must be propagated manually with the [OpenTelemetry Kotlin Extensions](https://github.com/open-telemetry/opentelemetry-java/tree/main/extensions/kotlin).

```kotlin theme={}
dependencies {
  implementation("io.opentelemetry:opentelemetry-extension-kotlin:1.47.0")
}
```

Once these are installed, replace any `launch` calls with

```kotlin theme={}
launch(Span.current().asContextElement()) {
  // ...
}
```

## Troubleshooting

To explore common issues when sending data, visit [Common Issues with Sending Data in Honeycomb](/troubleshoot/common-issues/sending-data/#opentelemetry-sdks-and-honeycomb-distributions).
