Skip to content

honeycombio/honeycomb-opentelemetry-android

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Honeycomb OpenTelemetry Android

OSS Lifecycle CircleCI

Honeycomb wrapper for OpenTelemetry on Android.

STATUS: this library is EXPERIMENTAL. Data shapes are unstable and not safe for production. We are actively seeking feedback to ensure usability.

Getting started

Add the following dependencies to your build.gradle.kts:

dependencies {
  implementation("io.honeycomb.android:honeycomb-opentelemetry-android:0.0.4-alpha")
}

To configure the SDK in your Application class:

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")
            .build()

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

To manually send a span:

    val app = application as ExampleApp
    val otelRum = app.otelRum
    val otel = otelRum?.openTelemetryA

    val tracer = otel?.getTracer("YOUR-INSTRUMENTATION-NAME")
    val span = tracer?.spanBuilder("YOUR-SPAN-NAME")?.startSpan()

    span?.end()

Configuration Options

Option Type Required? Description
apiKey String Yes Default Honeycomb API Key to use to send data directly to Honeycomb.
tracesApiKey String No Dedicated API Key to use when sending traces.
metricsApiKey String No Dedicated API Key to use when sending metrics.
logsApiKey String No Dedicated API Key to use when sending logs.
dataset String No Name of Honeycomb dataset to send traces to. Required if sending to a classic Honeycomb environment.
metricsDataset String No Name of Honeycomb dataset to send metrics to, instead of dataset.
apiEndpoint String No API endpoint to send data to.
tracesEndpoint String No API endpoint to send traces to. Overrides apiEndpoint for trace data.
metricsEndpoint String No API endpoint to send metrics to. Overrides apiEndpoint for metrics data.
logsEndpoint String No API endpoint to send trace to. Overrides apiEndpoint for logs data.
sampleRate Int No Sample rate to apply (ie. a value of 40 means 1 in 40 traces will be exported).
debug Boolean No Enable debug logging.
serviceName String? No Name of Honeycomb service to send data to.
resourceAttributes Map<String, String> No Attributes to attach to outgoing resources.
headers Map<String, String> No Headers to include on exported data.
tracesHeaders Map<String, String> No Headers to add to exported trace data.
metricsHeaders Map<String, String> No Headers to add to exported metrics data.
logsHeaders Map<String, String> No Headers to add to exported logs data.
timeout Duration No Timeout used by exporter when sending data.
tracesTimeout Duration No Timeout used by traces exporter. Overrides timeout for trace data.
metricsTimeout Duration No Timeout used by metrics exporter. Overrides timeout for metrics data.
logsTimeout Duration No Timeout used by logs exporter. Overrides timeout for logs data.
protocol io.honeycomb.opentelemetry.android.OtlpProtocol No Protocol to use when sending data.
tracesProtocol io.honeycomb.opentelemetry.android.OtlpProtocol No Overrides protocol for trace data.
metricsProtocol io.honeycomb.opentelemetry.android.OtlpProtocol No Overrides protocol for metrics data.
logsProtocol io.honeycomb.opentelemetry.android.OtlpProtocol No Overrides protocol for logs data.

Auto-instrumentation

The following auto-instrumentation libraries are automatically included:

The following additional auto-instrumentation is implemented in this library:

  • UI interaction in XML-based Activities.

Activity Lifecycle Instrumentation

A trace is emitted before, during, and after each stage of the Android Activity Lifecycle.

Trace Types

  • AppStart
    • name: AppStart
    • attributes:
      • start.type: "hot" or "cold"
  • Created
    • name: Created
    • events:
      • activityPreCreated, activityCreated, activityPostCreated
      • activityPreStarted, activityStarted, activityPostStarted
      • activityPreResumed, activityResumed, activityPostResumed
  • Paused
    • name: Paused
    • events:
      • activityPrePaused, activityPaused, activityPostPaused
  • Stopped
    • name: Stopped
    • events:
      • activityPreStopped, activityStopped, activityPostStopped
  • Destroyed
    • name: Destroyed
    • events:
      • activityPreDestroyed, activityDestroyed, activityPostDestroyed

Common Attributes:

  • activityName - The unqualified name for the activity, such as "MainActivity"

ANR (Application Not Responding) Instrumentation

A trace is emitted whenever the app becomes unresponsive for longer than approximately 5 seconds (ANR).

  • name: ANR
  • attributes:
    • exception.stacktrace

Crash Instrumentation

A trace is emitted whenever an uncaught exception is going to terminate the program. This is in addition to whatever other crash reporting is enabled. These traces are flushed as the app is shutting down, so the app does not need to be re-opened for them to be sent.

  • name: UncaughtException
  • attributes:
    • exception.name
    • exception.message
    • exception.stacktrace
    • exception.escaped
    • thread.name
    • thread.id

Slow Rendering Instrumentation

A trace is emitted whenever a frame is rendered too slowly, according to Android's Slow rendering guidelines.

  • name: slowRenders (>16ms) or frozenRenders (>700ms)
  • attributes:
    • activity.name - the fully-qualified name of the activity, such as "io.honeycomb.opentelemetry.android.example/.MainActivity"

Network Instrumentation

Network instrumentation is not included by default but can be configured on top of this distro. We test with the following OpenTelemetry instrumentation packages:

Configuration of each of these packages is described in their respective READMEs.

UI Interaction Instrumentation

Various touch events are instrumented for TextView fields, such as:

  • Touch Began - A touch started
  • Touch Ended - A touch ended
  • click - A "tap"

These events may have the following attributes.

  • view.class - e.g. "android.widget.Button"
  • view.accessibilityClassName - The accessibilityClassName for the view. Usually the same as view.class.
  • view.text - The text of the TextView.
  • view.id - The XML ID of the view element, as an integer.
  • view.id.entry - The text form of the XML ID of the view element.
  • view.id.package - The package for the XML ID of the view.
  • view.name - The "best" available name of the view, given the other identifiers. Usually the same as view.id.entry.

Manual Instrumentation

Context Propagation

In most cases, OpenTelemetry context will be propagated correctly across function calls, etc. By default, OpenTelemetry context is stored in a java.lang.ThreadLocal. However, Kotlin Coroutines may operate across multiple threads, and therefore do not automatically inherit the correct OpenTelemetry context.

Instead, context must be propagated manually, via the OpenTelemetry Kotlin Extensions.

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

Once these are installed, replace any launch calls with

launch(Span.current().asContextElement()) {

}

Android Compose

Setup

Android Compose instrumentation is included in a standalone library. Add the following to your dependencies in build.gradle.kts:

dependencies {
  implementation("io.honeycomb.android:honeycomb-opentelemetry-android-compose:0.0.3-alpha")
}

After you initialize the Honeycomb sdk, wrap your entire app in a CompositionLocalProvider that provides LocalOpenTelemetryRum, as so:

import io.honeycomb.opentelemetry.android.compose.LocalOpenTelemetryRum

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val app = application as ExampleApp
        val otelRum = app.otelRum

        setContent {
            CompositionLocalProvider(LocalOpenTelemetryRum provides otelRum) {
                // app content
            }
        }
    }
}

Usage

Wrap your Composables with HoneycombInstrumentedComposable(name: String), like so:

@Composable
private fun MyComposable() {
    HoneycombInstrumentedComposable("main view") {
        // ...
    }
}

This will measure and emit instrumentation for your Composable's render times, ex:

Specifically, it will emit 2 kinds of span for each composable that is wrapped:

View Render spans encompass the entire rendering process, from initialization to appearing on screen. They include the following attributes:

  • view.name (string): the name passed to HoneycombInstrumentedComposable
  • view.renderDuration (double): amount of time in seconds to spent initializing the contents of HoneycombInstrumentedComposable
  • view.totalDuration (double): amount of time in seconds from when the contents of HoneycombInstrumentedComposable start initializing to when the contents appear on screen

View Body spans encompass just the contents of the HoneycombInstrumentedView, and include the following attributes:

  • view.name (string): the name passed to HoneycombInstrumentedComposable

About

Honeycomb's OpenTelemetry Android SDK distribution

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Packages

No packages published

Languages