Skip to content
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
> make sure you follow our [migration guide](https://docs.sentry.io/platforms/react-native/migration/) first.
<!-- prettier-ignore-end -->

## Unreleased

### Features

- Add experimental `extendAppStart`/`finishExtendedAppStart`/`getExtendedAppStartSpan` to extend the standalone app start window and instrument post-init work ([#6392](https://github.com/getsentry/sentry-react-native/pull/6392))

## 8.17.0

### Features
Expand Down
9 changes: 9 additions & 0 deletions packages/core/etc/sentry-react-native.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ export const expoRouterIntegration: (options?: ExpoRouterIntegrationOptions) =>
// @public
export const expoUpdatesListenerIntegration: () => Integration;

// @public
Comment thread
antonis marked this conversation as resolved.
export function extendAppStart(): void;

export { extraErrorDataIntegration }

export { FeatureFlagsIntegration }
Expand Down Expand Up @@ -353,6 +356,9 @@ export const feedbackIntegration: (initOptions?: Partial<FeedbackFormProps> & {
enableShakeToReport?: boolean;
}) => FeedbackIntegration;

// @public
export function finishExtendedAppStart(): Promise<void>;

// @public
export function flush(): Promise<boolean>;

Expand Down Expand Up @@ -384,6 +390,9 @@ export function getDataFromUri(uri: string): Promise<Uint8Array | null>;
// @public
export function getDefaultIdleNavigationSpanOptions(): StartSpanOptions;

// @public
export function getExtendedAppStartSpan(): Span;

export { getGlobalScope }

export { getIsolationScope }
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ export {
withScope,
crashedLastRun,
appLoaded,
extendAppStart,
getExtendedAppStartSpan,
finishExtendedAppStart,
pauseAppHangTracking,
resumeAppHangTracking,
} from './sdk';
Expand Down
67 changes: 65 additions & 2 deletions packages/core/src/js/sdk.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* oxlint-disable eslint(complexity) */
import type { Breadcrumb, BreadcrumbHint, Integration, Scope } from '@sentry/core';
import type { Breadcrumb, BreadcrumbHint, Integration, Scope, Span } from '@sentry/core';

import {
debug,
Expand All @@ -25,7 +25,12 @@ import { shouldEnableNativeNagger } from './options';
import { enableSyncToNative } from './scopeSync';
import { TouchEventBoundary } from './touchevents';
import { ReactNativeProfiler } from './tracing';
import { _appLoaded } from './tracing/integrations/appStart';
import {
_appLoaded,
_extendAppStart,
_finishExtendedAppStart,
_getExtendedAppStartSpan,
Comment thread
antonis marked this conversation as resolved.
} from './tracing/integrations/appStart';
import { useEncodePolyfill } from './transports/encodePolyfill';
import { DEFAULT_BUFFER_SIZE, makeNativeTransportFactory } from './transports/native';
import { getDefaultEnvironment, isExpoGo, isRunningInMetroDevServer, isWeb } from './utils/environment';
Expand Down Expand Up @@ -250,6 +255,64 @@ export function appLoaded(): void {
_appLoaded();
}

/**
* Extends the app start window so work done after initialization (remote config, session restore,
* splash screen dismissal, etc.) is included in the app start measurement. Call
* {@link finishExtendedAppStart} when the app is ready, or attach child spans via
* {@link getExtendedAppStartSpan} to break the extended work down.
*
* Requires standalone app start tracing (`_experiments.enableStandaloneAppStartTracing`). No-ops if
* the app start transaction was already created, if extend was already called, or if called before
* `Sentry.init()`.
*
* @experimental This API is subject to change in future versions.
*
* @example
* ```ts
* Sentry.extendAppStart();
* await initializeRemoteConfig();
* Sentry.finishExtendedAppStart();
* ```
*/
export function extendAppStart(): void {
_extendAppStart();
}

/**
* Returns the extended app start span for attaching child spans, or a no-op span when there is no
* active extension. Only meaningful between {@link extendAppStart} and {@link finishExtendedAppStart}.
*
* @experimental This API is subject to change in future versions.
*
* @example
* ```ts
* Sentry.extendAppStart();
* const parentSpan = Sentry.getExtendedAppStartSpan();
* const child = Sentry.startInactiveSpan({ parentSpan, op: 'app.init', name: 'fetch remote config' });
* await loadRemoteConfig();
* child.end();
* Sentry.finishExtendedAppStart();
* ```
*/
export function getExtendedAppStartSpan(): Span {
return _getExtendedAppStartSpan();
}

/**
* Finishes the app start extension started with {@link extendAppStart}, finalizing the app start
* transaction (its duration is trimmed to the last child span). No-ops if there is no active
* extension.
*
* Returns a promise that resolves once the app start transaction has been captured. `await` it
* before {@link flush} (e.g. before a code-push/expo update) to make sure the app start data is
* queued.
*
* @experimental This API is subject to change in future versions.
*/
export function finishExtendedAppStart(): Promise<void> {
return _finishExtendedAppStart();
}

/**
* Flushes all pending events in the queue to disk.
* Use this before applying any realtime updates such as code-push or expo updates.
Expand Down
Loading
Loading