@sentry/react 11.0.0-alpha.1 → 11.0.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 (69) hide show
  1. package/build/cjs/error.js +4 -4
  2. package/build/cjs/error.js.map +1 -1
  3. package/build/cjs/profiler.js +10 -13
  4. package/build/cjs/profiler.js.map +1 -1
  5. package/build/cjs/reactrouter-compat-utils/instrumentation.js +30 -18
  6. package/build/cjs/reactrouter-compat-utils/instrumentation.js.map +1 -1
  7. package/build/cjs/reactrouter-compat-utils/route-manifest.js +4 -4
  8. package/build/cjs/reactrouter-compat-utils/route-manifest.js.map +1 -1
  9. package/build/cjs/reactrouter-compat-utils/utils.js +5 -5
  10. package/build/cjs/reactrouter-compat-utils/utils.js.map +1 -1
  11. package/build/cjs/reactrouter.compat.js +0 -3
  12. package/build/cjs/reactrouter.compat.js.map +1 -1
  13. package/build/cjs/reactrouter.js +10 -7
  14. package/build/cjs/reactrouter.js.map +1 -1
  15. package/build/cjs/reactrouterv3.js +12 -9
  16. package/build/cjs/reactrouterv3.js.map +1 -1
  17. package/build/cjs/reactrouterv6.js +0 -3
  18. package/build/cjs/reactrouterv6.js.map +1 -1
  19. package/build/cjs/reactrouterv7.js +0 -3
  20. package/build/cjs/reactrouterv7.js.map +1 -1
  21. package/build/cjs/redux.js +6 -6
  22. package/build/cjs/redux.js.map +1 -1
  23. package/build/cjs/sdk.js +7 -7
  24. package/build/cjs/sdk.js.map +1 -1
  25. package/build/cjs/tanstackrouter.js +25 -14
  26. package/build/cjs/tanstackrouter.js.map +1 -1
  27. package/build/esm/error.js +1 -1
  28. package/build/esm/error.js.map +1 -1
  29. package/build/esm/package.json +1 -1
  30. package/build/esm/profiler.js +12 -15
  31. package/build/esm/profiler.js.map +1 -1
  32. package/build/esm/reactrouter-compat-utils/instrumentation.js +32 -20
  33. package/build/esm/reactrouter-compat-utils/instrumentation.js.map +1 -1
  34. package/build/esm/reactrouter-compat-utils/route-manifest.js +1 -1
  35. package/build/esm/reactrouter-compat-utils/route-manifest.js.map +1 -1
  36. package/build/esm/reactrouter-compat-utils/utils.js +1 -1
  37. package/build/esm/reactrouter-compat-utils/utils.js.map +1 -1
  38. package/build/esm/reactrouter.compat.js +0 -3
  39. package/build/esm/reactrouter.compat.js.map +1 -1
  40. package/build/esm/reactrouter.js +12 -9
  41. package/build/esm/reactrouter.js.map +1 -1
  42. package/build/esm/reactrouterv3.js +11 -8
  43. package/build/esm/reactrouterv3.js.map +1 -1
  44. package/build/esm/reactrouterv6.js +0 -3
  45. package/build/esm/reactrouterv6.js.map +1 -1
  46. package/build/esm/reactrouterv7.js +0 -3
  47. package/build/esm/reactrouterv7.js.map +1 -1
  48. package/build/esm/redux.js +1 -1
  49. package/build/esm/redux.js.map +1 -1
  50. package/build/esm/sdk.js +1 -1
  51. package/build/esm/sdk.js.map +1 -1
  52. package/build/esm/tanstackrouter.js +25 -14
  53. package/build/esm/tanstackrouter.js.map +1 -1
  54. package/build/types/profiler.d.ts.map +1 -1
  55. package/build/types/reactrouter-compat-utils/instrumentation.d.ts.map +1 -1
  56. package/build/types/reactrouter-compat-utils/utils.d.ts +1 -1
  57. package/build/types/reactrouter-compat-utils/utils.d.ts.map +1 -1
  58. package/build/types/reactrouter.d.ts.map +1 -1
  59. package/build/types/reactrouterv3.d.ts +1 -1
  60. package/build/types/reactrouterv3.d.ts.map +1 -1
  61. package/build/types/redux.d.ts +1 -1
  62. package/build/types/redux.d.ts.map +1 -1
  63. package/build/types/sdk.d.ts +1 -1
  64. package/build/types/sdk.d.ts.map +1 -1
  65. package/build/types/tanstackrouter.d.ts +1 -1
  66. package/build/types/tanstackrouter.d.ts.map +1 -1
  67. package/build/types/vendor/tanstackrouter-types.d.ts +1 -0
  68. package/build/types/vendor/tanstackrouter-types.d.ts.map +1 -1
  69. package/package.json +5 -4
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
- const browser$1 = require('@sentry/browser');
4
- const browser = require('@sentry/core/browser');
3
+ const browser = require('@sentry/browser');
4
+ const core = require('@sentry/core');
5
5
 
6
6
  function setCause(error, cause) {
7
7
  const seenErrors = /* @__PURE__ */ new WeakSet();
@@ -18,13 +18,13 @@ function setCause(error, cause) {
18
18
  recurse(error, cause);
19
19
  }
20
20
  function captureReactException(error, { componentStack }, hint) {
21
- if (browser.isError(error) && componentStack) {
21
+ if (core.isError(error) && componentStack) {
22
22
  const errorBoundaryError = new Error(error.message);
23
23
  errorBoundaryError.name = `React ErrorBoundary ${error.name}`;
24
24
  errorBoundaryError.stack = componentStack;
25
25
  setCause(error, errorBoundaryError);
26
26
  }
27
- return browser$1.captureException(error, hint);
27
+ return browser.captureException(error, hint);
28
28
  }
29
29
  function reactErrorHandler(callback) {
30
30
  return (error, errorInfo) => {
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","sources":["../../src/error.ts"],"sourcesContent":["import { captureException } from '@sentry/browser';\nimport { isError } from '@sentry/core/browser';\nimport type { ErrorInfo } from 'react';\n\n/**\n * Recurse through `error.cause` chain to set cause on an error.\n */\nexport function setCause(error: Error & { cause?: Error }, cause: Error): void {\n const seenErrors = new WeakSet();\n\n function recurse(error: Error & { cause?: Error }, cause: Error): void {\n // If we've already seen the error, there is a recursive loop somewhere in the error's\n // cause chain. Let's just bail out then to prevent a stack overflow.\n if (seenErrors.has(error)) {\n return;\n }\n if (error.cause) {\n seenErrors.add(error);\n return recurse(error.cause, cause);\n }\n error.cause = cause;\n }\n\n recurse(error, cause);\n}\n\n/**\n * Captures an error that was thrown by a React ErrorBoundary or React root.\n *\n * @param error The error to capture.\n * @param errorInfo The errorInfo provided by React.\n * @param hint Optional additional data to attach to the Sentry event.\n * @returns the id of the captured Sentry event.\n */\nexport function captureReactException(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n { componentStack }: ErrorInfo,\n hint?: Parameters<typeof captureException>[1],\n): string {\n // Create a stack trace from the componentStack param and link it to the original error\n // using `error.cause`. Linking errors requires the `LinkedErrors` integration be enabled.\n // See: https://reactjs.org/blog/2020/08/10/react-v17-rc.html#native-component-stacks\n //\n // Although `componentDidCatch` is typed to accept an `Error` object, it can also be invoked\n // with non-error objects. This is why we need to check if the error is an error-like object.\n // See: https://github.com/getsentry/sentry-javascript/issues/6167\n if (isError(error) && componentStack) {\n const errorBoundaryError = new Error(error.message);\n errorBoundaryError.name = `React ErrorBoundary ${error.name}`;\n errorBoundaryError.stack = componentStack;\n\n // Using the `LinkedErrors` integration to link the errors together.\n setCause(error, errorBoundaryError);\n }\n\n return captureException(error, hint);\n}\n\n/**\n * Creates an error handler that can be used with the `onCaughtError`, `onUncaughtError`,\n * and `onRecoverableError` options in `createRoot` and `hydrateRoot` React DOM methods.\n *\n * @param callback An optional callback that will be called after the error is captured.\n * Use this to add custom handling for errors.\n *\n * @example\n *\n * ```JavaScript\n * const root = createRoot(container, {\n * onCaughtError: Sentry.reactErrorHandler(),\n * onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {\n * console.warn('Caught error', error, errorInfo.componentStack);\n * });\n * });\n * ```\n */\nexport function reactErrorHandler(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n callback?: (error: any, errorInfo: ErrorInfo, eventId: string) => void,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): (error: any, errorInfo: ErrorInfo) => void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (error: any, errorInfo: ErrorInfo) => {\n const hasCallback = !!callback;\n const eventId = captureReactException(error, errorInfo, {\n mechanism: { handled: hasCallback, type: 'auto.function.react.error_handler' },\n });\n if (hasCallback) {\n callback(error, errorInfo, eventId);\n }\n };\n}\n"],"names":["error","cause","isError","captureException"],"mappings":";;;;;AAOO,SAAS,QAAA,CAAS,OAAkC,KAAA,EAAoB;AAC7E,EAAA,MAAM,UAAA,uBAAiB,OAAA,EAAQ;AAE/B,EAAA,SAAS,OAAA,CAAQA,QAAkCC,MAAAA,EAAoB;AAGrE,IAAA,IAAI,UAAA,CAAW,GAAA,CAAID,MAAK,CAAA,EAAG;AACzB,MAAA;AAAA,IACF;AACA,IAAA,IAAIA,OAAM,KAAA,EAAO;AACf,MAAA,UAAA,CAAW,IAAIA,MAAK,CAAA;AACpB,MAAA,OAAO,OAAA,CAAQA,MAAAA,CAAM,KAAA,EAAOC,MAAK,CAAA;AAAA,IACnC;AACA,IAAAD,OAAM,KAAA,GAAQC,MAAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AACtB;AAUO,SAAS,qBAAA,CAEd,KAAA,EACA,EAAE,cAAA,IACF,IAAA,EACQ;AAQR,EAAA,IAAIC,eAAA,CAAQ,KAAK,CAAA,IAAK,cAAA,EAAgB;AACpC,IAAA,MAAM,kBAAA,GAAqB,IAAI,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAClD,IAAA,kBAAA,CAAmB,IAAA,GAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,CAAA;AAC3D,IAAA,kBAAA,CAAmB,KAAA,GAAQ,cAAA;AAG3B,IAAA,QAAA,CAAS,OAAO,kBAAkB,CAAA;AAAA,EACpC;AAEA,EAAA,OAAOC,0BAAA,CAAiB,OAAO,IAAI,CAAA;AACrC;AAoBO,SAAS,kBAEd,QAAA,EAE4C;AAE5C,EAAA,OAAO,CAAC,OAAY,SAAA,KAAyB;AAC3C,IAAA,MAAM,WAAA,GAAc,CAAC,CAAC,QAAA;AACtB,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,KAAA,EAAO,SAAA,EAAW;AAAA,MACtD,SAAA,EAAW,EAAE,OAAA,EAAS,WAAA,EAAa,MAAM,mCAAA;AAAoC,KAC9E,CAAA;AACD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,QAAA,CAAS,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,IACpC;AAAA,EACF,CAAA;AACF;;;;;;"}
1
+ {"version":3,"file":"error.js","sources":["../../src/error.ts"],"sourcesContent":["import { captureException } from '@sentry/browser';\nimport { isError } from '@sentry/core';\nimport type { ErrorInfo } from 'react';\n\n/**\n * Recurse through `error.cause` chain to set cause on an error.\n */\nexport function setCause(error: Error & { cause?: Error }, cause: Error): void {\n const seenErrors = new WeakSet();\n\n function recurse(error: Error & { cause?: Error }, cause: Error): void {\n // If we've already seen the error, there is a recursive loop somewhere in the error's\n // cause chain. Let's just bail out then to prevent a stack overflow.\n if (seenErrors.has(error)) {\n return;\n }\n if (error.cause) {\n seenErrors.add(error);\n return recurse(error.cause, cause);\n }\n error.cause = cause;\n }\n\n recurse(error, cause);\n}\n\n/**\n * Captures an error that was thrown by a React ErrorBoundary or React root.\n *\n * @param error The error to capture.\n * @param errorInfo The errorInfo provided by React.\n * @param hint Optional additional data to attach to the Sentry event.\n * @returns the id of the captured Sentry event.\n */\nexport function captureReactException(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n error: any,\n { componentStack }: ErrorInfo,\n hint?: Parameters<typeof captureException>[1],\n): string {\n // Create a stack trace from the componentStack param and link it to the original error\n // using `error.cause`. Linking errors requires the `LinkedErrors` integration be enabled.\n // See: https://reactjs.org/blog/2020/08/10/react-v17-rc.html#native-component-stacks\n //\n // Although `componentDidCatch` is typed to accept an `Error` object, it can also be invoked\n // with non-error objects. This is why we need to check if the error is an error-like object.\n // See: https://github.com/getsentry/sentry-javascript/issues/6167\n if (isError(error) && componentStack) {\n const errorBoundaryError = new Error(error.message);\n errorBoundaryError.name = `React ErrorBoundary ${error.name}`;\n errorBoundaryError.stack = componentStack;\n\n // Using the `LinkedErrors` integration to link the errors together.\n setCause(error, errorBoundaryError);\n }\n\n return captureException(error, hint);\n}\n\n/**\n * Creates an error handler that can be used with the `onCaughtError`, `onUncaughtError`,\n * and `onRecoverableError` options in `createRoot` and `hydrateRoot` React DOM methods.\n *\n * @param callback An optional callback that will be called after the error is captured.\n * Use this to add custom handling for errors.\n *\n * @example\n *\n * ```JavaScript\n * const root = createRoot(container, {\n * onCaughtError: Sentry.reactErrorHandler(),\n * onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {\n * console.warn('Caught error', error, errorInfo.componentStack);\n * });\n * });\n * ```\n */\nexport function reactErrorHandler(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n callback?: (error: any, errorInfo: ErrorInfo, eventId: string) => void,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): (error: any, errorInfo: ErrorInfo) => void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (error: any, errorInfo: ErrorInfo) => {\n const hasCallback = !!callback;\n const eventId = captureReactException(error, errorInfo, {\n mechanism: { handled: hasCallback, type: 'auto.function.react.error_handler' },\n });\n if (hasCallback) {\n callback(error, errorInfo, eventId);\n }\n };\n}\n"],"names":["error","cause","isError","captureException"],"mappings":";;;;;AAOO,SAAS,QAAA,CAAS,OAAkC,KAAA,EAAoB;AAC7E,EAAA,MAAM,UAAA,uBAAiB,OAAA,EAAQ;AAE/B,EAAA,SAAS,OAAA,CAAQA,QAAkCC,MAAAA,EAAoB;AAGrE,IAAA,IAAI,UAAA,CAAW,GAAA,CAAID,MAAK,CAAA,EAAG;AACzB,MAAA;AAAA,IACF;AACA,IAAA,IAAIA,OAAM,KAAA,EAAO;AACf,MAAA,UAAA,CAAW,IAAIA,MAAK,CAAA;AACpB,MAAA,OAAO,OAAA,CAAQA,MAAAA,CAAM,KAAA,EAAOC,MAAK,CAAA;AAAA,IACnC;AACA,IAAAD,OAAM,KAAA,GAAQC,MAAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,OAAO,KAAK,CAAA;AACtB;AAUO,SAAS,qBAAA,CAEd,KAAA,EACA,EAAE,cAAA,IACF,IAAA,EACQ;AAQR,EAAA,IAAIC,YAAA,CAAQ,KAAK,CAAA,IAAK,cAAA,EAAgB;AACpC,IAAA,MAAM,kBAAA,GAAqB,IAAI,KAAA,CAAM,KAAA,CAAM,OAAO,CAAA;AAClD,IAAA,kBAAA,CAAmB,IAAA,GAAO,CAAA,oBAAA,EAAuB,KAAA,CAAM,IAAI,CAAA,CAAA;AAC3D,IAAA,kBAAA,CAAmB,KAAA,GAAQ,cAAA;AAG3B,IAAA,QAAA,CAAS,OAAO,kBAAkB,CAAA;AAAA,EACpC;AAEA,EAAA,OAAOC,wBAAA,CAAiB,OAAO,IAAI,CAAA;AACrC;AAoBO,SAAS,kBAEd,QAAA,EAE4C;AAE5C,EAAA,OAAO,CAAC,OAAY,SAAA,KAAyB;AAC3C,IAAA,MAAM,WAAA,GAAc,CAAC,CAAC,QAAA;AACtB,IAAA,MAAM,OAAA,GAAU,qBAAA,CAAsB,KAAA,EAAO,SAAA,EAAW;AAAA,MACtD,SAAA,EAAW,EAAE,OAAA,EAAS,WAAA,EAAa,MAAM,mCAAA;AAAoC,KAC9E,CAAA;AACD,IAAA,IAAI,WAAA,EAAa;AACf,MAAA,QAAA,CAAS,KAAA,EAAO,WAAW,OAAO,CAAA;AAAA,IACpC;AAAA,EACF,CAAA;AACF;;;;;;"}
@@ -19,10 +19,9 @@ class Profiler extends React.Component {
19
19
  name: `<${name}>`,
20
20
  onlyIfParent: true,
21
21
  attributes: {
22
- // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.
23
- [attributes.SENTRY_OP]: "ui.mount",
22
+ [attributes.SENTRY_OP]: op.UI_MOUNT,
24
23
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
25
- "ui.component_name": name
24
+ [attributes.UI_COMPONENT_NAME]: name
26
25
  }
27
26
  });
28
27
  }
@@ -43,10 +42,9 @@ class Profiler extends React.Component {
43
42
  onlyIfParent: true,
44
43
  startTime: now,
45
44
  attributes: {
46
- // TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`.
47
- [attributes.SENTRY_OP]: "ui.update",
45
+ [attributes.SENTRY_OP]: op.UI_UPDATE,
48
46
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
49
- "ui.component_name": this.props.name,
47
+ [attributes.UI_COMPONENT_NAME]: this.props.name,
50
48
  "ui.react.changed_props": changedProps
51
49
  }
52
50
  });
@@ -74,9 +72,9 @@ class Profiler extends React.Component {
74
72
  name: `<${name}>`,
75
73
  startTime,
76
74
  attributes: {
77
- [attributes.SENTRY_OP]: op.BROWSER_UI_RENDER_SPAN_OP,
75
+ [attributes.SENTRY_OP]: op.UI_RENDER,
78
76
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
79
- "ui.component_name": name
77
+ [attributes.UI_COMPONENT_NAME]: name
80
78
  }
81
79
  });
82
80
  if (renderSpan) {
@@ -115,10 +113,9 @@ function useProfiler(name, options = {
115
113
  name: `<${name}>`,
116
114
  onlyIfParent: true,
117
115
  attributes: {
118
- // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.
119
- [attributes.SENTRY_OP]: "ui.mount",
116
+ [attributes.SENTRY_OP]: op.UI_MOUNT,
120
117
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
121
- "ui.component_name": name
118
+ [attributes.UI_COMPONENT_NAME]: name
122
119
  }
123
120
  });
124
121
  });
@@ -135,9 +132,9 @@ function useProfiler(name, options = {
135
132
  onlyIfParent: true,
136
133
  startTime,
137
134
  attributes: {
138
- [attributes.SENTRY_OP]: op.BROWSER_UI_RENDER_SPAN_OP,
135
+ [attributes.SENTRY_OP]: op.UI_RENDER,
139
136
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.react.profiler",
140
- "ui.component_name": name
137
+ [attributes.UI_COMPONENT_NAME]: name
141
138
  }
142
139
  });
143
140
  if (renderSpan) {
@@ -1 +1 @@
1
- {"version":3,"file":"profiler.js","sources":["../../src/profiler.tsx"],"sourcesContent":["import { startInactiveSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, timestampInSeconds, withActiveSpan } from '@sentry/core';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { BROWSER_UI_RENDER_SPAN_OP } from '@sentry/conventions/op';\nimport * as React from 'react';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // Component that is being profiled.\n children?: React.ReactNode;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined;\n /**\n * The span that represents the duration of time between shouldComponentUpdate and componentDidUpdate\n */\n protected _updateSpan: Span | undefined;\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n this._mountSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.mount',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.end();\n }\n }\n\n public shouldComponentUpdate({ updateProps, includeUpdates = true }: ProfilerProps): boolean {\n // Only generate an update span if includeUpdates is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props have changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potentially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n const now = timestampInSeconds();\n this._updateSpan = withActiveSpan(this._mountSpan, () => {\n return startInactiveSpan({\n name: `<${this.props.name}>`,\n onlyIfParent: true,\n startTime: now,\n attributes: {\n // TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.update',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': this.props.name,\n 'ui.react.changed_props': changedProps,\n },\n });\n });\n }\n }\n\n return true;\n }\n\n public componentDidUpdate(): void {\n if (this._updateSpan) {\n this._updateSpan.end();\n this._updateSpan = undefined;\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const endTimestamp = timestampInSeconds();\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n const startTime = spanToJSON(this._mountSpan).end_timestamp;\n withActiveSpan(this._mountSpan, () => {\n const renderSpan = startInactiveSpan({\n onlyIfParent: true,\n name: `<${name}>`,\n startTime,\n attributes: {\n [SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n// React.Component default props are defined as static property on the class\nObject.assign(Profiler, {\n defaultProps: {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n },\n});\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps' | 'children'>>,\n): React.FC<P> {\n const componentDisplayName =\n options?.name || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options?.disabled) {\n return undefined;\n }\n\n return startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`.\n [SENTRY_OP]: 'ui.mount',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.end();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n const startTime = spanToJSON(mountSpan).end_timestamp;\n const endTimestamp = timestampInSeconds();\n\n const renderSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n startTime,\n attributes: {\n [SENTRY_OP]: BROWSER_UI_RENDER_SPAN_OP,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n 'ui.component_name': name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { Profiler, useProfiler, withProfiler };\n"],"names":["startInactiveSpan","SENTRY_OP","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","timestampInSeconds","withActiveSpan","spanToJSON","BROWSER_UI_RENDER_SPAN_OP","hoistNonReactStatics"],"mappings":"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"}
1
+ {"version":3,"file":"profiler.js","sources":["../../src/profiler.tsx"],"sourcesContent":["import { startInactiveSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, timestampInSeconds, withActiveSpan } from '@sentry/core';\nimport { SENTRY_OP, UI_COMPONENT_NAME } from '@sentry/conventions/attributes';\nimport { UI_MOUNT, UI_RENDER, UI_UPDATE } from '@sentry/conventions/op';\nimport * as React from 'react';\nimport { hoistNonReactStatics } from './hoist-non-react-statics';\n\nexport const UNKNOWN_COMPONENT = 'unknown';\n\nexport type ProfilerProps = {\n // The name of the component being profiled.\n name: string;\n // If the Profiler is disabled. False by default. This is useful if you want to disable profilers\n // in certain environments.\n disabled?: boolean;\n // If time component is on page should be displayed as spans. True by default.\n includeRender?: boolean;\n // If component updates should be displayed as spans. True by default.\n includeUpdates?: boolean;\n // Component that is being profiled.\n children?: React.ReactNode;\n // props given to component being profiled.\n updateProps: { [key: string]: unknown };\n};\n\n/**\n * The Profiler component leverages Sentry's Tracing integration to generate\n * spans based on component lifecycles.\n */\nclass Profiler extends React.Component<ProfilerProps> {\n /**\n * The span of the mount activity\n * Made protected for the React Native SDK to access\n */\n protected _mountSpan: Span | undefined;\n /**\n * The span that represents the duration of time between shouldComponentUpdate and componentDidUpdate\n */\n protected _updateSpan: Span | undefined;\n\n public constructor(props: ProfilerProps) {\n super(props);\n const { name, disabled = false } = this.props;\n\n if (disabled) {\n return;\n }\n\n this._mountSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n [SENTRY_OP]: UI_MOUNT,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n [UI_COMPONENT_NAME]: name,\n },\n });\n }\n\n // If a component mounted, we can finish the mount activity.\n public componentDidMount(): void {\n if (this._mountSpan) {\n this._mountSpan.end();\n }\n }\n\n public shouldComponentUpdate({ updateProps, includeUpdates = true }: ProfilerProps): boolean {\n // Only generate an update span if includeUpdates is true, if there is a valid mountSpan,\n // and if the updateProps have changed. It is ok to not do a deep equality check here as it is expensive.\n // We are just trying to give baseline clues for further investigation.\n if (includeUpdates && this._mountSpan && updateProps !== this.props.updateProps) {\n // See what props have changed between the previous props, and the current props. This is\n // set as data on the span. We just store the prop keys as the values could be potentially very large.\n const changedProps = Object.keys(updateProps).filter(k => updateProps[k] !== this.props.updateProps[k]);\n if (changedProps.length > 0) {\n const now = timestampInSeconds();\n this._updateSpan = withActiveSpan(this._mountSpan, () => {\n return startInactiveSpan({\n name: `<${this.props.name}>`,\n onlyIfParent: true,\n startTime: now,\n attributes: {\n [SENTRY_OP]: UI_UPDATE,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n [UI_COMPONENT_NAME]: this.props.name,\n 'ui.react.changed_props': changedProps,\n },\n });\n });\n }\n }\n\n return true;\n }\n\n public componentDidUpdate(): void {\n if (this._updateSpan) {\n this._updateSpan.end();\n this._updateSpan = undefined;\n }\n }\n\n // If a component is unmounted, we can say it is no longer on the screen.\n // This means we can finish the span representing the component render.\n public componentWillUnmount(): void {\n const endTimestamp = timestampInSeconds();\n const { name, includeRender = true } = this.props;\n\n if (this._mountSpan && includeRender) {\n const startTime = spanToJSON(this._mountSpan).end_timestamp;\n withActiveSpan(this._mountSpan, () => {\n const renderSpan = startInactiveSpan({\n onlyIfParent: true,\n name: `<${name}>`,\n startTime,\n attributes: {\n [SENTRY_OP]: UI_RENDER,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n [UI_COMPONENT_NAME]: name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n });\n }\n }\n\n public render(): React.ReactNode {\n return this.props.children;\n }\n}\n\n// React.Component default props are defined as static property on the class\nObject.assign(Profiler, {\n defaultProps: {\n disabled: false,\n includeRender: true,\n includeUpdates: true,\n },\n});\n\n/**\n * withProfiler is a higher order component that wraps a\n * component in a {@link Profiler} component. It is recommended that\n * the higher order component be used over the regular {@link Profiler} component.\n *\n * @param WrappedComponent component that is wrapped by Profiler\n * @param options the {@link ProfilerProps} you can pass into the Profiler\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction withProfiler<P extends Record<string, any>>(\n WrappedComponent: React.ComponentType<P>,\n // We do not want to have `updateProps` given in options, it is instead filled through the HOC.\n options?: Pick<Partial<ProfilerProps>, Exclude<keyof ProfilerProps, 'updateProps' | 'children'>>,\n): React.FC<P> {\n const componentDisplayName =\n options?.name || WrappedComponent.displayName || WrappedComponent.name || UNKNOWN_COMPONENT;\n\n const Wrapped: React.FC<P> = (props: P) => (\n <Profiler {...options} name={componentDisplayName} updateProps={props}>\n <WrappedComponent {...props} />\n </Profiler>\n );\n\n Wrapped.displayName = `profiler(${componentDisplayName})`;\n\n // Copy over static methods from Wrapped component to Profiler HOC\n // See: https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over\n hoistNonReactStatics(Wrapped, WrappedComponent);\n return Wrapped;\n}\n\n/**\n *\n * `useProfiler` is a React hook that profiles a React component.\n *\n * @param name displayName of component being profiled\n */\nfunction useProfiler(\n name: string,\n options: { disabled?: boolean; hasRenderSpan?: boolean } = {\n disabled: false,\n hasRenderSpan: true,\n },\n): void {\n const [mountSpan] = React.useState(() => {\n if (options?.disabled) {\n return undefined;\n }\n\n return startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n attributes: {\n [SENTRY_OP]: UI_MOUNT,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n [UI_COMPONENT_NAME]: name,\n },\n });\n });\n\n React.useEffect(() => {\n if (mountSpan) {\n mountSpan.end();\n }\n\n return (): void => {\n if (mountSpan && options.hasRenderSpan) {\n const startTime = spanToJSON(mountSpan).end_timestamp;\n const endTimestamp = timestampInSeconds();\n\n const renderSpan = startInactiveSpan({\n name: `<${name}>`,\n onlyIfParent: true,\n startTime,\n attributes: {\n [SENTRY_OP]: UI_RENDER,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler',\n [UI_COMPONENT_NAME]: name,\n },\n });\n if (renderSpan) {\n // Have to cast to Span because the type of _mountSpan is Span | undefined\n // and not getting narrowed properly\n renderSpan.end(endTimestamp);\n }\n }\n };\n // We only want this to run once.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n}\n\nexport { Profiler, useProfiler, withProfiler };\n"],"names":["startInactiveSpan","SENTRY_OP","UI_MOUNT","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","UI_COMPONENT_NAME","timestampInSeconds","withActiveSpan","UI_UPDATE","spanToJSON","UI_RENDER","hoistNonReactStatics"],"mappings":"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"}
@@ -8,6 +8,7 @@ const hoistNonReactStatics = require('../hoist-non-react-statics.js');
8
8
  const lazyRoutes = require('./lazy-routes.js');
9
9
  const utils = require('./utils.js');
10
10
  const attributes = require('@sentry/conventions/attributes');
11
+ const op = require('@sentry/conventions/op');
11
12
 
12
13
  let _useEffect;
13
14
  let _useLocation;
@@ -159,14 +160,16 @@ function updateNavigationSpan(activeRootSpan, location, allRoutes2, forceUpdate
159
160
  _lazyRouteManifest,
160
161
  _enableAsyncRouteHandlers
161
162
  );
162
- const currentSource = attributes$1[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
163
+ const currentSource = attributes$1[attributes.SENTRY_SEGMENT_NAME_SOURCE];
163
164
  const isImprovement = name && (!currentName || // No current name - always set
164
165
  !hasBeenNamed && (currentSource !== "route" || source === "route") || // Not finalized - allow unless downgrading route→url
165
166
  currentSource !== "route" && source === "route" || // URL → route upgrade
166
167
  currentSource === "route" && source === "route" && currentNameHasWildcard);
167
168
  if (isImprovement) {
168
- activeRootSpan.updateName(name);
169
- activeRootSpan.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
169
+ const client = core.getClient();
170
+ const isUnparameterizedStreamedNavigation = source !== "route" && !!client && core.hasSpanStreamingEnabled(client);
171
+ activeRootSpan.updateName(isUnparameterizedStreamedNavigation ? core.NAVIGATION_SPAN_NAME_FALLBACK : name);
172
+ activeRootSpan.setAttribute(attributes.SENTRY_SEGMENT_NAME_SOURCE, source);
170
173
  if (source === "route") {
171
174
  activeRootSpan.setAttribute(attributes.URL_TEMPLATE, name);
172
175
  }
@@ -371,10 +374,12 @@ function createReactRouterV6CompatibleTracingIntegration(options, version) {
371
374
  const initPathName = browser.WINDOW.location?.pathname;
372
375
  if (instrumentPageLoad && initPathName) {
373
376
  browser.startBrowserTracingPageLoadSpan(client, {
374
- name: initPathName,
377
+ // With span streaming, span names have to be low cardinality. The route is only resolved
378
+ // once the router renders, which updates the span name then.
379
+ name: core.hasSpanStreamingEnabled(client) ? core.PAGELOAD_SPAN_NAME_FALLBACK : initPathName,
375
380
  attributes: {
376
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: "url",
377
- [core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "pageload",
381
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: "url",
382
+ [attributes.SENTRY_OP]: op.PAGELOAD,
378
383
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.pageload.react.reactrouter${version ? `_v${version}` : ""}`
379
384
  }
380
385
  });
@@ -543,8 +548,9 @@ function handleNavigation(opts) {
543
548
  `[Tracing] Updated placeholder navigation name from "${oldName}" to "${name}" (will apply to real span)`
544
549
  );
545
550
  } else {
546
- trackedNav.span.updateName(name);
547
- trackedNav.span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
551
+ const isUnparameterizedStreamedNavigation = source !== "route" && core.hasSpanStreamingEnabled(client);
552
+ trackedNav.span.updateName(isUnparameterizedStreamedNavigation ? core.NAVIGATION_SPAN_NAME_FALLBACK : name);
553
+ trackedNav.span.setAttribute(attributes.SENTRY_SEGMENT_NAME_SOURCE, source);
548
554
  if (source === "route") {
549
555
  trackedNav.span.setAttribute(attributes.URL_TEMPLATE, name);
550
556
  }
@@ -570,11 +576,12 @@ function handleNavigation(opts) {
570
576
  let navigationSpan;
571
577
  try {
572
578
  navigationSpan = browser.startBrowserTracingNavigationSpan(client, {
573
- name: placeholderEntry.routeName,
574
- // Use placeholder's routeName in case it was updated
579
+ // Use placeholder's routeName in case it was updated. With span streaming, span names have to
580
+ // be low cardinality, so we can't fall back to the URL.
581
+ name: source === "route" || !core.hasSpanStreamingEnabled(client) ? placeholderEntry.routeName : core.NAVIGATION_SPAN_NAME_FALLBACK,
575
582
  attributes: {
576
- [core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: source,
577
- [core.SEMANTIC_ATTRIBUTE_SENTRY_OP]: "navigation",
583
+ [attributes.SENTRY_SEGMENT_NAME_SOURCE]: source,
584
+ [attributes.SENTRY_OP]: op.NAVIGATION,
578
585
  [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: `auto.navigation.react.reactrouter${version ? `_v${version}` : ""}`,
579
586
  ...source === "route" && { [attributes.URL_TEMPLATE]: placeholderEntry.routeName }
580
587
  }
@@ -648,8 +655,10 @@ function updatePageloadTransaction({
648
655
  );
649
656
  core.getCurrentScope().setTransactionName(name || "/");
650
657
  if (activeRootSpan) {
651
- activeRootSpan.updateName(name);
652
- activeRootSpan.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
658
+ const client = core.getClient();
659
+ const isUnparameterizedStreamedPageload = source !== "route" && !!client && core.hasSpanStreamingEnabled(client);
660
+ activeRootSpan.updateName(isUnparameterizedStreamedPageload ? core.PAGELOAD_SPAN_NAME_FALLBACK : name);
661
+ activeRootSpan.setAttribute(attributes.SENTRY_SEGMENT_NAME_SOURCE, source);
653
662
  if (source === "route") {
654
663
  activeRootSpan.setAttribute(attributes.URL_TEMPLATE, name);
655
664
  }
@@ -677,7 +686,7 @@ function shouldUpdateWildcardSpanName(currentName, currentSource, newName, newSo
677
686
  }
678
687
  function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, routes, basename, spanType, allRoutes2) {
679
688
  try {
680
- const currentSource = spanJson.attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
689
+ const currentSource = spanJson.attributes[attributes.SENTRY_SEGMENT_NAME_SOURCE];
681
690
  if (currentSource === "route" && currentName && !utils.transactionNameHasWildcard(currentName)) {
682
691
  return;
683
692
  }
@@ -699,8 +708,11 @@ function tryUpdateSpanNameBeforeEnd(span, spanJson, currentName, location, route
699
708
  const isImprovement = shouldUpdateWildcardSpanName(currentName, currentSource, name, source, true);
700
709
  const spanNotEnded = spanType === "pageload" || !spanJson.end_timestamp;
701
710
  if (isImprovement && spanNotEnded) {
702
- span.updateName(name);
703
- span.setAttribute(core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
711
+ const client = core.getClient();
712
+ const isUnparameterizedStreamedSpan = source !== "route" && !!client && core.hasSpanStreamingEnabled(client);
713
+ const fallbackName = spanType === "pageload" ? core.PAGELOAD_SPAN_NAME_FALLBACK : core.NAVIGATION_SPAN_NAME_FALLBACK;
714
+ span.updateName(isUnparameterizedStreamedSpan ? fallbackName : name);
715
+ span.setAttribute(attributes.SENTRY_SEGMENT_NAME_SOURCE, source);
704
716
  if (source === "route") {
705
717
  span.setAttribute(attributes.URL_TEMPLATE, name);
706
718
  }
@@ -725,7 +737,7 @@ function patchSpanEnd(span, location, routes, basename, spanType) {
725
737
  const endTimestamp = args.length > 0 ? args[0] : Date.now() / 1e3;
726
738
  const spanJson = core.spanToJSON(span);
727
739
  const currentName = spanJson.name;
728
- const currentSource = spanJson.attributes[core.SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
740
+ const currentSource = spanJson.attributes[attributes.SENTRY_SEGMENT_NAME_SOURCE];
729
741
  const cleanupNavigationSpan = () => {
730
742
  const client = core.getClient();
731
743
  if (client && spanType === "navigation") {