MCPcopy Create free account
hub / github.com/getsentry/sentry-javascript / instrumentVueRouter

Function instrumentVueRouter

packages/vue/src/router.ts:41–141  ·  view source on GitHub ↗
(
  router: VueRouter,
  options: {
    /**
     * What to use for route labels.
     * By default, we use route.name (if set) and else the path.
     *
     * Default: 'name'
     */
    routeLabel: 'name' | 'path';
    instrumentPageLoad: boolean;
    instrumentNavigation: boolean;
  },
  startNavigationSpanFn: (context: StartSpanOptions) => void,
)

Source from the content-addressed store, hash-verified

39 * Instrument the Vue router to create navigation spans.
40 */
41export function instrumentVueRouter(
42 router: VueRouter,
43 options: {
44 /**
45 * What to use for route labels.
46 * By default, we use route.name (if set) and else the path.
47 *
48 * Default: 'name'
49 */
50 routeLabel: 'name' | 'path';
51 instrumentPageLoad: boolean;
52 instrumentNavigation: boolean;
53 },
54 startNavigationSpanFn: (context: StartSpanOptions) => void,
55): void {
56 let hasHandledFirstPageLoad = false;
57
58 // Detect Vue Router 3 by checking for the `mode` property which only exists in VR3.
59 // Vue Router 4+ uses `options.history` instead and does not expose `mode`.
60 const isLegacyRouter = 'mode' in router;
61
62 router.onError(error => captureException(error, { mechanism: { handled: false } }));
63
64 // Use rest params to capture `next` without declaring it as a named parameter.
65 // This keeps Function.length === 2, which tells Vue Router 4+/5+ to use the
66 // modern return-based resolution (no deprecation warning in Vue Router 5.0.3+).
67 router.beforeEach((to: Route, _from: Route, ...rest: [(() => void)?]) => {
68 // We avoid trying to re-fetch the page load span when we know we already handled it the first time
69 const activePageLoadSpan = !hasHandledFirstPageLoad ? getActivePageLoadSpan() : undefined;
70
71 const attributes: SpanAttributes = {};
72
73 for (const key of Object.keys(to.params)) {
74 attributes[`url.path.parameter.${key}`] = to.params[key];
75 attributes[`params.${key}`] = to.params[key]; // params.[key] is an alias
76 }
77 for (const key of Object.keys(to.query)) {
78 const value = to.query[key];
79 if (value) {
80 attributes[`query.${key}`] = value;
81 }
82 }
83
84 // Determine a name for the routing transaction and where that name came from
85 let spanName: string = to.path;
86 let transactionSource: TransactionSource = 'url';
87 if (to.name && options.routeLabel !== 'path') {
88 spanName = to.name.toString();
89 transactionSource = 'custom';
90 } else if (to.matched.length > 0) {
91 const lastIndex = to.matched.length - 1;
92 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
93 spanName = to.matched[lastIndex]!.path;
94 transactionSource = 'route';
95 }
96
97 getCurrentScope().setTransactionName(spanName);
98

Callers 2

router.test.tsFile · 0.90
afterAllSetupFunction · 0.90

Calls 12

getCurrentScopeFunction · 0.90
spanToJSONFunction · 0.90
getActivePageLoadSpanFunction · 0.85
nextFunction · 0.85
beforeEachMethod · 0.80
setTransactionNameMethod · 0.80
keysMethod · 0.65
toStringMethod · 0.65
updateNameMethod · 0.65
setAttributeMethod · 0.65
setAttributesMethod · 0.65
captureExceptionFunction · 0.50

Tested by

no test coverage detected