@sentry/browser 9.39.0 → 10.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 (101) hide show
  1. package/build/npm/cjs/client.js +1 -2
  2. package/build/npm/cjs/client.js.map +1 -1
  3. package/build/npm/cjs/eventbuilder.js +2 -2
  4. package/build/npm/cjs/eventbuilder.js.map +1 -1
  5. package/build/npm/cjs/helpers.js +1 -1
  6. package/build/npm/cjs/helpers.js.map +1 -1
  7. package/build/npm/cjs/index.js +3 -0
  8. package/build/npm/cjs/index.js.map +1 -1
  9. package/build/npm/cjs/integrations/breadcrumbs.js +2 -2
  10. package/build/npm/cjs/integrations/breadcrumbs.js.map +1 -1
  11. package/build/npm/cjs/integrations/browserapierrors.js +1 -1
  12. package/build/npm/cjs/integrations/browserapierrors.js.map +1 -1
  13. package/build/npm/cjs/integrations/browsersession.js +1 -1
  14. package/build/npm/cjs/integrations/browsersession.js.map +1 -1
  15. package/build/npm/cjs/integrations/featureFlags/unleash/integration.js +1 -1
  16. package/build/npm/cjs/integrations/featureFlags/unleash/integration.js.map +1 -1
  17. package/build/npm/cjs/integrations/globalhandlers.js +1 -1
  18. package/build/npm/cjs/integrations/globalhandlers.js.map +1 -1
  19. package/build/npm/cjs/integrations/httpclient.js +1 -1
  20. package/build/npm/cjs/integrations/httpclient.js.map +1 -1
  21. package/build/npm/cjs/integrations/spotlight.js +4 -5
  22. package/build/npm/cjs/integrations/spotlight.js.map +1 -1
  23. package/build/npm/cjs/integrations/webWorker.js +139 -0
  24. package/build/npm/cjs/integrations/webWorker.js.map +1 -0
  25. package/build/npm/cjs/log.js +6 -6
  26. package/build/npm/cjs/log.js.map +1 -1
  27. package/build/npm/cjs/profiling/integration.js +3 -3
  28. package/build/npm/cjs/profiling/integration.js.map +1 -1
  29. package/build/npm/cjs/profiling/startProfileForSpan.js +5 -5
  30. package/build/npm/cjs/profiling/startProfileForSpan.js.map +1 -1
  31. package/build/npm/cjs/profiling/utils.js +16 -18
  32. package/build/npm/cjs/profiling/utils.js.map +1 -1
  33. package/build/npm/cjs/report-dialog.js +2 -2
  34. package/build/npm/cjs/report-dialog.js.map +1 -1
  35. package/build/npm/cjs/tracing/backgroundtab.js +2 -2
  36. package/build/npm/cjs/tracing/backgroundtab.js.map +1 -1
  37. package/build/npm/cjs/tracing/browserTracingIntegration.js +4 -4
  38. package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
  39. package/build/npm/cjs/tracing/linkedTraces.js +3 -3
  40. package/build/npm/cjs/tracing/linkedTraces.js.map +1 -1
  41. package/build/npm/cjs/tracing/request.js +2 -2
  42. package/build/npm/cjs/tracing/request.js.map +1 -1
  43. package/build/npm/cjs/transports/offline.js +3 -3
  44. package/build/npm/cjs/transports/offline.js.map +1 -1
  45. package/build/npm/esm/client.js +1 -2
  46. package/build/npm/esm/client.js.map +1 -1
  47. package/build/npm/esm/eventbuilder.js +2 -2
  48. package/build/npm/esm/eventbuilder.js.map +1 -1
  49. package/build/npm/esm/helpers.js +1 -1
  50. package/build/npm/esm/helpers.js.map +1 -1
  51. package/build/npm/esm/index.js +1 -0
  52. package/build/npm/esm/index.js.map +1 -1
  53. package/build/npm/esm/integrations/breadcrumbs.js +3 -3
  54. package/build/npm/esm/integrations/breadcrumbs.js.map +1 -1
  55. package/build/npm/esm/integrations/browserapierrors.js +1 -1
  56. package/build/npm/esm/integrations/browserapierrors.js.map +1 -1
  57. package/build/npm/esm/integrations/browsersession.js +2 -2
  58. package/build/npm/esm/integrations/browsersession.js.map +1 -1
  59. package/build/npm/esm/integrations/featureFlags/unleash/integration.js +2 -2
  60. package/build/npm/esm/integrations/featureFlags/unleash/integration.js.map +1 -1
  61. package/build/npm/esm/integrations/globalhandlers.js +2 -2
  62. package/build/npm/esm/integrations/globalhandlers.js.map +1 -1
  63. package/build/npm/esm/integrations/httpclient.js +2 -2
  64. package/build/npm/esm/integrations/httpclient.js.map +1 -1
  65. package/build/npm/esm/integrations/spotlight.js +5 -6
  66. package/build/npm/esm/integrations/spotlight.js.map +1 -1
  67. package/build/npm/esm/integrations/webWorker.js +135 -0
  68. package/build/npm/esm/integrations/webWorker.js.map +1 -0
  69. package/build/npm/esm/log.js +6 -6
  70. package/build/npm/esm/log.js.map +1 -1
  71. package/build/npm/esm/package.json +1 -1
  72. package/build/npm/esm/profiling/integration.js +4 -4
  73. package/build/npm/esm/profiling/integration.js.map +1 -1
  74. package/build/npm/esm/profiling/startProfileForSpan.js +6 -6
  75. package/build/npm/esm/profiling/startProfileForSpan.js.map +1 -1
  76. package/build/npm/esm/profiling/utils.js +17 -19
  77. package/build/npm/esm/profiling/utils.js.map +1 -1
  78. package/build/npm/esm/report-dialog.js +3 -3
  79. package/build/npm/esm/report-dialog.js.map +1 -1
  80. package/build/npm/esm/tracing/backgroundtab.js +3 -3
  81. package/build/npm/esm/tracing/backgroundtab.js.map +1 -1
  82. package/build/npm/esm/tracing/browserTracingIntegration.js +5 -5
  83. package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
  84. package/build/npm/esm/tracing/linkedTraces.js +4 -4
  85. package/build/npm/esm/tracing/linkedTraces.js.map +1 -1
  86. package/build/npm/esm/tracing/request.js +2 -2
  87. package/build/npm/esm/tracing/request.js.map +1 -1
  88. package/build/npm/esm/transports/offline.js +3 -3
  89. package/build/npm/esm/transports/offline.js.map +1 -1
  90. package/build/npm/types/client.d.ts.map +1 -1
  91. package/build/npm/types/index.d.ts +1 -0
  92. package/build/npm/types/index.d.ts.map +1 -1
  93. package/build/npm/types/integrations/spotlight.d.ts.map +1 -1
  94. package/build/npm/types/integrations/webWorker.d.ts +103 -0
  95. package/build/npm/types/integrations/webWorker.d.ts.map +1 -0
  96. package/build/npm/types/log.d.ts +6 -6
  97. package/build/npm/types/profiling/utils.d.ts.map +1 -1
  98. package/build/npm/types-ts3.8/index.d.ts +1 -0
  99. package/build/npm/types-ts3.8/integrations/webWorker.d.ts +103 -0
  100. package/build/npm/types-ts3.8/log.d.ts +6 -6
  101. package/package.json +7 -7
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../src/profiling/utils.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { DebugImage, Envelope, Event, EventEnvelope, Profile, Span, ThreadCpuProfile } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n DEFAULT_ENVIRONMENT,\n forEachEnvelopeItem,\n getClient,\n getDebugImagesForResources,\n logger,\n spanToJSON,\n timestampInSeconds,\n uuid4,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport type { JSSelfProfile, JSSelfProfiler, JSSelfProfilerConstructor, JSSelfProfileStack } from './jsSelfProfiling';\n\nconst MS_TO_NS = 1e6;\n// Use 0 as main thread id which is identical to threadId in node:worker_threads\n// where main logs 0 and workers seem to log in increments of 1\nconst THREAD_ID_STRING = String(0);\nconst THREAD_NAME = 'main';\n\n// We force make this optional to be on the safe side...\nconst navigator = WINDOW.navigator as typeof WINDOW.navigator | undefined;\n\n// Machine properties (eval only once)\nlet OS_PLATFORM = '';\nlet OS_PLATFORM_VERSION = '';\nlet OS_ARCH = '';\nlet OS_BROWSER = navigator?.userAgent || '';\nlet OS_MODEL = '';\nconst OS_LOCALE = navigator?.language || navigator?.languages?.[0] || '';\n\ntype UAData = {\n platform?: string;\n architecture?: string;\n model?: string;\n platformVersion?: string;\n fullVersionList?: {\n brand: string;\n version: string;\n }[];\n};\n\ninterface UserAgentData {\n getHighEntropyValues: (keys: string[]) => Promise<UAData>;\n}\n\nfunction isUserAgentData(data: unknown): data is UserAgentData {\n return typeof data === 'object' && data !== null && 'getHighEntropyValues' in data;\n}\n\n// @ts-expect-error userAgentData is not part of the navigator interface yet\nconst userAgentData = navigator?.userAgentData;\n\nif (isUserAgentData(userAgentData)) {\n userAgentData\n .getHighEntropyValues(['architecture', 'model', 'platform', 'platformVersion', 'fullVersionList'])\n .then((ua: UAData) => {\n OS_PLATFORM = ua.platform || '';\n OS_ARCH = ua.architecture || '';\n OS_MODEL = ua.model || '';\n OS_PLATFORM_VERSION = ua.platformVersion || '';\n\n if (ua.fullVersionList?.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstUa = ua.fullVersionList[ua.fullVersionList.length - 1]!;\n OS_BROWSER = `${firstUa.brand} ${firstUa.version}`;\n }\n })\n .catch(e => void e);\n}\n\nfunction isProcessedJSSelfProfile(profile: ThreadCpuProfile | JSSelfProfile): profile is JSSelfProfile {\n return !('thread_metadata' in profile);\n}\n\n// Enriches the profile with threadId of the current thread.\n// This is done in node as we seem to not be able to get the info from C native code.\n/**\n *\n */\nexport function enrichWithThreadInformation(profile: ThreadCpuProfile | JSSelfProfile): ThreadCpuProfile {\n if (!isProcessedJSSelfProfile(profile)) {\n return profile;\n }\n\n return convertJSSelfProfileToSampledFormat(profile);\n}\n\n// Profile is marked as optional because it is deleted from the metadata\n// by the integration before the event is processed by other integrations.\nexport interface ProfiledEvent extends Event {\n sdkProcessingMetadata: {\n profile?: JSSelfProfile;\n };\n}\n\nfunction getTraceId(event: Event): string {\n const traceId: unknown = event.contexts?.trace?.['trace_id'];\n // Log a warning if the profile has an invalid traceId (should be uuidv4).\n // All profiles and transactions are rejected if this is the case and we want to\n // warn users that this is happening if they enable debug flag\n if (typeof traceId === 'string' && traceId.length !== 32) {\n if (DEBUG_BUILD) {\n logger.log(`[Profiling] Invalid traceId: ${traceId} on profiled event`);\n }\n }\n if (typeof traceId !== 'string') {\n return '';\n }\n\n return traceId;\n}\n/**\n * Creates a profiling event envelope from a Sentry event. If profile does not pass\n * validation, returns null.\n * @param event\n * @param dsn\n * @param metadata\n * @param tunnel\n * @returns {EventEnvelope | null}\n */\n\n/**\n * Creates a profiling event envelope from a Sentry event.\n */\nexport function createProfilePayload(\n profile_id: string,\n start_timestamp: number | undefined,\n processed_profile: JSSelfProfile,\n event: ProfiledEvent,\n): Profile {\n if (event.type !== 'transaction') {\n // createProfilingEventEnvelope should only be called for transactions,\n // we type guard this behavior with isProfiledTransactionEvent.\n throw new TypeError('Profiling events may only be attached to transactions, this should never occur.');\n }\n\n if (processed_profile === undefined || processed_profile === null) {\n throw new TypeError(\n `Cannot construct profiling event envelope without a valid profile. Got ${processed_profile} instead.`,\n );\n }\n\n const traceId = getTraceId(event);\n const enrichedThreadProfile = enrichWithThreadInformation(processed_profile);\n const transactionStartMs = start_timestamp\n ? start_timestamp\n : typeof event.start_timestamp === 'number'\n ? event.start_timestamp * 1000\n : timestampInSeconds() * 1000;\n const transactionEndMs = typeof event.timestamp === 'number' ? event.timestamp * 1000 : timestampInSeconds() * 1000;\n\n const profile: Profile = {\n event_id: profile_id,\n timestamp: new Date(transactionStartMs).toISOString(),\n platform: 'javascript',\n version: '1',\n release: event.release || '',\n environment: event.environment || DEFAULT_ENVIRONMENT,\n runtime: {\n name: 'javascript',\n version: WINDOW.navigator.userAgent,\n },\n os: {\n name: OS_PLATFORM,\n version: OS_PLATFORM_VERSION,\n build_number: OS_BROWSER,\n },\n device: {\n locale: OS_LOCALE,\n model: OS_MODEL,\n manufacturer: OS_BROWSER,\n architecture: OS_ARCH,\n is_emulator: false,\n },\n debug_meta: {\n images: applyDebugMetadata(processed_profile.resources),\n },\n profile: enrichedThreadProfile,\n transactions: [\n {\n name: event.transaction || '',\n id: event.event_id || uuid4(),\n trace_id: traceId,\n active_thread_id: THREAD_ID_STRING,\n relative_start_ns: '0',\n relative_end_ns: ((transactionEndMs - transactionStartMs) * 1e6).toFixed(0),\n },\n ],\n };\n\n return profile;\n}\n\n/**\n *\n */\nexport function isProfiledTransactionEvent(event: Event): event is ProfiledEvent {\n return !!event.sdkProcessingMetadata?.profile;\n}\n\n/*\n See packages/browser-utils/src/browser/router.ts\n*/\n/**\n *\n */\nexport function isAutomatedPageLoadSpan(span: Span): boolean {\n return spanToJSON(span).op === 'pageload';\n}\n\n/**\n * Converts a JSSelfProfile to a our sampled format.\n * Does not currently perform stack indexing.\n */\nexport function convertJSSelfProfileToSampledFormat(input: JSSelfProfile): Profile['profile'] {\n let EMPTY_STACK_ID: undefined | number = undefined;\n let STACK_ID = 0;\n\n // Initialize the profile that we will fill with data\n const profile: Profile['profile'] = {\n samples: [],\n stacks: [],\n frames: [],\n thread_metadata: {\n [THREAD_ID_STRING]: { name: THREAD_NAME },\n },\n };\n\n const firstSample = input.samples[0];\n if (!firstSample) {\n return profile;\n }\n\n // We assert samples.length > 0 above and timestamp should always be present\n const start = firstSample.timestamp;\n // The JS SDK might change it's time origin based on some heuristic (see See packages/utils/src/time.ts)\n // when that happens, we need to ensure we are correcting the profile timings so the two timelines stay in sync.\n // Since JS self profiling time origin is always initialized to performance.timeOrigin, we need to adjust for\n // the drift between the SDK selected value and our profile time origin.\n const perfOrigin = browserPerformanceTimeOrigin();\n const origin = typeof performance.timeOrigin === 'number' ? performance.timeOrigin : perfOrigin || 0;\n const adjustForOriginChange = origin - (perfOrigin || origin);\n\n input.samples.forEach((jsSample, i) => {\n // If sample has no stack, add an empty sample\n if (jsSample.stackId === undefined) {\n if (EMPTY_STACK_ID === undefined) {\n EMPTY_STACK_ID = STACK_ID;\n profile.stacks[EMPTY_STACK_ID] = [];\n STACK_ID++;\n }\n\n profile['samples'][i] = {\n // convert ms timestamp to ns\n elapsed_since_start_ns: ((jsSample.timestamp + adjustForOriginChange - start) * MS_TO_NS).toFixed(0),\n stack_id: EMPTY_STACK_ID,\n thread_id: THREAD_ID_STRING,\n };\n return;\n }\n\n let stackTop: JSSelfProfileStack | undefined = input.stacks[jsSample.stackId];\n\n // Functions in top->down order (root is last)\n // We follow the stackTop.parentId trail and collect each visited frameId\n const stack: number[] = [];\n\n while (stackTop) {\n stack.push(stackTop.frameId);\n\n const frame = input.frames[stackTop.frameId];\n\n // If our frame has not been indexed yet, index it\n if (frame && profile.frames[stackTop.frameId] === undefined) {\n profile.frames[stackTop.frameId] = {\n function: frame.name,\n abs_path: typeof frame.resourceId === 'number' ? input.resources[frame.resourceId] : undefined,\n lineno: frame.line,\n colno: frame.column,\n };\n }\n\n stackTop = stackTop.parentId === undefined ? undefined : input.stacks[stackTop.parentId];\n }\n\n const sample: Profile['profile']['samples'][0] = {\n // convert ms timestamp to ns\n elapsed_since_start_ns: ((jsSample.timestamp + adjustForOriginChange - start) * MS_TO_NS).toFixed(0),\n stack_id: STACK_ID,\n thread_id: THREAD_ID_STRING,\n };\n\n profile['stacks'][STACK_ID] = stack;\n profile['samples'][i] = sample;\n STACK_ID++;\n });\n\n return profile;\n}\n\n/**\n * Adds items to envelope if they are not already present - mutates the envelope.\n * @param envelope\n */\nexport function addProfilesToEnvelope(envelope: EventEnvelope, profiles: Profile[]): Envelope {\n if (!profiles.length) {\n return envelope;\n }\n\n for (const profile of profiles) {\n envelope[1].push([{ type: 'profile' }, profile]);\n }\n return envelope;\n}\n\n/**\n * Finds transactions with profile_id context in the envelope\n * @param envelope\n * @returns\n */\nexport function findProfiledTransactionsFromEnvelope(envelope: Envelope): Event[] {\n const events: Event[] = [];\n\n forEachEnvelopeItem(envelope, (item, type) => {\n if (type !== 'transaction') {\n return;\n }\n\n for (let j = 1; j < item.length; j++) {\n const event = item[j] as Event;\n\n if (event?.contexts && event.contexts['profile'] && event.contexts['profile']['profile_id']) {\n events.push(item[j] as Event);\n }\n }\n });\n\n return events;\n}\n\n/**\n * Applies debug meta data to an event from a list of paths to resources (sourcemaps)\n */\nexport function applyDebugMetadata(resource_paths: ReadonlyArray<string>): DebugImage[] {\n const client = getClient();\n const options = client?.getOptions();\n const stackParser = options?.stackParser;\n\n if (!stackParser) {\n return [];\n }\n\n return getDebugImagesForResources(stackParser, resource_paths);\n}\n\n/**\n * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).\n */\nexport function isValidSampleRate(rate: unknown): boolean {\n // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck\n if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) {\n DEBUG_BUILD &&\n logger.warn(\n `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(\n rate,\n )} of type ${JSON.stringify(typeof rate)}.`,\n );\n return false;\n }\n\n // Boolean sample rates are always valid\n if (rate === true || rate === false) {\n return true;\n }\n\n // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false\n if (rate < 0 || rate > 1) {\n DEBUG_BUILD && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);\n return false;\n }\n return true;\n}\n\nfunction isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { profile_id: string } {\n if (profile.samples.length < 2) {\n if (DEBUG_BUILD) {\n // Log a warning if the profile has less than 2 samples so users can know why\n // they are not seeing any profiling data and we cant avoid the back and forth\n // of asking them to provide us with a dump of the profile data.\n logger.log('[Profiling] Discarding profile because it contains less than 2 samples');\n }\n return false;\n }\n\n if (!profile.frames.length) {\n if (DEBUG_BUILD) {\n logger.log('[Profiling] Discarding profile because it contains no frames');\n }\n return false;\n }\n\n return true;\n}\n\n// Keep a flag value to avoid re-initializing the profiler constructor. If it fails\n// once, it will always fail and this allows us to early return.\nlet PROFILING_CONSTRUCTOR_FAILED: boolean = false;\nexport const MAX_PROFILE_DURATION_MS = 30_000;\n\n/**\n * Check if profiler constructor is available.\n * @param maybeProfiler\n */\nfunction isJSProfilerSupported(maybeProfiler: unknown): maybeProfiler is typeof JSSelfProfilerConstructor {\n return typeof maybeProfiler === 'function';\n}\n\n/**\n * Starts the profiler and returns the profiler instance.\n */\nexport function startJSSelfProfile(): JSSelfProfiler | undefined {\n // Feature support check first\n const JSProfilerConstructor = WINDOW.Profiler;\n\n if (!isJSProfilerSupported(JSProfilerConstructor)) {\n if (DEBUG_BUILD) {\n logger.log(\n '[Profiling] Profiling is not supported by this browser, Profiler interface missing on window object.',\n );\n }\n return;\n }\n\n // From initial testing, it seems that the minimum value for sampleInterval is 10ms.\n const samplingIntervalMS = 10;\n // Start the profiler\n const maxSamples = Math.floor(MAX_PROFILE_DURATION_MS / samplingIntervalMS);\n\n // Attempt to initialize the profiler constructor, if it fails, we disable profiling for the current user session.\n // This is likely due to a missing 'Document-Policy': 'js-profiling' header. We do not want to throw an error if this happens\n // as we risk breaking the user's application, so just disable profiling and log an error.\n try {\n return new JSProfilerConstructor({ sampleInterval: samplingIntervalMS, maxBufferSize: maxSamples });\n } catch (e) {\n if (DEBUG_BUILD) {\n logger.log(\n \"[Profiling] Failed to initialize the Profiling constructor, this is likely due to a missing 'Document-Policy': 'js-profiling' header.\",\n );\n logger.log('[Profiling] Disabling profiling for current user session.');\n }\n PROFILING_CONSTRUCTOR_FAILED = true;\n }\n\n return;\n}\n\n/**\n * Determine if a profile should be profiled.\n */\nexport function shouldProfileSpan(span: Span): boolean {\n // If constructor failed once, it will always fail, so we can early return.\n if (PROFILING_CONSTRUCTOR_FAILED) {\n if (DEBUG_BUILD) {\n logger.log('[Profiling] Profiling has been disabled for the duration of the current user session.');\n }\n return false;\n }\n\n if (!span.isRecording()) {\n if (DEBUG_BUILD) {\n logger.log('[Profiling] Discarding profile because transaction was not sampled.');\n }\n return false;\n }\n\n const client = getClient();\n const options = client?.getOptions();\n if (!options) {\n DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.');\n return false;\n }\n\n // @ts-expect-error profilesSampleRate is not part of the browser options yet\n const profilesSampleRate: number | boolean | undefined = options.profilesSampleRate;\n\n // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The\n // only valid values are booleans or numbers between 0 and 1.)\n if (!isValidSampleRate(profilesSampleRate)) {\n DEBUG_BUILD && logger.warn('[Profiling] Discarding profile because of invalid sample rate.');\n return false;\n }\n\n // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped\n if (!profilesSampleRate) {\n DEBUG_BUILD &&\n logger.log(\n '[Profiling] Discarding profile because a negative sampling decision was inherited or profileSampleRate is set to 0',\n );\n return false;\n }\n\n // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is\n // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.\n const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;\n // Check if we should sample this profile\n if (!sampled) {\n DEBUG_BUILD &&\n logger.log(\n `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(\n profilesSampleRate,\n )})`,\n );\n return false;\n }\n\n return true;\n}\n\n/**\n * Creates a profiling envelope item, if the profile does not pass validation, returns null.\n * @param event\n * @returns {Profile | null}\n */\nexport function createProfilingEvent(\n profile_id: string,\n start_timestamp: number | undefined,\n profile: JSSelfProfile,\n event: ProfiledEvent,\n): Profile | null {\n if (!isValidProfile(profile)) {\n return null;\n }\n\n return createProfilePayload(profile_id, start_timestamp, profile, event);\n}\n\n// TODO (v8): We need to obtain profile ids in @sentry-internal/tracing,\n// but we don't have access to this map because importing this map would\n// cause a circular dependency. We need to resolve this in v8.\nconst PROFILE_MAP: Map<string, JSSelfProfile> = new Map();\n/**\n *\n */\nexport function getActiveProfilesCount(): number {\n return PROFILE_MAP.size;\n}\n\n/**\n * Retrieves profile from global cache and removes it.\n */\nexport function takeProfileFromGlobalCache(profile_id: string): JSSelfProfile | undefined {\n const profile = PROFILE_MAP.get(profile_id);\n if (profile) {\n PROFILE_MAP.delete(profile_id);\n }\n return profile;\n}\n/**\n * Adds profile to global cache and evicts the oldest profile if the cache is full.\n */\nexport function addProfileToGlobalCache(profile_id: string, profile: JSSelfProfile): void {\n PROFILE_MAP.set(profile_id, profile);\n\n if (PROFILE_MAP.size > 30) {\n const last: string = PROFILE_MAP.keys().next().value;\n PROFILE_MAP.delete(last);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/profiling/utils.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { DebugImage, Envelope, Event, EventEnvelope, Profile, Span, ThreadCpuProfile } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n DEFAULT_ENVIRONMENT,\n forEachEnvelopeItem,\n getClient,\n getDebugImagesForResources,\n spanToJSON,\n timestampInSeconds,\n uuid4,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport type { JSSelfProfile, JSSelfProfiler, JSSelfProfilerConstructor, JSSelfProfileStack } from './jsSelfProfiling';\n\nconst MS_TO_NS = 1e6;\n// Use 0 as main thread id which is identical to threadId in node:worker_threads\n// where main logs 0 and workers seem to log in increments of 1\nconst THREAD_ID_STRING = String(0);\nconst THREAD_NAME = 'main';\n\n// We force make this optional to be on the safe side...\nconst navigator = WINDOW.navigator as typeof WINDOW.navigator | undefined;\n\n// Machine properties (eval only once)\nlet OS_PLATFORM = '';\nlet OS_PLATFORM_VERSION = '';\nlet OS_ARCH = '';\nlet OS_BROWSER = navigator?.userAgent || '';\nlet OS_MODEL = '';\nconst OS_LOCALE = navigator?.language || navigator?.languages?.[0] || '';\n\ntype UAData = {\n platform?: string;\n architecture?: string;\n model?: string;\n platformVersion?: string;\n fullVersionList?: {\n brand: string;\n version: string;\n }[];\n};\n\ninterface UserAgentData {\n getHighEntropyValues: (keys: string[]) => Promise<UAData>;\n}\n\nfunction isUserAgentData(data: unknown): data is UserAgentData {\n return typeof data === 'object' && data !== null && 'getHighEntropyValues' in data;\n}\n\n// @ts-expect-error userAgentData is not part of the navigator interface yet\nconst userAgentData = navigator?.userAgentData;\n\nif (isUserAgentData(userAgentData)) {\n userAgentData\n .getHighEntropyValues(['architecture', 'model', 'platform', 'platformVersion', 'fullVersionList'])\n .then((ua: UAData) => {\n OS_PLATFORM = ua.platform || '';\n OS_ARCH = ua.architecture || '';\n OS_MODEL = ua.model || '';\n OS_PLATFORM_VERSION = ua.platformVersion || '';\n\n if (ua.fullVersionList?.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstUa = ua.fullVersionList[ua.fullVersionList.length - 1]!;\n OS_BROWSER = `${firstUa.brand} ${firstUa.version}`;\n }\n })\n .catch(e => void e);\n}\n\nfunction isProcessedJSSelfProfile(profile: ThreadCpuProfile | JSSelfProfile): profile is JSSelfProfile {\n return !('thread_metadata' in profile);\n}\n\n// Enriches the profile with threadId of the current thread.\n// This is done in node as we seem to not be able to get the info from C native code.\n/**\n *\n */\nexport function enrichWithThreadInformation(profile: ThreadCpuProfile | JSSelfProfile): ThreadCpuProfile {\n if (!isProcessedJSSelfProfile(profile)) {\n return profile;\n }\n\n return convertJSSelfProfileToSampledFormat(profile);\n}\n\n// Profile is marked as optional because it is deleted from the metadata\n// by the integration before the event is processed by other integrations.\nexport interface ProfiledEvent extends Event {\n sdkProcessingMetadata: {\n profile?: JSSelfProfile;\n };\n}\n\nfunction getTraceId(event: Event): string {\n const traceId: unknown = event.contexts?.trace?.trace_id;\n // Log a warning if the profile has an invalid traceId (should be uuidv4).\n // All profiles and transactions are rejected if this is the case and we want to\n // warn users that this is happening if they enable debug flag\n if (typeof traceId === 'string' && traceId.length !== 32) {\n if (DEBUG_BUILD) {\n debug.log(`[Profiling] Invalid traceId: ${traceId} on profiled event`);\n }\n }\n if (typeof traceId !== 'string') {\n return '';\n }\n\n return traceId;\n}\n/**\n * Creates a profiling event envelope from a Sentry event. If profile does not pass\n * validation, returns null.\n * @param event\n * @param dsn\n * @param metadata\n * @param tunnel\n * @returns {EventEnvelope | null}\n */\n\n/**\n * Creates a profiling event envelope from a Sentry event.\n */\nexport function createProfilePayload(\n profile_id: string,\n start_timestamp: number | undefined,\n processed_profile: JSSelfProfile,\n event: ProfiledEvent,\n): Profile {\n if (event.type !== 'transaction') {\n // createProfilingEventEnvelope should only be called for transactions,\n // we type guard this behavior with isProfiledTransactionEvent.\n throw new TypeError('Profiling events may only be attached to transactions, this should never occur.');\n }\n\n if (processed_profile === undefined || processed_profile === null) {\n throw new TypeError(\n `Cannot construct profiling event envelope without a valid profile. Got ${processed_profile} instead.`,\n );\n }\n\n const traceId = getTraceId(event);\n const enrichedThreadProfile = enrichWithThreadInformation(processed_profile);\n const transactionStartMs = start_timestamp\n ? start_timestamp\n : typeof event.start_timestamp === 'number'\n ? event.start_timestamp * 1000\n : timestampInSeconds() * 1000;\n const transactionEndMs = typeof event.timestamp === 'number' ? event.timestamp * 1000 : timestampInSeconds() * 1000;\n\n const profile: Profile = {\n event_id: profile_id,\n timestamp: new Date(transactionStartMs).toISOString(),\n platform: 'javascript',\n version: '1',\n release: event.release || '',\n environment: event.environment || DEFAULT_ENVIRONMENT,\n runtime: {\n name: 'javascript',\n version: WINDOW.navigator.userAgent,\n },\n os: {\n name: OS_PLATFORM,\n version: OS_PLATFORM_VERSION,\n build_number: OS_BROWSER,\n },\n device: {\n locale: OS_LOCALE,\n model: OS_MODEL,\n manufacturer: OS_BROWSER,\n architecture: OS_ARCH,\n is_emulator: false,\n },\n debug_meta: {\n images: applyDebugMetadata(processed_profile.resources),\n },\n profile: enrichedThreadProfile,\n transactions: [\n {\n name: event.transaction || '',\n id: event.event_id || uuid4(),\n trace_id: traceId,\n active_thread_id: THREAD_ID_STRING,\n relative_start_ns: '0',\n relative_end_ns: ((transactionEndMs - transactionStartMs) * 1e6).toFixed(0),\n },\n ],\n };\n\n return profile;\n}\n\n/**\n *\n */\nexport function isProfiledTransactionEvent(event: Event): event is ProfiledEvent {\n return !!event.sdkProcessingMetadata?.profile;\n}\n\n/*\n See packages/browser-utils/src/browser/router.ts\n*/\n/**\n *\n */\nexport function isAutomatedPageLoadSpan(span: Span): boolean {\n return spanToJSON(span).op === 'pageload';\n}\n\n/**\n * Converts a JSSelfProfile to a our sampled format.\n * Does not currently perform stack indexing.\n */\nexport function convertJSSelfProfileToSampledFormat(input: JSSelfProfile): Profile['profile'] {\n let EMPTY_STACK_ID: undefined | number = undefined;\n let STACK_ID = 0;\n\n // Initialize the profile that we will fill with data\n const profile: Profile['profile'] = {\n samples: [],\n stacks: [],\n frames: [],\n thread_metadata: {\n [THREAD_ID_STRING]: { name: THREAD_NAME },\n },\n };\n\n const firstSample = input.samples[0];\n if (!firstSample) {\n return profile;\n }\n\n // We assert samples.length > 0 above and timestamp should always be present\n const start = firstSample.timestamp;\n // The JS SDK might change it's time origin based on some heuristic (see See packages/utils/src/time.ts)\n // when that happens, we need to ensure we are correcting the profile timings so the two timelines stay in sync.\n // Since JS self profiling time origin is always initialized to performance.timeOrigin, we need to adjust for\n // the drift between the SDK selected value and our profile time origin.\n const perfOrigin = browserPerformanceTimeOrigin();\n const origin = typeof performance.timeOrigin === 'number' ? performance.timeOrigin : perfOrigin || 0;\n const adjustForOriginChange = origin - (perfOrigin || origin);\n\n input.samples.forEach((jsSample, i) => {\n // If sample has no stack, add an empty sample\n if (jsSample.stackId === undefined) {\n if (EMPTY_STACK_ID === undefined) {\n EMPTY_STACK_ID = STACK_ID;\n profile.stacks[EMPTY_STACK_ID] = [];\n STACK_ID++;\n }\n\n profile['samples'][i] = {\n // convert ms timestamp to ns\n elapsed_since_start_ns: ((jsSample.timestamp + adjustForOriginChange - start) * MS_TO_NS).toFixed(0),\n stack_id: EMPTY_STACK_ID,\n thread_id: THREAD_ID_STRING,\n };\n return;\n }\n\n let stackTop: JSSelfProfileStack | undefined = input.stacks[jsSample.stackId];\n\n // Functions in top->down order (root is last)\n // We follow the stackTop.parentId trail and collect each visited frameId\n const stack: number[] = [];\n\n while (stackTop) {\n stack.push(stackTop.frameId);\n\n const frame = input.frames[stackTop.frameId];\n\n // If our frame has not been indexed yet, index it\n if (frame && profile.frames[stackTop.frameId] === undefined) {\n profile.frames[stackTop.frameId] = {\n function: frame.name,\n abs_path: typeof frame.resourceId === 'number' ? input.resources[frame.resourceId] : undefined,\n lineno: frame.line,\n colno: frame.column,\n };\n }\n\n stackTop = stackTop.parentId === undefined ? undefined : input.stacks[stackTop.parentId];\n }\n\n const sample: Profile['profile']['samples'][0] = {\n // convert ms timestamp to ns\n elapsed_since_start_ns: ((jsSample.timestamp + adjustForOriginChange - start) * MS_TO_NS).toFixed(0),\n stack_id: STACK_ID,\n thread_id: THREAD_ID_STRING,\n };\n\n profile['stacks'][STACK_ID] = stack;\n profile['samples'][i] = sample;\n STACK_ID++;\n });\n\n return profile;\n}\n\n/**\n * Adds items to envelope if they are not already present - mutates the envelope.\n * @param envelope\n */\nexport function addProfilesToEnvelope(envelope: EventEnvelope, profiles: Profile[]): Envelope {\n if (!profiles.length) {\n return envelope;\n }\n\n for (const profile of profiles) {\n envelope[1].push([{ type: 'profile' }, profile]);\n }\n return envelope;\n}\n\n/**\n * Finds transactions with profile_id context in the envelope\n * @param envelope\n * @returns\n */\nexport function findProfiledTransactionsFromEnvelope(envelope: Envelope): Event[] {\n const events: Event[] = [];\n\n forEachEnvelopeItem(envelope, (item, type) => {\n if (type !== 'transaction') {\n return;\n }\n\n for (let j = 1; j < item.length; j++) {\n const event = item[j] as Event;\n\n if (event?.contexts?.profile?.profile_id) {\n events.push(item[j] as Event);\n }\n }\n });\n\n return events;\n}\n\n/**\n * Applies debug meta data to an event from a list of paths to resources (sourcemaps)\n */\nexport function applyDebugMetadata(resource_paths: ReadonlyArray<string>): DebugImage[] {\n const client = getClient();\n const options = client?.getOptions();\n const stackParser = options?.stackParser;\n\n if (!stackParser) {\n return [];\n }\n\n return getDebugImagesForResources(stackParser, resource_paths);\n}\n\n/**\n * Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).\n */\nexport function isValidSampleRate(rate: unknown): boolean {\n // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck\n if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) {\n DEBUG_BUILD &&\n debug.warn(\n `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(\n rate,\n )} of type ${JSON.stringify(typeof rate)}.`,\n );\n return false;\n }\n\n // Boolean sample rates are always valid\n if (rate === true || rate === false) {\n return true;\n }\n\n // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false\n if (rate < 0 || rate > 1) {\n DEBUG_BUILD && debug.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`);\n return false;\n }\n return true;\n}\n\nfunction isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { profile_id: string } {\n if (profile.samples.length < 2) {\n if (DEBUG_BUILD) {\n // Log a warning if the profile has less than 2 samples so users can know why\n // they are not seeing any profiling data and we cant avoid the back and forth\n // of asking them to provide us with a dump of the profile data.\n debug.log('[Profiling] Discarding profile because it contains less than 2 samples');\n }\n return false;\n }\n\n if (!profile.frames.length) {\n if (DEBUG_BUILD) {\n debug.log('[Profiling] Discarding profile because it contains no frames');\n }\n return false;\n }\n\n return true;\n}\n\n// Keep a flag value to avoid re-initializing the profiler constructor. If it fails\n// once, it will always fail and this allows us to early return.\nlet PROFILING_CONSTRUCTOR_FAILED: boolean = false;\nexport const MAX_PROFILE_DURATION_MS = 30_000;\n\n/**\n * Check if profiler constructor is available.\n * @param maybeProfiler\n */\nfunction isJSProfilerSupported(maybeProfiler: unknown): maybeProfiler is typeof JSSelfProfilerConstructor {\n return typeof maybeProfiler === 'function';\n}\n\n/**\n * Starts the profiler and returns the profiler instance.\n */\nexport function startJSSelfProfile(): JSSelfProfiler | undefined {\n // Feature support check first\n const JSProfilerConstructor = WINDOW.Profiler;\n\n if (!isJSProfilerSupported(JSProfilerConstructor)) {\n if (DEBUG_BUILD) {\n debug.log('[Profiling] Profiling is not supported by this browser, Profiler interface missing on window object.');\n }\n return;\n }\n\n // From initial testing, it seems that the minimum value for sampleInterval is 10ms.\n const samplingIntervalMS = 10;\n // Start the profiler\n const maxSamples = Math.floor(MAX_PROFILE_DURATION_MS / samplingIntervalMS);\n\n // Attempt to initialize the profiler constructor, if it fails, we disable profiling for the current user session.\n // This is likely due to a missing 'Document-Policy': 'js-profiling' header. We do not want to throw an error if this happens\n // as we risk breaking the user's application, so just disable profiling and log an error.\n try {\n return new JSProfilerConstructor({ sampleInterval: samplingIntervalMS, maxBufferSize: maxSamples });\n } catch (e) {\n if (DEBUG_BUILD) {\n debug.log(\n \"[Profiling] Failed to initialize the Profiling constructor, this is likely due to a missing 'Document-Policy': 'js-profiling' header.\",\n );\n debug.log('[Profiling] Disabling profiling for current user session.');\n }\n PROFILING_CONSTRUCTOR_FAILED = true;\n }\n\n return;\n}\n\n/**\n * Determine if a profile should be profiled.\n */\nexport function shouldProfileSpan(span: Span): boolean {\n // If constructor failed once, it will always fail, so we can early return.\n if (PROFILING_CONSTRUCTOR_FAILED) {\n if (DEBUG_BUILD) {\n debug.log('[Profiling] Profiling has been disabled for the duration of the current user session.');\n }\n return false;\n }\n\n if (!span.isRecording()) {\n if (DEBUG_BUILD) {\n debug.log('[Profiling] Discarding profile because transaction was not sampled.');\n }\n return false;\n }\n\n const client = getClient();\n const options = client?.getOptions();\n if (!options) {\n DEBUG_BUILD && debug.log('[Profiling] Profiling disabled, no options found.');\n return false;\n }\n\n // @ts-expect-error profilesSampleRate is not part of the browser options yet\n const profilesSampleRate: number | boolean | undefined = options.profilesSampleRate;\n\n // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The\n // only valid values are booleans or numbers between 0 and 1.)\n if (!isValidSampleRate(profilesSampleRate)) {\n DEBUG_BUILD && debug.warn('[Profiling] Discarding profile because of invalid sample rate.');\n return false;\n }\n\n // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped\n if (!profilesSampleRate) {\n DEBUG_BUILD &&\n debug.log(\n '[Profiling] Discarding profile because a negative sampling decision was inherited or profileSampleRate is set to 0',\n );\n return false;\n }\n\n // Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is\n // a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.\n const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate;\n // Check if we should sample this profile\n if (!sampled) {\n DEBUG_BUILD &&\n debug.log(\n `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number(\n profilesSampleRate,\n )})`,\n );\n return false;\n }\n\n return true;\n}\n\n/**\n * Creates a profiling envelope item, if the profile does not pass validation, returns null.\n * @param event\n * @returns {Profile | null}\n */\nexport function createProfilingEvent(\n profile_id: string,\n start_timestamp: number | undefined,\n profile: JSSelfProfile,\n event: ProfiledEvent,\n): Profile | null {\n if (!isValidProfile(profile)) {\n return null;\n }\n\n return createProfilePayload(profile_id, start_timestamp, profile, event);\n}\n\n// TODO (v8): We need to obtain profile ids in @sentry-internal/tracing,\n// but we don't have access to this map because importing this map would\n// cause a circular dependency. We need to resolve this in v8.\nconst PROFILE_MAP: Map<string, JSSelfProfile> = new Map();\n/**\n *\n */\nexport function getActiveProfilesCount(): number {\n return PROFILE_MAP.size;\n}\n\n/**\n * Retrieves profile from global cache and removes it.\n */\nexport function takeProfileFromGlobalCache(profile_id: string): JSSelfProfile | undefined {\n const profile = PROFILE_MAP.get(profile_id);\n if (profile) {\n PROFILE_MAP.delete(profile_id);\n }\n return profile;\n}\n/**\n * Adds profile to global cache and evicts the oldest profile if the cache is full.\n */\nexport function addProfileToGlobalCache(profile_id: string, profile: JSSelfProfile): void {\n PROFILE_MAP.set(profile_id, profile);\n\n if (PROFILE_MAP.size > 30) {\n const last: string = PROFILE_MAP.keys().next().value;\n PROFILE_MAP.delete(last);\n }\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { logger, getCurrentScope, getClient, lastEventId, getReportDialogEndpoint } from '@sentry/core';
1
+ import { debug, getCurrentScope, getClient, lastEventId, getReportDialogEndpoint } from '@sentry/core';
2
2
  import { DEBUG_BUILD } from './debug-build.js';
3
3
  import { WINDOW } from './helpers.js';
4
4
 
@@ -13,7 +13,7 @@ function showReportDialog(options = {}) {
13
13
 
14
14
  // doesn't work without a document (React Native)
15
15
  if (!injectionPoint) {
16
- DEBUG_BUILD && logger.error('[showReportDialog] Global document not defined');
16
+ DEBUG_BUILD && debug.error('[showReportDialog] Global document not defined');
17
17
  return;
18
18
  }
19
19
 
@@ -22,7 +22,7 @@ function showReportDialog(options = {}) {
22
22
  const dsn = client?.getDsn();
23
23
 
24
24
  if (!dsn) {
25
- DEBUG_BUILD && logger.error('[showReportDialog] DSN not configured');
25
+ DEBUG_BUILD && debug.error('[showReportDialog] DSN not configured');
26
26
  return;
27
27
  }
28
28
 
@@ -1 +1 @@
1
- {"version":3,"file":"report-dialog.js","sources":["../../../src/report-dialog.ts"],"sourcesContent":["import type { ReportDialogOptions } from '@sentry/core';\nimport { getClient, getCurrentScope, getReportDialogEndpoint, lastEventId, logger } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { WINDOW } from './helpers';\n\n/**\n * Present the user with a report dialog.\n *\n * @param options Everything is optional, we try to fetch all info need from the current scope.\n */\nexport function showReportDialog(options: ReportDialogOptions = {}): void {\n const optionalDocument = WINDOW.document as Document | undefined;\n const injectionPoint = optionalDocument?.head || optionalDocument?.body;\n\n // doesn't work without a document (React Native)\n if (!injectionPoint) {\n DEBUG_BUILD && logger.error('[showReportDialog] Global document not defined');\n return;\n }\n\n const scope = getCurrentScope();\n const client = getClient();\n const dsn = client?.getDsn();\n\n if (!dsn) {\n DEBUG_BUILD && logger.error('[showReportDialog] DSN not configured');\n return;\n }\n\n const mergedOptions = {\n ...options,\n user: {\n ...scope.getUser(),\n ...options.user,\n },\n eventId: options.eventId || lastEventId(),\n };\n\n const script = WINDOW.document.createElement('script');\n script.async = true;\n script.crossOrigin = 'anonymous';\n script.src = getReportDialogEndpoint(dsn, mergedOptions);\n\n const { onLoad, onClose } = mergedOptions;\n\n if (onLoad) {\n script.onload = onLoad;\n }\n\n if (onClose) {\n const reportDialogClosedMessageHandler = (event: MessageEvent): void => {\n if (event.data === '__sentry_reportdialog_closed__') {\n try {\n onClose();\n } finally {\n WINDOW.removeEventListener('message', reportDialogClosedMessageHandler);\n }\n }\n };\n WINDOW.addEventListener('message', reportDialogClosedMessageHandler);\n }\n\n injectionPoint.appendChild(script);\n}\n"],"names":[],"mappings":";;;;AAKA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,OAAO,GAAwB,EAAE,EAAQ;AAC1E,EAAE,MAAM,gBAAA,GAAmB,MAAM,CAAC,QAAA;AAClC,EAAE,MAAM,iBAAiB,gBAAgB,EAAE,IAAA,IAAQ,gBAAgB,EAAE,IAAI;;AAEzE;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,eAAe,MAAM,CAAC,KAAK,CAAC,gDAAgD,CAAC;AACjF,IAAI;AACJ;;AAEA,EAAE,MAAM,KAAA,GAAQ,eAAe,EAAE;AACjC,EAAE,MAAM,MAAA,GAAS,SAAS,EAAE;AAC5B,EAAE,MAAM,GAAA,GAAM,MAAM,EAAE,MAAM,EAAE;;AAE9B,EAAE,IAAI,CAAC,GAAG,EAAE;AACZ,IAAI,eAAe,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC;AACxE,IAAI;AACJ;;AAEA,EAAE,MAAM,gBAAgB;AACxB,IAAI,GAAG,OAAO;AACd,IAAI,IAAI,EAAE;AACV,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE;AACxB,MAAM,GAAG,OAAO,CAAC,IAAI;AACrB,KAAK;AACL,IAAI,OAAO,EAAE,OAAO,CAAC,WAAW,WAAW,EAAE;AAC7C,GAAG;;AAEH,EAAE,MAAM,MAAA,GAAS,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AACxD,EAAE,MAAM,CAAC,KAAA,GAAQ,IAAI;AACrB,EAAE,MAAM,CAAC,WAAA,GAAc,WAAW;AAClC,EAAE,MAAM,CAAC,GAAA,GAAM,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC;;AAE1D,EAAE,MAAM,EAAE,MAAM,EAAE,OAAA,EAAQ,GAAI,aAAa;;AAE3C,EAAE,IAAI,MAAM,EAAE;AACd,IAAI,MAAM,CAAC,MAAA,GAAS,MAAM;AAC1B;;AAEA,EAAE,IAAI,OAAO,EAAE;AACf,IAAI,MAAM,gCAAA,GAAmC,CAAC,KAAK,KAAyB;AAC5E,MAAM,IAAI,KAAK,CAAC,IAAA,KAAS,gCAAgC,EAAE;AAC3D,QAAQ,IAAI;AACZ,UAAU,OAAO,EAAE;AACnB,kBAAkB;AAClB,UAAU,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,gCAAgC,CAAC;AACjF;AACA;AACA,KAAK;AACL,IAAI,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,gCAAgC,CAAC;AACxE;;AAEA,EAAE,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC;AACpC;;;;"}
1
+ {"version":3,"file":"report-dialog.js","sources":["../../../src/report-dialog.ts"],"sourcesContent":["import type { ReportDialogOptions } from '@sentry/core';\nimport { debug, getClient, getCurrentScope, getReportDialogEndpoint, lastEventId } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { WINDOW } from './helpers';\n\n/**\n * Present the user with a report dialog.\n *\n * @param options Everything is optional, we try to fetch all info need from the current scope.\n */\nexport function showReportDialog(options: ReportDialogOptions = {}): void {\n const optionalDocument = WINDOW.document as Document | undefined;\n const injectionPoint = optionalDocument?.head || optionalDocument?.body;\n\n // doesn't work without a document (React Native)\n if (!injectionPoint) {\n DEBUG_BUILD && debug.error('[showReportDialog] Global document not defined');\n return;\n }\n\n const scope = getCurrentScope();\n const client = getClient();\n const dsn = client?.getDsn();\n\n if (!dsn) {\n DEBUG_BUILD && debug.error('[showReportDialog] DSN not configured');\n return;\n }\n\n const mergedOptions = {\n ...options,\n user: {\n ...scope.getUser(),\n ...options.user,\n },\n eventId: options.eventId || lastEventId(),\n };\n\n const script = WINDOW.document.createElement('script');\n script.async = true;\n script.crossOrigin = 'anonymous';\n script.src = getReportDialogEndpoint(dsn, mergedOptions);\n\n const { onLoad, onClose } = mergedOptions;\n\n if (onLoad) {\n script.onload = onLoad;\n }\n\n if (onClose) {\n const reportDialogClosedMessageHandler = (event: MessageEvent): void => {\n if (event.data === '__sentry_reportdialog_closed__') {\n try {\n onClose();\n } finally {\n WINDOW.removeEventListener('message', reportDialogClosedMessageHandler);\n }\n }\n };\n WINDOW.addEventListener('message', reportDialogClosedMessageHandler);\n }\n\n injectionPoint.appendChild(script);\n}\n"],"names":[],"mappings":";;;;AAKA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,OAAO,GAAwB,EAAE,EAAQ;AAC1E,EAAE,MAAM,gBAAA,GAAmB,MAAM,CAAC,QAAA;AAClC,EAAE,MAAM,iBAAiB,gBAAgB,EAAE,IAAA,IAAQ,gBAAgB,EAAE,IAAI;;AAEzE;AACA,EAAE,IAAI,CAAC,cAAc,EAAE;AACvB,IAAI,eAAe,KAAK,CAAC,KAAK,CAAC,gDAAgD,CAAC;AAChF,IAAI;AACJ;;AAEA,EAAE,MAAM,KAAA,GAAQ,eAAe,EAAE;AACjC,EAAE,MAAM,MAAA,GAAS,SAAS,EAAE;AAC5B,EAAE,MAAM,GAAA,GAAM,MAAM,EAAE,MAAM,EAAE;;AAE9B,EAAE,IAAI,CAAC,GAAG,EAAE;AACZ,IAAI,eAAe,KAAK,CAAC,KAAK,CAAC,uCAAuC,CAAC;AACvE,IAAI;AACJ;;AAEA,EAAE,MAAM,gBAAgB;AACxB,IAAI,GAAG,OAAO;AACd,IAAI,IAAI,EAAE;AACV,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE;AACxB,MAAM,GAAG,OAAO,CAAC,IAAI;AACrB,KAAK;AACL,IAAI,OAAO,EAAE,OAAO,CAAC,WAAW,WAAW,EAAE;AAC7C,GAAG;;AAEH,EAAE,MAAM,MAAA,GAAS,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC;AACxD,EAAE,MAAM,CAAC,KAAA,GAAQ,IAAI;AACrB,EAAE,MAAM,CAAC,WAAA,GAAc,WAAW;AAClC,EAAE,MAAM,CAAC,GAAA,GAAM,uBAAuB,CAAC,GAAG,EAAE,aAAa,CAAC;;AAE1D,EAAE,MAAM,EAAE,MAAM,EAAE,OAAA,EAAQ,GAAI,aAAa;;AAE3C,EAAE,IAAI,MAAM,EAAE;AACd,IAAI,MAAM,CAAC,MAAA,GAAS,MAAM;AAC1B;;AAEA,EAAE,IAAI,OAAO,EAAE;AACf,IAAI,MAAM,gCAAA,GAAmC,CAAC,KAAK,KAAyB;AAC5E,MAAM,IAAI,KAAK,CAAC,IAAA,KAAS,gCAAgC,EAAE;AAC3D,QAAQ,IAAI;AACZ,UAAU,OAAO,EAAE;AACnB,kBAAkB;AAClB,UAAU,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE,gCAAgC,CAAC;AACjF;AACA;AACA,KAAK;AACL,IAAI,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,gCAAgC,CAAC;AACxE;;AAEA,EAAE,cAAc,CAAC,WAAW,CAAC,MAAM,CAAC;AACpC;;;;"}
@@ -1,4 +1,4 @@
1
- import { getActiveSpan, getRootSpan, spanToJSON, logger, SPAN_STATUS_ERROR } from '@sentry/core';
1
+ import { getActiveSpan, getRootSpan, spanToJSON, debug, SPAN_STATUS_ERROR } from '@sentry/core';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
3
  import { WINDOW } from '../helpers.js';
4
4
 
@@ -22,7 +22,7 @@ function registerBackgroundTabDetection() {
22
22
  const { op, status } = spanToJSON(rootSpan);
23
23
 
24
24
  if (DEBUG_BUILD) {
25
- logger.log(`[Tracing] Transaction: ${cancelledStatus} -> since tab moved to the background, op: ${op}`);
25
+ debug.log(`[Tracing] Transaction: ${cancelledStatus} -> since tab moved to the background, op: ${op}`);
26
26
  }
27
27
 
28
28
  // We should not set status if it is already set, this prevent important statuses like
@@ -36,7 +36,7 @@ function registerBackgroundTabDetection() {
36
36
  }
37
37
  });
38
38
  } else {
39
- DEBUG_BUILD && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document');
39
+ DEBUG_BUILD && debug.warn('[Tracing] Could not set up background tab detection due to lack of global document');
40
40
  }
41
41
  }
42
42
 
@@ -1 +1 @@
1
- {"version":3,"file":"backgroundtab.js","sources":["../../../../src/tracing/backgroundtab.ts"],"sourcesContent":["import { getActiveSpan, getRootSpan, logger, SPAN_STATUS_ERROR, spanToJSON } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\n/**\n * Add a listener that cancels and finishes a transaction when the global\n * document is hidden.\n */\nexport function registerBackgroundTabDetection(): void {\n if (WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return;\n }\n\n const rootSpan = getRootSpan(activeSpan);\n\n if (WINDOW.document.hidden && rootSpan) {\n const cancelledStatus = 'cancelled';\n\n const { op, status } = spanToJSON(rootSpan);\n\n if (DEBUG_BUILD) {\n logger.log(`[Tracing] Transaction: ${cancelledStatus} -> since tab moved to the background, op: ${op}`);\n }\n\n // We should not set status if it is already set, this prevent important statuses like\n // error or data loss from being overwritten on transaction.\n if (!status) {\n rootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: cancelledStatus });\n }\n\n rootSpan.setAttribute('sentry.cancellation_reason', 'document.hidden');\n rootSpan.end();\n }\n });\n } else {\n DEBUG_BUILD && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document');\n }\n}\n"],"names":[],"mappings":";;;;AAIA;AACA;AACA;AACA;AACO,SAAS,8BAA8B,GAAS;AACvD,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE;AACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AAC/D,MAAM,MAAM,UAAA,GAAa,aAAa,EAAE;AACxC,MAAM,IAAI,CAAC,UAAU,EAAE;AACvB,QAAQ;AACR;;AAEA,MAAM,MAAM,QAAA,GAAW,WAAW,CAAC,UAAU,CAAC;;AAE9C,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAA,IAAU,QAAQ,EAAE;AAC9C,QAAQ,MAAM,eAAA,GAAkB,WAAW;;AAE3C,QAAQ,MAAM,EAAE,EAAE,EAAE,MAAA,KAAW,UAAU,CAAC,QAAQ,CAAC;;AAEnD,QAAQ,IAAI,WAAW,EAAE;AACzB,UAAU,MAAM,CAAC,GAAG,CAAC,CAAC,uBAAuB,EAAE,eAAe,CAAC,2CAA2C,EAAE,EAAE,CAAC,CAAA,CAAA;AACA;;AAEA;AACA;AACA,QAAA,IAAA,CAAA,MAAA,EAAA;AACA,UAAA,QAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,eAAA,EAAA,CAAA;AACA;;AAEA,QAAA,QAAA,CAAA,YAAA,CAAA,4BAAA,EAAA,iBAAA,CAAA;AACA,QAAA,QAAA,CAAA,GAAA,EAAA;AACA;AACA,KAAA,CAAA;AACA,GAAA,MAAA;AACA,IAAA,WAAA,IAAA,MAAA,CAAA,IAAA,CAAA,oFAAA,CAAA;AACA;AACA;;;;"}
1
+ {"version":3,"file":"backgroundtab.js","sources":["../../../../src/tracing/backgroundtab.ts"],"sourcesContent":["import { debug, getActiveSpan, getRootSpan, SPAN_STATUS_ERROR, spanToJSON } from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\n\n/**\n * Add a listener that cancels and finishes a transaction when the global\n * document is hidden.\n */\nexport function registerBackgroundTabDetection(): void {\n if (WINDOW.document) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n const activeSpan = getActiveSpan();\n if (!activeSpan) {\n return;\n }\n\n const rootSpan = getRootSpan(activeSpan);\n\n if (WINDOW.document.hidden && rootSpan) {\n const cancelledStatus = 'cancelled';\n\n const { op, status } = spanToJSON(rootSpan);\n\n if (DEBUG_BUILD) {\n debug.log(`[Tracing] Transaction: ${cancelledStatus} -> since tab moved to the background, op: ${op}`);\n }\n\n // We should not set status if it is already set, this prevent important statuses like\n // error or data loss from being overwritten on transaction.\n if (!status) {\n rootSpan.setStatus({ code: SPAN_STATUS_ERROR, message: cancelledStatus });\n }\n\n rootSpan.setAttribute('sentry.cancellation_reason', 'document.hidden');\n rootSpan.end();\n }\n });\n } else {\n DEBUG_BUILD && debug.warn('[Tracing] Could not set up background tab detection due to lack of global document');\n }\n}\n"],"names":[],"mappings":";;;;AAIA;AACA;AACA;AACA;AACO,SAAS,8BAA8B,GAAS;AACvD,EAAE,IAAI,MAAM,CAAC,QAAQ,EAAE;AACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AAC/D,MAAM,MAAM,UAAA,GAAa,aAAa,EAAE;AACxC,MAAM,IAAI,CAAC,UAAU,EAAE;AACvB,QAAQ;AACR;;AAEA,MAAM,MAAM,QAAA,GAAW,WAAW,CAAC,UAAU,CAAC;;AAE9C,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAA,IAAU,QAAQ,EAAE;AAC9C,QAAQ,MAAM,eAAA,GAAkB,WAAW;;AAE3C,QAAQ,MAAM,EAAE,EAAE,EAAE,MAAA,KAAW,UAAU,CAAC,QAAQ,CAAC;;AAEnD,QAAQ,IAAI,WAAW,EAAE;AACzB,UAAU,KAAK,CAAC,GAAG,CAAC,CAAC,uBAAuB,EAAE,eAAe,CAAC,2CAA2C,EAAE,EAAE,CAAC,CAAA,CAAA;AACA;;AAEA;AACA;AACA,QAAA,IAAA,CAAA,MAAA,EAAA;AACA,UAAA,QAAA,CAAA,SAAA,CAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,eAAA,EAAA,CAAA;AACA;;AAEA,QAAA,QAAA,CAAA,YAAA,CAAA,4BAAA,EAAA,iBAAA,CAAA;AACA,QAAA,QAAA,CAAA,GAAA,EAAA;AACA;AACA,KAAA,CAAA;AACA,GAAA,MAAA;AACA,IAAA,WAAA,IAAA,KAAA,CAAA,IAAA,CAAA,oFAAA,CAAA;AACA;AACA;;;;"}
@@ -1,4 +1,4 @@
1
- import { TRACING_DEFAULTS, getLocationHref, browserPerformanceTimeOrigin, parseStringToURLObject, registerSpanErrorInstrumentation, GLOBAL_OBJ, getClient, logger, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, spanToJSON, dateTimestampInSeconds, timestampInSeconds, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startInactiveSpan, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
1
+ import { TRACING_DEFAULTS, getLocationHref, browserPerformanceTimeOrigin, parseStringToURLObject, registerSpanErrorInstrumentation, GLOBAL_OBJ, getClient, debug, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, spanToJSON, dateTimestampInSeconds, timestampInSeconds, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startInactiveSpan, startIdleSpan, getDynamicSamplingContextFromSpan, spanIsSampled, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
2
2
  import { addHistoryInstrumentationHandler, registerInpInteractionListener, startTrackingWebVitals, startTrackingINP, startTrackingElementTiming, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingInteractions, addPerformanceEntries } from '@sentry-internal/browser-utils';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { WINDOW, getHttpRequestData } from '../helpers.js';
@@ -205,7 +205,7 @@ const browserTracingIntegration = ((_options = {}) => {
205
205
  const activeSpan = getActiveIdleSpan(client);
206
206
 
207
207
  if (activeSpan && !spanToJSON(activeSpan).timestamp) {
208
- DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);
208
+ DEBUG_BUILD && debug.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);
209
209
  // If there's an open active span, we need to finish it before creating an new one.
210
210
  activeSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'cancelled');
211
211
  activeSpan.end();
@@ -219,7 +219,7 @@ const browserTracingIntegration = ((_options = {}) => {
219
219
 
220
220
  if (navigationOptions?.isRedirect) {
221
221
  DEBUG_BUILD &&
222
- logger.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');
222
+ debug.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');
223
223
  _createRouteSpan(
224
224
  client,
225
225
  {
@@ -446,7 +446,7 @@ function registerInteractionListener(
446
446
  const currentRootSpanOp = spanToJSON(activeIdleSpan).op;
447
447
  if (['navigation', 'pageload'].includes(currentRootSpanOp )) {
448
448
  DEBUG_BUILD &&
449
- logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);
449
+ debug.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);
450
450
  return undefined;
451
451
  }
452
452
  }
@@ -458,7 +458,7 @@ function registerInteractionListener(
458
458
  }
459
459
 
460
460
  if (!latestRoute.name) {
461
- DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);
461
+ DEBUG_BUILD && debug.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);
462
462
  return undefined;
463
463
  }
464
464
 
@@ -1 +1 @@
1
- {"version":3,"file":"browserTracingIntegration.js","sources":["../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, IntegrationFn, Span, StartSpanOptions, TransactionSource, WebFetchHeaders } from '@sentry/core';\nimport {\n addNonEnumerableProperty,\n browserPerformanceTimeOrigin,\n dateTimestampInSeconds,\n generateTraceId,\n getClient,\n getCurrentScope,\n getDynamicSamplingContextFromSpan,\n getIsolationScope,\n getLocationHref,\n GLOBAL_OBJ,\n logger,\n parseStringToURLObject,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanIsSampled,\n spanToJSON,\n startIdleSpan,\n startInactiveSpan,\n timestampInSeconds,\n TRACING_DEFAULTS,\n} from '@sentry/core';\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n registerInpInteractionListener,\n startTrackingElementTiming,\n startTrackingINP,\n startTrackingInteractions,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n startTrackingWebVitals,\n} from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { linkTraces } from './linkedTraces';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\ninterface RouteInfo {\n name: string | undefined;\n source: TransactionSource | undefined;\n}\n\n/** Options for Browser Tracing integration */\nexport interface BrowserTracingOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * Default: 1000 (ms)\n */\n idleTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 30000 (ms)\n */\n finalTimeout: number;\n\n /**\n The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 15000 (ms)\n */\n childSpanTimeout: number;\n\n /**\n * If a span should be created on page load.\n * If this is set to `false`, this integration will not start the default page load span.\n * Default: true\n */\n instrumentPageLoad: boolean;\n\n /**\n * If a span should be created on navigation (history change).\n * If this is set to `false`, this integration will not start the default navigation spans.\n * Default: true\n */\n instrumentNavigation: boolean;\n\n /**\n * Flag spans where tabs moved to background with \"cancelled\". Browser background tab timing is\n * not suited towards doing precise measurements of operations. By default, we recommend that this option\n * be enabled as background transactions can mess up your statistics in nondeterministic ways.\n *\n * Default: true\n */\n markBackgroundSpan: boolean;\n\n /**\n * If true, Sentry will capture long tasks and add them to the corresponding transaction.\n *\n * Default: true\n */\n enableLongTask: boolean;\n\n /**\n * If true, Sentry will capture long animation frames and add them to the corresponding transaction.\n *\n * Default: false\n */\n enableLongAnimationFrame: boolean;\n\n /**\n * If true, Sentry will capture first input delay and add it to the corresponding transaction.\n *\n * Default: true\n */\n enableInp: boolean;\n\n /**\n * If true, Sentry will capture [element timing](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceElementTiming)\n * information and add it to the corresponding transaction.\n *\n * Default: true\n */\n enableElementTiming: boolean;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Default: false\n */\n trackFetchStreamPerformance: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resouce.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Spans created from the following browser Performance APIs,\n *\n * - [`performance.mark(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark)\n * - [`performance.measure(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure)\n *\n * will not be emitted if their names match strings in this array.\n *\n * This is useful, if you come across `mark` or `measure` spans in your Sentry traces\n * that you want to ignore. For example, sometimes, browser extensions or libraries\n * emit these entries on their own, which might not be relevant to your application.\n *\n * * @example\n * ```ts\n * Sentry.init({\n * integrations: [\n * Sentry.browserTracingIntegration({\n * ignorePerformanceApiSpans: ['myMeasurement', /myMark/],\n * }),\n * ],\n * });\n *\n * // no spans will be created for these:\n * performance.mark('myMark');\n * performance.measure('myMeasurement');\n *\n * // spans will be created for these:\n * performance.mark('authenticated');\n * performance.measure('input-duration', ...);\n * ```\n *\n * Default: [] - By default, all `mark` and `measure` entries are sent as spans.\n */\n ignorePerformanceApiSpans: Array<string | RegExp>;\n\n /**\n * By default, the SDK will try to detect redirects and avoid creating separate spans for them.\n * If you want to opt-out of this behavior, you can set this option to `false`.\n *\n * Default: true\n */\n detectRedirects: boolean;\n\n /**\n * Link the currently started trace to a previous trace (e.g. a prior pageload, navigation or\n * manually started span). When enabled, this option will allow you to navigate between traces\n * in the Sentry UI.\n *\n * You can set this option to the following values:\n *\n * - `'in-memory'`: The previous trace data will be stored in memory.\n * This is useful for single-page applications and enabled by default.\n *\n * - `'session-storage'`: The previous trace data will be stored in the `sessionStorage`.\n * This is useful for multi-page applications or static sites but it means that the\n * Sentry SDK writes to the browser's `sessionStorage`.\n *\n * - `'off'`: The previous trace data will not be stored or linked.\n *\n * You can also use {@link BrowserTracingOptions.consistentTraceSampling} to get\n * consistent trace sampling of subsequent traces. Otherwise, by default, your\n * `tracesSampleRate` or `tracesSampler` config significantly influences how often\n * traces will be linked.\n *\n * @default 'in-memory' - see explanation above\n */\n linkPreviousTrace: 'in-memory' | 'session-storage' | 'off';\n\n /**\n * If true, Sentry will consistently sample subsequent traces based on the\n * sampling decision of the initial trace. For example, if the initial page\n * load trace was sampled positively, all subsequent traces (e.g. navigations)\n * are also sampled positively. In case the initial trace was sampled negatively,\n * all subsequent traces are also sampled negatively.\n *\n * This option allows you to get consistent, linked traces within a user journey\n * while maintaining an overall quota based on your trace sampling settings.\n *\n * This option is only effective if {@link BrowserTracingOptions.linkPreviousTrace}\n * is enabled (i.e. not set to `'off'`).\n *\n * @default `false` - this is an opt-in feature.\n */\n consistentTraceSampling: boolean;\n\n /**\n * _experiments allows the user to send options to define how this integration works.\n *\n * Default: undefined\n */\n _experiments: Partial<{\n enableInteractions: boolean;\n enableStandaloneClsSpans: boolean;\n enableStandaloneLcpSpans: boolean;\n }>;\n\n /**\n * A callback which is called before a span for a pageload or navigation is started.\n * It receives the options passed to `startSpan`, and expects to return an updated options object.\n */\n beforeStartSpan?: (options: StartSpanOptions) => StartSpanOptions;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * This callback is invoked directly after a span is started for an outgoing fetch or XHR request.\n * You can use it to annotate the span with additional data or attributes, for example by setting\n * attributes based on the passed request headers.\n */\n onRequestSpanStart?(span: Span, requestInformation: { headers?: WebFetchHeaders }): void;\n}\n\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n enableInp: true,\n enableElementTiming: true,\n ignoreResourceSpans: [],\n ignorePerformanceApiSpans: [],\n detectRedirects: true,\n linkPreviousTrace: 'in-memory',\n consistentTraceSampling: false,\n _experiments: {},\n ...defaultRequestInstrumentationOptions,\n};\n\n/**\n * The Browser Tracing integration automatically instruments browser pageload/navigation\n * actions as transactions, and captures requests, metrics and errors as spans.\n *\n * The integration can be configured with a variety of options, and can be extended to use\n * any routing library.\n *\n * We explicitly export the proper type here, as this has to be extended in some cases.\n */\nexport const browserTracingIntegration = ((_options: Partial<BrowserTracingOptions> = {}) => {\n const latestRoute: RouteInfo = {\n name: undefined,\n source: undefined,\n };\n\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const {\n enableInp,\n enableElementTiming,\n enableLongTask,\n enableLongAnimationFrame,\n _experiments: { enableInteractions, enableStandaloneClsSpans, enableStandaloneLcpSpans },\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n ignoreResourceSpans,\n ignorePerformanceApiSpans,\n instrumentPageLoad,\n instrumentNavigation,\n detectRedirects,\n linkPreviousTrace,\n consistentTraceSampling,\n onRequestSpanStart,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ..._options,\n };\n\n let _collectWebVitals: undefined | (() => void);\n let lastInteractionTimestamp: number | undefined;\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions, makeActive = true): void {\n const isPageloadTransaction = startSpanOptions.op === 'pageload';\n\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n const attributes = finalStartSpanOptions.attributes || {};\n\n // If `finalStartSpanOptions.name` is different than `startSpanOptions.name`\n // it is because `beforeStartSpan` set a custom name. Therefore we set the source to 'custom'.\n if (startSpanOptions.name !== finalStartSpanOptions.name) {\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = 'custom';\n finalStartSpanOptions.attributes = attributes;\n }\n\n if (!makeActive) {\n // We want to ensure this has 0s duration\n const now = dateTimestampInSeconds();\n startInactiveSpan({\n ...finalStartSpanOptions,\n startTime: now,\n }).end(now);\n return;\n }\n\n latestRoute.name = finalStartSpanOptions.name;\n latestRoute.source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];\n\n const idleSpan = startIdleSpan(finalStartSpanOptions, {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n // should wait for finish signal if it's a pageload transaction\n disableAutoFinish: isPageloadTransaction,\n beforeSpanEnd: span => {\n // This will generally always be defined here, because it is set in `setup()` of the integration\n // but technically, it is optional, so we guard here to be extra safe\n _collectWebVitals?.();\n addPerformanceEntries(span, {\n recordClsOnPageloadSpan: !enableStandaloneClsSpans,\n recordLcpOnPageloadSpan: !enableStandaloneLcpSpans,\n ignoreResourceSpans,\n ignorePerformanceApiSpans,\n });\n setActiveIdleSpan(client, undefined);\n\n // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.\n // Only when another navigation happens, we want to create a new trace.\n // This way, e.g. errors that occur after the pageload span ended are still associated to the pageload trace.\n const scope = getCurrentScope();\n const oldPropagationContext = scope.getPropagationContext();\n\n scope.setPropagationContext({\n ...oldPropagationContext,\n traceId: idleSpan.spanContext().traceId,\n sampled: spanIsSampled(idleSpan),\n dsc: getDynamicSamplingContextFromSpan(span),\n });\n },\n });\n\n setActiveIdleSpan(client, idleSpan);\n\n function emitFinish(): void {\n if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {\n client.emit('idleSpanEnableAutoFinish', idleSpan);\n }\n }\n\n if (isPageloadTransaction && optionalWindowDocument) {\n optionalWindowDocument.addEventListener('readystatechange', () => {\n emitFinish();\n });\n\n emitFinish();\n }\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n setup(client) {\n registerSpanErrorInstrumentation();\n\n _collectWebVitals = startTrackingWebVitals({\n recordClsStandaloneSpans: enableStandaloneClsSpans || false,\n recordLcpStandaloneSpans: enableStandaloneLcpSpans || false,\n client,\n });\n\n if (enableInp) {\n startTrackingINP();\n }\n\n if (enableElementTiming) {\n startTrackingElementTiming();\n }\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes &&\n PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (enableInteractions) {\n startTrackingInteractions();\n }\n\n if (detectRedirects && optionalWindowDocument) {\n const interactionHandler = (): void => {\n lastInteractionTimestamp = timestampInSeconds();\n };\n addEventListener('click', interactionHandler, { capture: true });\n addEventListener('keydown', interactionHandler, { capture: true, passive: true });\n }\n\n function maybeEndActiveSpan(): void {\n const activeSpan = getActiveIdleSpan(client);\n\n if (activeSpan && !spanToJSON(activeSpan).timestamp) {\n DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'cancelled');\n activeSpan.end();\n }\n }\n\n client.on('startNavigationSpan', (startSpanOptions, navigationOptions) => {\n if (getClient() !== client) {\n return;\n }\n\n if (navigationOptions?.isRedirect) {\n DEBUG_BUILD &&\n logger.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');\n _createRouteSpan(\n client,\n {\n op: 'navigation.redirect',\n ...startSpanOptions,\n },\n false,\n );\n return;\n }\n\n maybeEndActiveSpan();\n\n getIsolationScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n\n const scope = getCurrentScope();\n scope.setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n // We reset this to ensure we do not have lingering incorrect data here\n // places that call this hook may set this where appropriate - else, the URL at span sending time is used\n scope.setSDKProcessingMetadata({\n normalizedRequest: undefined,\n });\n\n _createRouteSpan(client, {\n op: 'navigation',\n ...startSpanOptions,\n });\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace = traceOptions.sentryTrace || getMetaContent('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n\n const scope = getCurrentScope();\n scope.setPropagationContext(propagationContext);\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n scope.setSDKProcessingMetadata({\n normalizedRequest: getHttpRequestData(),\n });\n\n _createRouteSpan(client, {\n op: 'pageload',\n ...startSpanOptions,\n });\n });\n },\n afterAllSetup(client) {\n let startingUrl: string | undefined = getLocationHref();\n\n if (linkPreviousTrace !== 'off') {\n linkTraces(client, { linkPreviousTrace, consistentTraceSampling });\n }\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n const origin = browserPerformanceTimeOrigin();\n startBrowserTracingPageLoadSpan(client, {\n name: WINDOW.location.pathname,\n // pageload should always start at timeOrigin (and needs to be in s, not ms)\n startTime: origin ? origin / 1000 : undefined,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser',\n },\n });\n }\n\n if (instrumentNavigation) {\n addHistoryInstrumentationHandler(({ to, from }) => {\n /**\n * This early return is there to account for some cases where a navigation transaction starts right after\n * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't\n * create an uneccessary navigation transaction.\n *\n * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also\n * only be caused in certain development environments where the usage of a hot module reloader is causing\n * errors.\n */\n if (from === undefined && startingUrl?.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n startingUrl = undefined;\n const parsed = parseStringToURLObject(to);\n const activeSpan = getActiveIdleSpan(client);\n const navigationIsRedirect =\n activeSpan && detectRedirects && isRedirect(activeSpan, lastInteractionTimestamp);\n startBrowserTracingNavigationSpan(\n client,\n {\n name: parsed?.pathname || WINDOW.location.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n },\n { url: to, isRedirect: navigationIsRedirect },\n );\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n if (enableInteractions) {\n registerInteractionListener(client, idleTimeout, finalTimeout, childSpanTimeout, latestRoute);\n }\n\n if (enableInp) {\n registerInpInteractionListener();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n onRequestSpanStart,\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Manually start a page load span.\n * This will only do something if a browser tracing integration integration has been setup.\n *\n * If you provide a custom `traceOptions` object, it will be used to continue the trace\n * instead of the default behavior, which is to look it up on the <meta> tags.\n */\nexport function startBrowserTracingPageLoadSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n traceOptions?: { sentryTrace?: string | undefined; baggage?: string | undefined },\n): Span | undefined {\n client.emit('startPageLoadSpan', spanOptions, traceOptions);\n getCurrentScope().setTransactionName(spanOptions.name);\n\n const pageloadSpan = getActiveIdleSpan(client);\n\n if (pageloadSpan) {\n client.emit('afterStartPageLoadSpan', pageloadSpan);\n }\n\n return pageloadSpan;\n}\n\n/**\n * Manually start a navigation span.\n * This will only do something if a browser tracing integration has been setup.\n */\nexport function startBrowserTracingNavigationSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n options?: { url?: string; isRedirect?: boolean },\n): Span | undefined {\n const { url, isRedirect } = options || {};\n client.emit('beforeStartNavigationSpan', spanOptions, { isRedirect });\n client.emit('startNavigationSpan', spanOptions, { isRedirect });\n\n const scope = getCurrentScope();\n scope.setTransactionName(spanOptions.name);\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n if (url && !isRedirect) {\n scope.setSDKProcessingMetadata({\n normalizedRequest: {\n ...getHttpRequestData(),\n url,\n },\n });\n }\n\n return getActiveIdleSpan(client);\n}\n\n/** Returns the value of a meta tag */\nexport function getMetaContent(metaName: string): string | undefined {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const metaTag = optionalWindowDocument?.querySelector(`meta[name=${metaName}]`);\n return metaTag?.getAttribute('content') || undefined;\n}\n\n/** Start listener for interaction transactions */\nfunction registerInteractionListener(\n client: Client,\n idleTimeout: BrowserTracingOptions['idleTimeout'],\n finalTimeout: BrowserTracingOptions['finalTimeout'],\n childSpanTimeout: BrowserTracingOptions['childSpanTimeout'],\n latestRoute: RouteInfo,\n): void {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n let inflightInteractionSpan: Span | undefined;\n const registerInteractionTransaction = (): void => {\n const op = 'ui.action.click';\n\n const activeIdleSpan = getActiveIdleSpan(client);\n if (activeIdleSpan) {\n const currentRootSpanOp = spanToJSON(activeIdleSpan).op;\n if (['navigation', 'pageload'].includes(currentRootSpanOp as string)) {\n DEBUG_BUILD &&\n logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);\n return undefined;\n }\n }\n\n if (inflightInteractionSpan) {\n inflightInteractionSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'interactionInterrupted');\n inflightInteractionSpan.end();\n inflightInteractionSpan = undefined;\n }\n\n if (!latestRoute.name) {\n DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);\n return undefined;\n }\n\n inflightInteractionSpan = startIdleSpan(\n {\n name: latestRoute.name,\n op,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: latestRoute.source || 'url',\n },\n },\n {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n },\n );\n };\n\n if (optionalWindowDocument) {\n addEventListener('click', registerInteractionTransaction, { capture: true });\n }\n}\n\n// We store the active idle span on the client object, so we can access it from exported functions\nconst ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';\nfunction getActiveIdleSpan(client: Client): Span | undefined {\n return (client as { [ACTIVE_IDLE_SPAN_PROPERTY]?: Span })[ACTIVE_IDLE_SPAN_PROPERTY];\n}\n\nfunction setActiveIdleSpan(client: Client, span: Span | undefined): void {\n addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);\n}\n\n// The max. time in seconds between two pageload/navigation spans that makes us consider the second one a redirect\nconst REDIRECT_THRESHOLD = 0.3;\n\nfunction isRedirect(activeSpan: Span, lastInteractionTimestamp: number | undefined): boolean {\n const spanData = spanToJSON(activeSpan);\n\n const now = dateTimestampInSeconds();\n\n // More than 300ms since last navigation/pageload span?\n // --> never consider this a redirect\n const startTimestamp = spanData.start_timestamp;\n if (now - startTimestamp > REDIRECT_THRESHOLD) {\n return false;\n }\n\n // A click happened in the last 300ms?\n // --> never consider this a redirect\n if (lastInteractionTimestamp && now - lastInteractionTimestamp <= REDIRECT_THRESHOLD) {\n return false;\n }\n\n return true;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browserTracingIntegration.js","sources":["../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, IntegrationFn, Span, StartSpanOptions, TransactionSource, WebFetchHeaders } from '@sentry/core';\nimport {\n addNonEnumerableProperty,\n browserPerformanceTimeOrigin,\n dateTimestampInSeconds,\n debug,\n generateTraceId,\n getClient,\n getCurrentScope,\n getDynamicSamplingContextFromSpan,\n getIsolationScope,\n getLocationHref,\n GLOBAL_OBJ,\n parseStringToURLObject,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n spanIsSampled,\n spanToJSON,\n startIdleSpan,\n startInactiveSpan,\n timestampInSeconds,\n TRACING_DEFAULTS,\n} from '@sentry/core';\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n registerInpInteractionListener,\n startTrackingElementTiming,\n startTrackingINP,\n startTrackingInteractions,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n startTrackingWebVitals,\n} from '@sentry-internal/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { linkTraces } from './linkedTraces';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\ninterface RouteInfo {\n name: string | undefined;\n source: TransactionSource | undefined;\n}\n\n/** Options for Browser Tracing integration */\nexport interface BrowserTracingOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * Default: 1000 (ms)\n */\n idleTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 30000 (ms)\n */\n finalTimeout: number;\n\n /**\n The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 15000 (ms)\n */\n childSpanTimeout: number;\n\n /**\n * If a span should be created on page load.\n * If this is set to `false`, this integration will not start the default page load span.\n * Default: true\n */\n instrumentPageLoad: boolean;\n\n /**\n * If a span should be created on navigation (history change).\n * If this is set to `false`, this integration will not start the default navigation spans.\n * Default: true\n */\n instrumentNavigation: boolean;\n\n /**\n * Flag spans where tabs moved to background with \"cancelled\". Browser background tab timing is\n * not suited towards doing precise measurements of operations. By default, we recommend that this option\n * be enabled as background transactions can mess up your statistics in nondeterministic ways.\n *\n * Default: true\n */\n markBackgroundSpan: boolean;\n\n /**\n * If true, Sentry will capture long tasks and add them to the corresponding transaction.\n *\n * Default: true\n */\n enableLongTask: boolean;\n\n /**\n * If true, Sentry will capture long animation frames and add them to the corresponding transaction.\n *\n * Default: false\n */\n enableLongAnimationFrame: boolean;\n\n /**\n * If true, Sentry will capture first input delay and add it to the corresponding transaction.\n *\n * Default: true\n */\n enableInp: boolean;\n\n /**\n * If true, Sentry will capture [element timing](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceElementTiming)\n * information and add it to the corresponding transaction.\n *\n * Default: true\n */\n enableElementTiming: boolean;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Default: false\n */\n trackFetchStreamPerformance: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resouce.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Spans created from the following browser Performance APIs,\n *\n * - [`performance.mark(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark)\n * - [`performance.measure(...)`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure)\n *\n * will not be emitted if their names match strings in this array.\n *\n * This is useful, if you come across `mark` or `measure` spans in your Sentry traces\n * that you want to ignore. For example, sometimes, browser extensions or libraries\n * emit these entries on their own, which might not be relevant to your application.\n *\n * * @example\n * ```ts\n * Sentry.init({\n * integrations: [\n * Sentry.browserTracingIntegration({\n * ignorePerformanceApiSpans: ['myMeasurement', /myMark/],\n * }),\n * ],\n * });\n *\n * // no spans will be created for these:\n * performance.mark('myMark');\n * performance.measure('myMeasurement');\n *\n * // spans will be created for these:\n * performance.mark('authenticated');\n * performance.measure('input-duration', ...);\n * ```\n *\n * Default: [] - By default, all `mark` and `measure` entries are sent as spans.\n */\n ignorePerformanceApiSpans: Array<string | RegExp>;\n\n /**\n * By default, the SDK will try to detect redirects and avoid creating separate spans for them.\n * If you want to opt-out of this behavior, you can set this option to `false`.\n *\n * Default: true\n */\n detectRedirects: boolean;\n\n /**\n * Link the currently started trace to a previous trace (e.g. a prior pageload, navigation or\n * manually started span). When enabled, this option will allow you to navigate between traces\n * in the Sentry UI.\n *\n * You can set this option to the following values:\n *\n * - `'in-memory'`: The previous trace data will be stored in memory.\n * This is useful for single-page applications and enabled by default.\n *\n * - `'session-storage'`: The previous trace data will be stored in the `sessionStorage`.\n * This is useful for multi-page applications or static sites but it means that the\n * Sentry SDK writes to the browser's `sessionStorage`.\n *\n * - `'off'`: The previous trace data will not be stored or linked.\n *\n * You can also use {@link BrowserTracingOptions.consistentTraceSampling} to get\n * consistent trace sampling of subsequent traces. Otherwise, by default, your\n * `tracesSampleRate` or `tracesSampler` config significantly influences how often\n * traces will be linked.\n *\n * @default 'in-memory' - see explanation above\n */\n linkPreviousTrace: 'in-memory' | 'session-storage' | 'off';\n\n /**\n * If true, Sentry will consistently sample subsequent traces based on the\n * sampling decision of the initial trace. For example, if the initial page\n * load trace was sampled positively, all subsequent traces (e.g. navigations)\n * are also sampled positively. In case the initial trace was sampled negatively,\n * all subsequent traces are also sampled negatively.\n *\n * This option allows you to get consistent, linked traces within a user journey\n * while maintaining an overall quota based on your trace sampling settings.\n *\n * This option is only effective if {@link BrowserTracingOptions.linkPreviousTrace}\n * is enabled (i.e. not set to `'off'`).\n *\n * @default `false` - this is an opt-in feature.\n */\n consistentTraceSampling: boolean;\n\n /**\n * _experiments allows the user to send options to define how this integration works.\n *\n * Default: undefined\n */\n _experiments: Partial<{\n enableInteractions: boolean;\n enableStandaloneClsSpans: boolean;\n enableStandaloneLcpSpans: boolean;\n }>;\n\n /**\n * A callback which is called before a span for a pageload or navigation is started.\n * It receives the options passed to `startSpan`, and expects to return an updated options object.\n */\n beforeStartSpan?: (options: StartSpanOptions) => StartSpanOptions;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * This callback is invoked directly after a span is started for an outgoing fetch or XHR request.\n * You can use it to annotate the span with additional data or attributes, for example by setting\n * attributes based on the passed request headers.\n */\n onRequestSpanStart?(span: Span, requestInformation: { headers?: WebFetchHeaders }): void;\n}\n\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n enableInp: true,\n enableElementTiming: true,\n ignoreResourceSpans: [],\n ignorePerformanceApiSpans: [],\n detectRedirects: true,\n linkPreviousTrace: 'in-memory',\n consistentTraceSampling: false,\n _experiments: {},\n ...defaultRequestInstrumentationOptions,\n};\n\n/**\n * The Browser Tracing integration automatically instruments browser pageload/navigation\n * actions as transactions, and captures requests, metrics and errors as spans.\n *\n * The integration can be configured with a variety of options, and can be extended to use\n * any routing library.\n *\n * We explicitly export the proper type here, as this has to be extended in some cases.\n */\nexport const browserTracingIntegration = ((_options: Partial<BrowserTracingOptions> = {}) => {\n const latestRoute: RouteInfo = {\n name: undefined,\n source: undefined,\n };\n\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const {\n enableInp,\n enableElementTiming,\n enableLongTask,\n enableLongAnimationFrame,\n _experiments: { enableInteractions, enableStandaloneClsSpans, enableStandaloneLcpSpans },\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n ignoreResourceSpans,\n ignorePerformanceApiSpans,\n instrumentPageLoad,\n instrumentNavigation,\n detectRedirects,\n linkPreviousTrace,\n consistentTraceSampling,\n onRequestSpanStart,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ..._options,\n };\n\n let _collectWebVitals: undefined | (() => void);\n let lastInteractionTimestamp: number | undefined;\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions, makeActive = true): void {\n const isPageloadTransaction = startSpanOptions.op === 'pageload';\n\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n const attributes = finalStartSpanOptions.attributes || {};\n\n // If `finalStartSpanOptions.name` is different than `startSpanOptions.name`\n // it is because `beforeStartSpan` set a custom name. Therefore we set the source to 'custom'.\n if (startSpanOptions.name !== finalStartSpanOptions.name) {\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = 'custom';\n finalStartSpanOptions.attributes = attributes;\n }\n\n if (!makeActive) {\n // We want to ensure this has 0s duration\n const now = dateTimestampInSeconds();\n startInactiveSpan({\n ...finalStartSpanOptions,\n startTime: now,\n }).end(now);\n return;\n }\n\n latestRoute.name = finalStartSpanOptions.name;\n latestRoute.source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];\n\n const idleSpan = startIdleSpan(finalStartSpanOptions, {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n // should wait for finish signal if it's a pageload transaction\n disableAutoFinish: isPageloadTransaction,\n beforeSpanEnd: span => {\n // This will generally always be defined here, because it is set in `setup()` of the integration\n // but technically, it is optional, so we guard here to be extra safe\n _collectWebVitals?.();\n addPerformanceEntries(span, {\n recordClsOnPageloadSpan: !enableStandaloneClsSpans,\n recordLcpOnPageloadSpan: !enableStandaloneLcpSpans,\n ignoreResourceSpans,\n ignorePerformanceApiSpans,\n });\n setActiveIdleSpan(client, undefined);\n\n // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.\n // Only when another navigation happens, we want to create a new trace.\n // This way, e.g. errors that occur after the pageload span ended are still associated to the pageload trace.\n const scope = getCurrentScope();\n const oldPropagationContext = scope.getPropagationContext();\n\n scope.setPropagationContext({\n ...oldPropagationContext,\n traceId: idleSpan.spanContext().traceId,\n sampled: spanIsSampled(idleSpan),\n dsc: getDynamicSamplingContextFromSpan(span),\n });\n },\n });\n\n setActiveIdleSpan(client, idleSpan);\n\n function emitFinish(): void {\n if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {\n client.emit('idleSpanEnableAutoFinish', idleSpan);\n }\n }\n\n if (isPageloadTransaction && optionalWindowDocument) {\n optionalWindowDocument.addEventListener('readystatechange', () => {\n emitFinish();\n });\n\n emitFinish();\n }\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n setup(client) {\n registerSpanErrorInstrumentation();\n\n _collectWebVitals = startTrackingWebVitals({\n recordClsStandaloneSpans: enableStandaloneClsSpans || false,\n recordLcpStandaloneSpans: enableStandaloneLcpSpans || false,\n client,\n });\n\n if (enableInp) {\n startTrackingINP();\n }\n\n if (enableElementTiming) {\n startTrackingElementTiming();\n }\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes &&\n PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (enableInteractions) {\n startTrackingInteractions();\n }\n\n if (detectRedirects && optionalWindowDocument) {\n const interactionHandler = (): void => {\n lastInteractionTimestamp = timestampInSeconds();\n };\n addEventListener('click', interactionHandler, { capture: true });\n addEventListener('keydown', interactionHandler, { capture: true, passive: true });\n }\n\n function maybeEndActiveSpan(): void {\n const activeSpan = getActiveIdleSpan(client);\n\n if (activeSpan && !spanToJSON(activeSpan).timestamp) {\n DEBUG_BUILD && debug.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'cancelled');\n activeSpan.end();\n }\n }\n\n client.on('startNavigationSpan', (startSpanOptions, navigationOptions) => {\n if (getClient() !== client) {\n return;\n }\n\n if (navigationOptions?.isRedirect) {\n DEBUG_BUILD &&\n debug.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');\n _createRouteSpan(\n client,\n {\n op: 'navigation.redirect',\n ...startSpanOptions,\n },\n false,\n );\n return;\n }\n\n maybeEndActiveSpan();\n\n getIsolationScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n\n const scope = getCurrentScope();\n scope.setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n // We reset this to ensure we do not have lingering incorrect data here\n // places that call this hook may set this where appropriate - else, the URL at span sending time is used\n scope.setSDKProcessingMetadata({\n normalizedRequest: undefined,\n });\n\n _createRouteSpan(client, {\n op: 'navigation',\n ...startSpanOptions,\n });\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace = traceOptions.sentryTrace || getMetaContent('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n\n const scope = getCurrentScope();\n scope.setPropagationContext(propagationContext);\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n scope.setSDKProcessingMetadata({\n normalizedRequest: getHttpRequestData(),\n });\n\n _createRouteSpan(client, {\n op: 'pageload',\n ...startSpanOptions,\n });\n });\n },\n afterAllSetup(client) {\n let startingUrl: string | undefined = getLocationHref();\n\n if (linkPreviousTrace !== 'off') {\n linkTraces(client, { linkPreviousTrace, consistentTraceSampling });\n }\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n const origin = browserPerformanceTimeOrigin();\n startBrowserTracingPageLoadSpan(client, {\n name: WINDOW.location.pathname,\n // pageload should always start at timeOrigin (and needs to be in s, not ms)\n startTime: origin ? origin / 1000 : undefined,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser',\n },\n });\n }\n\n if (instrumentNavigation) {\n addHistoryInstrumentationHandler(({ to, from }) => {\n /**\n * This early return is there to account for some cases where a navigation transaction starts right after\n * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't\n * create an uneccessary navigation transaction.\n *\n * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also\n * only be caused in certain development environments where the usage of a hot module reloader is causing\n * errors.\n */\n if (from === undefined && startingUrl?.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n startingUrl = undefined;\n const parsed = parseStringToURLObject(to);\n const activeSpan = getActiveIdleSpan(client);\n const navigationIsRedirect =\n activeSpan && detectRedirects && isRedirect(activeSpan, lastInteractionTimestamp);\n startBrowserTracingNavigationSpan(\n client,\n {\n name: parsed?.pathname || WINDOW.location.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n },\n { url: to, isRedirect: navigationIsRedirect },\n );\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n if (enableInteractions) {\n registerInteractionListener(client, idleTimeout, finalTimeout, childSpanTimeout, latestRoute);\n }\n\n if (enableInp) {\n registerInpInteractionListener();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n onRequestSpanStart,\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Manually start a page load span.\n * This will only do something if a browser tracing integration integration has been setup.\n *\n * If you provide a custom `traceOptions` object, it will be used to continue the trace\n * instead of the default behavior, which is to look it up on the <meta> tags.\n */\nexport function startBrowserTracingPageLoadSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n traceOptions?: { sentryTrace?: string | undefined; baggage?: string | undefined },\n): Span | undefined {\n client.emit('startPageLoadSpan', spanOptions, traceOptions);\n getCurrentScope().setTransactionName(spanOptions.name);\n\n const pageloadSpan = getActiveIdleSpan(client);\n\n if (pageloadSpan) {\n client.emit('afterStartPageLoadSpan', pageloadSpan);\n }\n\n return pageloadSpan;\n}\n\n/**\n * Manually start a navigation span.\n * This will only do something if a browser tracing integration has been setup.\n */\nexport function startBrowserTracingNavigationSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n options?: { url?: string; isRedirect?: boolean },\n): Span | undefined {\n const { url, isRedirect } = options || {};\n client.emit('beforeStartNavigationSpan', spanOptions, { isRedirect });\n client.emit('startNavigationSpan', spanOptions, { isRedirect });\n\n const scope = getCurrentScope();\n scope.setTransactionName(spanOptions.name);\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n if (url && !isRedirect) {\n scope.setSDKProcessingMetadata({\n normalizedRequest: {\n ...getHttpRequestData(),\n url,\n },\n });\n }\n\n return getActiveIdleSpan(client);\n}\n\n/** Returns the value of a meta tag */\nexport function getMetaContent(metaName: string): string | undefined {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const metaTag = optionalWindowDocument?.querySelector(`meta[name=${metaName}]`);\n return metaTag?.getAttribute('content') || undefined;\n}\n\n/** Start listener for interaction transactions */\nfunction registerInteractionListener(\n client: Client,\n idleTimeout: BrowserTracingOptions['idleTimeout'],\n finalTimeout: BrowserTracingOptions['finalTimeout'],\n childSpanTimeout: BrowserTracingOptions['childSpanTimeout'],\n latestRoute: RouteInfo,\n): void {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n let inflightInteractionSpan: Span | undefined;\n const registerInteractionTransaction = (): void => {\n const op = 'ui.action.click';\n\n const activeIdleSpan = getActiveIdleSpan(client);\n if (activeIdleSpan) {\n const currentRootSpanOp = spanToJSON(activeIdleSpan).op;\n if (['navigation', 'pageload'].includes(currentRootSpanOp as string)) {\n DEBUG_BUILD &&\n debug.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);\n return undefined;\n }\n }\n\n if (inflightInteractionSpan) {\n inflightInteractionSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'interactionInterrupted');\n inflightInteractionSpan.end();\n inflightInteractionSpan = undefined;\n }\n\n if (!latestRoute.name) {\n DEBUG_BUILD && debug.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);\n return undefined;\n }\n\n inflightInteractionSpan = startIdleSpan(\n {\n name: latestRoute.name,\n op,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: latestRoute.source || 'url',\n },\n },\n {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n },\n );\n };\n\n if (optionalWindowDocument) {\n addEventListener('click', registerInteractionTransaction, { capture: true });\n }\n}\n\n// We store the active idle span on the client object, so we can access it from exported functions\nconst ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';\nfunction getActiveIdleSpan(client: Client): Span | undefined {\n return (client as { [ACTIVE_IDLE_SPAN_PROPERTY]?: Span })[ACTIVE_IDLE_SPAN_PROPERTY];\n}\n\nfunction setActiveIdleSpan(client: Client, span: Span | undefined): void {\n addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);\n}\n\n// The max. time in seconds between two pageload/navigation spans that makes us consider the second one a redirect\nconst REDIRECT_THRESHOLD = 0.3;\n\nfunction isRedirect(activeSpan: Span, lastInteractionTimestamp: number | undefined): boolean {\n const spanData = spanToJSON(activeSpan);\n\n const now = dateTimestampInSeconds();\n\n // More than 300ms since last navigation/pageload span?\n // --> never consider this a redirect\n const startTimestamp = spanData.start_timestamp;\n if (now - startTimestamp > REDIRECT_THRESHOLD) {\n return false;\n }\n\n // A click happened in the last 300ms?\n // --> never consider this a redirect\n if (lastInteractionTimestamp && now - lastInteractionTimestamp <= REDIRECT_THRESHOLD) {\n return false;\n }\n\n return true;\n}\n"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { getRootSpan, getCurrentScope, SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE, spanToJSON, logger, SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '@sentry/core';
1
+ import { getRootSpan, getCurrentScope, SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE, spanToJSON, debug, SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '@sentry/core';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
3
  import { WINDOW } from '../helpers.js';
4
4
  import '@sentry-internal/browser-utils';
@@ -151,7 +151,7 @@ function addPreviousTraceSpanLink(
151
151
  // - enable more efficient querying for previous/next traces in Sentry
152
152
  if (Date.now() / 1000 - previousTraceInfo.startTimestamp <= PREVIOUS_TRACE_MAX_DURATION) {
153
153
  if (DEBUG_BUILD) {
154
- logger.info(
154
+ debug.log(
155
155
  `Adding previous_trace ${previousTraceSpanCtx} link to span ${{
156
156
  op: spanJson.op,
157
157
  ...span.spanContext(),
@@ -189,7 +189,7 @@ function storePreviousTraceInSessionStorage(previousTraceInfo) {
189
189
  WINDOW.sessionStorage.setItem(PREVIOUS_TRACE_KEY, JSON.stringify(previousTraceInfo));
190
190
  } catch (e) {
191
191
  // Ignore potential errors (e.g. if sessionStorage is not available)
192
- DEBUG_BUILD && logger.warn('Could not store previous trace in sessionStorage', e);
192
+ DEBUG_BUILD && debug.warn('Could not store previous trace in sessionStorage', e);
193
193
  }
194
194
  }
195
195
 
@@ -201,7 +201,7 @@ function getPreviousTraceFromSessionStorage() {
201
201
  const previousTraceInfo = WINDOW.sessionStorage?.getItem(PREVIOUS_TRACE_KEY);
202
202
  // @ts-expect-error - intentionally risking JSON.parse throwing when previousTraceInfo is null to save bundle size
203
203
  return JSON.parse(previousTraceInfo);
204
- } catch (e) {
204
+ } catch {
205
205
  return undefined;
206
206
  }
207
207
  }
@@ -1 +1 @@
1
- {"version":3,"file":"linkedTraces.js","sources":["../../../../src/tracing/linkedTraces.ts"],"sourcesContent":["import type { Client, PropagationContext, Span } from '@sentry/core';\nimport {\n type SpanContextData,\n getCurrentScope,\n getRootSpan,\n logger,\n SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE,\n SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,\n SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE,\n spanToJSON,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../exports';\n\nexport interface PreviousTraceInfo {\n /**\n * Span context of the previous trace's local root span\n */\n spanContext: SpanContextData;\n\n /**\n * Timestamp in seconds when the previous trace was started\n */\n startTimestamp: number;\n\n /**\n * sample rate of the previous trace\n */\n sampleRate: number;\n\n /**\n * The sample rand of the previous trace\n */\n sampleRand: number;\n}\n\n// 1h in seconds\nexport const PREVIOUS_TRACE_MAX_DURATION = 3600;\n\n// session storage key\nexport const PREVIOUS_TRACE_KEY = 'sentry_previous_trace';\n\nexport const PREVIOUS_TRACE_TMP_SPAN_ATTRIBUTE = 'sentry.previous_trace';\n\n/**\n * Takes care of linking traces and applying the (consistent) sampling behavoiour based on the passed options\n * @param options - options for linking traces and consistent trace sampling (@see BrowserTracingOptions)\n * @param client - Sentry client\n */\nexport function linkTraces(\n client: Client,\n {\n linkPreviousTrace,\n consistentTraceSampling,\n }: {\n linkPreviousTrace: 'session-storage' | 'in-memory';\n consistentTraceSampling: boolean;\n },\n): void {\n const useSessionStorage = linkPreviousTrace === 'session-storage';\n\n let inMemoryPreviousTraceInfo = useSessionStorage ? getPreviousTraceFromSessionStorage() : undefined;\n\n client.on('spanStart', span => {\n if (getRootSpan(span) !== span) {\n return;\n }\n\n const oldPropagationContext = getCurrentScope().getPropagationContext();\n inMemoryPreviousTraceInfo = addPreviousTraceSpanLink(inMemoryPreviousTraceInfo, span, oldPropagationContext);\n\n if (useSessionStorage) {\n storePreviousTraceInSessionStorage(inMemoryPreviousTraceInfo);\n }\n });\n\n let isFirstTraceOnPageload = true;\n if (consistentTraceSampling) {\n /*\n When users opt into `consistentTraceSampling`, we need to ensure that we propagate\n the previous trace's sample rate and rand to the current trace. This is necessary because otherwise, span\n metric extrapolation is inaccurate, as we'd propagate too high of a sample rate for the subsequent traces.\n\n So therefore, we pretend that the previous trace was the parent trace of the newly started trace. To do that,\n we mutate the propagation context of the current trace and set the sample rate and sample rand of the previous trace.\n Timing-wise, it is fine because it happens before we even sample the root span.\n\n @see https://github.com/getsentry/sentry-javascript/issues/15754\n */\n client.on('beforeSampling', mutableSamplingContextData => {\n if (!inMemoryPreviousTraceInfo) {\n return;\n }\n\n const scope = getCurrentScope();\n const currentPropagationContext = scope.getPropagationContext();\n\n // We do not want to force-continue the sampling decision if we continue a trace\n // that was started on the backend. Most prominently, this will happen in MPAs where\n // users hard-navigate between pages. In this case, the sampling decision of a potentially\n // started trace on the server takes precedence.\n // Why? We want to prioritize inter-trace consistency over intra-trace consistency.\n if (isFirstTraceOnPageload && currentPropagationContext.parentSpanId) {\n isFirstTraceOnPageload = false;\n return;\n }\n\n scope.setPropagationContext({\n ...currentPropagationContext,\n dsc: {\n ...currentPropagationContext.dsc,\n sample_rate: String(inMemoryPreviousTraceInfo.sampleRate),\n sampled: String(spanContextSampled(inMemoryPreviousTraceInfo.spanContext)),\n },\n sampleRand: inMemoryPreviousTraceInfo.sampleRand,\n });\n\n mutableSamplingContextData.parentSampled = spanContextSampled(inMemoryPreviousTraceInfo.spanContext);\n mutableSamplingContextData.parentSampleRate = inMemoryPreviousTraceInfo.sampleRate;\n\n mutableSamplingContextData.spanAttributes = {\n ...mutableSamplingContextData.spanAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE]: inMemoryPreviousTraceInfo.sampleRate,\n };\n });\n }\n}\n\n/**\n * Adds a previous_trace span link to the passed span if the passed\n * previousTraceInfo is still valid.\n *\n * @returns the updated previous trace info (based on the current span/trace) to\n * be used on the next call\n */\nexport function addPreviousTraceSpanLink(\n previousTraceInfo: PreviousTraceInfo | undefined,\n span: Span,\n oldPropagationContext: PropagationContext,\n): PreviousTraceInfo {\n const spanJson = spanToJSON(span);\n\n function getSampleRate(): number {\n try {\n return (\n Number(oldPropagationContext.dsc?.sample_rate) ?? Number(spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE])\n );\n } catch {\n return 0;\n }\n }\n\n const updatedPreviousTraceInfo = {\n spanContext: span.spanContext(),\n startTimestamp: spanJson.start_timestamp,\n sampleRate: getSampleRate(),\n sampleRand: oldPropagationContext.sampleRand,\n };\n\n if (!previousTraceInfo) {\n return updatedPreviousTraceInfo;\n }\n\n const previousTraceSpanCtx = previousTraceInfo.spanContext;\n if (previousTraceSpanCtx.traceId === spanJson.trace_id) {\n // This means, we're still in the same trace so let's not update the previous trace info\n // or add a link to the current span.\n // Once we move away from the long-lived, route-based trace model, we can remove this cases\n return previousTraceInfo;\n }\n\n // Only add the link if the startTimeStamp of the previous trace's root span is within\n // PREVIOUS_TRACE_MAX_DURATION (1h) of the current root span's startTimestamp\n // This is done to\n // - avoid adding links to \"stale\" traces\n // - enable more efficient querying for previous/next traces in Sentry\n if (Date.now() / 1000 - previousTraceInfo.startTimestamp <= PREVIOUS_TRACE_MAX_DURATION) {\n if (DEBUG_BUILD) {\n logger.info(\n `Adding previous_trace ${previousTraceSpanCtx} link to span ${{\n op: spanJson.op,\n ...span.spanContext(),\n }}`,\n );\n }\n\n span.addLink({\n context: previousTraceSpanCtx,\n attributes: {\n [SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',\n },\n });\n\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v10), to remind us\n // to check this at v10 time :)\n span.setAttribute(\n PREVIOUS_TRACE_TMP_SPAN_ATTRIBUTE,\n `${previousTraceSpanCtx.traceId}-${previousTraceSpanCtx.spanId}-${\n spanContextSampled(previousTraceSpanCtx) ? 1 : 0\n }`,\n );\n }\n\n return updatedPreviousTraceInfo;\n}\n\n/**\n * Stores @param previousTraceInfo in sessionStorage.\n */\nexport function storePreviousTraceInSessionStorage(previousTraceInfo: PreviousTraceInfo): void {\n try {\n WINDOW.sessionStorage.setItem(PREVIOUS_TRACE_KEY, JSON.stringify(previousTraceInfo));\n } catch (e) {\n // Ignore potential errors (e.g. if sessionStorage is not available)\n DEBUG_BUILD && logger.warn('Could not store previous trace in sessionStorage', e);\n }\n}\n\n/**\n * Retrieves the previous trace from sessionStorage if available.\n */\nexport function getPreviousTraceFromSessionStorage(): PreviousTraceInfo | undefined {\n try {\n const previousTraceInfo = WINDOW.sessionStorage?.getItem(PREVIOUS_TRACE_KEY);\n // @ts-expect-error - intentionally risking JSON.parse throwing when previousTraceInfo is null to save bundle size\n return JSON.parse(previousTraceInfo);\n } catch (e) {\n return undefined;\n }\n}\n\n/**\n * see {@link import('@sentry/core').spanIsSampled}\n */\nexport function spanContextSampled(ctx: SpanContextData): boolean {\n return ctx.traceFlags === 0x1;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"linkedTraces.js","sources":["../../../../src/tracing/linkedTraces.ts"],"sourcesContent":["import type { Client, PropagationContext, Span } from '@sentry/core';\nimport {\n type SpanContextData,\n debug,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE,\n SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,\n SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE,\n spanToJSON,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../exports';\n\nexport interface PreviousTraceInfo {\n /**\n * Span context of the previous trace's local root span\n */\n spanContext: SpanContextData;\n\n /**\n * Timestamp in seconds when the previous trace was started\n */\n startTimestamp: number;\n\n /**\n * sample rate of the previous trace\n */\n sampleRate: number;\n\n /**\n * The sample rand of the previous trace\n */\n sampleRand: number;\n}\n\n// 1h in seconds\nexport const PREVIOUS_TRACE_MAX_DURATION = 3600;\n\n// session storage key\nexport const PREVIOUS_TRACE_KEY = 'sentry_previous_trace';\n\nexport const PREVIOUS_TRACE_TMP_SPAN_ATTRIBUTE = 'sentry.previous_trace';\n\n/**\n * Takes care of linking traces and applying the (consistent) sampling behavoiour based on the passed options\n * @param options - options for linking traces and consistent trace sampling (@see BrowserTracingOptions)\n * @param client - Sentry client\n */\nexport function linkTraces(\n client: Client,\n {\n linkPreviousTrace,\n consistentTraceSampling,\n }: {\n linkPreviousTrace: 'session-storage' | 'in-memory';\n consistentTraceSampling: boolean;\n },\n): void {\n const useSessionStorage = linkPreviousTrace === 'session-storage';\n\n let inMemoryPreviousTraceInfo = useSessionStorage ? getPreviousTraceFromSessionStorage() : undefined;\n\n client.on('spanStart', span => {\n if (getRootSpan(span) !== span) {\n return;\n }\n\n const oldPropagationContext = getCurrentScope().getPropagationContext();\n inMemoryPreviousTraceInfo = addPreviousTraceSpanLink(inMemoryPreviousTraceInfo, span, oldPropagationContext);\n\n if (useSessionStorage) {\n storePreviousTraceInSessionStorage(inMemoryPreviousTraceInfo);\n }\n });\n\n let isFirstTraceOnPageload = true;\n if (consistentTraceSampling) {\n /*\n When users opt into `consistentTraceSampling`, we need to ensure that we propagate\n the previous trace's sample rate and rand to the current trace. This is necessary because otherwise, span\n metric extrapolation is inaccurate, as we'd propagate too high of a sample rate for the subsequent traces.\n\n So therefore, we pretend that the previous trace was the parent trace of the newly started trace. To do that,\n we mutate the propagation context of the current trace and set the sample rate and sample rand of the previous trace.\n Timing-wise, it is fine because it happens before we even sample the root span.\n\n @see https://github.com/getsentry/sentry-javascript/issues/15754\n */\n client.on('beforeSampling', mutableSamplingContextData => {\n if (!inMemoryPreviousTraceInfo) {\n return;\n }\n\n const scope = getCurrentScope();\n const currentPropagationContext = scope.getPropagationContext();\n\n // We do not want to force-continue the sampling decision if we continue a trace\n // that was started on the backend. Most prominently, this will happen in MPAs where\n // users hard-navigate between pages. In this case, the sampling decision of a potentially\n // started trace on the server takes precedence.\n // Why? We want to prioritize inter-trace consistency over intra-trace consistency.\n if (isFirstTraceOnPageload && currentPropagationContext.parentSpanId) {\n isFirstTraceOnPageload = false;\n return;\n }\n\n scope.setPropagationContext({\n ...currentPropagationContext,\n dsc: {\n ...currentPropagationContext.dsc,\n sample_rate: String(inMemoryPreviousTraceInfo.sampleRate),\n sampled: String(spanContextSampled(inMemoryPreviousTraceInfo.spanContext)),\n },\n sampleRand: inMemoryPreviousTraceInfo.sampleRand,\n });\n\n mutableSamplingContextData.parentSampled = spanContextSampled(inMemoryPreviousTraceInfo.spanContext);\n mutableSamplingContextData.parentSampleRate = inMemoryPreviousTraceInfo.sampleRate;\n\n mutableSamplingContextData.spanAttributes = {\n ...mutableSamplingContextData.spanAttributes,\n [SEMANTIC_ATTRIBUTE_SENTRY_PREVIOUS_TRACE_SAMPLE_RATE]: inMemoryPreviousTraceInfo.sampleRate,\n };\n });\n }\n}\n\n/**\n * Adds a previous_trace span link to the passed span if the passed\n * previousTraceInfo is still valid.\n *\n * @returns the updated previous trace info (based on the current span/trace) to\n * be used on the next call\n */\nexport function addPreviousTraceSpanLink(\n previousTraceInfo: PreviousTraceInfo | undefined,\n span: Span,\n oldPropagationContext: PropagationContext,\n): PreviousTraceInfo {\n const spanJson = spanToJSON(span);\n\n function getSampleRate(): number {\n try {\n return (\n Number(oldPropagationContext.dsc?.sample_rate) ?? Number(spanJson.data?.[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE])\n );\n } catch {\n return 0;\n }\n }\n\n const updatedPreviousTraceInfo = {\n spanContext: span.spanContext(),\n startTimestamp: spanJson.start_timestamp,\n sampleRate: getSampleRate(),\n sampleRand: oldPropagationContext.sampleRand,\n };\n\n if (!previousTraceInfo) {\n return updatedPreviousTraceInfo;\n }\n\n const previousTraceSpanCtx = previousTraceInfo.spanContext;\n if (previousTraceSpanCtx.traceId === spanJson.trace_id) {\n // This means, we're still in the same trace so let's not update the previous trace info\n // or add a link to the current span.\n // Once we move away from the long-lived, route-based trace model, we can remove this cases\n return previousTraceInfo;\n }\n\n // Only add the link if the startTimeStamp of the previous trace's root span is within\n // PREVIOUS_TRACE_MAX_DURATION (1h) of the current root span's startTimestamp\n // This is done to\n // - avoid adding links to \"stale\" traces\n // - enable more efficient querying for previous/next traces in Sentry\n if (Date.now() / 1000 - previousTraceInfo.startTimestamp <= PREVIOUS_TRACE_MAX_DURATION) {\n if (DEBUG_BUILD) {\n debug.log(\n `Adding previous_trace ${previousTraceSpanCtx} link to span ${{\n op: spanJson.op,\n ...span.spanContext(),\n }}`,\n );\n }\n\n span.addLink({\n context: previousTraceSpanCtx,\n attributes: {\n [SEMANTIC_LINK_ATTRIBUTE_LINK_TYPE]: 'previous_trace',\n },\n });\n\n // TODO: Remove this once EAP can store span links. We currently only set this attribute so that we\n // can obtain the previous trace information from the EAP store. Long-term, EAP will handle\n // span links and then we should remove this again. Also throwing in a TODO(v10), to remind us\n // to check this at v10 time :)\n span.setAttribute(\n PREVIOUS_TRACE_TMP_SPAN_ATTRIBUTE,\n `${previousTraceSpanCtx.traceId}-${previousTraceSpanCtx.spanId}-${\n spanContextSampled(previousTraceSpanCtx) ? 1 : 0\n }`,\n );\n }\n\n return updatedPreviousTraceInfo;\n}\n\n/**\n * Stores @param previousTraceInfo in sessionStorage.\n */\nexport function storePreviousTraceInSessionStorage(previousTraceInfo: PreviousTraceInfo): void {\n try {\n WINDOW.sessionStorage.setItem(PREVIOUS_TRACE_KEY, JSON.stringify(previousTraceInfo));\n } catch (e) {\n // Ignore potential errors (e.g. if sessionStorage is not available)\n DEBUG_BUILD && debug.warn('Could not store previous trace in sessionStorage', e);\n }\n}\n\n/**\n * Retrieves the previous trace from sessionStorage if available.\n */\nexport function getPreviousTraceFromSessionStorage(): PreviousTraceInfo | undefined {\n try {\n const previousTraceInfo = WINDOW.sessionStorage?.getItem(PREVIOUS_TRACE_KEY);\n // @ts-expect-error - intentionally risking JSON.parse throwing when previousTraceInfo is null to save bundle size\n return JSON.parse(previousTraceInfo);\n } catch {\n return undefined;\n }\n}\n\n/**\n * see {@link import('@sentry/core').spanIsSampled}\n */\nexport function spanContextSampled(ctx: SpanContextData): boolean {\n return ctx.traceFlags === 0x1;\n}\n"],"names":[],"mappings":"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"}
@@ -178,7 +178,7 @@ function shouldAttachHeaders(
178
178
  try {
179
179
  resolvedUrl = new URL(targetUrl, href);
180
180
  currentOrigin = new URL(href).origin;
181
- } catch (e) {
181
+ } catch {
182
182
  return false;
183
183
  }
184
184
 
@@ -314,7 +314,7 @@ function setHeaderOnXhr(
314
314
  xhr.setRequestHeader('baggage', sentryBaggageHeader);
315
315
  }
316
316
  }
317
- } catch (_) {
317
+ } catch {
318
318
  // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.
319
319
  }
320
320
  }