Getting started with observability for .NET MAUI
This guide shows how to add LaunchDarkly observability to a .NET MAUI application targeting Android and iOS. Because MAUI is a single C# codebase that compiles to both platforms, one path serves both targets. Platform-specific differences are called out inline as you reach them. By the end, you’ll have the SDK and plugins installed, observability and session replay turned on, and confirmation that data is flowing.
The MAUI observability plugin is in early access. Its APIs may change before the 1.x release.
The .NET MAUI SDK supports two complementary telemetry plugins:
- Observability captures errors, crashes, logs, and traces. Use it to debug failures in production, watch error rates for a release, and trace network calls end-to-end. Observability automatically reports uncaught exceptions.
- Session replay captures UI snapshots of what a user encountered. Use it when a stack trace alone doesn’t tell you why a user got stuck, and pair it with masking to keep sensitive fields out of the recording.
Both plugins install alongside the LaunchDarkly .NET MAUI SDK and initialize in the same place. To learn more about every configuration field, the full LDObserve method surface, and advanced distributed-tracing patterns, read the .NET MAUI SDK observability reference.
Prerequisites
To complete this guide, you need:
- .NET 9.0 or .NET 10.0 with the MAUI workload installed.
- A target device or emulator: Android API level 24+ (Android 7.0, Nougat), or iOS 13.2+.
- A LaunchDarkly account and a mobile key for the environment you’re testing against. Find the mobile key on the SDK keys page under Settings.
Step 1: Install the SDK
Add the LaunchDarkly.SessionReplay package to your MAUI project:
Then run a clean build before anything else:
Stale build artifacts cause hard-to-diagnose failures, especially on iOS targets. If you hit dependency-resolution errors, running dotnet restore first usually clears them.
If you build for Android from Visual Studio on Windows, the Android SDK may land in a system-protected directory the build can’t write to, causing build errors. The fix is to relocate the Android SDK to a user-writable location. For step-by-step instructions, read the Android SDK relocation guide for Windows. This only affects Android-on-Windows.
Import the namespaces where you’ll initialize the SDK:
Step 2: Initialize the SDK
Initialization belongs in MauiProgram.cs, alongside the rest of your MauiApp.CreateBuilder() configuration. This example references LDConfig.MobileKey. LDConfig is a small static class that holds the mobile key. Replace that reference with your own constant or with an inline string literal:
The serviceName is how this app appears in the LaunchDarkly UI, so make it recognizable.
Step 3: Turn on session replay
Add the SessionReplayPlugin to the plugin list alongside ObservabilityPlugin:
Step 4: Decide what to mask
Masking is configured through PrivacyOptions on SessionReplayOptions. There are several configuration options depending on your use case.
They are:
- Production: Mask everything, including labels, images, and web views.
- Local debugging: Turn masking off on your own test data so you can see what’s going on.
- Balanced: Mask inputs and web views (passwords, payment forms, and similar) but keep ordinary labels and images visible.
The simple rule is to start fully masked, and only unmask what you’ve confirmed is safe to record.

Mask a specific element
When a preset is almost right but one field is the exception, override it at the element level. Call .LDMask() on the underlying view after you have a reference to it, or call .LDUnmask() to reveal something the preset would hide:
LDMask() and LDUnmask() reach the underlying view, so the view’s handler must be attached first. Call them after the view is in the visual tree, for example in a page’s Appearing event, not in a constructor.
Step 5: Run it and confirm data is arriving
Build and run on a device or emulator:
Test out the app by navigating between a couple of screens. Trigger an error deliberately if you want to verify that Observability captures it correctly.
Then open the Observability page in the LaunchDarkly UI. Logs and errors attributed to your serviceName appear there, as well as a session replay recording you can scrub through with your masking choices applied. When your service name appears in Observability, that is a confirmation that the SDK initialized successfully and is recording data.

Logs and errors arriving in LaunchDarkly, attributed to the serviceName you set in Step 2.

After data shows up on one target, the other target reports the same way after you build and run it there.
Complete code sample
Here is a MauiProgram.cs showing both plugins wired into MAUI’s startup. LDConfig is a small static class that holds the MobileKey constant. The privacy block uses the SDK default (mask text inputs only). Swap in any preset from Step 4 to change what session replay records:
What to explore next
- Every configuration field: The complete
ObservabilityOptionsandSessionReplayOptionstables are in the SDK reference documentation and in Configuration for client-side observability. - Custom tracing: Time your own operations with
LDObservespans. The reference’s distributed-tracing section covers root spans, nesting, cross-thread context, and automaticHttpClientinstrumentation. - How this relates to OpenTelemetry: The plugin is an OpenTelemetry implementation under the hood. If you already use
System.Diagnostics.Activity,LDObservehasStartActivity,StartRootActivity, andGetActivitySourceequivalents so your existing trace code flows in. - Working with your data: After telemetry is flowing, set up alerts and dashboards, then investigate issues with Vega.
Troubleshooting
Use this section to investigate issues.
No data appearing
- Confirm you pasted the mobile key for the environment you’re viewing in the UI, and not for a different environment.
- Make sure plugin registration runs in
MauiProgram.csand that the configured builder is actually returned fromCreateMauiApp(). - Test the app a bit more and refresh. Data isn’t always instantaneous, so it may take a few minutes to display correctly.
Session replay isn’t recording, but observability works
- Confirm
SessionReplayPluginis added to thePluginConfigurationBuilder, not justObservabilityPlugin. - If you set
isEnabledtofalseonSessionReplayOptionsfor consent-gated rollout, confirm the call that enables it is actually running.
Build failures
- Run
dotnet cleanand rebuild, especially on iOS. - On Windows building for Android, check the Android SDK relocation note in Step 1.
Masking not applied to a specific view
- Confirm
.LDMask()or.LDUnmask()is called after the view’s handler is attached, for example inAppearing, not in a constructor.
Conclusion
In this guide, you instrumented a .NET MAUI application for LaunchDarkly observability. You can now:
- Capture errors, logs, and session replays from both Android and iOS with one C# codebase
- Control what session replay records through
PrivacyOptionspresets and per-view masking - Confirm telemetry is flowing in the LaunchDarkly UI, ready for alerts, dashboards, and Vega
Your 14-day trial begins as soon as you sign up. Get started in minutes using the in-app Quickstart. You’ll discover how easy it is to release, monitor, and optimize your software.
Want to try it out? Start a trial.