diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
new file mode 100644
index 000000000000..bff793d5eae7
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.gitignore
@@ -0,0 +1,24 @@
+test-results
+node_modules
+
+# Output
+.output
+.vercel
+.netlify
+.wrangler
+/.svelte-kit
+/build
+
+# OS
+.DS_Store
+Thumbs.db
+
+# Env
+.env
+.env.*
+!.env.example
+!.env.test
+
+# Vite
+vite.config.js.timestamp-*
+vite.config.ts.timestamp-*
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
new file mode 100644
index 000000000000..070f80f05092
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/.npmrc
@@ -0,0 +1,2 @@
+@sentry:registry=http://127.0.0.1:4873
+@sentry-internal:registry=http://127.0.0.1:4873
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
new file mode 100644
index 000000000000..b5b295070b44
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/README.md
@@ -0,0 +1,38 @@
+# sv
+
+Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```bash
+# create a new project in the current directory
+npx sv create
+
+# create a new project in my-app
+npx sv create my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```bash
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
new file mode 100644
index 000000000000..51fe00136f06
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/package.json
@@ -0,0 +1,31 @@
+{
+ "name": "sveltekit-cloudflare-pages",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "wrangler pages dev ./.svelte-kit/cloudflare --port 4173",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "test:e2e": "playwright test",
+ "test": "pnpm run test:e2e",
+ "test:build": "pnpm install && pnpm build",
+ "test:assert": "pnpm run test:e2e"
+ },
+ "dependencies": {
+ "@sentry/sveltekit": "latest || *"
+ },
+ "devDependencies": {
+ "@playwright/test": "^1.45.3",
+ "@sveltejs/adapter-cloudflare": "^5.0.3",
+ "@sveltejs/kit": "^2.17.2",
+ "@sveltejs/vite-plugin-svelte": "^5.0.3",
+ "svelte": "^5.20.2",
+ "svelte-check": "^4.1.4",
+ "typescript": "^5.0.0",
+ "vite": "^6.1.1",
+ "wrangler": "3.105.0"
+ }
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
new file mode 100644
index 000000000000..18bda456025e
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/playwright.config.ts
@@ -0,0 +1,10 @@
+import { defineConfig } from '@playwright/test';
+
+export default defineConfig({
+ webServer: {
+ command: 'pnpm run build && pnpm run preview',
+ port: 4173,
+ },
+
+ testDir: 'tests',
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
new file mode 100644
index 000000000000..520c4217a10c
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.d.ts
@@ -0,0 +1,13 @@
+// See https://svelte.dev/docs/kit/types#app.d.ts
+// for information about these interfaces
+declare global {
+ namespace App {
+ // interface Error {}
+ // interface Locals {}
+ // interface PageData {}
+ // interface PageState {}
+ // interface Platform {}
+ }
+}
+
+export {};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html
new file mode 100644
index 000000000000..77a5ff52c923
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
new file mode 100644
index 000000000000..4dc12acebc45
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.client.ts
@@ -0,0 +1,8 @@
+import { env } from '$env/dynamic/public';
+import * as Sentry from '@sentry/sveltekit';
+
+Sentry.init({
+ dsn: env.PUBLIC_E2E_TEST_DSN,
+});
+
+export const handleError = Sentry.handleErrorWithSentry();
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
new file mode 100644
index 000000000000..d5067459d565
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/hooks.server.ts
@@ -0,0 +1,13 @@
+import { E2E_TEST_DSN } from '$env/static/private';
+import { handleErrorWithSentry, initCloudflareSentryHandle, sentryHandle } from '@sentry/sveltekit';
+import { sequence } from '@sveltejs/kit/hooks';
+
+export const handleError = handleErrorWithSentry();
+
+export const handle = sequence(
+ initCloudflareSentryHandle({
+ dsn: E2E_TEST_DSN,
+ tracesSampleRate: 1.0,
+ }),
+ sentryHandle(),
+);
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts
new file mode 100644
index 000000000000..3cbde33753a2
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.server.ts
@@ -0,0 +1,7 @@
+import type { PageServerLoad } from './$types';
+
+export const load: PageServerLoad = async function load() {
+ return {
+ message: 'From server load function.',
+ };
+};
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
new file mode 100644
index 000000000000..e17881ceaca9
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/src/routes/+page.svelte
@@ -0,0 +1,10 @@
+
+
+Welcome to SvelteKit
+Visit svelte.dev/docs/kit to read the documentation
+
+prerender test
+
+{data.message}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png
new file mode 100644
index 000000000000..825b9e65af7c
Binary files /dev/null and b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/static/favicon.png differ
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
new file mode 100644
index 000000000000..4e0314356cde
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/svelte.config.js
@@ -0,0 +1,21 @@
+import adapter from '@sveltejs/adapter-cloudflare';
+import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://svelte.dev/docs/kit/integrations
+ // for more information about preprocessors
+ preprocess: vitePreprocess(),
+
+ kit: {
+ // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
+ // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
+ // See https://svelte.dev/docs/kit/adapters for more information about adapters.
+ adapter: adapter(),
+ prerender: {
+ handleHttpError: 'ignore',
+ },
+ },
+};
+
+export default config;
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
new file mode 100644
index 000000000000..a67e4e7f299d
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tests/demo.test.ts
@@ -0,0 +1,6 @@
+import { expect, test } from '@playwright/test';
+
+test('home page has expected h1', async ({ page }) => {
+ await page.goto('/');
+ await expect(page.locator('h1')).toBeVisible();
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
new file mode 100644
index 000000000000..0b2d8865f4ef
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true,
+ "moduleResolution": "bundler"
+ }
+ // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
+ // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
new file mode 100644
index 000000000000..706faf25f2b5
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/vite.config.ts
@@ -0,0 +1,7 @@
+import { sentrySvelteKit } from '@sentry/sveltekit';
+import { sveltekit } from '@sveltejs/kit/vite';
+import { defineConfig } from 'vite';
+
+export default defineConfig({
+ plugins: [sentrySvelteKit({ autoUploadSourceMaps: false }), sveltekit()],
+});
diff --git a/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml
new file mode 100644
index 000000000000..d31d2fc7f225
--- /dev/null
+++ b/dev-packages/e2e-tests/test-applications/sveltekit-cloudflare-pages/wrangler.toml
@@ -0,0 +1,2 @@
+compatibility_date = "2024-12-17"
+compatibility_flags = ["nodejs_compat"]
diff --git a/packages/sveltekit/package.json b/packages/sveltekit/package.json
index ba1535d799de..3c39cb3093f0 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",
@@ -20,6 +18,10 @@
"./package.json": "./package.json",
".": {
"types": "./build/types/index.types.d.ts",
+ "worker": {
+ "import": "./build/esm/index.worker.js",
+ "require": "./build/cjs/index.worker.js"
+ },
"browser": {
"import": "./build/esm/index.client.js",
"require": "./build/cjs/index.client.js"
@@ -40,6 +42,7 @@
}
},
"dependencies": {
+ "@sentry/cloudflare": "9.1.0",
"@sentry/core": "9.1.0",
"@sentry/node": "9.1.0",
"@sentry/opentelemetry": "9.1.0",
diff --git a/packages/sveltekit/rollup.npm.config.mjs b/packages/sveltekit/rollup.npm.config.mjs
index b0a19e091ad8..ca0792cb4868 100644
--- a/packages/sveltekit/rollup.npm.config.mjs
+++ b/packages/sveltekit/rollup.npm.config.mjs
@@ -2,7 +2,14 @@ import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollu
export default makeNPMConfigVariants(
makeBaseNPMConfig({
- entrypoints: ['src/index.server.ts', 'src/index.client.ts', 'src/client/index.ts', 'src/server/index.ts'],
+ entrypoints: [
+ 'src/index.server.ts',
+ 'src/index.client.ts',
+ 'src/index.worker.ts',
+ 'src/client/index.ts',
+ 'src/server/index.ts',
+ 'src/worker/index.ts',
+ ],
packageSpecificConfig: {
external: ['$app/stores'],
output: {
diff --git a/packages/sveltekit/src/common/utils.ts b/packages/sveltekit/src/common/utils.ts
index 84b384861dff..1362ee82293c 100644
--- a/packages/sveltekit/src/common/utils.ts
+++ b/packages/sveltekit/src/common/utils.ts
@@ -1,5 +1,7 @@
import type { HttpError, Redirect } from '@sveltejs/kit';
+export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
+
export type SentryWrappedFlag = {
/**
* If this flag is set, we know that the load event was already wrapped once
diff --git a/packages/sveltekit/src/index.types.ts b/packages/sveltekit/src/index.types.ts
index 3ad8b728bb5f..bf2edbfb0a0f 100644
--- a/packages/sveltekit/src/index.types.ts
+++ b/packages/sveltekit/src/index.types.ts
@@ -4,6 +4,12 @@
export * from './client';
export * from './vite';
export * from './server';
+export * from './worker';
+
+// Use the ./server version of some functions that are also exported from ./worker
+export { sentryHandle } from './server';
+// Use the ./worker version of some functions that are also exported from ./server
+export { initCloudflareSentryHandle } from './worker';
import type { Client, Integration, Options, StackParser } from '@sentry/core';
import type { HandleClientError, HandleServerError } from '@sveltejs/kit';
diff --git a/packages/sveltekit/src/index.worker.ts b/packages/sveltekit/src/index.worker.ts
new file mode 100644
index 000000000000..016e36c8a289
--- /dev/null
+++ b/packages/sveltekit/src/index.worker.ts
@@ -0,0 +1,2 @@
+export * from './worker';
+// export * from './vite';
diff --git a/packages/sveltekit/src/server-common/handle.ts b/packages/sveltekit/src/server-common/handle.ts
new file mode 100644
index 000000000000..48167066c6d7
--- /dev/null
+++ b/packages/sveltekit/src/server-common/handle.ts
@@ -0,0 +1,208 @@
+import type { Span } from '@sentry/core';
+import {
+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+ continueTrace,
+ getCurrentScope,
+ getDefaultIsolationScope,
+ getIsolationScope,
+ getTraceMetaTags,
+ logger,
+ setHttpStatus,
+ startSpan,
+ winterCGRequestToRequestData,
+ withIsolationScope,
+} from '@sentry/core';
+import type { Handle, ResolveOptions } from '@sveltejs/kit';
+
+import { DEBUG_BUILD } from '../common/debug-build';
+import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
+
+export type SentryHandleOptions = {
+ /**
+ * Controls whether the SDK should capture errors and traces in requests that don't belong to a
+ * route defined in your SvelteKit application.
+ *
+ * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
+ *
+ * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
+ * scenarios, for instance if you registered other handlers that handle these requests.
+ * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
+ * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
+ * transactions that you still don't want to be sent to Sentry.
+ *
+ * @default false
+ */
+ handleUnknownRoutes?: boolean;
+
+ /**
+ * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
+ * of `fetch` calls in `load` functions.
+ *
+ * @default true
+ */
+ injectFetchProxyScript?: boolean;
+};
+
+export const FETCH_PROXY_SCRIPT = `
+ const f = window.fetch;
+ if(f){
+ window._sentryFetchProxy = function(...a){return f(...a)}
+ window.fetch = function(...a){return window._sentryFetchProxy(...a)}
+ }
+`;
+/**
+ * Adds Sentry tracing tags to the returned html page.
+ * Adds Sentry fetch proxy script to the returned html page if enabled in options.
+ *
+ * Exported only for testing
+ */
+export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }): NonNullable<
+ ResolveOptions['transformPageChunk']
+> {
+ return ({ html }) => {
+ const metaTags = getTraceMetaTags();
+ const headWithMetaTags = metaTags ? `\n${metaTags}` : '';
+
+ const headWithFetchScript = options.injectFetchProxyScript ? `\n` : '';
+
+ const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
+
+ return html.replace('', modifiedHead);
+ };
+}
+
+/**
+ * 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;
+}
+
+async function instrumentHandle(
+ { event, resolve }: Parameters[0],
+ 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()) {
+ getIsolationScope().setTransactionName(routeName);
+ } else {
+ DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
+ }
+
+ try {
+ const resolveResult = await startSpan(
+ {
+ op: 'http.server',
+ attributes: {
+ [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
+ [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
+ 'http.method': event.request.method,
+ },
+ name: routeName,
+ },
+ async (span?: Span) => {
+ getCurrentScope().setSDKProcessingMetadata({
+ // We specifically avoid cloning the request here to avoid double read errors.
+ // We only read request headers so we're not consuming the body anyway.
+ // Note to future readers: This sounds counter-intuitive but please read
+ // https://github.com/getsentry/sentry-javascript/issues/14583
+ normalizedRequest: winterCGRequestToRequestData(event.request),
+ });
+ const res = await resolve(event, {
+ transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }),
+ });
+ if (span) {
+ setHttpStatus(span, res.status);
+ }
+ return res;
+ },
+ );
+ return resolveResult;
+ } catch (e: unknown) {
+ sendErrorToSentry(e, 'handle');
+ throw e;
+ } finally {
+ await flushIfServerless();
+ }
+}
+
+/**
+ * A SvelteKit handle function that wraps the request for Sentry error and
+ * performance monitoring.
+ *
+ * Usage:
+ * ```
+ * // src/hooks.server.ts
+ * import { sentryHandle } from '@sentry/sveltekit';
+ *
+ * export const handle = sentryHandle();
+ *
+ * // Optionally use the `sequence` function to add additional handlers.
+ * // export const handle = sequence(sentryHandle(), yourCustomHandler);
+ * ```
+ */
+export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
+ const { handleUnknownRoutes, ...rest } = handlerOptions ?? {};
+ const options = {
+ handleUnknownRoutes: handleUnknownRoutes ?? false,
+ ...rest,
+ };
+
+ const sentryRequestHandler: Handle = input => {
+ // Escape hatch to suppress request isolation and trace continuation (see initCloudflareSentryHandle)
+ const skipIsolation =
+ '_sentrySkipRequestIsolation' in input.event.locals && input.event.locals._sentrySkipRequestIsolation;
+
+ // In case of a same-origin `fetch` call within a server`load` function,
+ // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
+ // to `true` so that no additional network call is made.
+ // We want the `http.server` span of that nested call to be a child span of the
+ // currently active span instead of a new root span to correctly reflect this
+ // behavior.
+ if (skipIsolation || input.event.isSubRequest) {
+ return instrumentHandle(input, options);
+ }
+
+ return withIsolationScope(isolationScope => {
+ // We only call continueTrace in the initial top level request to avoid
+ // creating a new root span for the sub request.
+ isolationScope.setSDKProcessingMetadata({
+ // We specifically avoid cloning the request here to avoid double read errors.
+ // We only read request headers so we're not consuming the body anyway.
+ // Note to future readers: This sounds counter-intuitive but please read
+ // https://github.com/getsentry/sentry-javascript/issues/14583
+ normalizedRequest: winterCGRequestToRequestData(input.event.request),
+ });
+ return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
+ });
+ };
+
+ return sentryRequestHandler;
+}
diff --git a/packages/sveltekit/src/server/handleError.ts b/packages/sveltekit/src/server-common/handleError.ts
similarity index 95%
rename from packages/sveltekit/src/server/handleError.ts
rename to packages/sveltekit/src/server-common/handleError.ts
index 30ca4e28de1a..0f9782282e48 100644
--- a/packages/sveltekit/src/server/handleError.ts
+++ b/packages/sveltekit/src/server-common/handleError.ts
@@ -1,8 +1,7 @@
-import { consoleSandbox } from '@sentry/core';
-import { captureException } from '@sentry/node';
+import { captureException, consoleSandbox } from '@sentry/core';
import type { HandleServerError } from '@sveltejs/kit';
-import { flushIfServerless } from './utils';
+import { flushIfServerless } from '../server-common/utils';
// The SvelteKit default error handler just logs the error's stack trace to the console
// see: https://github.com/sveltejs/kit/blob/369e7d6851f543a40c947e033bfc4a9506fdc0a8/packages/kit/src/runtime/server/index.js#L43
diff --git a/packages/sveltekit/src/server/load.ts b/packages/sveltekit/src/server-common/load.ts
similarity index 96%
rename from packages/sveltekit/src/server/load.ts
rename to packages/sveltekit/src/server-common/load.ts
index 30fab345e05b..49160a65b4a5 100644
--- a/packages/sveltekit/src/server/load.ts
+++ b/packages/sveltekit/src/server-common/load.ts
@@ -1,5 +1,9 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/node';
+import {
+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+ addNonEnumerableProperty,
+ startSpan,
+} from '@sentry/core';
import type { LoadEvent, ServerLoadEvent } from '@sveltejs/kit';
import type { SentryWrappedFlag } from '../common/utils';
diff --git a/packages/sveltekit/src/server/rewriteFramesIntegration.ts b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
similarity index 97%
rename from packages/sveltekit/src/server/rewriteFramesIntegration.ts
rename to packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
index 44afbca2d6df..d5928f8974b0 100644
--- a/packages/sveltekit/src/server/rewriteFramesIntegration.ts
+++ b/packages/sveltekit/src/server-common/rewriteFramesIntegration.ts
@@ -7,7 +7,7 @@ import {
join,
rewriteFramesIntegration as originalRewriteFramesIntegration,
} from '@sentry/core';
-import { WRAPPED_MODULE_SUFFIX } from '../vite/autoInstrument';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
import type { GlobalWithSentryValues } from '../vite/injectGlobalValues';
type StackFrameIteratee = (frame: StackFrame) => StackFrame;
diff --git a/packages/sveltekit/src/server/serverRoute.ts b/packages/sveltekit/src/server-common/serverRoute.ts
similarity index 92%
rename from packages/sveltekit/src/server/serverRoute.ts
rename to packages/sveltekit/src/server-common/serverRoute.ts
index 9d2cba3dbcdc..1b2169c58b8c 100644
--- a/packages/sveltekit/src/server/serverRoute.ts
+++ b/packages/sveltekit/src/server-common/serverRoute.ts
@@ -1,5 +1,9 @@
-import { addNonEnumerableProperty } from '@sentry/core';
-import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, startSpan } from '@sentry/node';
+import {
+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+ addNonEnumerableProperty,
+ startSpan,
+} from '@sentry/core';
import type { RequestEvent } from '@sveltejs/kit';
import { flushIfServerless, sendErrorToSentry } from './utils';
diff --git a/packages/sveltekit/src/server/utils.ts b/packages/sveltekit/src/server-common/utils.ts
similarity index 95%
rename from packages/sveltekit/src/server/utils.ts
rename to packages/sveltekit/src/server-common/utils.ts
index 8eae93d531ab..d6f09093b74d 100644
--- a/packages/sveltekit/src/server/utils.ts
+++ b/packages/sveltekit/src/server-common/utils.ts
@@ -1,5 +1,4 @@
-import { logger, objectify } from '@sentry/core';
-import { captureException, flush } from '@sentry/node';
+import { captureException, flush, logger, objectify } from '@sentry/core';
import type { RequestEvent } from '@sveltejs/kit';
import { DEBUG_BUILD } from '../common/debug-build';
diff --git a/packages/sveltekit/src/server/handle.ts b/packages/sveltekit/src/server/handle.ts
index 84f29a2c70c5..da429bc1040f 100644
--- a/packages/sveltekit/src/server/handle.ts
+++ b/packages/sveltekit/src/server/handle.ts
@@ -1,208 +1,24 @@
-import type { Span } from '@sentry/core';
-import {
- SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
- SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
- continueTrace,
- getCurrentScope,
- getDefaultIsolationScope,
- getIsolationScope,
- getTraceMetaTags,
- logger,
- setHttpStatus,
- startSpan,
- winterCGRequestToRequestData,
- withIsolationScope,
-} from '@sentry/core';
-import type { Handle, ResolveOptions } from '@sveltejs/kit';
-
-import { DEBUG_BUILD } from '../common/debug-build';
-import { flushIfServerless, getTracePropagationData, sendErrorToSentry } from './utils';
-
-export type SentryHandleOptions = {
- /**
- * Controls whether the SDK should capture errors and traces in requests that don't belong to a
- * route defined in your SvelteKit application.
- *
- * By default, this option is set to `false` to reduce noise (e.g. bots sending random requests to your server).
- *
- * Set this option to `true` if you want to monitor requests events without a route. This might be useful in certain
- * scenarios, for instance if you registered other handlers that handle these requests.
- * If you set this option, you might want adjust the the transaction name in the `beforeSendTransaction`
- * callback of your server-side `Sentry.init` options. You can also use `beforeSendTransaction` to filter out
- * transactions that you still don't want to be sent to Sentry.
- *
- * @default false
- */
- handleUnknownRoutes?: boolean;
-
- /**
- * Controls if `sentryHandle` should inject a script tag into the page that enables instrumentation
- * of `fetch` calls in `load` functions.
- *
- * @default true
- */
- injectFetchProxyScript?: boolean;
-};
+import type { CloudflareOptions } from '@sentry/cloudflare';
+import type { Handle } from '@sveltejs/kit';
+import { init } from './sdk';
/**
- * Exported only for testing
- */
-export const FETCH_PROXY_SCRIPT = `
- const f = window.fetch;
- if(f){
- window._sentryFetchProxy = function(...a){return f(...a)}
- window.fetch = function(...a){return window._sentryFetchProxy(...a)}
- }
-`;
-
-/**
- * Adds Sentry tracing tags to the returned html page.
- * Adds Sentry fetch proxy script to the returned html page if enabled in options.
- *
- * Exported only for testing
- */
-export function addSentryCodeToPage(options: { injectFetchProxyScript: boolean }): NonNullable<
- ResolveOptions['transformPageChunk']
-> {
- return ({ html }) => {
- const metaTags = getTraceMetaTags();
- const headWithMetaTags = metaTags ? `\n${metaTags}` : '';
-
- const headWithFetchScript = options.injectFetchProxyScript ? `\n` : '';
-
- const modifiedHead = `${headWithMetaTags}${headWithFetchScript}`;
-
- return html.replace('', modifiedHead);
- };
-}
-
-/**
- * A SvelteKit handle function that wraps the request for Sentry error and
- * performance monitoring.
- *
- * Usage:
- * ```
- * // src/hooks.server.ts
- * import { sentryHandle } from '@sentry/sveltekit';
+ * Actual implementation in ../worker/handle.ts
*
- * export const handle = sentryHandle();
+ * This handler initializes the Sentry Node(!) SDK with the passed options. This is necessary to get
+ * the SDK configured for cloudflare working in dev mode.
*
- * // Optionally use the `sequence` function to add additional handlers.
- * // export const handle = sequence(sentryHandle(), yourCustomHandler);
- * ```
+ * @return version of initCLoudflareSentryHandle that is called via node/server entry point
*/
-export function sentryHandle(handlerOptions?: SentryHandleOptions): Handle {
- const { handleUnknownRoutes, ...rest } = handlerOptions ?? {};
- const options = {
- handleUnknownRoutes: handleUnknownRoutes ?? false,
- ...rest,
- };
+export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
+ let sentryInitialized = false;
- const sentryRequestHandler: Handle = input => {
- // In case of a same-origin `fetch` call within a server`load` function,
- // SvelteKit will actually just re-enter the `handle` function and set `isSubRequest`
- // to `true` so that no additional network call is made.
- // We want the `http.server` span of that nested call to be a child span of the
- // currently active span instead of a new root span to correctly reflect this
- // behavior.
- if (input.event.isSubRequest) {
- return instrumentHandle(input, options);
+ return ({ event, resolve }) => {
+ if (!sentryInitialized) {
+ sentryInitialized = true;
+ init(options);
}
- return withIsolationScope(isolationScope => {
- // We only call continueTrace in the initial top level request to avoid
- // creating a new root span for the sub request.
- isolationScope.setSDKProcessingMetadata({
- // We specifically avoid cloning the request here to avoid double read errors.
- // We only read request headers so we're not consuming the body anyway.
- // Note to future readers: This sounds counter-intuitive but please read
- // https://github.com/getsentry/sentry-javascript/issues/14583
- normalizedRequest: winterCGRequestToRequestData(input.event.request),
- });
- return continueTrace(getTracePropagationData(input.event), () => instrumentHandle(input, options));
- });
- };
-
- return sentryRequestHandler;
-}
-
-async function instrumentHandle(
- { event, resolve }: Parameters[0],
- 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()) {
- getIsolationScope().setTransactionName(routeName);
- } else {
- DEBUG_BUILD && logger.warn('Isolation scope is default isolation scope - skipping setting transactionName');
- }
-
- try {
- const resolveResult = await startSpan(
- {
- op: 'http.server',
- attributes: {
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.sveltekit',
- [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: event.route?.id ? 'route' : 'url',
- 'http.method': event.request.method,
- },
- name: routeName,
- },
- async (span?: Span) => {
- getCurrentScope().setSDKProcessingMetadata({
- // We specifically avoid cloning the request here to avoid double read errors.
- // We only read request headers so we're not consuming the body anyway.
- // Note to future readers: This sounds counter-intuitive but please read
- // https://github.com/getsentry/sentry-javascript/issues/14583
- normalizedRequest: winterCGRequestToRequestData(event.request),
- });
- const res = await resolve(event, {
- transformPageChunk: addSentryCodeToPage({ injectFetchProxyScript: options.injectFetchProxyScript ?? true }),
- });
- if (span) {
- setHttpStatus(span, res.status);
- }
- return res;
- },
- );
- return resolveResult;
- } catch (e: unknown) {
- sendErrorToSentry(e, 'handle');
- throw e;
- } finally {
- 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/src/server/index.ts b/packages/sveltekit/src/server/index.ts
index 232e0562eb22..ccd09570b674 100644
--- a/packages/sveltekit/src/server/index.ts
+++ b/packages/sveltekit/src/server/index.ts
@@ -123,10 +123,11 @@ export * from '@sentry/node';
// -------------------------
// SvelteKit SDK exports:
export { init } from './sdk';
-export { handleErrorWithSentry } from './handleError';
-export { wrapLoadWithSentry, wrapServerLoadWithSentry } from './load';
-export { sentryHandle } from './handle';
-export { wrapServerRouteWithSentry } from './serverRoute';
+export { handleErrorWithSentry } from '../server-common/handleError';
+export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
+export { sentryHandle } from '../server-common/handle';
+export { initCloudflareSentryHandle } from './handle';
+export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
/**
* Tracks the Svelte component's initialization and mounting operation as well as
diff --git a/packages/sveltekit/src/server/sdk.ts b/packages/sveltekit/src/server/sdk.ts
index 7f3acbf57fbd..66362e96a729 100644
--- a/packages/sveltekit/src/server/sdk.ts
+++ b/packages/sveltekit/src/server/sdk.ts
@@ -3,10 +3,10 @@ import type { NodeClient, NodeOptions } from '@sentry/node';
import { getDefaultIntegrations as getDefaultNodeIntegrations } from '@sentry/node';
import { init as initNodeSdk } from '@sentry/node';
-import { rewriteFramesIntegration } from './rewriteFramesIntegration';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
/**
- *
+ * Initialize the Server-side Sentry SDK
* @param options
*/
export function init(options: NodeOptions): NodeClient | undefined {
diff --git a/packages/sveltekit/src/vite/autoInstrument.ts b/packages/sveltekit/src/vite/autoInstrument.ts
index 1e11f2f61500..8303af502f90 100644
--- a/packages/sveltekit/src/vite/autoInstrument.ts
+++ b/packages/sveltekit/src/vite/autoInstrument.ts
@@ -3,8 +3,7 @@ import * as path from 'path';
import type { ExportNamedDeclaration } from '@babel/types';
import { parseModule } from 'magicast';
import type { Plugin } from 'vite';
-
-export const WRAPPED_MODULE_SUFFIX = '?sentry-auto-wrap';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
export type AutoInstrumentSelection = {
/**
diff --git a/packages/sveltekit/src/vite/sourceMaps.ts b/packages/sveltekit/src/vite/sourceMaps.ts
index 799688b33845..5d93849a1281 100644
--- a/packages/sveltekit/src/vite/sourceMaps.ts
+++ b/packages/sveltekit/src/vite/sourceMaps.ts
@@ -9,7 +9,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin';
import type { Plugin, UserConfig } from 'vite';
import MagicString from 'magic-string';
-import { WRAPPED_MODULE_SUFFIX } from './autoInstrument';
+import { WRAPPED_MODULE_SUFFIX } from '../common/utils';
import type { GlobalSentryValues } from './injectGlobalValues';
import { VIRTUAL_GLOBAL_VALUES_FILE, getGlobalValueInjectionCode } from './injectGlobalValues';
import { getAdapterOutputDir, getHooksFileName, loadSvelteConfig } from './svelteConfig';
diff --git a/packages/sveltekit/src/worker/cloudflare.ts b/packages/sveltekit/src/worker/cloudflare.ts
new file mode 100644
index 000000000000..0d26c566ea10
--- /dev/null
+++ b/packages/sveltekit/src/worker/cloudflare.ts
@@ -0,0 +1,43 @@
+import { type CloudflareOptions, wrapRequestHandler } from '@sentry/cloudflare';
+import { getDefaultIntegrations as getDefaultCloudflareIntegrations } from '@sentry/cloudflare';
+import type { Handle } from '@sveltejs/kit';
+
+import { addNonEnumerableProperty } from '@sentry/core';
+import { rewriteFramesIntegration } from '../server-common/rewriteFramesIntegration';
+
+/**
+ * Initializes Sentry SvelteKit Cloudflare SDK
+ * This should be before the sentryHandle() call.
+ *
+ * In the Node export, this is a stub that does nothing.
+ */
+export function initCloudflareSentryHandle(options: CloudflareOptions): Handle {
+ const opts: CloudflareOptions = {
+ defaultIntegrations: [...getDefaultCloudflareIntegrations(options), rewriteFramesIntegration()],
+ ...options,
+ };
+
+ const handleInitSentry: Handle = ({ event, resolve }) => {
+ // if event.platform exists (should be there in a cloudflare worker), then do the cloudflare sentry init
+ if (event.platform) {
+ // This is an optional local that the `sentryHandle` handler checks for to avoid double isolation
+ // In Cloudflare the `wrapRequestHandler` function already takes care of
+ // - request isolation
+ // - trace continuation
+ // -setting the request onto the scope
+ addNonEnumerableProperty(event.locals, '_sentrySkipRequestIsolation', true);
+ return wrapRequestHandler(
+ {
+ options: opts,
+ request: event.request,
+ // @ts-expect-error This will exist in Cloudflare
+ context: event.platform.context,
+ },
+ () => resolve(event),
+ );
+ }
+ return resolve(event);
+ };
+
+ return handleInitSentry;
+}
diff --git a/packages/sveltekit/src/worker/index.ts b/packages/sveltekit/src/worker/index.ts
new file mode 100644
index 000000000000..a74989b7d28e
--- /dev/null
+++ b/packages/sveltekit/src/worker/index.ts
@@ -0,0 +1,90 @@
+// For use in cloudflare workers and other edge environments
+//
+// These are essentially the same as the node server exports, but using imports from @sentry/core
+// instead of @sentry/node.
+//
+// This is expected to be used together with something like the @sentry/cloudflare package, to initialize Sentry
+// in the worker.
+//
+// -------------------------
+// SvelteKit SDK exports:
+export { handleErrorWithSentry } from '../server-common/handleError';
+export { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../server-common/load';
+export { sentryHandle } from '../server-common/handle';
+export { initCloudflareSentryHandle } from './cloudflare';
+export { wrapServerRouteWithSentry } from '../server-common/serverRoute';
+
+// Re-export some functions from Cloudflare SDK
+export {
+ addBreadcrumb,
+ addEventProcessor,
+ addIntegration,
+ captureCheckIn,
+ captureConsoleIntegration,
+ captureEvent,
+ captureException,
+ captureFeedback,
+ captureMessage,
+ close,
+ continueTrace,
+ createTransport,
+ dedupeIntegration,
+ extraErrorDataIntegration,
+ flush,
+ functionToStringIntegration,
+ getActiveSpan,
+ getClient,
+ getCurrentScope,
+ getDefaultIntegrations,
+ getGlobalScope,
+ getIsolationScope,
+ getRootSpan,
+ getSpanDescendants,
+ getSpanStatusFromHttpCode,
+ getTraceData,
+ getTraceMetaTags,
+ inboundFiltersIntegration,
+ isInitialized,
+ lastEventId,
+ linkedErrorsIntegration,
+ requestDataIntegration,
+ rewriteFramesIntegration,
+ Scope,
+ SDK_VERSION,
+ SEMANTIC_ATTRIBUTE_SENTRY_OP,
+ SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
+ SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE,
+ SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
+ setContext,
+ setCurrentClient,
+ setExtra,
+ setExtras,
+ setHttpStatus,
+ setMeasurement,
+ setTag,
+ setTags,
+ setUser,
+ spanToBaggageHeader,
+ spanToJSON,
+ spanToTraceHeader,
+ startInactiveSpan,
+ startNewTrace,
+ suppressTracing,
+ startSpan,
+ startSpanManual,
+ trpcMiddleware,
+ withActiveSpan,
+ withIsolationScope,
+ withMonitor,
+ withScope,
+ zodErrorsIntegration,
+} from '@sentry/cloudflare';
+
+/**
+ * Tracks the Svelte component's initialization and mounting operation as well as
+ * updates and records them as spans. These spans are only recorded on the client-side.
+ * Sever-side, during SSR, this function will not record any spans.
+ */
+export function trackComponent(_options?: unknown): void {
+ // no-op on the server side
+}
diff --git a/packages/sveltekit/test/server/handle.test.ts b/packages/sveltekit/test/server/handle.test.ts
index b2adb50d91b8..9c6e2b71d330 100644
--- a/packages/sveltekit/test/server/handle.test.ts
+++ b/packages/sveltekit/test/server/handle.test.ts
@@ -8,16 +8,17 @@ import {
spanToJSON,
} from '@sentry/core';
import type { EventEnvelopeHeaders, Span } from '@sentry/core';
+import * as SentryCore from '@sentry/core';
import { NodeClient, setCurrentClient } from '@sentry/node';
-import * as SentryNode from '@sentry/node';
import type { Handle } from '@sveltejs/kit';
import { redirect } from '@sveltejs/kit';
import { vi } from 'vitest';
-import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, isFetchProxyRequired, sentryHandle } from '../../src/server/handle';
+import { FETCH_PROXY_SCRIPT, addSentryCodeToPage, isFetchProxyRequired } from '../../src/server-common/handle';
+import { sentryHandle } from '../../src/server-common/handle';
import { getDefaultNodeClientOptions } from '../utils';
-const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
function mockEvent(override: Record = {}): Parameters[0]['event'] {
const event: Parameters[0]['event'] = {
@@ -98,6 +99,7 @@ beforeEach(() => {
client.init();
mockCaptureException.mockClear();
+ vi.clearAllMocks();
});
describe('sentryHandle', () => {
@@ -366,6 +368,23 @@ describe('sentryHandle', () => {
expect(_span!).toBeDefined();
});
+
+ it("doesn't create an isolation scope when the `_sentrySkipRequestIsolation` local is set", async () => {
+ const withIsolationScopeSpy = vi.spyOn(SentryCore, 'withIsolationScope');
+ const continueTraceSpy = vi.spyOn(SentryCore, 'continueTrace');
+
+ try {
+ await sentryHandle({ handleUnknownRoutes: true })({
+ event: { ...mockEvent({ route: undefined }), locals: { _sentrySkipRequestIsolation: true } },
+ resolve: resolve(type, isError),
+ });
+ } catch {
+ //
+ }
+
+ expect(withIsolationScopeSpy).not.toHaveBeenCalled();
+ expect(continueTraceSpy).not.toHaveBeenCalled();
+ });
});
});
@@ -394,7 +413,7 @@ describe('addSentryCodeToPage', () => {
it('adds meta tags and the fetch proxy script if there is an active transaction', () => {
const transformPageChunk = addSentryCodeToPage({ injectFetchProxyScript: true });
- SentryNode.startSpan({ name: 'test' }, () => {
+ SentryCore.startSpan({ name: 'test' }, () => {
const transformed = transformPageChunk({ html, done: true }) as string;
expect(transformed).toContain(' 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
const captureExceptionEventHint = {
mechanism: { handled: false, type: 'sveltekit' },
diff --git a/packages/sveltekit/test/server/load.test.ts b/packages/sveltekit/test/server/load.test.ts
index 1001d8464ad4..8530208347a4 100644
--- a/packages/sveltekit/test/server/load.test.ts
+++ b/packages/sveltekit/test/server/load.test.ts
@@ -6,15 +6,15 @@ import {
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
} from '@sentry/core';
import type { Event } from '@sentry/core';
+import * as SentryCore from '@sentry/core';
import { NodeClient, getCurrentScope, getIsolationScope, setCurrentClient } from '@sentry/node';
-import * as SentryNode from '@sentry/node';
import type { Load, ServerLoad } from '@sveltejs/kit';
import { error, redirect } from '@sveltejs/kit';
-import { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../../src/server/load';
+import { wrapLoadWithSentry, wrapServerLoadWithSentry } from '../../src/server-common/load';
import { getDefaultNodeClientOptions } from '../utils';
-const mockCaptureException = vi.spyOn(SentryNode, 'captureException').mockImplementation(() => 'xx');
+const mockCaptureException = vi.spyOn(SentryCore, 'captureException').mockImplementation(() => 'xx');
const mockStartSpan = vi.fn();
diff --git a/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts b/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
index 3dfd5d3e460e..1d5ca8d4d695 100644
--- a/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
+++ b/packages/sveltekit/test/server/rewriteFramesIntegration.test.ts
@@ -2,7 +2,7 @@ import { rewriteFramesIntegration } from '@sentry/browser';
import { basename } from '@sentry/core';
import type { Event, StackFrame } from '@sentry/core';
-import { rewriteFramesIteratee } from '../../src/server/rewriteFramesIntegration';
+import { rewriteFramesIteratee } from '../../src/server-common/rewriteFramesIntegration';
import type { GlobalWithSentryValues } from '../../src/vite/injectGlobalValues';
describe('rewriteFramesIteratee', () => {
diff --git a/packages/sveltekit/test/server/serverRoute.test.ts b/packages/sveltekit/test/server/serverRoute.test.ts
index de99db5a548e..046c3673a8c7 100644
--- a/packages/sveltekit/test/server/serverRoute.test.ts
+++ b/packages/sveltekit/test/server/serverRoute.test.ts
@@ -1,4 +1,4 @@
-import * as SentryNode from '@sentry/node';
+import * as SentryCore from '@sentry/core';
import type { NumericRange } from '@sveltejs/kit';
import { type RequestEvent, error, redirect } from '@sveltejs/kit';
import { beforeEach, describe, expect, it, vi } from 'vitest';
@@ -26,7 +26,7 @@ describe('wrapServerRouteWithSentry', () => {
});
describe('wraps a server route span around the original server route handler', () => {
- const startSpanSpy = vi.spyOn(SentryNode, 'startSpan');
+ const startSpanSpy = vi.spyOn(SentryCore, 'startSpan');
it('assigns the route id as name if available', () => {
const wrappedRouteHandler = wrapServerRouteWithSentry(originalRouteHandler);
@@ -71,7 +71,7 @@ describe('wrapServerRouteWithSentry', () => {
});
});
- const captureExceptionSpy = vi.spyOn(SentryNode, 'captureException');
+ const captureExceptionSpy = vi.spyOn(SentryCore, 'captureException');
describe('captures server route errors', () => {
it('captures and rethrows normal server route error', async () => {
const error = new Error('Server Route Error');
diff --git a/packages/sveltekit/test/server/utils.test.ts b/packages/sveltekit/test/server/utils.test.ts
index 5e8b9b2b99a3..53e588d683ec 100644
--- a/packages/sveltekit/test/server/utils.test.ts
+++ b/packages/sveltekit/test/server/utils.test.ts
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';
-import { getTracePropagationData } from '../../src/server/utils';
+import { getTracePropagationData } from '../../src/server-common/utils';
const MOCK_REQUEST_EVENT: any = {
request: {