Skip to content

feat(tracing): Add extend app start API for standalone app start#6392

Open
antonis wants to merge 8 commits into
mainfrom
antonis/rn-675-add-api-to-extend-app-start-react-native
Open

feat(tracing): Add extend app start API for standalone app start#6392
antonis wants to merge 8 commits into
mainfrom
antonis/rn-675-add-api-to-extend-app-start-react-native

feat(tracing): Add extend app start API for standalone app start (RN-…

4620572
Select commit
Loading
Failed to load commit list.
@sentry/warden / warden: find-bugs completed Jul 2, 2026 in 0s

1 issue

find-bugs: Found 1 issue (1 medium)

Medium

Extended app start end-time (`trimmedEndMs`) discarded when `appStartEndData` is unset - `packages/core/src/js/sdk.tsx:304-307`

In the standalone extend flow, finalizeStandaloneAppStart computes trimmedEndMs (the latest finished child span end, floored at the default app-start end) and sets it on the transaction span via setEndTimeValue. However, it only persists this value into appStartEndData.timestampMs when appStartEndData is already defined (if (appStartEndData && trimmedEndMs)). When extendAppStart() is used without Sentry.wrap/ReactNativeProfiler and without a manual appLoaded() call, appStartEndData stays undefined (the deferred captureStandaloneAppStart, which would otherwise call _setAppStartEndData, was cancelled by extendAppStart). attachAppStartToTransactionEvent then reads appStartEndData?.timestampMs || getBundleStartTimestampMs(), falling back to the bundle-start time, and overwrites event.timestamp with it. The extended window is silently dropped, producing a too-short app.vitals.start.value measurement and a transaction that no longer reflects the extension work.


⏱ 27m 59s · 3.2M in / 237.9k out · $6.55

Annotations

Check warning on line 307 in packages/core/src/js/sdk.tsx

See this annotation in the file changed.

@sentry-warden sentry-warden / warden: find-bugs

Extended app start end-time (`trimmedEndMs`) discarded when `appStartEndData` is unset

In the standalone extend flow, `finalizeStandaloneAppStart` computes `trimmedEndMs` (the latest finished child span end, floored at the default app-start end) and sets it on the transaction span via `setEndTimeValue`. However, it only persists this value into `appStartEndData.timestampMs` when `appStartEndData` is already defined (`if (appStartEndData && trimmedEndMs)`). When `extendAppStart()` is used without `Sentry.wrap`/`ReactNativeProfiler` and without a manual `appLoaded()` call, `appStartEndData` stays `undefined` (the deferred `captureStandaloneAppStart`, which would otherwise call `_setAppStartEndData`, was cancelled by `extendAppStart`). `attachAppStartToTransactionEvent` then reads `appStartEndData?.timestampMs || getBundleStartTimestampMs()`, falling back to the bundle-start time, and overwrites `event.timestamp` with it. The extended window is silently dropped, producing a too-short `app.vitals.start.value` measurement and a transaction that no longer reflects the extension work.