Skip to content

Commit 447911a

Browse files
authored
feat(core): Rename hasTracingEnabled to hasSpansEnabled (#15309)
Rename the `hasTracingEnabled` utility function to `hasSpansEnabled`. The original name is causing confusion and doesn't represent what the function actually does: determining if the SDK is configured to record spans. This function does not check if trace propagation without span recording (or "Tracing without Performance") is enabled (which it basically always is).
1 parent 2780c3c commit 447911a

File tree

19 files changed

+91
-71
lines changed

19 files changed

+91
-71
lines changed

packages/browser/src/tracing/request.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
getActiveSpan,
1616
getLocationHref,
1717
getTraceData,
18-
hasTracingEnabled,
18+
hasSpansEnabled,
1919
instrumentFetchRequest,
2020
parseUrl,
2121
setHttpStatus,
@@ -322,7 +322,7 @@ export function xhrCallback(
322322
return undefined;
323323
}
324324

325-
const shouldCreateSpanResult = hasTracingEnabled() && shouldCreateSpan(sentryXhrData.url);
325+
const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(sentryXhrData.url);
326326

327327
// check first if the request has finished and is tracked by an existing span which should now end
328328
if (handlerData.endTimestamp && shouldCreateSpanResult) {
@@ -370,7 +370,7 @@ export function xhrCallback(
370370
// If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),
371371
// we do not want to use the span as base for the trace headers,
372372
// which means that the headers will be generated from the scope and the sampling decision is deferred
373-
hasTracingEnabled() && hasParent ? span : undefined,
373+
hasSpansEnabled() && hasParent ? span : undefined,
374374
);
375375
}
376376

packages/core/src/fetch.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import type { HandlerDataFetch, Span, SpanOrigin } from './types-hoist';
55
import { SENTRY_BAGGAGE_KEY_PREFIX } from './utils-hoist/baggage';
66
import { isInstanceOf } from './utils-hoist/is';
77
import { parseUrl } from './utils-hoist/url';
8-
import { hasTracingEnabled } from './utils/hasTracingEnabled';
8+
import { hasSpansEnabled } from './utils/hasSpansEnabled';
99
import { getActiveSpan } from './utils/spanUtils';
1010
import { getTraceData } from './utils/traceData';
1111

@@ -34,7 +34,7 @@ export function instrumentFetchRequest(
3434
return undefined;
3535
}
3636

37-
const shouldCreateSpanResult = hasTracingEnabled() && shouldCreateSpan(handlerData.fetchData.url);
37+
const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(handlerData.fetchData.url);
3838

3939
if (handlerData.endTimestamp && shouldCreateSpanResult) {
4040
const spanId = handlerData.fetchData.__span;
@@ -87,7 +87,7 @@ export function instrumentFetchRequest(
8787
// If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),
8888
// we do not want to use the span as base for the trace headers,
8989
// which means that the headers will be generated from the scope and the sampling decision is deferred
90-
hasTracingEnabled() && hasParent ? span : undefined,
90+
hasSpansEnabled() && hasParent ? span : undefined,
9191
);
9292
if (headers) {
9393
// Ensure this is actually set, if no options have been passed previously

packages/core/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ export {
6868
export { applyScopeDataToEvent, mergeScopeData } from './utils/applyScopeDataToEvent';
6969
export { prepareEvent } from './utils/prepareEvent';
7070
export { createCheckInEnvelope } from './checkin';
71-
export { hasTracingEnabled } from './utils/hasTracingEnabled';
71+
// eslint-disable-next-line deprecation/deprecation
72+
export { hasTracingEnabled } from './utils/hasSpansEnabled';
73+
export { hasSpansEnabled } from './utils/hasSpansEnabled';
7274
export { isSentryRequestUrl } from './utils/isSentryRequestUrl';
7375
export { handleCallbackErrors } from './utils/handleCallbackErrors';
7476
export { parameterize } from './utils/parameterize';

packages/core/src/tracing/dynamicSamplingContext.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
dynamicSamplingContextToSentryBaggageHeader,
1010
} from '../utils-hoist/baggage';
1111
import { addNonEnumerableProperty, dropUndefinedKeys } from '../utils-hoist/object';
12-
import { hasTracingEnabled } from '../utils/hasTracingEnabled';
12+
import { hasSpansEnabled } from '../utils/hasSpansEnabled';
1313
import { getRootSpan, spanIsSampled, spanToJSON } from '../utils/spanUtils';
1414
import { getCapturedScopesOnSpan } from './utils';
1515

@@ -118,10 +118,10 @@ export function getDynamicSamplingContextFromSpan(span: Span): Readonly<Partial<
118118
dsc.transaction = name;
119119
}
120120

121-
// How can we even land here with hasTracingEnabled() returning false?
121+
// How can we even land here with hasSpansEnabled() returning false?
122122
// Otel creates a Non-recording span in Tracing Without Performance mode when handling incoming requests
123123
// So we end up with an active span that is not sampled (neither positively nor negatively)
124-
if (hasTracingEnabled()) {
124+
if (hasSpansEnabled()) {
125125
dsc.sampled = String(spanIsSampled(rootSpan));
126126
dsc.sample_rand =
127127
// In OTEL we store the sample rand on the trace state because we cannot access scopes for NonRecordingSpans

packages/core/src/tracing/idleSpan.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { DEBUG_BUILD } from '../debug-build';
55
import { SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '../semanticAttributes';
66
import { logger } from '../utils-hoist/logger';
77
import { timestampInSeconds } from '../utils-hoist/time';
8-
import { hasTracingEnabled } from '../utils/hasTracingEnabled';
8+
import { hasSpansEnabled } from '../utils/hasSpansEnabled';
99
import { _setSpanForScope } from '../utils/spanOnScope';
1010
import {
1111
getActiveSpan,
@@ -109,7 +109,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
109109

110110
const client = getClient();
111111

112-
if (!client || !hasTracingEnabled()) {
112+
if (!client || !hasSpansEnabled()) {
113113
const span = new SentryNonRecordingSpan();
114114

115115
const dsc = {

packages/core/src/tracing/sampling.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { Options, SamplingContext } from '../types-hoist';
22

33
import { DEBUG_BUILD } from '../debug-build';
44
import { logger } from '../utils-hoist/logger';
5-
import { hasTracingEnabled } from '../utils/hasTracingEnabled';
5+
import { hasSpansEnabled } from '../utils/hasSpansEnabled';
66
import { parseSampleRate } from '../utils/parseSampleRate';
77

88
/**
@@ -16,8 +16,8 @@ export function sampleSpan(
1616
samplingContext: SamplingContext,
1717
sampleRand: number,
1818
): [sampled: boolean, sampleRate?: number, localSampleRateWasApplied?: boolean] {
19-
// nothing to do if tracing is not enabled
20-
if (!hasTracingEnabled(options)) {
19+
// nothing to do if span recording is not enabled
20+
if (!hasSpansEnabled(options)) {
2121
return [false];
2222
}
2323

packages/core/src/tracing/trace.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { logger } from '../utils-hoist/logger';
2121
import { generateTraceId } from '../utils-hoist/propagationContext';
2222
import { propagationContextFromHeaders } from '../utils-hoist/tracing';
2323
import { handleCallbackErrors } from '../utils/handleCallbackErrors';
24-
import { hasTracingEnabled } from '../utils/hasTracingEnabled';
24+
import { hasSpansEnabled } from '../utils/hasSpansEnabled';
2525
import { parseSampleRate } from '../utils/parseSampleRate';
2626
import { _getSpanForScope, _setSpanForScope } from '../utils/spanOnScope';
2727
import { addChildSpanToSpan, getRootSpan, spanIsSampled, spanTimeInputToSeconds, spanToJSON } from '../utils/spanUtils';
@@ -302,7 +302,7 @@ function createChildOrRootSpan({
302302
forceTransaction?: boolean;
303303
scope: Scope;
304304
}): Span {
305-
if (!hasTracingEnabled()) {
305+
if (!hasSpansEnabled()) {
306306
const span = new SentryNonRecordingSpan();
307307

308308
// If this is a root span, we ensure to freeze a DSC
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { getClient } from '../currentScopes';
2+
import type { Options } from '../types-hoist';
3+
4+
// Treeshakable guard to remove all code related to tracing
5+
declare const __SENTRY_TRACING__: boolean | undefined;
6+
7+
/**
8+
* Determines if span recording is currently enabled.
9+
*
10+
* Spans are recorded when at least one of `tracesSampleRate` and `tracesSampler`
11+
* is defined in the SDK config. This function does not make any assumption about
12+
* sampling decisions, it only checks if the SDK is configured to record spans.
13+
*
14+
* Important: This function only determines if span recording is enabled. Trace
15+
* continuation and propagation is separately controlled and not covered by this function.
16+
* If this function returns `false`, traces can still be propagated (which is what
17+
* we refer to by "Tracing without Performance")
18+
* @see https://develop.sentry.dev/sdk/telemetry/traces/tracing-without-performance/
19+
*
20+
* @param maybeOptions An SDK options object to be passed to this function.
21+
* If this option is not provided, the function will use the current client's options.
22+
*/
23+
export function hasSpansEnabled(
24+
maybeOptions?: Pick<Options, 'tracesSampleRate' | 'tracesSampler'> | undefined,
25+
): boolean {
26+
if (typeof __SENTRY_TRACING__ === 'boolean' && !__SENTRY_TRACING__) {
27+
return false;
28+
}
29+
30+
const options = maybeOptions || getClient()?.getOptions();
31+
return (
32+
!!options &&
33+
// Note: This check is `!= null`, meaning "nullish". `0` is not "nullish", `undefined` and `null` are. (This comment was brought to you by 15 minutes of questioning life)
34+
(options.tracesSampleRate != null || !!options.tracesSampler)
35+
);
36+
}
37+
38+
/**
39+
* @see JSDoc of `hasSpansEnabled`
40+
* @deprecated Use `hasSpansEnabled` instead, which is a more accurately named version of this function.
41+
* This function will be removed in the next major version of the SDK.
42+
*/
43+
// TODO(v10): Remove this export
44+
export const hasTracingEnabled = hasSpansEnabled;

packages/core/src/utils/hasTracingEnabled.ts

Lines changed: 0 additions & 26 deletions
This file was deleted.
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { hasSpansEnabled } from '../../../src';
12
import { hasTracingEnabled } from '../../../src';
23

3-
describe('hasTracingEnabled', () => {
4+
describe('hasSpansEnabled', () => {
45
const tracesSampler = () => 1;
56
const tracesSampleRate = 1;
67
it.each([
@@ -12,10 +13,9 @@ describe('hasTracingEnabled', () => {
1213
['With tracesSampleRate=0', { tracesSampleRate: 0 }, true],
1314
['With tracesSampler=undefined', { tracesSampler: undefined }, false],
1415
['With tracesSampler and tracesSampleRate', { tracesSampler, tracesSampleRate }, true],
15-
])(
16-
'%s',
17-
(_: string, input: Parameters<typeof hasTracingEnabled>[0], output: ReturnType<typeof hasTracingEnabled>) => {
18-
expect(hasTracingEnabled(input)).toBe(output);
19-
},
20-
);
16+
])('%s', (_: string, input: Parameters<typeof hasSpansEnabled>[0], output: ReturnType<typeof hasSpansEnabled>) => {
17+
expect(hasSpansEnabled(input)).toBe(output);
18+
// eslint-disable-next-line deprecation/deprecation
19+
expect(hasTracingEnabled(input)).toBe(output);
20+
});
2121
});

packages/nextjs/test/config/wrappers.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('data-fetching function wrappers should not create manual spans', () =>
1515
req = { headers: {}, url: 'http://dogs.are.great/tricks/kangaroo' } as IncomingMessage;
1616
res = { end: jest.fn() } as unknown as ServerResponse;
1717

18-
jest.spyOn(SentryCore, 'hasTracingEnabled').mockReturnValue(true);
18+
jest.spyOn(SentryCore, 'hasSpansEnabled').mockReturnValue(true);
1919
jest.spyOn(SentryCore, 'getClient').mockImplementation(() => {
2020
return {
2121
getOptions: () => ({}),

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
getClient,
1212
getSanitizedUrlString,
1313
getTraceData,
14-
hasTracingEnabled,
14+
hasSpansEnabled,
1515
parseUrl,
1616
} from '@sentry/core';
1717
import { shouldPropagateTraceForUrl } from '@sentry/opentelemetry';
@@ -49,9 +49,9 @@ const _nativeNodeFetchIntegration = ((options: NodeFetchOptions = {}) => {
4949
return true;
5050
}
5151

52-
// If tracing is disabled, we still want to propagate traces
52+
// If span recording is disabled, we still want to propagate traces
5353
// So we do that manually here, matching what the instrumentation does otherwise
54-
if (!hasTracingEnabled()) {
54+
if (!hasSpansEnabled()) {
5555
const tracePropagationTargets = getClient()?.getOptions().tracePropagationTargets;
5656
const addedHeaders = shouldPropagateTraceForUrl(url, tracePropagationTargets, propagationDecisionMap)
5757
? getTraceData()

packages/node/src/sdk/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
functionToStringIntegration,
66
getCurrentScope,
77
getIntegrationsToSetup,
8-
hasTracingEnabled,
8+
hasSpansEnabled,
99
inboundFiltersIntegration,
1010
linkedErrorsIntegration,
1111
logger,
@@ -80,7 +80,7 @@ export function getDefaultIntegrations(options: Options): Integration[] {
8080
// Note that this means that without tracing enabled, e.g. `expressIntegration()` will not be added
8181
// This means that generally request isolation will work (because that is done by httpIntegration)
8282
// But `transactionName` will not be set automatically
83-
...(hasTracingEnabled(options) ? getAutoPerformanceIntegrations() : []),
83+
...(hasSpansEnabled(options) ? getAutoPerformanceIntegrations() : []),
8484
];
8585
}
8686

@@ -175,7 +175,7 @@ export function validateOpenTelemetrySetup(): void {
175175

176176
const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];
177177

178-
if (hasTracingEnabled()) {
178+
if (hasSpansEnabled()) {
179179
required.push('SentrySpanProcessor');
180180
}
181181

packages/node/src/utils/ensureIsWrapped.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { isWrapped } from '@opentelemetry/core';
2-
import { consoleSandbox, getClient, getGlobalScope, hasTracingEnabled, isEnabled } from '@sentry/core';
2+
import { consoleSandbox, getClient, getGlobalScope, hasSpansEnabled, isEnabled } from '@sentry/core';
33
import type { NodeClient } from '../sdk/client';
44
import { isCjs } from './commonjs';
55
import { createMissingInstrumentationContext } from './createMissingInstrumentationContext';
@@ -11,12 +11,12 @@ export function ensureIsWrapped(
1111
maybeWrappedFunction: unknown,
1212
name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa',
1313
): void {
14-
const client = getClient<NodeClient>();
14+
const clientOptions = getClient<NodeClient>()?.getOptions();
1515
if (
16-
!client?.getOptions().disableInstrumentationWarnings &&
16+
!clientOptions?.disableInstrumentationWarnings &&
1717
!isWrapped(maybeWrappedFunction) &&
1818
isEnabled() &&
19-
hasTracingEnabled()
19+
hasSpansEnabled(clientOptions)
2020
) {
2121
consoleSandbox(() => {
2222
if (isCjs()) {

packages/opentelemetry/src/sampler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import type { Client, SpanAttributes } from '@sentry/core';
1414
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '@sentry/core';
1515
import { baggageHeaderToDynamicSamplingContext } from '@sentry/core';
16-
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, hasTracingEnabled, logger, parseSampleRate, sampleSpan } from '@sentry/core';
16+
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, hasSpansEnabled, logger, parseSampleRate, sampleSpan } from '@sentry/core';
1717
import {
1818
SENTRY_TRACE_STATE_DSC,
1919
SENTRY_TRACE_STATE_SAMPLED_NOT_RECORDING,
@@ -52,7 +52,7 @@ export class SentrySampler implements Sampler {
5252
const parentSpan = getValidSpan(context);
5353
const parentContext = parentSpan?.spanContext();
5454

55-
if (!hasTracingEnabled(options)) {
55+
if (!hasSpansEnabled(options)) {
5656
return wrapSamplingDecision({ decision: undefined, context, spanAttributes });
5757
}
5858

packages/opentelemetry/src/utils/enhanceDscWithOpenTelemetryRootSpanName.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, hasTracingEnabled, spanToJSON } from '@sentry/core';
1+
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, hasSpansEnabled, spanToJSON } from '@sentry/core';
22
import type { Client } from '@sentry/core';
33
import { getSamplingDecision } from './getSamplingDecision';
44
import { parseSpanDescription } from './parseSpanDescription';
@@ -32,7 +32,7 @@ export function enhanceDscWithOpenTelemetryRootSpanName(client: Client): void {
3232
// Also ensure sampling decision is correctly inferred
3333
// In core, we use `spanIsSampled`, which just looks at the trace flags
3434
// but in OTEL, we use a slightly more complex logic to be able to differntiate between unsampled and deferred sampling
35-
if (hasTracingEnabled()) {
35+
if (hasSpansEnabled()) {
3636
const sampled = getSamplingDecision(rootSpan.spanContext());
3737
dsc.sampled = sampled == undefined ? undefined : String(sampled);
3838
}

packages/remix/src/utils/instrumentServer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
fill,
55
getClient,
66
getTraceData,
7-
hasTracingEnabled,
7+
hasSpansEnabled,
88
isNodeEnv,
99
loadModule,
1010
logger,
@@ -197,7 +197,7 @@ function wrapRequestHandler(origRequestHandler: RequestHandler): RequestHandler
197197

198198
isolationScope.setSDKProcessingMetadata({ normalizedRequest });
199199

200-
if (!options || !hasTracingEnabled(options)) {
200+
if (!options || !hasSpansEnabled(options)) {
201201
return origRequestHandler.call(this, request, loadContext);
202202
}
203203

packages/vercel-edge/src/sdk.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
functionToStringIntegration,
1616
getCurrentScope,
1717
getIntegrationsToSetup,
18-
hasTracingEnabled,
18+
hasSpansEnabled,
1919
inboundFiltersIntegration,
2020
linkedErrorsIntegration,
2121
logger,
@@ -124,7 +124,7 @@ function validateOpenTelemetrySetup(): void {
124124

125125
const required: ReturnType<typeof openTelemetrySetupCheck> = ['SentryContextManager', 'SentryPropagator'];
126126

127-
if (hasTracingEnabled()) {
127+
if (hasSpansEnabled()) {
128128
required.push('SentrySpanProcessor');
129129
}
130130

0 commit comments

Comments
 (0)