@sentry/react-native 5.29.0 → 6.0.0-alpha.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 (280) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/dist/js/client.d.ts +5 -9
  3. package/dist/js/client.d.ts.map +1 -1
  4. package/dist/js/client.js +11 -42
  5. package/dist/js/client.js.map +1 -1
  6. package/dist/js/index.d.ts +5 -10
  7. package/dist/js/index.d.ts.map +1 -1
  8. package/dist/js/index.js +4 -21
  9. package/dist/js/index.js.map +1 -1
  10. package/dist/js/integrations/debugsymbolicator.d.ts +2 -8
  11. package/dist/js/integrations/debugsymbolicator.d.ts.map +1 -1
  12. package/dist/js/integrations/debugsymbolicator.js +1 -9
  13. package/dist/js/integrations/debugsymbolicator.js.map +1 -1
  14. package/dist/js/integrations/default.d.ts.map +1 -1
  15. package/dist/js/integrations/default.js +18 -7
  16. package/dist/js/integrations/default.js.map +1 -1
  17. package/dist/js/integrations/devicecontext.d.ts +2 -8
  18. package/dist/js/integrations/devicecontext.d.ts.map +1 -1
  19. package/dist/js/integrations/devicecontext.js +0 -9
  20. package/dist/js/integrations/devicecontext.js.map +1 -1
  21. package/dist/js/integrations/eventorigin.d.ts +2 -8
  22. package/dist/js/integrations/eventorigin.d.ts.map +1 -1
  23. package/dist/js/integrations/eventorigin.js +0 -8
  24. package/dist/js/integrations/eventorigin.js.map +1 -1
  25. package/dist/js/integrations/expocontext.d.ts +2 -8
  26. package/dist/js/integrations/expocontext.d.ts.map +1 -1
  27. package/dist/js/integrations/expocontext.js +0 -8
  28. package/dist/js/integrations/expocontext.js.map +1 -1
  29. package/dist/js/integrations/exports.d.ts +4 -0
  30. package/dist/js/integrations/exports.d.ts.map +1 -1
  31. package/dist/js/integrations/exports.js +4 -0
  32. package/dist/js/integrations/exports.js.map +1 -1
  33. package/dist/js/integrations/modulesloader.d.ts +2 -8
  34. package/dist/js/integrations/modulesloader.d.ts.map +1 -1
  35. package/dist/js/integrations/modulesloader.js +0 -8
  36. package/dist/js/integrations/modulesloader.js.map +1 -1
  37. package/dist/js/integrations/nativelinkederrors.d.ts +2 -8
  38. package/dist/js/integrations/nativelinkederrors.d.ts.map +1 -1
  39. package/dist/js/integrations/nativelinkederrors.js +0 -8
  40. package/dist/js/integrations/nativelinkederrors.js.map +1 -1
  41. package/dist/js/integrations/reactnativeerrorhandlers.d.ts +2 -8
  42. package/dist/js/integrations/reactnativeerrorhandlers.d.ts.map +1 -1
  43. package/dist/js/integrations/reactnativeerrorhandlers.js +1 -8
  44. package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
  45. package/dist/js/integrations/reactnativeinfo.d.ts +2 -8
  46. package/dist/js/integrations/reactnativeinfo.d.ts.map +1 -1
  47. package/dist/js/integrations/reactnativeinfo.js +0 -8
  48. package/dist/js/integrations/reactnativeinfo.js.map +1 -1
  49. package/dist/js/integrations/release.d.ts +2 -8
  50. package/dist/js/integrations/release.d.ts.map +1 -1
  51. package/dist/js/integrations/release.js +0 -8
  52. package/dist/js/integrations/release.js.map +1 -1
  53. package/dist/js/integrations/rewriteframes.js +1 -1
  54. package/dist/js/integrations/rewriteframes.js.map +1 -1
  55. package/dist/js/integrations/screenshot.d.ts +2 -8
  56. package/dist/js/integrations/screenshot.d.ts.map +1 -1
  57. package/dist/js/integrations/screenshot.js +2 -11
  58. package/dist/js/integrations/screenshot.js.map +1 -1
  59. package/dist/js/integrations/sdkinfo.d.ts +2 -8
  60. package/dist/js/integrations/sdkinfo.d.ts.map +1 -1
  61. package/dist/js/integrations/sdkinfo.js +0 -8
  62. package/dist/js/integrations/sdkinfo.js.map +1 -1
  63. package/dist/js/integrations/spotlight.d.ts +2 -10
  64. package/dist/js/integrations/spotlight.d.ts.map +1 -1
  65. package/dist/js/integrations/spotlight.js +1 -10
  66. package/dist/js/integrations/spotlight.js.map +1 -1
  67. package/dist/js/integrations/viewhierarchy.d.ts +2 -8
  68. package/dist/js/integrations/viewhierarchy.d.ts.map +1 -1
  69. package/dist/js/integrations/viewhierarchy.js +0 -8
  70. package/dist/js/integrations/viewhierarchy.js.map +1 -1
  71. package/dist/js/options.d.ts +43 -0
  72. package/dist/js/options.d.ts.map +1 -1
  73. package/dist/js/options.js.map +1 -1
  74. package/dist/js/profiling/cache.d.ts +1 -1
  75. package/dist/js/profiling/hermes.d.ts +1 -1
  76. package/dist/js/profiling/hermes.d.ts.map +1 -1
  77. package/dist/js/profiling/integration.d.ts +1 -7
  78. package/dist/js/profiling/integration.d.ts.map +1 -1
  79. package/dist/js/profiling/integration.js +39 -25
  80. package/dist/js/profiling/integration.js.map +1 -1
  81. package/dist/js/profiling/utils.js +2 -1
  82. package/dist/js/profiling/utils.js.map +1 -1
  83. package/dist/js/replay/mobilereplay.d.ts +2 -2
  84. package/dist/js/replay/mobilereplay.d.ts.map +1 -1
  85. package/dist/js/replay/mobilereplay.js.map +1 -1
  86. package/dist/js/scopeSync.d.ts +6 -0
  87. package/dist/js/scopeSync.d.ts.map +1 -0
  88. package/dist/js/scopeSync.js +60 -0
  89. package/dist/js/scopeSync.js.map +1 -0
  90. package/dist/js/sdk.d.ts +1 -20
  91. package/dist/js/sdk.d.ts.map +1 -1
  92. package/dist/js/sdk.js +20 -53
  93. package/dist/js/sdk.js.map +1 -1
  94. package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
  95. package/dist/js/touchevents.d.ts +0 -1
  96. package/dist/js/touchevents.d.ts.map +1 -1
  97. package/dist/js/touchevents.js +5 -9
  98. package/dist/js/touchevents.js.map +1 -1
  99. package/dist/js/tracing/gesturetracing.d.ts +1 -6
  100. package/dist/js/tracing/gesturetracing.d.ts.map +1 -1
  101. package/dist/js/tracing/gesturetracing.js +8 -12
  102. package/dist/js/tracing/gesturetracing.js.map +1 -1
  103. package/dist/js/tracing/index.d.ts +6 -7
  104. package/dist/js/tracing/index.d.ts.map +1 -1
  105. package/dist/js/tracing/index.js +4 -7
  106. package/dist/js/tracing/index.js.map +1 -1
  107. package/dist/js/tracing/integrations/appStart.d.ts +39 -0
  108. package/dist/js/tracing/integrations/appStart.d.ts.map +1 -0
  109. package/dist/js/tracing/integrations/appStart.js +301 -0
  110. package/dist/js/tracing/integrations/appStart.js.map +1 -0
  111. package/dist/js/tracing/integrations/nativeFrames.d.ts +20 -0
  112. package/dist/js/tracing/integrations/nativeFrames.d.ts.map +1 -0
  113. package/dist/js/tracing/integrations/nativeFrames.js +256 -0
  114. package/dist/js/tracing/integrations/nativeFrames.js.map +1 -0
  115. package/dist/js/tracing/integrations/stalltracking.d.ts +31 -0
  116. package/dist/js/tracing/integrations/stalltracking.d.ts.map +1 -0
  117. package/dist/js/tracing/integrations/stalltracking.js +236 -0
  118. package/dist/js/tracing/integrations/stalltracking.js.map +1 -0
  119. package/dist/js/tracing/integrations/userInteraction.d.ts +11 -0
  120. package/dist/js/tracing/integrations/userInteraction.d.ts.map +1 -0
  121. package/dist/js/tracing/integrations/userInteraction.js +70 -0
  122. package/dist/js/tracing/integrations/userInteraction.js.map +1 -0
  123. package/dist/js/tracing/onSpanEndUtils.d.ts +17 -0
  124. package/dist/js/tracing/onSpanEndUtils.d.ts.map +1 -0
  125. package/dist/js/tracing/onSpanEndUtils.js +112 -0
  126. package/dist/js/tracing/onSpanEndUtils.js.map +1 -0
  127. package/dist/js/tracing/origin.d.ts +2 -0
  128. package/dist/js/tracing/origin.d.ts.map +1 -0
  129. package/dist/js/tracing/origin.js +2 -0
  130. package/dist/js/tracing/origin.js.map +1 -0
  131. package/dist/js/tracing/reactnativenavigation.d.ts +21 -39
  132. package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
  133. package/dist/js/tracing/reactnativenavigation.js +98 -87
  134. package/dist/js/tracing/reactnativenavigation.js.map +1 -1
  135. package/dist/js/tracing/reactnativeprofiler.d.ts.map +1 -1
  136. package/dist/js/tracing/reactnativeprofiler.js +6 -13
  137. package/dist/js/tracing/reactnativeprofiler.js.map +1 -1
  138. package/dist/js/tracing/reactnativetracing.d.ts +44 -160
  139. package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
  140. package/dist/js/tracing/reactnativetracing.js +51 -481
  141. package/dist/js/tracing/reactnativetracing.js.map +1 -1
  142. package/dist/js/tracing/reactnavigation.d.ts +18 -63
  143. package/dist/js/tracing/reactnavigation.d.ts.map +1 -1
  144. package/dist/js/tracing/reactnavigation.js +200 -205
  145. package/dist/js/tracing/reactnavigation.js.map +1 -1
  146. package/dist/js/tracing/semanticAttributes.d.ts +12 -0
  147. package/dist/js/tracing/semanticAttributes.d.ts.map +1 -0
  148. package/dist/js/tracing/semanticAttributes.js +12 -0
  149. package/dist/js/tracing/semanticAttributes.js.map +1 -0
  150. package/dist/js/tracing/span.d.ts +52 -0
  151. package/dist/js/tracing/span.d.ts.map +1 -0
  152. package/dist/js/tracing/span.js +82 -0
  153. package/dist/js/tracing/span.js.map +1 -0
  154. package/dist/js/tracing/timetodisplay.d.ts.map +1 -1
  155. package/dist/js/tracing/timetodisplay.js +14 -29
  156. package/dist/js/tracing/timetodisplay.js.map +1 -1
  157. package/dist/js/tracing/types.d.ts +2 -9
  158. package/dist/js/tracing/types.d.ts.map +1 -1
  159. package/dist/js/tracing/types.js.map +1 -1
  160. package/dist/js/tracing/utils.d.ts +19 -14
  161. package/dist/js/tracing/utils.d.ts.map +1 -1
  162. package/dist/js/tracing/utils.js +38 -52
  163. package/dist/js/tracing/utils.js.map +1 -1
  164. package/dist/js/transports/encodePolyfill.d.ts +3 -0
  165. package/dist/js/transports/encodePolyfill.d.ts.map +1 -0
  166. package/dist/js/transports/encodePolyfill.js +13 -0
  167. package/dist/js/transports/encodePolyfill.js.map +1 -0
  168. package/dist/js/transports/native.d.ts +2 -2
  169. package/dist/js/transports/native.d.ts.map +1 -1
  170. package/dist/js/transports/native.js +2 -1
  171. package/dist/js/transports/native.js.map +1 -1
  172. package/dist/js/utils/fill.d.ts +7 -0
  173. package/dist/js/utils/fill.d.ts.map +1 -0
  174. package/dist/js/utils/fill.js +9 -0
  175. package/dist/js/utils/fill.js.map +1 -0
  176. package/dist/js/utils/span.d.ts +19 -0
  177. package/dist/js/utils/span.d.ts.map +1 -0
  178. package/dist/js/utils/span.js +29 -0
  179. package/dist/js/utils/span.js.map +1 -0
  180. package/dist/js/vendor/react-native/index.d.ts +1 -1
  181. package/dist/js/vendor/react-native/index.d.ts.map +1 -1
  182. package/dist/js/vendor/react-native/index.js.map +1 -1
  183. package/dist/js/version.d.ts +1 -1
  184. package/dist/js/version.d.ts.map +1 -1
  185. package/dist/js/version.js +1 -1
  186. package/dist/js/version.js.map +1 -1
  187. package/dist/js/wrapper.d.ts.map +1 -1
  188. package/dist/js/wrapper.js +1 -0
  189. package/dist/js/wrapper.js.map +1 -1
  190. package/package.json +10 -12
  191. package/ts3.8/dist/js/client.d.ts +5 -9
  192. package/ts3.8/dist/js/index.d.ts +5 -10
  193. package/ts3.8/dist/js/integrations/debugsymbolicator.d.ts +2 -8
  194. package/ts3.8/dist/js/integrations/devicecontext.d.ts +2 -8
  195. package/ts3.8/dist/js/integrations/eventorigin.d.ts +2 -8
  196. package/ts3.8/dist/js/integrations/expocontext.d.ts +2 -8
  197. package/ts3.8/dist/js/integrations/exports.d.ts +4 -0
  198. package/ts3.8/dist/js/integrations/modulesloader.d.ts +2 -8
  199. package/ts3.8/dist/js/integrations/nativelinkederrors.d.ts +2 -8
  200. package/ts3.8/dist/js/integrations/reactnativeerrorhandlers.d.ts +2 -8
  201. package/ts3.8/dist/js/integrations/reactnativeinfo.d.ts +2 -8
  202. package/ts3.8/dist/js/integrations/release.d.ts +2 -8
  203. package/ts3.8/dist/js/integrations/screenshot.d.ts +2 -8
  204. package/ts3.8/dist/js/integrations/sdkinfo.d.ts +2 -8
  205. package/ts3.8/dist/js/integrations/spotlight.d.ts +2 -10
  206. package/ts3.8/dist/js/integrations/viewhierarchy.d.ts +2 -8
  207. package/ts3.8/dist/js/options.d.ts +43 -0
  208. package/ts3.8/dist/js/profiling/cache.d.ts +1 -1
  209. package/ts3.8/dist/js/profiling/hermes.d.ts +1 -1
  210. package/ts3.8/dist/js/profiling/integration.d.ts +1 -7
  211. package/ts3.8/dist/js/replay/mobilereplay.d.ts +2 -2
  212. package/ts3.8/dist/js/scopeSync.d.ts +6 -0
  213. package/ts3.8/dist/js/sdk.d.ts +1 -20
  214. package/ts3.8/dist/js/touchevents.d.ts +0 -1
  215. package/ts3.8/dist/js/tracing/gesturetracing.d.ts +1 -6
  216. package/ts3.8/dist/js/tracing/index.d.ts +6 -7
  217. package/ts3.8/dist/js/tracing/integrations/appStart.d.ts +39 -0
  218. package/ts3.8/dist/js/tracing/integrations/nativeFrames.d.ts +20 -0
  219. package/ts3.8/dist/js/tracing/integrations/stalltracking.d.ts +31 -0
  220. package/ts3.8/dist/js/tracing/integrations/userInteraction.d.ts +11 -0
  221. package/ts3.8/dist/js/tracing/onSpanEndUtils.d.ts +17 -0
  222. package/ts3.8/dist/js/tracing/origin.d.ts +2 -0
  223. package/ts3.8/dist/js/tracing/reactnativenavigation.d.ts +21 -39
  224. package/ts3.8/dist/js/tracing/reactnativetracing.d.ts +44 -160
  225. package/ts3.8/dist/js/tracing/reactnavigation.d.ts +18 -63
  226. package/ts3.8/dist/js/tracing/semanticAttributes.d.ts +12 -0
  227. package/ts3.8/dist/js/tracing/span.d.ts +52 -0
  228. package/ts3.8/dist/js/tracing/types.d.ts +2 -9
  229. package/ts3.8/dist/js/tracing/utils.d.ts +19 -14
  230. package/ts3.8/dist/js/transports/encodePolyfill.d.ts +3 -0
  231. package/ts3.8/dist/js/transports/native.d.ts +2 -2
  232. package/ts3.8/dist/js/utils/fill.d.ts +7 -0
  233. package/ts3.8/dist/js/utils/span.d.ts +19 -0
  234. package/ts3.8/dist/js/vendor/react-native/index.d.ts +1 -1
  235. package/ts3.8/dist/js/version.d.ts +1 -1
  236. package/dist/js/integrations/index.d.ts +0 -16
  237. package/dist/js/integrations/index.d.ts.map +0 -1
  238. package/dist/js/integrations/index.js +0 -17
  239. package/dist/js/integrations/index.js.map +0 -1
  240. package/dist/js/scope.d.ts +0 -54
  241. package/dist/js/scope.d.ts.map +0 -1
  242. package/dist/js/scope.js +0 -89
  243. package/dist/js/scope.js.map +0 -1
  244. package/dist/js/tracing/addTracingExtensions.d.ts +0 -8
  245. package/dist/js/tracing/addTracingExtensions.d.ts.map +0 -1
  246. package/dist/js/tracing/addTracingExtensions.js +0 -66
  247. package/dist/js/tracing/addTracingExtensions.js.map +0 -1
  248. package/dist/js/tracing/nativeframes.d.ts +0 -60
  249. package/dist/js/tracing/nativeframes.d.ts.map +0 -1
  250. package/dist/js/tracing/nativeframes.js +0 -210
  251. package/dist/js/tracing/nativeframes.js.map +0 -1
  252. package/dist/js/tracing/reactnavigationv4.d.ts +0 -92
  253. package/dist/js/tracing/reactnavigationv4.d.ts.map +0 -1
  254. package/dist/js/tracing/reactnavigationv4.js +0 -229
  255. package/dist/js/tracing/reactnavigationv4.js.map +0 -1
  256. package/dist/js/tracing/routingInstrumentation.d.ts +0 -52
  257. package/dist/js/tracing/routingInstrumentation.d.ts.map +0 -1
  258. package/dist/js/tracing/routingInstrumentation.js +0 -36
  259. package/dist/js/tracing/routingInstrumentation.js.map +0 -1
  260. package/dist/js/tracing/stalltracking.d.ts +0 -99
  261. package/dist/js/tracing/stalltracking.d.ts.map +0 -1
  262. package/dist/js/tracing/stalltracking.js +0 -286
  263. package/dist/js/tracing/stalltracking.js.map +0 -1
  264. package/dist/js/tracing/transaction.d.ts +0 -11
  265. package/dist/js/tracing/transaction.d.ts.map +0 -1
  266. package/dist/js/tracing/transaction.js +0 -37
  267. package/dist/js/tracing/transaction.js.map +0 -1
  268. package/dist/js/transports/TextEncoder.d.ts +0 -3
  269. package/dist/js/transports/TextEncoder.d.ts.map +0 -1
  270. package/dist/js/transports/TextEncoder.js +0 -12
  271. package/dist/js/transports/TextEncoder.js.map +0 -1
  272. package/ts3.8/dist/js/integrations/index.d.ts +0 -16
  273. package/ts3.8/dist/js/scope.d.ts +0 -54
  274. package/ts3.8/dist/js/tracing/addTracingExtensions.d.ts +0 -8
  275. package/ts3.8/dist/js/tracing/nativeframes.d.ts +0 -60
  276. package/ts3.8/dist/js/tracing/reactnavigationv4.d.ts +0 -92
  277. package/ts3.8/dist/js/tracing/routingInstrumentation.d.ts +0 -52
  278. package/ts3.8/dist/js/tracing/stalltracking.d.ts +0 -99
  279. package/ts3.8/dist/js/tracing/transaction.d.ts +0 -11
  280. package/ts3.8/dist/js/transports/TextEncoder.d.ts +0 -3
@@ -1,16 +1,18 @@
1
1
  /* eslint-disable max-lines */
2
- import { getActiveSpan, startInactiveSpan } from '@sentry/core';
3
- import { logger, timestampInSeconds } from '@sentry/utils';
2
+ import { addBreadcrumb, getActiveSpan, getClient, SEMANTIC_ATTRIBUTE_SENTRY_OP, SPAN_STATUS_OK, spanToJSON, startInactiveSpan, } from '@sentry/core';
3
+ import { isPlainObject, logger, timestampInSeconds } from '@sentry/utils';
4
4
  import { createSentryEventEmitter, NewFrameEventName } from '../utils/sentryeventemitter';
5
+ import { isSentrySpan } from '../utils/span';
5
6
  import { RN_GLOBAL_OBJ } from '../utils/worldwide';
6
7
  import { NATIVE } from '../wrapper';
7
- import { InternalRoutingInstrumentation } from './routingInstrumentation';
8
+ import { ignoreEmptyBackNavigation } from './onSpanEndUtils';
9
+ import { getReactNativeTracingIntegration } from './reactnativetracing';
10
+ import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes';
11
+ import { DEFAULT_NAVIGATION_SPAN_NAME, defaultIdleOptions, getDefaultIdleNavigationSpanOptions, startIdleNavigationSpan as startGenericIdleNavigationSpan, } from './span';
8
12
  import { manualInitialDisplaySpans, startTimeToInitialDisplaySpan } from './timetodisplay';
9
- import { customTransactionSource, defaultTransactionSource, getBlankTransactionContext, setSpanDurationAsMeasurementOnTransaction, } from './utils';
10
- const defaultOptions = {
11
- routeChangeTimeoutMs: 1000,
12
- enableTimeToInitialDisplay: false,
13
- };
13
+ import { setSpanDurationAsMeasurementOnSpan } from './utils';
14
+ export const INTEGRATION_NAME = 'ReactNavigation';
15
+ const NAVIGATION_HISTORY_MAX_SIZE = 200;
14
16
  /**
15
17
  * Instrumentation for React-Navigation V5 and above. See docs or sample app for usage.
16
18
  *
@@ -19,233 +21,226 @@ const defaultOptions = {
19
21
  * - `_onStateChange` is then called AFTER the state change happens due to a dispatch and sets the route context onto the active transaction.
20
22
  * - If `_onStateChange` isn't called within `STATE_CHANGE_TIMEOUT_DURATION` of the dispatch, then the transaction is not sampled and finished.
21
23
  */
22
- export class ReactNavigationInstrumentation extends InternalRoutingInstrumentation {
23
- constructor(options = {}) {
24
- super();
25
- this.name = ReactNavigationInstrumentation.instrumentationName;
26
- this._navigationContainer = null;
27
- this._newScreenFrameEventEmitter = null;
28
- this._maxRecentRouteLen = 200;
29
- this._initialStateHandled = false;
30
- this._recentRouteKeys = [];
31
- /** Pushes a recent route key, and removes earlier routes when there is greater than the max length */
32
- this._pushRecentRouteKey = (key) => {
33
- this._recentRouteKeys.push(key);
34
- if (this._recentRouteKeys.length > this._maxRecentRouteLen) {
35
- this._recentRouteKeys = this._recentRouteKeys.slice(this._recentRouteKeys.length - this._maxRecentRouteLen);
36
- }
37
- };
38
- this._options = Object.assign(Object.assign({}, defaultOptions), options);
39
- if (this._options.enableTimeToInitialDisplay) {
40
- this._newScreenFrameEventEmitter = createSentryEventEmitter();
41
- this._newScreenFrameEventEmitter.initAsync(NewFrameEventName);
42
- NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason) => {
43
- logger.error(`[ReactNavigationInstrumentation] Failed to initialize native new frame tracking: ${reason}`);
44
- });
45
- }
24
+ export const reactNavigationIntegration = ({ routeChangeTimeoutMs = 1000, enableTimeToInitialDisplay = false, ignoreEmptyBackNavigationTransactions = true, } = {}) => {
25
+ let navigationContainer;
26
+ let newScreenFrameEventEmitter;
27
+ let tracing;
28
+ let idleSpanOptions = defaultIdleOptions;
29
+ let latestRoute;
30
+ let latestNavigationSpan;
31
+ let navigationProcessingSpan;
32
+ let initialStateHandled = false;
33
+ let stateChangeTimeout;
34
+ let recentRouteKeys = [];
35
+ if (enableTimeToInitialDisplay) {
36
+ newScreenFrameEventEmitter = createSentryEventEmitter();
37
+ newScreenFrameEventEmitter.initAsync(NewFrameEventName);
38
+ NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason) => {
39
+ logger.error(`${INTEGRATION_NAME} Failed to initialize native new frame tracking: ${reason}`);
40
+ });
46
41
  }
47
42
  /**
48
- * Extends by calling _handleInitialState at the end.
43
+ * Set the initial state and start initial navigation span for the current screen.
49
44
  */
50
- registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute) {
51
- super.registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute);
52
- // We create an initial state here to ensure a transaction gets created before the first route mounts.
53
- if (!this._initialStateHandled) {
54
- this._onDispatch();
55
- if (this._navigationContainer) {
56
- // Navigation container already registered, just populate with route state
57
- this._onStateChange();
58
- this._initialStateHandled = true;
59
- }
45
+ const afterAllSetup = (client) => {
46
+ tracing = getReactNativeTracingIntegration(client);
47
+ if (tracing) {
48
+ idleSpanOptions = {
49
+ finalTimeout: tracing.options.finalTimeoutMs,
50
+ idleTimeout: tracing.options.idleTimeoutMs,
51
+ };
60
52
  }
61
- }
62
- /**
63
- * Pass the ref to the navigation container to register it to the instrumentation
64
- * @param navigationContainerRef Ref to a `NavigationContainer`
65
- */
66
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
67
- registerNavigationContainer(navigationContainerRef) {
53
+ if (initialStateHandled) {
54
+ // We create an initial state here to ensure a transaction gets created before the first route mounts.
55
+ return undefined;
56
+ }
57
+ startIdleNavigationSpan();
58
+ if (!navigationContainer) {
59
+ // This is expected as navigation container is registered after the root component is mounted.
60
+ return undefined;
61
+ }
62
+ // Navigation container already registered, just populate with route state
63
+ updateLatestNavigationSpanWithCurrentRoute();
64
+ initialStateHandled = true;
65
+ };
66
+ const registerNavigationContainer = (navigationContainerRef) => {
68
67
  /* We prevent duplicate routing instrumentation to be initialized on fast refreshes
69
68
 
70
69
  Explanation: If the user triggers a fast refresh on the file that the instrumentation is
71
70
  initialized in, it will initialize a new instance and will cause undefined behavior.
72
71
  */
73
- if (!RN_GLOBAL_OBJ.__sentry_rn_v5_registered) {
74
- if ('current' in navigationContainerRef) {
75
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
76
- this._navigationContainer = navigationContainerRef.current;
77
- }
78
- else {
79
- this._navigationContainer = navigationContainerRef;
80
- }
81
- if (this._navigationContainer) {
82
- this._navigationContainer.addListener('__unsafe_action__', // This action is emitted on every dispatch
83
- this._onDispatch.bind(this));
84
- this._navigationContainer.addListener('state', // This action is emitted on every state change
85
- this._onStateChange.bind(this));
86
- if (!this._initialStateHandled) {
87
- if (this._latestTransaction) {
88
- // If registerRoutingInstrumentation was called first _onDispatch has already been called
89
- this._onStateChange();
90
- this._initialStateHandled = true;
91
- }
92
- else {
93
- logger.log('[ReactNavigationInstrumentation] Navigation container registered, but integration has not been setup yet.');
94
- }
95
- }
96
- RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true;
97
- }
98
- else {
99
- logger.warn('[ReactNavigationInstrumentation] Received invalid navigation container ref!');
100
- }
72
+ if (RN_GLOBAL_OBJ.__sentry_rn_v5_registered) {
73
+ logger.log(`${INTEGRATION_NAME} Instrumentation already exists, but register has been called again, doing nothing.`);
74
+ return undefined;
75
+ }
76
+ if (isPlainObject(navigationContainerRef) && 'current' in navigationContainerRef) {
77
+ navigationContainer = navigationContainerRef.current;
101
78
  }
102
79
  else {
103
- logger.log('[ReactNavigationInstrumentation] Instrumentation already exists, but register has been called again, doing nothing.');
80
+ navigationContainer = navigationContainerRef;
104
81
  }
105
- }
82
+ if (!navigationContainer) {
83
+ logger.warn(`${INTEGRATION_NAME} Received invalid navigation container ref!`);
84
+ return undefined;
85
+ }
86
+ // This action is emitted on every dispatch
87
+ navigationContainer.addListener('__unsafe_action__', startIdleNavigationSpan);
88
+ navigationContainer.addListener('state', updateLatestNavigationSpanWithCurrentRoute);
89
+ RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true;
90
+ if (initialStateHandled) {
91
+ return undefined;
92
+ }
93
+ if (!latestNavigationSpan) {
94
+ logger.log(`${INTEGRATION_NAME} Navigation container registered, but integration has not been setup yet.`);
95
+ return undefined;
96
+ }
97
+ // Navigation Container is registered after the first navigation
98
+ // Initial navigation span was started, after integration setup,
99
+ // so now we populate it with the current route.
100
+ updateLatestNavigationSpanWithCurrentRoute();
101
+ initialStateHandled = true;
102
+ };
106
103
  /**
107
104
  * To be called on every React-Navigation action dispatch.
108
105
  * It does not name the transaction or populate it with route information. Instead, it waits for the state to fully change
109
- * and gets the route information from there, @see _onStateChange
106
+ * and gets the route information from there, @see updateLatestNavigationSpanWithCurrentRoute
110
107
  */
111
- _onDispatch() {
112
- var _a;
113
- if (this._latestTransaction) {
114
- logger.log('[ReactNavigationInstrumentation] A transaction was detected that turned out to be a noop, discarding.');
115
- this._discardLatestTransaction();
116
- this._clearStateChangeTimeout();
117
- }
118
- this._latestTransaction = this.onRouteWillChange(getBlankTransactionContext(ReactNavigationInstrumentation.instrumentationName));
119
- if (this._options.enableTimeToInitialDisplay) {
120
- this._navigationProcessingSpan = startInactiveSpan({
108
+ const startIdleNavigationSpan = () => {
109
+ if (latestNavigationSpan) {
110
+ logger.log(`${INTEGRATION_NAME} A transaction was detected that turned out to be a noop, discarding.`);
111
+ _discardLatestTransaction();
112
+ clearStateChangeTimeout();
113
+ }
114
+ latestNavigationSpan = startGenericIdleNavigationSpan(tracing && tracing.options.beforeStartSpan
115
+ ? tracing.options.beforeStartSpan(getDefaultIdleNavigationSpanOptions())
116
+ : getDefaultIdleNavigationSpanOptions(), idleSpanOptions);
117
+ if (ignoreEmptyBackNavigationTransactions) {
118
+ ignoreEmptyBackNavigation(getClient(), latestNavigationSpan);
119
+ }
120
+ if (enableTimeToInitialDisplay) {
121
+ navigationProcessingSpan = startInactiveSpan({
121
122
  op: 'navigation.processing',
122
123
  name: 'Navigation processing',
123
- startTimestamp: (_a = this._latestTransaction) === null || _a === void 0 ? void 0 : _a.startTimestamp,
124
+ startTime: latestNavigationSpan && spanToJSON(latestNavigationSpan).start_timestamp,
124
125
  });
125
126
  }
126
- this._stateChangeTimeout = setTimeout(this._discardLatestTransaction.bind(this), this._options.routeChangeTimeoutMs);
127
- }
127
+ stateChangeTimeout = setTimeout(_discardLatestTransaction, routeChangeTimeoutMs);
128
+ };
128
129
  /**
129
130
  * To be called AFTER the state has been changed to populate the transaction with the current route.
130
131
  */
131
- _onStateChange() {
132
- var _a, _b, _c, _d, _e;
132
+ const updateLatestNavigationSpanWithCurrentRoute = () => {
133
133
  const stateChangedTimestamp = timestampInSeconds();
134
- // Use the getCurrentRoute method to be accurate.
135
- const previousRoute = this._latestRoute;
136
- if (!this._navigationContainer) {
137
- logger.warn('[ReactNavigationInstrumentation] Missing navigation container ref. Route transactions will not be sent.');
138
- return;
139
- }
140
- const route = this._navigationContainer.getCurrentRoute();
141
- if (route) {
142
- if (this._latestTransaction) {
143
- if (!previousRoute || previousRoute.key !== route.key) {
144
- const routeHasBeenSeen = this._recentRouteKeys.includes(route.key);
145
- const latestTransaction = this._latestTransaction;
146
- const latestTtidSpan = !routeHasBeenSeen &&
147
- this._options.enableTimeToInitialDisplay &&
148
- startTimeToInitialDisplaySpan({
149
- name: `${route.name} initial display`,
150
- isAutoInstrumented: true,
151
- });
152
- !routeHasBeenSeen &&
153
- latestTtidSpan &&
154
- ((_a = this._newScreenFrameEventEmitter) === null || _a === void 0 ? void 0 : _a.once(NewFrameEventName, ({ newFrameTimestampInSeconds }) => {
155
- const activeSpan = getActiveSpan();
156
- if (activeSpan && manualInitialDisplaySpans.has(activeSpan)) {
157
- logger.warn('[ReactNavigationInstrumentation] Detected manual instrumentation for the current active span.');
158
- return;
159
- }
160
- latestTtidSpan.setStatus('ok');
161
- latestTtidSpan.end(newFrameTimestampInSeconds);
162
- setSpanDurationAsMeasurementOnTransaction(latestTransaction, 'time_to_initial_display', latestTtidSpan);
163
- }));
164
- (_b = this._navigationProcessingSpan) === null || _b === void 0 ? void 0 : _b.updateName(`Processing navigation to ${route.name}`);
165
- (_c = this._navigationProcessingSpan) === null || _c === void 0 ? void 0 : _c.setStatus('ok');
166
- (_d = this._navigationProcessingSpan) === null || _d === void 0 ? void 0 : _d.end(stateChangedTimestamp);
167
- this._navigationProcessingSpan = undefined;
168
- const originalContext = latestTransaction.toContext();
169
- const data = Object.assign(Object.assign({}, originalContext.data), { route: {
170
- name: route.name,
171
- key: route.key,
172
- // TODO: filter PII params instead of dropping them all
173
- params: {},
174
- hasBeenSeen: routeHasBeenSeen,
175
- }, previousRoute: previousRoute
176
- ? {
177
- name: previousRoute.name,
178
- key: previousRoute.key,
179
- // TODO: filter PII params instead of dropping them all
180
- params: {},
181
- }
182
- : null });
183
- const updatedContext = Object.assign(Object.assign({}, originalContext), { name: route.name, tags: Object.assign(Object.assign({}, originalContext.tags), { 'routing.route.name': route.name }), data });
184
- const finalContext = this._prepareFinalContext(updatedContext);
185
- latestTransaction.updateWithContext(finalContext);
186
- const isCustomName = updatedContext.name !== finalContext.name;
187
- latestTransaction.setName(finalContext.name, isCustomName ? customTransactionSource : defaultTransactionSource);
188
- (_e = this._onConfirmRoute) === null || _e === void 0 ? void 0 : _e.call(this, finalContext);
189
- }
190
- this._pushRecentRouteKey(route.key);
191
- this._latestRoute = route;
192
- // Clear the latest transaction as it has been handled.
193
- this._latestTransaction = undefined;
194
- }
134
+ const previousRoute = latestRoute;
135
+ if (!navigationContainer) {
136
+ logger.warn(`${INTEGRATION_NAME} Missing navigation container ref. Route transactions will not be sent.`);
137
+ return undefined;
195
138
  }
196
- }
197
- /** Creates final transaction context before confirmation */
198
- _prepareFinalContext(updatedContext) {
199
- var _a;
200
- let finalContext = (_a = this._beforeNavigate) === null || _a === void 0 ? void 0 : _a.call(this, Object.assign({}, updatedContext));
201
- // This block is to catch users not returning a transaction context
202
- if (!finalContext) {
203
- logger.error(`[ReactNavigationInstrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.`);
204
- finalContext = Object.assign(Object.assign({}, updatedContext), { sampled: false });
205
- }
206
- // Note: finalContext.sampled will be false at this point only if the user sets it to be so in beforeNavigate.
207
- if (finalContext.sampled === false) {
208
- logger.log(`[ReactNavigationInstrumentation] Will not send transaction "${finalContext.name}" due to beforeNavigate.`);
139
+ const route = navigationContainer.getCurrentRoute();
140
+ if (!route) {
141
+ logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but no route is rendered.`);
142
+ return undefined;
209
143
  }
210
- else {
211
- // Clear the timeout so the transaction does not get cancelled.
212
- this._clearStateChangeTimeout();
144
+ if (!latestNavigationSpan) {
145
+ logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but navigation transaction was not started on dispatch.`);
146
+ return undefined;
213
147
  }
214
- return finalContext;
215
- }
148
+ if (previousRoute && previousRoute.key === route.key) {
149
+ logger.debug(`[${INTEGRATION_NAME}] Navigation state changed, but route is the same as previous.`);
150
+ pushRecentRouteKey(route.key);
151
+ latestRoute = route;
152
+ // Clear the latest transaction as it has been handled.
153
+ latestNavigationSpan = undefined;
154
+ return undefined;
155
+ }
156
+ const routeHasBeenSeen = recentRouteKeys.includes(route.key);
157
+ const latestTtidSpan = !routeHasBeenSeen &&
158
+ enableTimeToInitialDisplay &&
159
+ startTimeToInitialDisplaySpan({
160
+ name: `${route.name} initial display`,
161
+ isAutoInstrumented: true,
162
+ });
163
+ const navigationSpanWithTtid = latestNavigationSpan;
164
+ !routeHasBeenSeen &&
165
+ latestTtidSpan &&
166
+ (newScreenFrameEventEmitter === null || newScreenFrameEventEmitter === void 0 ? void 0 : newScreenFrameEventEmitter.once(NewFrameEventName, ({ 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
+ navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.updateName(`Processing navigation to ${route.name}`);
177
+ navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.setStatus({ code: SPAN_STATUS_OK });
178
+ navigationProcessingSpan === null || navigationProcessingSpan === void 0 ? void 0 : navigationProcessingSpan.end(stateChangedTimestamp);
179
+ navigationProcessingSpan = undefined;
180
+ if (spanToJSON(latestNavigationSpan).description === DEFAULT_NAVIGATION_SPAN_NAME) {
181
+ latestNavigationSpan.updateName(route.name);
182
+ }
183
+ latestNavigationSpan.setAttributes({
184
+ 'route.name': route.name,
185
+ 'route.key': route.key,
186
+ // TODO: filter PII params instead of dropping them all
187
+ // 'route.params': {},
188
+ 'route.has_been_seen': routeHasBeenSeen,
189
+ 'previous_route.name': previousRoute === null || previousRoute === void 0 ? void 0 : previousRoute.name,
190
+ 'previous_route.key': previousRoute === null || previousRoute === void 0 ? void 0 : previousRoute.key,
191
+ // TODO: filter PII params instead of dropping them all
192
+ // 'previous_route.params': {},
193
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'component',
194
+ [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'navigation',
195
+ });
196
+ // Clear the timeout so the transaction does not get cancelled.
197
+ clearStateChangeTimeout();
198
+ addBreadcrumb({
199
+ category: 'navigation',
200
+ type: 'navigation',
201
+ message: `Navigation to ${route.name}`,
202
+ data: {
203
+ from: previousRoute === null || previousRoute === void 0 ? void 0 : previousRoute.name,
204
+ to: route.name,
205
+ },
206
+ });
207
+ tracing === null || tracing === void 0 ? void 0 : tracing.setCurrentRoute(route.key);
208
+ pushRecentRouteKey(route.key);
209
+ latestRoute = route;
210
+ // Clear the latest transaction as it has been handled.
211
+ latestNavigationSpan = undefined;
212
+ };
213
+ /** Pushes a recent route key, and removes earlier routes when there is greater than the max length */
214
+ const pushRecentRouteKey = (key) => {
215
+ recentRouteKeys.push(key);
216
+ if (recentRouteKeys.length > NAVIGATION_HISTORY_MAX_SIZE) {
217
+ recentRouteKeys = recentRouteKeys.slice(recentRouteKeys.length - NAVIGATION_HISTORY_MAX_SIZE);
218
+ }
219
+ };
216
220
  /** Cancels the latest transaction so it does not get sent to Sentry. */
217
- _discardLatestTransaction() {
218
- if (this._latestTransaction) {
219
- this._latestTransaction.sampled = false;
220
- this._latestTransaction.finish();
221
- this._latestTransaction = undefined;
221
+ const _discardLatestTransaction = () => {
222
+ if (latestNavigationSpan) {
223
+ if (isSentrySpan(latestNavigationSpan)) {
224
+ latestNavigationSpan['_sampled'] = false;
225
+ }
226
+ // TODO: What if it's not SentrySpan?
227
+ latestNavigationSpan.end();
228
+ latestNavigationSpan = undefined;
222
229
  }
223
- if (this._navigationProcessingSpan) {
224
- this._navigationProcessingSpan = undefined;
230
+ if (navigationProcessingSpan) {
231
+ navigationProcessingSpan = undefined;
225
232
  }
226
- }
227
- /**
228
- *
229
- */
230
- _clearStateChangeTimeout() {
231
- if (typeof this._stateChangeTimeout !== 'undefined') {
232
- clearTimeout(this._stateChangeTimeout);
233
- this._stateChangeTimeout = undefined;
233
+ };
234
+ const clearStateChangeTimeout = () => {
235
+ if (typeof stateChangeTimeout !== 'undefined') {
236
+ clearTimeout(stateChangeTimeout);
237
+ stateChangeTimeout = undefined;
234
238
  }
235
- }
236
- }
237
- ReactNavigationInstrumentation.instrumentationName = 'react-navigation-v5';
238
- /**
239
- * Backwards compatibility alias for ReactNavigationInstrumentation
240
- * @deprecated Use ReactNavigationInstrumentation
241
- */
242
- export const ReactNavigationV5Instrumentation = ReactNavigationInstrumentation;
243
- export const BLANK_TRANSACTION_CONTEXT = {
244
- name: 'Route Change',
245
- op: 'navigation',
246
- tags: {
247
- 'routing.instrumentation': ReactNavigationInstrumentation.instrumentationName,
248
- },
249
- data: {},
239
+ };
240
+ return {
241
+ name: INTEGRATION_NAME,
242
+ afterAllSetup,
243
+ registerNavigationContainer,
244
+ };
250
245
  };
251
246
  //# 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 { getActiveSpan, startInactiveSpan } from '@sentry/core';\nimport type { Span, Transaction as TransactionType, TransactionContext } from '@sentry/types';\nimport { logger, timestampInSeconds } from '@sentry/utils';\n\nimport type { NewFrameEvent } from '../utils/sentryeventemitter';\nimport { type SentryEventEmitter, createSentryEventEmitter, NewFrameEventName } from '../utils/sentryeventemitter';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\nimport { NATIVE } from '../wrapper';\nimport type { OnConfirmRoute, TransactionCreator } from './routingInstrumentation';\nimport { InternalRoutingInstrumentation } from './routingInstrumentation';\nimport { manualInitialDisplaySpans, startTimeToInitialDisplaySpan } from './timetodisplay';\nimport type { BeforeNavigate, ReactNavigationTransactionContext, RouteChangeContextData } from './types';\nimport {\n customTransactionSource,\n defaultTransactionSource,\n getBlankTransactionContext,\n setSpanDurationAsMeasurementOnTransaction,\n} from './utils';\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\ninterface ReactNavigationOptions {\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 * Time is in ms.\n *\n * @default 1000\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\nconst defaultOptions: ReactNavigationOptions = {\n routeChangeTimeoutMs: 1000,\n enableTimeToInitialDisplay: false,\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 class ReactNavigationInstrumentation extends InternalRoutingInstrumentation {\n public static instrumentationName: string = 'react-navigation-v5';\n\n public readonly name: string = ReactNavigationInstrumentation.instrumentationName;\n\n private _navigationContainer: NavigationContainer | null = null;\n private _newScreenFrameEventEmitter: SentryEventEmitter | null = null;\n\n private readonly _maxRecentRouteLen: number = 200;\n\n private _latestRoute?: NavigationRoute;\n private _latestTransaction?: TransactionType;\n private _navigationProcessingSpan?: Span;\n\n private _initialStateHandled: boolean = false;\n private _stateChangeTimeout?: number | undefined;\n private _recentRouteKeys: string[] = [];\n\n private _options: ReactNavigationOptions;\n\n public constructor(options: Partial<ReactNavigationOptions> = {}) {\n super();\n\n this._options = {\n ...defaultOptions,\n ...options,\n };\n\n if (this._options.enableTimeToInitialDisplay) {\n this._newScreenFrameEventEmitter = createSentryEventEmitter();\n this._newScreenFrameEventEmitter.initAsync(NewFrameEventName);\n NATIVE.initNativeReactNavigationNewFrameTracking().catch((reason: unknown) => {\n logger.error(`[ReactNavigationInstrumentation] Failed to initialize native new frame tracking: ${reason}`);\n });\n }\n }\n\n /**\n * Extends by calling _handleInitialState at the end.\n */\n public registerRoutingInstrumentation(\n listener: TransactionCreator,\n beforeNavigate: BeforeNavigate,\n onConfirmRoute: OnConfirmRoute,\n ): void {\n super.registerRoutingInstrumentation(listener, beforeNavigate, onConfirmRoute);\n\n // We create an initial state here to ensure a transaction gets created before the first route mounts.\n if (!this._initialStateHandled) {\n this._onDispatch();\n if (this._navigationContainer) {\n // Navigation container already registered, just populate with route state\n this._onStateChange();\n\n this._initialStateHandled = true;\n }\n }\n }\n\n /**\n * Pass the ref to the navigation container to register it to the instrumentation\n * @param navigationContainerRef Ref to a `NavigationContainer`\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types\n public registerNavigationContainer(navigationContainerRef: any): 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 if ('current' in navigationContainerRef) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n this._navigationContainer = navigationContainerRef.current;\n } else {\n this._navigationContainer = navigationContainerRef;\n }\n\n if (this._navigationContainer) {\n this._navigationContainer.addListener(\n '__unsafe_action__', // This action is emitted on every dispatch\n this._onDispatch.bind(this),\n );\n this._navigationContainer.addListener(\n 'state', // This action is emitted on every state change\n this._onStateChange.bind(this),\n );\n\n if (!this._initialStateHandled) {\n if (this._latestTransaction) {\n // If registerRoutingInstrumentation was called first _onDispatch has already been called\n this._onStateChange();\n\n this._initialStateHandled = true;\n } else {\n logger.log(\n '[ReactNavigationInstrumentation] Navigation container registered, but integration has not been setup yet.',\n );\n }\n }\n\n RN_GLOBAL_OBJ.__sentry_rn_v5_registered = true;\n } else {\n logger.warn('[ReactNavigationInstrumentation] Received invalid navigation container ref!');\n }\n } else {\n logger.log(\n '[ReactNavigationInstrumentation] Instrumentation already exists, but register has been called again, doing nothing.',\n );\n }\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 _onStateChange\n */\n private _onDispatch(): void {\n if (this._latestTransaction) {\n logger.log(\n '[ReactNavigationInstrumentation] A transaction was detected that turned out to be a noop, discarding.',\n );\n this._discardLatestTransaction();\n this._clearStateChangeTimeout();\n }\n\n this._latestTransaction = this.onRouteWillChange(\n getBlankTransactionContext(ReactNavigationInstrumentation.instrumentationName),\n );\n\n if (this._options.enableTimeToInitialDisplay) {\n this._navigationProcessingSpan = startInactiveSpan({\n op: 'navigation.processing',\n name: 'Navigation processing',\n startTimestamp: this._latestTransaction?.startTimestamp,\n });\n }\n\n this._stateChangeTimeout = setTimeout(\n this._discardLatestTransaction.bind(this),\n this._options.routeChangeTimeoutMs,\n );\n }\n\n /**\n * To be called AFTER the state has been changed to populate the transaction with the current route.\n */\n private _onStateChange(): void {\n const stateChangedTimestamp = timestampInSeconds();\n\n // Use the getCurrentRoute method to be accurate.\n const previousRoute = this._latestRoute;\n\n if (!this._navigationContainer) {\n logger.warn(\n '[ReactNavigationInstrumentation] Missing navigation container ref. Route transactions will not be sent.',\n );\n\n return;\n }\n\n const route = this._navigationContainer.getCurrentRoute();\n\n if (route) {\n if (this._latestTransaction) {\n if (!previousRoute || previousRoute.key !== route.key) {\n const routeHasBeenSeen = this._recentRouteKeys.includes(route.key);\n const latestTransaction = this._latestTransaction;\n const latestTtidSpan =\n !routeHasBeenSeen &&\n this._options.enableTimeToInitialDisplay &&\n startTimeToInitialDisplaySpan({\n name: `${route.name} initial display`,\n isAutoInstrumented: true,\n });\n\n !routeHasBeenSeen &&\n latestTtidSpan &&\n this._newScreenFrameEventEmitter?.once(\n NewFrameEventName,\n ({ newFrameTimestampInSeconds }: NewFrameEvent) => {\n const activeSpan = getActiveSpan();\n if (activeSpan && manualInitialDisplaySpans.has(activeSpan)) {\n logger.warn(\n '[ReactNavigationInstrumentation] Detected manual instrumentation for the current active span.',\n );\n return;\n }\n\n latestTtidSpan.setStatus('ok');\n latestTtidSpan.end(newFrameTimestampInSeconds);\n setSpanDurationAsMeasurementOnTransaction(latestTransaction, 'time_to_initial_display', latestTtidSpan);\n },\n );\n\n this._navigationProcessingSpan?.updateName(`Processing navigation to ${route.name}`);\n this._navigationProcessingSpan?.setStatus('ok');\n this._navigationProcessingSpan?.end(stateChangedTimestamp);\n this._navigationProcessingSpan = undefined;\n\n const originalContext = latestTransaction.toContext() as typeof BLANK_TRANSACTION_CONTEXT;\n\n const data: RouteChangeContextData = {\n ...originalContext.data,\n route: {\n name: route.name,\n key: route.key,\n // TODO: filter PII params instead of dropping them all\n params: {},\n hasBeenSeen: routeHasBeenSeen,\n },\n previousRoute: previousRoute\n ? {\n name: previousRoute.name,\n key: previousRoute.key,\n // TODO: filter PII params instead of dropping them all\n params: {},\n }\n : null,\n };\n\n const updatedContext: ReactNavigationTransactionContext = {\n ...originalContext,\n name: route.name,\n tags: {\n ...originalContext.tags,\n 'routing.route.name': route.name,\n },\n data,\n };\n\n const finalContext = this._prepareFinalContext(updatedContext);\n latestTransaction.updateWithContext(finalContext);\n\n const isCustomName = updatedContext.name !== finalContext.name;\n latestTransaction.setName(\n finalContext.name,\n isCustomName ? customTransactionSource : defaultTransactionSource,\n );\n\n this._onConfirmRoute?.(finalContext);\n }\n\n this._pushRecentRouteKey(route.key);\n this._latestRoute = route;\n\n // Clear the latest transaction as it has been handled.\n this._latestTransaction = undefined;\n }\n }\n }\n\n /** Creates final transaction context before confirmation */\n private _prepareFinalContext(updatedContext: TransactionContext): TransactionContext {\n let finalContext = this._beforeNavigate?.({ ...updatedContext });\n\n // This block is to catch users not returning a transaction context\n if (!finalContext) {\n logger.error(\n `[ReactNavigationInstrumentation] beforeNavigate returned ${finalContext}, return context.sampled = false to not send transaction.`,\n );\n\n finalContext = {\n ...updatedContext,\n sampled: false,\n };\n }\n\n // Note: finalContext.sampled will be false at this point only if the user sets it to be so in beforeNavigate.\n if (finalContext.sampled === false) {\n logger.log(\n `[ReactNavigationInstrumentation] Will not send transaction \"${finalContext.name}\" due to beforeNavigate.`,\n );\n } else {\n // Clear the timeout so the transaction does not get cancelled.\n this._clearStateChangeTimeout();\n }\n\n return finalContext;\n }\n\n /** Pushes a recent route key, and removes earlier routes when there is greater than the max length */\n private _pushRecentRouteKey = (key: string): void => {\n this._recentRouteKeys.push(key);\n\n if (this._recentRouteKeys.length > this._maxRecentRouteLen) {\n this._recentRouteKeys = this._recentRouteKeys.slice(this._recentRouteKeys.length - this._maxRecentRouteLen);\n }\n };\n\n /** Cancels the latest transaction so it does not get sent to Sentry. */\n private _discardLatestTransaction(): void {\n if (this._latestTransaction) {\n this._latestTransaction.sampled = false;\n this._latestTransaction.finish();\n this._latestTransaction = undefined;\n }\n if (this._navigationProcessingSpan) {\n this._navigationProcessingSpan = undefined;\n }\n }\n\n /**\n *\n */\n private _clearStateChangeTimeout(): void {\n if (typeof this._stateChangeTimeout !== 'undefined') {\n clearTimeout(this._stateChangeTimeout);\n this._stateChangeTimeout = undefined;\n }\n }\n}\n\n/**\n * Backwards compatibility alias for ReactNavigationInstrumentation\n * @deprecated Use ReactNavigationInstrumentation\n */\nexport const ReactNavigationV5Instrumentation = ReactNavigationInstrumentation;\n\nexport const BLANK_TRANSACTION_CONTEXT = {\n name: 'Route Change',\n op: 'navigation',\n tags: {\n 'routing.instrumentation': ReactNavigationInstrumentation.instrumentationName,\n },\n data: {},\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 {\n addBreadcrumb,\n getActiveSpan,\n getClient,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SPAN_STATUS_OK,\n spanToJSON,\n startInactiveSpan,\n} from '@sentry/core';\nimport type { Client, Integration, Span } from '@sentry/types';\nimport { isPlainObject, logger, timestampInSeconds } from '@sentry/utils';\n\nimport type { NewFrameEvent } from '../utils/sentryeventemitter';\nimport { type SentryEventEmitter, createSentryEventEmitter, NewFrameEventName } from '../utils/sentryeventemitter';\nimport { isSentrySpan } from '../utils/span';\nimport { RN_GLOBAL_OBJ } from '../utils/worldwide';\nimport { NATIVE } from '../wrapper';\nimport { ignoreEmptyBackNavigation } from './onSpanEndUtils';\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';\n\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: SentryEventEmitter | 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 = createSentryEventEmitter();\n newScreenFrameEventEmitter.initAsync(NewFrameEventName);\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 if (ignoreEmptyBackNavigationTransactions) {\n ignoreEmptyBackNavigation(getClient(), latestNavigationSpan);\n }\n\n if (enableTimeToInitialDisplay) {\n navigationProcessingSpan = startInactiveSpan({\n op: 'navigation.processing',\n name: 'Navigation processing',\n startTime: latestNavigationSpan && spanToJSON(latestNavigationSpan).start_timestamp,\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\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 !routeHasBeenSeen &&\n latestTtidSpan &&\n newScreenFrameEventEmitter?.once(NewFrameEventName, ({ 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 navigationProcessingSpan?.updateName(`Processing navigation to ${route.name}`);\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"]}
@@ -0,0 +1,12 @@
1
+ export { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, } from '@sentry/core';
2
+ export declare const SEMANTIC_ATTRIBUTE_ROUTING_INSTRUMENTATION = "routing.instrumentation";
3
+ export declare const SEMANTIC_ATTRIBUTE_ROUTE_NAME = "route.name";
4
+ export declare const SEMANTIC_ATTRIBUTE_ROUTE_KEY = "route.key";
5
+ export declare const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_ID = "route.component_id";
6
+ export declare const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_TYPE = "route.component_type";
7
+ export declare const SEMANTIC_ATTRIBUTE_ROUTE_HAS_BEEN_SEEN = "route.has_been_seen";
8
+ export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = "previous_route.name";
9
+ export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = "previous_route.key";
10
+ export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = "previous_route.component_id";
11
+ export declare const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = "previous_route.component_type";
12
+ //# sourceMappingURL=semanticAttributes.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,12 @@
1
+ export { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, } from '@sentry/core';
2
+ export const SEMANTIC_ATTRIBUTE_ROUTING_INSTRUMENTATION = 'routing.instrumentation';
3
+ export const SEMANTIC_ATTRIBUTE_ROUTE_NAME = 'route.name';
4
+ export const SEMANTIC_ATTRIBUTE_ROUTE_KEY = 'route.key';
5
+ export const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_ID = 'route.component_id';
6
+ export const SEMANTIC_ATTRIBUTE_ROUTE_COMPONENT_TYPE = 'route.component_type';
7
+ export const SEMANTIC_ATTRIBUTE_ROUTE_HAS_BEEN_SEEN = 'route.has_been_seen';
8
+ export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_NAME = 'previous_route.name';
9
+ export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_KEY = 'previous_route.key';
10
+ export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_ID = 'previous_route.component_id';
11
+ export const SEMANTIC_ATTRIBUTE_PREVIOUS_ROUTE_COMPONENT_TYPE = 'previous_route.component_type';
12
+ //# sourceMappingURL=semanticAttributes.js.map
@@ -0,0 +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"]}