Skip to content

Commit df5fb86

Browse files
committed
feat(vue): Allow to set routeLabel: 'path' to opt-out of using name
1 parent 45158f4 commit df5fb86

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

packages/vue/src/router.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { captureException, WINDOW } from '@sentry/browser';
1+
import { captureException, getCurrentHub, WINDOW } from '@sentry/browser';
22
import type { Transaction, TransactionContext, TransactionSource } from '@sentry/types';
33

44
import { getActiveTransaction } from './tracing';
5+
import type { Options } from './types';
56

67
export type VueRouterInstrumentation = <T extends Transaction>(
78
startTransaction: (context: TransactionContext) => T | undefined,
@@ -38,6 +39,9 @@ interface VueRouter {
3839
* @param router The Vue Router instance that is used
3940
*/
4041
export function vueRouterInstrumentation(router: VueRouter): VueRouterInstrumentation {
42+
const client = getCurrentHub().getClient();
43+
const options = ((client && client.getOptions()) || {}) as Partial<Options>;
44+
4145
return (
4246
startTransaction: (context: TransactionContext) => Transaction | undefined,
4347
startTransactionOnPageLoad: boolean = true,
@@ -81,7 +85,7 @@ export function vueRouterInstrumentation(router: VueRouter): VueRouterInstrument
8185
// Determine a name for the routing transaction and where that name came from
8286
let transactionName: string = to.path;
8387
let transactionSource: TransactionSource = 'url';
84-
if (to.name) {
88+
if (to.name && options.routeLabel !== 'path') {
8589
transactionName = to.name.toString();
8690
transactionSource = 'custom';
8791
} else if (to.matched[0] && to.matched[0].path) {

packages/vue/src/sdk.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const DEFAULT_CONFIG: Options = {
1616
hooks: DEFAULT_HOOKS,
1717
timeout: 2000,
1818
trackComponents: false,
19+
routeLabel: 'name',
1920
_metadata: {
2021
sdk: {
2122
name: 'sentry.javascript.vue',

packages/vue/src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ export interface Options extends TracingOptions, BrowserOptions {
4646

4747
/** {@link TracingOptions} */
4848
tracingOptions?: Partial<TracingOptions>;
49+
50+
/**
51+
* What to use for route labels.
52+
* By default, we use route.name (if set) and else the path.
53+
*
54+
* Default: 'name'
55+
*/
56+
routeLabel: 'name' | 'path';
4957
}
5058

5159
/** Vue specific configuration for Tracing Integration */

packages/vue/test/errorHandler.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ const testHarness = ({
368368
tracingOptions: {},
369369
trackComponents: [],
370370
timeout: 0,
371+
routeLabel: 'name',
371372
hooks: [] as Operation[],
372373
};
373374

packages/vue/test/router.test.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import * as SentryBrowser from '@sentry/browser';
22
import type { Transaction } from '@sentry/types';
3+
import { createApp } from 'vue';
34

4-
import { vueRouterInstrumentation } from '../src';
5+
import { init, vueRouterInstrumentation } from '../src';
56
import type { Route } from '../src/router';
67
import * as vueTracing from '../src/tracing';
78

@@ -169,6 +170,51 @@ describe('vueRouterInstrumentation()', () => {
169170
},
170171
);
171172

173+
it('allows to configure routeLabel=path', () => {
174+
// Need to setup a proper client with options etc.
175+
const app = createApp({
176+
template: '<div>hello</div>',
177+
});
178+
const el = document.createElement('div');
179+
180+
init({
181+
app,
182+
defaultIntegrations: false,
183+
routeLabel: 'path',
184+
});
185+
186+
app.mount(el);
187+
188+
// create instrumentation
189+
const instrument = vueRouterInstrumentation(mockVueRouter);
190+
191+
// instrument
192+
instrument(mockStartTransaction, true, true);
193+
194+
// check
195+
const beforeEachCallback = mockVueRouter.beforeEach.mock.calls[0][0];
196+
197+
const from = testRoutes.normalRoute1;
198+
const to = testRoutes.namedRoute;
199+
beforeEachCallback(to, from, mockNext);
200+
201+
// first startTx call happens when the instrumentation is initialized (for pageloads)
202+
expect(mockStartTransaction).toHaveBeenLastCalledWith({
203+
name: '/login',
204+
metadata: {
205+
source: 'route',
206+
},
207+
data: {
208+
params: to.params,
209+
query: to.query,
210+
},
211+
op: 'navigation',
212+
tags: {
213+
'routing.instrumentation': 'vue-router',
214+
},
215+
});
216+
});
217+
172218
it("doesn't overwrite a pageload transaction name it was set to custom before the router resolved the route", () => {
173219
const mockedTxn = {
174220
setName: jest.fn(),

0 commit comments

Comments
 (0)