From 95a5f4886ea2626eeaf7069cf59c5da3a5537233 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 3 Mar 2023 13:23:56 +0100 Subject: [PATCH] feat(vue): Allow to set `routeLabel: 'path'` to opt-out of using name (#7326) --- packages/vue/src/router.ts | 20 +++++++++-- packages/vue/test/router.test.ts | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 2 deletions(-) diff --git a/packages/vue/src/router.ts b/packages/vue/src/router.ts index 2bdb088a24cf..617cc516e421 100644 --- a/packages/vue/src/router.ts +++ b/packages/vue/src/router.ts @@ -3,6 +3,16 @@ import type { Transaction, TransactionContext, TransactionSource } from '@sentry import { getActiveTransaction } from './tracing'; +interface VueRouterInstrumationOptions { + /** + * What to use for route labels. + * By default, we use route.name (if set) and else the path. + * + * Default: 'name' + */ + routeLabel: 'name' | 'path'; +} + export type VueRouterInstrumentation = ( startTransaction: (context: TransactionContext) => T | undefined, startTransactionOnPageLoad?: boolean, @@ -35,9 +45,15 @@ interface VueRouter { /** * Creates routing instrumentation for Vue Router v2, v3 and v4 * + * You can optionally pass in an options object with the available option: + * * `routeLabel`: Set this to `route` to opt-out of using `route.name` for transaction names. + * * @param router The Vue Router instance that is used */ -export function vueRouterInstrumentation(router: VueRouter): VueRouterInstrumentation { +export function vueRouterInstrumentation( + router: VueRouter, + options: Partial = {}, +): VueRouterInstrumentation { return ( startTransaction: (context: TransactionContext) => Transaction | undefined, startTransactionOnPageLoad: boolean = true, @@ -81,7 +97,7 @@ export function vueRouterInstrumentation(router: VueRouter): VueRouterInstrument // 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) { + if (to.name && options.routeLabel !== 'path') { transactionName = to.name.toString(); transactionSource = 'custom'; } else if (to.matched[0] && to.matched[0].path) { diff --git a/packages/vue/test/router.test.ts b/packages/vue/test/router.test.ts index 65482f80f10b..2e8fd9a01d0d 100644 --- a/packages/vue/test/router.test.ts +++ b/packages/vue/test/router.test.ts @@ -169,6 +169,68 @@ describe('vueRouterInstrumentation()', () => { }, ); + it('allows to configure routeLabel=path', () => { + // create instrumentation + const instrument = vueRouterInstrumentation(mockVueRouter, { routeLabel: 'path' }); + + // instrument + instrument(mockStartTransaction, true, true); + + // check + const beforeEachCallback = mockVueRouter.beforeEach.mock.calls[0][0]; + + const from = testRoutes.normalRoute1; + const to = testRoutes.namedRoute; + beforeEachCallback(to, from, mockNext); + + // first startTx call happens when the instrumentation is initialized (for pageloads) + expect(mockStartTransaction).toHaveBeenLastCalledWith({ + name: '/login', + metadata: { + source: 'route', + }, + data: { + params: to.params, + query: to.query, + }, + op: 'navigation', + tags: { + 'routing.instrumentation': 'vue-router', + }, + }); + }); + + it('allows to configure routeLabel=name', () => { + // create instrumentation + const instrument = vueRouterInstrumentation(mockVueRouter, { routeLabel: 'name' }); + + // instrument + instrument(mockStartTransaction, true, true); + + // check + const beforeEachCallback = mockVueRouter.beforeEach.mock.calls[0][0]; + + const from = testRoutes.normalRoute1; + const to = testRoutes.namedRoute; + beforeEachCallback(to, from, mockNext); + + // first startTx call happens when the instrumentation is initialized (for pageloads) + expect(mockStartTransaction).toHaveBeenLastCalledWith({ + name: 'login-screen', + metadata: { + source: 'custom', + }, + data: { + params: to.params, + query: to.query, + }, + op: 'navigation', + tags: { + 'routing.instrumentation': 'vue-router', + }, + }); + }); + it("doesn't overwrite a pageload transaction name it was set to custom before the router resolved the route", () => { const mockedTxn = { setName: jest.fn(),