Repository navigation
Add API to extend app start (React Native) #6303
Copy link
Copy link
Closed
Labels
Description
Rewrite RN's app start end customization onto a span-returning API consistent with Flutter, Android and Cocoa. Today appLoaded() only moves the end timestamp and returns nothing, so users can't break down extended launch work.
// Simple: extend the app start window, then finish
Sentry.extendAppStart();
await initializeRemoteConfig();
Sentry.finishExtendedAppStart();// With child spans: instrument the extended region
Sentry.extendAppStart();
const span = Sentry.getExtendedAppStartSpan();
const configSpan = span.startChild({ op: 'app.init', description: 'fetch remote config' });
await loadRemoteConfig();
configSpan.finish();
Sentry.finishExtendedAppStart();Reference: getsentry/sentry-cocoa#6886 (Done, SentryExtendedAppLaunchManager). Siblings: getsentry/sentry-dart#3767, getsentry/sentry-java#5553 — shared contract, RN-specific sections below.
API
extendAppStart(): void— creates the extended app start span (opapp.start.extended, description"Extended App Start").finishExtendedAppStart— finishes it (returns void); triggers finalization.getExtendedAppStartSpan(): Span— returns the span for attaching children; a no-op span when there's no active extension.
finishExtendedAppStartis equivalent to calling.finish()on the returned span.
Lifecycle
extendAppStart: creates the span (start = call time). No-ops if app start already finished, if none is in progress, or on repeat calls (first wins).getExtendedAppStartSpan: returns the extended span, else a no-op span.finishExtendedAppStart: no-ops if not extended or called twice. Doesn't finalize directly — the parent (auto-generated,waitForChildren) finalizes when its last child finishes and trims its end to that child. Open children of the extended span are finishedcancelledat the finish-call time.
Duration & measurement
- Parent duration = end of the last child to finish (trim-to-last-child), floored at the default app start end — i.e.
end = max(last child end, default app start end). Extending can only push the end later; finishing before the default end keeps the default (never shorter than a non-extended app start). The extended span is just one participant. - App start measurement = that final duration (process start → last child), set at finalization. The normal completion-time measurement must be suppressed in extended mode so the early (non-extended) value doesn't win.
Timeout
- Parent's auto-finish deadline is 30s. If
finishExtendedAppStartis never called, the transaction auto-finishes on the deadline (unfinished children →deadlineExceeded, snapped to transaction end), is still captured, but theapp.vitals.startmeasurement is suppressed — never emit a ~30s app start. Same for standalone andui.load.
Standalone & non-standalone
- Both supported, same mechanism: standalone uses the app-start tracer, non-standalone the
ui.loadtransaction (alsowaitForChildren+ deadline). In non-standalone the duration is bounded by anything keepingui.loadopen (TTID, other children), so it can include spans unrelated to the extension.
RN specifics
- Replace
appLoaded()directly (experimental — no deprecation cycle) and fold in the already-deprecatedcaptureAppStart(). Document the migration toextendAppStart/ children /finishExtendedAppStart. - RN's
waitForChildrenequivalent is the cancel-deferred path: auto-capture schedulescaptureStandaloneAppStart()viasetTimeout(…, 0);extendAppStart()must cancel that deferred send and keep the transaction open untilfinishExtendedAppStartis called, producing the same trim-to-last-child end. Reuse the cached-response path that bypasses the nativehas_fetched: trueguard.
Acceptance criteria
-
extendAppStart()creates the span before finish; no-ops when too late, not started, or called repeatedly. -
getExtendedAppStartSpan()returns the span, else a no-op span (including after finish). - Custom child spans render under
Extended App Start. -
finishExtendedAppStartno-ops if not extended or called twice; finalizes via the deferred-cancel path with transaction end = last child. - Measurement = process start → last child, floored at the default app start end (never shorter than a non-extended app start), set at finalization.
- Open children at finish →
cancelled; on deadline →deadlineExceeded, snapped to end. - Deadline path: transaction captured,
app.vitals.startsuppressed. - Extended app starts carry a segmentation attribute.
-
appLoaded()replaced,captureAppStart()folded in, migration documented. - Docs updated.
Reactions are currently unavailable
Activity
linear-code commentedon Jun 16, 2026
RN-675
[-]Rewrite app start end API to `getExtendedAppStartSpan` (React Native)[/-][+]Add API to extend app start (React Native)[/+]github-actions commentedon Jul 9, 2026
A PR closing this issue has just been released 🚀
This issue was referenced by PR #6392, which was included in the 8.18.0 release.