Skip to content

Commit 6a1e720

Browse files
committed
Honor SENTRY_TRACES_SAMPLE_RATE in the diagnostics-channel injection gate
1 parent 58a581d commit 6a1e720

3 files changed

Lines changed: 54 additions & 3 deletions

File tree

packages/node/src/sdk/diagnosticsChannelInjection.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ let cached: DiagnosticsChannelInjection | undefined;
3535
*/
3636
export function setDiagnosticsChannelInjectionLoader(load: () => DiagnosticsChannelInjection): void {
3737
loader = load;
38+
// Invalidate the memoized result so a newly set loader resolves fresh.
39+
cached = undefined;
3840
}
3941

4042
/** Whether `experimentalUseDiagnosticsChannelInjection()` was called. */

packages/node/src/sdk/index.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ import {
1616
} from './diagnosticsChannelInjection';
1717
import { initOpenTelemetry } from './initOtel';
1818

19+
/**
20+
* Whether span recording is enabled, including the `SENTRY_TRACES_SAMPLE_RATE` env var that node-core
21+
* resolves later. `hasSpansEnabled` only inspects the options object, so on init paths that enable
22+
* tracing purely through the env var (e.g. the `@sentry/aws-serverless` Lambda auto-init) it would
23+
* otherwise report `false` and skip the diagnostics-channel injection swap and hook registration.
24+
*/
25+
function hasSpansEnabledIncludingEnv(options: Options): boolean {
26+
return (
27+
hasSpansEnabled(options) ||
28+
(options.tracesSampleRate == null && !options.tracesSampler && !!process.env.SENTRY_TRACES_SAMPLE_RATE)
29+
);
30+
}
31+
1932
/**
2033
* Get default integrations, excluding performance.
2134
*/
@@ -61,7 +74,7 @@ export function applyDiagnosticsChannelInjectionIntegrations(
6174
integrations: Integration[],
6275
options: Options,
6376
): Integration[] {
64-
if (isDiagnosticsChannelInjectionEnabled() && hasSpansEnabled(options)) {
77+
if (isDiagnosticsChannelInjectionEnabled() && hasSpansEnabledIncludingEnv(options)) {
6578
const diagnosticsChannelInjection = resolveDiagnosticsChannelInjection();
6679
if (diagnosticsChannelInjection) {
6780
const replaced = new Set(diagnosticsChannelInjection.replacedOtelIntegrationNames);
@@ -90,9 +103,12 @@ function _init(
90103
// EXPERIMENTAL: diagnostics-channel injection, opted into via
91104
// `experimentalUseDiagnosticsChannelInjection()`. Gated on span recording to
92105
// match the OTel integrations it replaces. With tracing off there are no
93-
// channel subscribers, so injecting is pointless work.
106+
// channel subscribers, so injecting is pointless work. The env var is included
107+
// because node-core resolves `SENTRY_TRACES_SAMPLE_RATE` later, and without it
108+
// the auto-init path (pre-built `integrations`) would skip `register()` and
109+
// never install the module hooks, silently emitting no spans.
94110
const diagnosticsChannelInjection =
95-
isDiagnosticsChannelInjectionEnabled() && hasSpansEnabled(options)
111+
isDiagnosticsChannelInjectionEnabled() && hasSpansEnabledIncludingEnv(options)
96112
? resolveDiagnosticsChannelInjection()
97113
: undefined;
98114

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

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,37 @@ describe('diagnostics-channel injection integration swap', () => {
114114

115115
expect(channelNoDefaults.setupOnce).not.toHaveBeenCalled();
116116
});
117+
118+
it('swaps integrations and registers hooks when tracing is enabled only via SENTRY_TRACES_SAMPLE_RATE', () => {
119+
// The auto-init path (e.g. `@sentry/aws-serverless`) enables tracing through the env var, not the
120+
// options object. `hasSpansEnabled(options)` alone reports false there, so the swap and
121+
// `register()` must still fire from the env-derived rate or spans silently never emit.
122+
const channelEnvMysql = mockIntegration('EnvMysql');
123+
const register = vi.fn();
124+
setDiagnosticsChannelInjectionLoader(() => ({
125+
integrations: [channelEnvMysql],
126+
replacedOtelIntegrationNames: ['EnvMysql'],
127+
register,
128+
detect: vi.fn(),
129+
}));
130+
131+
const otelEnvMysql = mockIntegration('EnvMysql');
132+
const http = mockIntegration('EnvHttp');
133+
134+
vi.stubEnv('SENTRY_TRACES_SAMPLE_RATE', '1');
135+
try {
136+
init({
137+
dsn: PUBLIC_DSN,
138+
skipOpenTelemetrySetup: true,
139+
defaultIntegrations: [otelEnvMysql, http],
140+
});
141+
} finally {
142+
vi.unstubAllEnvs();
143+
}
144+
145+
expect(otelEnvMysql.setupOnce).not.toHaveBeenCalled();
146+
expect(channelEnvMysql.setupOnce).toHaveBeenCalledTimes(1);
147+
expect(http.setupOnce).toHaveBeenCalledTimes(1);
148+
expect(register).toHaveBeenCalledTimes(1);
149+
});
117150
});

0 commit comments

Comments
 (0)