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 |
|---|---|
| GitHub repository | LaunchDarkly.SessionReplay |
| Published package | NuGet |
Prerequisites and dependencies
This SDK requires:- .NET 9 or .NET 10 with the MAUI workload installed
- Android API level 23 or higher (Android 6.0, Marshmallow)
- iOS 15 or higher
Get started
Follow these steps to get started:- Install the SDK
- Initialize the SDK
- Enable HTTP request tracing
- Configure observability options
- Configure session replay
- Configure session replay privacy options
- Use custom masking
- Explore supported features
- Review observability data in LaunchDarkly
Install the SDK
Add theLaunchDarkly.SessionReplay NuGet package to your MAUI project:
dotnet clean before building. This is especially important for iOS targets, as stale build artifacts can cause issues. If you encounter dependency resolution problems, run dotnet restore first:
Initialize the SDK
Initialize the SDK by registering theObservabilityPlugin on the LaunchDarkly client configuration. Call this during your app’s startup, typically in MauiProgram.cs.
The ObservabilityPlugin handles both observability and session replay. Register it using the PluginConfigurationBuilder to integrate it directly with the LaunchDarkly client lifecycle. To turn on session replay, pass a SessionReplayOptions object as the plugin’s second argument. To learn more, read Configure session replay.
Here’s how to initialize the SDK:
Enable HTTP request tracing
The SDK automatically creates spans for outgoing HTTP requests made throughHttpClient. For these spans to be recorded, set HttpActivityPropagationSupport to true in your app’s project file.
Here is an example:
HttpActivityPropagationSupport to false by default in every build configuration, and the .NET iOS SDK sets it to false in Release builds. While it is false, the trimmer removes the System.Net.Http diagnostics that the observability SDK listens to. As a result, the SDK records no HTTP spans, even if you enable NetworkRequests instrumentation. The SDK cannot turn this setting on at runtime.
Configure observability options
You can customize the observability behavior by passing anObservabilityOptions object to the ObservabilityPlugin constructor.
Here is an example:
ObservabilityOptions configuration options are:
- IsEnabled: Whether the SDK records observability telemetry. Defaults to
true. - ServiceName: The service name for the application. Defaults to
"observability-maui". - ServiceVersion: The version of the service. If you do not set it, the SDK reports your app’s version, from
AppInfo.Current.VersionString. - OtlpEndpoint: The endpoint URL for the OpenTelemetry Protocol (OTLP) exporter. Defaults to the LaunchDarkly endpoint. Override it to send data through a proxy.
- BackendUrl: The backend URL for the observability service. Defaults to the LaunchDarkly backend.
- ContextFriendlyName: An optional friendly name for the user context, displayed in the LaunchDarkly UI.
- Attributes: Additional resource attributes to attach to every exported signal, such as
deployment.environment. - CustomHeaders: Additional HTTP headers to add to OTLP exports, for example, for a proxy or for authentication.
- LogsApiLevel: The minimum severity of logs to export. Uses the
ObservabilityLogLevelenum, whose values match the OpenTelemetry severity numbers, fromTracetoFatal4. Set it toObservabilityLogLevel.Noneto turn off log export. Defaults toObservabilityLogLevel.Info. - Instrumentation: An
InstrumentationOptionsobject with two settings,NetworkRequestsandLaunchTimes, that turn automatic instrumentation ofHttpClientrequests and app launch times on or off. Both default totrue.
Default service version changed in version 0.13.0In SDK versions earlier than 0.13.0,
ServiceVersion defaults to "0.1.0". Starting in version 0.13.0, apps that do not set ServiceVersion report their own app version instead. The ObservabilityOptions.DefaultServiceVersion constant is obsolete.LDObserve.NativeVersion returns the version of the underlying native observability SDK. Include it when you contact LaunchDarkly Support.
For more information on plugin options, read Configuration for client-side observability.
Configure session replay
The .NET MAUI SDK supports session replay, which captures snapshots of your app’s UI at regular intervals. This lets you visually review user sessions in LaunchDarkly to better understand user behavior and diagnose issues. To turn on session replay, pass aSessionReplayOptions object as the second argument to the ObservabilityPlugin constructor.
Here’s how to configure session replay:
SessionReplayOptions configuration options are:
- IsEnabled: Enables or disables session replay. Defaults to
true. - ServiceName: The service name for session replay telemetry. Defaults to
"sessionreplay-dotnet". - Privacy: Controls how UI elements are masked in the replay. To learn more, read Configure session replay privacy options.
- SampleRate: The probability, from
0.0to1.0, that the SDK records a session. For example,0.25records about a quarter of sessions. Defaults to1.0. - FrameRate: The target capture rate, in frames per second. Defaults to
1.0. - Scale: The capture resolution.
1.0is 1x (160 dots per inch),2.0is 2x, and so on. Higher values capture more detail but produce larger frames. Defaults to1.0. - ImageQuality: The JPEG quality of exported frames, from
0.0(smallest) to1.0(best). Defaults to0.3.
Configure session replay privacy options
ThePrivacyOptions class controls how UI elements are masked during session replay. 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. Defaults totrue. - MaskWebViews: When
true, masks the contents of web views. Web views are rendered as blank rectangles in session replays. Defaults tofalse. - MaskLabels: When
true, masks all text labels. Defaults tofalse. - MaskImages: When
true, masks all images. Defaults tofalse. - MinimumAlpha: Minimum alpha value for view visibility in recordings. Views with alpha below this threshold are not captured. Defaults to
0.02.
Common privacy configurations
For maximum privacy (recommended for production):Use custom masking
In addition to the privacy profile settings, you can explicitly mask or unmask individual MAUI views using theLDMask() and LDUnmask() extension methods. This gives you fine-grained control over which UI elements are captured in session replay recordings.
Here is an example:
Handler must be attachedThe
LDMask() and LDUnmask() methods work by accessing the underlying native platform view. The MAUI view’s handler must be attached before calling these methods. Call them after the view has been added to the visual tree, such as in a page’s Appearing event or in OnHandlerChanged. Before the handler is attached, these methods have no effect..LDMask() and .LDUnmask() extension methods work on any MAUI View, and they apply to the underlying native view on both Android and iOS.
Explore supported features
The .NET MAUI observability SDK supports the following features. After the SDK is initialized, you can access these from within your application:Using .NET System.Diagnostics
As with other LaunchDarkly observability SDK plugins, the .NET MAUI observability plugin supports OpenTelemetry operations using the following span methods.| Method | Description | Return value |
|---|---|---|
LDObserve.StartActiveSpan(name) | Uses the current active span as its parent. | TelemetrySpan |
LDObserve.StartActiveSpan(name, parentContext) | Uses the provided SpanContext as its parent. | TelemetrySpan |
LDObserve.StartActiveSpan(name, kind, parentContext) | Uses the provided SpanContext with a custom kind as its parent. | TelemetrySpan |
LDObserve.StartRootSpan(name) | Creates a new trace. | TelemetrySpan |
LDObserve.GetTracer() | Returns an OpenTelemetry tracer. | Tracer |
System.Diagnostics API, LaunchDarkly’s observability plugin provides the following methods help you continue using your existing trace code.
| Method | Description | Return value |
|---|---|---|
LDObserve.StartActivity(name) | Uses the current activity as its parent. | Activity? |
LDObserve.StartRootActivity(name) | Creates a new trace. | Activity? |
LDObserve.GetActivitySource() | Returns an ActivitySource to create and start Activity objects. | ActivitySource |
System.Diagnostics API:
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. This section shows techniques for nesting spans and propagating span contexts across services when using the .NET MAUI observability SDK.Creating a root span
Creating a root span creates a new trace regardless of any current span context that might exist. UseStartRootSpan to create your initial trace and span context.
Nesting spans
UseStartActiveSpan to create new spans using the parent span context. This pattern enables you to trace multi-step operations in the same application.
The following example nests all newly-created spans under LoadProducts. The DeserializeJson span is further nested under FetchFromApi.
Propagating span context across threads
When work runs on a detached thread, for example, usingTask.Run, the span context is lost. Use span.Context to capture the context and pass it to other threads.
Using spans with HttpClient
When calling a remote service you must preserve the current span context when creating new spans, or capture details of the service call in the current span. WhenInstrumentationOptions.NetworkRequests is enabled, every HttpClient request generates a System.Net.Http span automatically. This is the default behavior, but it requires the HttpActivityPropagationSupport project setting. To learn more, read Enable HTTP request tracing. If a custom span is active at call time, the HTTP span becomes its child. The following example automatically generates a new span for the HTTP GET call and nests it under the active SyncOrders span. You do not need to create a span for the HTTP call itself:
Additional distributed tracing techniques
Your application may also need to perform other, more advanced distributed tracing activities such as:- Correlating log entries within a span
- Correlating log entries or across different threads
- Recording span exceptions
- Using the Activity API in place of OpenTelemetry methods