This topic documents how to get started with the LaunchDarkly observability plugin for the iOS SDK.The iOS SDK supports the observability plugin for error monitoring, logging, and tracing.
LaunchDarkly’s SDKs are open source. In addition to this reference guide, we provide source and a sample application:
This reference guide assumes that you are somewhat familiar with the LaunchDarkly iOS SDK.The observability plugin is compatible with the iOS SDK, version 9.14.0 and later, and is only available if you are using Swift.
LaunchDarkly uses a plugin to the iOS SDK to provide observability.The first step is to make both the SDK and the observability plugin available as dependencies.Here’s how:
Next, initialize the SDK and the plugin.To initialize, you need your LaunchDarkly environment’s mobile key. 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:
let config = LDConfig(mobileKey: "example-mobile-key", autoEnvAttributes: .enabled) config.plugins = [Observability()] let contextBuilder = LDContextBuilder(key: "example-context-key") guard case .success(let context) = contextBuilder.build() else { return } LDClient.start(config: config, context: context, startWaitSeconds: 5) { timedOut in if timedOut { // Client may not have the most recent flags for the configured context } else { // Client has received flags for the configured context } }
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:
// Create configuration with custom options let configuration = Configuration( serviceName: "MyApp", otlpEndpoint: "https://otel.observability.app.launchdarkly.com:4318", serviceVersion: "1.2.3", resourceAttributes: [ "environment": .string("production"), "team": .string("mobile-team"), "app.version": .string("1.2.3") ], customHeaders: [("Custom-Header", "header-value")], sessionTimeout: 30 * 60, // 30 minutes in seconds isDebug: false, isErrorTrackingDisabled: false, isLogsDisabled: false, isTracesDisabled: false, isMetricsDisabled: false ) // Create the observability plugin with configuration let observabilityPlugin = Observability(configuration: configuration) let config = LDConfig(mobileKey: "example-mobile-key", autoEnvAttributes: .enabled) config.plugins = [observabilityPlugin]
After initializing the observability plugin, you can use the LDObserve singleton to manually instrument your iOS application with custom metrics, logs, traces, and error reporting.
do { // Some operation that might fail try performNetworkRequest() } catch { // Record the error with context let errorAttributes: [String: AttributeValue] = [ "operation": .string("network_request"), "endpoint": .string("/api/data") ] LDObserve.shared.recordError(error: error, attributes: errorAttributes) }
// Start a span and end it manually let attributes: [String: AttributeValue] = [ "table": .string("users"), "operation": .string("select") ] let span = LDObserve.shared.startSpan(name: "database_query", attributes: attributes) // Perform your operation performDatabaseQuery() // Optionally add more attributes during execution span.setAttribute(key: "rows_returned", value: .int(42)) // Always end the span span.end()
// Get span builder for more control let spanBuilder = LDObserve.shared.spanBuilder(spanName: "complex_operation") .setSpanKind(spanKind: .client) spanBuilder.setAttribute(key: "user.id", value: .string("12345")) let span = spanBuilder.startSpan() // Make the span current for nested operations span.makeCurrent() // Perform work that might create child spans performComplexWork() span.end()
Session Replay is available in Early Access. APIs are subject to change until a 1.x version is released.
Session Replay captures user interactions and screen recordings to help you understand how users interact with your application. Session Replay works as an additional plugin that requires the observability plugin to be configured first.
To enable Session Replay, add the SessionReplay plugin to your SDK configuration alongside the Observability plugin. The Observability plugin must be added before the SessionReplay plugin:
let mobileKey = "example-mobile-key" let config = LDConfig( mobileKey: mobileKey, autoEnvAttributes: .enabled ) config.plugins = [ // Observability plugin must be added before SessionReplay Observability(options: .init( serviceName: "ios-app", sessionBackgroundTimeout: 3)), SessionReplay(options: .init( isEnabled: true, privacy: .init( maskTextInputs: true, maskWebViews: false, maskImages: false, maskAccessibilityIdentifiers: ["email-field", "password-field"] ) )) ] let contextBuilder = LDContextBuilder(key: "example-context-key") guard case .success(let context) = contextBuilder.build() else { return } LDClient.start( config: config, context: context, startWaitSeconds: 5.0, completion: { (timedOut: Bool) -> Void in if timedOut { // Client may not have the most recent flags for the configured context } else { // Client has received flags for the configured context } } )
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. Set isEnabled to false in SessionReplayOptions, then call LDReplay.shared.start() when you’re ready to begin recording.First, configure the plugin with isEnabled: false:
The PrivacyOptions struct provides the following parameters:
maskTextInputs: Mask all text input fields. Defaults to true.
maskWebViews: Mask the contents of web views (WKWebView and UIWebView). When this setting is enabled, web views are rendered as blank rectangles in session replays. Defaults to false.
maskLabels: Mask all text labels. Defaults to false.
maskImages: Mask all images. Defaults to false.
maskUIViews: Array of UIView classes to automatically mask in recordings.
ignoreUIViews: Array of UIView classes to exclude from masking rules.
maskAccessibilityIdentifiers: Array of accessibility identifiers to mask. Use this to mask specific UI elements by their accessibility identifier.
ignoreAccessibilityIdentifiers: Array of accessibility identifiers to exclude from masking rules.
minimumAlpha: Minimum alpha value for view visibility in recordings. Views with alpha below this threshold are not captured. Defaults to 0.02.
You can override the default privacy settings on individual views using the .ldPrivate() and .ldUnmask() methods. This allows precise control over what is captured in session replays.
UI view maskingUse view modifiers to control masking for SwiftUI views:
import SwiftUI import SessionReplay struct ContentView: View { @State private var email = "" @State private var shouldMaskEmail = true var body: some View { VStack { // Mask this specific view Text("Sensitive information") .ldPrivate() // Unmask this view (even if it would be masked by default) Image("profile-photo") .ldUnmask() // Conditionally mask based on a flag TextField("Email", text: $email) .ldPrivate(isEnabled: shouldMaskEmail) } } }
Use the .ldPrivate() and .ldUnmask() methods on UIView instances:
import UIKit import SessionReplay class CreditCardViewController: UIViewController { let cvvField = UITextField() let nameField = UITextField() let cardNumberField = UITextField() override func viewDidLoad() { super.viewDidLoad() // Mask the CVV field cvvField.ldPrivate() // Unmask the name field (even if text inputs are masked by default) nameField.ldUnmask() // Conditionally mask based on a flag cardNumberField.ldPrivate(isEnabled: true) } }
The observability plugin supports the following features. After the SDK and plugins are initialized, you can access these from within your application:
After you initialize the SDK and observability plugin, your application automatically starts sending observability data back to LaunchDarkly in the form of custom events and OpenTelemetry data. 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
Specifically, the observability data includes events that LaunchDarkly uses to automatically create the following metrics:
User error rate and crash frequency
Application performance metrics such as launch time and session duration