diff --git a/MIGRATION.md b/MIGRATION.md index b173b0714d68..7f4b90b975fa 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -626,6 +626,23 @@ Affected SDKs: `@sentry/cloudflare`. + import { wrapRequestHandler } from '@sentry/cloudflare/request'; ``` +### Cloudflare: the Vite plugin auto-instruments your Worker by default + +Affected SDKs: `@sentry/cloudflare`. + +`sentryCloudflareVitePlugin()` now wraps your Worker entry — and any Durable Object, Workflow or WorkerEntrypoint class listed in your wrangler config — at build time. Entries you already wrapped yourself are left untouched, so no action is required for most users. Opt out with the new top-level `autoInstrumentation` option: + +```js +sentryCloudflareVitePlugin({ autoInstrumentation: false }); +``` + +The experimental opt-in this replaces was removed: + +```diff +- sentryCloudflareVitePlugin({ _experimental: { autoInstrumentation: true } }); ++ sentryCloudflareVitePlugin(); +``` + ## 3. Removed APIs ### `@sentry/core` / All SDKs diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-chained/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-chained/vite.config.mts index 34eb08bdcdcf..5819d3719a56 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-chained/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-chained/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry, the self-bound `CounterEntrypoint`, and the `Counter` Durable Object // before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-manual-mixed/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-manual-mixed/vite.config.mts index a669042495e9..f49d6f365c91 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-manual-mixed/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do-manual-mixed/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform runs over the // worker entry — it must skip the manually wrapped `Counter` Durable Object // and only auto-wrap the plain `GreeterEntrypoint` and default export. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do/vite.config.mts index 4a71fda44344..08a487c326bf 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/combination-entrypoint-do/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry, the self-bound `GreeterEntrypoint`, and the `Counter` Durable Object // before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/default-export/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/default-export/vite.config.mts index ec756a37ed0e..60a7e746bae9 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/default-export/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/default-export/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker's // default export before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-manual-wrap/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-manual-wrap/vite.config.mts index 940cc5b002bf..1323745508ab 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-manual-wrap/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-manual-wrap/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform runs over the // worker entry — it must skip the manually wrapped `Counter` and only wrap // the plain default export. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-mixed/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-mixed/vite.config.mts index 7a2c4dc4d75a..d344d0245557 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-mixed/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-mixed/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform skips the manually // wrapped `Manual` DO and auto-wraps `Auto` before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-multiple/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-multiple/vite.config.mts index 770531239ab7..ae40759ffe82 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-multiple/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-multiple/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and both Durable Object classes before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-reexport-instrumented/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-reexport-instrumented/vite.config.mts index 519ddddca31c..f6e79c8cfc78 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-reexport-instrumented/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-reexport-instrumented/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform runs over the // worker entry — it must skip the imported/re-exported `Counter` (wrapped in // `./counter`) and only wrap the plain default export. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier-alias/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier-alias/vite.config.mts index 842d83510d2d..4aa78f6b2f19 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier-alias/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier-alias/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and the aliased Durable Object class before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier/vite.config.mts index efd0e098c528..0507bc90e040 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-specifier/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and the `Counter` Durable Object before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-manual-mixed/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-manual-mixed/vite.config.mts index 5a47364942aa..a1c43a84ce7a 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-manual-mixed/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-manual-mixed/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform skips the manually // wrapped `Counter` Durable Object and auto-wraps the `MyWorkflow` Workflow // before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-specifier/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-specifier/vite.config.mts index 47ee9a8178fb..036d492d41f5 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-specifier/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow-specifier/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and both specifier-exported classes before the Cloudflare plugin // bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow/vite.config.mts index 1d09acff5c6f..aa5bc59c0982 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject-workflow/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry, the `Counter` Durable Object, and the `MyWorkflow` Workflow before the // Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject/vite.config.mts index efd0e098c528..0507bc90e040 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/durableobject/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and the `Counter` Durable Object before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workerentrypoint/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workerentrypoint/vite.config.mts index f68e50f0019d..40415c06e761 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workerentrypoint/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workerentrypoint/vite.config.mts @@ -6,12 +6,5 @@ export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and the self-bound `GreeterEntrypoint` before the Cloudflare plugin // bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workflow/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workflow/vite.config.mts index 49cd4b297b8e..23781cdde6cf 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workflow/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite-autoinstrument/workflow/vite.config.mts @@ -5,12 +5,5 @@ import { defineConfig } from 'vite'; export default defineConfig({ // The Sentry plugin runs first so its build-time transform wraps the worker // entry and the `MyWorkflow` class before the Cloudflare plugin bundles it. - plugins: [ - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/dev-packages/cloudflare-integration-tests/suites/vite/diagnostics-channel/client-build/vite.config.mts b/dev-packages/cloudflare-integration-tests/suites/vite/diagnostics-channel/client-build/vite.config.mts index 005f4448f6cb..323fa4f10351 100644 --- a/dev-packages/cloudflare-integration-tests/suites/vite/diagnostics-channel/client-build/vite.config.mts +++ b/dev-packages/cloudflare-integration-tests/suites/vite/diagnostics-channel/client-build/vite.config.mts @@ -3,5 +3,7 @@ import { sentryCloudflareVitePlugin } from '@sentry/cloudflare/vite'; import { defineConfig } from 'vite'; export default defineConfig({ - plugins: [cloudflare(), sentryCloudflareVitePlugin()], + // Auto-instrumentation is off so this suite exercises the orchestrion + // transform alone — the worker entry stays untouched. + plugins: [cloudflare(), sentryCloudflareVitePlugin({ autoInstrumentation: false })], }); diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/src/index.ts b/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/src/index.ts index 5026f1fbd13b..8ed8c4e8f21c 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/src/index.ts +++ b/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/src/index.ts @@ -5,7 +5,7 @@ import { MyBase } from './base'; // NOTE: this file deliberately contains NO `Sentry.*` calls and no import of // `@sentry/cloudflare`. Everything below is wrapped at build time by -// `sentryCloudflareVitePlugin({ _experimental: { autoInstrumentation: true } })`, +// `sentryCloudflareVitePlugin()`, // which reads wrangler.jsonc, wraps the default export with `withSentry`, and // picks a wrapper per class: `instrumentAgentWithSentry` for the three Agents, // `instrumentDurableObjectWithSentry` for the plain Durable Object. diff --git a/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/vite.config.ts b/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/vite.config.ts index 55e45b9a9b6f..397c14bb166a 100644 --- a/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/vite.config.ts +++ b/dev-packages/e2e-tests/test-applications/cloudflare-autoinstrument/vite.config.ts @@ -4,16 +4,8 @@ import agents from 'agents/vite'; import { defineConfig } from 'vite'; // `agents()` supplies the TC39 decorator transform that `@callable()` needs. -// `autoInstrumentation` is the plugin under test: it rewrites `src/index.ts` at -// build time so the entry itself contains no Sentry calls. +// Auto-instrumentation is the plugin behavior under test: it rewrites +// `src/index.ts` at build time so the entry itself contains no Sentry calls. export default defineConfig({ - plugins: [ - agents(), - cloudflare(), - sentryCloudflareVitePlugin({ - _experimental: { - autoInstrumentation: true, - }, - }), - ], + plugins: [agents(), cloudflare(), sentryCloudflareVitePlugin()], }); diff --git a/packages/cloudflare/src/vite/index.ts b/packages/cloudflare/src/vite/index.ts index b87b5ebef763..f1fcb6b739b3 100644 --- a/packages/cloudflare/src/vite/index.ts +++ b/packages/cloudflare/src/vite/index.ts @@ -36,34 +36,34 @@ export interface SentryCloudflareVitePluginOptions { */ buildTimeInstrumentation?: boolean; /** - * Experimental options that may change or be removed without notice. + * Automatically wraps your Worker at build time so you don't have to edit + * your entry: the plugin reads your wrangler config, wraps the default + * export with `Sentry.withSentry()` (sourcing options from a co-located + * `instrument.*` file, falling back to env), and wraps any configured + * Durable Object class with `instrumentDurableObjectWithSentry`. Both + * `vite build` and `vite dev` are instrumented. Already-wrapped entries are + * left alone, so this is safe alongside manual instrumentation. Set to + * `false` to opt out. + * + * @default true */ - _experimental?: { - /** - * Automatically wraps your Worker at build time so you don't have to edit - * your entry: the plugin reads your wrangler config, wraps the default - * export with `Sentry.withSentry()` (sourcing options from a co-located - * `instrument.*` file, falling back to env), and wraps any configured - * Durable Object class with `instrumentDurableObjectWithSentry`. Both - * `vite build` and `vite dev` are instrumented. - * - * @default false - * @experimental May change or be removed in any release. - */ - autoInstrumentation?: boolean; - }; + autoInstrumentation?: boolean; } /** * Sentry Vite plugin for Cloudflare Workers. * * Add this plugin to your Vite configuration to enable additional Sentry - * instrumentation for Cloudflare Workers built with Vite. Configure the Sentry - * SDK in your Worker as usual with `Sentry.withSentry()`. + * instrumentation for Cloudflare Workers built with Vite. * - * By default, the plugin build-time instruments supported dependencies (such as - * database clients) so they are traced without changing your application code. - * Opt out with `buildTimeInstrumentation: false`. + * By default, the plugin + * - build-time instruments supported dependencies (such as database clients) so + * they are traced without changing your application code — opt out with + * `buildTimeInstrumentation: false`, and + * - wraps your Worker entry (and any Durable Object, Workflow or + * WorkerEntrypoint class in your wrangler config) with the matching Sentry + * helper — opt out with `autoInstrumentation: false` and call + * `Sentry.withSentry()` yourself. * * @example * ```ts @@ -82,7 +82,7 @@ export function sentryCloudflareVitePlugin(options: SentryCloudflareVitePluginOp sentryOrchestrionPlugin({ buildTimeInstrumentation: options.buildTimeInstrumentation, }), - ...(options._experimental?.autoInstrumentation + ...(options.autoInstrumentation !== false ? [sentryCloudflareAutoInstrumentPlugin({ wranglerConfigPath: options.wranglerConfigPath })] : []), ]; diff --git a/packages/cloudflare/test/vite/index.test.ts b/packages/cloudflare/test/vite/index.test.ts new file mode 100644 index 000000000000..8559ef1123c6 --- /dev/null +++ b/packages/cloudflare/test/vite/index.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from 'vitest'; +import { sentryCloudflareVitePlugin } from '../../src/vite/index'; + +const AUTO_INSTRUMENT_PLUGIN = 'sentry-cloudflare-auto-instrument'; + +function pluginNames(options?: Parameters[0]): string[] { + return sentryCloudflareVitePlugin(options).map(plugin => plugin.name); +} + +describe('sentryCloudflareVitePlugin', () => { + it('enables auto-instrumentation by default', () => { + expect(pluginNames()).toContain(AUTO_INSTRUMENT_PLUGIN); + }); + + it('omits the auto-instrument plugin when opted out', () => { + expect(pluginNames({ autoInstrumentation: false })).not.toContain(AUTO_INSTRUMENT_PLUGIN); + }); + + it('returns an inert orchestrion plugin when build-time instrumentation is disabled', () => { + expect(pluginNames({ buildTimeInstrumentation: false })).toContain('sentry-orchestrion-disabled'); + }); +});