-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathrouter.ts
103 lines (92 loc) · 3.44 KB
/
router.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { captureException } from '@sentry/browser';
import { Transaction, TransactionContext, TransactionSource } from '@sentry/types';
export type VueRouterInstrumentation = <T extends Transaction>(
startTransaction: (context: TransactionContext) => T | undefined,
startTransactionOnPageLoad?: boolean,
startTransactionOnLocationChange?: boolean,
) => void;
// The following type is an intersection of the Route type from VueRouter v2, v3, and v4.
// This is not great, but kinda necessary to make it work with all versions at the same time.
export type Route = {
/** Unparameterized URL */
path: string;
/**
* Query params (keys map to null when there is no value associated, e.g. "?foo" and to an array when there are
* multiple query params that have the same key, e.g. "?foo&foo=bar")
*/
query: Record<string, string | null | (string | null)[]>;
/** Route name (VueRouter provides a way to give routes individual names) */
name?: string | symbol | null | undefined;
/** Evaluated parameters */
params: Record<string, string | string[]>;
/** All the matched route objects as defined in VueRouter constructor */
matched: { path: string }[];
};
interface VueRouter {
onError: (fn: (err: Error) => void) => void;
beforeEach: (fn: (to: Route, from: Route, next: () => void) => void) => void;
}
/**
* Creates routing instrumentation for Vue Router v2
*
* @param router The Vue Router instance that is used
*/
export function vueRouterInstrumentation(router: VueRouter): VueRouterInstrumentation {
return (
startTransaction: (context: TransactionContext) => Transaction | undefined,
startTransactionOnPageLoad: boolean = true,
startTransactionOnLocationChange: boolean = true,
) => {
router.onError(error => captureException(error));
router.beforeEach((to, from, next) => {
// According to docs we could use `from === VueRouter.START_LOCATION` but I couldnt get it working for Vue 2
// https://router.vuejs.org/api/#router-start-location
// https://next.router.vuejs.org/api/#start-location
// from.name:
// - Vue 2: null
// - Vue 3: undefined
// hence only '==' instead of '===', because `undefined == null` evaluates to `true`
const isPageLoadNavigation = from.name == null && from.matched.length === 0;
const tags = {
'routing.instrumentation': 'vue-router',
};
const data = {
params: to.params,
query: to.query,
};
// Determine a name for the routing transaction and where that name came from
let transactionName: string = to.path;
let transactionSource: TransactionSource = 'url';
if (to.name) {
transactionName = to.name.toString();
transactionSource = 'custom';
} else if (to.matched[0] && to.matched[0].path) {
transactionName = to.matched[0].path;
transactionSource = 'route';
}
if (startTransactionOnPageLoad && isPageLoadNavigation) {
startTransaction({
name: transactionName,
op: 'pageload',
tags,
data,
metadata: {
source: transactionSource,
},
});
}
if (startTransactionOnLocationChange && !isPageLoadNavigation) {
startTransaction({
name: transactionName,
op: 'navigation',
tags,
data,
metadata: {
source: transactionSource,
},
});
}
next();
});
};
}