@sentry/react-native 6.9.1 → 6.11.0-beta.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.
Files changed (144) hide show
  1. package/RNSentry.podspec +1 -1
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +43 -21
  4. package/android/src/main/java/io/sentry/react/RNSentryOnDrawReporterManager.java +82 -51
  5. package/android/src/main/java/io/sentry/react/RNSentryTimeToDisplay.java +37 -0
  6. package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
  7. package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +10 -0
  8. package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +5 -0
  9. package/dist/js/NativeRNSentry.d.ts +2 -0
  10. package/dist/js/NativeRNSentry.d.ts.map +1 -1
  11. package/dist/js/NativeRNSentry.js.map +1 -1
  12. package/dist/js/feedback/FeedbackWidget.js +3 -3
  13. package/dist/js/feedback/FeedbackWidget.js.map +1 -1
  14. package/dist/js/index.d.ts +2 -1
  15. package/dist/js/index.d.ts.map +1 -1
  16. package/dist/js/index.js +2 -1
  17. package/dist/js/index.js.map +1 -1
  18. package/dist/js/integrations/appRegistry.d.ts +8 -0
  19. package/dist/js/integrations/appRegistry.d.ts.map +1 -0
  20. package/dist/js/integrations/appRegistry.js +43 -0
  21. package/dist/js/integrations/appRegistry.js.map +1 -0
  22. package/dist/js/integrations/default.d.ts.map +1 -1
  23. package/dist/js/integrations/default.js +5 -1
  24. package/dist/js/integrations/default.js.map +1 -1
  25. package/dist/js/integrations/exports.d.ts +2 -0
  26. package/dist/js/integrations/exports.d.ts.map +1 -1
  27. package/dist/js/integrations/exports.js +2 -0
  28. package/dist/js/integrations/exports.js.map +1 -1
  29. package/dist/js/replay/CustomMask.d.ts.map +1 -1
  30. package/dist/js/replay/CustomMask.js +3 -2
  31. package/dist/js/replay/CustomMask.js.map +1 -1
  32. package/dist/js/replay/mobilereplay.d.ts +23 -0
  33. package/dist/js/replay/mobilereplay.d.ts.map +1 -1
  34. package/dist/js/replay/mobilereplay.js +2 -0
  35. package/dist/js/replay/mobilereplay.js.map +1 -1
  36. package/dist/js/tracing/integrations/appStart.d.ts.map +1 -1
  37. package/dist/js/tracing/integrations/appStart.js +41 -9
  38. package/dist/js/tracing/integrations/appStart.js.map +1 -1
  39. package/dist/js/tracing/integrations/timeToDisplayIntegration.d.ts +4 -0
  40. package/dist/js/tracing/integrations/timeToDisplayIntegration.d.ts.map +1 -0
  41. package/dist/js/tracing/integrations/timeToDisplayIntegration.js +193 -0
  42. package/dist/js/tracing/integrations/timeToDisplayIntegration.js.map +1 -0
  43. package/dist/js/tracing/ops.d.ts +2 -0
  44. package/dist/js/tracing/ops.d.ts.map +1 -1
  45. package/dist/js/tracing/ops.js +2 -0
  46. package/dist/js/tracing/ops.js.map +1 -1
  47. package/dist/js/tracing/reactnativeprofiler.d.ts.map +1 -1
  48. package/dist/js/tracing/reactnativeprofiler.js +5 -0
  49. package/dist/js/tracing/reactnativeprofiler.js.map +1 -1
  50. package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
  51. package/dist/js/tracing/reactnativetracing.js +2 -1
  52. package/dist/js/tracing/reactnativetracing.js.map +1 -1
  53. package/dist/js/tracing/reactnavigation.d.ts +20 -2
  54. package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
  55. package/dist/js/tracing/reactnavigation.js +69 -41
  56. package/dist/js/tracing/reactnavigation.js.map +1 -1
  57. package/dist/js/tracing/semanticAttributes.d.ts +2 -0
  58. package/dist/js/tracing/semanticAttributes.d.ts.map +1 -1
  59. package/dist/js/tracing/semanticAttributes.js +2 -0
  60. package/dist/js/tracing/semanticAttributes.js.map +1 -1
  61. package/dist/js/tracing/span.d.ts +13 -1
  62. package/dist/js/tracing/span.d.ts.map +1 -1
  63. package/dist/js/tracing/span.js +23 -0
  64. package/dist/js/tracing/span.js.map +1 -1
  65. package/dist/js/tracing/timeToDisplayFallback.d.ts +3 -0
  66. package/dist/js/tracing/timeToDisplayFallback.d.ts.map +1 -0
  67. package/dist/js/tracing/timeToDisplayFallback.js +21 -0
  68. package/dist/js/tracing/timeToDisplayFallback.js.map +1 -0
  69. package/dist/js/tracing/timetodisplay.d.ts +29 -0
  70. package/dist/js/tracing/timetodisplay.d.ts.map +1 -1
  71. package/dist/js/tracing/timetodisplay.js +43 -20
  72. package/dist/js/tracing/timetodisplay.js.map +1 -1
  73. package/dist/js/tracing/timetodisplaynative.d.ts.map +1 -1
  74. package/dist/js/tracing/timetodisplaynative.js +2 -1
  75. package/dist/js/tracing/timetodisplaynative.js.map +1 -1
  76. package/dist/js/tracing/timetodisplaynative.types.d.ts +1 -3
  77. package/dist/js/tracing/timetodisplaynative.types.d.ts.map +1 -1
  78. package/dist/js/tracing/timetodisplaynative.types.js.map +1 -1
  79. package/dist/js/utils/rnlibraries.d.ts +1 -1
  80. package/dist/js/utils/rnlibraries.d.ts.map +1 -1
  81. package/dist/js/utils/rnlibraries.js +5 -3
  82. package/dist/js/utils/rnlibraries.js.map +1 -1
  83. package/dist/js/utils/rnlibrariesinterface.d.ts +1 -0
  84. package/dist/js/utils/rnlibrariesinterface.d.ts.map +1 -1
  85. package/dist/js/utils/rnlibrariesinterface.js.map +1 -1
  86. package/dist/js/vendor/react-native/index.d.ts +3 -0
  87. package/dist/js/vendor/react-native/index.d.ts.map +1 -1
  88. package/dist/js/vendor/react-native/index.js.map +1 -1
  89. package/dist/js/vendor/react-navigation/types.d.ts +27 -0
  90. package/dist/js/vendor/react-navigation/types.d.ts.map +1 -0
  91. package/dist/js/vendor/react-navigation/types.js +3 -0
  92. package/dist/js/vendor/react-navigation/types.js.map +1 -0
  93. package/dist/js/version.d.ts +1 -1
  94. package/dist/js/version.d.ts.map +1 -1
  95. package/dist/js/version.js +1 -1
  96. package/dist/js/version.js.map +1 -1
  97. package/dist/js/wrapper.d.ts +8 -0
  98. package/dist/js/wrapper.d.ts.map +1 -1
  99. package/dist/js/wrapper.js +34 -0
  100. package/dist/js/wrapper.js.map +1 -1
  101. package/ios/RNSentry.mm +15 -6
  102. package/ios/RNSentryBreadcrumb.m +2 -1
  103. package/ios/RNSentryFramesTrackerListener.h +7 -3
  104. package/ios/RNSentryOnDrawReporter.h +6 -2
  105. package/ios/RNSentryOnDrawReporter.m +47 -20
  106. package/ios/RNSentryReplay.mm +3 -0
  107. package/ios/RNSentryTimeToDisplay.h +7 -0
  108. package/ios/RNSentryTimeToDisplay.m +69 -2
  109. package/ios/RNSentryVersion.m +1 -1
  110. package/package.json +4 -4
  111. package/plugin/build/withSentryAndroidGradlePlugin.js +4 -4
  112. package/scripts/sentry-xcode-debug-files.sh +1 -4
  113. package/scripts/sentry-xcode.sh +1 -4
  114. package/sentry.gradle +4 -2
  115. package/src/js/NativeRNSentry.ts +2 -0
  116. package/ts3.8/dist/js/NativeRNSentry.d.ts +2 -0
  117. package/ts3.8/dist/js/index.d.ts +2 -1
  118. package/ts3.8/dist/js/integrations/appRegistry.d.ts +8 -0
  119. package/ts3.8/dist/js/integrations/exports.d.ts +2 -0
  120. package/ts3.8/dist/js/replay/mobilereplay.d.ts +23 -0
  121. package/ts3.8/dist/js/tracing/integrations/timeToDisplayIntegration.d.ts +4 -0
  122. package/ts3.8/dist/js/tracing/ops.d.ts +2 -0
  123. package/ts3.8/dist/js/tracing/reactnavigation.d.ts +20 -2
  124. package/ts3.8/dist/js/tracing/semanticAttributes.d.ts +2 -0
  125. package/ts3.8/dist/js/tracing/span.d.ts +13 -1
  126. package/ts3.8/dist/js/tracing/timeToDisplayFallback.d.ts +3 -0
  127. package/ts3.8/dist/js/tracing/timetodisplay.d.ts +29 -0
  128. package/ts3.8/dist/js/tracing/timetodisplaynative.types.d.ts +1 -3
  129. package/ts3.8/dist/js/utils/rnlibraries.d.ts +1 -1
  130. package/ts3.8/dist/js/utils/rnlibrariesinterface.d.ts +1 -0
  131. package/ts3.8/dist/js/vendor/react-native/index.d.ts +3 -0
  132. package/ts3.8/dist/js/vendor/react-navigation/types.d.ts +27 -0
  133. package/ts3.8/dist/js/version.d.ts +1 -1
  134. package/ts3.8/dist/js/wrapper.d.ts +8 -0
  135. package/dist/js/utils/sentryeventemitter.d.ts +0 -24
  136. package/dist/js/utils/sentryeventemitter.d.ts.map +0 -1
  137. package/dist/js/utils/sentryeventemitter.js +0 -82
  138. package/dist/js/utils/sentryeventemitter.js.map +0 -1
  139. package/dist/js/utils/sentryeventemitterfallback.d.ts +0 -19
  140. package/dist/js/utils/sentryeventemitterfallback.d.ts.map +0 -1
  141. package/dist/js/utils/sentryeventemitterfallback.js +0 -78
  142. package/dist/js/utils/sentryeventemitterfallback.js.map +0 -1
  143. package/ts3.8/dist/js/utils/sentryeventemitter.d.ts +0 -24
  144. package/ts3.8/dist/js/utils/sentryeventemitterfallback.d.ts +0 -19
@@ -1,15 +1,14 @@
1
- import { addBreadcrumb, getActiveSpan, getClient, isPlainObject, logger, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_OK, spanToJSON, startInactiveSpan, timestampInSeconds, } from '@sentry/core';
2
- import { createSentryFallbackEventEmitter } from '../utils/sentryeventemitterfallback';
1
+ import { addBreadcrumb, getClient, isPlainObject, logger, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_STATUS_OK, spanToJSON, startInactiveSpan, timestampInSeconds, } from '@sentry/core';
2
+ import { getAppRegistryIntegration } from '../integrations/appRegistry';
3
3
  import { isSentrySpan } from '../utils/span';
4
4
  import { RN_GLOBAL_OBJ } from '../utils/worldwide';
5
5
  import { NATIVE } from '../wrapper';
6
6
  import { ignoreEmptyBackNavigation } from './onSpanEndUtils';
7
7
  import { SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION } from './origin';
8
8
  import { getReactNativeTracingIntegration } from './reactnativetracing';
9
- import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';
9
+ import { SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';
10
10
  import { DEFAULT_NAVIGATION_SPAN_NAME, defaultIdleOptions, getDefaultIdleNavigationSpanOptions, startIdleNavigationSpan as startGenericIdleNavigationSpan, } from './span';
11
- import { manualInitialDisplaySpans, startTimeToInitialDisplaySpan } from './timetodisplay';
12
- import { setSpanDurationAsMeasurementOnSpan } from './utils';
11
+ import { addTimeToInitialDisplayFallback } from './timeToDisplayFallback';
13
12
  export const INTEGRATION_NAME = 'ReactNavigation';
14
13
  const NAVIGATION_HISTORY_MAX_SIZE = 200;
15
14
  /**
@@ -20,9 +19,8 @@ const NAVIGATION_HISTORY_MAX_SIZE = 200;
20
19
  * - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.
21
20
  * - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished.
22
21
  */
23
- export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enableTimeToInitialDisplay = false, ignoreEmptyBackNavigationTransactions = true, } = {}) => {
22
+ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enableTimeToInitialDisplay = false, ignoreEmptyBackNavigationTransactions = true, enableTimeToInitialDisplayForPreloadedRoutes = false, useDispatchedActionData = false, } = {}) => {
24
23
  let navigationContainer;
25
- let newScreenFrameEventEmitter;
26
24
  let tracing;
27
25
  let idleSpanOptions = defaultIdleOptions;
28
26
  let latestRoute;
@@ -32,8 +30,6 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
32
30
  let stateChangeTimeout;
33
31
  let recentRouteKeys = [];
34
32
  if (enableTimeToInitialDisplay) {
35
- newScreenFrameEventEmitter = createSentryFallbackEventEmitter();
36
- newScreenFrameEventEmitter.initAsync();
37
33
  NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason) => {
38
34
  logger.error(`${INTEGRATION_NAME} Failed to initialize native new frame tracking: ${reason}`);
39
35
  });
@@ -42,6 +38,7 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
42
38
  * Set the initial state and start initial navigation span for the current screen.
43
39
  */
44
40
  const afterAllSetup = (client) => {
41
+ var _a;
45
42
  tracing = getReactNativeTracingIntegration(client);
46
43
  if (tracing) {
47
44
  idleSpanOptions = {
@@ -51,8 +48,19 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
51
48
  }
52
49
  if (initialStateHandled) {
53
50
  // We create an initial state here to ensure a transaction gets created before the first route mounts.
51
+ // This assumes that the Sentry.init() call is made before the first route mounts.
52
+ // If this is not the case, the first transaction will be nameless 'Route Changed'
54
53
  return undefined;
55
54
  }
55
+ (_a = getAppRegistryIntegration(client)) === null || _a === void 0 ? void 0 : _a.onRunApplication(() => {
56
+ if (initialStateHandled) {
57
+ // To avoid conflict with the initial transaction we check if it was already handled.
58
+ // This ensures runApplication calls after the initial start are correctly traced.
59
+ // This is used for example when Activity is (re)started on Android.
60
+ logger.log('[ReactNavigationIntegration] Starting new idle navigation span based on runApplication call.');
61
+ startIdleNavigationSpan();
62
+ }
63
+ });
56
64
  startIdleNavigationSpan();
57
65
  if (!navigationContainer) {
58
66
  // This is expected as navigation container is registered after the root component is mounted.
@@ -62,22 +70,26 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
62
70
  updateLatestNavigationSpanWithCurrentRoute();
63
71
  initialStateHandled = true;
64
72
  };
65
- const registerNavigationContainer = (navigationContainerRef) => {
66
- /* We prevent duplicate routing instrumentation to be initialized on fast refreshes
67
-
68
- Explanation: If the user triggers a fast refresh on the file that the instrumentation is
69
- initialized in, it will initialize a new instance and will cause undefined behavior.
70
- */
73
+ const registerNavigationContainer = (maybeNewNavigationContainer) => {
71
74
  if (RN_GLOBAL_OBJ.__sentry_rn_v5_registered) {
72
- logger.log(`${INTEGRATION_NAME} Instrumentation already exists, but register has been called again, doing nothing.`);
73
- return undefined;
75
+ logger.debug(`${INTEGRATION_NAME} Instrumentation already exists, but registering again...`);
76
+ // In the past we have not allowed re-registering the navigation container to avoid unexpected behavior.
77
+ // But this doesn't work for Android and re-recreating application main activity.
78
+ // Where new navigation container is created and the old one is discarded. We need to re-register to
79
+ // trace the new navigation container navigation.
74
80
  }
75
- if (isPlainObject(navigationContainerRef) && 'current' in navigationContainerRef) {
76
- navigationContainer = navigationContainerRef.current;
81
+ let newNavigationContainer;
82
+ if (isPlainObject(maybeNewNavigationContainer) && 'current' in maybeNewNavigationContainer) {
83
+ newNavigationContainer = maybeNewNavigationContainer.current;
77
84
  }
78
85
  else {
79
- navigationContainer = navigationContainerRef;
86
+ newNavigationContainer = maybeNewNavigationContainer;
80
87
  }
88
+ if (navigationContainer === newNavigationContainer) {
89
+ logger.log(`${INTEGRATION_NAME} Navigation container ref is the same as the one already registered.`);
90
+ return;
91
+ }
92
+ navigationContainer = newNavigationContainer;
81
93
  if (!navigationContainer) {
82
94
  logger.warn(`${INTEGRATION_NAME} Received invalid navigation container ref!`);
83
95
  return undefined;
@@ -104,7 +116,26 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
104
116
  * It does not name the transaction or populate it with route information. Instead, it waits for the state to fully change
105
117
  * and gets the route information from there, @see updateLatestNavigationSpanWithCurrentRoute
106
118
  */
107
- const startIdleNavigationSpan = () => {
119
+ const startIdleNavigationSpan = (unknownEvent) => {
120
+ const event = unknownEvent;
121
+ if (useDispatchedActionData && (event === null || event === void 0 ? void 0 : event.data.noop)) {
122
+ logger.debug(`${INTEGRATION_NAME} Navigation action is a noop, not starting navigation span.`);
123
+ return;
124
+ }
125
+ const navigationActionType = useDispatchedActionData ? event === null || event === void 0 ? void 0 : event.data.action.type : undefined;
126
+ if (useDispatchedActionData &&
127
+ [
128
+ // Process common actions
129
+ 'PRELOAD',
130
+ 'SET_PARAMS',
131
+ // Drawer actions
132
+ 'OPEN_DRAWER',
133
+ 'CLOSE_DRAWER',
134
+ 'TOGGLE_DRAWER',
135
+ ].includes(navigationActionType)) {
136
+ logger.debug(`${INTEGRATION_NAME} Navigation action is ${navigationActionType}, not starting navigation span.`);
137
+ return;
138
+ }
108
139
  if (latestNavigationSpan) {
109
140
  logger.log(`${INTEGRATION_NAME} A transaction was detected that turned out to be a noop, discarding.`);
110
141
  _discardLatestTransaction();
@@ -114,10 +145,12 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
114
145
  ? tracing.options.beforeStartSpan(getDefaultIdleNavigationSpanOptions())
115
146
  : getDefaultIdleNavigationSpanOptions(), idleSpanOptions);
116
147
  latestNavigationSpan === null || latestNavigationSpan === void 0 ? void 0 : latestNavigationSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION);
148
+ latestNavigationSpan === null || latestNavigationSpan === void 0 ? void 0 : latestNavigationSpan.setAttribute(SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE, navigationActionType);
117
149
  if (ignoreEmptyBackNavigationTransactions) {
118
150
  ignoreEmptyBackNavigation(getClient(), latestNavigationSpan);
119
151
  }
120
152
  if (enableTimeToInitialDisplay) {
153
+ NATIVE.setActiveSpanId(latestNavigationSpan === null || latestNavigationSpan === void 0 ? void 0 : latestNavigationSpan.spanContext().spanId);
121
154
  navigationProcessingSpan = startInactiveSpan({
122
155
  op: 'navigation.processing',
123
156
  name: 'Navigation dispatch to navigation cancelled or screen mounted',
@@ -146,6 +179,7 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
146
179
  logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but navigation transaction was not started on dispatch.`);
147
180
  return undefined;
148
181
  }
182
+ addTimeToInitialDisplayFallback(latestNavigationSpan.spanContext().spanId, NATIVE.getNewScreenTimeToDisplay());
149
183
  if (previousRoute && previousRoute.key === route.key) {
150
184
  logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but route is the same as previous.`);
151
185
  pushRecentRouteKey(route.key);
@@ -155,25 +189,6 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
155
189
  return undefined;
156
190
  }
157
191
  const routeHasBeenSeen = recentRouteKeys.includes(route.key);
158
- const latestTtidSpan = !routeHasBeenSeen &&
159
- enableTimeToInitialDisplay &&
160
- startTimeToInitialDisplaySpan({
161
- name: `${route.name} initial display`,
162
- isAutoInstrumented: true,
163
- });
164
- const navigationSpanWithTtid = latestNavigationSpan;
165
- if (!routeHasBeenSeen && latestTtidSpan) {
166
- newScreenFrameEventEmitter === null || newScreenFrameEventEmitter === void 0 ? void 0 : newScreenFrameEventEmitter.onceNewFrame(({ newFrameTimestampInSeconds }) => {
167
- const activeSpan = getActiveSpan();
168
- if (activeSpan && manualInitialDisplaySpans.has(activeSpan)) {
169
- logger.warn('[ReactNavigationInstrumentation] Detected manual instrumentation for the current active span.');
170
- return;
171
- }
172
- latestTtidSpan.setStatus({ code: SPAN_STATUS_OK });
173
- latestTtidSpan.end(newFrameTimestampInSeconds);
174
- setSpanDurationAsMeasurementOnSpan('time_to_initial_display', latestTtidSpan, navigationSpanWithTtid);
175
- });
176
- }
177
192
  navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.updateName(`Navigation dispatch to screen ${route.name} mounted`);
178
193
  navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.setStatus({ code: SPAN_STATUS_OK });
179
194
  navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.end(stateChangedTimestamp);
@@ -205,7 +220,7 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
205
220
  to: route.name,
206
221
  },
207
222
  });
208
- tracing === null || tracing === void 0 ? void 0 : tracing.setCurrentRoute(route.key);
223
+ tracing === null || tracing === void 0 ? void 0 : tracing.setCurrentRoute(route.name);
209
224
  pushRecentRouteKey(route.key);
210
225
  latestRoute = route;
211
226
  // Clear the latest transaction as it has been handled.
@@ -242,6 +257,19 @@ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enable
242
257
  name: INTEGRATION_NAME,
243
258
  afterAllSetup,
244
259
  registerNavigationContainer,
260
+ options: {
261
+ routeChangeTimeoutMs,
262
+ enableTimeToInitialDisplay,
263
+ ignoreEmptyBackNavigationTransactions,
264
+ enableTimeToInitialDisplayForPreloadedRoutes,
265
+ useDispatchedActionData,
266
+ },
245
267
  };
246
268
  };
269
+ /**
270
+ * Returns React Navigation integration of the given client.
271
+ */
272
+ export function getReactNavigationIntegration(client) {
273
+ return client.getIntegrationByName(INTEGRATION_NAME);
274
+ }
247
275
  //# sourceMappingURL=reactnavigation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reactnavigation.js","sourceRoot":"","sources":["../../../src/js/tracing/reactnavigation.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, Integration, Span } from '@sentry/core';\nimport {\n addBreadcrumb,\n getActiveSpan,\n getClient,\n isPlainObject,\n logger,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_OK,\n spanToJSON,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\n\nimport type { NewFrameEvent } from '../utils/sentryeventemitter';\nimport type { SentryEventEmitterFallback } from '../utils/sentryeventemitterfallback';\nimport { createSentryFallbackEventEmitter } from '../utils/sentryeventemitterfallback';\nimport { isSentrySpan } from '../utils/span';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\nimport { NATIVE } from '../wrapper';\nimport { ignoreEmptyBackNavigation } from './onSpanEndUtils';\nimport { SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION } from './origin';\nimport type { ReactNativeTracingIntegration } from './reactnativetracing';\nimport { getReactNativeTracingIntegration } from './reactnativetracing';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';\nimport {\n DEFAULT_NAVIGATION_SPAN_NAME,\n defaultIdleOptions,\n getDefaultIdleNavigationSpanOptions,\n startIdleNavigationSpan as startGenericIdleNavigationSpan,\n} from './span';\nimport { manualInitialDisplaySpans, startTimeToInitialDisplaySpan } from './timetodisplay';\nimport { setSpanDurationAsMeasurementOnSpan } from './utils';\nexport const INTEGRATION_NAME = 'ReactNavigation';\n\nconst NAVIGATION_HISTORY_MAX_SIZE = 200;\n\ninterface ReactNavigationIntegrationOptions {\n /**\n * How long the instrumentation will wait for the route to mount after a change has been initiated,\n * before the transaction is discarded.\n *\n * @default 1_000 (ms)\n */\n routeChangeTimeoutMs: number;\n\n /**\n * Time to initial display measures the time it takes from\n * navigation dispatch to the render of the first frame of the new screen.\n *\n * @default false\n */\n enableTimeToInitialDisplay: boolean;\n\n /**\n * Does not sample transactions that are from routes that have been seen any more and don't have any spans.\n * This removes a lot of the clutter as most back navigation transactions are now ignored.\n *\n * @default true\n */\n ignoreEmptyBackNavigationTransactions: boolean;\n}\n\n/**\n * Instrumentation for React-Navigation V5 and above. See docs or sample app for usage.\n *\n * How this works:\n * - `_onDispatch` is called every time a dispatch happens and sets an IdleTransaction on the scope without any route context.\n * - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.\n * - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished.\n */\nexport const reactNavigationIntegration = ({\n routeChangeTimeoutMs = 1_000,\n enableTimeToInitialDisplay = false,\n ignoreEmptyBackNavigationTransactions = true,\n}: Partial<ReactNavigationIntegrationOptions> = {}): Integration & {\n /**\n * Pass the ref to the navigation container to register it to the instrumentation\n * @param navigationContainerRef Ref to a `NavigationContainer`\n */\n registerNavigationContainer: (navigationContainerRef: unknown) => void;\n} => {\n let navigationContainer: NavigationContainer | undefined;\n let newScreenFrameEventEmitter: SentryEventEmitterFallback | undefined;\n\n let tracing: ReactNativeTracingIntegration | undefined;\n let idleSpanOptions: Parameters<typeof startGenericIdleNavigationSpan>[1] = defaultIdleOptions;\n let latestRoute: NavigationRoute | undefined;\n\n let latestNavigationSpan: Span | undefined;\n let navigationProcessingSpan: Span | undefined;\n\n let initialStateHandled: boolean = false;\n let stateChangeTimeout: ReturnType<typeof setTimeout> | undefined;\n let recentRouteKeys: string[] = [];\n\n if (enableTimeToInitialDisplay) {\n newScreenFrameEventEmitter = createSentryFallbackEventEmitter();\n newScreenFrameEventEmitter.initAsync();\n NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason: unknown) => {\n logger.error(`${INTEGRATION_NAME} Failed to initialize native new frame tracking: ${reason}`);\n });\n }\n\n /**\n * Set the initial state and start initial navigation span for the current screen.\n */\n const afterAllSetup = (client: Client): void => {\n tracing = getReactNativeTracingIntegration(client);\n if (tracing) {\n idleSpanOptions = {\n finalTimeout: tracing.options.finalTimeoutMs,\n idleTimeout: tracing.options.idleTimeoutMs,\n };\n }\n\n if (initialStateHandled) {\n // We create an initial state here to ensure a transaction gets created before the first route mounts.\n return undefined;\n }\n\n startIdleNavigationSpan();\n\n if (!navigationContainer) {\n // This is expected as navigation container is registered after the root component is mounted.\n return undefined;\n }\n\n // Navigation container already registered, just populate with route state\n updateLatestNavigationSpanWithCurrentRoute();\n initialStateHandled = true;\n };\n\n const registerNavigationContainer = (navigationContainerRef: unknown): void => {\n /* We prevent duplicate routing instrumentation to be initialized on fast refreshes\n\n Explanation: If the user triggers a fast refresh on the file that the instrumentation is\n initialized in, it will initialize a new instance and will cause undefined behavior.\n */\n if (RN_GLOBAL_OBJ.__sentry_rn_v5_registered) {\n logger.log(\n `${INTEGRATION_NAME} Instrumentation already exists, but register has been called again, doing nothing.`,\n );\n return undefined;\n }\n\n if (isPlainObject(navigationContainerRef) && 'current' in navigationContainerRef) {\n navigationContainer = navigationContainerRef.current as NavigationContainer;\n } else {\n navigationContainer = navigationContainerRef as NavigationContainer;\n }\n if (!navigationContainer) {\n logger.warn(`${INTEGRATION_NAME} Received invalid navigation container ref!`);\n return undefined;\n }\n\n // This action is emitted on every dispatch\n navigationContainer.addListener('__unsafe_action__', startIdleNavigationSpan);\n navigationContainer.addListener('state', updateLatestNavigationSpanWithCurrentRoute);\n RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true;\n\n if (initialStateHandled) {\n return undefined;\n }\n\n if (!latestNavigationSpan) {\n logger.log(`${INTEGRATION_NAME} Navigation container registered, but integration has not been setup yet.`);\n return undefined;\n }\n\n // Navigation Container is registered after the first navigation\n // Initial navigation span was started, after integration setup,\n // so now we populate it with the current route.\n updateLatestNavigationSpanWithCurrentRoute();\n initialStateHandled = true;\n };\n\n /**\n * To be called on every React-Navigation action dispatch.\n * It does not name the transaction or populate it with route information. Instead, it waits for the state to fully change\n * and gets the route information from there, @see updateLatestNavigationSpanWithCurrentRoute\n */\n const startIdleNavigationSpan = (): void => {\n if (latestNavigationSpan) {\n logger.log(`${INTEGRATION_NAME} A transaction was detected that turned out to be a noop, discarding.`);\n _discardLatestTransaction();\n clearStateChangeTimeout();\n }\n\n latestNavigationSpan = startGenericIdleNavigationSpan(\n tracing && tracing.options.beforeStartSpan\n ? tracing.options.beforeStartSpan(getDefaultIdleNavigationSpanOptions())\n : getDefaultIdleNavigationSpanOptions(),\n idleSpanOptions,\n );\n latestNavigationSpan?.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION);\n if (ignoreEmptyBackNavigationTransactions) {\n ignoreEmptyBackNavigation(getClient(), latestNavigationSpan);\n }\n\n if (enableTimeToInitialDisplay) {\n navigationProcessingSpan = startInactiveSpan({\n op: 'navigation.processing',\n name: 'Navigation dispatch to navigation cancelled or screen mounted',\n startTime: latestNavigationSpan && spanToJSON(latestNavigationSpan).start_timestamp,\n });\n navigationProcessingSpan.setAttribute(\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,\n );\n }\n\n stateChangeTimeout = setTimeout(_discardLatestTransaction, routeChangeTimeoutMs);\n };\n\n /**\n * To be called AFTER the state has been changed to populate the transaction with the current route.\n */\n const updateLatestNavigationSpanWithCurrentRoute = (): void => {\n const stateChangedTimestamp = timestampInSeconds();\n const previousRoute = latestRoute;\n\n if (!navigationContainer) {\n logger.warn(`${INTEGRATION_NAME} Missing navigation container ref. Route transactions will not be sent.`);\n return undefined;\n }\n\n const route = navigationContainer.getCurrentRoute();\n if (!route) {\n logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but no route is rendered.`);\n return undefined;\n }\n\n if (!latestNavigationSpan) {\n logger.debug(\n `[${INTEGRATION_NAME}] Navigation state changed, but navigation transaction was not started on dispatch.`,\n );\n return undefined;\n }\n\n if (previousRoute && previousRoute.key === route.key) {\n logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but route is the same as previous.`);\n pushRecentRouteKey(route.key);\n latestRoute = route;\n\n // Clear the latest transaction as it has been handled.\n latestNavigationSpan = undefined;\n return undefined;\n }\n\n const routeHasBeenSeen = recentRouteKeys.includes(route.key);\n const latestTtidSpan =\n !routeHasBeenSeen &&\n enableTimeToInitialDisplay &&\n startTimeToInitialDisplaySpan({\n name: `${route.name} initial display`,\n isAutoInstrumented: true,\n });\n\n const navigationSpanWithTtid = latestNavigationSpan;\n if (!routeHasBeenSeen && latestTtidSpan) {\n newScreenFrameEventEmitter?.onceNewFrame(({ newFrameTimestampInSeconds }: NewFrameEvent) => {\n const activeSpan = getActiveSpan();\n if (activeSpan && manualInitialDisplaySpans.has(activeSpan)) {\n logger.warn('[ReactNavigationInstrumentation] Detected manual instrumentation for the current active span.');\n return;\n }\n\n latestTtidSpan.setStatus({ code: SPAN_STATUS_OK });\n latestTtidSpan.end(newFrameTimestampInSeconds);\n setSpanDurationAsMeasurementOnSpan('time_to_initial_display', latestTtidSpan, navigationSpanWithTtid);\n });\n }\n\n navigationProcessingSpan?.updateName(`Navigation dispatch to screen ${route.name} mounted`);\n navigationProcessingSpan?.setStatus({ code: SPAN_STATUS_OK });\n navigationProcessingSpan?.end(stateChangedTimestamp);\n navigationProcessingSpan = undefined;\n\n if (spanToJSON(latestNavigationSpan).description === DEFAULT_NAVIGATION_SPAN_NAME) {\n latestNavigationSpan.updateName(route.name);\n }\n latestNavigationSpan.setAttributes({\n 'route.name': route.name,\n 'route.key': route.key,\n // TODO: filter PII params instead of dropping them all\n // 'route.params': {},\n 'route.has_been_seen': routeHasBeenSeen,\n 'previous_route.name': previousRoute?.name,\n 'previous_route.key': previousRoute?.key,\n // TODO: filter PII params instead of dropping them all\n // 'previous_route.params': {},\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n });\n\n // Clear the timeout so the transaction does not get cancelled.\n clearStateChangeTimeout();\n\n addBreadcrumb({\n category: 'navigation',\n type: 'navigation',\n message: `Navigation to ${route.name}`,\n data: {\n from: previousRoute?.name,\n to: route.name,\n },\n });\n\n tracing?.setCurrentRoute(route.key);\n\n pushRecentRouteKey(route.key);\n latestRoute = route;\n // Clear the latest transaction as it has been handled.\n latestNavigationSpan = undefined;\n };\n\n /** Pushes a recent route key, and removes earlier routes when there is greater than the max length */\n const pushRecentRouteKey = (key: string): void => {\n recentRouteKeys.push(key);\n\n if (recentRouteKeys.length > NAVIGATION_HISTORY_MAX_SIZE) {\n recentRouteKeys = recentRouteKeys.slice(recentRouteKeys.length - NAVIGATION_HISTORY_MAX_SIZE);\n }\n };\n\n /** Cancels the latest transaction so it does not get sent to Sentry. */\n const _discardLatestTransaction = (): void => {\n if (latestNavigationSpan) {\n if (isSentrySpan(latestNavigationSpan)) {\n latestNavigationSpan['_sampled'] = false;\n }\n // TODO: What if it's not SentrySpan?\n latestNavigationSpan.end();\n latestNavigationSpan = undefined;\n }\n if (navigationProcessingSpan) {\n navigationProcessingSpan = undefined;\n }\n };\n\n const clearStateChangeTimeout = (): void => {\n if (typeof stateChangeTimeout !== 'undefined') {\n clearTimeout(stateChangeTimeout);\n stateChangeTimeout = undefined;\n }\n };\n\n return {\n name: INTEGRATION_NAME,\n afterAllSetup,\n registerNavigationContainer,\n };\n};\n\nexport interface NavigationRoute {\n name: string;\n key: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>;\n}\n\ninterface NavigationContainer {\n addListener: (type: string, listener: () => void) => void;\n getCurrentRoute: () => NavigationRoute;\n}\n"]}
1
+ {"version":3,"file":"reactnavigation.js","sourceRoot":"","sources":["../../../src/js/tracing/reactnavigation.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, Integration, Span } from '@sentry/core';\nimport {\n addBreadcrumb,\n getClient,\n isPlainObject,\n logger,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_STATUS_OK,\n spanToJSON,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\n\nimport { getAppRegistryIntegration } from '../integrations/appRegistry';\nimport { isSentrySpan } from '../utils/span';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\nimport type { UnsafeAction } from '../vendor/react-navigation/types';\nimport { NATIVE } from '../wrapper';\nimport { ignoreEmptyBackNavigation } from './onSpanEndUtils';\nimport { SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION } from './origin';\nimport type { ReactNativeTracingIntegration } from './reactnativetracing';\nimport { getReactNativeTracingIntegration } from './reactnativetracing';\nimport { SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';\nimport {\n DEFAULT_NAVIGATION_SPAN_NAME,\n defaultIdleOptions,\n getDefaultIdleNavigationSpanOptions,\n startIdleNavigationSpan as startGenericIdleNavigationSpan,\n} from './span';\nimport { addTimeToInitialDisplayFallback } from './timeToDisplayFallback';\nexport const INTEGRATION_NAME = 'ReactNavigation';\n\nconst NAVIGATION_HISTORY_MAX_SIZE = 200;\n\ninterface ReactNavigationIntegrationOptions {\n /**\n * How long the instrumentation will wait for the route to mount after a change has been initiated,\n * before the transaction is discarded.\n *\n * @default 1_000 (ms)\n */\n routeChangeTimeoutMs: number;\n\n /**\n * Time to initial display measures the time it takes from\n * navigation dispatch to the render of the first frame of the new screen.\n *\n * @default false\n */\n enableTimeToInitialDisplay: boolean;\n\n /**\n * Does not sample transactions that are from routes that have been seen any more and don't have any spans.\n * This removes a lot of the clutter as most back navigation transactions are now ignored.\n *\n * @default true\n */\n ignoreEmptyBackNavigationTransactions: boolean;\n\n /**\n * Enabled measuring Time to Initial Display for routes that are already loaded in memory.\n * (a.k.a., Routes that the navigation integration has already seen.)\n *\n * @default false\n */\n enableTimeToInitialDisplayForPreloadedRoutes: boolean;\n\n /**\n * Whether to use the dispatched action data to populate the transaction metadata.\n *\n * @default false\n */\n useDispatchedActionData: boolean;\n}\n\n/**\n * Instrumentation for React-Navigation V5 and above. See docs or sample app for usage.\n *\n * How this works:\n * - `_onDispatch` is called every time a dispatch happens and sets an IdleTransaction on the scope without any route context.\n * - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.\n * - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished.\n */\nexport const reactNavigationIntegration = ({\n routeChangeTimeoutMs = 1_000,\n enableTimeToInitialDisplay = false,\n ignoreEmptyBackNavigationTransactions = true,\n enableTimeToInitialDisplayForPreloadedRoutes = false,\n useDispatchedActionData = false,\n}: Partial<ReactNavigationIntegrationOptions> = {}): Integration & {\n /**\n * Pass the ref to the navigation container to register it to the instrumentation\n * @param navigationContainerRef Ref to a `NavigationContainer`\n */\n registerNavigationContainer: (navigationContainerRef: unknown) => void;\n options: ReactNavigationIntegrationOptions;\n} => {\n let navigationContainer: NavigationContainer | undefined;\n\n let tracing: ReactNativeTracingIntegration | undefined;\n let idleSpanOptions: Parameters<typeof startGenericIdleNavigationSpan>[1] = defaultIdleOptions;\n let latestRoute: NavigationRoute | undefined;\n\n let latestNavigationSpan: Span | undefined;\n let navigationProcessingSpan: Span | undefined;\n\n let initialStateHandled: boolean = false;\n let stateChangeTimeout: ReturnType<typeof setTimeout> | undefined;\n let recentRouteKeys: string[] = [];\n\n if (enableTimeToInitialDisplay) {\n NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason: unknown) => {\n logger.error(`${INTEGRATION_NAME} Failed to initialize native new frame tracking: ${reason}`);\n });\n }\n\n /**\n * Set the initial state and start initial navigation span for the current screen.\n */\n const afterAllSetup = (client: Client): void => {\n tracing = getReactNativeTracingIntegration(client);\n if (tracing) {\n idleSpanOptions = {\n finalTimeout: tracing.options.finalTimeoutMs,\n idleTimeout: tracing.options.idleTimeoutMs,\n };\n }\n\n if (initialStateHandled) {\n // We create an initial state here to ensure a transaction gets created before the first route mounts.\n // This assumes that the Sentry.init() call is made before the first route mounts.\n // If this is not the case, the first transaction will be nameless 'Route Changed'\n return undefined;\n }\n\n getAppRegistryIntegration(client)?.onRunApplication(() => {\n if (initialStateHandled) {\n // To avoid conflict with the initial transaction we check if it was already handled.\n // This ensures runApplication calls after the initial start are correctly traced.\n // This is used for example when Activity is (re)started on Android.\n logger.log('[ReactNavigationIntegration] Starting new idle navigation span based on runApplication call.');\n startIdleNavigationSpan();\n }\n });\n\n startIdleNavigationSpan();\n\n if (!navigationContainer) {\n // This is expected as navigation container is registered after the root component is mounted.\n return undefined;\n }\n\n // Navigation container already registered, just populate with route state\n updateLatestNavigationSpanWithCurrentRoute();\n initialStateHandled = true;\n };\n\n const registerNavigationContainer = (maybeNewNavigationContainer: unknown): void => {\n if (RN_GLOBAL_OBJ.__sentry_rn_v5_registered) {\n logger.debug(`${INTEGRATION_NAME} Instrumentation already exists, but registering again...`);\n // In the past we have not allowed re-registering the navigation container to avoid unexpected behavior.\n // But this doesn't work for Android and re-recreating application main activity.\n // Where new navigation container is created and the old one is discarded. We need to re-register to\n // trace the new navigation container navigation.\n }\n\n let newNavigationContainer: NavigationContainer | undefined;\n if (isPlainObject(maybeNewNavigationContainer) && 'current' in maybeNewNavigationContainer) {\n newNavigationContainer = maybeNewNavigationContainer.current as NavigationContainer;\n } else {\n newNavigationContainer = maybeNewNavigationContainer as NavigationContainer;\n }\n\n if (navigationContainer === newNavigationContainer) {\n logger.log(`${INTEGRATION_NAME} Navigation container ref is the same as the one already registered.`);\n return;\n }\n navigationContainer = newNavigationContainer as NavigationContainer;\n\n if (!navigationContainer) {\n logger.warn(`${INTEGRATION_NAME} Received invalid navigation container ref!`);\n return undefined;\n }\n\n // This action is emitted on every dispatch\n navigationContainer.addListener('__unsafe_action__', startIdleNavigationSpan);\n navigationContainer.addListener('state', updateLatestNavigationSpanWithCurrentRoute);\n RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true;\n\n if (initialStateHandled) {\n return undefined;\n }\n\n if (!latestNavigationSpan) {\n logger.log(`${INTEGRATION_NAME} Navigation container registered, but integration has not been setup yet.`);\n return undefined;\n }\n\n // Navigation Container is registered after the first navigation\n // Initial navigation span was started, after integration setup,\n // so now we populate it with the current route.\n updateLatestNavigationSpanWithCurrentRoute();\n initialStateHandled = true;\n };\n\n /**\n * To be called on every React-Navigation action dispatch.\n * It does not name the transaction or populate it with route information. Instead, it waits for the state to fully change\n * and gets the route information from there, @see updateLatestNavigationSpanWithCurrentRoute\n */\n const startIdleNavigationSpan = (unknownEvent?: unknown): void => {\n const event = unknownEvent as UnsafeAction | undefined;\n if (useDispatchedActionData && event?.data.noop) {\n logger.debug(`${INTEGRATION_NAME} Navigation action is a noop, not starting navigation span.`);\n return;\n }\n\n const navigationActionType = useDispatchedActionData ? event?.data.action.type : undefined;\n if (\n useDispatchedActionData &&\n [\n // Process common actions\n 'PRELOAD',\n 'SET_PARAMS',\n // Drawer actions\n 'OPEN_DRAWER',\n 'CLOSE_DRAWER',\n 'TOGGLE_DRAWER',\n ].includes(navigationActionType)\n ) {\n logger.debug(`${INTEGRATION_NAME} Navigation action is ${navigationActionType}, not starting navigation span.`);\n return;\n }\n\n if (latestNavigationSpan) {\n logger.log(`${INTEGRATION_NAME} A transaction was detected that turned out to be a noop, discarding.`);\n _discardLatestTransaction();\n clearStateChangeTimeout();\n }\n\n latestNavigationSpan = startGenericIdleNavigationSpan(\n tracing && tracing.options.beforeStartSpan\n ? tracing.options.beforeStartSpan(getDefaultIdleNavigationSpanOptions())\n : getDefaultIdleNavigationSpanOptions(),\n idleSpanOptions,\n );\n latestNavigationSpan?.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION);\n latestNavigationSpan?.setAttribute(SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE, navigationActionType);\n if (ignoreEmptyBackNavigationTransactions) {\n ignoreEmptyBackNavigation(getClient(), latestNavigationSpan);\n }\n\n if (enableTimeToInitialDisplay) {\n NATIVE.setActiveSpanId(latestNavigationSpan?.spanContext().spanId);\n navigationProcessingSpan = startInactiveSpan({\n op: 'navigation.processing',\n name: 'Navigation dispatch to navigation cancelled or screen mounted',\n startTime: latestNavigationSpan && spanToJSON(latestNavigationSpan).start_timestamp,\n });\n navigationProcessingSpan.setAttribute(\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SPAN_ORIGIN_AUTO_NAVIGATION_REACT_NAVIGATION,\n );\n }\n\n stateChangeTimeout = setTimeout(_discardLatestTransaction, routeChangeTimeoutMs);\n };\n\n /**\n * To be called AFTER the state has been changed to populate the transaction with the current route.\n */\n const updateLatestNavigationSpanWithCurrentRoute = (): void => {\n const stateChangedTimestamp = timestampInSeconds();\n const previousRoute = latestRoute;\n\n if (!navigationContainer) {\n logger.warn(`${INTEGRATION_NAME} Missing navigation container ref. Route transactions will not be sent.`);\n return undefined;\n }\n\n const route = navigationContainer.getCurrentRoute();\n if (!route) {\n logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but no route is rendered.`);\n return undefined;\n }\n\n if (!latestNavigationSpan) {\n logger.debug(\n `[${INTEGRATION_NAME}] Navigation state changed, but navigation transaction was not started on dispatch.`,\n );\n return undefined;\n }\n\n addTimeToInitialDisplayFallback(latestNavigationSpan.spanContext().spanId, NATIVE.getNewScreenTimeToDisplay());\n\n if (previousRoute && previousRoute.key === route.key) {\n logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but route is the same as previous.`);\n pushRecentRouteKey(route.key);\n latestRoute = route;\n\n // Clear the latest transaction as it has been handled.\n latestNavigationSpan = undefined;\n return undefined;\n }\n\n const routeHasBeenSeen = recentRouteKeys.includes(route.key);\n\n navigationProcessingSpan?.updateName(`Navigation dispatch to screen ${route.name} mounted`);\n navigationProcessingSpan?.setStatus({ code: SPAN_STATUS_OK });\n navigationProcessingSpan?.end(stateChangedTimestamp);\n navigationProcessingSpan = undefined;\n\n if (spanToJSON(latestNavigationSpan).description === DEFAULT_NAVIGATION_SPAN_NAME) {\n latestNavigationSpan.updateName(route.name);\n }\n latestNavigationSpan.setAttributes({\n 'route.name': route.name,\n 'route.key': route.key,\n // TODO: filter PII params instead of dropping them all\n // 'route.params': {},\n 'route.has_been_seen': routeHasBeenSeen,\n 'previous_route.name': previousRoute?.name,\n 'previous_route.key': previousRoute?.key,\n // TODO: filter PII params instead of dropping them all\n // 'previous_route.params': {},\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',\n });\n\n // Clear the timeout so the transaction does not get cancelled.\n clearStateChangeTimeout();\n\n addBreadcrumb({\n category: 'navigation',\n type: 'navigation',\n message: `Navigation to ${route.name}`,\n data: {\n from: previousRoute?.name,\n to: route.name,\n },\n });\n\n tracing?.setCurrentRoute(route.name);\n\n pushRecentRouteKey(route.key);\n latestRoute = route;\n // Clear the latest transaction as it has been handled.\n latestNavigationSpan = undefined;\n };\n\n /** Pushes a recent route key, and removes earlier routes when there is greater than the max length */\n const pushRecentRouteKey = (key: string): void => {\n recentRouteKeys.push(key);\n\n if (recentRouteKeys.length > NAVIGATION_HISTORY_MAX_SIZE) {\n recentRouteKeys = recentRouteKeys.slice(recentRouteKeys.length - NAVIGATION_HISTORY_MAX_SIZE);\n }\n };\n\n /** Cancels the latest transaction so it does not get sent to Sentry. */\n const _discardLatestTransaction = (): void => {\n if (latestNavigationSpan) {\n if (isSentrySpan(latestNavigationSpan)) {\n latestNavigationSpan['_sampled'] = false;\n }\n // TODO: What if it's not SentrySpan?\n latestNavigationSpan.end();\n latestNavigationSpan = undefined;\n }\n if (navigationProcessingSpan) {\n navigationProcessingSpan = undefined;\n }\n };\n\n const clearStateChangeTimeout = (): void => {\n if (typeof stateChangeTimeout !== 'undefined') {\n clearTimeout(stateChangeTimeout);\n stateChangeTimeout = undefined;\n }\n };\n\n return {\n name: INTEGRATION_NAME,\n afterAllSetup,\n registerNavigationContainer,\n options: {\n routeChangeTimeoutMs,\n enableTimeToInitialDisplay,\n ignoreEmptyBackNavigationTransactions,\n enableTimeToInitialDisplayForPreloadedRoutes,\n useDispatchedActionData,\n },\n };\n};\n\nexport interface NavigationRoute {\n name: string;\n key: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n params?: Record<string, any>;\n}\n\ninterface NavigationContainer {\n addListener: (type: string, listener: (event?: unknown) => void) => void;\n getCurrentRoute: () => NavigationRoute;\n}\n\n/**\n * Returns React Navigation integration of the given client.\n */\nexport function getReactNavigationIntegration(\n client: Client,\n): ReturnType<typeof reactNavigationIntegration> | undefined {\n return client.getIntegrationByName<ReturnType<typeof reactNavigationIntegration>>(INTEGRATION_NAME);\n}\n"]}
@@ -9,4 +9,6 @@ export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = "previous_route.na
9
9
  export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = "previous_route.key";
10
10
  export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = "previous_route.component_id";
11
11
  export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = "previous_route.component_type";
12
+ export declare const SEMANTIC_ATTRIBUTE_TIME_TO_INITIAL_DISPLAY_FALLBACK = "route.initial_display_fallback";
13
+ export declare const SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE = "navigation.action_type";
12
14
  //# sourceMappingURL=semanticAttributes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"semanticAttributes.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/semanticAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,4BAA4B,EAC5B,qCAAqC,EACrC,iDAAiD,GAClD,MAAM,cAAc,CAAC;AAEtB,eAAO,MAAM,0CAA0C,4BAA4B,CAAC;AACpF,eAAO,MAAM,6BAA6B,eAAe,CAAC;AAC1D,eAAO,MAAM,4BAA4B,cAAc,CAAC;AACxD,eAAO,MAAM,qCAAqC,uBAAuB,CAAC;AAC1E,eAAO,MAAM,uCAAuC,yBAAyB,CAAC;AAC9E,eAAO,MAAM,sCAAsC,wBAAwB,CAAC;AAC5E,eAAO,MAAM,sCAAsC,wBAAwB,CAAC;AAC5E,eAAO,MAAM,qCAAqC,uBAAuB,CAAC;AAC1E,eAAO,MAAM,8CAA8C,gCAAgC,CAAC;AAC5F,eAAO,MAAM,gDAAgD,kCAAkC,CAAC"}
1
+ {"version":3,"file":"semanticAttributes.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/semanticAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,4BAA4B,EAC5B,qCAAqC,EACrC,iDAAiD,GAClD,MAAM,cAAc,CAAC;AAEtB,eAAO,MAAM,0CAA0C,4BAA4B,CAAC;AACpF,eAAO,MAAM,6BAA6B,eAAe,CAAC;AAC1D,eAAO,MAAM,4BAA4B,cAAc,CAAC;AACxD,eAAO,MAAM,qCAAqC,uBAAuB,CAAC;AAC1E,eAAO,MAAM,uCAAuC,yBAAyB,CAAC;AAC9E,eAAO,MAAM,sCAAsC,wBAAwB,CAAC;AAC5E,eAAO,MAAM,sCAAsC,wBAAwB,CAAC;AAC5E,eAAO,MAAM,qCAAqC,uBAAuB,CAAC;AAC1E,eAAO,MAAM,8CAA8C,gCAAgC,CAAC;AAC5F,eAAO,MAAM,gDAAgD,kCAAkC,CAAC;AAChG,eAAO,MAAM,mDAAmD,mCAAmC,CAAC;AACpG,eAAO,MAAM,yCAAyC,2BAA2B,CAAC"}
@@ -9,4 +9,6 @@ export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = 'previous_route.name';
9
9
  export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = 'previous_route.key';
10
10
  export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = 'previous_route.component_id';
11
11
  export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = 'previous_route.component_type';
12
+ export const SEMANTIC_ATTRIBUTE_TIME_TO_INITIAL_DISPLAY_FALLBACK = 'route.initial_display_fallback';
13
+ export const SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE = 'navigation.action_type';
12
14
  //# sourceMappingURL=semanticAttributes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"semanticAttributes.js","sourceRoot":"","sources":["../../../src/js/tracing/semanticAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,4BAA4B,EAC5B,qCAAqC,EACrC,iDAAiD,GAClD,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,0CAA0C,GAAG,yBAAyB,CAAC;AACpF,MAAM,CAAC,MAAM,6BAA6B,GAAG,YAAY,CAAC;AAC1D,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CAAC;AACxD,MAAM,CAAC,MAAM,qCAAqC,GAAG,oBAAoB,CAAC;AAC1E,MAAM,CAAC,MAAM,uCAAuC,GAAG,sBAAsB,CAAC;AAC9E,MAAM,CAAC,MAAM,sCAAsC,GAAG,qBAAqB,CAAC;AAC5E,MAAM,CAAC,MAAM,sCAAsC,GAAG,qBAAqB,CAAC;AAC5E,MAAM,CAAC,MAAM,qCAAqC,GAAG,oBAAoB,CAAC;AAC1E,MAAM,CAAC,MAAM,8CAA8C,GAAG,6BAA6B,CAAC;AAC5F,MAAM,CAAC,MAAM,gDAAgD,GAAG,+BAA+B,CAAC","sourcesContent":["export {\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n} from '@sentry/core';\n\nexport const SEMANTIC_ATTRIBUTE_ROUTING_INSTRUMENTATION = 'routing.instrumentation';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_NAME = 'route.name';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_KEY = 'route.key';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_ID = 'route.component_id';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_TYPE = 'route.component_type';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_HAS_BEEN_SEEN = 'route.has_been_seen';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = 'previous_route.name';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = 'previous_route.key';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = 'previous_route.component_id';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = 'previous_route.component_type';\n"]}
1
+ {"version":3,"file":"semanticAttributes.js","sourceRoot":"","sources":["../../../src/js/tracing/semanticAttributes.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,4BAA4B,EAC5B,qCAAqC,EACrC,iDAAiD,GAClD,MAAM,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,0CAA0C,GAAG,yBAAyB,CAAC;AACpF,MAAM,CAAC,MAAM,6BAA6B,GAAG,YAAY,CAAC;AAC1D,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CAAC;AACxD,MAAM,CAAC,MAAM,qCAAqC,GAAG,oBAAoB,CAAC;AAC1E,MAAM,CAAC,MAAM,uCAAuC,GAAG,sBAAsB,CAAC;AAC9E,MAAM,CAAC,MAAM,sCAAsC,GAAG,qBAAqB,CAAC;AAC5E,MAAM,CAAC,MAAM,sCAAsC,GAAG,qBAAqB,CAAC;AAC5E,MAAM,CAAC,MAAM,qCAAqC,GAAG,oBAAoB,CAAC;AAC1E,MAAM,CAAC,MAAM,8CAA8C,GAAG,6BAA6B,CAAC;AAC5F,MAAM,CAAC,MAAM,gDAAgD,GAAG,+BAA+B,CAAC;AAChG,MAAM,CAAC,MAAM,mDAAmD,GAAG,gCAAgC,CAAC;AACpG,MAAM,CAAC,MAAM,yCAAyC,GAAG,wBAAwB,CAAC","sourcesContent":["export {\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n} from '@sentry/core';\n\nexport const SEMANTIC_ATTRIBUTE_ROUTING_INSTRUMENTATION = 'routing.instrumentation';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_NAME = 'route.name';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_KEY = 'route.key';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_ID = 'route.component_id';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_TYPE = 'route.component_type';\nexport const SEMANTIC_ATTRIBUTE_ROUTE_HAS_BEEN_SEEN = 'route.has_been_seen';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = 'previous_route.name';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = 'previous_route.key';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = 'previous_route.component_id';\nexport const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = 'previous_route.component_type';\nexport const SEMANTIC_ATTRIBUTE_TIME_TO_INITIAL_DISPLAY_FALLBACK = 'route.initial_display_fallback';\nexport const SEMANTIC_ATTRIBUTE_NAVIGATION_ACTION_TYPE = 'navigation.action_type';\n"]}
@@ -1,4 +1,4 @@
1
- import type { Client, Scope, Span, StartSpanOptions } from '@sentry/core';
1
+ import type { Client, Scope, Span, SpanJSON, StartSpanOptions } from '@sentry/core';
2
2
  export declare const DEFAULT_NAVIGATION_SPAN_NAME = "Route Change";
3
3
  export declare const defaultIdleOptions: {
4
4
  /**
@@ -48,4 +48,16 @@ export declare function clearActiveSpanFromScope(scope: ScopeWithMaybeSpan): voi
48
48
  * Ensures that all created spans have an operation name.
49
49
  */
50
50
  export declare function addDefaultOpForSpanFrom(client: Client): void;
51
+ export declare const SPAN_THREAD_NAME = "thread.name";
52
+ export declare const SPAN_THREAD_NAME_MAIN = "main";
53
+ export declare const SPAN_THREAD_NAME_JAVASCRIPT = "javascript";
54
+ /**
55
+ * Adds Javascript thread info to spans.
56
+ * Ref: https://reactnative.dev/architecture/threading-model
57
+ */
58
+ export declare function addThreadInfoToSpan(client: Client): void;
59
+ /**
60
+ * Sets the Main thread info to the span.
61
+ */
62
+ export declare function setMainThreadInfo(spanJSON: SpanJSON): SpanJSON;
51
63
  //# sourceMappingURL=span.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"span.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/span.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAuB1E,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAE3D,eAAO,MAAM,kBAAkB,EAAE;IAC/B;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAC;CAIrB,CAAC;AAEF,eAAO,MAAM,uBAAuB,oBACjB,gBAAgB,mCAI9B,QAAQ,yBAAyB,CAAC,KACpC,IAAI,GAAG,SAmCT,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,oBACP,gBAAgB;kBACc,MAAM,GAAG,SAAS;iBAAe,MAAM,GAAG,SAAS;MACjG,IAYF,CAAC;AAEF;;GAEG;AACH,wBAAgB,mCAAmC,IAAI,gBAAgB,CAOtE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE3D;AAED,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG;IACvC,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAGxE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAM5D"}
1
+ {"version":3,"file":"span.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/span.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAuBpF,eAAO,MAAM,4BAA4B,iBAAiB,CAAC;AAE3D,eAAO,MAAM,kBAAkB,EAAE;IAC/B;;;;;OAKG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAC;CAIrB,CAAC;AAEF,eAAO,MAAM,uBAAuB,oBACjB,gBAAgB,mCAI9B,QAAQ,yBAAyB,CAAC,KACpC,IAAI,GAAG,SAmCT,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,oBACP,gBAAgB;kBACc,MAAM,GAAG,SAAS;iBAAe,MAAM,GAAG,SAAS;MACjG,IAYF,CAAC;AAEF;;GAEG;AACH,wBAAgB,mCAAmC,IAAI,gBAAgB,CAOtE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE3D;AAED,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG;IACvC,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAGxE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAM5D;AAED,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAC9C,eAAO,MAAM,qBAAqB,SAAS,CAAC;AAC5C,eAAO,MAAM,2BAA2B,eAAe,CAAC;AAExD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAMxD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,CAI9D"}
@@ -80,4 +80,27 @@ export function addDefaultOpForSpanFrom(client) {
80
80
  }
81
81
  });
82
82
  }
83
+ export const SPAN_THREAD_NAME = 'thread.name';
84
+ export const SPAN_THREAD_NAME_MAIN = 'main';
85
+ export const SPAN_THREAD_NAME_JAVASCRIPT = 'javascript';
86
+ /**
87
+ * Adds Javascript thread info to spans.
88
+ * Ref: https://reactnative.dev/architecture/threading-model
89
+ */
90
+ export function addThreadInfoToSpan(client) {
91
+ client.on('spanStart', (span) => {
92
+ var _a;
93
+ if (!((_a = spanToJSON(span).data) === null || _a === void 0 ? void 0 : _a[SPAN_THREAD_NAME])) {
94
+ span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT);
95
+ }
96
+ });
97
+ }
98
+ /**
99
+ * Sets the Main thread info to the span.
100
+ */
101
+ export function setMainThreadInfo(spanJSON) {
102
+ spanJSON.data = spanJSON.data || {};
103
+ spanJSON.data[SPAN_THREAD_NAME] = SPAN_THREAD_NAME_MAIN;
104
+ return spanJSON;
105
+ }
83
106
  //# sourceMappingURL=span.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"span.js","sourceRoot":"","sources":["../../../src/js/tracing/span.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Scope, Span, StartSpanOptions } from '@sentry/core';\nimport {\n generatePropagationContext,\n getActiveSpan,\n getClient,\n getCurrentScope,\n logger,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n SPAN_STATUS_ERROR,\n spanToJSON,\n startIdleSpan as coreStartIdleSpan,\n} from '@sentry/core';\n\nimport { isRootSpan } from '../utils/span';\nimport { adjustTransactionDuration, cancelInBackground } from './onSpanEndUtils';\nimport {\n SPAN_ORIGIN_AUTO_INTERACTION,\n SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM,\n SPAN_ORIGIN_MANUAL_INTERACTION,\n} from './origin';\n\nexport const DEFAULT_NAVIGATION_SPAN_NAME = 'Route Change';\n\nexport const defaultIdleOptions: {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * @default 1_000 (ms)\n */\n finalTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * @default 60_0000 (ms)\n */\n idleTimeout: number;\n} = {\n idleTimeout: 1_000,\n finalTimeout: 60_0000,\n};\n\nexport const startIdleNavigationSpan = (\n startSpanOption: StartSpanOptions,\n {\n finalTimeout = defaultIdleOptions.finalTimeout,\n idleTimeout = defaultIdleOptions.idleTimeout,\n }: Partial<typeof defaultIdleOptions> = {},\n): Span | undefined => {\n const client = getClient();\n if (!client) {\n logger.warn(`[startIdleNavigationSpan] Can't create route change span, missing client.`);\n return undefined;\n }\n\n const activeSpan = getActiveSpan();\n clearActiveSpanFromScope(getCurrentScope());\n if (activeSpan && isRootSpan(activeSpan) && isSentryInteractionSpan(activeSpan)) {\n logger.log(\n `[startIdleNavigationSpan] Canceling ${\n spanToJSON(activeSpan).op\n } transaction because of a new navigation root span.`,\n );\n activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n activeSpan.end();\n }\n\n const finalStartStapOptions = {\n ...getDefaultIdleNavigationSpanOptions(),\n ...startSpanOption,\n };\n\n const idleSpan = startIdleSpan(finalStartStapOptions, { finalTimeout, idleTimeout });\n logger.log(\n `[startIdleNavigationSpan] Starting ${finalStartStapOptions.op || 'unknown op'} transaction \"${\n finalStartStapOptions.name\n }\" on scope`,\n );\n\n adjustTransactionDuration(client, idleSpan, finalTimeout);\n\n idleSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM);\n return idleSpan;\n};\n\n/**\n * Starts an idle span from `@sentry/core` with React Native application\n * context awareness.\n *\n * - Span will be started with new propagation context.\n * - Span will be canceled if the app goes to background.\n */\nexport const startIdleSpan = (\n startSpanOption: StartSpanOptions,\n { finalTimeout, idleTimeout }: { finalTimeout: number | undefined; idleTimeout: number | undefined },\n): Span => {\n const client = getClient();\n if (!client) {\n logger.warn(`[startIdleSpan] Can't create idle span, missing client.`);\n return new SentryNonRecordingSpan();\n }\n\n getCurrentScope().setPropagationContext(generatePropagationContext());\n\n const span = coreStartIdleSpan(startSpanOption, { finalTimeout, idleTimeout });\n cancelInBackground(client, span);\n return span;\n};\n\n/**\n * Returns the default options for the idle navigation span.\n */\nexport function getDefaultIdleNavigationSpanOptions(): StartSpanOptions {\n return {\n name: DEFAULT_NAVIGATION_SPAN_NAME,\n op: 'navigation',\n forceTransaction: true,\n scope: getCurrentScope(),\n };\n}\n\n/**\n * Checks if the span is a Sentry User Interaction span.\n */\nexport function isSentryInteractionSpan(span: Span): boolean {\n return [SPAN_ORIGIN_AUTO_INTERACTION, SPAN_ORIGIN_MANUAL_INTERACTION].includes(spanToJSON(span).origin);\n}\n\nexport const SCOPE_SPAN_FIELD = '_sentrySpan';\n\nexport type ScopeWithMaybeSpan = Scope & {\n [SCOPE_SPAN_FIELD]?: Span;\n};\n\n/**\n * Removes the active span from the scope.\n */\nexport function clearActiveSpanFromScope(scope: ScopeWithMaybeSpan): void {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete scope[SCOPE_SPAN_FIELD];\n}\n\n/**\n * Ensures that all created spans have an operation name.\n */\nexport function addDefaultOpForSpanFrom(client: Client): void {\n client.on('spanStart', (span: Span) => {\n if (!spanToJSON(span).op) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'default');\n }\n });\n}\n"]}
1
+ {"version":3,"file":"span.js","sourceRoot":"","sources":["../../../src/js/tracing/span.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Client, Scope, Span, SpanJSON, StartSpanOptions } from '@sentry/core';\nimport {\n generatePropagationContext,\n getActiveSpan,\n getClient,\n getCurrentScope,\n logger,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n SPAN_STATUS_ERROR,\n spanToJSON,\n startIdleSpan as coreStartIdleSpan,\n} from '@sentry/core';\n\nimport { isRootSpan } from '../utils/span';\nimport { adjustTransactionDuration, cancelInBackground } from './onSpanEndUtils';\nimport {\n SPAN_ORIGIN_AUTO_INTERACTION,\n SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM,\n SPAN_ORIGIN_MANUAL_INTERACTION,\n} from './origin';\n\nexport const DEFAULT_NAVIGATION_SPAN_NAME = 'Route Change';\n\nexport const defaultIdleOptions: {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * @default 1_000 (ms)\n */\n finalTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * @default 60_0000 (ms)\n */\n idleTimeout: number;\n} = {\n idleTimeout: 1_000,\n finalTimeout: 60_0000,\n};\n\nexport const startIdleNavigationSpan = (\n startSpanOption: StartSpanOptions,\n {\n finalTimeout = defaultIdleOptions.finalTimeout,\n idleTimeout = defaultIdleOptions.idleTimeout,\n }: Partial<typeof defaultIdleOptions> = {},\n): Span | undefined => {\n const client = getClient();\n if (!client) {\n logger.warn(`[startIdleNavigationSpan] Can't create route change span, missing client.`);\n return undefined;\n }\n\n const activeSpan = getActiveSpan();\n clearActiveSpanFromScope(getCurrentScope());\n if (activeSpan && isRootSpan(activeSpan) && isSentryInteractionSpan(activeSpan)) {\n logger.log(\n `[startIdleNavigationSpan] Canceling ${\n spanToJSON(activeSpan).op\n } transaction because of a new navigation root span.`,\n );\n activeSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });\n activeSpan.end();\n }\n\n const finalStartStapOptions = {\n ...getDefaultIdleNavigationSpanOptions(),\n ...startSpanOption,\n };\n\n const idleSpan = startIdleSpan(finalStartStapOptions, { finalTimeout, idleTimeout });\n logger.log(\n `[startIdleNavigationSpan] Starting ${finalStartStapOptions.op || 'unknown op'} transaction \"${\n finalStartStapOptions.name\n }\" on scope`,\n );\n\n adjustTransactionDuration(client, idleSpan, finalTimeout);\n\n idleSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SPAN_ORIGIN_AUTO_NAVIGATION_CUSTOM);\n return idleSpan;\n};\n\n/**\n * Starts an idle span from `@sentry/core` with React Native application\n * context awareness.\n *\n * - Span will be started with new propagation context.\n * - Span will be canceled if the app goes to background.\n */\nexport const startIdleSpan = (\n startSpanOption: StartSpanOptions,\n { finalTimeout, idleTimeout }: { finalTimeout: number | undefined; idleTimeout: number | undefined },\n): Span => {\n const client = getClient();\n if (!client) {\n logger.warn(`[startIdleSpan] Can't create idle span, missing client.`);\n return new SentryNonRecordingSpan();\n }\n\n getCurrentScope().setPropagationContext(generatePropagationContext());\n\n const span = coreStartIdleSpan(startSpanOption, { finalTimeout, idleTimeout });\n cancelInBackground(client, span);\n return span;\n};\n\n/**\n * Returns the default options for the idle navigation span.\n */\nexport function getDefaultIdleNavigationSpanOptions(): StartSpanOptions {\n return {\n name: DEFAULT_NAVIGATION_SPAN_NAME,\n op: 'navigation',\n forceTransaction: true,\n scope: getCurrentScope(),\n };\n}\n\n/**\n * Checks if the span is a Sentry User Interaction span.\n */\nexport function isSentryInteractionSpan(span: Span): boolean {\n return [SPAN_ORIGIN_AUTO_INTERACTION, SPAN_ORIGIN_MANUAL_INTERACTION].includes(spanToJSON(span).origin);\n}\n\nexport const SCOPE_SPAN_FIELD = '_sentrySpan';\n\nexport type ScopeWithMaybeSpan = Scope & {\n [SCOPE_SPAN_FIELD]?: Span;\n};\n\n/**\n * Removes the active span from the scope.\n */\nexport function clearActiveSpanFromScope(scope: ScopeWithMaybeSpan): void {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete scope[SCOPE_SPAN_FIELD];\n}\n\n/**\n * Ensures that all created spans have an operation name.\n */\nexport function addDefaultOpForSpanFrom(client: Client): void {\n client.on('spanStart', (span: Span) => {\n if (!spanToJSON(span).op) {\n span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'default');\n }\n });\n}\n\nexport const SPAN_THREAD_NAME = 'thread.name';\nexport const SPAN_THREAD_NAME_MAIN = 'main';\nexport const SPAN_THREAD_NAME_JAVASCRIPT = 'javascript';\n\n/**\n * Adds Javascript thread info to spans.\n * Ref: https://reactnative.dev/architecture/threading-model\n */\nexport function addThreadInfoToSpan(client: Client): void {\n client.on('spanStart', (span: Span) => {\n if (!spanToJSON(span).data?.[SPAN_THREAD_NAME]) {\n span.setAttribute(SPAN_THREAD_NAME, SPAN_THREAD_NAME_JAVASCRIPT);\n }\n });\n}\n\n/**\n * Sets the Main thread info to the span.\n */\nexport function setMainThreadInfo(spanJSON: SpanJSON): SpanJSON {\n spanJSON.data = spanJSON.data || {};\n spanJSON.data[SPAN_THREAD_NAME] = SPAN_THREAD_NAME_MAIN;\n return spanJSON;\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export declare const addTimeToInitialDisplayFallback: (spanId: string, timestampSeconds: Promise<number | undefined | null>) => void;
2
+ export declare const getTimeToInitialDisplayFallback: (spanId: string) => Promise<number | undefined>;
3
+ //# sourceMappingURL=timeToDisplayFallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeToDisplayFallback.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/timeToDisplayFallback.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,+BAA+B,WAClC,MAAM,oBACI,QAAQ,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC,KACnD,IAEF,CAAC;AAEF,eAAO,MAAM,+BAA+B,WAAkB,MAAM,KAAG,QAAQ,MAAM,GAAG,SAAS,CAEhG,CAAC"}
@@ -0,0 +1,21 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { AsyncExpiringMap } from '../utils/AsyncExpiringMap';
11
+ const TIME_TO_DISPLAY_FALLBACK_TTL_MS = 60000;
12
+ const spanIdToTimeToInitialDisplayFallback = new AsyncExpiringMap({
13
+ ttl: TIME_TO_DISPLAY_FALLBACK_TTL_MS,
14
+ });
15
+ export const addTimeToInitialDisplayFallback = (spanId, timestampSeconds) => {
16
+ spanIdToTimeToInitialDisplayFallback.set(spanId, timestampSeconds);
17
+ };
18
+ export const getTimeToInitialDisplayFallback = (spanId) => __awaiter(void 0, void 0, void 0, function* () {
19
+ return spanIdToTimeToInitialDisplayFallback.get(spanId);
20
+ });
21
+ //# sourceMappingURL=timeToDisplayFallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeToDisplayFallback.js","sourceRoot":"","sources":["../../../src/js/tracing/timeToDisplayFallback.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,+BAA+B,GAAG,KAAM,CAAC;AAE/C,MAAM,oCAAoC,GAAwD,IAAI,gBAAgB,CAAC;IACrH,GAAG,EAAE,+BAA+B;CACrC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAC7C,MAAc,EACd,gBAAoD,EAC9C,EAAE;IACR,oCAAoC,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AACrE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,+BAA+B,GAAG,CAAO,MAAc,EAA+B,EAAE;IACnG,OAAO,oCAAoC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAC1D,CAAC,CAAA,CAAC","sourcesContent":["import { AsyncExpiringMap } from '../utils/AsyncExpiringMap';\n\nconst TIME_TO_DISPLAY_FALLBACK_TTL_MS = 60_000;\n\nconst spanIdToTimeToInitialDisplayFallback: AsyncExpiringMap<string, number | undefined | null> = new AsyncExpiringMap({\n ttl: TIME_TO_DISPLAY_FALLBACK_TTL_MS,\n});\n\nexport const addTimeToInitialDisplayFallback = (\n spanId: string,\n timestampSeconds: Promise<number | undefined | null>,\n): void => {\n spanIdToTimeToInitialDisplayFallback.set(spanId, timestampSeconds);\n};\n\nexport const getTimeToInitialDisplayFallback = async (spanId: string): Promise<number | undefined> => {\n return spanIdToTimeToInitialDisplayFallback.get(spanId);\n};\n"]}
@@ -28,6 +28,8 @@ export declare function TimeToFullDisplay(props: TimeToDisplayProps): React.Reac
28
28
  * Starts a new span for the initial display.
29
29
  *
30
30
  * Returns current span if already exists in the currently active span.
31
+ *
32
+ * @deprecated Use `<TimeToInitialDisplay record={boolean}/>` component instead.
31
33
  */
32
34
  export declare function startTimeToInitialDisplaySpan(options?: Omit<StartSpanOptions, 'op' | 'name'> & {
33
35
  name?: string;
@@ -37,10 +39,37 @@ export declare function startTimeToInitialDisplaySpan(options?: Omit<StartSpanOp
37
39
  * Starts a new span for the full display.
38
40
  *
39
41
  * Returns current span if already exists in the currently active span.
42
+ *
43
+ * @deprecated Use `<TimeToFullDisplay record={boolean}/>` component instead.
40
44
  */
41
45
  export declare function startTimeToFullDisplaySpan(options?: Omit<StartSpanOptions, 'op' | 'name'> & {
42
46
  name?: string;
43
47
  timeoutMs?: number;
44
48
  isAutoInstrumented?: boolean;
45
49
  }): Span | undefined;
50
+ /**
51
+ *
52
+ */
53
+ export declare function updateInitialDisplaySpan(frameTimestampSeconds: number, { activeSpan, span, }?: {
54
+ activeSpan?: Span;
55
+ /**
56
+ * Time to initial display span to update.
57
+ */
58
+ span?: Span;
59
+ }): void;
60
+ /**
61
+ * Creates a new TimeToFullDisplay component which triggers the full display recording every time the component is focused.
62
+ */
63
+ export declare function createTimeToFullDisplay({ useFocusEffect, }: {
64
+ /**
65
+ * `@react-navigation/native` useFocusEffect hook.
66
+ */
67
+ useFocusEffect: (callback: () => void) => void;
68
+ }): React.ComponentType<TimeToDisplayProps>;
69
+ /**
70
+ * Creates a new TimeToInitialDisplay component which triggers the initial display recording every time the component is focused.
71
+ */
72
+ export declare function createTimeToInitialDisplay({ useFocusEffect, }: {
73
+ useFocusEffect: (callback: () => void) => void;
74
+ }): React.ComponentType<TimeToDisplayProps>;
46
75
  //# sourceMappingURL=timetodisplay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timetodisplay.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/timetodisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAC,gBAAgB,EAAG,MAAM,cAAc,CAAC;AAE3D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B;;GAEG;AACH,eAAO,MAAM,yBAAyB,qBAA4B,CAAC;AAOnE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAQlF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAG/E;AAgCD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,GACA,IAAI,GAAG,SAAS,CAgClB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAG7B,GACA,IAAI,GAAG,SAAS,CAqDlB"}
1
+ {"version":3,"file":"timetodisplay.d.ts","sourceRoot":"","sources":["../../../src/js/tracing/timetodisplay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAC,gBAAgB,EAAG,MAAM,cAAc,CAAC;AAE3D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B;;GAEG;AACH,eAAO,MAAM,yBAAyB,qBAA4B,CAAC;AAOnE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAQlF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAI/E;AA+BD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,GACA,IAAI,GAAG,SAAS,CAgClB;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,OAAO,GAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAG7B,GACA,IAAI,GAAG,SAAS,CAqDlB;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,qBAAqB,EAAE,MAAM,EAC7B,EACE,UAA4B,EAC5B,IAAsC,GACvC,GAAE;IACD,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;CACR,GAAG,IAAI,CAgCd;AA6CD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,cAAc,GACf,EAAE;IACD;;OAEG;IACH,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;CAC/C,GAAG,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAE1C;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,cAAc,GACf,EAAE;IACD,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAA;CAC/C,GAAG,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAE1C"}