Skip to content

Commit 993bd3b

Browse files
authored
feat(tracing): Track appLoaded and extendAppStart adoption (#6426)
* feat(core): Track GlobalErrorBoundary adoption Register a no-op `GlobalErrorBoundary` integration when the component mounts so the name flows through to `event.sdk.integrations` — the same channel used for feature- adoption signals like `MobileFeedback` and `AppStart`. Also introduces a shared `registerFeatureMarker` helper. Subsequent markers for other opt-in features (NavigationContainer, ExpoRouter error boundary, AppLoaded, ...) will use this helper — see #6415. Refs: #6415 * feat(tracing): Track appLoaded and extendAppStart adoption Register no-op `AppLoaded` and `ExtendedAppStart` integrations on first call so the names flow through to `event.sdk.integrations`. `ExtendedAppStart` covers all three extend API entry points: `extendAppStart`, `getExtendedAppStartSpan`, and `finishExtendedAppStart`. Refs: #6415
1 parent 05047ad commit 993bd3b

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

packages/core/src/js/tracing/integrations/appStart.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
APP_START_COLD as APP_START_COLD_MEASUREMENT,
2525
APP_START_WARM as APP_START_WARM_MEASUREMENT,
2626
} from '../../measurements';
27+
import { registerFeatureMarker } from '../../utils/featureMarkers';
2728
import { convertSpanToTransaction, isRootSpan, setEndTimeValue } from '../../utils/span';
2829
import { NATIVE } from '../../wrapper';
2930
import { getRootSpanDiscardReason, getTransactionEventDiscardReason } from '../onSpanEndUtils';
@@ -51,6 +52,8 @@ import {
5152
} from '../utils';
5253

5354
const INTEGRATION_NAME = 'AppStart';
55+
const APP_LOADED_INTEGRATION_NAME = 'AppLoaded';
56+
const EXTENDED_APP_START_INTEGRATION_NAME = 'ExtendedAppStart';
5457

5558
export type AppStartIntegration = Integration & {
5659
captureStandaloneAppStart: () => Promise<void>;
@@ -124,6 +127,7 @@ export async function _appLoaded(): Promise<void> {
124127
return;
125128
}
126129

130+
registerFeatureMarker(APP_LOADED_INTEGRATION_NAME);
127131
isAppLoadedManuallyInvoked = true;
128132

129133
const timestampMs = timestampInSeconds() * 1000;
@@ -204,6 +208,7 @@ export async function _captureAppStart({ isManual }: { isManual: boolean }): Pro
204208
* @private
205209
*/
206210
export function _extendAppStart(): void {
211+
registerFeatureMarker(EXTENDED_APP_START_INTEGRATION_NAME);
207212
getClient()?.getIntegrationByName<AppStartIntegration>(INTEGRATION_NAME)?.extendAppStart();
208213
}
209214

@@ -214,6 +219,7 @@ export function _extendAppStart(): void {
214219
* @private
215220
*/
216221
export function _getExtendedAppStartSpan(): Span {
222+
registerFeatureMarker(EXTENDED_APP_START_INTEGRATION_NAME);
217223
return (
218224
getClient()?.getIntegrationByName<AppStartIntegration>(INTEGRATION_NAME)?.getExtendedAppStartSpan() ??
219225
new SentryNonRecordingSpan()
@@ -227,6 +233,7 @@ export function _getExtendedAppStartSpan(): Span {
227233
* @private
228234
*/
229235
export async function _finishExtendedAppStart(): Promise<void> {
236+
registerFeatureMarker(EXTENDED_APP_START_INTEGRATION_NAME);
230237
await getClient()?.getIntegrationByName<AppStartIntegration>(INTEGRATION_NAME)?.finishExtendedAppStart();
231238
}
232239

packages/core/test/tracing/integrations/appStart.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ import {
3232
_captureAppStart,
3333
_clearAppStartEndData,
3434
_clearRootComponentCreationTimestampMs,
35+
_extendAppStart,
36+
_finishExtendedAppStart,
37+
_getExtendedAppStartSpan,
3538
_setAppStartEndData,
3639
_setRootComponentCreationTimestampMs,
3740
appStartIntegration,
@@ -1219,6 +1222,19 @@ describe('Extended App Start', () => {
12191222
return { integration, client };
12201223
};
12211224

1225+
it.each([
1226+
['_extendAppStart', (): void => _extendAppStart()],
1227+
['_getExtendedAppStartSpan', (): void => void _getExtendedAppStartSpan()],
1228+
['_finishExtendedAppStart', async (): Promise<void> => _finishExtendedAppStart()],
1229+
])('registers the ExtendedAppStart feature marker via %s', async (_name, call) => {
1230+
const { client } = setupStandaloneIntegration();
1231+
expect(client.getIntegrationByName('ExtendedAppStart')).toBeUndefined();
1232+
1233+
await call();
1234+
1235+
expect(client.getIntegrationByName('ExtendedAppStart')).toEqual({ name: 'ExtendedAppStart' });
1236+
});
1237+
12221238
it('creates an extended app start span and finalizes it with a measurement on finish', async () => {
12231239
mockAppStart({ cold: true });
12241240
const { integration, client } = setupStandaloneIntegration();
@@ -1573,6 +1589,14 @@ describe('appLoaded() API', () => {
15731589
return integration;
15741590
}
15751591

1592+
it('registers the AppLoaded feature marker on first call', async () => {
1593+
expect(client.getIntegrationByName('AppLoaded')).toBeUndefined();
1594+
1595+
await _appLoaded();
1596+
1597+
expect(client.getIntegrationByName('AppLoaded')).toEqual({ name: 'AppLoaded' });
1598+
});
1599+
15761600
it('sets the app start end timestamp and marks it as manual', async () => {
15771601
const appLoadedTimeSeconds = Date.now() / 1000;
15781602
mockFunction(timestampInSeconds).mockReturnValue(appLoadedTimeSeconds);

0 commit comments

Comments
 (0)