@sentry/react-native 8.4.0 → 8.6.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/RNSentry.podspec +1 -1
- package/android/build.gradle +2 -2
- package/android/expo-handler/build.gradle +20 -0
- package/android/expo-handler/src/main/java/io/sentry/react/expo/SentryExpoPackage.java +22 -0
- package/android/expo-handler/src/main/java/io/sentry/react/expo/SentryReactNativeHostHandler.java +48 -0
- package/android/expo-stubs/README.md +7 -0
- package/android/expo-stubs/build.gradle +23 -0
- package/android/expo-stubs/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/expo-stubs/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/android/expo-stubs/gradlew +251 -0
- package/android/expo-stubs/gradlew.bat +94 -0
- package/android/expo-stubs/settings.gradle +1 -0
- package/android/expo-stubs/src/main/java/expo/modules/core/interfaces/Package.java +11 -0
- package/android/expo-stubs/src/main/java/expo/modules/core/interfaces/ReactNativeHostHandler.java +7 -0
- package/android/libs/expo-stubs.jar +0 -0
- package/android/libs/replay-stubs.jar +0 -0
- package/android/replay-stubs/build.gradle +1 -1
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +71 -15
- package/android/src/main/java/io/sentry/react/RNSentryStart.java +3 -0
- package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
- package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +10 -0
- package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +10 -0
- package/dist/js/NativeLogListener.js.map +1 -1
- package/dist/js/NativeRNSentry.d.ts +2 -0
- package/dist/js/NativeRNSentry.d.ts.map +1 -1
- package/dist/js/NativeRNSentry.js.map +1 -1
- package/dist/js/RNSentryReplayMaskNativeComponent.d.ts.map +1 -1
- package/dist/js/RNSentryReplayUnmaskNativeComponent.d.ts.map +1 -1
- package/dist/js/breadcrumb.js.map +1 -1
- package/dist/js/client.js.map +1 -1
- package/dist/js/feedback/FeedbackButton.js.map +1 -1
- package/dist/js/feedback/FeedbackWidget.js +6 -6
- package/dist/js/feedback/FeedbackWidget.js.map +1 -1
- package/dist/js/feedback/FeedbackWidget.styles.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidgetManager.d.ts +3 -1
- package/dist/js/feedback/FeedbackWidgetManager.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidgetManager.js +15 -1
- package/dist/js/feedback/FeedbackWidgetManager.js.map +1 -1
- package/dist/js/feedback/FeedbackWidgetProvider.d.ts +3 -2
- package/dist/js/feedback/FeedbackWidgetProvider.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidgetProvider.js +12 -4
- package/dist/js/feedback/FeedbackWidgetProvider.js.map +1 -1
- package/dist/js/feedback/ScreenshotButton.d.ts +1 -1
- package/dist/js/feedback/ScreenshotButton.js.map +1 -1
- package/dist/js/feedback/ShakeToReportBug.d.ts +27 -0
- package/dist/js/feedback/ShakeToReportBug.d.ts.map +1 -0
- package/dist/js/feedback/ShakeToReportBug.js +83 -0
- package/dist/js/feedback/ShakeToReportBug.js.map +1 -0
- package/dist/js/feedback/defaults.js.map +1 -1
- package/dist/js/feedback/integration.d.ts +13 -2
- package/dist/js/feedback/integration.d.ts.map +1 -1
- package/dist/js/feedback/integration.js +7 -1
- package/dist/js/feedback/integration.js.map +1 -1
- package/dist/js/feedback/lazy.js.map +1 -1
- package/dist/js/feedback/utils.d.ts.map +1 -1
- package/dist/js/feedback/utils.js.map +1 -1
- package/dist/js/index.d.ts +1 -1
- 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/appRegistry.d.ts.map +1 -1
- package/dist/js/integrations/appRegistry.js.map +1 -1
- package/dist/js/integrations/breadcrumbs.d.ts.map +1 -1
- package/dist/js/integrations/debugsymbolicator.js +6 -4
- package/dist/js/integrations/debugsymbolicator.js.map +1 -1
- package/dist/js/integrations/debugsymbolicatorutils.js.map +1 -1
- package/dist/js/integrations/default.d.ts.map +1 -1
- package/dist/js/integrations/default.js +3 -2
- package/dist/js/integrations/default.js.map +1 -1
- package/dist/js/integrations/devicecontext.js +1 -1
- package/dist/js/integrations/devicecontext.js.map +1 -1
- package/dist/js/integrations/expoconstants.js.map +1 -1
- package/dist/js/integrations/expocontext.js.map +1 -1
- 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/integrations/expoupdateslistener.d.ts +38 -0
- package/dist/js/integrations/expoupdateslistener.d.ts.map +1 -0
- package/dist/js/integrations/expoupdateslistener.js +130 -0
- package/dist/js/integrations/expoupdateslistener.js.map +1 -0
- package/dist/js/integrations/logEnricherIntegration.js +1 -1
- package/dist/js/integrations/logEnricherIntegration.js.map +1 -1
- package/dist/js/integrations/modulesloader.js.map +1 -1
- package/dist/js/integrations/nativelinkederrors.d.ts.map +1 -1
- package/dist/js/integrations/nativelinkederrors.js +1 -0
- package/dist/js/integrations/nativelinkederrors.js.map +1 -1
- package/dist/js/integrations/primitiveTagIntegration.js.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlers.d.ts.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlersutils.js.map +1 -1
- package/dist/js/integrations/reactnativeinfo.js.map +1 -1
- package/dist/js/integrations/release.js +1 -1
- package/dist/js/integrations/release.js.map +1 -1
- package/dist/js/integrations/rewriteframes.js.map +1 -1
- package/dist/js/integrations/screenshot.js +1 -1
- package/dist/js/integrations/screenshot.js.map +1 -1
- package/dist/js/integrations/sdkinfo.js.map +1 -1
- package/dist/js/integrations/spotlight.js.map +1 -1
- package/dist/js/integrations/viewhierarchy.js +1 -1
- package/dist/js/integrations/viewhierarchy.js.map +1 -1
- package/dist/js/misc.js +2 -2
- package/dist/js/misc.js.map +1 -1
- package/dist/js/options.d.ts +13 -1
- package/dist/js/options.d.ts.map +1 -1
- package/dist/js/options.js.map +1 -1
- package/dist/js/playground/examples.js.map +1 -1
- package/dist/js/playground/modal.d.ts +2 -2
- package/dist/js/playground/modal.d.ts.map +1 -1
- package/dist/js/playground/modal.js +6 -6
- package/dist/js/playground/modal.js.map +1 -1
- package/dist/js/profiling/cache.js.map +1 -1
- package/dist/js/profiling/convertHermesProfile.js.map +1 -1
- package/dist/js/profiling/debugid.js.map +1 -1
- package/dist/js/profiling/integration.d.ts.map +1 -1
- package/dist/js/profiling/integration.js.map +1 -1
- package/dist/js/profiling/utils.js.map +1 -1
- package/dist/js/replay/CustomMask.d.ts.map +1 -1
- package/dist/js/replay/CustomMask.js.map +1 -1
- package/dist/js/replay/CustomMask.web.d.ts.map +1 -1
- package/dist/js/replay/browserReplay.d.ts.map +1 -1
- package/dist/js/replay/browserReplay.js.map +1 -1
- package/dist/js/replay/mobilereplay.d.ts.map +1 -1
- package/dist/js/replay/mobilereplay.js +21 -2
- package/dist/js/replay/mobilereplay.js.map +1 -1
- package/dist/js/replay/networkUtils.d.ts +0 -1
- package/dist/js/replay/networkUtils.d.ts.map +1 -1
- package/dist/js/replay/networkUtils.js.map +1 -1
- package/dist/js/replay/xhrUtils.js.map +1 -1
- package/dist/js/scopeSync.js.map +1 -1
- package/dist/js/sdk.d.ts.map +1 -1
- package/dist/js/sdk.js +4 -2
- package/dist/js/sdk.js.map +1 -1
- package/dist/js/tools/ModulesCollector.js.map +1 -1
- package/dist/js/tools/easBuildHooks.js +13 -14
- package/dist/js/tools/easBuildHooks.js.map +1 -1
- package/dist/js/tools/enableLogger.js +1 -2
- package/dist/js/tools/enableLogger.js.map +1 -1
- package/dist/js/tools/metroMiddleware.d.ts.map +1 -1
- package/dist/js/tools/metroMiddleware.js.map +1 -1
- package/dist/js/tools/metroconfig.js +6 -7
- package/dist/js/tools/metroconfig.js.map +1 -1
- package/dist/js/tools/sentryBabelTransformerUtils.js +7 -7
- package/dist/js/tools/sentryBabelTransformerUtils.js.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.d.ts.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.js +2 -2
- package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
- package/dist/js/tools/sentryOptionsSerializer.js +1 -2
- package/dist/js/tools/sentryOptionsSerializer.js.map +1 -1
- package/dist/js/tools/sentryReleaseInjector.d.ts +1 -1
- package/dist/js/tools/sentryReleaseInjector.d.ts.map +1 -1
- package/dist/js/tools/sentryReleaseInjector.js.map +1 -1
- package/dist/js/tools/utils.d.ts.map +1 -1
- package/dist/js/tools/utils.js +9 -10
- package/dist/js/tools/utils.js.map +1 -1
- package/dist/js/tools/vendor/metro/countLines.d.ts.map +1 -1
- package/dist/js/tools/vendor/metro/utils.d.ts.map +1 -1
- package/dist/js/tools/vendor/metro/utils.js.map +1 -1
- package/dist/js/touchevents.d.ts.map +1 -1
- package/dist/js/touchevents.js +2 -0
- package/dist/js/touchevents.js.map +1 -1
- package/dist/js/tracing/expoAsset.js.map +1 -1
- package/dist/js/tracing/expoImage.js.map +1 -1
- package/dist/js/tracing/expoRouter.js.map +1 -1
- package/dist/js/tracing/gesturetracing.js.map +1 -1
- package/dist/js/tracing/integrations/appStart.d.ts +9 -1
- package/dist/js/tracing/integrations/appStart.d.ts.map +1 -1
- package/dist/js/tracing/integrations/appStart.js +61 -12
- package/dist/js/tracing/integrations/appStart.js.map +1 -1
- package/dist/js/tracing/integrations/nativeFrames.d.ts.map +1 -1
- package/dist/js/tracing/integrations/nativeFrames.js +35 -22
- package/dist/js/tracing/integrations/nativeFrames.js.map +1 -1
- package/dist/js/tracing/integrations/stalltracking.d.ts +1 -1
- package/dist/js/tracing/integrations/stalltracking.d.ts.map +1 -1
- package/dist/js/tracing/integrations/stalltracking.js +4 -1
- package/dist/js/tracing/integrations/stalltracking.js.map +1 -1
- package/dist/js/tracing/integrations/timeToDisplayIntegration.d.ts.map +1 -1
- package/dist/js/tracing/integrations/timeToDisplayIntegration.js +15 -14
- package/dist/js/tracing/integrations/timeToDisplayIntegration.js.map +1 -1
- package/dist/js/tracing/integrations/userInteraction.d.ts.map +1 -1
- package/dist/js/tracing/integrations/userInteraction.js.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.d.ts.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.js +20 -13
- package/dist/js/tracing/onSpanEndUtils.js.map +1 -1
- package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnativenavigation.js +1 -1
- package/dist/js/tracing/reactnativenavigation.js.map +1 -1
- package/dist/js/tracing/reactnativeprofiler.js.map +1 -1
- package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
- package/dist/js/tracing/reactnativetracing.js.map +1 -1
- package/dist/js/tracing/reactnavigation.d.ts +3 -0
- package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnavigation.js +7 -3
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/tracing/span.d.ts +2 -17
- package/dist/js/tracing/span.d.ts.map +1 -1
- package/dist/js/tracing/span.js.map +1 -1
- package/dist/js/tracing/timeToDisplayFallback.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplay.js.map +1 -1
- package/dist/js/tracing/timetodisplaynative.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplaynative.js.map +1 -1
- package/dist/js/tracing/utils.js.map +1 -1
- package/dist/js/transports/encodePolyfill.d.ts +1 -1
- package/dist/js/transports/encodePolyfill.d.ts.map +1 -1
- package/dist/js/transports/encodePolyfill.js.map +1 -1
- package/dist/js/transports/native.js.map +1 -1
- package/dist/js/utils/AsyncExpiringMap.js.map +1 -1
- package/dist/js/utils/encode.js.map +1 -1
- package/dist/js/utils/environment.js.map +1 -1
- package/dist/js/utils/ignorerequirecyclelogs.js +1 -1
- package/dist/js/utils/ignorerequirecyclelogs.js.map +1 -1
- package/dist/js/utils/normalize.js.map +1 -1
- package/dist/js/utils/outcome.js.map +1 -1
- package/dist/js/utils/primitiveConverter.js.map +1 -1
- package/dist/js/utils/release.js.map +1 -1
- package/dist/js/utils/rnlibraries.js.map +1 -1
- package/dist/js/utils/safe.d.ts +1 -1
- package/dist/js/utils/safe.d.ts.map +1 -1
- package/dist/js/utils/safe.js.map +1 -1
- package/dist/js/utils/worldwide.d.ts +0 -1
- package/dist/js/utils/worldwide.d.ts.map +1 -1
- package/dist/js/utils/xhr.d.ts +0 -1
- package/dist/js/utils/xhr.d.ts.map +1 -1
- package/dist/js/utils/xhr.js.map +1 -1
- package/dist/js/vendor/base64-js/fromByteArray.js.map +1 -1
- package/dist/js/vendor/buffer/utf8ToBytes.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +5 -6
- package/dist/js/wrapper.js.map +1 -1
- package/expo-module.config.json +7 -0
- package/ios/RNSentry.mm +47 -1
- package/ios/RNSentryEvents.h +1 -0
- package/ios/RNSentryEvents.m +1 -0
- package/ios/RNSentryStart.m +4 -1
- package/ios/RNSentryVersion.m +1 -1
- package/package.json +15 -15
- package/plugin/build/withSentry.js +1 -1
- package/plugin/build/withSentryAndroidGradlePlugin.d.ts +1 -1
- package/plugin/build/withSentryAndroidGradlePlugin.js +1 -1
- package/scripts/sentry-xcode.sh +14 -0
- package/sentry.gradle +13 -0
- package/src/js/NativeRNSentry.ts +2 -0
- package/ts3.8/dist/js/NativeRNSentry.d.ts +2 -0
- package/ts3.8/dist/js/feedback/FeedbackWidgetManager.d.ts +3 -1
- package/ts3.8/dist/js/feedback/FeedbackWidgetProvider.d.ts +3 -2
- package/ts3.8/dist/js/feedback/ScreenshotButton.d.ts +1 -1
- package/ts3.8/dist/js/feedback/ShakeToReportBug.d.ts +27 -0
- package/ts3.8/dist/js/feedback/integration.d.ts +13 -2
- package/ts3.8/dist/js/index.d.ts +1 -1
- package/ts3.8/dist/js/integrations/exports.d.ts +1 -0
- package/ts3.8/dist/js/integrations/expoupdateslistener.d.ts +38 -0
- package/ts3.8/dist/js/options.d.ts +13 -1
- package/ts3.8/dist/js/playground/modal.d.ts +2 -2
- package/ts3.8/dist/js/replay/networkUtils.d.ts +0 -1
- package/ts3.8/dist/js/tracing/integrations/appStart.d.ts +9 -1
- package/ts3.8/dist/js/tracing/integrations/stalltracking.d.ts +1 -1
- package/ts3.8/dist/js/tracing/reactnavigation.d.ts +3 -0
- package/ts3.8/dist/js/tracing/span.d.ts +2 -17
- package/ts3.8/dist/js/transports/encodePolyfill.d.ts +1 -1
- package/ts3.8/dist/js/utils/safe.d.ts +1 -1
- package/ts3.8/dist/js/utils/worldwide.d.ts +0 -1
- package/ts3.8/dist/js/utils/xhr.d.ts +0 -1
- package/ts3.8/dist/js/version.d.ts +1 -1
|
@@ -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 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"]}
|
|
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 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\n // Set end timestamp immediately to avoid race with processEvent\n // Frames data will be updated after the async fetch\n _setAppStartEndData({\n timestampMs,\n endFrames: null,\n });\n\n if (NATIVE.enableNative) {\n try {\n const endFrames = await NATIVE.fetchNativeFrames();\n debug.log('[AppStart] Captured end frames for app start.', endFrames);\n _updateAppStartEndFrames(endFrames);\n } catch (error) {\n debug.log('[AppStart] Failed to capture end frames for app start.', error);\n }\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 * Updates only the endFrames on existing appStartEndData.\n * Used after the async fetchNativeFrames completes to attach frame data\n * without triggering the overwrite warning from _setAppStartEndData.\n *\n * @private\n */\nexport const _updateAppStartEndFrames = (endFrames: NativeFramesResponse | null): void => {\n if (appStartEndData) {\n appStartEndData.endFrames = endFrames;\n }\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 let firstStartedActiveRootSpan: Span | 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 firstStartedActiveRootSpan = 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 // Check if the previously locked span was dropped after it ended (e.g., by\n // ignoreEmptyRouteChangeTransactions or ignoreEmptyBackNavigation setting\n // _sampled = false during spanEnd). If so, reset and allow this new span.\n // We check here (at the next spanStart) rather than at spanEnd because\n // the discard listeners run after the app start listener in registration order,\n // so _sampled is not yet false when our own spanEnd listener would fire.\n if (firstStartedActiveRootSpan && !spanIsSampled(firstStartedActiveRootSpan)) {\n debug.log(\n '[AppStart] Previously locked root span was unsampled after ending. Resetting to allow next transaction.',\n );\n resetFirstStartedActiveRootSpanId();\n // Fall through to lock to this new span\n } else {\n return;\n }\n }\n\n if (!isRootSpan(rootSpan)) {\n return;\n }\n\n if (!spanIsSampled(rootSpan)) {\n return;\n }\n\n firstStartedActiveRootSpan = rootSpan;\n setFirstStartedActiveRootSpanId(rootSpan.spanContext().spanId);\n };\n\n /**\n * Resets the first started active root span id and span reference to allow\n * the next root span's transaction to attempt app start attachment.\n */\n const resetFirstStartedActiveRootSpanId = (): void => {\n debug.log('[AppStart] Resetting first started active root span id to allow retry on next transaction.');\n firstStartedActiveRootSpanId = undefined;\n firstStartedActiveRootSpan = undefined;\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 debug.log('[AppStart] App start data already flushed. Skipping.');\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 // All failure paths below set appStartDataFlushed = true to prevent\n // wasteful retries — these conditions won't change within the same app start.\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 appStartDataFlushed = true;\n return;\n }\n if (appStart.has_fetched) {\n debug.warn('[AppStart] Measured app start metrics were already reported from the native layer.');\n appStartDataFlushed = true;\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 appStartDataFlushed = true;\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 appStartDataFlushed = true;\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 appStartDataFlushed = true;\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 appStartDataFlushed = true;\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 appStartDataFlushed = true;\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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeFrames.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/nativeFrames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAE,eAAe,EAAQ,MAAM,cAAc,CAAC;AAkCpG,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACvD,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACtD,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;CACzD;AAOD,eAAO,MAAM,8BAA8B,
|
|
1
|
+
{"version":3,"file":"nativeFrames.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/nativeFrames.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,WAAW,EAAE,YAAY,EAAE,eAAe,EAAQ,MAAM,cAAc,CAAC;AAkCpG,MAAM,WAAW,kBAAmB,SAAQ,YAAY;IACtD,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACvD,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACtD,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;CACzD;AAOD,eAAO,MAAM,8BAA8B,GAAI,QAAQ,OAAO,GAAG,SAAS,KAAG,WAAW,GAAG,SAQ1F,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAAO,WAkO1C,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, timestampInSeconds } from '@sentry/core';
|
|
10
|
+
import { debug, getRootSpan, spanIsSampled, spanToJSON, timestampInSeconds } from '@sentry/core';
|
|
11
11
|
import { AsyncExpiringMap } from '../../utils/AsyncExpiringMap';
|
|
12
12
|
import { isRootSpan } from '../../utils/span';
|
|
13
13
|
import { NATIVE } from '../../wrapper';
|
|
@@ -46,8 +46,10 @@ export const createNativeFramesIntegrations = (enable) => {
|
|
|
46
46
|
* and frame data (frames.total, frames.slow, frames.frozen) onto all spans.
|
|
47
47
|
*/
|
|
48
48
|
export const nativeFramesIntegration = () => {
|
|
49
|
-
/** The native frames at the finish time of the most recent span.
|
|
50
|
-
|
|
49
|
+
/** The native frames at the finish time of the most recent child span, keyed by root span ID.
|
|
50
|
+
* Stores promises so the data is available for processEvent to await even before
|
|
51
|
+
* the async native bridge call completes. */
|
|
52
|
+
const _lastChildSpanEndFramesByRootSpan = new AsyncExpiringMap({ ttl: START_FRAMES_TIMEOUT_MS });
|
|
51
53
|
const _spanToNativeFramesAtStartMap = new AsyncExpiringMap({
|
|
52
54
|
ttl: START_FRAMES_TIMEOUT_MS,
|
|
53
55
|
});
|
|
@@ -65,6 +67,9 @@ export const nativeFramesIntegration = () => {
|
|
|
65
67
|
client.on('spanEnd', fetchEndFramesForSpan);
|
|
66
68
|
};
|
|
67
69
|
const fetchStartFramesForSpan = (span) => {
|
|
70
|
+
if (!spanIsSampled(span)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
68
73
|
const spanId = span.spanContext().spanId;
|
|
69
74
|
const spanType = isRootSpan(span) ? 'root' : 'child';
|
|
70
75
|
debug.log(`[${INTEGRATION_NAME}] Fetching frames for ${spanType} span start (${spanId}).`);
|
|
@@ -86,15 +91,30 @@ export const nativeFramesIntegration = () => {
|
|
|
86
91
|
* produce incorrect deltas. The native bridge calls are async and non-blocking.
|
|
87
92
|
*/
|
|
88
93
|
const fetchEndFramesForSpan = (span) => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
-
const timestamp = timestampInSeconds();
|
|
90
94
|
const spanId = span.spanContext().spanId;
|
|
91
95
|
const hasStartFrames = _spanToNativeFramesAtStartMap.has(spanId);
|
|
92
96
|
if (!hasStartFrames) {
|
|
93
97
|
// We don't have start frames, won't be able to calculate the difference.
|
|
94
98
|
return;
|
|
95
99
|
}
|
|
100
|
+
// For child spans: immediately store a promise for fallback end frames before any awaits,
|
|
101
|
+
// so processEvent can find and await it even if this async function hasn't completed yet.
|
|
102
|
+
// Uses the actual span timestamp (not wall-clock time) so it matches the trimmed event.timestamp
|
|
103
|
+
// for idle transactions. Scoped per root span to avoid concurrent transaction interference.
|
|
104
|
+
let childEndFramesPromise;
|
|
105
|
+
if (!isRootSpan(span)) {
|
|
106
|
+
const rootSpanId = getRootSpan(span).spanContext().spanId;
|
|
107
|
+
const spanTimestamp = spanToJSON(span).timestamp;
|
|
108
|
+
if (spanTimestamp) {
|
|
109
|
+
childEndFramesPromise = fetchNativeFrames();
|
|
110
|
+
_lastChildSpanEndFramesByRootSpan.set(rootSpanId, childEndFramesPromise
|
|
111
|
+
.then(frames => ({ timestamp: spanTimestamp, nativeFrames: frames }))
|
|
112
|
+
.then(undefined, () => null));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
96
115
|
if (isRootSpan(span)) {
|
|
97
116
|
// Root spans: Store end frames for transaction measurements (backward compatibility)
|
|
117
|
+
const timestamp = timestampInSeconds();
|
|
98
118
|
debug.log(`[${INTEGRATION_NAME}] Fetch frames for root span end (${spanId}).`);
|
|
99
119
|
_spanToNativeFramesAtEndMap.set(spanId, new Promise(resolve => {
|
|
100
120
|
fetchNativeFrames()
|
|
@@ -117,10 +137,10 @@ export const nativeFramesIntegration = () => {
|
|
|
117
137
|
debug.log(`[${INTEGRATION_NAME}] No start frames found for span ${spanId}, skipping frame data.`);
|
|
118
138
|
return;
|
|
119
139
|
}
|
|
120
|
-
//
|
|
140
|
+
// For child spans, reuse the already-kicked-off promise to avoid a redundant native bridge call.
|
|
141
|
+
// For root spans, this is the second call to fetchNativeFrames() for the same span.
|
|
121
142
|
// The calls are very close together (microseconds apart), so inconsistency is minimal.
|
|
122
|
-
|
|
123
|
-
const endFrames = yield fetchNativeFrames();
|
|
143
|
+
const endFrames = childEndFramesPromise ? yield childEndFramesPromise : yield fetchNativeFrames();
|
|
124
144
|
// Calculate deltas
|
|
125
145
|
const totalFrames = endFrames.totalFrames - startFrames.totalFrames;
|
|
126
146
|
const slowFrames = endFrames.slowFrames - startFrames.slowFrames;
|
|
@@ -132,24 +152,16 @@ export const nativeFramesIntegration = () => {
|
|
|
132
152
|
span.setAttribute('frames.frozen', frozenFrames);
|
|
133
153
|
debug.log(`[${INTEGRATION_NAME}] Attached frame data to span ${spanId}: total=${totalFrames}, slow=${slowFrames}, frozen=${frozenFrames}`);
|
|
134
154
|
}
|
|
135
|
-
// Update last child span end frames for root span fallback logic
|
|
136
|
-
if (!isRootSpan(span)) {
|
|
137
|
-
_lastChildSpanEndFrames = {
|
|
138
|
-
timestamp,
|
|
139
|
-
nativeFrames: endFrames,
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
155
|
}
|
|
143
156
|
catch (error) {
|
|
144
157
|
debug.log(`[${INTEGRATION_NAME}] Error while capturing end frames for span ${spanId}.`, error);
|
|
145
158
|
}
|
|
146
159
|
});
|
|
147
160
|
const processEvent = (event) => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
-
var _a;
|
|
161
|
+
var _a, _b;
|
|
149
162
|
if (event.type !== 'transaction' ||
|
|
150
163
|
!event.transaction ||
|
|
151
|
-
!event.contexts ||
|
|
152
|
-
!event.contexts.trace ||
|
|
164
|
+
!((_a = event.contexts) === null || _a === void 0 ? void 0 : _a.trace) ||
|
|
153
165
|
!event.timestamp ||
|
|
154
166
|
!event.contexts.trace.span_id) {
|
|
155
167
|
return event;
|
|
@@ -162,17 +174,18 @@ export const nativeFramesIntegration = () => {
|
|
|
162
174
|
return event;
|
|
163
175
|
}
|
|
164
176
|
const endFrames = yield _spanToNativeFramesAtEndMap.pop(spanId);
|
|
177
|
+
const lastChildFrames = yield _lastChildSpanEndFramesByRootSpan.pop(spanId);
|
|
165
178
|
let finalEndFrames;
|
|
166
179
|
if (endFrames && isClose(endFrames.timestamp, event.timestamp)) {
|
|
167
180
|
// Must be in the margin of error of the actual transaction finish time (finalEndTimestamp)
|
|
168
181
|
debug.log(`[${INTEGRATION_NAME}] Using frames from root span end (spanId, ${spanId}).`);
|
|
169
182
|
finalEndFrames = endFrames.nativeFrames;
|
|
170
183
|
}
|
|
171
|
-
else if (
|
|
172
|
-
// Fallback to the last span finish if it is within the margin of error of the actual finish timestamp.
|
|
173
|
-
// This
|
|
184
|
+
else if (lastChildFrames && isClose(lastChildFrames.timestamp, event.timestamp)) {
|
|
185
|
+
// Fallback to the last child span finish if it is within the margin of error of the actual finish timestamp.
|
|
186
|
+
// This handles idle transactions where event.timestamp is trimmed to the last child span's end time.
|
|
174
187
|
debug.log(`[${INTEGRATION_NAME}] Using native frames from last child span end (spanId, ${spanId}).`);
|
|
175
|
-
finalEndFrames =
|
|
188
|
+
finalEndFrames = lastChildFrames.nativeFrames;
|
|
176
189
|
}
|
|
177
190
|
else {
|
|
178
191
|
debug.warn(`[${INTEGRATION_NAME}] Frames were collected within larger than margin of error delay for spanId (${spanId}). Dropping the inaccurate values.`);
|
|
@@ -199,7 +212,7 @@ export const nativeFramesIntegration = () => {
|
|
|
199
212
|
return event;
|
|
200
213
|
}
|
|
201
214
|
debug.log(`[${INTEGRATION_NAME}] Adding measurements to ${traceOp} transaction ${event.transaction}: ${JSON.stringify(measurements, undefined, 2)}`);
|
|
202
|
-
event.measurements = Object.assign(Object.assign({}, ((
|
|
215
|
+
event.measurements = Object.assign(Object.assign({}, ((_b = event.measurements) !== null && _b !== void 0 ? _b : {})), measurements);
|
|
203
216
|
return event;
|
|
204
217
|
});
|
|
205
218
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nativeFrames.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/nativeFrames.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Event, Integration, Measurements, MeasurementUnit, Span } from '@sentry/core';\nimport { debug, timestampInSeconds } from '@sentry/core';\nimport type { NativeFramesResponse } from '../../NativeRNSentry';\nimport { AsyncExpiringMap } from '../../utils/AsyncExpiringMap';\nimport { isRootSpan } from '../../utils/span';\nimport { NATIVE } from '../../wrapper';\n\n/**\n * Timeout from the start of a span to fetching the associated native frames.\n */\nconst FETCH_FRAMES_TIMEOUT_MS = 2_000;\n\n/**\n * This is the time end frames data from the native layer will be\n * kept in memory and waiting for the event processing. This ensures that spans\n * which are never processed are not leaking memory.\n */\nconst END_FRAMES_TIMEOUT_MS = 2_000;\n\n/**\n * This is the time start frames data from the native layer will be\n * kept in memory and waiting for span end. This ensures that spans\n * which never end or are not processed are not leaking memory.\n */\nconst START_FRAMES_TIMEOUT_MS = 60_000;\n\n/**\n * A margin of error of 50ms is allowed for the async native bridge call.\n * Anything larger would reduce the accuracy of our frames measurements.\n */\nconst MARGIN_OF_ERROR_SECONDS = 0.05;\n\nconst INTEGRATION_NAME = 'NativeFrames';\n\nexport interface FramesMeasurements extends Measurements {\n frames_total: { value: number; unit: MeasurementUnit };\n frames_slow: { value: number; unit: MeasurementUnit };\n frames_frozen: { value: number; unit: MeasurementUnit };\n}\n\ninterface NativeFramesResponseWithTimestamp {\n timestamp: number;\n nativeFrames: NativeFramesResponse;\n}\n\nexport const createNativeFramesIntegrations = (enable: boolean | undefined): Integration | undefined => {\n if (!enable && NATIVE.enableNative) {\n // On Android this will free up resource when JS reloaded (native modules stay) and thus JS side of the SDK reinitialized.\n NATIVE.disableNativeFramesTracking();\n return undefined;\n }\n\n return nativeFramesIntegration();\n};\n\n/**\n * Instrumentation to add native slow/frozen frames measurements onto transactions\n * and frame data (frames.total, frames.slow, frames.frozen) onto all spans.\n */\nexport const nativeFramesIntegration = (): Integration => {\n /** The native frames at the finish time of the most recent span. */\n let _lastChildSpanEndFrames: NativeFramesResponseWithTimestamp | null = null;\n const _spanToNativeFramesAtStartMap: AsyncExpiringMap<string, NativeFramesResponse | null> = new AsyncExpiringMap({\n ttl: START_FRAMES_TIMEOUT_MS,\n });\n const _spanToNativeFramesAtEndMap: AsyncExpiringMap<string, NativeFramesResponseWithTimestamp | null> =\n new AsyncExpiringMap({ ttl: END_FRAMES_TIMEOUT_MS });\n\n /**\n * Hooks into the client start and end span events.\n */\n const setup = (client: Client): void => {\n if (!NATIVE.enableNative) {\n debug.warn(\n `[${INTEGRATION_NAME}] This is not available on the Web, Expo Go and other platforms without native modules.`,\n );\n return undefined;\n }\n\n NATIVE.enableNativeFramesTracking();\n client.on('spanStart', fetchStartFramesForSpan);\n client.on('spanEnd', fetchEndFramesForSpan);\n };\n\n const fetchStartFramesForSpan = (span: Span): void => {\n const spanId = span.spanContext().spanId;\n const spanType = isRootSpan(span) ? 'root' : 'child';\n debug.log(`[${INTEGRATION_NAME}] Fetching frames for ${spanType} span start (${spanId}).`);\n\n _spanToNativeFramesAtStartMap.set(\n spanId,\n new Promise<NativeFramesResponse | null>(resolve => {\n fetchNativeFrames()\n .then(frames => resolve(frames))\n .then(undefined, error => {\n debug.log(`[${INTEGRATION_NAME}] Error while fetching native frames.`, error);\n resolve(null);\n });\n }),\n );\n };\n\n /**\n * Fetches end frames for a span and attaches frame data as span attributes.\n *\n * Note: This makes one native bridge call per span end. While this creates O(n) calls\n * for n spans, it's necessary for accuracy. Frame counts are cumulative and continuously\n * incrementing, so each span needs the exact frame count at its end time. Caching would\n * produce incorrect deltas. The native bridge calls are async and non-blocking.\n */\n const fetchEndFramesForSpan = async (span: Span): Promise<void> => {\n const timestamp = timestampInSeconds();\n const spanId = span.spanContext().spanId;\n const hasStartFrames = _spanToNativeFramesAtStartMap.has(spanId);\n\n if (!hasStartFrames) {\n // We don't have start frames, won't be able to calculate the difference.\n return;\n }\n\n if (isRootSpan(span)) {\n // Root spans: Store end frames for transaction measurements (backward compatibility)\n debug.log(`[${INTEGRATION_NAME}] Fetch frames for root span end (${spanId}).`);\n _spanToNativeFramesAtEndMap.set(\n spanId,\n new Promise<NativeFramesResponseWithTimestamp | null>(resolve => {\n fetchNativeFrames()\n .then(frames => {\n resolve({\n timestamp,\n nativeFrames: frames,\n });\n })\n .then(undefined, error => {\n debug.log(`[${INTEGRATION_NAME}] Error while fetching native frames.`, error);\n resolve(null);\n });\n }),\n );\n }\n\n // All spans (root and child): Attach frame data as span attributes\n try {\n const startFrames = await _spanToNativeFramesAtStartMap.get(spanId);\n if (!startFrames) {\n debug.log(`[${INTEGRATION_NAME}] No start frames found for span ${spanId}, skipping frame data.`);\n return;\n }\n\n // NOTE: For root spans, this is the second call to fetchNativeFrames() for the same span.\n // The calls are very close together (microseconds apart), so inconsistency is minimal.\n // Future optimization: reuse the first call's promise to avoid redundant native bridge call.\n const endFrames = await fetchNativeFrames();\n\n // Calculate deltas\n const totalFrames = endFrames.totalFrames - startFrames.totalFrames;\n const slowFrames = endFrames.slowFrames - startFrames.slowFrames;\n const frozenFrames = endFrames.frozenFrames - startFrames.frozenFrames;\n\n // Only attach if we have meaningful data\n if (totalFrames > 0 || slowFrames > 0 || frozenFrames > 0) {\n span.setAttribute('frames.total', totalFrames);\n span.setAttribute('frames.slow', slowFrames);\n span.setAttribute('frames.frozen', frozenFrames);\n debug.log(\n `[${INTEGRATION_NAME}] Attached frame data to span ${spanId}: total=${totalFrames}, slow=${slowFrames}, frozen=${frozenFrames}`,\n );\n }\n\n // Update last child span end frames for root span fallback logic\n if (!isRootSpan(span)) {\n _lastChildSpanEndFrames = {\n timestamp,\n nativeFrames: endFrames,\n };\n }\n } catch (error) {\n debug.log(`[${INTEGRATION_NAME}] Error while capturing end frames for span ${spanId}.`, error);\n }\n };\n\n const processEvent = async (event: Event): Promise<Event> => {\n if (\n event.type !== 'transaction' ||\n !event.transaction ||\n !event.contexts ||\n !event.contexts.trace ||\n !event.timestamp ||\n !event.contexts.trace.span_id\n ) {\n return event;\n }\n\n const traceOp = event.contexts.trace.op;\n const spanId = event.contexts.trace.span_id;\n const startFrames = await _spanToNativeFramesAtStartMap.pop(spanId);\n if (!startFrames) {\n debug.warn(\n `[${INTEGRATION_NAME}] Start frames of transaction ${event.transaction} (eventId, ${event.event_id}) are missing, but the transaction already ended.`,\n );\n return event;\n }\n\n const endFrames = await _spanToNativeFramesAtEndMap.pop(spanId);\n let finalEndFrames: NativeFramesResponse | undefined;\n\n if (endFrames && isClose(endFrames.timestamp, event.timestamp)) {\n // Must be in the margin of error of the actual transaction finish time (finalEndTimestamp)\n debug.log(`[${INTEGRATION_NAME}] Using frames from root span end (spanId, ${spanId}).`);\n finalEndFrames = endFrames.nativeFrames;\n } else if (_lastChildSpanEndFrames && isClose(_lastChildSpanEndFrames.timestamp, event.timestamp)) {\n // Fallback to the last span finish if it is within the margin of error of the actual finish timestamp.\n // This should be the case for trimEnd.\n debug.log(`[${INTEGRATION_NAME}] Using native frames from last child span end (spanId, ${spanId}).`);\n finalEndFrames = _lastChildSpanEndFrames.nativeFrames;\n } else {\n debug.warn(\n `[${INTEGRATION_NAME}] Frames were collected within larger than margin of error delay for spanId (${spanId}). Dropping the inaccurate values.`,\n );\n return event;\n }\n\n const measurements = {\n frames_total: {\n value: finalEndFrames.totalFrames - startFrames.totalFrames,\n unit: 'none',\n },\n frames_frozen: {\n value: finalEndFrames.frozenFrames - startFrames.frozenFrames,\n unit: 'none',\n },\n frames_slow: {\n value: finalEndFrames.slowFrames - startFrames.slowFrames,\n unit: 'none',\n },\n };\n\n if (\n measurements.frames_frozen.value <= 0 &&\n measurements.frames_slow.value <= 0 &&\n measurements.frames_total.value <= 0\n ) {\n debug.warn(\n `[${INTEGRATION_NAME}] Detected zero slow or frozen frames. Not adding measurements to spanId (${spanId}).`,\n );\n return event;\n }\n\n debug.log(\n `[${INTEGRATION_NAME}] Adding measurements to ${traceOp} transaction ${event.transaction}: ${JSON.stringify(\n measurements,\n undefined,\n 2,\n )}`,\n );\n event.measurements = {\n ...(event.measurements ?? {}),\n ...measurements,\n };\n return event;\n };\n\n return {\n name: INTEGRATION_NAME,\n setup,\n processEvent,\n };\n};\n\nfunction fetchNativeFrames(): Promise<NativeFramesResponse> {\n return new Promise<NativeFramesResponse>((resolve, reject) => {\n let settled = false;\n\n const timeoutId = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject('Fetching native frames took too long. Dropping frames.');\n }\n }, FETCH_FRAMES_TIMEOUT_MS);\n\n NATIVE.fetchNativeFrames()\n .then(value => {\n if (settled) {\n return;\n }\n clearTimeout(timeoutId);\n settled = true;\n\n if (!value) {\n reject('Native frames response is null.');\n return;\n }\n resolve(value);\n })\n .then(undefined, error => {\n if (settled) {\n return;\n }\n clearTimeout(timeoutId);\n settled = true;\n reject(error);\n });\n });\n}\n\nfunction isClose(t1: number, t2: number): boolean {\n return Math.abs(t1 - t2) < MARGIN_OF_ERROR_SECONDS;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"nativeFrames.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/nativeFrames.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Event, Integration, Measurements, MeasurementUnit, Span } from '@sentry/core';\nimport { debug, getRootSpan, spanIsSampled, spanToJSON, timestampInSeconds } from '@sentry/core';\nimport type { NativeFramesResponse } from '../../NativeRNSentry';\nimport { AsyncExpiringMap } from '../../utils/AsyncExpiringMap';\nimport { isRootSpan } from '../../utils/span';\nimport { NATIVE } from '../../wrapper';\n\n/**\n * Timeout from the start of a span to fetching the associated native frames.\n */\nconst FETCH_FRAMES_TIMEOUT_MS = 2_000;\n\n/**\n * This is the time end frames data from the native layer will be\n * kept in memory and waiting for the event processing. This ensures that spans\n * which are never processed are not leaking memory.\n */\nconst END_FRAMES_TIMEOUT_MS = 2_000;\n\n/**\n * This is the time start frames data from the native layer will be\n * kept in memory and waiting for span end. This ensures that spans\n * which never end or are not processed are not leaking memory.\n */\nconst START_FRAMES_TIMEOUT_MS = 60_000;\n\n/**\n * A margin of error of 50ms is allowed for the async native bridge call.\n * Anything larger would reduce the accuracy of our frames measurements.\n */\nconst MARGIN_OF_ERROR_SECONDS = 0.05;\n\nconst INTEGRATION_NAME = 'NativeFrames';\n\nexport interface FramesMeasurements extends Measurements {\n frames_total: { value: number; unit: MeasurementUnit };\n frames_slow: { value: number; unit: MeasurementUnit };\n frames_frozen: { value: number; unit: MeasurementUnit };\n}\n\ninterface NativeFramesResponseWithTimestamp {\n timestamp: number;\n nativeFrames: NativeFramesResponse;\n}\n\nexport const createNativeFramesIntegrations = (enable: boolean | undefined): Integration | undefined => {\n if (!enable && NATIVE.enableNative) {\n // On Android this will free up resource when JS reloaded (native modules stay) and thus JS side of the SDK reinitialized.\n NATIVE.disableNativeFramesTracking();\n return undefined;\n }\n\n return nativeFramesIntegration();\n};\n\n/**\n * Instrumentation to add native slow/frozen frames measurements onto transactions\n * and frame data (frames.total, frames.slow, frames.frozen) onto all spans.\n */\nexport const nativeFramesIntegration = (): Integration => {\n /** The native frames at the finish time of the most recent child span, keyed by root span ID.\n * Stores promises so the data is available for processEvent to await even before\n * the async native bridge call completes. */\n const _lastChildSpanEndFramesByRootSpan: AsyncExpiringMap<string, NativeFramesResponseWithTimestamp | null> =\n new AsyncExpiringMap({ ttl: START_FRAMES_TIMEOUT_MS });\n const _spanToNativeFramesAtStartMap: AsyncExpiringMap<string, NativeFramesResponse | null> = new AsyncExpiringMap({\n ttl: START_FRAMES_TIMEOUT_MS,\n });\n const _spanToNativeFramesAtEndMap: AsyncExpiringMap<string, NativeFramesResponseWithTimestamp | null> =\n new AsyncExpiringMap({ ttl: END_FRAMES_TIMEOUT_MS });\n\n /**\n * Hooks into the client start and end span events.\n */\n const setup = (client: Client): void => {\n if (!NATIVE.enableNative) {\n debug.warn(\n `[${INTEGRATION_NAME}] This is not available on the Web, Expo Go and other platforms without native modules.`,\n );\n return undefined;\n }\n\n NATIVE.enableNativeFramesTracking();\n client.on('spanStart', fetchStartFramesForSpan);\n client.on('spanEnd', fetchEndFramesForSpan);\n };\n\n const fetchStartFramesForSpan = (span: Span): void => {\n if (!spanIsSampled(span)) {\n return;\n }\n\n const spanId = span.spanContext().spanId;\n const spanType = isRootSpan(span) ? 'root' : 'child';\n debug.log(`[${INTEGRATION_NAME}] Fetching frames for ${spanType} span start (${spanId}).`);\n\n _spanToNativeFramesAtStartMap.set(\n spanId,\n new Promise<NativeFramesResponse | null>(resolve => {\n fetchNativeFrames()\n .then(frames => resolve(frames))\n .then(undefined, error => {\n debug.log(`[${INTEGRATION_NAME}] Error while fetching native frames.`, error);\n resolve(null);\n });\n }),\n );\n };\n\n /**\n * Fetches end frames for a span and attaches frame data as span attributes.\n *\n * Note: This makes one native bridge call per span end. While this creates O(n) calls\n * for n spans, it's necessary for accuracy. Frame counts are cumulative and continuously\n * incrementing, so each span needs the exact frame count at its end time. Caching would\n * produce incorrect deltas. The native bridge calls are async and non-blocking.\n */\n const fetchEndFramesForSpan = async (span: Span): Promise<void> => {\n const spanId = span.spanContext().spanId;\n const hasStartFrames = _spanToNativeFramesAtStartMap.has(spanId);\n\n if (!hasStartFrames) {\n // We don't have start frames, won't be able to calculate the difference.\n return;\n }\n\n // For child spans: immediately store a promise for fallback end frames before any awaits,\n // so processEvent can find and await it even if this async function hasn't completed yet.\n // Uses the actual span timestamp (not wall-clock time) so it matches the trimmed event.timestamp\n // for idle transactions. Scoped per root span to avoid concurrent transaction interference.\n let childEndFramesPromise: Promise<NativeFramesResponse> | undefined;\n if (!isRootSpan(span)) {\n const rootSpanId = getRootSpan(span).spanContext().spanId;\n const spanTimestamp = spanToJSON(span).timestamp;\n if (spanTimestamp) {\n childEndFramesPromise = fetchNativeFrames();\n _lastChildSpanEndFramesByRootSpan.set(\n rootSpanId,\n childEndFramesPromise\n .then(frames => ({ timestamp: spanTimestamp, nativeFrames: frames }))\n .then(undefined, () => null),\n );\n }\n }\n\n if (isRootSpan(span)) {\n // Root spans: Store end frames for transaction measurements (backward compatibility)\n const timestamp = timestampInSeconds();\n debug.log(`[${INTEGRATION_NAME}] Fetch frames for root span end (${spanId}).`);\n _spanToNativeFramesAtEndMap.set(\n spanId,\n new Promise<NativeFramesResponseWithTimestamp | null>(resolve => {\n fetchNativeFrames()\n .then(frames => {\n resolve({\n timestamp,\n nativeFrames: frames,\n });\n })\n .then(undefined, error => {\n debug.log(`[${INTEGRATION_NAME}] Error while fetching native frames.`, error);\n resolve(null);\n });\n }),\n );\n }\n\n // All spans (root and child): Attach frame data as span attributes\n try {\n const startFrames = await _spanToNativeFramesAtStartMap.get(spanId);\n if (!startFrames) {\n debug.log(`[${INTEGRATION_NAME}] No start frames found for span ${spanId}, skipping frame data.`);\n return;\n }\n\n // For child spans, reuse the already-kicked-off promise to avoid a redundant native bridge call.\n // For root spans, this is the second call to fetchNativeFrames() for the same span.\n // The calls are very close together (microseconds apart), so inconsistency is minimal.\n const endFrames = childEndFramesPromise ? await childEndFramesPromise : await fetchNativeFrames();\n\n // Calculate deltas\n const totalFrames = endFrames.totalFrames - startFrames.totalFrames;\n const slowFrames = endFrames.slowFrames - startFrames.slowFrames;\n const frozenFrames = endFrames.frozenFrames - startFrames.frozenFrames;\n\n // Only attach if we have meaningful data\n if (totalFrames > 0 || slowFrames > 0 || frozenFrames > 0) {\n span.setAttribute('frames.total', totalFrames);\n span.setAttribute('frames.slow', slowFrames);\n span.setAttribute('frames.frozen', frozenFrames);\n debug.log(\n `[${INTEGRATION_NAME}] Attached frame data to span ${spanId}: total=${totalFrames}, slow=${slowFrames}, frozen=${frozenFrames}`,\n );\n }\n } catch (error) {\n debug.log(`[${INTEGRATION_NAME}] Error while capturing end frames for span ${spanId}.`, error);\n }\n };\n\n const processEvent = async (event: Event): Promise<Event> => {\n if (\n event.type !== 'transaction' ||\n !event.transaction ||\n !event.contexts?.trace ||\n !event.timestamp ||\n !event.contexts.trace.span_id\n ) {\n return event;\n }\n\n const traceOp = event.contexts.trace.op;\n const spanId = event.contexts.trace.span_id;\n const startFrames = await _spanToNativeFramesAtStartMap.pop(spanId);\n if (!startFrames) {\n debug.warn(\n `[${INTEGRATION_NAME}] Start frames of transaction ${event.transaction} (eventId, ${event.event_id}) are missing, but the transaction already ended.`,\n );\n return event;\n }\n\n const endFrames = await _spanToNativeFramesAtEndMap.pop(spanId);\n const lastChildFrames = await _lastChildSpanEndFramesByRootSpan.pop(spanId);\n let finalEndFrames: NativeFramesResponse | undefined;\n\n if (endFrames && isClose(endFrames.timestamp, event.timestamp)) {\n // Must be in the margin of error of the actual transaction finish time (finalEndTimestamp)\n debug.log(`[${INTEGRATION_NAME}] Using frames from root span end (spanId, ${spanId}).`);\n finalEndFrames = endFrames.nativeFrames;\n } else if (lastChildFrames && isClose(lastChildFrames.timestamp, event.timestamp)) {\n // Fallback to the last child span finish if it is within the margin of error of the actual finish timestamp.\n // This handles idle transactions where event.timestamp is trimmed to the last child span's end time.\n debug.log(`[${INTEGRATION_NAME}] Using native frames from last child span end (spanId, ${spanId}).`);\n finalEndFrames = lastChildFrames.nativeFrames;\n } else {\n debug.warn(\n `[${INTEGRATION_NAME}] Frames were collected within larger than margin of error delay for spanId (${spanId}). Dropping the inaccurate values.`,\n );\n return event;\n }\n\n const measurements = {\n frames_total: {\n value: finalEndFrames.totalFrames - startFrames.totalFrames,\n unit: 'none',\n },\n frames_frozen: {\n value: finalEndFrames.frozenFrames - startFrames.frozenFrames,\n unit: 'none',\n },\n frames_slow: {\n value: finalEndFrames.slowFrames - startFrames.slowFrames,\n unit: 'none',\n },\n };\n\n if (\n measurements.frames_frozen.value <= 0 &&\n measurements.frames_slow.value <= 0 &&\n measurements.frames_total.value <= 0\n ) {\n debug.warn(\n `[${INTEGRATION_NAME}] Detected zero slow or frozen frames. Not adding measurements to spanId (${spanId}).`,\n );\n return event;\n }\n\n debug.log(\n `[${INTEGRATION_NAME}] Adding measurements to ${traceOp} transaction ${event.transaction}: ${JSON.stringify(\n measurements,\n undefined,\n 2,\n )}`,\n );\n event.measurements = {\n ...(event.measurements ?? {}),\n ...measurements,\n };\n return event;\n };\n\n return {\n name: INTEGRATION_NAME,\n setup,\n processEvent,\n };\n};\n\nfunction fetchNativeFrames(): Promise<NativeFramesResponse> {\n return new Promise<NativeFramesResponse>((resolve, reject) => {\n let settled = false;\n\n const timeoutId = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject('Fetching native frames took too long. Dropping frames.');\n }\n }, FETCH_FRAMES_TIMEOUT_MS);\n\n NATIVE.fetchNativeFrames()\n .then(value => {\n if (settled) {\n return;\n }\n clearTimeout(timeoutId);\n settled = true;\n\n if (!value) {\n reject('Native frames response is null.');\n return;\n }\n resolve(value);\n })\n .then(undefined, error => {\n if (settled) {\n return;\n }\n clearTimeout(timeoutId);\n settled = true;\n reject(error);\n });\n });\n}\n\nfunction isClose(t1: number, t2: number): boolean {\n return Math.abs(t1 - t2) < MARGIN_OF_ERROR_SECONDS;\n}\n"]}
|
|
@@ -26,6 +26,6 @@ export declare const stallTrackingIntegration: ({ minimumStallThresholdMs, }?: {
|
|
|
26
26
|
* How long in milliseconds an event loop iteration can be delayed for before being considered a "stall."
|
|
27
27
|
* @default 50
|
|
28
28
|
*/
|
|
29
|
-
minimumStallThresholdMs?: number
|
|
29
|
+
minimumStallThresholdMs?: number;
|
|
30
30
|
}) => Integration;
|
|
31
31
|
//# sourceMappingURL=stalltracking.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stalltracking.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/stalltracking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,WAAW,EAAE,YAAY,EAAE,eAAe,EAAQ,MAAM,cAAc,CAAC;AAI7F,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMvF,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,CAAC,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACxD,CAAC,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IAC7D,CAAC,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;CAChE;AASD;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB;
|
|
1
|
+
{"version":3,"file":"stalltracking.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/stalltracking.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,WAAW,EAAE,YAAY,EAAE,eAAe,EAAQ,MAAM,cAAc,CAAC;AAI7F,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMvF,MAAM,WAAW,iBAAkB,SAAQ,YAAY;IACrD,CAAC,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IACxD,CAAC,gBAAgB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;IAC7D,CAAC,kBAAkB,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC;CAChE;AASD;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GAAI,+BAEtC;IACD;;;OAGG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC7B,KAAG,WA8TR,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { debug, getRootSpan, spanToJSON, timestampInSeconds } from '@sentry/core';
|
|
1
|
+
import { debug, getRootSpan, spanIsSampled, spanToJSON, timestampInSeconds } from '@sentry/core';
|
|
2
2
|
import { AppState } from 'react-native';
|
|
3
3
|
import { STALL_COUNT, STALL_LONGEST_TIME, STALL_TOTAL_TIME } from '../../measurements';
|
|
4
4
|
import { isRootSpan } from '../../utils/span';
|
|
@@ -66,6 +66,9 @@ export const stallTrackingIntegration = ({ minimumStallThresholdMs = 50, } = {})
|
|
|
66
66
|
if (!isRootSpan(rootSpan)) {
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
|
+
if (!spanIsSampled(rootSpan)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
69
72
|
if (statsByRootSpan.has(rootSpan)) {
|
|
70
73
|
debug.error('[StallTracking] Tried to start stall tracking on a transaction already being tracked. Measurements might be lost.');
|
|
71
74
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stalltracking.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/stalltracking.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, Integration, Measurements, MeasurementUnit, Span } from '@sentry/core';\nimport { debug, getRootSpan, spanToJSON, timestampInSeconds } from '@sentry/core';\nimport type { AppStateStatus } from 'react-native';\nimport { AppState } from 'react-native';\nimport { STALL_COUNT, STALL_LONGEST_TIME, STALL_TOTAL_TIME } from '../../measurements';\nimport { isRootSpan } from '../../utils/span';\nimport { getLatestChildSpanEndTimestamp, isNearToNow, setSpanMeasurement } from '../utils';\n\nconst INTEGRATION_NAME = 'StallTracking';\n\nexport interface StallMeasurements extends Measurements {\n [STALL_COUNT]: { value: number; unit: MeasurementUnit };\n [STALL_TOTAL_TIME]: { value: number; unit: MeasurementUnit };\n [STALL_LONGEST_TIME]: { value: number; unit: MeasurementUnit };\n}\n\n/** Margin of error of 20ms */\nconst MARGIN_OF_ERROR_SECONDS = 0.02;\n/** How long between each iteration in the event loop tracker timeout */\nconst LOOP_TIMEOUT_INTERVAL_MS = 50;\n/** Limit for how many transactions the stall tracker will track at a time to prevent leaks due to transactions not being finished */\nconst MAX_RUNNING_TRANSACTIONS = 10;\n\n/**\n * Stall measurement tracker inspired by the `JSEventLoopWatchdog` used internally in React Native:\n * https://github.com/facebook/react-native/blob/006f5afe120c290a37cf6ff896748fbc062bf7ed/Libraries/Interaction/JSEventLoopWatchdog.js\n *\n * However, we modified the interval implementation to instead have a fixed loop timeout interval of `LOOP_TIMEOUT_INTERVAL_MS`.\n * We then would consider that iteration a stall when the total time for that interval to run is greater than `LOOP_TIMEOUT_INTERVAL_MS + minimumStallThreshold`\n */\nexport const stallTrackingIntegration = ({\n minimumStallThresholdMs = 50,\n}: {\n /**\n * How long in milliseconds an event loop iteration can be delayed for before being considered a \"stall.\"\n * @default 50\n */\n minimumStallThresholdMs?: number;\n} = {}): Integration => {\n const statsByRootSpan: Map<\n Span,\n {\n longestStallTime: number;\n atStart: StallMeasurements;\n atTimestamp: {\n timestamp: number;\n stats: StallMeasurements;\n } | null;\n }\n > = new Map();\n\n const state: {\n isTracking: boolean;\n timeout: ReturnType<typeof setTimeout> | null;\n isBackground: boolean;\n /** Switch that enables the iteration once app moves from background to foreground. */\n backgroundEventListener: (appState: AppStateStatus) => void;\n /** The last timestamp the iteration ran in milliseconds */\n lastIntervalMs: number;\n /** Total amount of time of all stalls that occurred during the current tracking session */\n totalStallTime: number;\n /** Total number of stalls that occurred during the current tracking session */\n stallCount: number;\n /**\n * Iteration of the stall tracking interval. Measures how long the timer strayed from its expected time of running, and how\n * long the stall is for.\n */\n iteration: () => void;\n } = {\n isTracking: false,\n timeout: null,\n isBackground: false,\n lastIntervalMs: 0,\n totalStallTime: 0,\n stallCount: 0,\n backgroundEventListener: (appState: AppStateStatus): void => {\n if (appState === ('active' as AppStateStatus)) {\n state.isBackground = false;\n if (state.timeout != null) {\n state.lastIntervalMs = timestampInSeconds() * 1000;\n state.iteration();\n }\n } else {\n state.isBackground = true;\n state.timeout !== null && clearTimeout(state.timeout);\n }\n },\n iteration: (): void => {\n const now = timestampInSeconds() * 1000;\n const totalTimeTaken = now - state.lastIntervalMs;\n\n if (totalTimeTaken >= LOOP_TIMEOUT_INTERVAL_MS + minimumStallThresholdMs) {\n const stallTime = totalTimeTaken - LOOP_TIMEOUT_INTERVAL_MS;\n state.stallCount += 1;\n state.totalStallTime += stallTime;\n\n for (const [transaction, value] of statsByRootSpan.entries()) {\n const longestStallTime = Math.max(value.longestStallTime ?? 0, stallTime);\n\n statsByRootSpan.set(transaction, {\n ...value,\n longestStallTime,\n });\n }\n }\n\n state.lastIntervalMs = now;\n\n if (state.isTracking && !state.isBackground) {\n state.timeout = setTimeout(state.iteration, LOOP_TIMEOUT_INTERVAL_MS);\n }\n },\n };\n\n const setup = (client: Client): void => {\n client.on('spanStart', _onSpanStart);\n client.on('spanEnd', _onSpanEnd);\n };\n\n const _onSpanStart = (rootSpan: Span): void => {\n if (!isRootSpan(rootSpan)) {\n return;\n }\n\n if (statsByRootSpan.has(rootSpan)) {\n debug.error(\n '[StallTracking] Tried to start stall tracking on a transaction already being tracked. Measurements might be lost.',\n );\n return;\n }\n\n _startTracking();\n statsByRootSpan.set(rootSpan, {\n longestStallTime: 0,\n atTimestamp: null,\n atStart: _getCurrentStats(rootSpan),\n });\n _flushLeakedTransactions();\n };\n\n const _onSpanEnd = (rootSpan: Span): void => {\n if (!isRootSpan(rootSpan)) {\n return _onChildSpanEnd(rootSpan);\n }\n\n const transactionStats = statsByRootSpan.get(rootSpan);\n\n if (!transactionStats) {\n // Transaction has been flushed out somehow, we return null.\n debug.log('[StallTracking] Stall measurements were not added to transaction due to exceeding the max count.');\n\n statsByRootSpan.delete(rootSpan);\n _shouldStopTracking();\n\n return;\n }\n\n // The endTimestamp is always set, but type-wise it's optional\n // https://github.com/getsentry/sentry-javascript/blob/38bd57b0785c97c413f36f89ff931d927e469078/packages/core/src/tracing/sentrySpan.ts#L170\n const endTimestamp = spanToJSON(rootSpan).timestamp;\n\n let statsOnFinish: StallMeasurements | undefined;\n if (isNearToNow(endTimestamp)) {\n statsOnFinish = _getCurrentStats(rootSpan);\n } else {\n // The idleSpan in JS V8 is always trimmed to the last span's endTimestamp (timestamp).\n // The unfinished child spans are removed from the root span after the `spanEnd` event.\n\n const latestChildSpanEnd = getLatestChildSpanEndTimestamp(rootSpan);\n if (latestChildSpanEnd !== endTimestamp) {\n debug.log(\n '[StallTracking] Stall measurements not added due to a custom `endTimestamp` (root end is not equal to the latest child span end).',\n );\n }\n\n if (!transactionStats.atTimestamp) {\n debug.log(\n '[StallTracking] Stall measurements not added due to `endTimestamp` not being close to now. And no previous stats from child end were found.',\n );\n }\n\n if (latestChildSpanEnd === endTimestamp && transactionStats.atTimestamp) {\n statsOnFinish = transactionStats.atTimestamp.stats;\n }\n }\n\n statsByRootSpan.delete(rootSpan);\n _shouldStopTracking();\n\n if (!statsOnFinish) {\n if (typeof endTimestamp !== 'undefined') {\n debug.log(\n '[StallTracking] Stall measurements not added due to `endTimestamp` not being close to now.',\n 'endTimestamp',\n endTimestamp,\n 'now',\n timestampInSeconds(),\n );\n }\n\n return;\n }\n\n setSpanMeasurement(\n rootSpan,\n STALL_COUNT,\n statsOnFinish.stall_count.value - transactionStats.atStart.stall_count.value,\n transactionStats.atStart.stall_count.unit,\n );\n\n setSpanMeasurement(\n rootSpan,\n STALL_TOTAL_TIME,\n statsOnFinish.stall_total_time.value - transactionStats.atStart.stall_total_time.value,\n transactionStats.atStart.stall_total_time.unit,\n );\n\n setSpanMeasurement(\n rootSpan,\n STALL_LONGEST_TIME,\n statsOnFinish.stall_longest_time.value,\n statsOnFinish.stall_longest_time.unit,\n );\n };\n\n const _onChildSpanEnd = (childSpan: Span): void => {\n const rootSpan = getRootSpan(childSpan);\n\n const finalEndTimestamp = spanToJSON(childSpan).timestamp;\n if (finalEndTimestamp) {\n _markSpanFinish(rootSpan, finalEndTimestamp);\n }\n };\n\n /**\n * Logs the finish time of the span for use in `trimEnd: true` transactions.\n */\n const _markSpanFinish = (rootSpan: Span, childSpanEndTime: number): void => {\n const previousStats = statsByRootSpan.get(rootSpan);\n if (previousStats) {\n if (Math.abs(timestampInSeconds() - childSpanEndTime) > MARGIN_OF_ERROR_SECONDS) {\n debug.log(\n '[StallTracking] Span end not logged due to end timestamp being outside the margin of error from now.',\n );\n\n if (previousStats.atTimestamp && previousStats.atTimestamp.timestamp < childSpanEndTime) {\n // We also need to delete the stat for the last span, as the transaction would be trimmed to this span not the last one.\n statsByRootSpan.set(rootSpan, {\n ...previousStats,\n atTimestamp: null,\n });\n }\n } else {\n statsByRootSpan.set(rootSpan, {\n ...previousStats,\n atTimestamp: {\n timestamp: childSpanEndTime,\n stats: _getCurrentStats(rootSpan),\n },\n });\n }\n }\n };\n\n /**\n * Get the current stats for a transaction at a given time.\n */\n const _getCurrentStats = (span: Span): StallMeasurements => {\n return {\n stall_count: { value: state.stallCount, unit: 'none' },\n stall_total_time: { value: state.totalStallTime, unit: 'millisecond' },\n stall_longest_time: {\n value: statsByRootSpan.get(span)?.longestStallTime ?? 0,\n unit: 'millisecond',\n },\n };\n };\n\n /**\n * Start tracking stalls\n */\n const _startTracking = (): void => {\n if (!state.isTracking) {\n state.isTracking = true;\n state.lastIntervalMs = Math.floor(timestampInSeconds() * 1000);\n\n state.iteration();\n }\n };\n\n /**\n * Stops the stall tracking interval and calls reset().\n */\n const _stopTracking = (): void => {\n state.isTracking = false;\n\n if (state.timeout !== null) {\n clearTimeout(state.timeout);\n state.timeout = null;\n }\n\n _reset();\n };\n\n /**\n * Will stop tracking if there are no more transactions.\n */\n const _shouldStopTracking = (): void => {\n if (statsByRootSpan.size === 0) {\n _stopTracking();\n }\n };\n\n /**\n * Clears all the collected stats\n */\n const _reset = (): void => {\n state.stallCount = 0;\n state.totalStallTime = 0;\n state.lastIntervalMs = 0;\n statsByRootSpan.clear();\n };\n\n /**\n * Deletes leaked transactions (Earliest transactions when we have more than MAX_RUNNING_TRANSACTIONS transactions.)\n */\n const _flushLeakedTransactions = (): void => {\n if (statsByRootSpan.size > MAX_RUNNING_TRANSACTIONS) {\n let counter = 0;\n const len = statsByRootSpan.size - MAX_RUNNING_TRANSACTIONS;\n const transactions = statsByRootSpan.keys();\n for (const t of transactions) {\n if (counter >= len) break;\n counter += 1;\n statsByRootSpan.delete(t);\n }\n }\n };\n\n // Avoids throwing any error if using React Native on a environment that doesn't implement AppState.\n if (AppState?.isAvailable) {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n AppState.addEventListener('change', state.backgroundEventListener);\n }\n\n return {\n name: INTEGRATION_NAME,\n setup,\n\n /** For testing only @private */\n _internalState: state,\n } as Integration;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"stalltracking.js","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/stalltracking.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, Integration, Measurements, MeasurementUnit, Span } from '@sentry/core';\nimport { debug, getRootSpan, spanIsSampled, spanToJSON, timestampInSeconds } from '@sentry/core';\nimport type { AppStateStatus } from 'react-native';\nimport { AppState } from 'react-native';\nimport { STALL_COUNT, STALL_LONGEST_TIME, STALL_TOTAL_TIME } from '../../measurements';\nimport { isRootSpan } from '../../utils/span';\nimport { getLatestChildSpanEndTimestamp, isNearToNow, setSpanMeasurement } from '../utils';\n\nconst INTEGRATION_NAME = 'StallTracking';\n\nexport interface StallMeasurements extends Measurements {\n [STALL_COUNT]: { value: number; unit: MeasurementUnit };\n [STALL_TOTAL_TIME]: { value: number; unit: MeasurementUnit };\n [STALL_LONGEST_TIME]: { value: number; unit: MeasurementUnit };\n}\n\n/** Margin of error of 20ms */\nconst MARGIN_OF_ERROR_SECONDS = 0.02;\n/** How long between each iteration in the event loop tracker timeout */\nconst LOOP_TIMEOUT_INTERVAL_MS = 50;\n/** Limit for how many transactions the stall tracker will track at a time to prevent leaks due to transactions not being finished */\nconst MAX_RUNNING_TRANSACTIONS = 10;\n\n/**\n * Stall measurement tracker inspired by the `JSEventLoopWatchdog` used internally in React Native:\n * https://github.com/facebook/react-native/blob/006f5afe120c290a37cf6ff896748fbc062bf7ed/Libraries/Interaction/JSEventLoopWatchdog.js\n *\n * However, we modified the interval implementation to instead have a fixed loop timeout interval of `LOOP_TIMEOUT_INTERVAL_MS`.\n * We then would consider that iteration a stall when the total time for that interval to run is greater than `LOOP_TIMEOUT_INTERVAL_MS + minimumStallThreshold`\n */\nexport const stallTrackingIntegration = ({\n minimumStallThresholdMs = 50,\n}: {\n /**\n * How long in milliseconds an event loop iteration can be delayed for before being considered a \"stall.\"\n * @default 50\n */\n minimumStallThresholdMs?: number;\n} = {}): Integration => {\n const statsByRootSpan: Map<\n Span,\n {\n longestStallTime: number;\n atStart: StallMeasurements;\n atTimestamp: {\n timestamp: number;\n stats: StallMeasurements;\n } | null;\n }\n > = new Map();\n\n const state: {\n isTracking: boolean;\n timeout: ReturnType<typeof setTimeout> | null;\n isBackground: boolean;\n /** Switch that enables the iteration once app moves from background to foreground. */\n backgroundEventListener: (appState: AppStateStatus) => void;\n /** The last timestamp the iteration ran in milliseconds */\n lastIntervalMs: number;\n /** Total amount of time of all stalls that occurred during the current tracking session */\n totalStallTime: number;\n /** Total number of stalls that occurred during the current tracking session */\n stallCount: number;\n /**\n * Iteration of the stall tracking interval. Measures how long the timer strayed from its expected time of running, and how\n * long the stall is for.\n */\n iteration: () => void;\n } = {\n isTracking: false,\n timeout: null,\n isBackground: false,\n lastIntervalMs: 0,\n totalStallTime: 0,\n stallCount: 0,\n backgroundEventListener: (appState: AppStateStatus): void => {\n if (appState === ('active' as AppStateStatus)) {\n state.isBackground = false;\n if (state.timeout != null) {\n state.lastIntervalMs = timestampInSeconds() * 1000;\n state.iteration();\n }\n } else {\n state.isBackground = true;\n state.timeout !== null && clearTimeout(state.timeout);\n }\n },\n iteration: (): void => {\n const now = timestampInSeconds() * 1000;\n const totalTimeTaken = now - state.lastIntervalMs;\n\n if (totalTimeTaken >= LOOP_TIMEOUT_INTERVAL_MS + minimumStallThresholdMs) {\n const stallTime = totalTimeTaken - LOOP_TIMEOUT_INTERVAL_MS;\n state.stallCount += 1;\n state.totalStallTime += stallTime;\n\n for (const [transaction, value] of statsByRootSpan.entries()) {\n const longestStallTime = Math.max(value.longestStallTime ?? 0, stallTime);\n\n statsByRootSpan.set(transaction, {\n ...value,\n longestStallTime,\n });\n }\n }\n\n state.lastIntervalMs = now;\n\n if (state.isTracking && !state.isBackground) {\n state.timeout = setTimeout(state.iteration, LOOP_TIMEOUT_INTERVAL_MS);\n }\n },\n };\n\n const setup = (client: Client): void => {\n client.on('spanStart', _onSpanStart);\n client.on('spanEnd', _onSpanEnd);\n };\n\n const _onSpanStart = (rootSpan: Span): void => {\n if (!isRootSpan(rootSpan)) {\n return;\n }\n\n if (!spanIsSampled(rootSpan)) {\n return;\n }\n\n if (statsByRootSpan.has(rootSpan)) {\n debug.error(\n '[StallTracking] Tried to start stall tracking on a transaction already being tracked. Measurements might be lost.',\n );\n return;\n }\n\n _startTracking();\n statsByRootSpan.set(rootSpan, {\n longestStallTime: 0,\n atTimestamp: null,\n atStart: _getCurrentStats(rootSpan),\n });\n _flushLeakedTransactions();\n };\n\n const _onSpanEnd = (rootSpan: Span): void => {\n if (!isRootSpan(rootSpan)) {\n return _onChildSpanEnd(rootSpan);\n }\n\n const transactionStats = statsByRootSpan.get(rootSpan);\n\n if (!transactionStats) {\n // Transaction has been flushed out somehow, we return null.\n debug.log('[StallTracking] Stall measurements were not added to transaction due to exceeding the max count.');\n\n statsByRootSpan.delete(rootSpan);\n _shouldStopTracking();\n\n return;\n }\n\n // The endTimestamp is always set, but type-wise it's optional\n // https://github.com/getsentry/sentry-javascript/blob/38bd57b0785c97c413f36f89ff931d927e469078/packages/core/src/tracing/sentrySpan.ts#L170\n const endTimestamp = spanToJSON(rootSpan).timestamp;\n\n let statsOnFinish: StallMeasurements | undefined;\n if (isNearToNow(endTimestamp)) {\n statsOnFinish = _getCurrentStats(rootSpan);\n } else {\n // The idleSpan in JS V8 is always trimmed to the last span's endTimestamp (timestamp).\n // The unfinished child spans are removed from the root span after the `spanEnd` event.\n\n const latestChildSpanEnd = getLatestChildSpanEndTimestamp(rootSpan);\n if (latestChildSpanEnd !== endTimestamp) {\n debug.log(\n '[StallTracking] Stall measurements not added due to a custom `endTimestamp` (root end is not equal to the latest child span end).',\n );\n }\n\n if (!transactionStats.atTimestamp) {\n debug.log(\n '[StallTracking] Stall measurements not added due to `endTimestamp` not being close to now. And no previous stats from child end were found.',\n );\n }\n\n if (latestChildSpanEnd === endTimestamp && transactionStats.atTimestamp) {\n statsOnFinish = transactionStats.atTimestamp.stats;\n }\n }\n\n statsByRootSpan.delete(rootSpan);\n _shouldStopTracking();\n\n if (!statsOnFinish) {\n if (typeof endTimestamp !== 'undefined') {\n debug.log(\n '[StallTracking] Stall measurements not added due to `endTimestamp` not being close to now.',\n 'endTimestamp',\n endTimestamp,\n 'now',\n timestampInSeconds(),\n );\n }\n\n return;\n }\n\n setSpanMeasurement(\n rootSpan,\n STALL_COUNT,\n statsOnFinish.stall_count.value - transactionStats.atStart.stall_count.value,\n transactionStats.atStart.stall_count.unit,\n );\n\n setSpanMeasurement(\n rootSpan,\n STALL_TOTAL_TIME,\n statsOnFinish.stall_total_time.value - transactionStats.atStart.stall_total_time.value,\n transactionStats.atStart.stall_total_time.unit,\n );\n\n setSpanMeasurement(\n rootSpan,\n STALL_LONGEST_TIME,\n statsOnFinish.stall_longest_time.value,\n statsOnFinish.stall_longest_time.unit,\n );\n };\n\n const _onChildSpanEnd = (childSpan: Span): void => {\n const rootSpan = getRootSpan(childSpan);\n\n const finalEndTimestamp = spanToJSON(childSpan).timestamp;\n if (finalEndTimestamp) {\n _markSpanFinish(rootSpan, finalEndTimestamp);\n }\n };\n\n /**\n * Logs the finish time of the span for use in `trimEnd: true` transactions.\n */\n const _markSpanFinish = (rootSpan: Span, childSpanEndTime: number): void => {\n const previousStats = statsByRootSpan.get(rootSpan);\n if (previousStats) {\n if (Math.abs(timestampInSeconds() - childSpanEndTime) > MARGIN_OF_ERROR_SECONDS) {\n debug.log(\n '[StallTracking] Span end not logged due to end timestamp being outside the margin of error from now.',\n );\n\n if (previousStats.atTimestamp && previousStats.atTimestamp.timestamp < childSpanEndTime) {\n // We also need to delete the stat for the last span, as the transaction would be trimmed to this span not the last one.\n statsByRootSpan.set(rootSpan, {\n ...previousStats,\n atTimestamp: null,\n });\n }\n } else {\n statsByRootSpan.set(rootSpan, {\n ...previousStats,\n atTimestamp: {\n timestamp: childSpanEndTime,\n stats: _getCurrentStats(rootSpan),\n },\n });\n }\n }\n };\n\n /**\n * Get the current stats for a transaction at a given time.\n */\n const _getCurrentStats = (span: Span): StallMeasurements => {\n return {\n stall_count: { value: state.stallCount, unit: 'none' },\n stall_total_time: { value: state.totalStallTime, unit: 'millisecond' },\n stall_longest_time: {\n value: statsByRootSpan.get(span)?.longestStallTime ?? 0,\n unit: 'millisecond',\n },\n };\n };\n\n /**\n * Start tracking stalls\n */\n const _startTracking = (): void => {\n if (!state.isTracking) {\n state.isTracking = true;\n state.lastIntervalMs = Math.floor(timestampInSeconds() * 1000);\n\n state.iteration();\n }\n };\n\n /**\n * Stops the stall tracking interval and calls reset().\n */\n const _stopTracking = (): void => {\n state.isTracking = false;\n\n if (state.timeout !== null) {\n clearTimeout(state.timeout);\n state.timeout = null;\n }\n\n _reset();\n };\n\n /**\n * Will stop tracking if there are no more transactions.\n */\n const _shouldStopTracking = (): void => {\n if (statsByRootSpan.size === 0) {\n _stopTracking();\n }\n };\n\n /**\n * Clears all the collected stats\n */\n const _reset = (): void => {\n state.stallCount = 0;\n state.totalStallTime = 0;\n state.lastIntervalMs = 0;\n statsByRootSpan.clear();\n };\n\n /**\n * Deletes leaked transactions (Earliest transactions when we have more than MAX_RUNNING_TRANSACTIONS transactions.)\n */\n const _flushLeakedTransactions = (): void => {\n if (statsByRootSpan.size > MAX_RUNNING_TRANSACTIONS) {\n let counter = 0;\n const len = statsByRootSpan.size - MAX_RUNNING_TRANSACTIONS;\n const transactions = statsByRootSpan.keys();\n for (const t of transactions) {\n if (counter >= len) break;\n counter += 1;\n statsByRootSpan.delete(t);\n }\n }\n };\n\n // Avoids throwing any error if using React Native on a environment that doesn't implement AppState.\n if (AppState?.isAvailable) {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n AppState.addEventListener('change', state.backgroundEventListener);\n }\n\n return {\n name: INTEGRATION_NAME,\n setup,\n\n /** For testing only @private */\n _internalState: state,\n } as Integration;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeToDisplayIntegration.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/timeToDisplayIntegration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,WAAW,EAAY,MAAM,cAAc,CAAC;AAWjE,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,QAAO,
|
|
1
|
+
{"version":3,"file":"timeToDisplayIntegration.d.ts","sourceRoot":"","sources":["../../../../src/js/tracing/integrations/timeToDisplayIntegration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,WAAW,EAAY,MAAM,cAAc,CAAC;AAWjE,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAKhD,eAAO,MAAM,wBAAwB,QAAO,WAyE3C,CAAC"}
|