1- import { WINDOW , captureException } from '@sentry/browser' ;
2- import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN , SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , spanToJSON } from '@sentry/core' ;
3- import type { SpanAttributes , Transaction , TransactionContext , TransactionSource } from '@sentry/types' ;
4-
5- import { getActiveTransaction } from './tracing' ;
6-
7- interface VueRouterInstrumationOptions {
8- /**
9- * What to use for route labels.
10- * By default, we use route.name (if set) and else the path.
11- *
12- * Default: 'name'
13- */
14- routeLabel : 'name' | 'path' ;
15- }
16-
17- export type VueRouterInstrumentation = < T extends Transaction > (
18- startTransaction : ( context : TransactionContext ) => T | undefined ,
19- startTransactionOnPageLoad ?: boolean ,
20- startTransactionOnLocationChange ?: boolean ,
21- ) => void ;
1+ import { captureException } from '@sentry/browser' ;
2+ import {
3+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
4+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ,
5+ getActiveSpan ,
6+ getRootSpan ,
7+ spanToJSON ,
8+ } from '@sentry/core' ;
9+ import type { Span , SpanAttributes , TransactionContext , TransactionSource } from '@sentry/types' ;
2210
2311// The following type is an intersection of the Route type from VueRouter v2, v3, and v4.
2412// This is not great, but kinda necessary to make it work with all versions at the same time.
@@ -43,57 +31,18 @@ interface VueRouter {
4331 beforeEach : ( fn : ( to : Route , from : Route , next ?: ( ) => void ) => void ) => void ;
4432}
4533
46- /**
47- * Creates routing instrumentation for Vue Router v2, v3 and v4
48- *
49- * You can optionally pass in an options object with the available option:
50- * * `routeLabel`: Set this to `route` to opt-out of using `route.name` for transaction names.
51- *
52- * @param router The Vue Router instance that is used
53- *
54- * @deprecated Use `browserTracingIntegration()` from `@sentry/vue` instead - this includes the vue router instrumentation.
55- */
56- export function vueRouterInstrumentation (
57- router : VueRouter ,
58- options : Partial < VueRouterInstrumationOptions > = { } ,
59- ) : VueRouterInstrumentation {
60- return (
61- startTransaction : ( context : TransactionContext ) => Transaction | undefined ,
62- startTransactionOnPageLoad : boolean = true ,
63- startTransactionOnLocationChange : boolean = true ,
64- ) => {
65- // We have to start the pageload transaction as early as possible (before the router's `beforeEach` hook
66- // is called) to not miss child spans of the pageload.
67- // We check that window & window.location exists in order to not run this code in SSR environments.
68- if ( startTransactionOnPageLoad && WINDOW && WINDOW . location ) {
69- startTransaction ( {
70- name : WINDOW . location . pathname ,
71- op : 'pageload' ,
72- attributes : {
73- [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.pageload.vue' ,
74- [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] : 'url' ,
75- } ,
76- } ) ;
77- }
78-
79- instrumentVueRouter (
80- router ,
81- {
82- routeLabel : options . routeLabel || 'name' ,
83- instrumentNavigation : startTransactionOnLocationChange ,
84- instrumentPageLoad : startTransactionOnPageLoad ,
85- } ,
86- startTransaction ,
87- ) ;
88- } ;
89- }
90-
9134/**
9235 * Instrument the Vue router to create navigation spans.
9336 */
9437export function instrumentVueRouter (
9538 router : VueRouter ,
9639 options : {
40+ /**
41+ * What to use for route labels.
42+ * By default, we use route.name (if set) and else the path.
43+ *
44+ * Default: 'name'
45+ */
9746 routeLabel : 'name' | 'path' ;
9847 instrumentPageLoad : boolean ;
9948 instrumentNavigation : boolean ;
@@ -139,17 +88,16 @@ export function instrumentVueRouter(
13988 }
14089
14190 if ( options . instrumentPageLoad && isPageLoadNavigation ) {
142- // eslint-disable-next-line deprecation/deprecation
143- const pageloadTransaction = getActiveTransaction ( ) ;
144- if ( pageloadTransaction ) {
145- const existingAttributes = spanToJSON ( pageloadTransaction ) . data || { } ;
91+ const activeRootSpan = getActiveRootSpan ( ) ;
92+ if ( activeRootSpan ) {
93+ const existingAttributes = spanToJSON ( activeRootSpan ) . data || { } ;
14694 if ( existingAttributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] !== 'custom' ) {
147- pageloadTransaction . updateName ( transactionName ) ;
148- pageloadTransaction . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , transactionSource ) ;
95+ activeRootSpan . updateName ( transactionName ) ;
96+ activeRootSpan . setAttribute ( SEMANTIC_ATTRIBUTE_SENTRY_SOURCE , transactionSource ) ;
14997 }
15098 // Set router attributes on the existing pageload transaction
151- // This will the origin, and add params & query attributes
152- pageloadTransaction . setAttributes ( {
99+ // This will override the origin, and add params & query attributes
100+ activeRootSpan . setAttributes ( {
153101 ...attributes ,
154102 [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] : 'auto.pageload.vue' ,
155103 } ) ;
@@ -158,6 +106,7 @@ export function instrumentVueRouter(
158106
159107 if ( options . instrumentNavigation && ! isPageLoadNavigation ) {
160108 attributes [ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE ] = transactionSource ;
109+ attributes [ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ] = 'auto.navigation.vue' ;
161110 startNavigationSpanFn ( {
162111 name : transactionName ,
163112 op : 'navigation' ,
@@ -173,3 +122,17 @@ export function instrumentVueRouter(
173122 }
174123 } ) ;
175124}
125+
126+ function getActiveRootSpan ( ) : Span | undefined {
127+ const span = getActiveSpan ( ) ;
128+ const rootSpan = span ? getRootSpan ( span ) : undefined ;
129+
130+ if ( ! rootSpan ) {
131+ return undefined ;
132+ }
133+
134+ const op = spanToJSON ( rootSpan ) . op ;
135+
136+ // Only use this root span if it is a pageload or navigation span
137+ return op === 'navigation' || op === 'pageload' ? rootSpan : undefined ;
138+ }
0 commit comments