@@ -4,7 +4,8 @@ import * as fs from 'fs';
44import * as path from 'path' ;
55import type { Plugin } from 'vite' ;
66import { WRAPPED_MODULE_SUFFIX } from '../common/utils' ;
7- import type { BackwardsForwardsCompatibleKitConfig , BackwardsForwardsCompatibleSvelteConfig } from './svelteConfig' ;
7+ import type { ResolvedKitConfig } from './kitConfig' ;
8+ import { isNativeServerTracingEnabled } from './kitConfig' ;
89
910const AcornParser = acorn . Parser . extend ( tsPlugin ( ) ) ;
1011
@@ -29,7 +30,7 @@ export type AutoInstrumentSelection = {
2930
3031type AutoInstrumentPluginOptions = AutoInstrumentSelection & {
3132 debug : boolean ;
32- onlyInstrumentClient : boolean ;
33+ getKitConfig : ( ) => Promise < ResolvedKitConfig > ;
3334} ;
3435
3536/**
@@ -42,14 +43,15 @@ type AutoInstrumentPluginOptions = AutoInstrumentSelection & {
4243 * @returns the plugin
4344 */
4445export function makeAutoInstrumentationPlugin ( options : AutoInstrumentPluginOptions ) : Plugin {
45- const { load : wrapLoadEnabled , serverLoad : wrapServerLoadEnabled , debug } = options ;
46+ const { load : wrapLoadEnabled , serverLoad : wrapServerLoadEnabled , debug, getKitConfig } = options ;
4647
4748 let isServerBuild : boolean | undefined = undefined ;
4849
4950 // Whether we should skip server-side load instrumentation because SvelteKit's native server
50- // tracing is enabled. Initialized from the option (derived from `svelte.config.js`), but may be
51- // flipped to `true` in `configResolved` once we can read SvelteKit's resolved config (see below).
52- let onlyInstrumentClient = options . onlyInstrumentClient ;
51+ // tracing is enabled. If it is, adding our own wrapper on top would emit duplicate spans.
52+ let onlyInstrumentClientPromise : Promise < boolean > | undefined ;
53+ const shouldOnlyInstrumentClient = ( ) : Promise < boolean > =>
54+ ( onlyInstrumentClientPromise ??= getKitConfig ( ) . then ( isNativeServerTracingEnabled ) ) ;
5355
5456 return {
5557 name : 'sentry-auto-instrumentation' ,
@@ -62,16 +64,6 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
6264 // `config.build.ssr` is `true` for that first build and `false` in the other ones.
6365 // Hence we can use it as a switch to upload source maps only once in main build.
6466 isServerBuild = ! ! config . build . ssr ;
65-
66- // As of SvelteKit 3, the native server-tracing config is no longer read from
67- // `svelte.config.js` (so the `onlyInstrumentClient` option, derived from it, is `false`).
68- // It's passed to the `sveltekit()` Vite plugin instead, which exposes the resolved config
69- // via its plugin `api.options`. Reading it here lets us reliably detect native tracing
70- // regardless of SvelteKit version. When it's enabled, we must not add our own server-side
71- // load instrumentation, otherwise we'd emit duplicate spans on top of SvelteKit's.
72- if ( ! onlyInstrumentClient && isNativeServerTracingEnabled ( config . plugins ) ) {
73- onlyInstrumentClient = true ;
74- }
7567 } ,
7668
7769 async load ( id ) {
@@ -81,7 +73,7 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
8173 const environmentName = ( this as { environment ?: { name ?: string } } ) . environment ?. name ;
8274 const isServerEnvironment = environmentName != null ? environmentName === 'ssr' : ! ! isServerBuild ;
8375
84- if ( onlyInstrumentClient && isServerEnvironment ) {
76+ if ( isServerEnvironment && ( await shouldOnlyInstrumentClient ( ) ) ) {
8577 return null ;
8678 }
8779
@@ -96,9 +88,9 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
9688 return getWrapperCode ( 'wrapLoadWithSentry' , `${ id } ${ WRAPPED_MODULE_SUFFIX } ` ) ;
9789 }
9890
99- if ( onlyInstrumentClient ) {
91+ if ( await shouldOnlyInstrumentClient ( ) ) {
10092 // Now that we've checked universal files, we can early return and avoid further
101- // regexp checks below for server-only files, in case `onlyInstrumentClient` is `true` .
93+ // regexp checks below for server-only files.
10294 return null ;
10395 }
10496
@@ -118,39 +110,6 @@ export function makeAutoInstrumentationPlugin(options: AutoInstrumentPluginOptio
118110 } ;
119111}
120112
121- /**
122- * Detects whether SvelteKit's native server-side tracing is enabled by reading the resolved
123- * SvelteKit config that the `sveltekit()` Vite plugin exposes via its plugin `api.options`.
124- *
125- * This is the source of truth as of SvelteKit 3, where the config moved out of `svelte.config.js`
126- * and into the `sveltekit()` plugin. On older SvelteKit versions that don't expose the config this
127- * way, it simply returns `false` and we fall back to the `svelte.config.js`-derived value.
128- */
129- function isNativeServerTracingEnabled ( plugins : readonly Plugin [ ] | undefined ) : boolean {
130- if ( ! plugins ) {
131- return false ;
132- }
133-
134- for ( const plugin of plugins ) {
135- const options = (
136- plugin ?. api as
137- | { options ?: BackwardsForwardsCompatibleSvelteConfig & BackwardsForwardsCompatibleKitConfig }
138- | undefined
139- ) ?. options ;
140-
141- // SvelteKit 3 flattened the plugin config: what used to live under `kit` now sits
142- // at the top level of the exposed options.
143- const kitConfig = options ?. kit ?? options ;
144-
145- // SvelteKit 3 promoted `tracing` out of `experimental`; older versions nest it there.
146- if ( kitConfig ?. tracing ?. server || kitConfig ?. experimental ?. tracing ?. server ) {
147- return true ;
148- }
149- }
150-
151- return false ;
152- }
153-
154113/**
155114 * We only want to apply our wrapper to files that
156115 *
0 commit comments