Skip to content

Commit f6f52ff

Browse files
committed
feat(node): Do not add HTTP & fetch span instrumentation if tracing is disabled
1 parent 90cb4d1 commit f6f52ff

File tree

3 files changed

+36
-8
lines changed

3 files changed

+36
-8
lines changed

packages/node/src/integrations/http/index.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { diag } from '@opentelemetry/api';
33
import type { HttpInstrumentationConfig } from '@opentelemetry/instrumentation-http';
44
import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
55
import type { Span } from '@sentry/core';
6-
import { defineIntegration, getClient } from '@sentry/core';
6+
import { defineIntegration, getClient, hasSpansEnabled } from '@sentry/core';
7+
import { NODE_VERSION } from '../../nodeVersion';
78
import { generateInstrumentOnce } from '../../otel/instrument';
89
import type { NodeClient } from '../../sdk/client';
910
import type { HTTPModuleRequestIncomingMessage } from '../../transports/http-module';
@@ -159,8 +160,22 @@ export const instrumentOtelHttp = generateInstrumentOnce<HttpInstrumentationConf
159160
/** Exported only for tests. */
160161
export function _shouldInstrumentSpans(options: HttpOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {
161162
// If `spans` is passed in, it takes precedence
162-
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true`
163-
return typeof options.spans === 'boolean' ? options.spans : !clientOptions.skipOpenTelemetrySetup;
163+
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled
164+
if (typeof options.spans === 'boolean') {
165+
return options.spans;
166+
}
167+
168+
if (clientOptions.skipOpenTelemetrySetup) {
169+
return false;
170+
}
171+
172+
// IMPORTANT: We only disable span instrumentation when spans are not enabled _and_ we are on Node 22+,
173+
// as otherwise the necessary diagnostics channel is not available yet
174+
if (!hasSpansEnabled(clientOptions) && NODE_VERSION.major >= 22) {
175+
return false;
176+
}
177+
178+
return true;
164179
}
165180

166181
/**

packages/node/src/integrations/node-fetch/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { UndiciInstrumentationConfig } from '@opentelemetry/instrumentation-undici';
22
import { UndiciInstrumentation } from '@opentelemetry/instrumentation-undici';
33
import type { IntegrationFn } from '@sentry/core';
4-
import { defineIntegration, getClient, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
4+
import { defineIntegration, getClient, hasSpansEnabled, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core';
55
import { generateInstrumentOnce } from '../../otel/instrument';
66
import type { NodeClient } from '../../sdk/client';
77
import type { NodeClientOptions } from '../../types';
@@ -86,8 +86,10 @@ function getAbsoluteUrl(origin: string, path: string = '/'): string {
8686

8787
function _shouldInstrumentSpans(options: NodeFetchOptions, clientOptions: Partial<NodeClientOptions> = {}): boolean {
8888
// If `spans` is passed in, it takes precedence
89-
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true`
90-
return typeof options.spans === 'boolean' ? options.spans : !clientOptions.skipOpenTelemetrySetup;
89+
// Else, we by default emit spans, unless `skipOpenTelemetrySetup` is set to `true` or spans are not enabled
90+
return typeof options.spans === 'boolean'
91+
? options.spans
92+
: !clientOptions.skipOpenTelemetrySetup && hasSpansEnabled(clientOptions);
9193
}
9294

9395
function getConfigWithDefaults(options: Partial<NodeFetchOptions> = {}): UndiciInstrumentationConfig {
Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
import { describe, expect, it } from 'vitest';
22
import { _shouldInstrumentSpans } from '../../src/integrations/http';
3+
import { conditionalTest } from '../helpers/conditional';
34

45
describe('httpIntegration', () => {
56
describe('_shouldInstrumentSpans', () => {
67
it.each([
7-
[{}, {}, true],
88
[{ spans: true }, {}, true],
99
[{ spans: false }, {}, false],
1010
[{ spans: true }, { skipOpenTelemetrySetup: true }, true],
1111
[{ spans: false }, { skipOpenTelemetrySetup: true }, false],
1212
[{}, { skipOpenTelemetrySetup: true }, false],
13-
[{}, { skipOpenTelemetrySetup: false }, true],
13+
[{}, { tracesSampleRate: 0, skipOpenTelemetrySetup: true }, false],
14+
[{}, { tracesSampleRate: 0 }, true],
1415
])('returns the correct value for options=%j and clientOptions=%j', (options, clientOptions, expected) => {
1516
const actual = _shouldInstrumentSpans(options, clientOptions);
1617
expect(actual).toBe(expected);
1718
});
19+
20+
conditionalTest({ min: 22 })('returns false without tracesSampleRate on Node >=22', () => {
21+
const actual = _shouldInstrumentSpans({}, {});
22+
expect(actual).toBe(false);
23+
});
24+
25+
conditionalTest({ max: 21 })('returns true without tracesSampleRate on Node <22', () => {
26+
const actual = _shouldInstrumentSpans({}, {});
27+
expect(actual).toBe(true);
28+
});
1829
});
1930
});

0 commit comments

Comments
 (0)