Android SDK observability reference

The LaunchDarkly observability features are available for early access

Observability features in the LaunchDarkly UI are publicly available in early access.

The observability SDKs, implemented as plugins for LaunchDarkly server-side and client-side SDKs, are designed for use with the in-app observability features. They are currently in available in Early Access, and APIs are subject to change until a 1.x version is released.

If you are interested in participating in the Early Access Program for upcoming observability SDKs, sign up here.

Overview

This topic documents how to get started with the LaunchDarkly observability plugin for the Android SDK.

The Android SDK supports the observability plugin for error monitoring, logging, tracing, and session replay.

SDK quick links

LaunchDarkly’s SDKs are open source. In addition to this reference guide, we provide source, API reference documentation, and a sample application:

ResourceLocation
SDK API documentation

Observability plugin API docs

GitHub repository

@launchdarkly/observability-android

Published moduleMaven

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

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:

1implementation 'com.launchdarkly:launchdarkly-android-client-sdk:5.+'
2implementation 'com.launchdarkly:launchdarkly-observability-android:0.21.0'

Then, import the plugin into your code:

1import com.launchdarkly.sdk.*;
2import com.launchdarkly.sdk.android.*;
3import com.launchdarkly.observability.plugin.Observability
4import com.launchdarkly.sdk.android.integrations.Plugin

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.

Android observability SDK credentials

The Android observability SDK uses a mobile key. Keys are specific to each project and environment. They are available from Project settings, on the Environments list. To learn more about key types, read Keys.

Mobile keys are not secret and you can expose them in your client-side code without risk. However, never embed a server-side SDK key into a client-side application.

Here’s how to initialize the SDK and plugin:

1String mobileKey = "mobile-key-123abc";
2
3LDConfig ldConfig = new LDConfig.Builder(AutoEnvAttributes.Enabled)
4 .mobileKey(mobileKey)
5 .plugins(Components.plugins().setPlugins(
6 Collections.singletonList<Plugin>(Observability(this.getApplication(), mobileKey))
7 ))
8 // other options
9 .build();
10
11// You'll need this context later, but you can ignore it for now.
12LDContext context = LDContext.create("context-key-123abc");
13
14LDClient client = LDClient.init(this.getApplication(), ldConfig, context, 0);

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:

Plugin options, Android SDK v5.9+
1String mobileKey = "mobile-key-123abc";
2
3LDConfig ldConfig = new LDConfig.Builder(AutoEnvAttributes.Enabled)
4 .mobileKey(mobileKey)
5 .plugins(
6 Components.plugins().setPlugins(
7 Collections.singletonList<Plugin>(
8 Observability(
9 this.getApplication(),
10 mobileKey,
11 ObservabilityOptions(
12 resourceAttributes = Attributes.of(
13 AttributeKey.stringKey("serviceName"), "example-service"
14 )
15 )
16 )
17 )
18 )
19 )
20 .build();

For more information on plugin options, read Configuration for client-side observability.

Advanced configuration options

You can customize the observability plugin with additional options:

Advanced options example
1val mobileKey = "mobile-key-123abc"
2
3val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
4 .mobileKey(mobileKey)
5 .plugins(
6 Components.plugins().setPlugins(
7 listOf(
8 Observability(
9 this@BaseApplication,
10 mobileKey,
11 ObservabilityOptions(
12 serviceName = "my-android-app",
13 serviceVersion = "1.0.0",
14 debug = true,
15 logsApiLevel = ObservabilityOptions.LogLevel.WARN,
16 tracesApi = ObservabilityOptions.TracesApi(includeErrors = true, includeSpans = false),
17 metricsApi = ObservabilityOptions.MetricsApi.disabled(),
18 instrumentations = ObservabilityOptions.Instrumentations(
19 crashReporting = false,
20 activityLifecycle = true,
21 launchTime = true
22 ),
23 resourceAttributes = Attributes.of(
24 AttributeKey.stringKey("environment"), "production",
25 AttributeKey.stringKey("team"), "mobile"
26 ),
27 customHeaders = mapOf(
28 "X-Custom-Header" to "custom-value"
29 )
30 )
31 )
32 )
33 )
34 )
35 .build()

The available ObservabilityOptions configuration options are:

  • logsApiLevel: Minimum log severity to export. Defaults to INFO. Set to ObservabilityOptions.LogLevel.NONE to disable log exporting.
  • tracesApi: Controls trace recording. Defaults to enabled. Use ObservabilityOptions.TracesApi.disabled() to disable all tracing, or set includeErrors/includeSpans individually.
  • metricsApi: Controls metric export. Defaults to enabled. Use ObservabilityOptions.MetricsApi.disabled() to disable metrics.
  • instrumentations: Enables or disables specific automatic instrumentations:
    • crashReporting: If true, automatically reports uncaught exceptions as errors. Defaults to true.
    • activityLifecycle: If true, automatically starts spans for Android Activity lifecycle events. Defaults to true.
    • launchTime: If true, automatically measures and reports application startup time as metrics. Defaults to false.
  • 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.

1plugins {
2 id 'net.bytebuddy.byte-buddy-gradle-plugin' version '1.+'
3}
4
5dependencies {
6 // Android HTTP Url instrumentation
7 implementation 'io.opentelemetry.android.instrumentation:httpurlconnection-library:0.11.0-alpha'
8 byteBuddy 'io.opentelemetry.android.instrumentation:httpurlconnection-agent:0.11.0-alpha'
9
10 // OkHTTP instrumentation
11 implementation 'io.opentelemetry.android.instrumentation:okhttp3-library:0.11.0-alpha'
12 byteBuddy 'io.opentelemetry.android.instrumentation:okhttp3-agent:0.11.0-alpha'
13}

Configure session replay

The Android SDK supports session replay, which captures snapshots of your app’s UI at regular intervals. This allows you to visually review user sessions in LaunchDarkly to better understand user behavior and diagnose issues.

To enable session replay, add the SessionReplay plugin to the plugins list after the Observability plugin. Session replay depends on the Observability plugin being present and initialized first.

Here’s how:

Enable session replay
1import com.launchdarkly.observability.plugin.Observability
2import com.launchdarkly.observability.replay.plugin.SessionReplay
3
4val mobileKey = "mobile-key-123abc"
5
6val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
7 .mobileKey(mobileKey)
8 .plugins(
9 Components.plugins().setPlugins(
10 listOf(
11 Observability(this@BaseApplication, mobileKey),
12 SessionReplay() // depends on Observability being present first
13 )
14 )
15 )
16 .build()

Important notes:

  • SessionReplay depends on Observability. 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.

Session replay configuration options

You can customize session replay behavior by passing a ReplayOptions object to the SessionReplay constructor:

Session replay options
1import com.launchdarkly.observability.plugin.Observability
2import com.launchdarkly.observability.replay.plugin.SessionReplay
3import com.launchdarkly.observability.replay.ReplayOptions
4import com.launchdarkly.observability.replay.PrivacyProfile
5
6val mobileKey = "mobile-key-123abc"
7
8val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
9 .mobileKey(mobileKey)
10 .plugins(
11 Components.plugins().setPlugins(
12 listOf(
13 Observability(this@BaseApplication, mobileKey),
14 SessionReplay(
15 options = ReplayOptions(
16 privacyProfile = PrivacyProfile(
17 maskTextInputs = true,
18 maskText = true
19 ),
20 capturePeriodMillis = 1000,
21 debug = false
22 )
23 )
24 )
25 )
26 )
27 .build()

The available 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 to false.

Note: Service configuration options like serviceName and serviceVersion are set in ObservabilityOptions, not in ReplayOptions.

Privacy options

The PrivacyProfile 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, all masking options are enabled to protect user privacy.

Here’s how to configure privacy settings:

Privacy profile configuration
1import com.launchdarkly.observability.plugin.Observability
2import com.launchdarkly.observability.replay.plugin.SessionReplay
3import com.launchdarkly.observability.replay.ReplayOptions
4import com.launchdarkly.observability.replay.PrivacyProfile
5
6val mobileKey = "mobile-key-123abc"
7
8val ldConfig = LDConfig.Builder(AutoEnvAttributes.Enabled)
9 .mobileKey(mobileKey)
10 .plugins(
11 Components.plugins().setPlugins(
12 listOf(
13 Observability(this@BaseApplication, mobileKey),
14 SessionReplay(
15 options = ReplayOptions(
16 privacyProfile = PrivacyProfile(
17 maskTextInputs = true,
18 maskText = false
19 )
20 )
21 )
22 )
23 )
24 )
25 .build()

The available privacy options are:

  • maskTextInputs: When true, masks all text input fields including editable text and paste operations. Defaults to true.
  • maskText: When true, masks all text elements in the UI. Defaults to true.
  • maskSensitive: When true, masks sensitive views that contain password fields or text matching sensitive keywords. Defaults to true.

Sensitive keywords

When maskSensitive 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):

Maximum privacy
1privacyProfile = PrivacyProfile(
2 maskTextInputs = true,
3 maskText = true,
4 maskSensitive = true
5)

For debugging or development, you can turn masking off:

No masking
1privacyProfile = PrivacyProfile(
2 maskTextInputs = false,
3 maskText = false,
4 maskSensitive = false
5)

For selective masking, which masks inputs and sensitive data but shows regular text:

Selective masking
1privacyProfile = PrivacyProfile(
2 maskTextInputs = true,
3 maskText = false,
4 maskSensitive = true
5)

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 any View by calling the .ldMask() extension function:

Masking XML views
1import com.launchdarkly.observability.api.ldMask
2
3class LoginActivity : AppCompatActivity() {
4 override fun onCreate(savedInstanceState: Bundle?) {
5 super.onCreate(savedInstanceState)
6 setContentView(R.layout.activity_login)
7
8 val password = findViewById<EditText>(R.id.password)
9 password.ldMask() // mask this field in session replay
10 }
11}

Masking Jetpack Compose elements

For Jetpack Compose, you can add the .ldMask() modifier to any composable to mask it in session replay recordings:

Masking Compose elements
1import com.launchdarkly.observability.api.ldMask
2
3@Composable
4fun CreditCardField() {
5 var number by remember { mutableStateOf("") }
6 TextField(
7 value = number,
8 onValueChange = { number = it },
9 modifier = Modifier
10 .fillMaxWidth()
11 .ldMask() // mask this composable in session replay
12 )
13}

Unmasking elements

You can also explicitly unmask elements that would otherwise be masked by the privacy profile settings using the .ldUnmask() modifier:

Unmasking elements
1import com.launchdarkly.observability.api.ldUnmask
2
3@Composable
4fun PublicInfoField() {
5 var info by remember { mutableStateOf("") }
6 TextField(
7 value = info,
8 onValueChange = { info = it },
9 modifier = Modifier
10 .fillMaxWidth()
11 .ldUnmask() // explicitly unmask this field
12 )
13}

The .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.

For more information on session replay configuration, read Configuration for session replay.

Explore supported features

The observability plugins supports the following features. After the SDK and plugins are initialized, you can access these from within your application:

Review observability data in LaunchDarkly

After you initialize the SDK and observability plugin, your application automatically starts sending observability data back to LaunchDarkly, including errors and logs. You can review this information in the LaunchDarkly user interface. To learn how, read Observability.