Skip to content
Merged
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
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,28 @@

- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott

- **feat(vue): Add TanStack Router integration ([#18359](https://github.com/getsentry/sentry-javascript/pull/18359))**

The `@sentry/vue` package now includes support for TanStack Router. Use `tanstackRouterBrowserTracingIntegration` to automatically instrument pageload and navigation transactions with parameterized routes:

```javascript
import { createApp } from 'vue';
import { createRouter } from '@tanstack/vue-router';
import * as Sentry from '@sentry/vue';
import { tanstackRouterBrowserTracingIntegration } from '@sentry/vue/tanstackrouter';

const router = createRouter({
// your router config
});

Sentry.init({
app,
dsn: '__PUBLIC_DSN__',
integrations: [tanstackRouterBrowserTracingIntegration(router)],
tracesSampleRate: 1.0,
});
```

- **feat(nextjs): Add tree-shaking configuration to `webpack` build config ([#18359](https://github.com/getsentry/sentry-javascript/pull/18359))**

- **feat(replay): Add Request body with `attachRawBodyFromRequest` option ([#18501](https://github.com/getsentry/sentry-javascript/pull/18501))**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@sentry:registry=http://127.0.0.1:4873
@sentry-internal:registry=http://127.0.0.1:4873
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Vue TanStack Router E2E Test App

E2E test application for `@sentry/vue` with TanStack Router integration.

## Getting Started

To run this application:

```bash
pnpm install
pnpm dev
```

## Building For Production

To build this application for production:

```bash
pnpm build
```

## Running Tests

To run E2E tests:

```bash
pnpm test:build # Install deps and build
pnpm test:assert # Run Playwright tests
```

## Routing

This project uses [TanStack Router](https://tanstack.com/router) for Vue.js. The router is set up with code-based routing in the `./src/main.ts` file.

### Routes

- `/` - Home page with navigation links
- `/posts/$postId` - Post detail page with parameterized route

### Sentry Integration

The app demonstrates:

- TanStack Router browser tracing integration
- Pageload transaction tracking with parameterized routes
- Navigation transaction tracking
- Route parameter extraction and span attribution

## Testing

The E2E tests verify:

1. Pageload transactions are created with correct route parameters
2. Navigation transactions are properly instrumented
3. Route parameters are captured in transaction data
4. Sentry origins are correctly set for Vue TanStack Router

## Learn More

- [TanStack Router Documentation](https://tanstack.com/router)
- [Sentry Vue SDK](https://docs.sentry.io/platforms/javascript/guides/vue/)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Vue TanStack Router E2E Test App" />
<title>Vue TanStack Router - Sentry E2E Tests</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "vue-tanstack-router",
"private": true,
"type": "module",
"scripts": {
"build": "vite build",
"clean": "npx rimraf node_modules pnpm-lock.yaml dist",
"dev": "vite",
"start": "vite preview",
"preview": "vite preview",
"test:prod": "TEST_ENV=production playwright test",
"test:build": "pnpm install && pnpm build",
"test:assert": "pnpm test:prod"
},
"dependencies": {
"@sentry/vue": "latest || *",
"@tanstack/vue-router": "^1.64.0",
"vue": "^3.4.15"
},
"devDependencies": {
"@playwright/test": "~1.56.0",
"@sentry-internal/test-utils": "link:../../../test-utils",
"@tsconfig/node20": "^20.1.2",
"@types/node": "^18.19.1",
"@vitejs/plugin-vue": "^5.0.3",
"@vue/tsconfig": "^0.5.1",
"typescript": "~5.3.0",
"vite": "^5.4.11"
},
"volta": {
"extends": "../../package.json"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getPlaywrightConfig } from '@sentry-internal/test-utils';

const config = getPlaywrightConfig({
startCommand: 'pnpm preview --port 4173',
port: 4173,
});

export default config;
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/posts/$postId" :params="{ postId: '1' }">Post 1</Link>
</li>
<li>
<Link to="/posts/$postId" :params="{ postId: '2' }" id="nav-link"> Post 2 </Link>
</li>
</ul>
</nav>
<hr />
<Outlet />
</div>
</template>

<script setup lang="ts">
import { Link, Outlet } from '@tanstack/vue-router';
</script>

<style scoped>
nav ul {
list-style: none;
padding: 0;
display: flex;
gap: 1rem;
}

nav li {
display: inline;
}

nav a {
color: #42b983;
text-decoration: none;
}

nav a:hover {
text-decoration: underline;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template>
<div class="home">
<h1>Vue + TanStack Router</h1>
<p>Welcome to the Sentry E2E Test App!</p>
</div>
</template>

<style scoped>
.home {
margin: 2rem 0;
}

h1 {
color: #42b983;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div>
<h2>Post View</h2>
<p>Post ID: {{ params.postId }}</p>
</div>
</template>

<script setup lang="ts">
import { useParams } from '@tanstack/vue-router';

const params = useParams({ from: '/posts/$postId' });
</script>

<style scoped>
h2 {
color: #42b983;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { createApp } from 'vue';
import { RouterProvider, createRoute, createRootRoute, createRouter } from '@tanstack/vue-router';
import * as Sentry from '@sentry/vue';
import { tanstackRouterBrowserTracingIntegration } from '@sentry/vue/tanstackrouter';

import App from './App.vue';
import HomeView from './HomeView.vue';
import PostView from './PostView.vue';

const rootRoute = createRootRoute({
component: App,
});

const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/',
component: HomeView,
});

const postsRoute = createRoute({
getParentRoute: () => rootRoute,
path: 'posts/',
});

const postIdRoute = createRoute({
getParentRoute: () => postsRoute,
path: '$postId',
loader: async ({ params }) => {
return Sentry.startSpan({ name: `loading-post-${params.postId}` }, async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
});
},
component: PostView,
});

const routeTree = rootRoute.addChildren([indexRoute, postsRoute.addChildren([postIdRoute])]);

const router = createRouter({
routeTree,
defaultPreload: 'intent',
});

declare module '@tanstack/vue-router' {
interface Register {
router: typeof router;
}
}

const app = createApp(RouterProvider, { router });

Sentry.init({
app,
dsn: import.meta.env.PUBLIC_E2E_TEST_DSN,
debug: true,
environment: 'qa', // dynamic sampling bias to keep transactions
integrations: [tanstackRouterBrowserTracingIntegration(router)],
release: 'e2e-test',
tunnel: 'http://localhost:3031/', // proxy server
tracesSampleRate: 1.0,
});

app.mount('#app');
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { startEventProxyServer } from '@sentry-internal/test-utils';

startEventProxyServer({
port: 3031,
proxyServerName: 'vue-tanstack-router',
});
Loading
Loading