From cc60da0078bd7b69eee457f3cd5918a2a5b42034 Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 31 Jul 2026 10:40:00 +0200 Subject: [PATCH 1/2] e2e --- .../tanstackstart-react-orchestrion/package.json | 1 - .../tanstackstart-react-orchestrion/vite.config.ts | 5 ----- 2 files changed, 6 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/package.json b/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/package.json index acc3d04b3a5a..0e391842cbf8 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/package.json +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/package.json @@ -15,7 +15,6 @@ "//": "Need to use ioredis 5.10.1 because that's the last version before they support tracing channels", "dependencies": { "@sentry/tanstackstart-react": "file:../../packed/sentry-tanstackstart-react-packed.tgz", - "@sentry/server-utils": "file:../../packed/sentry-server-utils-packed.tgz", "@tanstack/react-start": "^1.136.0", "@tanstack/react-router": "^1.136.0", "react": "^19.2.0", diff --git a/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/vite.config.ts b/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/vite.config.ts index 5930d075be33..2821a3eb25f7 100644 --- a/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/vite.config.ts +++ b/dev-packages/e2e-tests/test-applications/tanstackstart-react-orchestrion/vite.config.ts @@ -4,7 +4,6 @@ import { tanstackStart } from '@tanstack/react-start/plugin/vite'; import viteReact from '@vitejs/plugin-react-swc'; import { nitro } from 'nitro/vite'; import { sentryTanstackStart } from '@sentry/tanstackstart-react/vite'; -import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite'; const appDsn = 'http://public@localhost:3031/1337'; @@ -28,9 +27,5 @@ export default defineConfig({ authToken: process.env.E2E_TEST_AUTH_TOKEN, debug: true, }), - // Runs the orchestrion code transform over the server bundle and - // force-bundles the instrumented deps (mysql, ioredis, …) so the - // diagnostics-channel calls are actually injected. - sentryOrchestrionPlugin(), ], }); From 84a2917a64c5e4bbcab5e487f0ec9fab229006be Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Fri, 31 Jul 2026 10:40:07 +0200 Subject: [PATCH 2/2] auto-wire --- packages/tanstackstart-react/package.json | 1 + .../src/vite/sentryTanstackStart.ts | 6 ++ .../test/vite/sentryTanstackStart.test.ts | 68 +++++++++++++++++-- 3 files changed, 71 insertions(+), 4 deletions(-) diff --git a/packages/tanstackstart-react/package.json b/packages/tanstackstart-react/package.json index 789f10e39165..7a4771b2baa2 100644 --- a/packages/tanstackstart-react/package.json +++ b/packages/tanstackstart-react/package.json @@ -62,6 +62,7 @@ "@sentry/core": "10.67.0", "@sentry/node": "10.67.0", "@sentry/react": "10.67.0", + "@sentry/server-utils": "10.67.0", "@sentry/bundler-plugins": "10.67.0" }, "devDependencies": { diff --git a/packages/tanstackstart-react/src/vite/sentryTanstackStart.ts b/packages/tanstackstart-react/src/vite/sentryTanstackStart.ts index a440e791e242..0dd7f9f12fda 100644 --- a/packages/tanstackstart-react/src/vite/sentryTanstackStart.ts +++ b/packages/tanstackstart-react/src/vite/sentryTanstackStart.ts @@ -1,4 +1,5 @@ import type { BuildTimeOptionsBase } from '@sentry/core'; +import { sentryOrchestrionPlugin } from '@sentry/server-utils/orchestrion/vite'; import type { Plugin } from 'vite'; import { makeAutoInstrumentMiddlewarePlugin } from './autoInstrumentMiddleware'; import { makeRoutePatternPlugin } from './routePatterns'; @@ -96,6 +97,11 @@ export function sentryTanstackStart(options: SentryTanstackStartOptions = {}): P return plugins; } + // Runs the orchestrion code transform over the server bundle so instrumented DB drivers get + // `diagnostics_channel` publishers injected. Production-only: it force-bundles the instrumented + // (CommonJS) deps via `ssr.noExternal`, which the `vite dev` SSR module runner can't evaluate. + plugins.push(sentryOrchestrionPlugin({ buildTimeInstrumentation: options.buildTimeInstrumentation })); + plugins.push(...makeAddSentryVitePlugin(options)); // middleware auto-instrumentation diff --git a/packages/tanstackstart-react/test/vite/sentryTanstackStart.test.ts b/packages/tanstackstart-react/test/vite/sentryTanstackStart.test.ts index cba4508de1a1..0715873cdfa5 100644 --- a/packages/tanstackstart-react/test/vite/sentryTanstackStart.test.ts +++ b/packages/tanstackstart-react/test/vite/sentryTanstackStart.test.ts @@ -41,6 +41,17 @@ const mockRoutePatternPlugin: Plugin = { config: vi.fn(), }; +// Stub the orchestrion plugin so these stay pure wiring tests (no apm code transformer pulled in). +// Mirror the real plugin's contract: `buildTimeInstrumentation: false` yields the inert variant. +const orchestrionVite = vi.fn((options?: { buildTimeInstrumentation?: boolean }) => ({ + name: options?.buildTimeInstrumentation === false ? 'sentry-orchestrion-disabled' : 'sentry-orchestrion-vite', +})); +vi.mock('@sentry/server-utils/orchestrion/vite', () => ({ + sentryOrchestrionPlugin: (options?: { buildTimeInstrumentation?: boolean }) => orchestrionVite(options), +})); + +const mockOrchestrionPlugin: Plugin = { name: 'sentry-orchestrion-vite' }; + vi.mock('../../src/vite/routePatterns', () => ({ makeRoutePatternPlugin: vi.fn(() => mockRoutePatternPlugin), })); @@ -74,13 +85,14 @@ describe('sentryTanstackStart()', () => { expect(plugins).toEqual([ mockRoutePatternPlugin, + mockOrchestrionPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockEnableSourceMapsPlugin, ]); }); - it('returns no plugins in development mode when tunnelRoute is not configured', () => { + it('returns no build-time plugins in development mode when tunnelRoute is not configured', () => { process.env.NODE_ENV = 'development'; const plugins = sentryTanstackStart({ autoInstrumentMiddleware: false }); @@ -105,7 +117,12 @@ describe('sentryTanstackStart()', () => { sourcemaps: { disable: true }, }); - expect(plugins).toEqual([mockRoutePatternPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]); + expect(plugins).toEqual([ + mockRoutePatternPlugin, + mockOrchestrionPlugin, + mockSourceMapsConfigPlugin, + mockSentryVitePlugin, + ]); }); it('returns Sentry Vite plugins but not enable source maps plugin when sourcemaps.disable is "disable-upload"', () => { @@ -114,7 +131,12 @@ describe('sentryTanstackStart()', () => { sourcemaps: { disable: 'disable-upload' }, }); - expect(plugins).toEqual([mockRoutePatternPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]); + expect(plugins).toEqual([ + mockRoutePatternPlugin, + mockOrchestrionPlugin, + mockSourceMapsConfigPlugin, + mockSentryVitePlugin, + ]); }); it('returns Sentry Vite plugins and enable source maps plugin when sourcemaps.disable is false', () => { @@ -125,6 +147,7 @@ describe('sentryTanstackStart()', () => { expect(plugins).toEqual([ mockRoutePatternPlugin, + mockOrchestrionPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockEnableSourceMapsPlugin, @@ -138,6 +161,7 @@ describe('sentryTanstackStart()', () => { expect(plugins).toEqual([ mockRoutePatternPlugin, + mockOrchestrionPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockMiddlewarePlugin, @@ -152,6 +176,7 @@ describe('sentryTanstackStart()', () => { expect(plugins).toEqual([ mockRoutePatternPlugin, + mockOrchestrionPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockMiddlewarePlugin, @@ -164,7 +189,12 @@ describe('sentryTanstackStart()', () => { sourcemaps: { disable: true }, }); - expect(plugins).toEqual([mockRoutePatternPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin]); + expect(plugins).toEqual([ + mockRoutePatternPlugin, + mockOrchestrionPlugin, + mockSourceMapsConfigPlugin, + mockSentryVitePlugin, + ]); }); it('passes correct options to makeAutoInstrumentMiddlewarePlugin', () => { @@ -193,6 +223,7 @@ describe('sentryTanstackStart()', () => { expect(plugins).toEqual([ mockRoutePatternPlugin, mockTunnelRoutePlugin, + mockOrchestrionPlugin, mockSourceMapsConfigPlugin, mockSentryVitePlugin, mockMiddlewarePlugin, @@ -213,4 +244,33 @@ describe('sentryTanstackStart()', () => { expect(makeTunnelRoutePlugin).toHaveBeenCalledWith(options.tunnelRoute, undefined); }); }); + + describe('orchestrion build-time instrumentation', () => { + it('adds the orchestrion plugin by default', () => { + const plugins = sentryTanstackStart({ sourcemaps: { disable: true } }); + + expect(orchestrionVite).toHaveBeenCalledWith({ buildTimeInstrumentation: undefined }); + expect(plugins.map(plugin => plugin.name)).toContain('sentry-orchestrion-vite'); + }); + + it('does not add the orchestrion plugin in development mode', () => { + process.env.NODE_ENV = 'development'; + + const plugins = sentryTanstackStart({ sourcemaps: { disable: true } }); + + // Orchestrion force-bundles the instrumented (CommonJS) deps via `ssr.noExternal`, which the + // `vite dev` SSR module runner can't evaluate — so it's a production-only transform. + expect(orchestrionVite).not.toHaveBeenCalled(); + expect(plugins.map(plugin => plugin.name)).not.toContain('sentry-orchestrion-vite'); + }); + + it('adds an inert orchestrion plugin when `buildTimeInstrumentation` is `false`', () => { + const plugins = sentryTanstackStart({ buildTimeInstrumentation: false, sourcemaps: { disable: true } }); + const pluginNames = plugins.map(plugin => plugin.name); + + expect(orchestrionVite).toHaveBeenCalledWith({ buildTimeInstrumentation: false }); + expect(pluginNames).toContain('sentry-orchestrion-disabled'); + expect(pluginNames).not.toContain('sentry-orchestrion-vite'); + }); + }); });