Skip to content

Commit dac4c3a

Browse files
mydeaclaude
andcommitted
feat(node): Add build-time opt-out for runtime channel injection
Introduce a `__SENTRY_CHANNEL_INJECTION__` treeshaking flag (mirroring `__SENTRY_TRACING__`) that removes the runtime diagnostics-channel injection when text-replaced with `false`, and expose it through the bundler plugins' `bundleSizeOptimizations.excludeChannelInjection`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 1718e70 commit dac4c3a

5 files changed

Lines changed: 45 additions & 4 deletions

File tree

packages/bundler-plugins/src/core/build-plugin-manager.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ export function createSentryBuildPluginManager(
335335
if (bundleSizeOptimizations.excludeTracing) {
336336
bundleSizeOptimizationReplacementValues['__SENTRY_TRACING__'] = false;
337337
}
338+
if (bundleSizeOptimizations.excludeChannelInjection) {
339+
bundleSizeOptimizationReplacementValues['__SENTRY_CHANNEL_INJECTION__'] = false;
340+
}
338341
if (bundleSizeOptimizations.excludeReplayCanvas) {
339342
bundleSizeOptimizationReplacementValues['__RRWEB_EXCLUDE_CANVAS__'] = true;
340343
}

packages/bundler-plugins/src/core/options-mapping.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export type NormalizedOptions = {
6060
| {
6161
excludeDebugStatements?: boolean;
6262
excludeTracing?: boolean;
63+
excludeChannelInjection?: boolean;
6364
excludeReplayCanvas?: boolean;
6465
excludeReplayShadowDom?: boolean;
6566
excludeReplayIframe?: boolean;

packages/bundler-plugins/src/core/types.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,21 @@ export interface Options {
303303
*/
304304
excludeTracing?: boolean;
305305

306+
/**
307+
* Exclude the Node SDK's runtime diagnostics-channel injection from the bundle.
308+
*
309+
* If set to `true`, the plugin will attempt to tree-shake (remove) code that installs the Node SDK's
310+
* runtime module hooks (e.g. for Express instrumentation) at load time. Note that the success of this
311+
* depends on tree-shaking being enabled in your build tooling.
312+
*
313+
* Only enable this when the diagnostics channels are injected at build time (via the bundler plugin) or
314+
* when you otherwise do not rely on the runtime channel injection. This is equivalent to setting
315+
* `enableRuntimeChannelInjection: false` in the SDK's `init` options.
316+
*
317+
* @default false
318+
*/
319+
excludeChannelInjection?: boolean;
320+
306321
/**
307322
* If set to `true`, the plugin will attempt to tree-shake (remove) code related to the Sentry SDK's Session Replay Canvas recording functionality.
308323
* Note that the success of this depends on tree-shaking being enabled in your build tooling.
@@ -526,6 +541,7 @@ export type IncludeEntry = {
526541
export interface SentrySDKBuildFlags extends Record<string, boolean | undefined> {
527542
__SENTRY_DEBUG__?: boolean;
528543
__SENTRY_TRACING__?: boolean;
544+
__SENTRY_CHANNEL_INJECTION__?: boolean;
529545
__RRWEB_EXCLUDE_CANVAS__?: boolean;
530546
__RRWEB_EXCLUDE_IFRAME__?: boolean;
531547
__RRWEB_EXCLUDE_SHADOW_DOM__?: boolean;

packages/node/src/sdk/index.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import { defaultStackParser, getSentryRelease } from './api';
4141
import { NodeClient } from './client';
4242
import { initOpenTelemetry } from './initOtel';
4343

44+
// Treeshakable guard to remove all code related to runtime diagnostics-channel injection. Set to
45+
// `false` at build time by the Sentry bundler plugins' `bundleSizeOptimizations.excludeChannelInjection`.
46+
declare const __SENTRY_CHANNEL_INJECTION__: boolean | undefined;
47+
4448
/**
4549
* Get the base default integrations shared by all Node SDK default-integration sets.
4650
*/
@@ -155,10 +159,13 @@ function _init(
155159
};
156160

157161
// Install the channel-based (orchestrion diagnostics-channel) instrumentation hooks by default,
158-
// independent of tracing — the channel integrations also capture errors, not just spans. Opt out
159-
// with `enableRuntimeChannelInjection: false`. Install as early as possible, before the app imports
160-
// its instrumented modules.
161-
const useChannelInjection = options.enableRuntimeChannelInjection !== false;
162+
// independent of tracing — the channel integrations also capture errors, not just spans. Opt out at
163+
// runtime with `enableRuntimeChannelInjection: false`, or at build time via the bundler plugins'
164+
// `bundleSizeOptimizations.excludeChannelInjection` (which tree-shakes this whole block away).
165+
// Install as early as possible, before the app imports its instrumented modules.
166+
const useChannelInjection =
167+
(typeof __SENTRY_CHANNEL_INJECTION__ === 'undefined' || __SENTRY_CHANNEL_INJECTION__) &&
168+
options.enableRuntimeChannelInjection !== false;
162169
if (useChannelInjection) {
163170
registerDiagnosticsChannelInjection();
164171
}

packages/node/test/sdk/diagnosticsChannelInjection.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,18 @@ describe('diagnostics-channel injection', () => {
6868
expect(registerDiagnosticsChannelInjection).toHaveBeenCalledTimes(1);
6969
expect(detectOrchestrionSetup).toHaveBeenCalledTimes(1);
7070
});
71+
72+
it('does not register the injection hooks but still runs detection when the `__SENTRY_CHANNEL_INJECTION__` build flag is false', () => {
73+
// Simulates the bundler plugins' `bundleSizeOptimizations.excludeChannelInjection` text-replacing the flag.
74+
vi.stubGlobal('__SENTRY_CHANNEL_INJECTION__', false);
75+
76+
try {
77+
init({ dsn: PUBLIC_DSN, tracesSampleRate: 1, enableOpenTelemetrySetup: false });
78+
79+
expect(registerDiagnosticsChannelInjection).not.toHaveBeenCalled();
80+
expect(detectOrchestrionSetup).toHaveBeenCalledTimes(1);
81+
} finally {
82+
vi.unstubAllGlobals();
83+
}
84+
});
7185
});

0 commit comments

Comments
 (0)