This LaunchDarkly observability plugin is available for early accessThis LaunchDarkly observability plugin is currently available in Early Access, and APIs are subject to change until a 1.x version is released.
SDK quick linksLaunchDarkly SDKs are open source. In addition to this reference guide, we provide source, API reference documentation, and a sample application:
| Resource | Location |
|---|---|
| SDK API documentation | Observability plugin API docs |
| GitHub repository | @launchdarkly/observability-android |
| Published module | Maven |
Prerequisites and dependencies
This reference guide assumes that you are somewhat familiar with the LaunchDarkly Android SDK. The observability plugin is compatible with the Android SDK, version 5.9.0 and later. The LaunchDarkly Android SDK is compatible with Android SDK versions 21 and higher (Android 5.0, Lollipop).Get started
Follow these steps to get started:- Install the plugin
- Initialize the Android SDK client
- Configure the plugin options
- Configure additional instrumentations
- Configure product analytics event collection
- Track screen views
- Configure session replay
- Explore supported features
- Review observability data in LaunchDarkly
Install the plugin
LaunchDarkly uses a plugin to the Android SDK to provide observability. The first step is to make both the SDK and the observability plugin available as dependencies. Here’s how:Initialize the client
Next, initialize the SDK and the plugin. To initialize, you need your LaunchDarkly environment’s mobile key and the context for which you want to evaluate flags. This authorizes your application to connect to a particular environment within LaunchDarkly. To learn more, read Initialize the client in the Android SDK reference guide. Here’s how to initialize the SDK and plugin:Configure the plugin options
You can configure options for the observability plugin when you initialize the SDK. The plugin constructor takes an optional object with the configuration details. Here is an example:Advanced configuration options
You can customize the observability plugin with additional options:ObservabilityOptions configuration options are:
- logsApiLevel: Minimum log severity to export. Defaults to
INFO. Set toObservabilityOptions.LogLevel.NONEto disable log exporting. - tracesApi: Controls trace recording. Defaults to enabled. Use
ObservabilityOptions.TracesApi.disabled()to disable all tracing, or setincludeErrors/includeSpansindividually. - metricsApi: Controls metric export. Defaults to enabled. Use
ObservabilityOptions.MetricsApi.disabled()to disable metrics. - instrumentations: Enables or disables specific automatic instrumentations:
crashReporting: Iftrue, automatically reports uncaught exceptions as errors. Defaults totrue.launchTime: Iftrue, automatically measures and reports application startup time as metrics. Defaults tofalse.userTaps: Iftrue, runs tap detection. Theanalytics.tapsoption separately controls whether the plugin publishes detected taps asclickspans. IfuserTapsisfalse, the plugin publishes noclickspans regardless of theanalytics.tapsvalue. Neither option affects session replay capture. Defaults totrue.screens: Iftrue, automatically detects screen changes from AndroidActivitylifecycle callbacks. Screen detection drives both the automaticscreen_viewspan and the session replayNavigateevents. Defaults totrue. Theanalytics.screenViewsoption gatesscreen_viewspans.
- sessionBackgroundTimeout: How long the app can stay in the background before the current session ends. In Kotlin, this is a
kotlin.time.Duration, such as30.minutes. In Java, use thesessionBackgroundTimeoutMillis(long)builder method instead. Defaults to 15 minutes. - serviceName: The service name for the application. Defaults to “observability-android”.
- serviceVersion: The version of the service. Defaults to the SDK version.
- debug: Enables verbose internal logging and debug functionality. Defaults to
false. - resourceAttributes: Additional resource attributes to include in telemetry data.
- customHeaders: Custom headers to include with OTLP exports.
Configure additional instrumentations
To enable HTTP request instrumentation and user interaction instrumentation, add the following plugin and dependencies to your top level application’s Gradle file.Configure product analytics event collection
The Android observability plugin can record the following product analytics events as OpenTelemetry spans:- Taps (automatic): A
clickspan for each user tap, with details about the tapped element and screen location. Enabled by default. - Track events (automatic): A
trackspan when your code callstrack(). Enabled by default. To learn more, read Recording product analytics events. - Screen views (automatic and manual): A
screen_viewspan when the app shows a screen, either detected automatically or recorded manually when your code callstrackScreenView(). To learn more, read Recording product analytics events. - App lifecycle (automatic): An
app_foregroundorapp_backgroundspan as the app moves between the foreground and background states. Enabled by default. - App launches (automatic): An
app_launchspan once per process launch, with the launch type and version information, plus anapp.startspan event that records the cold or warm startup dimension. Enabled by default. To learn more, read App launch events.
ObservabilityOptions.Analytics object to the analytics parameter:
ObservabilityOptions.Analytics options are:
- taps: Emits a
clickspan for each detected tap. Defaults totrue. - trackEvents: Emits a
trackspan when a custom event is tracked withtrack(). Defaults totrue. - screenViews: Emits a
screen_viewspan when the app displays a screen. Defaults totrue. - appLifecycle: Emits
app_foregroundandapp_backgroundspans as the app moves between states. Defaults totrue. - appLaunch: Emits an
app_launchspan once per process launch. Defaults totrue.
Track screen views
The plugin emits ascreen_view span each time your app shows a screen. Each screen_view span uses the event.* attribute namespace, and includes the event.previous_screen attribute from a shared navigation stack. The span broadcasts a session replay Navigate event to reflect navigation in the replay timeline.
Capture activities automatically
Wheninstrumentations.screens is true (the default), the plugin captures every Android Activity as it resumes. It derives the screen name from the class name. For example, ProfileActivity becomes Profile. The plugin populates the event.screen_class and event.screen_id attributes from the Activity class.
To customize the reported name or category, implement LDScreenNameProvider on your Activity:
Capture fragments and compose destinations manually
The plugin does not automatically capture screens that lack a distinctActivity, such as Fragments and Jetpack Compose destinations. Record these kinds of screens with LDObserve.trackScreenView. To learn more, read Recording product analytics events.
Only one call per appearance is required. The plugin resolves event.previous_screen through the shared navigation stack, which handles both re-appearance and back navigation.
About detection and span emission
Two separate options control screen views:instrumentations.screenscontrols automatic screen detection. It drives both the automaticscreen_viewspan and the session replayNavigateevent.analytics.screenViewsonly gates thescreen_viewspan. Detection and theNavigateevent are independent of this option, and manualtrackScreenViewcalls still work if you disableinstrumentations.screens.
Configure session replay
The Android SDK supports session replay, which captures snapshots of your app’s UI at regular intervals. This helps you review user sessions in LaunchDarkly to better understand user behavior and diagnose issues. To enable session replay, add theSessionReplay plugin to the plugins list after the Observability plugin. Session replay depends on the Observability plugin being present and initialized first.
Here’s how:
SessionReplaydepends onObservability. If Observability is missing or listed after SessionReplay, the plugin logs an error and stays inactive.- Observability runs fine without SessionReplay. Adding SessionReplay extends the Observability pipeline to include session recording.
Initialize the plugins after the SDK client
You can initialize the session replay plugin manually, after the SDK client is initialized. This approach supports feature-flagged rollouts or dynamic initialization after end user consent. Setenabled to false in ReplayOptions, then call LDReplay.start() when you’re ready to begin recording.
First, configure the plugin with enabled = false:
- Feature-flag the rollout of session replay to a subset of end users
- Wait for end user consent before starting data collection
- Dynamically enable session replay based on runtime conditions
- Maintain compliance with privacy regulations
Session replay configuration options
You can customize session replay behavior by passing aReplayOptions object to the SessionReplay constructor:
ReplayOptions configuration options are:
- privacyProfile: Controls how UI elements are masked in the replay. To learn more, read Privacy options.
- capturePeriodMillis: Period between UI captures in milliseconds. Defaults to
1000(1 second). - debug: Enables verbose logging when set to
true. Defaults tofalse.
serviceName and serviceVersion are set in ObservabilityOptions, not in ReplayOptions.
Privacy options
ThePrivacyProfile class controls how UI elements are masked during session replay. Session replay for Android uses Jetpack Compose semantics to identify and mask UI elements. By default, text inputs are masked to protect user privacy.
Here’s how to configure privacy settings:
- maskTextInputs: When
true, masks all text input fields including editable text and paste operations. Defaults totrue. - maskText: When
true, masks all non-input text elements in the UI. Defaults tofalse. - maskBySemanticsKeywords: When
true, masks sensitive views that contain password fields or text matching sensitive keywords. Defaults tofalse. - maskViews: A list of Android
Viewclasses to mask. Because matching uses the exact class names, subclasses do not match. Use theview()helper with either a Kotlin class or a fully qualified class name. - maskWebViews: When
true, masks the contents of web views using a default list of WebView class names. This includes subclasses, and web views hosted inside Jetpack Compose throughAndroidView. Defaults tofalse. - maskXMLViewIds: A list of resource IDs to mask. Accepts the
@+id/example,@id/example, orexampleformat. - unmaskXMLViewIds: A list of resource IDs to unmask. Uses the same format as
maskXMLViewIds.
Sensitive keywords
WhenmaskBySemanticsKeywords is enabled, the SDK automatically masks any Compose UI text or content descriptions containing predetermined keywords. Keywords you specify are not case-sensitive. For the current set of keywords, read PrivacyProfile.
Common privacy configurations
For maximum privacy (recommended for production):Custom masking with ldMask
In addition to the privacy profile settings, you can explicitly mask individual UI elements by using the.ldMask() modifier. This is useful when you need to mask specific sensitive fields while allowing other content to remain visible.
Masking XML views
For traditional Android XML-based views, you can mask anyView by calling the .ldMask() extension function:
Masking Jetpack Compose elements
For Jetpack Compose, you can add the.ldMask() modifier to any composable to mask it in session replay recordings:
Unmasking elements
You can also explicitly unmask elements that would otherwise be masked by the privacy profile settings using the.ldUnmask() modifier:
.ldMask() and .ldUnmask() modifiers give you fine-grained control over which UI elements are masked in session replay recordings, allowing you to balance privacy protection with useful debugging information.
Mask by resource ID
Instead of calling.ldMask() on each element, you can mask or unmask XML views by their resource ID. Use the maskXMLViewIds and unmaskXMLViewIds options in your PrivacyProfile.
Here is an example:
unmaskXMLViewIds takes precedence over global rules such as maskText and maskTextInputs, but an explicit mask on the same view or any of its parent views still wins. To learn more, read Masking precedence.
Masking precedence
When the SDK decides whether to mask a view, it evaluates the following rules in order and stops at the first rule that applies:- Explicit masking: If the view or any of its parent views is explicitly masked with
.ldMask()or a matchingmaskXMLViewIdsentry, the SDK masks the view. This overrides all other rules. - Explicit unmasking: If the view or any of its parent views is explicitly unmasked with
.ldUnmask()or a matchingunmaskXMLViewIdsentry, the SDK does not mask the view. - Global configuration: If a global privacy option such as
maskTextInputsormaskTextapplies to the view, the SDK follows that option.
Manual instrumentation
After initializing the observability plugin, use theLDObserve singleton to manually instrument your Android application with custom metrics, logs, errors, traces, and product analytics events.
Recording custom metrics
Use the metric methods onLDObserve to record a Metric with a name and a value. Each method maps to a different OpenTelemetry instrument type:
Recording custom logs
UseLDObserve.recordLog to emit a structured log. Pass attributes as a plain Kotlin map through the properties parameter, or use the Attributes overload when you need precise OpenTelemetry typing:
Recording custom errors
UseLDObserve.recordError to report a caught exception, with optional attributes for context:
instrumentations.crashReporting remains true, which is the default.
Recording custom traces
UseLDObserve.startSpan to create a span for tracing an operation. Always end the span when the operation completes:
Recording product analytics events
Usetrack to record a custom event as a product analytics span. Use trackScreenView to record a screen view:
Distributed tracing
To implement distributed tracing, all spans generated across different function calls and services for the same user request must share the same context. While nested spans in the same synchronous scope automatically use the context of their parent span, the context is not automatically propagated when launching new coroutines or switching dispatchers. Use the OpenTelemetryContext API to capture and restore the parent span context explicitly in asynchronous code:
W3CTraceContextPropagator to inject the context into outgoing HTTP headers. Services that receive the headers can then extract and use the context.
extract method from W3CTraceContextPropagator to obtain the trace context and use it as the parent context for new spans.
Explore supported features
The observability plugin supports the following features. After the SDK and plugins are initialized, you can access these from within your application:- Configuration for client-side observability
- Configuration for session replay
- Errors
- Logs
- Metrics
- Symbolication
- Tracing
Review observability data in LaunchDarkly
After you initialize the SDK and observability plugin, your application automatically starts sending observability data back to LaunchDarkly. You can review this information in the LaunchDarkly user interface. To learn how, read Observability. The observability data collected includes:- Error monitoring: Unhandled exceptions, crashes, and manually recorded errors with stack traces
- Logs: Application logs with configurable severity levels and custom attributes
- Traces: Distributed tracing data including span timing, nested operations, and custom instrumentation
- Metrics: Performance metrics, custom counters, histograms, and gauge measurements
- Session data: User session information including lifecycle events and timing
- User error rate and crash frequency
- Application performance metrics such as launch time and session duration
- Feature flag evaluation context and timing
- Custom business metrics recorded through the SDK