Flutter SDK observability reference
This LaunchDarkly observability plugin is available for early access
This LaunchDarkly observability plugin is currently available in Early Access, and APIs are subject to change until a 1.x version is released.
This topic documents how to get started with the LaunchDarkly observability plugin for the Flutter SDK.
The launchdarkly_flutter_observability package provides error monitoring, logging, tracing, and session replay through a single public facade named LDObserve.
SDK quick links
LaunchDarkly SDKs are open source. In addition to this reference guide, we provide source, API reference documentation, and a sample application:
Prerequisites and dependencies
This reference guide assumes you are familiar with the LaunchDarkly Flutter SDK.
The observability plugin requires the LaunchDarkly Flutter SDK version 4.18.0 or later.
The Flutter observability plugin is compatible with iOS, Android, and web platforms. Session replay is supported only on iOS and Android. Web session replay is not yet available.
Get started
Follow these steps to get started:
- Install the package
- Initialize observability
- Configure plugin options
- Configure session replay
- Manually instrument your app
- Explore supported features
- Review observability data in LaunchDarkly
Install the package
Add both the LaunchDarkly Flutter SDK and the observability package to your pubspec.yaml:
Then run:
For iOS, install the native pod dependencies from your app’s ios/ directory:
No extra setup is required for Android. Gradle resolves the plugin automatically.
After you install the dependencies, import the packages into your code:
Initialize observability
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 Flutter SDK reference guide.
Flutter observability mobile and web builds use different credential types
The Flutter observability SDK uses a mobile key for iOS and Android builds. For web builds, use a client-side ID instead. Keys are specific to each project and environment. They are available on the SDK keys page under Settings. 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.
There are two initialization variants. Use LDObserve.init if you are using the LaunchDarkly client, or LDObserve.initStandalone to initialize without a client.
Initialize with a LaunchDarkly client
Pass your LDClient to LDObserve.init. This registers the observability plugin on the client so feature flag evaluations are correlated with your telemetry:
Initialize standalone
To initialize without creating a LaunchDarkly client, pass your mobile key directly to LDObserve.initStandalone:
Configure plugin options
Pass an ObservabilityOptions object to LDObserve.init or LDObserve.initStandalone to configure observability behavior:
These ObservabilityOptions configuration options are available on all platforms:
- isEnabled: Enables or disables observability. Defaults to
true. - serviceName: The service name for telemetry. Defaults to
"observability-flutter". - serviceVersion: The service version, commonly a Git SHA or semantic version string. Defaults to
"0.1.0". - instrumentation: An
InstrumentationOptionsobject that controls automatic instrumentation. To learn more, read Instrumentation options. - otlpEndpoint: The OTLP endpoint for reporting OpenTelemetry data. Defaults to
https://otel.observability.app.launchdarkly.com:4318. You do not need to change this for most configurations. - backendUrl: The LaunchDarkly back-end URL. Defaults to
https://pub.observability.app.launchdarkly.com. You do not need to change this for most configurations. - contextFriendlyName: A display name to identify the user’s session in the observability UI.
- attributes: A map of additional resource attributes to include in telemetry.
The following ObservabilityOptions configuration options are available only on Android and iOS:
- customHeaders: Extra HTTP headers added to OTLP exports, for example for proxies or authentication. Defaults to
{}. - sessionBackgroundTimeout: How long the app can stay in the background before the session ends. Defaults to 15 minutes.
- logsApiLevel: The minimum severity of logs forwarded to the logs pipeline. Use
ObservabilityLogLevel.noneto disable logs. Defaults toObservabilityLogLevel.info. - traces: A
TracesOptionsobject that controls automatic trace generation. TogglesincludeErrorsandincludeSpans. Both default totrue. - metricsEnabled: Whether metrics are exported. Defaults to
true. - analytics: An
AnalyticsOptionsobject that controls telemetry for product analytics events. UseAnalyticsOptions.enabledto enable all types orAnalyticsOptions.disabledto disable all:- taps (Android and iOS): Emits a
clickspan for each user tap. Defaults totrue. Setting this tofalsealso stops tap detection, rather than detecting taps without publishing them. - views (Android only): Emits a
screen_viewspan for each screen view. Defaults totrue. - trackEvents: Emits a
trackspan when a custom event is tracked withtrack(). Defaults totrue. - appLifecycle (Android and iOS): Emits
app_foregroundandapp_backgroundspans as the app moves between states. Defaults totrue. - appLaunch (Android and iOS): Emits an
app_launchspan once per process launch, including anapp.startspan event with the cold or warm startup dimension. Defaults totrue. To learn more, read Product analytics events.
- taps (Android and iOS): Emits a
For more information on plugin options, read Configuration for client-side observability.
Instrumentation options
The InstrumentationOptions class controls which automatic instrumentation features are active. Pass it to the instrumentation parameter of ObservabilityOptions.
These instrumentation options are available on all platforms:
- networkRequests: When
true, automatically instruments HTTP network requests. Defaults totrue. - launchTimes: When
true, measures and reports application launch time. Defaults totrue. - debugPrint: Controls whether
debugPrintcalls are automatically captured as log events:DebugPrintSetting.releaseOnly()(the default) capturesdebugPrintcalls only in release builds.DebugPrintSetting.always()capturesdebugPrintcalls in all build configurations. When enabled,debugPrintoutput does not appear in the Flutter console.DebugPrintSetting.disabled()does not instrumentdebugPrint.
The following InstrumentationOptions configuration option is available only on Android and iOS:
- crashReporting: When
true, reports uncaught exceptions as errors. Defaults totrue.
Intercept print statements
To capture the output from print statements, pass LDObserve.zoneSpecification() to runZonedGuarded:
Map contexts to friendly names
Use contextFriendlyName to set a human-readable display name for the user’s session when displayed in the observability User Interface (UI):
Configure product analytics event collection
On Android and iOS, the observability SDK for Flutter can record the following product analytics events as OpenTelemetry spans:
- Track events (manual, all platforms): A
trackspan recorded when your code callsLDObserve.track(). ThetrackEventsflag inAnalyticsOptionscontrols whether the span is emitted. To learn more, read Recording product analytics events. - Taps (automatic, Android and iOS): A
clickspan for each user tap, with details about the tap location. Enabled by default. To learn more, read Product analytics on mobile. - App lifecycle (automatic, Android and iOS): An
app_foregroundorapp_backgroundspan as the app moves between the foreground and background states. Enabled by default. - App launches (automatic, Android and iOS): 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. - Screen views (automatic, Android only): A
screen_viewspan when the app shows a screen, with the screen name and optional details such as the previous screen, screen class, screen identifier, and category. Theviewsoption is a no-op on iOS. To learn more, read Screen view events.
All product analytics span events also include information about the LaunchDarkly context that generated the event.
Use the generated span events to create custom product analytics charts, such as time series and funnels. To learn more, read Product analytics events.
To enable all compatible product analytics events, set analytics to AnalyticsOptions.enabled in ObservabilityOptions:
To enable or disable individual event types, use AnalyticsOptions instead:
Default values for product analytics
Track event, tap, screen view, app lifecycle, and app launch collection are all enabled by default. Use AnalyticsOptions.disabled to disable all product analytics spans at once.
Configure session replay
Session replay is in Early Access
Session replay for Flutter is available in Early Access. APIs are subject to change until a 1.x version is released.
Session replay captures screen recordings of user actions to help you understand how users interact with your application. It is included in the launchdarkly_flutter_observability package and uses native iOS and Android libraries to capture and upload recordings.
Session replay for Flutter is supported only on iOS and Android. Web session replay is not yet available.
Initialize session replay
To enable session replay, pass a SessionReplayOptions object to the replay parameter of LDObserve.init or LDObserve.initStandalone, and wrap your app in SessionReplayCapture:
SessionReplayCapture widget
Wrap your top-level widget in SessionReplayCapture to allow the native session replay library to capture screen content. On web, SessionReplayCapture is a no-op pass-through, so it is safe to use on every platform:
Session replay configuration options
Pass a SessionReplayOptions object to LDObserve.init or LDObserve.initStandalone to control session replay behavior:
If you omit the replay parameter, session replay does not start. The isEnabled default applies only to the SessionReplayOptions object you pass in.
These SessionReplayOptions configuration options are available on all platforms:
- isEnabled: Controls whether session recording starts. Defaults to
true. - privacy: A
PrivacyOptionsobject that controls which UI elements are masked. To learn more, read Privacy options. - serviceName: The service name reported for session replay telemetry. Defaults to
"sessionreplay-flutter".
The following SessionReplayOptions configuration options are available only on Android and iOS:
- frameRate: Target capture rate in frames per second. Defaults to
1.0. - scale: The resolution multiplier for captured frames, where
1.0is 1x (160 DPI) and2.0is 2x. Higher values capture more detail but produce larger frames. Anullvalue is treated as1.0. Defaults to1.0.
Privacy options
Use PrivacyOptions to control which elements are masked in session replay recordings. By default, text inputs are masked to protect user data.
The available privacy options are:
- maskTextInputs: Masks all text input fields. Defaults to
true. - maskWebViews: Masks the contents of web views. When enabled, web views appear as blank rectangles in recordings. Defaults to
false. - maskLabels: Masks all text labels. Defaults to
false. - maskImages: Masks all images. Defaults to
false. - minimumAlpha: (iOS only) Minimum alpha value for a view to be captured. Views with a lower alpha are not recorded. Defaults to
0.02.
LaunchDarkly applies masks to every captured frame. Masks follow their widgets through scrolling, transforms, and animations. If a mask cannot be placed reliably in a frame, LaunchDarkly drops that frame rather than risk exposing unmasked content.
Per-widget masking
In addition to screen-wide PrivacyOptions, you can redact individual widgets using LDMask, LDIgnore, and LDUnmask.
Use LDMask to redact a widget’s subtree in all captured frames:
Use LDIgnore to exclude a subtree from session replay entirely. In Flutter, LDIgnore behaves like LDMask and paints over the region in every captured frame, so its contents never appear in a recording:
Use LDUnmask to exempt a subtree from global masking rules such as maskTextInputs. For example, to reveal one non-sensitive field on a page where every input is masked:
LDUnmask only overrides global masking. It does not override an explicit LDMask or LDIgnore. An LDUnmask nested inside either one stays masked, because an explicit per-widget mask always takes precedence.
LDMask, LDIgnore, and LDUnmask are active on iOS and Android. On web they render their child unchanged.
Mask by widget type or key
When wrapping widgets is not convenient, name them once in PrivacyOptions by their Type or Key. LaunchDarkly resolves these rules on the Flutter side and does not send them to the native SDKs:
The available widget matching options are:
- maskWidgetTypes: A set of widget
Types to mask wherever they appear. Defaults to an empty set. - maskWidgetKeys: A set of widget
Keys to mask wherever they appear. Defaults to an empty set. - unmaskWidgetTypes: A set of widget
Types to reveal from global masking. Defaults to an empty set. - unmaskWidgetKeys: A set of widget
Keys to reveal from global masking. Defaults to an empty set. - ignoreWidgetTypes: A set of widget
Types to ignore. Defaults to an empty set. - ignoreWidgetKeys: A set of widget
Keys to ignore. Defaults to an empty set.
These rules follow the same precedence as the wrapper widgets. A mask or ignore match takes precedence over an unmask match.
To learn more about session replay configuration, read Configuration for session replay.
Manual instrumentation
After initializing the observability plugin, use LDObserve to manually instrument your Flutter application with custom logs, traces, and product analytics events.
Recording custom logs
Use LDObserve.recordLog to emit a structured log. severity is a plain string. Common levels are trace, debug, info, warn, error, and fatal. properties is a plain Dart map with no LaunchDarkly or OpenTelemetry types required:
Recording custom traces
Use LDObserve.startSpan to create a span for tracing an operation. Spans nest automatically under the currently active span. Always end spans when the operation completes:
To set the span’s kind, pass the kind parameter to startSpan. SpanKind supports internal, which is the default, along with client, server, producer, and consumer.
Each span supports these methods:
- setAttribute(name, value): Sets a single attribute on the span.
- setAttributes(map): Sets multiple attributes on the span.
- addEvent(name, {attributes}): Records a named event on the span.
- setStatus(SpanStatusCode): Sets the span status to
ok,error, orunset. - recordException(exception, {stackTrace, attributes}): Records an exception on the span.
- end(): Ends the span.
To record spans independently instead of nesting them, end each span before you start the next:
Attribute and property values
Attributes and properties are plain Dart values, so no LaunchDarkly or OpenTelemetry types are required. A value can be a String, int, double, bool, or a homogeneous list of any of those types. The SDK ignores values it cannot represent as an attribute, such as nested maps or mixed-type lists.
The recordLog, recordException, startSpan, and track methods all accept a properties map of these same plain values.
Recording product analytics events
Use LDObserve.track to record a custom event as a product analytics span:
Shut down observability
Call LDObserve.shutdown() to shut down observability. You cannot restart observability after you shut it down:
Identify contexts
To tie observability data to the correct context, use the LaunchDarkly client to identify or switch contexts:
You do not need to call any LDObserve method. The observability plugin hooks into the LaunchDarkly client and, on Android and iOS, forwards each completed identify to the native observability SDK and to session replay. This attributes subsequent LDObserve.track events to the active context and records the context on the active session replay recording.
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
- 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, including errors and logs. You can review this information in the LaunchDarkly user interface. To learn how, read Observability.