Skip to content

Commit ea0740c

Browse files
committed
don't auto-wrap load functions if kit-tracing is enabled
1 parent 96eabd6 commit ea0740c

File tree

4 files changed

+136
-5
lines changed

4 files changed

+136
-5
lines changed

packages/sveltekit/src/vite/autoInstrument.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type AutoInstrumentSelection = {
2727

2828
type AutoInstrumentPluginOptions = AutoInstrumentSelection & {
2929
debug: boolean;
30+
onlyInstrumentClient: boolean;
3031
};
3132

3233
/**
@@ -41,12 +42,26 @@ type AutoInstrumentPluginOptions = AutoInstrumentSelection & {
4142
export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptions): Plugin {
4243
const { load: wrapLoadEnabled, serverLoad: wrapServerLoadEnabled, debug } = options;
4344

45+
let isServerBuild: boolean | undefined = undefined;
46+
4447
return {
4548
name: 'sentry-auto-instrumentation',
4649
// This plugin needs to run as early as possible, before the SvelteKit plugin virtualizes all paths and ids
4750
enforce: 'pre',
4851

52+
configResolved: config => {
53+
// The SvelteKit plugins trigger additional builds within the main (SSR) build.
54+
// We just need a mechanism to upload source maps only once.
55+
// `config.build.ssr` is `true` for that first build and `false` in the other ones.
56+
// Hence we can use it as a switch to upload source maps only once in main build.
57+
isServerBuild = !!config.build.ssr;
58+
},
59+
4960
async load(id) {
61+
if (options.onlyInstrumentClient && isServerBuild) {
62+
return null;
63+
}
64+
5065
const applyUniversalLoadWrapper =
5166
wrapLoadEnabled &&
5267
/^\+(page|layout)\.(js|ts|mjs|mts)$/.test(path.basename(id)) &&
@@ -58,6 +73,12 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
5873
return getWrapperCode('wrapLoadWithSentry', `${id}${WRAPPED_MODULE_SUFFIX}`);
5974
}
6075

76+
if (options.onlyInstrumentClient) {
77+
// Now that we've checked universal files, we can early return and avoid further
78+
// regexp checks below for server-only files, in case `onlyInstrumentClient` is `true`.
79+
return null;
80+
}
81+
6182
const applyServerLoadWrapper =
6283
wrapServerLoadEnabled &&
6384
/^\+(page|layout)\.server\.(js|ts|mjs|mts)$/.test(path.basename(id)) &&

packages/sveltekit/src/vite/sentryVitePlugins.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,13 @@ export async function sentrySvelteKit(options: SentrySvelteKitPluginOptions = {}
2828
adapter: options.adapter || (await detectAdapter(options.debug)),
2929
};
3030

31+
const svelteConfig = await loadSvelteConfig();
32+
3133
const sentryPlugins: Plugin[] = [];
3234

3335
if (mergedOptions.autoInstrument) {
36+
const kitTracingEnabled = !!svelteConfig.kit?.experimental?.tracing?.server;
37+
3438
const pluginOptions: AutoInstrumentSelection = {
3539
load: true,
3640
serverLoad: true,
@@ -41,14 +45,14 @@ export async function sentrySvelteKit(options: SentrySvelteKitPluginOptions = {}
4145
makeAutoInstrumentationPlugin({
4246
...pluginOptions,
4347
debug: options.debug || false,
48+
// if kit-internal tracing is enabled, we only want to instrument client-side code.
49+
onlyInstrumentClient: kitTracingEnabled,
4450
}),
4551
);
4652
}
4753

4854
const sentryVitePluginsOptions = generateVitePluginOptions(mergedOptions);
4955

50-
const svelteConfig = await loadSvelteConfig();
51-
5256
if (mergedOptions.injectGlobalValues) {
5357
sentryPlugins.push(await makeGlobalValuesInjectionPlugin(svelteConfig, mergedOptions));
5458
}

packages/sveltekit/test/vite/autoInstrument.test.ts

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ describe('makeAutoInstrumentationPlugin()', () => {
4141
});
4242

4343
it('returns the auto instrumentation plugin', async () => {
44-
const plugin = makeAutoInstrumentationPlugin({ debug: true, load: true, serverLoad: true });
44+
const plugin = makeAutoInstrumentationPlugin({
45+
debug: true,
46+
load: true,
47+
serverLoad: true,
48+
onlyInstrumentClient: false,
49+
});
4550
expect(plugin.name).toEqual('sentry-auto-instrumentation');
4651
expect(plugin.enforce).toEqual('pre');
4752
expect(plugin.load).toEqual(expect.any(Function));
@@ -58,7 +63,12 @@ describe('makeAutoInstrumentationPlugin()', () => {
5863
'path/to/+layout.mjs',
5964
])('transform %s files', (path: string) => {
6065
it('wraps universal load if `load` option is `true`', async () => {
61-
const plugin = makeAutoInstrumentationPlugin({ debug: false, load: true, serverLoad: true });
66+
const plugin = makeAutoInstrumentationPlugin({
67+
debug: false,
68+
load: true,
69+
serverLoad: true,
70+
onlyInstrumentClient: false,
71+
});
6272
// @ts-expect-error this exists
6373
const loadResult = await plugin.load(path);
6474
expect(loadResult).toEqual(
@@ -74,6 +84,7 @@ describe('makeAutoInstrumentationPlugin()', () => {
7484
debug: false,
7585
load: false,
7686
serverLoad: false,
87+
onlyInstrumentClient: false,
7788
});
7889
// @ts-expect-error this exists
7990
const loadResult = await plugin.load(path);
@@ -92,7 +103,12 @@ describe('makeAutoInstrumentationPlugin()', () => {
92103
'path/to/+layout.server.mjs',
93104
])('transform %s files', (path: string) => {
94105
it('wraps universal load if `load` option is `true`', async () => {
95-
const plugin = makeAutoInstrumentationPlugin({ debug: false, load: false, serverLoad: true });
106+
const plugin = makeAutoInstrumentationPlugin({
107+
debug: false,
108+
load: false,
109+
serverLoad: true,
110+
onlyInstrumentClient: false,
111+
});
96112
// @ts-expect-error this exists
97113
const loadResult = await plugin.load(path);
98114
expect(loadResult).toEqual(
@@ -108,12 +124,101 @@ describe('makeAutoInstrumentationPlugin()', () => {
108124
debug: false,
109125
load: false,
110126
serverLoad: false,
127+
onlyInstrumentClient: false,
111128
});
112129
// @ts-expect-error this exists
113130
const loadResult = await plugin.load(path);
114131
expect(loadResult).toEqual(null);
115132
});
116133
});
134+
135+
describe('when `onlyInstrumentClient` is `true`', () => {
136+
it.each([
137+
// server-only files
138+
'path/to/+page.server.ts',
139+
'path/to/+layout.server.js',
140+
// universal files
141+
'path/to/+page.mts',
142+
'path/to/+layout.mjs',
143+
])("doesn't wrap code in SSR build in %s", async (path: string) => {
144+
const plugin = makeAutoInstrumentationPlugin({
145+
debug: false,
146+
load: true,
147+
serverLoad: true,
148+
onlyInstrumentClient: true,
149+
});
150+
151+
// @ts-expect-error this exists and is callable
152+
plugin.configResolved({
153+
build: {
154+
ssr: true,
155+
},
156+
});
157+
158+
// @ts-expect-error this exists
159+
const loadResult = await plugin.load(path);
160+
161+
expect(loadResult).toEqual(null);
162+
});
163+
164+
it.each(['path/to/+page.ts', 'path/to/+layout.js'])(
165+
'wraps client-side code in universal files in %s',
166+
async (path: string) => {
167+
const plugin = makeAutoInstrumentationPlugin({
168+
debug: false,
169+
load: true,
170+
serverLoad: true,
171+
onlyInstrumentClient: true,
172+
});
173+
174+
// @ts-expect-error this exists and is callable
175+
plugin.configResolved({
176+
build: {
177+
ssr: false,
178+
},
179+
});
180+
181+
// @ts-expect-error this exists and is callable
182+
const loadResult = await plugin.load(path);
183+
184+
expect(loadResult).toBe(
185+
'import { wrapLoadWithSentry } from "@sentry/sveltekit";' +
186+
`import * as userModule from "${path}?sentry-auto-wrap";` +
187+
'export const load = userModule.load ? wrapLoadWithSentry(userModule.load) : undefined;' +
188+
`export * from "${path}?sentry-auto-wrap";`,
189+
);
190+
},
191+
);
192+
193+
/**
194+
* This is a bit of a constructed case because in a client build, server-only files
195+
* shouldn't even be passed into the load hook. But just to be extra careful, let's
196+
* make sure we don't wrap server-only files in a client build.
197+
*/
198+
it.each(['path/to/+page.server.ts', 'path/to/+layout.server.js'])(
199+
"doesn't wrap client-side code in server-only files in %s",
200+
async (path: string) => {
201+
const plugin = makeAutoInstrumentationPlugin({
202+
debug: false,
203+
load: true,
204+
serverLoad: true,
205+
onlyInstrumentClient: true,
206+
});
207+
208+
// @ts-expect-error this exists and is callable
209+
plugin.configResolved({
210+
build: {
211+
ssr: false,
212+
},
213+
});
214+
215+
// @ts-expect-error this exists and is callable
216+
const loadResult = await plugin.load(path);
217+
218+
expect(loadResult).toBe(null);
219+
},
220+
);
221+
});
117222
});
118223

119224
describe('canWrapLoad', () => {

packages/sveltekit/test/vite/sentrySvelteKitPlugins.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ describe('sentrySvelteKit()', () => {
200200
debug: true,
201201
load: true,
202202
serverLoad: false,
203+
onlyInstrumentClient: false,
203204
});
204205
});
205206
});

0 commit comments

Comments
 (0)