Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/migration/v11-end-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,58 @@ export default defineConfig({
});
```

### `@sentry/astro`

Runtime SDK options (`dsn`, `environment`, `release` as a string, `sampleRate`, `tracesSampleRate`, `replaysSessionSampleRate`, `replaysOnErrorSampleRate`) can no longer be passed to `sentryAstro()`. Configure them in `sentry.client.config.ts` / `sentry.server.config.ts` instead. `release` and `debug` on `sentryAstro()` are now build-time options (`release` for source map uploads, `debug` for build-time logging). If no config files exist, the generated default init snippets still pick them up (`release.name` as the runtime `release`, `debug` for SDK debug logging). The generated client snippet now always includes the `Replay` integration with default sample rates — to customize or remove it (previously done by setting both replay sample rates to `0`), create a `sentry.client.config.ts`.

```ts
// astro.config.mjs — before
import { defineConfig } from 'astro/config';
import sentry from '@sentry/astro';

export default defineConfig({
integrations: [
sentry({
// runtime SDK options on the integration
dsn: 'https://example@sentry.io/123',
release: '1.0.0',
environment: 'production',
tracesSampleRate: 0.5,
}),
],
});
```

```ts
// astro.config.mjs — after (build-time options only)
import { defineConfig } from 'astro/config';
import sentry from '@sentry/astro';

export default defineConfig({
integrations: [
sentry({
org: 'my-org',
project: 'my-project',
authToken: process.env.SENTRY_AUTH_TOKEN,
release: { name: '1.0.0' },
debug: true,
}),
],
});
```

```ts
// sentry.client.config.ts — after (runtime SDK options)
import * as Sentry from '@sentry/astro';

Sentry.init({
dsn: 'https://example@sentry.io/123',
release: '1.0.0',
environment: 'production',
tracesSampleRate: 0.5,
});
```

### `@sentry/react-router`

The deprecated `sourceMapsUploadOptions` option was removed from `sentryReactRouter()`. Move its fields to the root level of the `sentryConfig` passed to `sentryReactRouter()`. Note that `enabled` was replaced by `sourcemaps.disable` (inverted: `enabled: false` becomes `sourcemaps: { disable: true }`).
Expand Down
17 changes: 5 additions & 12 deletions packages/astro/src/integration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
// eslint-disable-next-line typescript/no-deprecated
sourceMapsUploadOptions,
sourcemaps,
// todo(v11): Extract `release` build time option here - cannot be done currently, because it conflicts with the `DeprecatedRuntimeOptions` type
// release,
release,
buildTimeInstrumentation,
bundleSizeOptimizations,
applicationKey,
Expand All @@ -49,18 +48,8 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
telemetry,
silent,
errorHandler,
...deprecatedOptions
} = options;

const deprecatedOptionsKeys = Object.keys(deprecatedOptions);
if (deprecatedOptionsKeys.length > 0) {
logger.warn(
`You passed in additional options (${deprecatedOptionsKeys.join(
', ',
)}) to the Sentry integration. This is deprecated and will stop working in a future version. Instead, configure the Sentry SDK in your \`sentry.client.config.(js|ts)\` or \`sentry.server.config.(js|ts)\` files.`,
);
}

const sdkEnabled = {
client: typeof enabled === 'boolean' ? enabled : (enabled?.client ?? true),
server: typeof enabled === 'boolean' ? enabled : (enabled?.server ?? true),
Expand Down Expand Up @@ -134,6 +123,10 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
},
...unstableMerged_sentryVitePluginOptions,
debug: debug ?? false,
release: {
...unstableMerged_sentryVitePluginOptions?.release,
...release,
},
sourcemaps: {
...sourcemaps,
// eslint-disable-next-line typescript/no-deprecated
Expand Down
34 changes: 11 additions & 23 deletions packages/astro/src/integration/snippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export function buildClientSnippet(options: SentryOptions): string {
Sentry.init({
${buildCommonInitOptions(options)}
integrations: [${buildClientIntegrations(options)}],
replaysSessionSampleRate: ${options.replaysSessionSampleRate ?? 0.1},
replaysOnErrorSampleRate: ${options.replaysOnErrorSampleRate ?? 1.0},
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});`;
}

Expand All @@ -35,22 +35,17 @@ Sentry.init({
});`;
}

const buildCommonInitOptions = (options: SentryOptions): string => `dsn: ${
options.dsn ? JSON.stringify(options.dsn) : 'import.meta.env.PUBLIC_SENTRY_DSN'
},
const buildCommonInitOptions = (options: SentryOptions): string => `dsn: import.meta.env.PUBLIC_SENTRY_DSN,
debug: ${options.debug ? true : false},
environment: ${options.environment ? JSON.stringify(options.environment) : 'import.meta.env.PUBLIC_VERCEL_ENV'},
release: ${options.release ? JSON.stringify(options.release) : 'import.meta.env.PUBLIC_VERCEL_GIT_COMMIT_SHA'},
tracesSampleRate: ${options.tracesSampleRate ?? 1.0},${
options.sampleRate ? `\n sampleRate: ${options.sampleRate},` : ''
}`;
environment: import.meta.env.PUBLIC_VERCEL_ENV,
release: ${
options.release?.name ? JSON.stringify(options.release.name) : 'import.meta.env.PUBLIC_VERCEL_GIT_COMMIT_SHA'
},
tracesSampleRate: 1.0,`;

/**
* We don't include the `BrowserTracing` integration if `bundleSizeOptimizations.excludeTracing` is falsy.
* Likewise, we don't include the `Replay` integration if the replaysSessionSampleRate
* and replaysOnErrorSampleRate are set to 0.
*
* This way, we avoid unnecessarily adding the integrations and thereby enable tree shaking of the integrations.
* We don't include the `BrowserTracing` integration if `bundleSizeOptimizations.excludeTracing` is set.
* The `Replay` integration, however, is always included with default sample rates in the generated snippet.
*/
const buildClientIntegrations = (options: SentryOptions): string => {
const integrations: string[] = [];
Expand All @@ -59,14 +54,7 @@ const buildClientIntegrations = (options: SentryOptions): string => {
integrations.push('Sentry.browserTracingIntegration()');
}

if (
options.replaysSessionSampleRate == null ||
options.replaysSessionSampleRate ||
options.replaysOnErrorSampleRate == null ||
options.replaysOnErrorSampleRate
) {
integrations.push('Sentry.replayIntegration()');
}
integrations.push('Sentry.replayIntegration()');

return integrations.join(', ');
};
Expand Down
30 changes: 8 additions & 22 deletions packages/astro/src/integration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ type SdkInitPaths = {
*
* If this option is not specified, the default location (`<projectRoot>/sentry.client.config.(js|ts)`)
* will be used to look up the config file.
* If there is no file at the default location either, the SDK will initialize with the options
* specified in the `sentryAstro` integration or with default options.
* If there is no file at the default location either, the SDK will initialize with default options.
*/
clientInitPath?: string;

Expand All @@ -18,8 +17,7 @@ type SdkInitPaths = {
*
* If this option is not specified, the default location (`<projectRoot>/sentry.server.config.(js|ts)`)
* will be used to look up the config file.
* If there is no file at the default location either, the SDK will initialize with the options
* specified in the `sentryAstro` integration or with default options.
* If there is no file at the default location either, the SDK will initialize with default options.
*/
serverInitPath?: string;
};
Expand Down Expand Up @@ -158,25 +156,14 @@ type SdkEnabledOptions = {
};

/**
* We accept aribtrary options that are passed through to the Sentry SDK.
* This is not recommended and will stop working in a future version.
* Note: Not all options are actually passed through, only a select subset:
* release, environment, dsn, debug, sampleRate, tracesSampleRate, replaysSessionSampleRate, replaysOnErrorSampleRate
* @deprecated This will be removed in a future major.
**/
type DeprecatedRuntimeOptions = Record<string, unknown>;

/**
* A subset of Sentry SDK options that can be set via the `sentryAstro` integration.
* Some options (e.g. integrations) are set by default and cannot be changed here.
* Options for the `sentryAstro` integration.
*
* If you want a more fine-grained control over the SDK, with all options,
* you can call Sentry.init in `sentry.client.config.(js|ts)` or `sentry.server.config.(js|ts)` files.
* Build-time options (source maps, release management, etc.) are configured here.
* Runtime SDK options must be set in `sentry.client.config.(js|ts)` or `sentry.server.config.(js|ts)`.
*
* If you specify a dedicated init file, the SDK options passed to `sentryAstro` will be ignored.
* If you specify a dedicated init file, the SDK options passed to `sentryAstro` will be ignored for init.
*/
export type SentryOptions = Omit<BuildTimeOptionsBase, 'release'> &
// todo(v11): `release` and `debug` need to be removed from BuildTimeOptionsBase as it is currently conflicting with `DeprecatedRuntimeOptions`
export type SentryOptions = BuildTimeOptionsBase &
UnstableVitePluginOptions<SentryVitePluginOptions> &
SdkInitPaths &
InstrumentationOptions &
Expand All @@ -192,8 +179,7 @@ export type SentryOptions = Omit<BuildTimeOptionsBase, 'release'> &
*/
// eslint-disable-next-line typescript/no-deprecated
sourceMapsUploadOptions?: SourceMapsOptions;
// eslint-disable-next-line typescript/no-deprecated
} & DeprecatedRuntimeOptions;
};

/**
* Routes inside 'astro:routes:resolved' hook (Astro v5+)
Expand Down
8 changes: 0 additions & 8 deletions packages/astro/test/buildOptions.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ describe('Sentry Astro build-time options type', () => {
autoInstrumentation: {
requestHandler: true,
},

// Deprecated runtime options
environment: 'test',
dsn: 'https://test@sentry.io/123',
sampleRate: 1.0,
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
};

expectTypeOf(completeOptions).toEqualTypeOf<SentryOptions>();
Expand Down
33 changes: 14 additions & 19 deletions packages/astro/test/integration/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -524,38 +524,33 @@ describe('sentryAstro integration', () => {
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('Sentry.init'));
});

it('injects runtime config into client and server init scripts and warns about deprecation', async () => {
it('passes build-time release options to the Sentry vite plugin and init snippets', async () => {
const integration = sentryAstro({
project: 'my-project',
environment: 'test',
release: '1.0.0',
dsn: 'https://test.sentry.io/123',
bundleSizeOptimizations: {},
// this also warns when debug is not enabled
release: { name: '1.0.0' },
debug: true,
});

const logger = {
warn: vi.fn(),
info: vi.fn(),
};

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config, logger });
await integration.hooks['astro:config:setup']({ ...baseConfigHookObject, updateConfig, injectScript, config });

expect(logger.warn).toHaveBeenCalledWith(
'You passed in additional options (environment, release, dsn) to the Sentry integration. This is deprecated and will stop working in a future version. Instead, configure the Sentry SDK in your `sentry.client.config.(js|ts)` or `sentry.server.config.(js|ts)` files.',
expect(sentryVitePluginSpy).toHaveBeenCalledWith(
expect.objectContaining({
release: { name: '1.0.0' },
debug: true,
}),
);

expect(injectScript).toHaveBeenCalledTimes(2);
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('Sentry.init'));
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('dsn: "https://test.sentry.io/123"'));
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('release: "1.0.0"'));
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('environment: "test"'));
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('Sentry.init'));
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('dsn: "https://test.sentry.io/123"'));
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('debug: true'));
expect(injectScript).toHaveBeenCalledWith(
'page',
expect.stringContaining('dsn: import.meta.env.PUBLIC_SENTRY_DSN'),
);
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('release: "1.0.0"'));
expect(injectScript).toHaveBeenCalledWith('page-ssr', expect.stringContaining('environment: "test"'));
});

it("doesn't inject client init script if `enabled.client` is `false`", async () => {
Expand Down
Loading
Loading