{"version":3,"file":"tracing.js","sources":["../../src/tracing.ts"],"sourcesContent":["import { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/browser';\nimport type { Span } from '@sentry/core';\nimport { debug, timestampInSeconds } from '@sentry/core';\nimport { DEFAULT_HOOKS } from './constants';\nimport { DEBUG_BUILD } from './debug-build';\nimport type { Hook, Operation, TracingOptions, ViewModel, Vue } from './types';\nimport { formatComponentName } from './vendor/components';\n\nconst VUE_OP = 'ui.vue';\n\ntype Mixins = Parameters[0];\n\ninterface VueSentry extends ViewModel {\n readonly $root: VueSentry;\n $_sentryComponentSpans?: {\n [key: string]: Span | undefined;\n };\n $_sentryRootComponentSpan?: Span;\n $_sentryRootComponentSpanTimer?: ReturnType;\n}\n\n// Mappings from operation to corresponding lifecycle hook.\nconst HOOKS: { [key in Operation]: Hook[] } = {\n activate: ['activated', 'deactivated'],\n create: ['beforeCreate', 'created'],\n // Vue 3\n unmount: ['beforeUnmount', 'unmounted'],\n // Vue 2\n destroy: ['beforeDestroy', 'destroyed'],\n mount: ['beforeMount', 'mounted'],\n update: ['beforeUpdate', 'updated'],\n};\n\n/** End the top-level component span and activity with a debounce configured using `timeout` option */\nfunction maybeEndRootComponentSpan(vm: VueSentry, timestamp: number, timeout: number): void {\n if (vm.$_sentryRootComponentSpanTimer) {\n clearTimeout(vm.$_sentryRootComponentSpanTimer);\n }\n\n vm.$_sentryRootComponentSpanTimer = setTimeout(() => {\n if (vm.$root?.$_sentryRootComponentSpan) {\n vm.$root.$_sentryRootComponentSpan.end(timestamp);\n vm.$root.$_sentryRootComponentSpan = undefined;\n }\n }, timeout);\n}\n\n/** Find if the current component exists in the provided `TracingOptions.trackComponents` array option. */\nexport function findTrackComponent(trackComponents: string[], formattedName: string): boolean {\n function extractComponentName(name: string): string {\n return name.replace(/^<([^\\s]*)>(?: at [^\\s]*)?$/, '$1');\n }\n\n const isMatched = trackComponents.some(compo => {\n return extractComponentName(formattedName) === extractComponentName(compo);\n });\n\n return isMatched;\n}\n\nexport const createTracingMixins = (options: Partial = {}): Mixins => {\n const hooks = (options.hooks || [])\n .concat(DEFAULT_HOOKS)\n // Removing potential duplicates\n .filter((value, index, self) => self.indexOf(value) === index);\n\n const mixins: Mixins = {};\n\n const rootComponentSpanFinalTimeout = options.timeout || 2000;\n\n for (const operation of hooks) {\n // Retrieve corresponding hooks from Vue lifecycle.\n // eg. mount => ['beforeMount', 'mounted']\n const internalHooks = HOOKS[operation];\n if (!internalHooks) {\n DEBUG_BUILD && debug.warn(`Unknown hook: ${operation}`);\n continue;\n }\n\n for (const internalHook of internalHooks) {\n mixins[internalHook] = function (this: VueSentry) {\n const isRootComponent = this.$root === this;\n\n // 1. Root Component span creation\n if (isRootComponent) {\n this.$_sentryRootComponentSpan =\n this.$_sentryRootComponentSpan ||\n startInactiveSpan({\n name: 'Application Render',\n op: `${VUE_OP}.render`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.vue',\n },\n onlyIfParent: true,\n });\n\n // call debounced end function once directly, just in case no child components call it\n maybeEndRootComponentSpan(this, timestampInSeconds(), rootComponentSpanFinalTimeout);\n }\n\n // 2. Component tracking filter\n const componentName = formatComponentName(this, false);\n\n const shouldTrack =\n isRootComponent || // We always want to track the root component\n (Array.isArray(options.trackComponents)\n ? findTrackComponent(options.trackComponents, componentName)\n : options.trackComponents);\n\n // We always want to track root component\n if (!shouldTrack) {\n // even if we don't track `this` component, we still want to end the root span eventually\n maybeEndRootComponentSpan(this, timestampInSeconds(), rootComponentSpanFinalTimeout);\n return;\n }\n\n this.$_sentryComponentSpans = this.$_sentryComponentSpans || {};\n\n // 3. Span lifecycle management based on the hook type\n const isBeforeHook = internalHook === internalHooks[0];\n const activeSpan = this.$root?.$_sentryRootComponentSpan || getActiveSpan();\n\n if (isBeforeHook) {\n // Starting a new span in the \"before\" hook\n if (activeSpan) {\n // Cancel any existing span for this operation (safety measure)\n // We're actually not sure if it will ever be the case that cleanup hooks were not called.\n // However, we had users report that spans didn't end, so we end the span before\n // starting a new one, just to be sure.\n const oldSpan = this.$_sentryComponentSpans[operation];\n if (oldSpan) {\n oldSpan.end();\n }\n\n this.$_sentryComponentSpans[operation] = startInactiveSpan({\n name: `Vue ${componentName}`,\n op: `${VUE_OP}.${operation}`,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.vue',\n },\n // UI spans should only be created if there is an active root span (transaction)\n onlyIfParent: true,\n });\n }\n } else {\n // The span should already be added via the first handler call (in the 'before' hook)\n const span = this.$_sentryComponentSpans[operation];\n // The before hook did not start the tracking span, so the span was not added.\n // This is probably because it happened before there is an active transaction\n if (!span) return; // Skip if no span was created in the \"before\" hook\n span.end();\n\n // For any \"after\" hook, also schedule the root component span to end\n maybeEndRootComponentSpan(this, timestampInSeconds(), rootComponentSpanFinalTimeout);\n }\n };\n }\n }\n\n return mixins;\n};\n"],"names":[],"mappings":"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"}