feat: supporting advanced trace cases#645
Merged
Merged
Conversation
Add a cookbook of distributed tracing patterns for the React Native observability SDK, mirroring the existing .NET MAUI guide but adapted to the JS/OpenTelemetry API (startActiveSpan/startSpan, explicit context propagation across async boundaries, tracingOrigins-based mobile-to-backend trace linking). Lives in guides/ since docs/ is reserved for generated Typedoc output, and is linked from the package README. Co-authored-by: Cursor <cursoragent@cursor.com>
… guide Document setting, reading, and updating W3C baggage and how it propagates to backends via tracingOrigins, plus a note that baggage is not copied onto spans automatically. Co-authored-by: Cursor <cursoragent@cursor.com>
Add a Tracing tab to the session-replay example with a button per recipe from the distributed tracing guide and a live output log, registering the Observability plugin with tracingOrigins so the backend-propagation and baggage recipes exercise real header injection. Co-authored-by: Cursor <cursoragent@cursor.com>
Stop tracking the session-replay example's ios/Podfile.lock and Gemfile.lock, which are regenerated per-machine and churn on every pod/bundle install. The monorepo yarn.lock remains tracked for reproducible installs. Co-authored-by: Cursor <cursoragent@cursor.com>
…s resource attributes buildObservabilityResource strips the default service.name from the OTel resource but never re-adds one from options, so exported spans, logs, and metrics had an empty service.name (the value only flowed to Session Replay). Populate service.name / service.version from ObservabilityOptions.serviceName and serviceVersion in the shared resource builder so both init paths (LDClient plugin and standalone LDObserve.init) emit a populated service identity. Co-authored-by: Cursor <cursoragent@cursor.com>
Vadman97
approved these changes
Jun 25, 2026
Vadman97
left a comment
Contributor
There was a problem hiding this comment.
could note to @dyozie-ld that we should make a docs update based on some of this?
Co-authored-by: Cursor <cursoragent@cursor.com>
…-tracing Bring in the launchdarkly-android-client-sdk bump (0.46.1).
Introduce a LaunchDarkly-owned SessionManager (LDSessionManager) that can be seeded with an external session id, so the native instance can adopt a session id created elsewhere (e.g. the JS SDK in a React Native app) and report a single shared session.id across spans, logs, metrics, and replay. - LDSessionManager: seedable session manager replicating OTel Android's rotation semantics (foreground never expires, background inactivity and max-lifetime rotation) and observer notifications. - LDRumSessionManagerAccessor: same-package shim to call the package-private OpenTelemetryRumBuilder.setSessionManager, making our manager back the RUM SDK's session.id span/log appenders (single source of session identity). - ObservabilityService: inject the custom manager, drop the old session-manager-bridge instrumentation and SessionConfig, drive the background-timeout from the app lifecycle, and read session.id from it. - Thread an optional customSessionId through the Observability plugin and LDObserve.init for callers (RN integration to follow). Co-authored-by: Cursor <cursoragent@cursor.com>
…on id When a session id is supplied externally the caller owns the session lifecycle, matching iOS's isCustomSession. Skip both background-inactivity and max-lifetime rotation so the seeded id is used unchanged for the lifetime of the manager. Co-authored-by: Cursor <cursoragent@cursor.com>
…pendency
The OpenTelemetry Android `activity` instrumentation is always suppressed
(its app/activity lifecycle spans are superseded by our own), so the
dependency was dead weight. Remove it (also drops `common-api`) and keep
suppressInstrumentation("activity") as a defensive guard in case a host
reintroduces it transitively.
Co-authored-by: Cursor <cursoragent@cursor.com>
…ound state AppLifecycleTracker only reports genuine transitions (it suppresses the initial replay and never emits a catch-up background), so an SDK init while the app is already backgrounded left LDSessionManager stuck in FOREGROUND and skipped background-inactivity rotation until the next stop/start cycle. Query the process lifecycle at init and mark the manager backgrounded when appropriate; a later genuine onStart settles it back to foreground. Co-authored-by: Cursor <cursoragent@cursor.com>
…ted-tracing * feat/android-external-session-id: fix(observability-android): prime session manager with initial background state chore(observability-android): drop unused activity instrumentation dependency feat(observability-android): disable auto rotation for external session id feat(observability-android): support external session id
2 tasks
… to README Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…independence Co-authored-by: Cursor <cursoragent@cursor.com>
…an/scope.active Co-authored-by: Cursor <cursoragent@cursor.com>
…e runnable example screen Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
There are 3 total unresolved issues (including 1 from previous review).
❌ 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 e2fc3e2. Configure here.
…s stand alone Co-authored-by: Cursor <cursoragent@cursor.com>
… URL origin The instrumentations' propagateTraceHeaderCorsUrls matches these patterns against the full request URL, so an unanchored host string could match a third-party URL carrying the host as a query value and leak trace/baggage headers. Anchor string entries to the origin (host + subdomains). Co-authored-by: Cursor <cursoragent@cursor.com>
…ver track data in afterTrack Co-authored-by: Cursor <cursoragent@cursor.com>
Merged
abelonogov-ld
pushed a commit
that referenced
this pull request
Jun 25, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>observability-react-native: 0.10.0</summary> ## [0.10.0](observability-react-native-0.9.3...observability-react-native-0.10.0) (2026-06-25) ### Features * supporting advanced trace cases ([#645](#645)) ([dac45eb](dac45eb)) </details> <details><summary>session-replay-react-native: 0.12.0</summary> ## [0.12.0](session-replay-react-native-0.11.1...session-replay-react-native-0.12.0) (2026-06-25) ### Features * supporting advanced trace cases ([#645](#645)) ([dac45eb](dac45eb)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/observability-react-native bumped to 0.10.0 </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Version and changelog-only release PR; behavioral changes were already merged in #645. > > **Overview** > Release Please version bump with **no application code** in this diff—only manifest, `package.json`, and changelog updates. > > **`@launchdarkly/observability-react-native`** goes **0.9.3 → 0.10.0** (minor). The new changelog entry records **advanced trace cases** ([#645](#645)) as the shipped feature. > > **`@launchdarkly/session-replay-react-native`** goes **0.11.1 → 0.12.0**, with the same feature noted and a workspace dependency bump to **`@launchdarkly/observability-react-native` 0.10.0**. `.release-please-manifest.json` is updated to match. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 71e0ede. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
This PR adds React Native distributed-tracing documentation and the supporting
LDObserveAPI surface, automatictracktracing via the LD plugin hook, an iOS/Android-parity example app, the RN external session-id wiring, and a tracing-origin matching fix.Changes
Docs
observability-react-native/guides/tracing.md): a cookbook of common patterns — root/nested spans, manual HTTP spans, automaticfetch/XHRinstrumentation, exception recording, correlated logs, explicit context propagation across async boundaries, independent root spans via{ root: true }, span events, end-to-end mobile-to-backend trace linking viatracingOrigins, and OpenTelemetry baggage propagation. Placed underguides/(not the gitignored, Typedoc-generateddocs/) and linked from the README.withSpan"Manual tracing" example.SDK (
observability-react-native)withSpanAPI (src/sdk/withSpan.ts,src/api/SpanScope.ts): an ergonomic wrapper that runs a callback inside a span and ends it automatically, withscope.childto parent nested spans off the captured context — important in RN where the active context is only tracked synchronously (lost acrossawait).LDObserve.track(Observe,LDObserve,ObservabilityClient,InstrumentationManager): records a customtrackspan carrying the eventkey, optional numericvalue, and properties — mirroring the iOS/AndroidtrackAPIs.tracktracing hook (plugin/observability.ts): the Observability plugin'sTracingHooknow implementsafterTrack, so everyLDClient.trackcall automatically emits a span (eventkey, optional metricvalue, evaluation context keys, and primitive track data) — no manual instrumentation needed. Flag-evaluation spans are additionally tagged with an internal attribute so SDK-emitted telemetry can be filtered out universally (independent of instrumentation scope).{ root: true }onstartSpan/startActiveSpanis forwarded to the underlying OpenTelemetry tracer, which drops the active span from context so the new span begins a fresh trace regardless of ambient context.observability-shared/src/instrumentation/utils.ts+ tests): match against the URL's origin (anchored host/subdomain regex) instead of an unanchored substring, so a configured host appearing as a query-param value in a third-party URL no longer leaks trace/baggage headers. String entries are escaped so.is literal.React Native external session id (
react-native-ld-session-replay)sessionIdthrough to the native Android SDK so RN, native observability, and session replay share onesession.id(SessionReplayClientAdapter.kt/.swift,NativeSessionReplayReactNative.ts,src/index.tsx).com.launchdarkly:launchdarkly-android-client-sdkand the iOSLaunchDarklySessionReplaypod to0.46.1.Example app (
react-native-ld-session-replay/example)TracingScreen.tsx) exercising every recipe in the guide, and an API tab (ApiScreen.tsx) mirroring the iOS TestApp (MainMenuViewModel): identify, spans, metrics, logs, errors, track (via LD client), network, crash.PASS/FAIL), so it actually exercises{ root: true }.Observabilityplugin with demotracingOriginsinApp.tsx; add@launchdarkly/observability-react-native+@opentelemetry/apideps; monorepometro.config.jsresolution (workspace watch folders + forced react/react-native singletons).Podfile.lock/Gemfile.lock.Notes
react-native-ld-session-replay, but that package is purely session replay/masking; the tracing API lives inobservability-react-native, so the guide and APIs were added there.LDObserve.trackplain-dictionary (nested) reshaping is intentionally split into a separate stacked PR (feat(observability-react-native): accept plain nested dictionaries in track #650) on top of this branch.Test plan
observability-react-nativeunit tests pass (incl. tracingOrigins matching).PASS;LDClient.trackauto-emits a span via the hook; API tab mirrors the iOS demo; sharedsession.idacross JS + native (Android).tracingOrigins.Note
Medium Risk
Changes public tracing APIs and distributed trace header matching (security-sensitive); native session ID wiring and dependency bumps affect session-replay integration.
Overview
Adds manual tracing for React Native via
LDObserve.withSpanandSpanScope(child,active,ctx) so span hierarchies surviveawaits where OTel’s stack context does not, plusLDObserve.trackand anafterTrackplugin hook soLDClient.trackemitstrackspans like other mobile SDKs. Flag-evaluation spans getlaunchdarkly.internalfor filtering.Ships a tracing cookbook (
guides/tracing.md) and README updates; the session-replay example gains Observability, Tracing and API tabs, and Metro monorepo fixes.Security / propagation:
tracingOriginsstring hosts are origin-anchored inobservability-sharedso trace/baggage headers are not matched inside third-party URLs.Session replay: Android forwards JS
sessionId/serviceVersioninto native observability; bumps Android/iOS LD dependencies; example lockfiles are gitignored.E2E: Android sample sets
sessionBackgroundTimeoutto 3 minutes.Reviewed by Cursor Bugbot for commit 9d06f16. Bugbot is set up for automated code reviews on this repo. Configure here.