Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script setup lang="ts">
import * as Sentry from '@sentry/nuxt';
import { onMounted, ref } from 'vue';

const route = ref<string>();

onMounted(() => {
route.value = Sentry.resolveCurrentRoute() ?? 'unresolved';
});
</script>

<template>
<div id="resolved-route">{{ route }}</div>
</template>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { expect, test } from '@playwright/test';

// The route provider reads the router off the Nuxt app, so this fails if the plugin never registers it.
test('resolves the parameterized route through the route provider', async ({ page }) => {
await page.goto('/route-provider/123');

await expect(page.locator('#resolved-route')).toHaveText('/route-provider/:id()');
});
23 changes: 22 additions & 1 deletion packages/nuxt/src/runtime/plugins/sentry.client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { getClient, GLOBAL_OBJ } from '@sentry/core';
import { browserTracingIntegration, vueIntegration } from '@sentry/vue';
import {
browserTracingIntegration,
createVueRouteProvider,
getRouteProvider,
setRouteProvider,
vueIntegration,
} from '@sentry/vue';
import { defineNuxtPlugin, isNuxtError } from 'nuxt/app';
import type { GlobalObjWithIntegrationOptions } from '../../client/vueIntegration';
import { reportNuxtError } from '../utils';
Expand Down Expand Up @@ -28,13 +34,28 @@ interface VueRouter {
beforeEach: (fn: (to: Route, from: Route, next?: () => void) => void) => void;
}

type VueRouteProviderRouter = ReturnType<Parameters<typeof createVueRouteProvider>[0]>;

// Tree-shakable guard to remove all code related to tracing
declare const __SENTRY_TRACING__: boolean;

export default defineNuxtPlugin({
name: 'sentry-client-integrations',
dependsOn: ['sentry-client-config'],
async setup(nuxtApp) {
// Registered outside the tracing guard, because route parameterization should not depend on
// tracing: anything that needs a route name (bfcache metrics, web vitals) can resolve one even
// when tracing is tree-shaken away. Nuxt installs the router before its plugins run, so unlike
// `@sentry/vue` this can read it straight off `nuxtApp`.
const client = getClient();
// A `routeProvider` passed to `Sentry.init` is the user's choice, so it is left in place.
if (client && '$router' in nuxtApp && !getRouteProvider(client)) {
setRouteProvider(
createVueRouteProvider(() => nuxtApp.$router as VueRouteProviderRouter),
client,
);
}
Comment thread
logaretm marked this conversation as resolved.

// This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false", in which case everything inside
// will get tree-shaken away
if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) {
Expand Down
Loading