Skip to content

Commit 993044d

Browse files
authored
feat(astro): Add enabled option to Astro integration options (#10007)
Add a top level `enabled` option to the Astro integration options. This option can be used to globally enable/disable all Sentry features, either for client or server separately or for both sides simultaneously. * Disabeling either side will avoid the respective SDK code being injected into the bundles. * If both sides are disabled, source maps will not be generated and uploaded. * If both or just the server side is disabled, the Sentry middleware won't be added. * Obviously, this options defaults to `true`
1 parent 679e149 commit 993044d

File tree

3 files changed

+122
-25
lines changed

3 files changed

+122
-25
lines changed

packages/astro/src/integration/index.ts

+31-22
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,14 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
2424
// Will revisit this later.
2525
const env = process.env;
2626

27-
const uploadOptions = options.sourceMapsUploadOptions || {};
27+
const sdkEnabled = {
28+
client: typeof options.enabled === 'boolean' ? options.enabled : options.enabled?.client ?? true,
29+
server: typeof options.enabled === 'boolean' ? options.enabled : options.enabled?.server ?? true,
30+
};
2831

29-
const shouldUploadSourcemaps = uploadOptions?.enabled ?? true;
32+
const sourceMapsNeeded = sdkEnabled.client || sdkEnabled.server;
33+
const uploadOptions = options.sourceMapsUploadOptions || {};
34+
const shouldUploadSourcemaps = (sourceMapsNeeded && uploadOptions?.enabled) ?? true;
3035

3136
// We don't need to check for AUTH_TOKEN here, because the plugin will pick it up from the env
3237
if (shouldUploadSourcemaps && command !== 'dev') {
@@ -51,31 +56,35 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
5156
});
5257
}
5358

54-
const pathToClientInit = options.clientInitPath
55-
? path.resolve(options.clientInitPath)
56-
: findDefaultSdkInitFile('client');
57-
const pathToServerInit = options.serverInitPath
58-
? path.resolve(options.serverInitPath)
59-
: findDefaultSdkInitFile('server');
60-
61-
if (pathToClientInit) {
62-
options.debug && console.log(`[sentry-astro] Using ${pathToClientInit} for client init.`);
63-
injectScript('page', buildSdkInitFileImportSnippet(pathToClientInit));
64-
} else {
65-
options.debug && console.log('[sentry-astro] Using default client init.');
66-
injectScript('page', buildClientSnippet(options || {}));
59+
if (sdkEnabled.client) {
60+
const pathToClientInit = options.clientInitPath
61+
? path.resolve(options.clientInitPath)
62+
: findDefaultSdkInitFile('client');
63+
64+
if (pathToClientInit) {
65+
options.debug && console.log(`[sentry-astro] Using ${pathToClientInit} for client init.`);
66+
injectScript('page', buildSdkInitFileImportSnippet(pathToClientInit));
67+
} else {
68+
options.debug && console.log('[sentry-astro] Using default client init.');
69+
injectScript('page', buildClientSnippet(options || {}));
70+
}
6771
}
6872

69-
if (pathToServerInit) {
70-
options.debug && console.log(`[sentry-astro] Using ${pathToServerInit} for server init.`);
71-
injectScript('page-ssr', buildSdkInitFileImportSnippet(pathToServerInit));
72-
} else {
73-
options.debug && console.log('[sentry-astro] Using default server init.');
74-
injectScript('page-ssr', buildServerSnippet(options || {}));
73+
if (sdkEnabled.server) {
74+
const pathToServerInit = options.serverInitPath
75+
? path.resolve(options.serverInitPath)
76+
: findDefaultSdkInitFile('server');
77+
if (pathToServerInit) {
78+
options.debug && console.log(`[sentry-astro] Using ${pathToServerInit} for server init.`);
79+
injectScript('page-ssr', buildSdkInitFileImportSnippet(pathToServerInit));
80+
} else {
81+
options.debug && console.log('[sentry-astro] Using default server init.');
82+
injectScript('page-ssr', buildServerSnippet(options || {}));
83+
}
7584
}
7685

7786
const isSSR = config && (config.output === 'server' || config.output === 'hybrid');
78-
const shouldAddMiddleware = options.autoInstrumentation?.requestHandler !== false;
87+
const shouldAddMiddleware = sdkEnabled.server && options.autoInstrumentation?.requestHandler !== false;
7988

8089
// Guarding calling the addMiddleware function because it was only introduced in [email protected]
8190
// Users on older versions of astro will need to add the middleware manually.

packages/astro/src/integration/types.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,26 @@ type InstrumentationOptions = {
106106
};
107107
};
108108

109+
type SdkEnabledOptions = {
110+
/**
111+
* Controls if the Sentry SDK is enabled or not.
112+
*
113+
* You can either set a boolean value to enable/disable the SDK for both client and server,
114+
* or pass an object with `client` and `server` properties to enable/disable the SDK.
115+
*
116+
* If the SDK is disabled, no data will be caught or sent to Sentry. In this case, also no
117+
* Sentry code will be added to your bundle.
118+
*
119+
* @default true - the SDK is enabled by default for both, client and server.
120+
*/
121+
enabled?:
122+
| boolean
123+
| {
124+
client?: boolean;
125+
server?: boolean;
126+
};
127+
};
128+
109129
/**
110130
* A subset of Sentry SDK options that can be set via the `sentryAstro` integration.
111131
* Some options (e.g. integrations) are set by default and cannot be changed here.
@@ -119,4 +139,5 @@ export type SentryOptions = SdkInitPaths &
119139
Pick<Options, 'dsn' | 'release' | 'environment' | 'sampleRate' | 'tracesSampleRate' | 'debug'> &
120140
Pick<BrowserOptions, 'replaysSessionSampleRate' | 'replaysOnErrorSampleRate'> &
121141
SourceMapsOptions &
122-
InstrumentationOptions;
142+
InstrumentationOptions &
143+
SdkEnabledOptions;

packages/astro/test/integration/index.test.ts

+69-2
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,21 @@ describe('sentryAstro integration', () => {
168168
expect(sentryVitePluginSpy).toHaveBeenCalledTimes(0);
169169
});
170170

171-
it('injects client and server init scripts', async () => {
172-
const integration = sentryAstro({});
171+
it("doesn't add the plugin or enable source maps if the SDK is disabled", async () => {
172+
const integration = sentryAstro({
173+
enabled: false,
174+
});
175+
176+
expect(integration.hooks['astro:config:setup']).toBeDefined();
177+
// @ts-expect-error - the hook exists and we only need to pass what we actually use
178+
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });
179+
180+
expect(updateConfig).toHaveBeenCalledTimes(0);
181+
expect(sentryVitePluginSpy).toHaveBeenCalledTimes(0);
182+
});
183+
184+
it.each([{}, { enabled: true }])('injects client and server init scripts', async options => {
185+
const integration = sentryAstro(options);
173186

174187
expect(integration.hooks['astro:config:setup']).toBeDefined();
175188
// @ts-expect-error - the hook exists and we only need to pass what we actually use
@@ -180,6 +193,41 @@ describe('sentryAstro integration', () => {
180193
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('Sentry.init'));
181194
});
182195

196+
it("doesn't inject client init script if `enabled.client` is `false`", async () => {
197+
const integration = sentryAstro({ enabled: { client: false } });
198+
199+
expect(integration.hooks['astro:config:setup']).toBeDefined();
200+
// @ts-expect-error - the hook exists and we only need to pass what we actually use
201+
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });
202+
203+
expect(injectScript).toHaveBeenCalledTimes(1);
204+
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('Sentry.init'));
205+
});
206+
207+
it("doesn't inject server init script if `enabled.server` is `false`", async () => {
208+
const integration = sentryAstro({ enabled: { server: false } });
209+
210+
expect(integration.hooks['astro:config:setup']).toBeDefined();
211+
// @ts-expect-error - the hook exists and we only need to pass what we actually use
212+
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });
213+
214+
expect(injectScript).toHaveBeenCalledTimes(1);
215+
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('Sentry.init'));
216+
});
217+
218+
it.each([false, { client: false, server: false }])(
219+
"doesn't inject any init script if `enabled` is generally false (`%s`)",
220+
async enabled => {
221+
const integration = sentryAstro({ enabled });
222+
223+
expect(integration.hooks['astro:config:setup']).toBeDefined();
224+
// @ts-expect-error - the hook exists and we only need to pass what we actually use
225+
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });
226+
227+
expect(injectScript).toHaveBeenCalledTimes(0);
228+
},
229+
);
230+
183231
it('injects client and server init scripts from custom paths', async () => {
184232
const integration = sentryAstro({
185233
clientInitPath: 'my-client-init-path.js',
@@ -278,4 +326,23 @@ describe('sentryAstro integration', () => {
278326
expect(updateConfig).toHaveBeenCalledTimes(1);
279327
expect(injectScript).toHaveBeenCalledTimes(2);
280328
});
329+
330+
it("doesn't add middleware if the SDK is disabled", () => {
331+
const integration = sentryAstro({ enabled: false });
332+
const addMiddleware = vi.fn();
333+
const updateConfig = vi.fn();
334+
const injectScript = vi.fn();
335+
336+
expect(integration.hooks['astro:config:setup']).toBeDefined();
337+
// @ts-expect-error - the hook exists and we only need to pass what we actually use
338+
integration.hooks['astro:config:setup']({
339+
// @ts-expect-error - we only need to pass what we actually use
340+
config: { output: 'server' },
341+
addMiddleware,
342+
updateConfig,
343+
injectScript,
344+
});
345+
346+
expect(addMiddleware).toHaveBeenCalledTimes(0);
347+
});
281348
});

0 commit comments

Comments
 (0)