diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/.gitignore b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/.gitignore similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/.gitignore rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/.gitignore diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/.npmrc b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/.npmrc similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/.npmrc rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/.npmrc diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/README.md b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/README.md similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/README.md rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/README.md diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json similarity index 93% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/package.json rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json index f961077f9977..344eba5705fd 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/package.json @@ -1,5 +1,5 @@ { - "name": "sveltekit-2-svelte-5", + "name": "sveltekit-2.5.0-twp", "version": "0.0.1", "private": true, "scripts": { @@ -22,7 +22,7 @@ "@sentry-internal/test-utils": "link:../../../test-utils", "@sentry/core": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", - "@sveltejs/kit": "^2.0.0", + "@sveltejs/kit": "2.5.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "svelte": "^5.0.0-next.115", "svelte-check": "^3.6.0", diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/playwright.config.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/playwright.config.mjs similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/playwright.config.mjs rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/playwright.config.mjs diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/app.d.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/app.d.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/app.d.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/app.d.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/app.html b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/app.html similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/app.html rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/app.html diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.client.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/hooks.client.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.client.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/hooks.server.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/hooks.server.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/+layout.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/+layout.svelte similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/+layout.svelte rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/+layout.svelte diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/+page.svelte similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/+page.svelte rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/+page.svelte diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/errors/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/errors/+page.server.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/errors/+page.server.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/errors/+page.server.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/errors/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/errors/+page.svelte similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/src/routes/errors/+page.svelte rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/src/routes/errors/+page.svelte diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/start-event-proxy.mjs b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/start-event-proxy.mjs similarity index 72% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/start-event-proxy.mjs rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/start-event-proxy.mjs index 01e1095d6956..1ba4492f150a 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/start-event-proxy.mjs +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/start-event-proxy.mjs @@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils'; startEventProxyServer({ port: 3031, - proxyServerName: 'sveltekit-2-twp', + proxyServerName: 'sveltekit-2.5.0-twp', }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/static/favicon.png b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/static/favicon.png similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/static/favicon.png rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/static/favicon.png diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/svelte.config.js similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/svelte.config.js rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/svelte.config.js diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tests/errors.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/errors.test.ts similarity index 92% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tests/errors.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/errors.test.ts index 0e16a2588982..984af2ec23a6 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tests/errors.test.ts +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/errors.test.ts @@ -2,11 +2,11 @@ import { expect, test } from '@playwright/test'; import { waitForError } from '@sentry-internal/test-utils'; test('errors on frontend and backend are connected by the same trace', async ({ page }) => { - const clientErrorPromise = waitForError('sveltekit-2-twp', evt => { + const clientErrorPromise = waitForError('sveltekit-2.5.0-twp', evt => { return evt.exception?.values?.[0].value === 'Client Error'; }); - const serverErrorPromise = waitForError('sveltekit-2-twp', evt => { + const serverErrorPromise = waitForError('sveltekit-2.5.0-twp', evt => { return evt.exception?.values?.[0].value === 'No search query provided'; }); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/sdk.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/sdk.test.ts new file mode 100644 index 000000000000..c1131913d057 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/sdk.test.ts @@ -0,0 +1,16 @@ +import { expect, test } from '@playwright/test'; + +test.describe('SDK-internal behavior', () => { + test('Injects fetch proxy script for SvelteKit<2.16.0', async ({ page }) => { + await page.goto('/'); + + const sentryCarrier = await page.evaluate('typeof window.__SENTRY__'); + const proxyHandle = await page.evaluate('typeof window._sentryFetchProxy'); + + // sanity check + expect(sentryCarrier).toBe('object'); + + // fetch proxy script ran + expect(proxyHandle).toBe('function'); + }); +}); diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tests/tracing.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/tracing.test.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tests/tracing.test.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tests/tracing.test.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tsconfig.json b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tsconfig.json similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/tsconfig.json rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/tsconfig.json diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2-twp/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/vite.config.ts similarity index 100% rename from dev-packages/e2e-tests/test-applications/sveltekit-2-twp/vite.config.ts rename to dev-packages/e2e-tests/test-applications/sveltekit-2.5.0-twp/vite.config.ts diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json index f02253198aaa..91bc78290199 100644 --- a/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/package.json @@ -23,7 +23,7 @@ "@sentry/core": "latest || *", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-node": "^2.0.0", - "@sveltejs/kit": "^2.5.0", + "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "svelte": "^4.2.8", "svelte-check": "^3.6.0", diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/sdk.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/sdk.test.ts new file mode 100644 index 000000000000..f35a81e91238 --- /dev/null +++ b/dev-packages/e2e-tests/test-applications/sveltekit-2/tests/sdk.test.ts @@ -0,0 +1,16 @@ +import { expect, test } from '@playwright/test'; +import { waitForInitialPageload } from './utils'; + +test.describe('SDK-internal behavior', () => { + test("Doesn't inject fetch proxy script for SvelteKit>=2.16.0", async ({ page }) => { + await waitForInitialPageload(page, { route: '/' }); + const sentryCarrier = await page.evaluate('typeof window.__SENTRY__'); + const proxyHandle = await page.evaluate('typeof window._sentryFetchProxy'); + + // sanity check + expect(sentryCarrier).toBe('object'); + + // fetch proxy script didn't run + expect(proxyHandle).toBe('undefined'); + }); +}); diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json index 077988a47bd1..94cb6fd32c39 100644 --- a/packages/sveltekit/package.json +++ b/packages/sveltekit/package.json @@ -9,9 +9,7 @@ "engines": { "node": ">=18" }, - "files": [ - "/build" - ], + "files": ["/build"], "main": "build/cjs/index.server.js", "module": "build/esm/index.server.js", "browser": "build/esm/index.client.js", diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts index d0e5e2e689f1..9bb9de9ce394 100644 --- a/packages/sveltekit/src/server/handle.ts +++ b/packages/sveltekit/src/server/handle.ts @@ -93,10 +93,10 @@ export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean } * ``` */ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle { - const options: Required = { - handleUnknownRoutes: false, - injectFetchProxyScript: true, - ...handlerOptions, + const { handleUnknownRoutes, ...rest } = handlerOptions ?? {}; + const options = { + handleUnknownRoutes: handleUnknownRoutes ?? false, + ...rest, }; const sentryRequestHandler: Handle = input => { @@ -131,12 +131,24 @@ export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle { async function instrumentHandle( { event, resolve }: Parameters[0], - options: Required, + options: SentryHandleOptions, ): Promise { if (!event.route?.id && !options.handleUnknownRoutes) { return resolve(event); } + // caching the result of the version check in `options.injectFetchProxyScript` + // to avoid doing the dynamic import on every request + if (options.injectFetchProxyScript == null) { + try { + // @ts-expect-error - the dynamic import is fine here + const { VERSION } = await import('@sveltejs/kit'); + options.injectFetchProxyScript = isFetchProxyRequired(VERSION); + } catch { + options.injectFetchProxyScript = true; + } + } + const routeName = `${event.request.method} ${event.route?.id || event.url.pathname}`; if (getIsolationScope() !== getDefaultIsolationScope()) { @@ -161,7 +173,7 @@ async function instrumentHandle( normalizedRequest: winterCGRequestToRequestData(event.request.clone()), }); const res = await resolve(event, { - transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript }), + transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }), }); if (span) { setHttpStatus(span, res.status); @@ -177,3 +189,19 @@ async function instrumentHandle( await flushIfServerless(); } } + +/** + * We only need to inject the fetch proxy script for SvelteKit versions < 2.16.0. + * Exported only for testing. + */ +export function isFetchProxyRequired(version: string): boolean { + try { + const [major, minor] = version.trim().replace(/-.*/, '').split('.').map(Number); + if (major != null && minor != null && (major > 2 || (major === 2 && minor >= 16))) { + return false; + } + } catch { + // ignore + } + return true; +} diff --git a/packages/sveltekit/test/server/handle.test.ts b/packages/sveltekit/test/server/handle.test.ts index f6556f8ddcea..150f59ae9bc8 100644 --- a/packages/sveltekit/test/server/handle.test.ts +++ b/packages/sveltekit/test/server/handle.test.ts @@ -14,7 +14,7 @@ import type { Handle } from '@sveltejs/kit'; import { redirect } from '@sveltejs/kit'; import { vi } from 'vitest'; -import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, sentryHandle } from '../../src/server/handle'; +import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, isFetchProxyRequired, sentryHandle } from '../../src/server/handle'; import { getDefaultNodeClientOptions } from '../utils'; const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx'); @@ -462,3 +462,20 @@ describe('addSentryCodeToPage', () => { expect(transformed).not.toContain(``); }); }); + +describe('isFetchProxyRequired', () => { + it.each(['2.16.0', '2.16.1', '2.17.0', '3.0.0', '3.0.0-alpha.0'])( + 'returns false if the version is greater than or equal to 2.16.0 (%s)', + version => { + expect(isFetchProxyRequired(version)).toBe(false); + }, + ); + + it.each(['2.15.0', '2.15.1', '1.30.0', '1.0.0'])('returns true if the version is lower than 2.16.0 (%s)', version => { + expect(isFetchProxyRequired(version)).toBe(true); + }); + + it.each(['invalid', 'a.b.c'])('returns true for an invalid version (%s)', version => { + expect(isFetchProxyRequired(version)).toBe(true); + }); +});