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.
Add the following dependencies to your build.gradle.kts
:
dependencies {
implementation("io.honeycomb.android:honeycomb-opentelemetry-android:0.0.1-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()
The following auto-instrumentation libraries are automatically included:
io.opentelemetry.android:android-agent
io.opentelemetry.android:instrumentation-activity
io.opentelemetry.android:instrumentation-anr
io.opentelemetry.android:instrumentation-crash
io.opentelemetry.android:instrumentation-slowrendering
The following additional auto-instrumentation is implemented in this library:
- UI interaction in XML-based Activities.
A trace is emitted before, during, and after each stage of the Android Activity Lifecycle.
- AppStart
- name:
AppStart
- attributes:
start.type
:"hot"
or"cold"
- name:
- Created
- name:
Created
- events:
activityPreCreated
,activityCreated
,activityPostCreated
activityPreStarted
,activityStarted
,activityPostStarted
activityPreResumed
,activityResumed
,activityPostResumed
- name:
- Paused
- name:
Paused
- events:
activityPrePaused
,activityPaused
,activityPostPaused
- name:
- Stopped
- name:
Stopped
- events:
activityPreStopped
,activityStopped
,activityPostStopped
- name:
- Destroyed
- name:
Destroyed
- events:
activityPreDestroyed
,activityDestroyed
,activityPostDestroyed
- name:
activityName
- The unqualified name for the activity, such as"MainActivity"
A trace is emitted whenever the app becomes unresponsive for longer than approximately 5 seconds (ANR).
- name:
ANR
- attributes:
exception.stacktrace
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
A trace is emitted whenever a frame is rendered too slowly, according to Android's Slow rendering guidelines.
- name:
slowRenders
(>16ms) orfrozenRenders
(>700ms) - attributes:
activity.name
- the fully-qualified name of the activity, such as"io.honeycomb.opentelemetry.android.example/.MainActivity"
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.
Various touch events are instrumented for TextView
fields, such as:
Touch Began
- A touch startedTouch Ended
- A touch endedclick
- A "tap"
These events may have the following attributes.
view.class
- e.g."android.widget.Button"
view.accessibilityClassName
- TheaccessibilityClassName
for the view. Usually the same asview.class
.view.text
- The text of theTextView
.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 asview.id.entry
.
Initialize the Honeycomb
sdk, and then wrap your entire app in a CompositionLocalProvider
that provides LocalOpenTelemetryRum
, as so:
import io.honeycomb.opentelemetry.android.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
}
}
}
}
Wrap your SwiftUI views 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 toHoneycombInstrumentedComposable
view.renderDuration
(double): amount of time in seconds to spent initializing the contents ofHoneycombInstrumentedComposable
view.totalDuration
(double): amount of time in seconds from when the contents ofHoneycombInstrumentedComposable
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 toHoneycombInstrumentedComposable