@sentry/react-native 8.1.0 → 8.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/RNSentry.podspec +1 -1
- package/android/AGENTS.md +51 -0
- package/android/build.gradle +2 -2
- package/android/libs/replay-stubs.jar +0 -0
- package/android/replay-stubs/build.gradle +1 -1
- package/android/src/main/java/io/sentry/react/RNSentryLogger.java +96 -0
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +14 -4
- package/android/src/main/java/io/sentry/react/RNSentryStart.java +11 -9
- package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
- package/dist/js/NativeLogListener.d.ts +16 -0
- package/dist/js/NativeLogListener.d.ts.map +1 -0
- package/dist/js/NativeLogListener.js +72 -0
- package/dist/js/NativeLogListener.js.map +1 -0
- package/dist/js/client.d.ts +1 -0
- package/dist/js/client.d.ts.map +1 -1
- package/dist/js/client.js +14 -3
- package/dist/js/client.js.map +1 -1
- package/dist/js/index.d.ts +2 -2
- package/dist/js/index.d.ts.map +1 -1
- package/dist/js/index.js +1 -1
- package/dist/js/index.js.map +1 -1
- package/dist/js/integrations/default.d.ts.map +1 -1
- package/dist/js/integrations/default.js +2 -1
- package/dist/js/integrations/default.js.map +1 -1
- package/dist/js/integrations/expoconstants.d.ts +24 -0
- package/dist/js/integrations/expoconstants.d.ts.map +1 -0
- package/dist/js/integrations/expoconstants.js +77 -0
- package/dist/js/integrations/expoconstants.js.map +1 -0
- package/dist/js/integrations/exports.d.ts +1 -0
- package/dist/js/integrations/exports.d.ts.map +1 -1
- package/dist/js/integrations/exports.js +1 -0
- package/dist/js/integrations/exports.js.map +1 -1
- package/dist/js/options.d.ts +26 -0
- package/dist/js/options.d.ts.map +1 -1
- package/dist/js/options.js.map +1 -1
- package/dist/js/tools/easBuildHooks.d.ts +48 -0
- package/dist/js/tools/easBuildHooks.d.ts.map +1 -0
- package/dist/js/tools/easBuildHooks.js +228 -0
- package/dist/js/tools/easBuildHooks.js.map +1 -0
- package/dist/js/tracing/integrations/appStart.d.ts.map +1 -1
- package/dist/js/tracing/integrations/appStart.js +4 -1
- package/dist/js/tracing/integrations/appStart.js.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.d.ts +7 -0
- package/dist/js/tracing/onSpanEndUtils.d.ts.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.js +45 -6
- package/dist/js/tracing/onSpanEndUtils.js.map +1 -1
- package/dist/js/tracing/reactnavigation.d.ts +15 -0
- package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnavigation.js +41 -13
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/tracing/span.d.ts +6 -6
- package/dist/js/tracing/span.d.ts.map +1 -1
- package/dist/js/tracing/span.js +3 -3
- package/dist/js/tracing/span.js.map +1 -1
- package/dist/js/utils/expoglobalobject.d.ts +47 -7
- package/dist/js/utils/expoglobalobject.d.ts.map +1 -1
- package/dist/js/utils/expoglobalobject.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.js +6 -3
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +1 -1
- package/dist/js/wrapper.js.map +1 -1
- package/ios/AGENTS.md +60 -0
- package/ios/RNSentry.mm +4 -1
- package/ios/RNSentryEvents.h +1 -0
- package/ios/RNSentryEvents.m +1 -0
- package/ios/RNSentryNativeLogsForwarder.h +20 -0
- package/ios/RNSentryNativeLogsForwarder.m +145 -0
- package/ios/RNSentryVersion.m +1 -1
- package/package.json +14 -11
- package/plugin/build/withSentryAndroidGradlePlugin.d.ts +1 -1
- package/plugin/build/withSentryAndroidGradlePlugin.js +1 -1
- package/scripts/eas-build-hook.js +234 -0
- package/scripts/sentry-xcode.sh +9 -2
- package/sentry.gradle +13 -5
- package/ts3.8/dist/js/NativeLogListener.d.ts +16 -0
- package/ts3.8/dist/js/client.d.ts +1 -0
- package/ts3.8/dist/js/index.d.ts +2 -2
- package/ts3.8/dist/js/integrations/expoconstants.d.ts +24 -0
- package/ts3.8/dist/js/integrations/exports.d.ts +1 -0
- package/ts3.8/dist/js/options.d.ts +26 -0
- package/ts3.8/dist/js/tracing/onSpanEndUtils.d.ts +7 -0
- package/ts3.8/dist/js/tracing/reactnavigation.d.ts +15 -0
- package/ts3.8/dist/js/tracing/span.d.ts +6 -6
- package/ts3.8/dist/js/utils/expoglobalobject.d.ts +47 -7
- package/ts3.8/dist/js/version.d.ts +1 -1
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* EAS Build Hooks for Sentry
|
|
4
|
+
*
|
|
5
|
+
* This module provides utilities for capturing EAS build lifecycle events
|
|
6
|
+
* and sending them to Sentry. It supports the following EAS npm hooks:
|
|
7
|
+
* - eas-build-on-error: Captures build failures
|
|
8
|
+
* - eas-build-on-success: Captures successful builds (optional)
|
|
9
|
+
* - eas-build-on-complete: Captures build completion with metrics
|
|
10
|
+
*
|
|
11
|
+
* @see https://docs.expo.dev/build-reference/npm-hooks/
|
|
12
|
+
*/
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.captureEASBuildComplete = exports.captureEASBuildSuccess = exports.captureEASBuildError = exports.getEASBuildEnv = exports.isEASBuild = void 0;
|
|
24
|
+
const core_1 = require("@sentry/core");
|
|
25
|
+
const version_1 = require("../version");
|
|
26
|
+
const SENTRY_DSN_ENV = 'SENTRY_DSN';
|
|
27
|
+
const EAS_BUILD_ENV = 'EAS_BUILD';
|
|
28
|
+
/** Checks if the current environment is an EAS Build. */
|
|
29
|
+
function isEASBuild() {
|
|
30
|
+
return process.env[EAS_BUILD_ENV] === 'true';
|
|
31
|
+
}
|
|
32
|
+
exports.isEASBuild = isEASBuild;
|
|
33
|
+
/** Gets the EAS build environment variables. */
|
|
34
|
+
function getEASBuildEnv() {
|
|
35
|
+
return {
|
|
36
|
+
EAS_BUILD: process.env.EAS_BUILD,
|
|
37
|
+
EAS_BUILD_ID: process.env.EAS_BUILD_ID,
|
|
38
|
+
EAS_BUILD_PLATFORM: process.env.EAS_BUILD_PLATFORM,
|
|
39
|
+
EAS_BUILD_PROFILE: process.env.EAS_BUILD_PROFILE,
|
|
40
|
+
EAS_BUILD_PROJECT_ID: process.env.EAS_BUILD_PROJECT_ID,
|
|
41
|
+
EAS_BUILD_GIT_COMMIT_HASH: process.env.EAS_BUILD_GIT_COMMIT_HASH,
|
|
42
|
+
EAS_BUILD_RUN_FROM_CI: process.env.EAS_BUILD_RUN_FROM_CI,
|
|
43
|
+
EAS_BUILD_STATUS: process.env.EAS_BUILD_STATUS,
|
|
44
|
+
EAS_BUILD_APP_VERSION: process.env.EAS_BUILD_APP_VERSION,
|
|
45
|
+
EAS_BUILD_APP_BUILD_VERSION: process.env.EAS_BUILD_APP_BUILD_VERSION,
|
|
46
|
+
EAS_BUILD_USERNAME: process.env.EAS_BUILD_USERNAME,
|
|
47
|
+
EAS_BUILD_WORKINGDIR: process.env.EAS_BUILD_WORKINGDIR,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
exports.getEASBuildEnv = getEASBuildEnv;
|
|
51
|
+
function getEnvelopeEndpoint(dsn) {
|
|
52
|
+
const { protocol, host, port, path, projectId, publicKey } = dsn;
|
|
53
|
+
const portStr = port ? `:${port}` : '';
|
|
54
|
+
const pathStr = path ? `/${path}` : '';
|
|
55
|
+
return `${protocol}://${host}${portStr}${pathStr}/api/${projectId}/envelope/?sentry_key=${publicKey}&sentry_version=7`;
|
|
56
|
+
}
|
|
57
|
+
function createEASBuildTags(env) {
|
|
58
|
+
const tags = {};
|
|
59
|
+
if (env.EAS_BUILD_PLATFORM)
|
|
60
|
+
tags['eas.platform'] = env.EAS_BUILD_PLATFORM;
|
|
61
|
+
if (env.EAS_BUILD_PROFILE)
|
|
62
|
+
tags['eas.profile'] = env.EAS_BUILD_PROFILE;
|
|
63
|
+
if (env.EAS_BUILD_ID)
|
|
64
|
+
tags['eas.build_id'] = env.EAS_BUILD_ID;
|
|
65
|
+
if (env.EAS_BUILD_PROJECT_ID)
|
|
66
|
+
tags['eas.project_id'] = env.EAS_BUILD_PROJECT_ID;
|
|
67
|
+
if (env.EAS_BUILD_RUN_FROM_CI)
|
|
68
|
+
tags['eas.from_ci'] = env.EAS_BUILD_RUN_FROM_CI;
|
|
69
|
+
if (env.EAS_BUILD_STATUS)
|
|
70
|
+
tags['eas.status'] = env.EAS_BUILD_STATUS;
|
|
71
|
+
if (env.EAS_BUILD_USERNAME)
|
|
72
|
+
tags['eas.username'] = env.EAS_BUILD_USERNAME;
|
|
73
|
+
return tags;
|
|
74
|
+
}
|
|
75
|
+
function createEASBuildContext(env) {
|
|
76
|
+
return {
|
|
77
|
+
build_id: env.EAS_BUILD_ID,
|
|
78
|
+
platform: env.EAS_BUILD_PLATFORM,
|
|
79
|
+
profile: env.EAS_BUILD_PROFILE,
|
|
80
|
+
project_id: env.EAS_BUILD_PROJECT_ID,
|
|
81
|
+
git_commit: env.EAS_BUILD_GIT_COMMIT_HASH,
|
|
82
|
+
from_ci: env.EAS_BUILD_RUN_FROM_CI === 'true',
|
|
83
|
+
status: env.EAS_BUILD_STATUS,
|
|
84
|
+
app_version: env.EAS_BUILD_APP_VERSION,
|
|
85
|
+
build_version: env.EAS_BUILD_APP_BUILD_VERSION,
|
|
86
|
+
username: env.EAS_BUILD_USERNAME,
|
|
87
|
+
working_dir: env.EAS_BUILD_WORKINGDIR,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function createEnvelope(event, dsn) {
|
|
91
|
+
const envelopeHeaders = JSON.stringify({
|
|
92
|
+
event_id: event.event_id,
|
|
93
|
+
sent_at: new Date().toISOString(),
|
|
94
|
+
dsn: (0, core_1.dsnToString)(dsn),
|
|
95
|
+
sdk: event.sdk,
|
|
96
|
+
});
|
|
97
|
+
const itemHeaders = JSON.stringify({ type: 'event', content_type: 'application/json' });
|
|
98
|
+
const itemPayload = JSON.stringify(event);
|
|
99
|
+
return `${envelopeHeaders}\n${itemHeaders}\n${itemPayload}`;
|
|
100
|
+
}
|
|
101
|
+
function sendEvent(event, dsn) {
|
|
102
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
103
|
+
const endpoint = getEnvelopeEndpoint(dsn);
|
|
104
|
+
const envelope = createEnvelope(event, dsn);
|
|
105
|
+
try {
|
|
106
|
+
const response = yield fetch(endpoint, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { 'Content-Type': 'application/x-sentry-envelope' },
|
|
109
|
+
body: envelope,
|
|
110
|
+
});
|
|
111
|
+
if (response.status >= 200 && response.status < 300)
|
|
112
|
+
return true;
|
|
113
|
+
console.warn(`[Sentry] Failed to send event: HTTP ${response.status}`);
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
console.error('[Sentry] Failed to send event:', error);
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function getReleaseFromEASEnv(env) {
|
|
123
|
+
// Honour explicit override first
|
|
124
|
+
if (process.env.SENTRY_RELEASE) {
|
|
125
|
+
return process.env.SENTRY_RELEASE;
|
|
126
|
+
}
|
|
127
|
+
// Best approximation without bundle identifier: version+buildNumber
|
|
128
|
+
if (env.EAS_BUILD_APP_VERSION && env.EAS_BUILD_APP_BUILD_VERSION) {
|
|
129
|
+
return `${env.EAS_BUILD_APP_VERSION}+${env.EAS_BUILD_APP_BUILD_VERSION}`;
|
|
130
|
+
}
|
|
131
|
+
return env.EAS_BUILD_APP_VERSION;
|
|
132
|
+
}
|
|
133
|
+
function createBaseEvent(level, env, customTags) {
|
|
134
|
+
return {
|
|
135
|
+
event_id: (0, core_1.uuid4)(),
|
|
136
|
+
timestamp: Date.now() / 1000,
|
|
137
|
+
platform: 'node',
|
|
138
|
+
level,
|
|
139
|
+
logger: 'eas-build-hook',
|
|
140
|
+
environment: 'eas-build',
|
|
141
|
+
release: getReleaseFromEASEnv(env),
|
|
142
|
+
tags: Object.assign(Object.assign({}, createEASBuildTags(env)), customTags),
|
|
143
|
+
contexts: { eas_build: createEASBuildContext(env), runtime: { name: 'node', version: process.version } },
|
|
144
|
+
sdk: { name: 'sentry.javascript.react-native.eas-build-hooks', version: version_1.SDK_VERSION },
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
/** Captures an EAS build error event. Call this from the eas-build-on-error hook. */
|
|
148
|
+
function captureEASBuildError(options = {}) {
|
|
149
|
+
var _a, _b, _c, _d, _e, _f;
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
const dsnString = (_a = options.dsn) !== null && _a !== void 0 ? _a : process.env[SENTRY_DSN_ENV];
|
|
152
|
+
if (!dsnString) {
|
|
153
|
+
console.warn('[Sentry] No DSN provided. Set SENTRY_DSN environment variable or pass dsn option.');
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (!isEASBuild()) {
|
|
157
|
+
console.warn('[Sentry] Not running in EAS Build environment. Skipping error capture.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const dsn = (0, core_1.makeDsn)(dsnString);
|
|
161
|
+
if (!dsn) {
|
|
162
|
+
console.error('[Sentry] Invalid DSN format.');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const env = getEASBuildEnv();
|
|
166
|
+
const errorMessage = (_b = options.errorMessage) !== null && _b !== void 0 ? _b : `EAS Build Failed: ${(_c = env.EAS_BUILD_PLATFORM) !== null && _c !== void 0 ? _c : 'unknown'} (${(_d = env.EAS_BUILD_PROFILE) !== null && _d !== void 0 ? _d : 'unknown'})`;
|
|
167
|
+
const event = createBaseEvent('error', env, Object.assign(Object.assign({}, options.tags), { 'eas.hook': 'on-error' }));
|
|
168
|
+
event.exception = {
|
|
169
|
+
values: [{ type: 'EASBuildError', value: errorMessage, mechanism: { type: 'eas-build-hook', handled: true } }],
|
|
170
|
+
};
|
|
171
|
+
event.fingerprint = ['eas-build-error', (_e = env.EAS_BUILD_PLATFORM) !== null && _e !== void 0 ? _e : 'unknown', (_f = env.EAS_BUILD_PROFILE) !== null && _f !== void 0 ? _f : 'unknown'];
|
|
172
|
+
const success = yield sendEvent(event, dsn);
|
|
173
|
+
if (success)
|
|
174
|
+
console.log('[Sentry] Build error captured.');
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
exports.captureEASBuildError = captureEASBuildError;
|
|
178
|
+
/** Captures an EAS build success event. Call this from the eas-build-on-success hook. */
|
|
179
|
+
function captureEASBuildSuccess(options = {}) {
|
|
180
|
+
var _a, _b, _c, _d, _e, _f;
|
|
181
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
182
|
+
if (!options.captureSuccessfulBuilds) {
|
|
183
|
+
console.log('[Sentry] Skipping successful build capture (captureSuccessfulBuilds is false).');
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const dsnString = (_a = options.dsn) !== null && _a !== void 0 ? _a : process.env[SENTRY_DSN_ENV];
|
|
187
|
+
if (!dsnString) {
|
|
188
|
+
console.warn('[Sentry] No DSN provided. Set SENTRY_DSN environment variable or pass dsn option.');
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (!isEASBuild()) {
|
|
192
|
+
console.warn('[Sentry] Not running in EAS Build environment. Skipping success capture.');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const dsn = (0, core_1.makeDsn)(dsnString);
|
|
196
|
+
if (!dsn) {
|
|
197
|
+
console.error('[Sentry] Invalid DSN format.');
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const env = getEASBuildEnv();
|
|
201
|
+
const successMessage = (_b = options.successMessage) !== null && _b !== void 0 ? _b : `EAS Build Succeeded: ${(_c = env.EAS_BUILD_PLATFORM) !== null && _c !== void 0 ? _c : 'unknown'} (${(_d = env.EAS_BUILD_PROFILE) !== null && _d !== void 0 ? _d : 'unknown'})`;
|
|
202
|
+
const event = createBaseEvent('info', env, Object.assign(Object.assign({}, options.tags), { 'eas.hook': 'on-success' }));
|
|
203
|
+
event.message = { formatted: successMessage };
|
|
204
|
+
event.fingerprint = ['eas-build-success', (_e = env.EAS_BUILD_PLATFORM) !== null && _e !== void 0 ? _e : 'unknown', (_f = env.EAS_BUILD_PROFILE) !== null && _f !== void 0 ? _f : 'unknown'];
|
|
205
|
+
const success = yield sendEvent(event, dsn);
|
|
206
|
+
if (success)
|
|
207
|
+
console.log('[Sentry] Build success captured.');
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
exports.captureEASBuildSuccess = captureEASBuildSuccess;
|
|
211
|
+
/** Captures an EAS build completion event with status. Call this from the eas-build-on-complete hook. */
|
|
212
|
+
function captureEASBuildComplete(options = {}) {
|
|
213
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
214
|
+
const env = getEASBuildEnv();
|
|
215
|
+
const status = env.EAS_BUILD_STATUS;
|
|
216
|
+
if (status === 'errored') {
|
|
217
|
+
yield captureEASBuildError(options);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (status === 'finished' && options.captureSuccessfulBuilds) {
|
|
221
|
+
yield captureEASBuildSuccess(Object.assign(Object.assign({}, options), { captureSuccessfulBuilds: true }));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
console.log(`[Sentry] Build completed with status: ${status !== null && status !== void 0 ? status : 'unknown'}. No event captured.`);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
exports.captureEASBuildComplete = captureEASBuildComplete;
|
|
228
|
+
//# sourceMappingURL=easBuildHooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easBuildHooks.js","sourceRoot":"","sources":["../../../src/js/tools/easBuildHooks.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * EAS Build Hooks for Sentry\n *\n * This module provides utilities for capturing EAS build lifecycle events\n * and sending them to Sentry. It supports the following EAS npm hooks:\n * - eas-build-on-error: Captures build failures\n * - eas-build-on-success: Captures successful builds (optional)\n * - eas-build-on-complete: Captures build completion with metrics\n *\n * @see https://docs.expo.dev/build-reference/npm-hooks/\n */\n\n/* eslint-disable no-console */\n\nimport type { DsnComponents } from '@sentry/core';\nimport { dsnToString, makeDsn, uuid4 } from '@sentry/core';\nimport { SDK_VERSION } from '../version';\n\nconst SENTRY_DSN_ENV = 'SENTRY_DSN';\nconst EAS_BUILD_ENV = 'EAS_BUILD';\n\n/**\n * Environment variables provided by EAS Build.\n * @see https://docs.expo.dev/build-reference/variables/\n */\nexport interface EASBuildEnv {\n EAS_BUILD?: string;\n EAS_BUILD_ID?: string;\n EAS_BUILD_PLATFORM?: string;\n EAS_BUILD_PROFILE?: string;\n EAS_BUILD_PROJECT_ID?: string;\n EAS_BUILD_GIT_COMMIT_HASH?: string;\n EAS_BUILD_RUN_FROM_CI?: string;\n EAS_BUILD_STATUS?: string;\n EAS_BUILD_APP_VERSION?: string;\n EAS_BUILD_APP_BUILD_VERSION?: string;\n EAS_BUILD_USERNAME?: string;\n EAS_BUILD_WORKINGDIR?: string;\n}\n\n/** Options for configuring EAS build hook behavior. */\nexport interface EASBuildHookOptions {\n dsn?: string;\n tags?: Record<string, string>;\n captureSuccessfulBuilds?: boolean;\n errorMessage?: string;\n successMessage?: string;\n}\n\ninterface SentryEvent {\n event_id: string;\n timestamp: number;\n platform: string;\n level: 'error' | 'info' | 'warning';\n logger: string;\n environment: string;\n release?: string;\n tags: Record<string, string>;\n contexts: Record<string, Record<string, unknown>>;\n message?: { formatted: string };\n exception?: {\n values: Array<{ type: string; value: string; mechanism: { type: string; handled: boolean } }>;\n };\n fingerprint?: string[];\n sdk: { name: string; version: string };\n}\n\n/** Checks if the current environment is an EAS Build. */\nexport function isEASBuild(): boolean {\n return process.env[EAS_BUILD_ENV] === 'true';\n}\n\n/** Gets the EAS build environment variables. */\nexport function getEASBuildEnv(): EASBuildEnv {\n return {\n EAS_BUILD: process.env.EAS_BUILD,\n EAS_BUILD_ID: process.env.EAS_BUILD_ID,\n EAS_BUILD_PLATFORM: process.env.EAS_BUILD_PLATFORM,\n EAS_BUILD_PROFILE: process.env.EAS_BUILD_PROFILE,\n EAS_BUILD_PROJECT_ID: process.env.EAS_BUILD_PROJECT_ID,\n EAS_BUILD_GIT_COMMIT_HASH: process.env.EAS_BUILD_GIT_COMMIT_HASH,\n EAS_BUILD_RUN_FROM_CI: process.env.EAS_BUILD_RUN_FROM_CI,\n EAS_BUILD_STATUS: process.env.EAS_BUILD_STATUS,\n EAS_BUILD_APP_VERSION: process.env.EAS_BUILD_APP_VERSION,\n EAS_BUILD_APP_BUILD_VERSION: process.env.EAS_BUILD_APP_BUILD_VERSION,\n EAS_BUILD_USERNAME: process.env.EAS_BUILD_USERNAME,\n EAS_BUILD_WORKINGDIR: process.env.EAS_BUILD_WORKINGDIR,\n };\n}\n\nfunction getEnvelopeEndpoint(dsn: DsnComponents): string {\n const { protocol, host, port, path, projectId, publicKey } = dsn;\n const portStr = port ? `:${port}` : '';\n const pathStr = path ? `/${path}` : '';\n return `${protocol}://${host}${portStr}${pathStr}/api/${projectId}/envelope/?sentry_key=${publicKey}&sentry_version=7`;\n}\n\nfunction createEASBuildTags(env: EASBuildEnv): Record<string, string> {\n const tags: Record<string, string> = {};\n if (env.EAS_BUILD_PLATFORM) tags['eas.platform'] = env.EAS_BUILD_PLATFORM;\n if (env.EAS_BUILD_PROFILE) tags['eas.profile'] = env.EAS_BUILD_PROFILE;\n if (env.EAS_BUILD_ID) tags['eas.build_id'] = env.EAS_BUILD_ID;\n if (env.EAS_BUILD_PROJECT_ID) tags['eas.project_id'] = env.EAS_BUILD_PROJECT_ID;\n if (env.EAS_BUILD_RUN_FROM_CI) tags['eas.from_ci'] = env.EAS_BUILD_RUN_FROM_CI;\n if (env.EAS_BUILD_STATUS) tags['eas.status'] = env.EAS_BUILD_STATUS;\n if (env.EAS_BUILD_USERNAME) tags['eas.username'] = env.EAS_BUILD_USERNAME;\n return tags;\n}\n\nfunction createEASBuildContext(env: EASBuildEnv): Record<string, unknown> {\n return {\n build_id: env.EAS_BUILD_ID,\n platform: env.EAS_BUILD_PLATFORM,\n profile: env.EAS_BUILD_PROFILE,\n project_id: env.EAS_BUILD_PROJECT_ID,\n git_commit: env.EAS_BUILD_GIT_COMMIT_HASH,\n from_ci: env.EAS_BUILD_RUN_FROM_CI === 'true',\n status: env.EAS_BUILD_STATUS,\n app_version: env.EAS_BUILD_APP_VERSION,\n build_version: env.EAS_BUILD_APP_BUILD_VERSION,\n username: env.EAS_BUILD_USERNAME,\n working_dir: env.EAS_BUILD_WORKINGDIR,\n };\n}\n\nfunction createEnvelope(event: SentryEvent, dsn: DsnComponents): string {\n const envelopeHeaders = JSON.stringify({\n event_id: event.event_id,\n sent_at: new Date().toISOString(),\n dsn: dsnToString(dsn),\n sdk: event.sdk,\n });\n const itemHeaders = JSON.stringify({ type: 'event', content_type: 'application/json' });\n const itemPayload = JSON.stringify(event);\n return `${envelopeHeaders}\\n${itemHeaders}\\n${itemPayload}`;\n}\n\nasync function sendEvent(event: SentryEvent, dsn: DsnComponents): Promise<boolean> {\n const endpoint = getEnvelopeEndpoint(dsn);\n const envelope = createEnvelope(event, dsn);\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-sentry-envelope' },\n body: envelope,\n });\n if (response.status >= 200 && response.status < 300) return true;\n console.warn(`[Sentry] Failed to send event: HTTP ${response.status}`);\n return false;\n } catch (error) {\n console.error('[Sentry] Failed to send event:', error);\n return false;\n }\n}\n\nfunction getReleaseFromEASEnv(env: EASBuildEnv): string | undefined {\n // Honour explicit override first\n if (process.env.SENTRY_RELEASE) {\n return process.env.SENTRY_RELEASE;\n }\n // Best approximation without bundle identifier: version+buildNumber\n if (env.EAS_BUILD_APP_VERSION && env.EAS_BUILD_APP_BUILD_VERSION) {\n return `${env.EAS_BUILD_APP_VERSION}+${env.EAS_BUILD_APP_BUILD_VERSION}`;\n }\n return env.EAS_BUILD_APP_VERSION;\n}\n\nfunction createBaseEvent(\n level: 'error' | 'info' | 'warning',\n env: EASBuildEnv,\n customTags?: Record<string, string>,\n): SentryEvent {\n return {\n event_id: uuid4(),\n timestamp: Date.now() / 1000,\n platform: 'node',\n level,\n logger: 'eas-build-hook',\n environment: 'eas-build',\n release: getReleaseFromEASEnv(env),\n tags: { ...createEASBuildTags(env), ...customTags },\n contexts: { eas_build: createEASBuildContext(env), runtime: { name: 'node', version: process.version } },\n sdk: { name: 'sentry.javascript.react-native.eas-build-hooks', version: SDK_VERSION },\n };\n}\n\n/** Captures an EAS build error event. Call this from the eas-build-on-error hook. */\nexport async function captureEASBuildError(options: EASBuildHookOptions = {}): Promise<void> {\n const dsnString = options.dsn ?? process.env[SENTRY_DSN_ENV];\n if (!dsnString) {\n console.warn('[Sentry] No DSN provided. Set SENTRY_DSN environment variable or pass dsn option.');\n return;\n }\n if (!isEASBuild()) {\n console.warn('[Sentry] Not running in EAS Build environment. Skipping error capture.');\n return;\n }\n const dsn = makeDsn(dsnString);\n if (!dsn) {\n console.error('[Sentry] Invalid DSN format.');\n return;\n }\n const env = getEASBuildEnv();\n const errorMessage =\n options.errorMessage ??\n `EAS Build Failed: ${env.EAS_BUILD_PLATFORM ?? 'unknown'} (${env.EAS_BUILD_PROFILE ?? 'unknown'})`;\n const event = createBaseEvent('error', env, { ...options.tags, 'eas.hook': 'on-error' });\n event.exception = {\n values: [{ type: 'EASBuildError', value: errorMessage, mechanism: { type: 'eas-build-hook', handled: true } }],\n };\n event.fingerprint = ['eas-build-error', env.EAS_BUILD_PLATFORM ?? 'unknown', env.EAS_BUILD_PROFILE ?? 'unknown'];\n const success = await sendEvent(event, dsn);\n if (success) console.log('[Sentry] Build error captured.');\n}\n\n/** Captures an EAS build success event. Call this from the eas-build-on-success hook. */\nexport async function captureEASBuildSuccess(options: EASBuildHookOptions = {}): Promise<void> {\n if (!options.captureSuccessfulBuilds) {\n console.log('[Sentry] Skipping successful build capture (captureSuccessfulBuilds is false).');\n return;\n }\n const dsnString = options.dsn ?? process.env[SENTRY_DSN_ENV];\n if (!dsnString) {\n console.warn('[Sentry] No DSN provided. Set SENTRY_DSN environment variable or pass dsn option.');\n return;\n }\n if (!isEASBuild()) {\n console.warn('[Sentry] Not running in EAS Build environment. Skipping success capture.');\n return;\n }\n const dsn = makeDsn(dsnString);\n if (!dsn) {\n console.error('[Sentry] Invalid DSN format.');\n return;\n }\n const env = getEASBuildEnv();\n const successMessage =\n options.successMessage ??\n `EAS Build Succeeded: ${env.EAS_BUILD_PLATFORM ?? 'unknown'} (${env.EAS_BUILD_PROFILE ?? 'unknown'})`;\n const event = createBaseEvent('info', env, { ...options.tags, 'eas.hook': 'on-success' });\n event.message = { formatted: successMessage };\n event.fingerprint = ['eas-build-success', env.EAS_BUILD_PLATFORM ?? 'unknown', env.EAS_BUILD_PROFILE ?? 'unknown'];\n const success = await sendEvent(event, dsn);\n if (success) console.log('[Sentry] Build success captured.');\n}\n\n/** Captures an EAS build completion event with status. Call this from the eas-build-on-complete hook. */\nexport async function captureEASBuildComplete(options: EASBuildHookOptions = {}): Promise<void> {\n const env = getEASBuildEnv();\n const status = env.EAS_BUILD_STATUS;\n if (status === 'errored') {\n await captureEASBuildError(options);\n return;\n }\n if (status === 'finished' && options.captureSuccessfulBuilds) {\n await captureEASBuildSuccess({ ...options, captureSuccessfulBuilds: true });\n return;\n }\n console.log(`[Sentry] Build completed with status: ${status ?? 'unknown'}. No event captured.`);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appStart.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,WAAW,EAAoC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"appStart.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,WAAW,EAAoC,MAAM,cAAc,CAAC;AAiBjG,OAAO,KAAK,EAA0B,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAgBzF,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG;IAC9C,yBAAyB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD,CAAC;AAeF,UAAU,eAAe;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACxC;AAQD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BzF;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAK7E;AAED;;;;GAIG;AACH,wBAAgB,oCAAoC,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAG9E;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,SAAU,eAAe,KAAG,IAG3D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAE7D;AAyBD;;GAEG;AACH,eAAO,MAAM,mBAAmB;IAG9B;;;;;OAKG;;MAEI,mBA8SR,CAAC"}
|
|
@@ -7,7 +7,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { debug, getCapturedScopesOnSpan, getClient, getCurrentScope, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SentryNonRecordingSpan, startInactiveSpan, timestampInSeconds, } from '@sentry/core';
|
|
10
|
+
import { debug, getCapturedScopesOnSpan, getClient, getCurrentScope, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SentryNonRecordingSpan, spanIsSampled, startInactiveSpan, timestampInSeconds, } from '@sentry/core';
|
|
11
11
|
import { getAppRegistryIntegration } from '../../integrations/appRegistry';
|
|
12
12
|
import { APP_START_COLD as APP_START_COLD_MEASUREMENT, APP_START_WARM as APP_START_WARM_MEASUREMENT, } from '../../measurements';
|
|
13
13
|
import { convertSpanToTransaction, isRootSpan, setEndTimeValue } from '../../utils/span';
|
|
@@ -182,6 +182,9 @@ export const appStartIntegration = ({ standalone = false, } = {}) => {
|
|
|
182
182
|
if (!isRootSpan(rootSpan)) {
|
|
183
183
|
return;
|
|
184
184
|
}
|
|
185
|
+
if (!spanIsSampled(rootSpan)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
185
188
|
setFirstStartedActiveRootSpanId(rootSpan.spanContext().spanId);
|
|
186
189
|
};
|
|
187
190
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appStart.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable complexity, max-lines */\nimport type { Client, Event, Integration, Span, SpanJSON, TransactionEvent } from '@sentry/core';\nimport {\n debug,\n getCapturedScopesOnSpan,\n getClient,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\nimport { getAppRegistryIntegration } from '../../integrations/appRegistry';\nimport {\n APP_START_COLD as APP_START_COLD_MEASUREMENT,\n APP_START_WARM as APP_START_WARM_MEASUREMENT,\n} from '../../measurements';\nimport type { NativeAppStartResponse, NativeFramesResponse } from '../../NativeRNSentry';\nimport type { ReactNativeClientOptions } from '../../options';\nimport { convertSpanToTransaction, isRootSpan, setEndTimeValue } from '../../utils/span';\nimport { NATIVE } from '../../wrapper';\nimport {\n APP_START_COLD as APP_START_COLD_OP,\n APP_START_WARM as APP_START_WARM_OP,\n UI_LOAD as UI_LOAD_OP,\n} from '../ops';\nimport { SPAN_ORIGIN_AUTO_APP_START, SPAN_ORIGIN_MANUAL_APP_START } from '../origin';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP } from '../semanticAttributes';\nimport { setMainThreadInfo } from '../span';\nimport { createChildSpanJSON, createSpanJSON, getBundleStartTimestampMs } from '../utils';\n\nconst INTEGRATION_NAME = 'AppStart';\n\nexport type AppStartIntegration = Integration & {\n captureStandaloneAppStart: () => Promise<void>;\n};\n\n/**\n * We filter out app start more than 60s.\n * This could be due to many different reasons.\n * We've seen app starts with hours, days and even months.\n */\nconst MAX_APP_START_DURATION_MS = 60_000;\n\n/** We filter out App starts which timestamp is 60s and more before the transaction start */\nconst MAX_APP_START_AGE_MS = 60_000;\n\n/** App Start transaction name */\nconst APP_START_TX_NAME = 'App Start';\n\ninterface AppStartEndData {\n timestampMs: number;\n endFrames: NativeFramesResponse | null;\n}\n\nlet appStartEndData: AppStartEndData | undefined = undefined;\nlet isRecordedAppStartEndTimestampMsManual = false;\n\nlet rootComponentCreationTimestampMs: number | undefined = undefined;\nlet isRootComponentCreationTimestampMsManual = false;\n\n/**\n * Records the application start end.\n * Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.\n */\nexport function captureAppStart(): Promise<void> {\n return _captureAppStart({ isManual: true });\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport async function _captureAppStart({ isManual }: { isManual: boolean }): Promise<void> {\n const client = getClient();\n if (!client) {\n debug.warn('[AppStart] Could not capture App Start, missing client.');\n return;\n }\n\n isRecordedAppStartEndTimestampMsManual = isManual;\n\n const timestampMs = timestampInSeconds() * 1000;\n let endFrames: NativeFramesResponse | null = null;\n\n if (NATIVE.enableNative) {\n try {\n endFrames = await NATIVE.fetchNativeFrames();\n debug.log('[AppStart] Captured end frames for app start.', endFrames);\n } catch (error) {\n debug.log('[AppStart] Failed to capture end frames for app start.', error);\n }\n }\n\n _setAppStartEndData({\n timestampMs,\n endFrames,\n });\n\n await client.getIntegrationByName<AppStartIntegration>(INTEGRATION_NAME)?.captureStandaloneAppStart();\n}\n\n/**\n * Sets the root component first constructor call timestamp.\n * Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.\n */\nexport function setRootComponentCreationTimestampMs(timestampMs: number): void {\n appStartEndData?.timestampMs && debug.warn('Setting Root component creation timestamp after app start end is set.');\n rootComponentCreationTimestampMs && debug.warn('Overwriting already set root component creation timestamp.');\n rootComponentCreationTimestampMs = timestampMs;\n isRootComponentCreationTimestampMsManual = true;\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport function _setRootComponentCreationTimestampMs(timestampMs: number): void {\n setRootComponentCreationTimestampMs(timestampMs);\n isRootComponentCreationTimestampMsManual = false;\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport const _setAppStartEndData = (data: AppStartEndData): void => {\n appStartEndData && debug.warn('Overwriting already set app start end data.');\n appStartEndData = data;\n};\n\n/**\n * For testing purposes only.\n *\n * @private\n */\nexport function _clearRootComponentCreationTimestampMs(): void {\n rootComponentCreationTimestampMs = undefined;\n}\n\n/**\n * Attaches frame data to a span's data object.\n */\nfunction attachFrameDataToSpan(span: SpanJSON, frames: NativeFramesResponse): void {\n if (frames.totalFrames <= 0 && frames.slowFrames <= 0 && frames.totalFrames <= 0) {\n debug.warn(`[AppStart] Detected zero slow or frozen frames. Not adding measurements to spanId (${span.span_id}).`);\n return;\n }\n span.data = span.data || {};\n span.data['frames.total'] = frames.totalFrames;\n span.data['frames.slow'] = frames.slowFrames;\n span.data['frames.frozen'] = frames.frozenFrames;\n\n debug.log('[AppStart] Attached frame data to span.', {\n spanId: span.span_id,\n frameData: {\n total: frames.totalFrames,\n slow: frames.slowFrames,\n frozen: frames.frozenFrames,\n },\n });\n}\n\n/**\n * Adds AppStart spans from the native layer to the transaction event.\n */\nexport const appStartIntegration = ({\n standalone = false,\n}: {\n /**\n * Should the integration send App Start as a standalone root span (transaction)?\n * If false, App Start will be added as a child span to the first transaction.\n *\n * @default false\n */\n standalone?: boolean;\n} = {}): AppStartIntegration => {\n let _client: Client | undefined = undefined;\n let isEnabled = true;\n let appStartDataFlushed = false;\n let afterAllSetupCalled = false;\n let firstStartedActiveRootSpanId: string | undefined = undefined;\n\n const setup = (client: Client): void => {\n _client = client;\n const { enableAppStartTracking } = client.getOptions() as ReactNativeClientOptions;\n\n if (!enableAppStartTracking) {\n isEnabled = false;\n debug.warn('[AppStart] App start tracking is disabled.');\n }\n\n client.on('spanStart', recordFirstStartedActiveRootSpanId);\n };\n\n const afterAllSetup = (client: Client): void => {\n if (afterAllSetupCalled) {\n return;\n }\n afterAllSetupCalled = true;\n\n // TODO: automatically set standalone based on the presence of the native layer navigation integration\n\n getAppRegistryIntegration(client)?.onRunApplication(() => {\n if (appStartDataFlushed) {\n debug.log('[AppStartIntegration] Resetting app start data flushed flag based on runApplication call.');\n appStartDataFlushed = false;\n firstStartedActiveRootSpanId = undefined;\n } else {\n debug.log(\n '[AppStartIntegration] Waiting for initial app start was flush, before updating based on runApplication call.',\n );\n }\n });\n };\n\n const processEvent = async (event: Event): Promise<Event> => {\n if (!isEnabled || standalone) {\n return event;\n }\n\n if (event.type !== 'transaction') {\n // App start data is only relevant for transactions\n return event;\n }\n\n await attachAppStartToTransactionEvent(event as TransactionEvent);\n\n return event;\n };\n\n const recordFirstStartedActiveRootSpanId = (rootSpan: Span): void => {\n if (firstStartedActiveRootSpanId) {\n return;\n }\n\n if (!isRootSpan(rootSpan)) {\n return;\n }\n\n setFirstStartedActiveRootSpanId(rootSpan.spanContext().spanId);\n };\n\n /**\n * For testing purposes only.\n * @private\n */\n const setFirstStartedActiveRootSpanId = (spanId: string | undefined): void => {\n firstStartedActiveRootSpanId = spanId;\n debug.log('[AppStart] First started active root span id recorded.', firstStartedActiveRootSpanId);\n };\n\n async function captureStandaloneAppStart(): Promise<void> {\n if (!_client) {\n // If client is not set, SDK was not initialized, logger is thus disabled\n // eslint-disable-next-line no-console\n console.warn('[AppStart] Could not capture App Start, missing client, call `Sentry.init` first.');\n return;\n }\n\n if (!standalone) {\n debug.log(\n '[AppStart] App start tracking is enabled. App start will be added to the first transaction as a child span.',\n );\n return;\n }\n\n debug.log('[AppStart] App start tracking standalone root span (transaction).');\n\n if (!appStartEndData?.endFrames && NATIVE.enableNative) {\n try {\n const endFrames = await NATIVE.fetchNativeFrames();\n debug.log('[AppStart] Captured end frames for standalone app start.', endFrames);\n\n const currentTimestamp = appStartEndData?.timestampMs || timestampInSeconds() * 1000;\n _setAppStartEndData({\n timestampMs: currentTimestamp,\n endFrames,\n });\n } catch (error) {\n debug.log('[AppStart] Failed to capture frames for standalone app start.', error);\n }\n }\n\n const span = startInactiveSpan({\n forceTransaction: true,\n name: APP_START_TX_NAME,\n op: UI_LOAD_OP,\n });\n if (span instanceof SentryNonRecordingSpan) {\n // Tracing is disabled or the transaction was sampled\n return;\n }\n\n setEndTimeValue(span, timestampInSeconds());\n _client.emit('spanEnd', span);\n\n const event = convertSpanToTransaction(span);\n if (!event) {\n debug.warn('[AppStart] Failed to convert App Start span to transaction.');\n return;\n }\n\n await attachAppStartToTransactionEvent(event);\n if (!event.spans || event.spans.length === 0) {\n // No spans were added to the transaction, so we don't need to send it\n return;\n }\n\n const scope = getCapturedScopesOnSpan(span).scope || getCurrentScope();\n scope.captureEvent(event);\n }\n\n async function attachAppStartToTransactionEvent(event: TransactionEvent): Promise<void> {\n if (appStartDataFlushed) {\n // App start data is only relevant for the first transaction of the app run\n return;\n }\n\n if (!event.contexts?.trace) {\n debug.warn('[AppStart] Transaction event is missing trace context. Can not attach app start.');\n return;\n }\n\n // When standalone is true, we create our own transaction and don't need to verify\n // it matches the first navigation transaction. When standalone is false, we need to\n // ensure we're attaching app start to the first transaction (not a later one).\n if (!standalone) {\n if (!firstStartedActiveRootSpanId) {\n debug.warn('[AppStart] No first started active root span id recorded. Can not attach app start.');\n return;\n }\n\n if (firstStartedActiveRootSpanId !== event.contexts.trace.span_id) {\n debug.warn(\n '[AppStart] First started active root span id does not match the transaction event span id. Can not attached app start.',\n );\n return;\n }\n }\n\n const appStart = await NATIVE.fetchNativeAppStart();\n if (!appStart) {\n debug.warn('[AppStart] Failed to retrieve the app start metrics from the native layer.');\n return;\n }\n if (appStart.has_fetched) {\n debug.warn('[AppStart] Measured app start metrics were already reported from the native layer.');\n return;\n }\n\n const appStartTimestampMs = appStart.app_start_timestamp_ms;\n if (!appStartTimestampMs) {\n debug.warn('[AppStart] App start timestamp could not be loaded from the native layer.');\n return;\n }\n\n const appStartEndTimestampMs = appStartEndData?.timestampMs || getBundleStartTimestampMs();\n if (!appStartEndTimestampMs) {\n debug.warn(\n '[AppStart] Javascript failed to record app start end. `_setAppStartEndData` was not called nor could the bundle start be found.',\n );\n return;\n }\n\n const isAppStartWithinBounds =\n !!event.start_timestamp && appStartTimestampMs >= event.start_timestamp * 1_000 - MAX_APP_START_AGE_MS;\n if (!__DEV__ && !isAppStartWithinBounds) {\n debug.warn('[AppStart] App start timestamp is too far in the past to be used for app start span.');\n return;\n }\n\n const appStartDurationMs = appStartEndTimestampMs - appStartTimestampMs;\n if (!__DEV__ && appStartDurationMs >= MAX_APP_START_DURATION_MS) {\n // Dev builds can have long app start waiting over minute for the first bundle to be produced\n debug.warn('[AppStart] App start duration is over a minute long, not adding app start span.');\n return;\n }\n\n if (appStartDurationMs < 0) {\n // This can happen when MainActivity on Android is recreated,\n // and the app start end timestamp is not updated, for example\n // due to missing `Sentry.wrap(RootComponent)` call.\n debug.warn(\n '[AppStart] Last recorded app start end timestamp is before the app start timestamp.',\n 'This is usually caused by missing `Sentry.wrap(RootComponent)` call.',\n );\n return;\n }\n\n appStartDataFlushed = true;\n\n event.contexts.trace.data = event.contexts.trace.data || {};\n event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = UI_LOAD_OP;\n event.contexts.trace.op = UI_LOAD_OP;\n\n const origin = isRecordedAppStartEndTimestampMsManual ? SPAN_ORIGIN_MANUAL_APP_START : SPAN_ORIGIN_AUTO_APP_START;\n event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = origin;\n event.contexts.trace.origin = origin;\n\n const appStartTimestampSeconds = appStartTimestampMs / 1000;\n event.start_timestamp = appStartTimestampSeconds;\n\n event.spans = event.spans || [];\n /** event.spans reference */\n const children: SpanJSON[] = event.spans;\n\n const maybeTtidSpan = children.find(({ op }) => op === 'ui.load.initial_display');\n if (maybeTtidSpan) {\n maybeTtidSpan.start_timestamp = appStartTimestampSeconds;\n setSpanDurationAsMeasurementOnTransactionEvent(event, 'time_to_initial_display', maybeTtidSpan);\n }\n\n const maybeTtfdSpan = children.find(({ op }) => op === 'ui.load.full_display');\n if (maybeTtfdSpan) {\n maybeTtfdSpan.start_timestamp = appStartTimestampSeconds;\n setSpanDurationAsMeasurementOnTransactionEvent(event, 'time_to_full_display', maybeTtfdSpan);\n }\n\n const appStartEndTimestampSeconds = appStartEndTimestampMs / 1000;\n if (event.timestamp && event.timestamp < appStartEndTimestampSeconds) {\n debug.log(\n '[AppStart] Transaction event timestamp is before app start end. Adjusting transaction event timestamp.',\n );\n event.timestamp = appStartEndTimestampSeconds;\n }\n\n const op = appStart.type === 'cold' ? APP_START_COLD_OP : APP_START_WARM_OP;\n const appStartSpanJSON: SpanJSON = createSpanJSON({\n op,\n description: appStart.type === 'cold' ? 'Cold Start' : 'Warm Start',\n start_timestamp: appStartTimestampSeconds,\n timestamp: appStartEndTimestampSeconds,\n trace_id: event.contexts.trace.trace_id,\n parent_span_id: event.contexts.trace.span_id,\n origin,\n });\n\n if (appStartEndData?.endFrames) {\n attachFrameDataToSpan(appStartSpanJSON, appStartEndData.endFrames);\n }\n\n const jsExecutionSpanJSON = createJSExecutionStartSpan(appStartSpanJSON, rootComponentCreationTimestampMs);\n\n const appStartSpans = [\n appStartSpanJSON,\n ...(jsExecutionSpanJSON ? [jsExecutionSpanJSON] : []),\n ...convertNativeSpansToSpanJSON(appStartSpanJSON, appStart.spans),\n ];\n\n children.push(...appStartSpans);\n debug.log('[AppStart] Added app start spans to transaction event.', JSON.stringify(appStartSpans, undefined, 2));\n\n const measurementKey = appStart.type === 'cold' ? APP_START_COLD_MEASUREMENT : APP_START_WARM_MEASUREMENT;\n const measurementValue = {\n value: appStartDurationMs,\n unit: 'millisecond',\n };\n event.measurements = event.measurements || {};\n event.measurements[measurementKey] = measurementValue;\n debug.log(\n '[AppStart] Added app start measurement to transaction event.',\n JSON.stringify(measurementValue, undefined, 2),\n );\n }\n\n return {\n name: INTEGRATION_NAME,\n setup,\n afterAllSetup,\n processEvent,\n captureStandaloneAppStart,\n setFirstStartedActiveRootSpanId,\n } as AppStartIntegration;\n};\n\nfunction setSpanDurationAsMeasurementOnTransactionEvent(event: TransactionEvent, label: string, span: SpanJSON): void {\n if (!span.timestamp || !span.start_timestamp) {\n debug.warn('Span is missing start or end timestamp. Cam not set measurement on transaction event.');\n return;\n }\n\n event.measurements = event.measurements || {};\n event.measurements[label] = {\n value: (span.timestamp - span.start_timestamp) * 1000,\n unit: 'millisecond',\n };\n}\n\n/**\n * Adds JS Execution before React Root. If `Sentry.wrap` is not used, create a span for the start of JS Bundle execution.\n */\nfunction createJSExecutionStartSpan(\n parentSpan: SpanJSON,\n rootComponentCreationTimestampMs: number | undefined,\n): SpanJSON | undefined {\n const bundleStartTimestampMs = getBundleStartTimestampMs();\n if (!bundleStartTimestampMs) {\n return undefined;\n }\n\n const bundleStartTimestampSeconds = bundleStartTimestampMs / 1000;\n if (bundleStartTimestampSeconds < parentSpan.start_timestamp) {\n debug.warn('Bundle start timestamp is before the app start span start timestamp. Skipping JS execution span.');\n return undefined;\n }\n\n if (!rootComponentCreationTimestampMs) {\n debug.warn('Missing the root component first constructor call timestamp.');\n return createChildSpanJSON(parentSpan, {\n description: 'JS Bundle Execution Start',\n start_timestamp: bundleStartTimestampSeconds,\n timestamp: bundleStartTimestampSeconds,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n }\n\n return createChildSpanJSON(parentSpan, {\n description: 'JS Bundle Execution Before React Root',\n start_timestamp: bundleStartTimestampSeconds,\n timestamp: rootComponentCreationTimestampMs / 1000,\n origin: isRootComponentCreationTimestampMsManual ? SPAN_ORIGIN_MANUAL_APP_START : SPAN_ORIGIN_AUTO_APP_START,\n });\n}\n\n/**\n * Adds native spans to the app start span.\n */\nfunction convertNativeSpansToSpanJSON(parentSpan: SpanJSON, nativeSpans: NativeAppStartResponse['spans']): SpanJSON[] {\n return nativeSpans\n .filter(span => span.start_timestamp_ms / 1000 >= parentSpan.start_timestamp)\n .map(span => {\n if (span.description === 'UIKit init') {\n return setMainThreadInfo(createUIKitSpan(parentSpan, span));\n }\n\n return setMainThreadInfo(\n createChildSpanJSON(parentSpan, {\n description: span.description,\n start_timestamp: span.start_timestamp_ms / 1000,\n timestamp: span.end_timestamp_ms / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n }),\n );\n });\n}\n\n/**\n * UIKit init is measured by the native layers till the native SDK start\n * RN initializes the native SDK later, the end timestamp would be wrong\n */\nfunction createUIKitSpan(parentSpan: SpanJSON, nativeUIKitSpan: NativeAppStartResponse['spans'][number]): SpanJSON {\n const bundleStart = getBundleStartTimestampMs();\n\n // If UIKit init ends after the bundle start, the native SDK was auto-initialized\n // and so the end timestamp is incorrect.\n // The timestamps can't equal, as RN initializes after UIKit.\n if (bundleStart && bundleStart < nativeUIKitSpan.end_timestamp_ms) {\n return createChildSpanJSON(parentSpan, {\n description: 'UIKit Init to JS Exec Start',\n start_timestamp: nativeUIKitSpan.start_timestamp_ms / 1000,\n timestamp: bundleStart / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n } else {\n return createChildSpanJSON(parentSpan, {\n description: 'UIKit Init',\n start_timestamp: nativeUIKitSpan.start_timestamp_ms / 1000,\n timestamp: nativeUIKitSpan.end_timestamp_ms / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"appStart.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/appStart.ts"],"names":[],"mappings":";;;;;;;;;AAEA,OAAO,EACL,KAAK,EACL,uBAAuB,EACvB,SAAS,EACT,eAAe,EACf,gCAAgC,EAChC,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EACL,cAAc,IAAI,0BAA0B,EAC5C,cAAc,IAAI,0BAA0B,GAC7C,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAE,wBAAwB,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EACL,cAAc,IAAI,iBAAiB,EACnC,cAAc,IAAI,iBAAiB,EACnC,OAAO,IAAI,UAAU,GACtB,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,WAAW,CAAC;AACrF,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,UAAU,CAAC;AAE1F,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAMpC;;;;GAIG;AACH,MAAM,yBAAyB,GAAG,KAAM,CAAC;AAEzC,4FAA4F;AAC5F,MAAM,oBAAoB,GAAG,KAAM,CAAC;AAEpC,iCAAiC;AACjC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAOtC,IAAI,eAAe,GAAgC,SAAS,CAAC;AAC7D,IAAI,sCAAsC,GAAG,KAAK,CAAC;AAEnD,IAAI,gCAAgC,GAAuB,SAAS,CAAC;AACrE,IAAI,wCAAwC,GAAG,KAAK,CAAC;AAErD;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,gBAAgB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAyB;;;QACxE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE;YACX,KAAK,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;YACtE,OAAO;SACR;QAED,sCAAsC,GAAG,QAAQ,CAAC;QAElD,MAAM,WAAW,GAAG,kBAAkB,EAAE,GAAG,IAAI,CAAC;QAChD,IAAI,SAAS,GAAgC,IAAI,CAAC;QAElD,IAAI,MAAM,CAAC,YAAY,EAAE;YACvB,IAAI;gBACF,SAAS,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;gBAC7C,KAAK,CAAC,GAAG,CAAC,+CAA+C,EAAE,SAAS,CAAC,CAAC;aACvE;YAAC,OAAO,KAAK,EAAE;gBACd,KAAK,CAAC,GAAG,CAAC,wDAAwD,EAAE,KAAK,CAAC,CAAC;aAC5E;SACF;QAED,mBAAmB,CAAC;YAClB,WAAW;YACX,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,CAAA,MAAA,MAAM,CAAC,oBAAoB,CAAsB,gBAAgB,CAAC,0CAAE,yBAAyB,EAAE,CAAA,CAAC;;CACvG;AAED;;;GAGG;AACH,MAAM,UAAU,mCAAmC,CAAC,WAAmB;IACrE,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,WAAW,KAAI,KAAK,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;IACpH,gCAAgC,IAAI,KAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;IAC7G,gCAAgC,GAAG,WAAW,CAAC;IAC/C,wCAAwC,GAAG,IAAI,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oCAAoC,CAAC,WAAmB;IACtE,mCAAmC,CAAC,WAAW,CAAC,CAAC;IACjD,wCAAwC,GAAG,KAAK,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,IAAqB,EAAQ,EAAE;IACjE,eAAe,IAAI,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7E,eAAe,GAAG,IAAI,CAAC;AACzB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,sCAAsC;IACpD,gCAAgC,GAAG,SAAS,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,IAAc,EAAE,MAA4B;IACzE,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,IAAI,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,EAAE;QAChF,KAAK,CAAC,IAAI,CAAC,sFAAsF,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC;QACnH,OAAO;KACR;IACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC;IAC7C,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC;IAEjD,KAAK,CAAC,GAAG,CAAC,yCAAyC,EAAE;QACnD,MAAM,EAAE,IAAI,CAAC,OAAO;QACpB,SAAS,EAAE;YACT,KAAK,EAAE,MAAM,CAAC,WAAW;YACzB,IAAI,EAAE,MAAM,CAAC,UAAU;YACvB,MAAM,EAAE,MAAM,CAAC,YAAY;SAC5B;KACF,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAClC,UAAU,GAAG,KAAK,MAShB,EAAE,EAAuB,EAAE;IAC7B,IAAI,OAAO,GAAuB,SAAS,CAAC;IAC5C,IAAI,SAAS,GAAG,IAAI,CAAC;IACrB,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,mBAAmB,GAAG,KAAK,CAAC;IAChC,IAAI,4BAA4B,GAAuB,SAAS,CAAC;IAEjE,MAAM,KAAK,GAAG,CAAC,MAAc,EAAQ,EAAE;QACrC,OAAO,GAAG,MAAM,CAAC;QACjB,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,CAAC,UAAU,EAA8B,CAAC;QAEnF,IAAI,CAAC,sBAAsB,EAAE;YAC3B,SAAS,GAAG,KAAK,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;SAC1D;QAED,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,kCAAkC,CAAC,CAAC;IAC7D,CAAC,CAAC;IAEF,MAAM,aAAa,GAAG,CAAC,MAAc,EAAQ,EAAE;;QAC7C,IAAI,mBAAmB,EAAE;YACvB,OAAO;SACR;QACD,mBAAmB,GAAG,IAAI,CAAC;QAE3B,sGAAsG;QAEtG,MAAA,yBAAyB,CAAC,MAAM,CAAC,0CAAE,gBAAgB,CAAC,GAAG,EAAE;YACvD,IAAI,mBAAmB,EAAE;gBACvB,KAAK,CAAC,GAAG,CAAC,2FAA2F,CAAC,CAAC;gBACvG,mBAAmB,GAAG,KAAK,CAAC;gBAC5B,4BAA4B,GAAG,SAAS,CAAC;aAC1C;iBAAM;gBACL,KAAK,CAAC,GAAG,CACP,8GAA8G,CAC/G,CAAC;aACH;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAO,KAAY,EAAkB,EAAE;QAC1D,IAAI,CAAC,SAAS,IAAI,UAAU,EAAE;YAC5B,OAAO,KAAK,CAAC;SACd;QAED,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa,EAAE;YAChC,mDAAmD;YACnD,OAAO,KAAK,CAAC;SACd;QAED,MAAM,gCAAgC,CAAC,KAAyB,CAAC,CAAC;QAElE,OAAO,KAAK,CAAC;IACf,CAAC,CAAA,CAAC;IAEF,MAAM,kCAAkC,GAAG,CAAC,QAAc,EAAQ,EAAE;QAClE,IAAI,4BAA4B,EAAE;YAChC,OAAO;SACR;QAED,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;YACzB,OAAO;SACR;QAED,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE;YAC5B,OAAO;SACR;QAED,+BAA+B,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,+BAA+B,GAAG,CAAC,MAA0B,EAAQ,EAAE;QAC3E,4BAA4B,GAAG,MAAM,CAAC;QACtC,KAAK,CAAC,GAAG,CAAC,wDAAwD,EAAE,4BAA4B,CAAC,CAAC;IACpG,CAAC,CAAC;IAEF,SAAe,yBAAyB;;YACtC,IAAI,CAAC,OAAO,EAAE;gBACZ,yEAAyE;gBACzE,sCAAsC;gBACtC,OAAO,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;gBAClG,OAAO;aACR;YAED,IAAI,CAAC,UAAU,EAAE;gBACf,KAAK,CAAC,GAAG,CACP,6GAA6G,CAC9G,CAAC;gBACF,OAAO;aACR;YAED,KAAK,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;YAE/E,IAAI,CAAC,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,SAAS,CAAA,IAAI,MAAM,CAAC,YAAY,EAAE;gBACtD,IAAI;oBACF,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;oBACnD,KAAK,CAAC,GAAG,CAAC,0DAA0D,EAAE,SAAS,CAAC,CAAC;oBAEjF,MAAM,gBAAgB,GAAG,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,WAAW,KAAI,kBAAkB,EAAE,GAAG,IAAI,CAAC;oBACrF,mBAAmB,CAAC;wBAClB,WAAW,EAAE,gBAAgB;wBAC7B,SAAS;qBACV,CAAC,CAAC;iBACJ;gBAAC,OAAO,KAAK,EAAE;oBACd,KAAK,CAAC,GAAG,CAAC,+DAA+D,EAAE,KAAK,CAAC,CAAC;iBACnF;aACF;YAED,MAAM,IAAI,GAAG,iBAAiB,CAAC;gBAC7B,gBAAgB,EAAE,IAAI;gBACtB,IAAI,EAAE,iBAAiB;gBACvB,EAAE,EAAE,UAAU;aACf,CAAC,CAAC;YACH,IAAI,IAAI,YAAY,sBAAsB,EAAE;gBAC1C,qDAAqD;gBACrD,OAAO;aACR;YAED,eAAe,CAAC,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC5C,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YAE9B,MAAM,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,KAAK,EAAE;gBACV,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;gBAC1E,OAAO;aACR;YAED,MAAM,gCAAgC,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE;gBAC5C,sEAAsE;gBACtE,OAAO;aACR;YAED,MAAM,KAAK,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC;YACvE,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC;KAAA;IAED,SAAe,gCAAgC,CAAC,KAAuB;;;YACrE,IAAI,mBAAmB,EAAE;gBACvB,2EAA2E;gBAC3E,OAAO;aACR;YAED,IAAI,CAAC,CAAA,MAAA,KAAK,CAAC,QAAQ,0CAAE,KAAK,CAAA,EAAE;gBAC1B,KAAK,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;gBAC/F,OAAO;aACR;YAED,kFAAkF;YAClF,oFAAoF;YACpF,+EAA+E;YAC/E,IAAI,CAAC,UAAU,EAAE;gBACf,IAAI,CAAC,4BAA4B,EAAE;oBACjC,KAAK,CAAC,IAAI,CAAC,qFAAqF,CAAC,CAAC;oBAClG,OAAO;iBACR;gBAED,IAAI,4BAA4B,KAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE;oBACjE,KAAK,CAAC,IAAI,CACR,wHAAwH,CACzH,CAAC;oBACF,OAAO;iBACR;aACF;YAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACpD,IAAI,CAAC,QAAQ,EAAE;gBACb,KAAK,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;gBACzF,OAAO;aACR;YACD,IAAI,QAAQ,CAAC,WAAW,EAAE;gBACxB,KAAK,CAAC,IAAI,CAAC,oFAAoF,CAAC,CAAC;gBACjG,OAAO;aACR;YAED,MAAM,mBAAmB,GAAG,QAAQ,CAAC,sBAAsB,CAAC;YAC5D,IAAI,CAAC,mBAAmB,EAAE;gBACxB,KAAK,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;gBACxF,OAAO;aACR;YAED,MAAM,sBAAsB,GAAG,CAAA,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,WAAW,KAAI,yBAAyB,EAAE,CAAC;YAC3F,IAAI,CAAC,sBAAsB,EAAE;gBAC3B,KAAK,CAAC,IAAI,CACR,iIAAiI,CAClI,CAAC;gBACF,OAAO;aACR;YAED,MAAM,sBAAsB,GAC1B,CAAC,CAAC,KAAK,CAAC,eAAe,IAAI,mBAAmB,IAAI,KAAK,CAAC,eAAe,GAAG,IAAK,GAAG,oBAAoB,CAAC;YACzG,IAAI,CAAC,OAAO,IAAI,CAAC,sBAAsB,EAAE;gBACvC,KAAK,CAAC,IAAI,CAAC,sFAAsF,CAAC,CAAC;gBACnG,OAAO;aACR;YAED,MAAM,kBAAkB,GAAG,sBAAsB,GAAG,mBAAmB,CAAC;YACxE,IAAI,CAAC,OAAO,IAAI,kBAAkB,IAAI,yBAAyB,EAAE;gBAC/D,6FAA6F;gBAC7F,KAAK,CAAC,IAAI,CAAC,iFAAiF,CAAC,CAAC;gBAC9F,OAAO;aACR;YAED,IAAI,kBAAkB,GAAG,CAAC,EAAE;gBAC1B,6DAA6D;gBAC7D,8DAA8D;gBAC9D,oDAAoD;gBACpD,KAAK,CAAC,IAAI,CACR,qFAAqF,EACrF,sEAAsE,CACvE,CAAC;gBACF,OAAO;aACR;YAED,mBAAmB,GAAG,IAAI,CAAC;YAE3B,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;YAC5D,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,GAAG,UAAU,CAAC;YACrE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC;YAErC,MAAM,MAAM,GAAG,sCAAsC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,0BAA0B,CAAC;YAClH,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,GAAG,MAAM,CAAC;YACrE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;YAErC,MAAM,wBAAwB,GAAG,mBAAmB,GAAG,IAAI,CAAC;YAC5D,KAAK,CAAC,eAAe,GAAG,wBAAwB,CAAC;YAEjD,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;YAChC,4BAA4B;YAC5B,MAAM,QAAQ,GAAe,KAAK,CAAC,KAAK,CAAC;YAEzC,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,yBAAyB,CAAC,CAAC;YAClF,IAAI,aAAa,EAAE;gBACjB,aAAa,CAAC,eAAe,GAAG,wBAAwB,CAAC;gBACzD,8CAA8C,CAAC,KAAK,EAAE,yBAAyB,EAAE,aAAa,CAAC,CAAC;aACjG;YAED,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,sBAAsB,CAAC,CAAC;YAC/E,IAAI,aAAa,EAAE;gBACjB,aAAa,CAAC,eAAe,GAAG,wBAAwB,CAAC;gBACzD,8CAA8C,CAAC,KAAK,EAAE,sBAAsB,EAAE,aAAa,CAAC,CAAC;aAC9F;YAED,MAAM,2BAA2B,GAAG,sBAAsB,GAAG,IAAI,CAAC;YAClE,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,2BAA2B,EAAE;gBACpE,KAAK,CAAC,GAAG,CACP,wGAAwG,CACzG,CAAC;gBACF,KAAK,CAAC,SAAS,GAAG,2BAA2B,CAAC;aAC/C;YAED,MAAM,EAAE,GAAG,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC;YAC5E,MAAM,gBAAgB,GAAa,cAAc,CAAC;gBAChD,EAAE;gBACF,WAAW,EAAE,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY;gBACnE,eAAe,EAAE,wBAAwB;gBACzC,SAAS,EAAE,2BAA2B;gBACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ;gBACvC,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO;gBAC5C,MAAM;aACP,CAAC,CAAC;YAEH,IAAI,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,SAAS,EAAE;gBAC9B,qBAAqB,CAAC,gBAAgB,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC;aACpE;YAED,MAAM,mBAAmB,GAAG,0BAA0B,CAAC,gBAAgB,EAAE,gCAAgC,CAAC,CAAC;YAE3G,MAAM,aAAa,GAAG;gBACpB,gBAAgB;gBAChB,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,GAAG,4BAA4B,CAAC,gBAAgB,EAAE,QAAQ,CAAC,KAAK,CAAC;aAClE,CAAC;YAEF,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;YAChC,KAAK,CAAC,GAAG,CAAC,wDAAwD,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;YAEjH,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,0BAA0B,CAAC;YAC1G,MAAM,gBAAgB,GAAG;gBACvB,KAAK,EAAE,kBAAkB;gBACzB,IAAI,EAAE,aAAa;aACpB,CAAC;YACF,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;YAC9C,KAAK,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,gBAAgB,CAAC;YACtD,KAAK,CAAC,GAAG,CACP,8DAA8D,EAC9D,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,SAAS,EAAE,CAAC,CAAC,CAC/C,CAAC;;KACH;IAED,OAAO;QACL,IAAI,EAAE,gBAAgB;QACtB,KAAK;QACL,aAAa;QACb,YAAY;QACZ,yBAAyB;QACzB,+BAA+B;KACT,CAAC;AAC3B,CAAC,CAAC;AAEF,SAAS,8CAA8C,CAAC,KAAuB,EAAE,KAAa,EAAE,IAAc;IAC5G,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;QAC5C,KAAK,CAAC,IAAI,CAAC,uFAAuF,CAAC,CAAC;QACpG,OAAO;KACR;IAED,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,EAAE,CAAC;IAC9C,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG;QAC1B,KAAK,EAAE,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,IAAI;QACrD,IAAI,EAAE,aAAa;KACpB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,0BAA0B,CACjC,UAAoB,EACpB,gCAAoD;IAEpD,MAAM,sBAAsB,GAAG,yBAAyB,EAAE,CAAC;IAC3D,IAAI,CAAC,sBAAsB,EAAE;QAC3B,OAAO,SAAS,CAAC;KAClB;IAED,MAAM,2BAA2B,GAAG,sBAAsB,GAAG,IAAI,CAAC;IAClE,IAAI,2BAA2B,GAAG,UAAU,CAAC,eAAe,EAAE;QAC5D,KAAK,CAAC,IAAI,CAAC,kGAAkG,CAAC,CAAC;QAC/G,OAAO,SAAS,CAAC;KAClB;IAED,IAAI,CAAC,gCAAgC,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC;QAC3E,OAAO,mBAAmB,CAAC,UAAU,EAAE;YACrC,WAAW,EAAE,2BAA2B;YACxC,eAAe,EAAE,2BAA2B;YAC5C,SAAS,EAAE,2BAA2B;YACtC,MAAM,EAAE,0BAA0B;SACnC,CAAC,CAAC;KACJ;IAED,OAAO,mBAAmB,CAAC,UAAU,EAAE;QACrC,WAAW,EAAE,uCAAuC;QACpD,eAAe,EAAE,2BAA2B;QAC5C,SAAS,EAAE,gCAAgC,GAAG,IAAI;QAClD,MAAM,EAAE,wCAAwC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,0BAA0B;KAC7G,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,4BAA4B,CAAC,UAAoB,EAAE,WAA4C;IACtG,OAAO,WAAW;SACf,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,GAAG,IAAI,IAAI,UAAU,CAAC,eAAe,CAAC;SAC5E,GAAG,CAAC,IAAI,CAAC,EAAE;QACV,IAAI,IAAI,CAAC,WAAW,KAAK,YAAY,EAAE;YACrC,OAAO,iBAAiB,CAAC,eAAe,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;SAC7D;QAED,OAAO,iBAAiB,CACtB,mBAAmB,CAAC,UAAU,EAAE;YAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,eAAe,EAAE,IAAI,CAAC,kBAAkB,GAAG,IAAI;YAC/C,SAAS,EAAE,IAAI,CAAC,gBAAgB,GAAG,IAAI;YACvC,MAAM,EAAE,0BAA0B;SACnC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,UAAoB,EAAE,eAAwD;IACrG,MAAM,WAAW,GAAG,yBAAyB,EAAE,CAAC;IAEhD,iFAAiF;IACjF,yCAAyC;IACzC,6DAA6D;IAC7D,IAAI,WAAW,IAAI,WAAW,GAAG,eAAe,CAAC,gBAAgB,EAAE;QACjE,OAAO,mBAAmB,CAAC,UAAU,EAAE;YACrC,WAAW,EAAE,6BAA6B;YAC1C,eAAe,EAAE,eAAe,CAAC,kBAAkB,GAAG,IAAI;YAC1D,SAAS,EAAE,WAAW,GAAG,IAAI;YAC7B,MAAM,EAAE,0BAA0B;SACnC,CAAC,CAAC;KACJ;SAAM;QACL,OAAO,mBAAmB,CAAC,UAAU,EAAE;YACrC,WAAW,EAAE,YAAY;YACzB,eAAe,EAAE,eAAe,CAAC,kBAAkB,GAAG,IAAI;YAC1D,SAAS,EAAE,eAAe,CAAC,gBAAgB,GAAG,IAAI;YAClD,MAAM,EAAE,0BAA0B;SACnC,CAAC,CAAC;KACJ;AACH,CAAC","sourcesContent":["/* eslint-disable complexity, max-lines */\nimport type { Client, Event, Integration, Span, SpanJSON, TransactionEvent } from '@sentry/core';\nimport {\n debug,\n getCapturedScopesOnSpan,\n getClient,\n getCurrentScope,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n spanIsSampled,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\nimport { getAppRegistryIntegration } from '../../integrations/appRegistry';\nimport {\n APP_START_COLD as APP_START_COLD_MEASUREMENT,\n APP_START_WARM as APP_START_WARM_MEASUREMENT,\n} from '../../measurements';\nimport type { NativeAppStartResponse, NativeFramesResponse } from '../../NativeRNSentry';\nimport type { ReactNativeClientOptions } from '../../options';\nimport { convertSpanToTransaction, isRootSpan, setEndTimeValue } from '../../utils/span';\nimport { NATIVE } from '../../wrapper';\nimport {\n APP_START_COLD as APP_START_COLD_OP,\n APP_START_WARM as APP_START_WARM_OP,\n UI_LOAD as UI_LOAD_OP,\n} from '../ops';\nimport { SPAN_ORIGIN_AUTO_APP_START, SPAN_ORIGIN_MANUAL_APP_START } from '../origin';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_OP } from '../semanticAttributes';\nimport { setMainThreadInfo } from '../span';\nimport { createChildSpanJSON, createSpanJSON, getBundleStartTimestampMs } from '../utils';\n\nconst INTEGRATION_NAME = 'AppStart';\n\nexport type AppStartIntegration = Integration & {\n captureStandaloneAppStart: () => Promise<void>;\n};\n\n/**\n * We filter out app start more than 60s.\n * This could be due to many different reasons.\n * We've seen app starts with hours, days and even months.\n */\nconst MAX_APP_START_DURATION_MS = 60_000;\n\n/** We filter out App starts which timestamp is 60s and more before the transaction start */\nconst MAX_APP_START_AGE_MS = 60_000;\n\n/** App Start transaction name */\nconst APP_START_TX_NAME = 'App Start';\n\ninterface AppStartEndData {\n timestampMs: number;\n endFrames: NativeFramesResponse | null;\n}\n\nlet appStartEndData: AppStartEndData | undefined = undefined;\nlet isRecordedAppStartEndTimestampMsManual = false;\n\nlet rootComponentCreationTimestampMs: number | undefined = undefined;\nlet isRootComponentCreationTimestampMsManual = false;\n\n/**\n * Records the application start end.\n * Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.\n */\nexport function captureAppStart(): Promise<void> {\n return _captureAppStart({ isManual: true });\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport async function _captureAppStart({ isManual }: { isManual: boolean }): Promise<void> {\n const client = getClient();\n if (!client) {\n debug.warn('[AppStart] Could not capture App Start, missing client.');\n return;\n }\n\n isRecordedAppStartEndTimestampMsManual = isManual;\n\n const timestampMs = timestampInSeconds() * 1000;\n let endFrames: NativeFramesResponse | null = null;\n\n if (NATIVE.enableNative) {\n try {\n endFrames = await NATIVE.fetchNativeFrames();\n debug.log('[AppStart] Captured end frames for app start.', endFrames);\n } catch (error) {\n debug.log('[AppStart] Failed to capture end frames for app start.', error);\n }\n }\n\n _setAppStartEndData({\n timestampMs,\n endFrames,\n });\n\n await client.getIntegrationByName<AppStartIntegration>(INTEGRATION_NAME)?.captureStandaloneAppStart();\n}\n\n/**\n * Sets the root component first constructor call timestamp.\n * Used automatically by `Sentry.wrap` and `Sentry.ReactNativeProfiler`.\n */\nexport function setRootComponentCreationTimestampMs(timestampMs: number): void {\n appStartEndData?.timestampMs && debug.warn('Setting Root component creation timestamp after app start end is set.');\n rootComponentCreationTimestampMs && debug.warn('Overwriting already set root component creation timestamp.');\n rootComponentCreationTimestampMs = timestampMs;\n isRootComponentCreationTimestampMsManual = true;\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport function _setRootComponentCreationTimestampMs(timestampMs: number): void {\n setRootComponentCreationTimestampMs(timestampMs);\n isRootComponentCreationTimestampMsManual = false;\n}\n\n/**\n * For internal use only.\n *\n * @private\n */\nexport const _setAppStartEndData = (data: AppStartEndData): void => {\n appStartEndData && debug.warn('Overwriting already set app start end data.');\n appStartEndData = data;\n};\n\n/**\n * For testing purposes only.\n *\n * @private\n */\nexport function _clearRootComponentCreationTimestampMs(): void {\n rootComponentCreationTimestampMs = undefined;\n}\n\n/**\n * Attaches frame data to a span's data object.\n */\nfunction attachFrameDataToSpan(span: SpanJSON, frames: NativeFramesResponse): void {\n if (frames.totalFrames <= 0 && frames.slowFrames <= 0 && frames.totalFrames <= 0) {\n debug.warn(`[AppStart] Detected zero slow or frozen frames. Not adding measurements to spanId (${span.span_id}).`);\n return;\n }\n span.data = span.data || {};\n span.data['frames.total'] = frames.totalFrames;\n span.data['frames.slow'] = frames.slowFrames;\n span.data['frames.frozen'] = frames.frozenFrames;\n\n debug.log('[AppStart] Attached frame data to span.', {\n spanId: span.span_id,\n frameData: {\n total: frames.totalFrames,\n slow: frames.slowFrames,\n frozen: frames.frozenFrames,\n },\n });\n}\n\n/**\n * Adds AppStart spans from the native layer to the transaction event.\n */\nexport const appStartIntegration = ({\n standalone = false,\n}: {\n /**\n * Should the integration send App Start as a standalone root span (transaction)?\n * If false, App Start will be added as a child span to the first transaction.\n *\n * @default false\n */\n standalone?: boolean;\n} = {}): AppStartIntegration => {\n let _client: Client | undefined = undefined;\n let isEnabled = true;\n let appStartDataFlushed = false;\n let afterAllSetupCalled = false;\n let firstStartedActiveRootSpanId: string | undefined = undefined;\n\n const setup = (client: Client): void => {\n _client = client;\n const { enableAppStartTracking } = client.getOptions() as ReactNativeClientOptions;\n\n if (!enableAppStartTracking) {\n isEnabled = false;\n debug.warn('[AppStart] App start tracking is disabled.');\n }\n\n client.on('spanStart', recordFirstStartedActiveRootSpanId);\n };\n\n const afterAllSetup = (client: Client): void => {\n if (afterAllSetupCalled) {\n return;\n }\n afterAllSetupCalled = true;\n\n // TODO: automatically set standalone based on the presence of the native layer navigation integration\n\n getAppRegistryIntegration(client)?.onRunApplication(() => {\n if (appStartDataFlushed) {\n debug.log('[AppStartIntegration] Resetting app start data flushed flag based on runApplication call.');\n appStartDataFlushed = false;\n firstStartedActiveRootSpanId = undefined;\n } else {\n debug.log(\n '[AppStartIntegration] Waiting for initial app start was flush, before updating based on runApplication call.',\n );\n }\n });\n };\n\n const processEvent = async (event: Event): Promise<Event> => {\n if (!isEnabled || standalone) {\n return event;\n }\n\n if (event.type !== 'transaction') {\n // App start data is only relevant for transactions\n return event;\n }\n\n await attachAppStartToTransactionEvent(event as TransactionEvent);\n\n return event;\n };\n\n const recordFirstStartedActiveRootSpanId = (rootSpan: Span): void => {\n if (firstStartedActiveRootSpanId) {\n return;\n }\n\n if (!isRootSpan(rootSpan)) {\n return;\n }\n\n if (!spanIsSampled(rootSpan)) {\n return;\n }\n\n setFirstStartedActiveRootSpanId(rootSpan.spanContext().spanId);\n };\n\n /**\n * For testing purposes only.\n * @private\n */\n const setFirstStartedActiveRootSpanId = (spanId: string | undefined): void => {\n firstStartedActiveRootSpanId = spanId;\n debug.log('[AppStart] First started active root span id recorded.', firstStartedActiveRootSpanId);\n };\n\n async function captureStandaloneAppStart(): Promise<void> {\n if (!_client) {\n // If client is not set, SDK was not initialized, logger is thus disabled\n // eslint-disable-next-line no-console\n console.warn('[AppStart] Could not capture App Start, missing client, call `Sentry.init` first.');\n return;\n }\n\n if (!standalone) {\n debug.log(\n '[AppStart] App start tracking is enabled. App start will be added to the first transaction as a child span.',\n );\n return;\n }\n\n debug.log('[AppStart] App start tracking standalone root span (transaction).');\n\n if (!appStartEndData?.endFrames && NATIVE.enableNative) {\n try {\n const endFrames = await NATIVE.fetchNativeFrames();\n debug.log('[AppStart] Captured end frames for standalone app start.', endFrames);\n\n const currentTimestamp = appStartEndData?.timestampMs || timestampInSeconds() * 1000;\n _setAppStartEndData({\n timestampMs: currentTimestamp,\n endFrames,\n });\n } catch (error) {\n debug.log('[AppStart] Failed to capture frames for standalone app start.', error);\n }\n }\n\n const span = startInactiveSpan({\n forceTransaction: true,\n name: APP_START_TX_NAME,\n op: UI_LOAD_OP,\n });\n if (span instanceof SentryNonRecordingSpan) {\n // Tracing is disabled or the transaction was sampled\n return;\n }\n\n setEndTimeValue(span, timestampInSeconds());\n _client.emit('spanEnd', span);\n\n const event = convertSpanToTransaction(span);\n if (!event) {\n debug.warn('[AppStart] Failed to convert App Start span to transaction.');\n return;\n }\n\n await attachAppStartToTransactionEvent(event);\n if (!event.spans || event.spans.length === 0) {\n // No spans were added to the transaction, so we don't need to send it\n return;\n }\n\n const scope = getCapturedScopesOnSpan(span).scope || getCurrentScope();\n scope.captureEvent(event);\n }\n\n async function attachAppStartToTransactionEvent(event: TransactionEvent): Promise<void> {\n if (appStartDataFlushed) {\n // App start data is only relevant for the first transaction of the app run\n return;\n }\n\n if (!event.contexts?.trace) {\n debug.warn('[AppStart] Transaction event is missing trace context. Can not attach app start.');\n return;\n }\n\n // When standalone is true, we create our own transaction and don't need to verify\n // it matches the first navigation transaction. When standalone is false, we need to\n // ensure we're attaching app start to the first transaction (not a later one).\n if (!standalone) {\n if (!firstStartedActiveRootSpanId) {\n debug.warn('[AppStart] No first started active root span id recorded. Can not attach app start.');\n return;\n }\n\n if (firstStartedActiveRootSpanId !== event.contexts.trace.span_id) {\n debug.warn(\n '[AppStart] First started active root span id does not match the transaction event span id. Can not attached app start.',\n );\n return;\n }\n }\n\n const appStart = await NATIVE.fetchNativeAppStart();\n if (!appStart) {\n debug.warn('[AppStart] Failed to retrieve the app start metrics from the native layer.');\n return;\n }\n if (appStart.has_fetched) {\n debug.warn('[AppStart] Measured app start metrics were already reported from the native layer.');\n return;\n }\n\n const appStartTimestampMs = appStart.app_start_timestamp_ms;\n if (!appStartTimestampMs) {\n debug.warn('[AppStart] App start timestamp could not be loaded from the native layer.');\n return;\n }\n\n const appStartEndTimestampMs = appStartEndData?.timestampMs || getBundleStartTimestampMs();\n if (!appStartEndTimestampMs) {\n debug.warn(\n '[AppStart] Javascript failed to record app start end. `_setAppStartEndData` was not called nor could the bundle start be found.',\n );\n return;\n }\n\n const isAppStartWithinBounds =\n !!event.start_timestamp && appStartTimestampMs >= event.start_timestamp * 1_000 - MAX_APP_START_AGE_MS;\n if (!__DEV__ && !isAppStartWithinBounds) {\n debug.warn('[AppStart] App start timestamp is too far in the past to be used for app start span.');\n return;\n }\n\n const appStartDurationMs = appStartEndTimestampMs - appStartTimestampMs;\n if (!__DEV__ && appStartDurationMs >= MAX_APP_START_DURATION_MS) {\n // Dev builds can have long app start waiting over minute for the first bundle to be produced\n debug.warn('[AppStart] App start duration is over a minute long, not adding app start span.');\n return;\n }\n\n if (appStartDurationMs < 0) {\n // This can happen when MainActivity on Android is recreated,\n // and the app start end timestamp is not updated, for example\n // due to missing `Sentry.wrap(RootComponent)` call.\n debug.warn(\n '[AppStart] Last recorded app start end timestamp is before the app start timestamp.',\n 'This is usually caused by missing `Sentry.wrap(RootComponent)` call.',\n );\n return;\n }\n\n appStartDataFlushed = true;\n\n event.contexts.trace.data = event.contexts.trace.data || {};\n event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_OP] = UI_LOAD_OP;\n event.contexts.trace.op = UI_LOAD_OP;\n\n const origin = isRecordedAppStartEndTimestampMsManual ? SPAN_ORIGIN_MANUAL_APP_START : SPAN_ORIGIN_AUTO_APP_START;\n event.contexts.trace.data[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] = origin;\n event.contexts.trace.origin = origin;\n\n const appStartTimestampSeconds = appStartTimestampMs / 1000;\n event.start_timestamp = appStartTimestampSeconds;\n\n event.spans = event.spans || [];\n /** event.spans reference */\n const children: SpanJSON[] = event.spans;\n\n const maybeTtidSpan = children.find(({ op }) => op === 'ui.load.initial_display');\n if (maybeTtidSpan) {\n maybeTtidSpan.start_timestamp = appStartTimestampSeconds;\n setSpanDurationAsMeasurementOnTransactionEvent(event, 'time_to_initial_display', maybeTtidSpan);\n }\n\n const maybeTtfdSpan = children.find(({ op }) => op === 'ui.load.full_display');\n if (maybeTtfdSpan) {\n maybeTtfdSpan.start_timestamp = appStartTimestampSeconds;\n setSpanDurationAsMeasurementOnTransactionEvent(event, 'time_to_full_display', maybeTtfdSpan);\n }\n\n const appStartEndTimestampSeconds = appStartEndTimestampMs / 1000;\n if (event.timestamp && event.timestamp < appStartEndTimestampSeconds) {\n debug.log(\n '[AppStart] Transaction event timestamp is before app start end. Adjusting transaction event timestamp.',\n );\n event.timestamp = appStartEndTimestampSeconds;\n }\n\n const op = appStart.type === 'cold' ? APP_START_COLD_OP : APP_START_WARM_OP;\n const appStartSpanJSON: SpanJSON = createSpanJSON({\n op,\n description: appStart.type === 'cold' ? 'Cold Start' : 'Warm Start',\n start_timestamp: appStartTimestampSeconds,\n timestamp: appStartEndTimestampSeconds,\n trace_id: event.contexts.trace.trace_id,\n parent_span_id: event.contexts.trace.span_id,\n origin,\n });\n\n if (appStartEndData?.endFrames) {\n attachFrameDataToSpan(appStartSpanJSON, appStartEndData.endFrames);\n }\n\n const jsExecutionSpanJSON = createJSExecutionStartSpan(appStartSpanJSON, rootComponentCreationTimestampMs);\n\n const appStartSpans = [\n appStartSpanJSON,\n ...(jsExecutionSpanJSON ? [jsExecutionSpanJSON] : []),\n ...convertNativeSpansToSpanJSON(appStartSpanJSON, appStart.spans),\n ];\n\n children.push(...appStartSpans);\n debug.log('[AppStart] Added app start spans to transaction event.', JSON.stringify(appStartSpans, undefined, 2));\n\n const measurementKey = appStart.type === 'cold' ? APP_START_COLD_MEASUREMENT : APP_START_WARM_MEASUREMENT;\n const measurementValue = {\n value: appStartDurationMs,\n unit: 'millisecond',\n };\n event.measurements = event.measurements || {};\n event.measurements[measurementKey] = measurementValue;\n debug.log(\n '[AppStart] Added app start measurement to transaction event.',\n JSON.stringify(measurementValue, undefined, 2),\n );\n }\n\n return {\n name: INTEGRATION_NAME,\n setup,\n afterAllSetup,\n processEvent,\n captureStandaloneAppStart,\n setFirstStartedActiveRootSpanId,\n } as AppStartIntegration;\n};\n\nfunction setSpanDurationAsMeasurementOnTransactionEvent(event: TransactionEvent, label: string, span: SpanJSON): void {\n if (!span.timestamp || !span.start_timestamp) {\n debug.warn('Span is missing start or end timestamp. Cam not set measurement on transaction event.');\n return;\n }\n\n event.measurements = event.measurements || {};\n event.measurements[label] = {\n value: (span.timestamp - span.start_timestamp) * 1000,\n unit: 'millisecond',\n };\n}\n\n/**\n * Adds JS Execution before React Root. If `Sentry.wrap` is not used, create a span for the start of JS Bundle execution.\n */\nfunction createJSExecutionStartSpan(\n parentSpan: SpanJSON,\n rootComponentCreationTimestampMs: number | undefined,\n): SpanJSON | undefined {\n const bundleStartTimestampMs = getBundleStartTimestampMs();\n if (!bundleStartTimestampMs) {\n return undefined;\n }\n\n const bundleStartTimestampSeconds = bundleStartTimestampMs / 1000;\n if (bundleStartTimestampSeconds < parentSpan.start_timestamp) {\n debug.warn('Bundle start timestamp is before the app start span start timestamp. Skipping JS execution span.');\n return undefined;\n }\n\n if (!rootComponentCreationTimestampMs) {\n debug.warn('Missing the root component first constructor call timestamp.');\n return createChildSpanJSON(parentSpan, {\n description: 'JS Bundle Execution Start',\n start_timestamp: bundleStartTimestampSeconds,\n timestamp: bundleStartTimestampSeconds,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n }\n\n return createChildSpanJSON(parentSpan, {\n description: 'JS Bundle Execution Before React Root',\n start_timestamp: bundleStartTimestampSeconds,\n timestamp: rootComponentCreationTimestampMs / 1000,\n origin: isRootComponentCreationTimestampMsManual ? SPAN_ORIGIN_MANUAL_APP_START : SPAN_ORIGIN_AUTO_APP_START,\n });\n}\n\n/**\n * Adds native spans to the app start span.\n */\nfunction convertNativeSpansToSpanJSON(parentSpan: SpanJSON, nativeSpans: NativeAppStartResponse['spans']): SpanJSON[] {\n return nativeSpans\n .filter(span => span.start_timestamp_ms / 1000 >= parentSpan.start_timestamp)\n .map(span => {\n if (span.description === 'UIKit init') {\n return setMainThreadInfo(createUIKitSpan(parentSpan, span));\n }\n\n return setMainThreadInfo(\n createChildSpanJSON(parentSpan, {\n description: span.description,\n start_timestamp: span.start_timestamp_ms / 1000,\n timestamp: span.end_timestamp_ms / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n }),\n );\n });\n}\n\n/**\n * UIKit init is measured by the native layers till the native SDK start\n * RN initializes the native SDK later, the end timestamp would be wrong\n */\nfunction createUIKitSpan(parentSpan: SpanJSON, nativeUIKitSpan: NativeAppStartResponse['spans'][number]): SpanJSON {\n const bundleStart = getBundleStartTimestampMs();\n\n // If UIKit init ends after the bundle start, the native SDK was auto-initialized\n // and so the end timestamp is incorrect.\n // The timestamps can't equal, as RN initializes after UIKit.\n if (bundleStart && bundleStart < nativeUIKitSpan.end_timestamp_ms) {\n return createChildSpanJSON(parentSpan, {\n description: 'UIKit Init to JS Exec Start',\n start_timestamp: nativeUIKitSpan.start_timestamp_ms / 1000,\n timestamp: bundleStart / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n } else {\n return createChildSpanJSON(parentSpan, {\n description: 'UIKit Init',\n start_timestamp: nativeUIKitSpan.start_timestamp_ms / 1000,\n timestamp: nativeUIKitSpan.end_timestamp_ms / 1000,\n origin: SPAN_ORIGIN_AUTO_APP_START,\n });\n }\n}\n"]}
|
|
@@ -21,6 +21,13 @@ export declare const ignoreEmptyRouteChangeTransactions: (client: Client | undef
|
|
|
21
21
|
export declare const onlySampleIfChildSpans: (client: Client, span: Span) => void;
|
|
22
22
|
/**
|
|
23
23
|
* Hooks on AppState change to cancel the span if the app goes background.
|
|
24
|
+
*
|
|
25
|
+
* On iOS the JS thread can be suspended between the `inactive` and
|
|
26
|
+
* `background` transitions, which means the `background` event may never
|
|
27
|
+
* reach JS in time. To handle this we schedule a deferred cancellation when
|
|
28
|
+
* the app becomes `inactive`. If the app returns to `active` before the
|
|
29
|
+
* timeout fires, the cancellation is cleared. If it transitions to
|
|
30
|
+
* `background` first, we cancel immediately and clear the timeout.
|
|
24
31
|
*/
|
|
25
32
|
export declare const cancelInBackground: (client: Client, span: Span) => void;
|
|
26
33
|
//# sourceMappingURL=onSpanEndUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onSpanEndUtils.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/onSpanEndUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"onSpanEndUtils.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/onSpanEndUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAYjD;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,GAAG,IAAI,CAO9F;AAED,eAAO,MAAM,yBAAyB,WAAY,MAAM,QAAQ,IAAI,iBAAiB,MAAM,KAAG,IA0B7F,CAAC;AAwDF,eAAO,MAAM,yBAAyB,WAAY,MAAM,GAAG,SAAS,QAAQ,IAAI,GAAG,SAAS,KAAG,IAa9F,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kCAAkC,WACrC,MAAM,GAAG,SAAS,QACpB,IAAI,GAAG,SAAS,6BACK,MAAM,sBACb,MAAM,OAAO,KAChC,IAoBF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,WAAY,MAAM,QAAQ,IAAI,KAAG,IAmBnE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,WAAY,MAAM,QAAQ,IAAI,KAAG,IA2C/D,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { debug, getSpanDescendants, SPAN_STATUS_ERROR, spanToJSON } from '@sentry/core';
|
|
2
|
-
import { AppState } from 'react-native';
|
|
2
|
+
import { AppState, Platform } from 'react-native';
|
|
3
3
|
import { isRootSpan, isSentrySpan } from '../utils/span';
|
|
4
|
+
/**
|
|
5
|
+
* The time to wait after the app enters the `inactive` state on iOS before
|
|
6
|
+
* cancelling the span.
|
|
7
|
+
*/
|
|
8
|
+
const IOS_INACTIVE_CANCEL_DELAY_MS = 5000;
|
|
4
9
|
/**
|
|
5
10
|
* Hooks on span end event to execute a callback when the span ends.
|
|
6
11
|
*/
|
|
@@ -26,8 +31,8 @@ export const adjustTransactionDuration = (client, span, maxDurationMs) => {
|
|
|
26
31
|
if (!endTimestamp || !startTimestamp) {
|
|
27
32
|
return;
|
|
28
33
|
}
|
|
29
|
-
const diff = endTimestamp - startTimestamp;
|
|
30
|
-
const isOutdatedTransaction =
|
|
34
|
+
const diff = endTimestamp - startTimestamp; // a diff in *seconds*
|
|
35
|
+
const isOutdatedTransaction = diff > maxDurationMs / 1000 || diff < 0;
|
|
31
36
|
if (isOutdatedTransaction) {
|
|
32
37
|
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });
|
|
33
38
|
// TODO: check where was used, might be possible to delete
|
|
@@ -131,13 +136,43 @@ export const onlySampleIfChildSpans = (client, span) => {
|
|
|
131
136
|
};
|
|
132
137
|
/**
|
|
133
138
|
* Hooks on AppState change to cancel the span if the app goes background.
|
|
139
|
+
*
|
|
140
|
+
* On iOS the JS thread can be suspended between the `inactive` and
|
|
141
|
+
* `background` transitions, which means the `background` event may never
|
|
142
|
+
* reach JS in time. To handle this we schedule a deferred cancellation when
|
|
143
|
+
* the app becomes `inactive`. If the app returns to `active` before the
|
|
144
|
+
* timeout fires, the cancellation is cleared. If it transitions to
|
|
145
|
+
* `background` first, we cancel immediately and clear the timeout.
|
|
134
146
|
*/
|
|
135
147
|
export const cancelInBackground = (client, span) => {
|
|
148
|
+
let inactiveTimeout;
|
|
149
|
+
const cancelSpan = () => {
|
|
150
|
+
if (inactiveTimeout !== undefined) {
|
|
151
|
+
clearTimeout(inactiveTimeout);
|
|
152
|
+
inactiveTimeout = undefined;
|
|
153
|
+
}
|
|
154
|
+
debug.log(`Setting ${spanToJSON(span).op} transaction to cancelled because the app is in the background.`);
|
|
155
|
+
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });
|
|
156
|
+
span.end();
|
|
157
|
+
};
|
|
136
158
|
const subscription = AppState.addEventListener('change', (newState) => {
|
|
137
159
|
if (newState === 'background') {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
160
|
+
cancelSpan();
|
|
161
|
+
}
|
|
162
|
+
else if (Platform.OS === 'ios' && newState === 'inactive') {
|
|
163
|
+
// Schedule a deferred cancellation — if the JS thread is suspended
|
|
164
|
+
// before the 'background' event fires, this timer will execute when
|
|
165
|
+
// the app is eventually resumed and end the span.
|
|
166
|
+
if (inactiveTimeout === undefined) {
|
|
167
|
+
inactiveTimeout = setTimeout(cancelSpan, IOS_INACTIVE_CANCEL_DELAY_MS);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else if (newState === 'active') {
|
|
171
|
+
// App returned to foreground — clear any pending inactive cancellation.
|
|
172
|
+
if (inactiveTimeout !== undefined) {
|
|
173
|
+
clearTimeout(inactiveTimeout);
|
|
174
|
+
inactiveTimeout = undefined;
|
|
175
|
+
}
|
|
141
176
|
}
|
|
142
177
|
});
|
|
143
178
|
subscription &&
|
|
@@ -145,6 +180,10 @@ export const cancelInBackground = (client, span) => {
|
|
|
145
180
|
var _a;
|
|
146
181
|
if (endedSpan === span) {
|
|
147
182
|
debug.log(`Removing AppState listener for ${spanToJSON(span).op} transaction.`);
|
|
183
|
+
if (inactiveTimeout !== undefined) {
|
|
184
|
+
clearTimeout(inactiveTimeout);
|
|
185
|
+
inactiveTimeout = undefined;
|
|
186
|
+
}
|
|
148
187
|
(_a = subscription === null || subscription === void 0 ? void 0 : subscription.remove) === null || _a === void 0 ? void 0 : _a.call(subscription);
|
|
149
188
|
}
|
|
150
189
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onSpanEndUtils.js","sourceRoot":"","sources":["../../../src/js/tracing/onSpanEndUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Span } from '@sentry/core';\nimport { debug, getSpanDescendants, SPAN_STATUS_ERROR, spanToJSON } from '@sentry/core';\nimport type { AppStateStatus } from 'react-native';\nimport { AppState } from 'react-native';\nimport { isRootSpan, isSentrySpan } from '../utils/span';\n\n/**\n * Hooks on span end event to execute a callback when the span ends.\n */\nexport function onThisSpanEnd(client: Client, span: Span, callback: (span: Span) => void): void {\n client.on('spanEnd', (endedSpan: Span) => {\n if (span !== endedSpan) {\n return;\n }\n callback(endedSpan);\n });\n}\n\nexport const adjustTransactionDuration = (client: Client, span: Span, maxDurationMs: number): void => {\n if (!isRootSpan(span)) {\n debug.warn('Not sampling empty back spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n const endTimestamp = spanToJSON(span).timestamp;\n const startTimestamp = spanToJSON(span).start_timestamp;\n if (!endTimestamp || !startTimestamp) {\n return;\n }\n\n const diff = endTimestamp - startTimestamp;\n const isOutdatedTransaction = endTimestamp && (diff > maxDurationMs || diff < 0);\n if (isOutdatedTransaction) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });\n // TODO: check where was used, might be possible to delete\n span.setAttribute('maxTransactionDurationExceeded', 'true');\n }\n });\n};\n\n/**\n * Helper function to filter out auto-instrumentation child spans.\n */\nfunction getMeaningfulChildSpans(span: Span): Span[] {\n const children = getSpanDescendants(span);\n return children.filter(\n child =>\n child.spanContext().spanId !== span.spanContext().spanId &&\n spanToJSON(child).op !== 'ui.load.initial_display' &&\n spanToJSON(child).op !== 'navigation.processing',\n );\n}\n\n/**\n * Generic helper to discard empty navigation spans based on a condition.\n */\nfunction discardEmptyNavigationSpan(\n client: Client | undefined,\n span: Span | undefined,\n shouldDiscardFn: (span: Span) => boolean,\n onDiscardFn: (span: Span) => void,\n): void {\n if (!client) {\n debug.warn('Could not hook on spanEnd event because client is not defined.');\n return;\n }\n\n if (!span) {\n debug.warn('Could not hook on spanEnd event because span is not defined.');\n return;\n }\n\n if (!isRootSpan(span) || !isSentrySpan(span)) {\n debug.warn('Not sampling empty navigation spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n if (!shouldDiscardFn(span)) {\n return;\n }\n\n const meaningfulChildren = getMeaningfulChildSpans(span);\n if (meaningfulChildren.length <= 0) {\n onDiscardFn(span);\n span['_sampled'] = false;\n }\n });\n}\n\nexport const ignoreEmptyBackNavigation = (client: Client | undefined, span: Span | undefined): void => {\n discardEmptyNavigationSpan(\n client,\n span,\n // Only discard if route has been seen before\n span => spanToJSON(span).data?.['route.has_been_seen'] === true,\n // Log message when discarding\n () => {\n debug.log(\n 'Not sampling transaction as route has been seen before. Pass ignoreEmptyBackNavigationTransactions = false to disable this feature.',\n );\n },\n );\n};\n\n/**\n * Discards empty \"Route Change\" transactions that never received route information.\n * This happens when navigation library emits a route change event but getCurrentRoute() returns undefined.\n * Such transactions don't contain any useful information and should not be sent to Sentry.\n *\n * This function must be called with a reference tracker function that can check if the span\n * was cleared from the integration's tracking (indicating it went through the state listener).\n */\nexport const ignoreEmptyRouteChangeTransactions = (\n client: Client | undefined,\n span: Span | undefined,\n defaultNavigationSpanName: string,\n isSpanStillTracked: () => boolean,\n): void => {\n discardEmptyNavigationSpan(\n client,\n span,\n // Only discard if:\n // 1. Still has default name\n // 2. No route information was set\n // 3. Still being tracked (state listener never called)\n span => {\n const spanJSON = spanToJSON(span);\n return (\n spanJSON.description === defaultNavigationSpanName && !spanJSON.data?.['route.name'] && isSpanStillTracked()\n );\n },\n // Log and record dropped event\n _span => {\n debug.log(`Discarding empty \"${defaultNavigationSpanName}\" transaction that never received route information.`);\n client?.recordDroppedEvent('sample_rate', 'transaction');\n },\n );\n};\n\n/**\n * Idle Transaction callback to only sample transactions with child spans.\n * To avoid side effects of other callbacks this should be hooked as the last callback.\n */\nexport const onlySampleIfChildSpans = (client: Client, span: Span): void => {\n if (!isRootSpan(span) || !isSentrySpan(span)) {\n debug.warn('Not sampling childless spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n const children = getSpanDescendants(span);\n\n if (children.length <= 1) {\n // Span always has at lest one child, itself\n debug.log(`Not sampling as ${spanToJSON(span).op} transaction has no child spans.`);\n span['_sampled'] = false;\n }\n });\n};\n\n/**\n * Hooks on AppState change to cancel the span if the app goes background.\n */\nexport const cancelInBackground = (client: Client, span: Span): void => {\n const subscription = AppState.addEventListener('change', (newState: AppStateStatus) => {\n if (newState === 'background') {\n debug.log(`Setting ${spanToJSON(span).op} transaction to cancelled because the app is in the background.`);\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n span.end();\n }\n });\n\n subscription &&\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan === span) {\n debug.log(`Removing AppState listener for ${spanToJSON(span).op} transaction.`);\n subscription?.remove?.();\n }\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"onSpanEndUtils.js","sourceRoot":"","sources":["../../../src/js/tracing/onSpanEndUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Span } from '@sentry/core';\nimport { debug, getSpanDescendants, SPAN_STATUS_ERROR, spanToJSON } from '@sentry/core';\nimport type { AppStateStatus } from 'react-native';\nimport { AppState, Platform } from 'react-native';\nimport { isRootSpan, isSentrySpan } from '../utils/span';\n\n/**\n * The time to wait after the app enters the `inactive` state on iOS before\n * cancelling the span.\n */\nconst IOS_INACTIVE_CANCEL_DELAY_MS = 5_000;\n\n/**\n * Hooks on span end event to execute a callback when the span ends.\n */\nexport function onThisSpanEnd(client: Client, span: Span, callback: (span: Span) => void): void {\n client.on('spanEnd', (endedSpan: Span) => {\n if (span !== endedSpan) {\n return;\n }\n callback(endedSpan);\n });\n}\n\nexport const adjustTransactionDuration = (client: Client, span: Span, maxDurationMs: number): void => {\n if (!isRootSpan(span)) {\n debug.warn('Not sampling empty back spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n const endTimestamp = spanToJSON(span).timestamp;\n const startTimestamp = spanToJSON(span).start_timestamp;\n if (!endTimestamp || !startTimestamp) {\n return;\n }\n\n const diff = endTimestamp - startTimestamp; // a diff in *seconds*\n const isOutdatedTransaction = diff > maxDurationMs / 1000 || diff < 0;\n\n if (isOutdatedTransaction) {\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });\n // TODO: check where was used, might be possible to delete\n span.setAttribute('maxTransactionDurationExceeded', 'true');\n }\n });\n};\n\n/**\n * Helper function to filter out auto-instrumentation child spans.\n */\nfunction getMeaningfulChildSpans(span: Span): Span[] {\n const children = getSpanDescendants(span);\n return children.filter(\n child =>\n child.spanContext().spanId !== span.spanContext().spanId &&\n spanToJSON(child).op !== 'ui.load.initial_display' &&\n spanToJSON(child).op !== 'navigation.processing',\n );\n}\n\n/**\n * Generic helper to discard empty navigation spans based on a condition.\n */\nfunction discardEmptyNavigationSpan(\n client: Client | undefined,\n span: Span | undefined,\n shouldDiscardFn: (span: Span) => boolean,\n onDiscardFn: (span: Span) => void,\n): void {\n if (!client) {\n debug.warn('Could not hook on spanEnd event because client is not defined.');\n return;\n }\n\n if (!span) {\n debug.warn('Could not hook on spanEnd event because span is not defined.');\n return;\n }\n\n if (!isRootSpan(span) || !isSentrySpan(span)) {\n debug.warn('Not sampling empty navigation spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n if (!shouldDiscardFn(span)) {\n return;\n }\n\n const meaningfulChildren = getMeaningfulChildSpans(span);\n if (meaningfulChildren.length <= 0) {\n onDiscardFn(span);\n span['_sampled'] = false;\n }\n });\n}\n\nexport const ignoreEmptyBackNavigation = (client: Client | undefined, span: Span | undefined): void => {\n discardEmptyNavigationSpan(\n client,\n span,\n // Only discard if route has been seen before\n span => spanToJSON(span).data?.['route.has_been_seen'] === true,\n // Log message when discarding\n () => {\n debug.log(\n 'Not sampling transaction as route has been seen before. Pass ignoreEmptyBackNavigationTransactions = false to disable this feature.',\n );\n },\n );\n};\n\n/**\n * Discards empty \"Route Change\" transactions that never received route information.\n * This happens when navigation library emits a route change event but getCurrentRoute() returns undefined.\n * Such transactions don't contain any useful information and should not be sent to Sentry.\n *\n * This function must be called with a reference tracker function that can check if the span\n * was cleared from the integration's tracking (indicating it went through the state listener).\n */\nexport const ignoreEmptyRouteChangeTransactions = (\n client: Client | undefined,\n span: Span | undefined,\n defaultNavigationSpanName: string,\n isSpanStillTracked: () => boolean,\n): void => {\n discardEmptyNavigationSpan(\n client,\n span,\n // Only discard if:\n // 1. Still has default name\n // 2. No route information was set\n // 3. Still being tracked (state listener never called)\n span => {\n const spanJSON = spanToJSON(span);\n return (\n spanJSON.description === defaultNavigationSpanName && !spanJSON.data?.['route.name'] && isSpanStillTracked()\n );\n },\n // Log and record dropped event\n _span => {\n debug.log(`Discarding empty \"${defaultNavigationSpanName}\" transaction that never received route information.`);\n client?.recordDroppedEvent('sample_rate', 'transaction');\n },\n );\n};\n\n/**\n * Idle Transaction callback to only sample transactions with child spans.\n * To avoid side effects of other callbacks this should be hooked as the last callback.\n */\nexport const onlySampleIfChildSpans = (client: Client, span: Span): void => {\n if (!isRootSpan(span) || !isSentrySpan(span)) {\n debug.warn('Not sampling childless spans only works for Sentry Transactions (Root Spans).');\n return;\n }\n\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan !== span) {\n return;\n }\n\n const children = getSpanDescendants(span);\n\n if (children.length <= 1) {\n // Span always has at lest one child, itself\n debug.log(`Not sampling as ${spanToJSON(span).op} transaction has no child spans.`);\n span['_sampled'] = false;\n }\n });\n};\n\n/**\n * Hooks on AppState change to cancel the span if the app goes background.\n *\n * On iOS the JS thread can be suspended between the `inactive` and\n * `background` transitions, which means the `background` event may never\n * reach JS in time. To handle this we schedule a deferred cancellation when\n * the app becomes `inactive`. If the app returns to `active` before the\n * timeout fires, the cancellation is cleared. If it transitions to\n * `background` first, we cancel immediately and clear the timeout.\n */\nexport const cancelInBackground = (client: Client, span: Span): void => {\n let inactiveTimeout: ReturnType<typeof setTimeout> | undefined;\n\n const cancelSpan = (): void => {\n if (inactiveTimeout !== undefined) {\n clearTimeout(inactiveTimeout);\n inactiveTimeout = undefined;\n }\n debug.log(`Setting ${spanToJSON(span).op} transaction to cancelled because the app is in the background.`);\n span.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n span.end();\n };\n\n const subscription = AppState.addEventListener('change', (newState: AppStateStatus) => {\n if (newState === 'background') {\n cancelSpan();\n } else if (Platform.OS === 'ios' && newState === 'inactive') {\n // Schedule a deferred cancellation — if the JS thread is suspended\n // before the 'background' event fires, this timer will execute when\n // the app is eventually resumed and end the span.\n if (inactiveTimeout === undefined) {\n inactiveTimeout = setTimeout(cancelSpan, IOS_INACTIVE_CANCEL_DELAY_MS);\n }\n } else if (newState === 'active') {\n // App returned to foreground — clear any pending inactive cancellation.\n if (inactiveTimeout !== undefined) {\n clearTimeout(inactiveTimeout);\n inactiveTimeout = undefined;\n }\n }\n });\n\n subscription &&\n client.on('spanEnd', (endedSpan: Span) => {\n if (endedSpan === span) {\n debug.log(`Removing AppState listener for ${spanToJSON(span).op} transaction.`);\n if (inactiveTimeout !== undefined) {\n clearTimeout(inactiveTimeout);\n inactiveTimeout = undefined;\n }\n subscription?.remove?.();\n }\n });\n};\n"]}
|