initializeSdk.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. import {browserHistory, createRoutes, match} from 'react-router';
  2. import {ExtraErrorData} from '@sentry/integrations';
  3. import * as Sentry from '@sentry/react';
  4. import SentryRRWeb from '@sentry/rrweb';
  5. import {Integrations} from '@sentry/tracing';
  6. import {_browserPerformanceTimeOriginMode} from '@sentry/utils';
  7. import {DISABLE_RR_WEB, SENTRY_RELEASE_VERSION, SPA_DSN} from 'sentry/constants';
  8. import {Config} from 'sentry/types';
  9. import {init as initApiSentryClient} from 'sentry/utils/apiSentryClient';
  10. /**
  11. * We accept a routes argument here because importing `static/routes`
  12. * is expensive in regards to bundle size. Some entrypoints may opt to forgo
  13. * having routing instrumentation in order to have a smaller bundle size.
  14. * (e.g. `static/views/integrationPipeline`)
  15. */
  16. function getSentryIntegrations(hasReplays: boolean = false, routes?: Function) {
  17. const integrations = [
  18. new ExtraErrorData({
  19. // 6 is arbitrary, seems like a nice number
  20. depth: 6,
  21. }),
  22. new Integrations.BrowserTracing({
  23. ...(typeof routes === 'function'
  24. ? {
  25. routingInstrumentation: Sentry.reactRouterV3Instrumentation(
  26. browserHistory as any,
  27. createRoutes(routes()),
  28. match
  29. ),
  30. }
  31. : {}),
  32. idleTimeout: 5000,
  33. _metricOptions: {
  34. _reportAllChanges: false,
  35. },
  36. }),
  37. ];
  38. if (hasReplays) {
  39. // eslint-disable-next-line no-console
  40. console.log('[sentry] Instrumenting session with rrweb');
  41. // TODO(ts): The type returned by SentryRRWeb seems to be somewhat
  42. // incompatible. It's a newer plugin, so this can be expected, but we
  43. // should fix.
  44. integrations.push(
  45. new SentryRRWeb({
  46. checkoutEveryNms: 60 * 1000, // 60 seconds
  47. }) as any
  48. );
  49. }
  50. return integrations;
  51. }
  52. /**
  53. * Initialize the Sentry SDK
  54. *
  55. * If `routes` is passed, we will instrument react-router. Not all
  56. * entrypoints require this.
  57. */
  58. export function initializeSdk(config: Config, {routes}: {routes?: Function} = {}) {
  59. if (config.dsn_requests) {
  60. initApiSentryClient(config.dsn_requests);
  61. }
  62. const {apmSampling, sentryConfig, userIdentity} = config;
  63. const tracesSampleRate = apmSampling ?? 0;
  64. const hasReplays = userIdentity?.isStaff && !DISABLE_RR_WEB;
  65. Sentry.init({
  66. ...sentryConfig,
  67. /**
  68. * For SPA mode, we need a way to overwrite the default DSN from backend
  69. * as well as `whitelistUrls`
  70. */
  71. dsn: SPA_DSN || sentryConfig?.dsn,
  72. /**
  73. * Frontend can be built with a `SENTRY_RELEASE_VERSION` environment variable for release string, useful if frontend is
  74. * deployed separately from backend.
  75. */
  76. release: SENTRY_RELEASE_VERSION ?? sentryConfig?.release,
  77. whitelistUrls: SPA_DSN
  78. ? ['localhost', 'dev.getsentry.net', 'sentry.dev', 'webpack-internal://']
  79. : sentryConfig?.whitelistUrls,
  80. integrations: getSentryIntegrations(hasReplays, routes),
  81. tracesSampleRate,
  82. /**
  83. * There is a bug in Safari, that causes `AbortError` when fetch is aborted, and you are in the middle of reading the response.
  84. * In Chrome and other browsers, it is handled gracefully, where in Safari, it produces additional error, that is jumping
  85. * outside of the original Promise chain and bubbles up to the `unhandledRejection` handler, that we then captures as error.
  86. * Ref: https://bugs.webkit.org/show_bug.cgi?id=215771
  87. */
  88. ignoreErrors: ['AbortError: Fetch is aborted'],
  89. });
  90. // Track timeOrigin Selection by the SDK to see if it improves transaction durations
  91. Sentry.addGlobalEventProcessor((event: Sentry.Event, _hint?: Sentry.EventHint) => {
  92. event.tags = event.tags || {};
  93. event.tags['timeOrigin.mode'] = _browserPerformanceTimeOriginMode;
  94. return event;
  95. });
  96. if (userIdentity) {
  97. Sentry.setUser(userIdentity);
  98. }
  99. if (window.__SENTRY__VERSION) {
  100. Sentry.setTag('sentry_version', window.__SENTRY__VERSION);
  101. }
  102. Sentry.setTag('rrweb.active', hasReplays ? 'yes' : 'no');
  103. }