Skip to content

feat(maui): catch up public API with Flutter observability SDK - #798

Merged
abelonogov-ld merged 17 commits into
mainfrom
feat/maui-api-catch-up
Oct 6, 2026
Merged

abelonogov-ld merged 17 commits into
mainfrom
feat/maui-api-catch-up

Conversation

@abelonogov-ld

@abelonogov-ld abelonogov-ld commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #791. Review that first; this PR's diff is only the API work on top of it.

Summary

Brings the MAUI public API closer to the Flutter observability SDK. Every option below already existed in the native Android and iOS SDKs. MAUI simply didn't expose it, so this is mostly plumbing through the Kotlin and Swift bridges and the binding definitions.

Observability options

  • CustomHeaders — extra headers sent with OTLP export.
  • LogsApiLevel — minimum severity for logs sent through LDObserve.RecordLog. Uses a new ObservabilityLogLevel enum that follows the OpenTelemetry severity numbers (Trace = 1 … Fatal4 = 24), plus None to turn logging off. The default is Info.
  • ServiceVersion now defaults to null and resolves to the app's version (AppInfo.Current.VersionString) instead of a hardcoded constant. DefaultServiceVersion is marked [Obsolete]. Behavior change: apps that don't set it now report their real version.
  • LDObserve.NativeVersion — the version of the underlying native SDK, useful in support requests.

Session replay options

  • Capture: SampleRate, FrameRate, Scale, ImageQuality (defaults 1.0 / 1.0 / 1.0 / 0.3, the same as native).
  • Privacy: MinimumAlpha is now passed through on iOS too.
  • LDIgnore() view extension, next to the existing LDMask() / LDUnmask().

On Android, "ignore" maps to mask, because the native Android SDK has no per-view ignore. The README says so.

Docs

The README now covers the new options, capture settings and NativeVersion.

Not in this PR

  • Type-based privacy rules (MaskViewTypes, UnmaskViewTypes, IgnoreViewTypes) moved to the feat/maui-privacy-view-types branch, stacked on this one, so they can be reviewed separately.
  • LDReplay.TrackEvaluation is effectively dead: nothing calls it, there's no native entry point, and evaluations are already recorded as evaluation spans by the observability hook. I suggest marking it [Obsolete] separately.
  • Remaining Flutter-parity gaps: init readiness result, Shutdown(), Track / TrackScreenView / TrackClick, WithSpan, log capture, and the analytics / traces / metricsEnabled toggles.
  • The Android bridge passes Analytics(screenViews = false) because MAUI is meant to report screen views itself, but MAUI never does. So Android currently records no screen views. Worth a follow-up.

Verification

  • Built the sample on Android and iOS, and checked the new fields in the generated Android binding and in the rebuilt xcframework.
  • After fix(maui): .NET 10 Android Release build fixes (relocate okio/okhttp) #791 dropped the OTel upgrade, rebuilt the Android binding cleanly against the reverted observability-android. CustomHeaders, LogsApiLevel and SampleRate are all present in the generated C#.
  • Not verified on a device: CustomHeaders arriving on export.

Note

Overview
Expands the MAUI observability SDK so more native settings are configurable from .NET and documented, aligning with the Flutter SDK.

Observability: Adds CustomHeaders and LogsApiLevel (new ObservabilityLogLevel enum, OTel severities plus None). ServiceVersion is optional and, when unset, resolves to AppInfo.Current.VersionString instead of a fixed default (DefaultServiceVersion is obsolete). Exposes LDObserve.NativeVersion after init. Values are passed through the Android and iOS bridges.

Session replay: Adds capture knobs SampleRate, FrameRate, Scale, and ImageQuality, and wires Privacy.MinimumAlpha through on iOS. Adds View.LDIgnore() (Android falls back to mask). README covers observability options, capture settings, masking timing, and NativeVersion.

Package version bumps to 0.14.1.

Reviewed by Cursor Bugbot for commit bada0a0. Bugbot is set up for automated code reviews on this repo. Configure here.

abelonogov-ld and others added 13 commits October 2, 2026 17:00
…ndled okio/okhttp

- Bump OpenTelemetry Java 1.51.0 -> 1.66.0 and OpenTelemetry Android 0.11.0-alpha -> 1.7.0
  in observability-android and the MAUI LDObserve native module; migrate to the split
  SessionProvider/SessionPublisher API, RumBuilder, and the new AttributeType.VALUE /
  ValueType.EMPTY cases.
- Pin kotlinx-coroutines, kotlin-stdlib, androidx.core and okhttp to versions the current
  Kotlin 2.0.21 / AGP 8.x toolchain can build against.
- Drop the Org.Jetbrains.Kotlinx.KotlinxSerializationJson NuGet dependency. Its JVM package
  injects a jar from a hardcoded Gradle cache path, which duplicated
  kotlinx.serialization.json classes in apps using Xamarin.KotlinX.Serialization.Json.
- Relocate the okio and okhttp3 classes bundled in ldobserve-otel-bundle.jar under
  com.launchdarkly.sessionreplay.shaded so they no longer collide with Square.OkIO
  (R8 'defined multiple times' failure in Release builds, e.g. via Firebase).
- Update NativeAndroidDeps.props globs for the renamed OTel Android 1.x artifacts.
- Fix ObservabilityBridge for the pageViews -> screenViews rename.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Add MauiSample10.csproj (net10.0-android/ios) sharing sources with MauiSample9, with
  isolated obj/bin paths.
- Reference Xamarin.Firebase.Messaging/Analytics on Android as a standing check against
  the Square.OkIO / KotlinX duplicate-class conflicts (exercised by Release builds).
- Guard CommunityToolkit.Maui Popup API differences (v11 vs v15) in DialogsPage.
- Show platform, .NET runtime version and Debug/Release in the shell title.
- Remove global.json so the .NET 10 SDK can build the tree.

Co-authored-by: Cursor <cursoragent@cursor.com>
… consumer apps

0.11.1 raised Xamarin.AndroidX.Lifecycle.* floors to 2.11.0.1, which requires
SavedState >= 1.5.0.1 and Collection.Jvm >= 1.6.0.1 and conflicts with our
SavedState 1.3.1.1 / Collection 1.5.0.3 floors, producing NU1605 downgrade
errors in MAUI apps (e.g. MauiPlanets on MAUI 9). Our Java only uses lifecycle
APIs present in 2.9 (ProcessLifecycleOwner, DefaultLifecycleObserver), so go
back to the 2.9.2.1 line MAUI itself ships.

Stop suppressing NU1605/NU1608 in MauiSample10 so the sample catches this, and
bump the package version to 0.11.2.

Co-authored-by: Cursor <cursoragent@cursor.com>
Observability options:
- LDObserve.NativeVersion exposes the native SDK version reported at startup.
- ServiceVersion is now optional and defaults to the host app version
  (AppInfo.Current.VersionString) instead of the hardcoded "0.1.0";
  DefaultServiceVersion is marked obsolete.
- CustomHeaders for OTLP exports.
- LogsApiLevel (new ObservabilityLogLevel enum, OTel severity numbers, None disables).

Session replay options:
- SampleRate, FrameRate, Scale, ImageQuality.
- PrivacyOptions.MaskViewTypes / UnmaskViewTypes / IgnoreViewTypes: MAUI view
  types (exact match) resolved in .NET and applied through the native per-view
  masking API when a matching view's handler connects. Android has no per-view
  ignore, so ignored views are masked there.
- LDIgnore() view extension.

Bridges (Kotlin, Swift, iOS ApiDefinition) carry the new fields to the native
SDKs. Also forward ContextFriendlyName (Android) and MinimumAlpha (both
platforms), which the bridges received but never passed to native.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
The okio/okhttp relocation is what fixes the R8 duplicate-class failure in
Release, and it is independent of the OTel version: 0.10.2, which shipped on
OTel 1.51, already bundles 433 unshaded okio/okhttp3 entries including the
okio/-DeflaterSinkExtensions that R8 rejects.

Upgrading to OTel Android 1.7 pulls androidx.core 1.19, androidx.lifecycle 2.11
and okhttp-android 5.4, which require compileSdk 36-37 and AGP 9.1. That breaks
every native Android consumer still on AGP 8, including our own e2e app, and is
a migration the Android owners should land on its own schedule.

Reverts the version bumps and the observability-android changes that existed
only to track the 1.x API. Keeps the relocation, the Lifecycle floors, the
.NET 10 sample and the Analytics.screenViews fix.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@abelonogov-ld
abelonogov-ld requested a review from a team as a code owner October 6, 2026 18:26
Base automatically changed from feat/maui-otel-upgrade-net10 to main October 6, 2026 19:24
* main:
  fix(maui): .NET 10 Android Release build fixes (relocate okio/okhttp) (#791)

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit c92f0c9. Configure here.

Comment thread sdk/@launchdarkly/mobile-dotnet/observability/replay/api/PrivacyTypeRules.cs Outdated
abelonogov-ld and others added 3 commits October 6, 2026 13:25
- iOS bridge: copy customHeaders entry by entry instead of casting the
  NSDictionary to [String: String] and falling back to an empty map.
- PrivacyTypeRules: when LDObserve is initialized from CreateMauiApp,
  Application.Current is still null, so the visual-tree watch was never
  installed. Retry until the application exists, and watch each window
  directly in case DescendantAdded doesn't bubble to the application.

Co-authored-by: Cursor <cursoragent@cursor.com>
MaskViewTypes / UnmaskViewTypes / IgnoreViewTypes and PrivacyTypeRules move
to feat/maui-privacy-view-types so they can be reviewed separately.

Co-authored-by: Cursor <cursoragent@cursor.com>
@abelonogov-ld
abelonogov-ld merged commit 3eb9c0b into main Oct 6, 2026
23 checks passed
@abelonogov-ld
abelonogov-ld deleted the feat/maui-api-catch-up branch October 6, 2026 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants