Skip to content

Commit cd60e47

Browse files
committed
add shouldContinueTrace util function
1 parent e2dd6a6 commit cd60e47

File tree

4 files changed

+112
-34
lines changed

4 files changed

+112
-34
lines changed

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ export {
216216
extractTraceparentData,
217217
generateSentryTraceHeader,
218218
propagationContextFromHeaders,
219+
shouldContinueTrace,
219220
} from './utils-hoist/tracing';
220221
export { getSDKSource, isBrowserBundle } from './utils-hoist/env';
221222
export type { SdkSource } from './utils-hoist/env';

packages/core/src/tracing/trace.ts

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { addChildSpanToSpan, getRootSpan, spanIsSampled, spanTimeInputToSeconds,
1919
import { baggageHeaderToDynamicSamplingContext } from '../utils-hoist/baggage';
2020
import { logger } from '../utils-hoist/logger';
2121
import { generateTraceId } from '../utils-hoist/propagationContext';
22-
import { propagationContextFromHeaders } from '../utils-hoist/tracing';
22+
import { propagationContextFromHeaders, shouldContinueTrace } from '../utils-hoist/tracing';
2323
import { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
2424
import { logSpanStart } from './logSpans';
2525
import { sampleSpan } from './sampling';
@@ -216,41 +216,10 @@ export const continueTrace = <V>(
216216
}
217217

218218
const { sentryTrace, baggage } = options;
219-
const client = getClient();
220-
221-
const clientOptions = client?.getOptions();
222-
const strictTraceContinuation = clientOptions?.strictTraceContinuation || false; // default for `strictTraceContinuation` is `false` todo(v10): set default to `true`
223219

224220
const incomingDsc = baggageHeaderToDynamicSamplingContext(baggage);
225-
const baggageOrgId = incomingDsc?.org_id;
226-
227-
const sdkOrgId = deriveOrgIdFromClient(client);
228-
229-
const shouldStartNewTrace = (): boolean => {
230-
// Case: baggage org ID and SDK org ID don't match - always start new trace
231-
if (baggageOrgId && sdkOrgId && baggageOrgId !== sdkOrgId) {
232-
DEBUG_BUILD &&
233-
logger.info(`Starting a new trace because org IDs don't match (incoming: ${baggageOrgId}, sdk: ${sdkOrgId})`);
234-
return true;
235-
}
236-
237-
if (strictTraceContinuation) {
238-
// With strict continuation enabled, start new trace if:
239-
// - Baggage has org ID but SDK doesn't have one
240-
// - SDK has org ID but baggage doesn't have one
241-
if ((baggageOrgId && !sdkOrgId) || (!baggageOrgId && sdkOrgId)) {
242-
DEBUG_BUILD &&
243-
logger.info(
244-
`Starting a new trace because strict trace continuation is enabled and one org ID is missing (incoming: ${baggageOrgId}, sdk: ${sdkOrgId})`,
245-
);
246-
return true;
247-
}
248-
}
249-
250-
return false;
251-
};
252221

253-
if (shouldStartNewTrace()) {
222+
if (shouldContinueTrace(getClient(), incomingDsc?.org_id)) {
254223
return startNewTrace(callback);
255224
}
256225

packages/core/src/utils-hoist/tracing.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import type { Client } from '../client';
2+
import { DEBUG_BUILD } from '../debug-build';
3+
import { deriveOrgIdFromClient } from '../tracing/utils';
14
import type { DynamicSamplingContext } from '../types-hoist/envelope';
25
import type { PropagationContext } from '../types-hoist/tracing';
36
import type { TraceparentData } from '../types-hoist/transaction';
47
import { parseSampleRate } from '../utils/parseSampleRate';
8+
import { logger } from '../utils-hoist/logger';
59
import { baggageHeaderToDynamicSamplingContext } from './baggage';
610
import { generateSpanId, generateTraceId } from './propagationContext';
711

@@ -124,3 +128,40 @@ function getSampleRandFromTraceparentAndDsc(
124128
return Math.random();
125129
}
126130
}
131+
132+
/**
133+
* Determines whether a new trace should be continued based on the provided client and baggage org ID.
134+
* If the trace should not be continued, a new trace will be started.
135+
*
136+
* The result is dependent on the `strictTraceContinuation` option in the client.
137+
* See https://develop.sentry.dev/sdk/telemetry/traces/#stricttracecontinuation
138+
*/
139+
export function shouldContinueTrace(client: Client | undefined, baggageOrgId?: string): boolean {
140+
const sdkOptionOrgId = deriveOrgIdFromClient(client);
141+
142+
// Case: baggage org ID and SDK org ID don't match - always start new trace
143+
if (baggageOrgId && sdkOptionOrgId && baggageOrgId !== sdkOptionOrgId) {
144+
DEBUG_BUILD &&
145+
logger.info(
146+
`Starting a new trace because org IDs don't match (incoming baggage: ${baggageOrgId}, SDK options: ${sdkOptionOrgId})`,
147+
);
148+
return false;
149+
}
150+
151+
const strictTraceContinuation = client?.getOptions()?.strictTraceContinuation || false; // default for `strictTraceContinuation` is `false` todo(v10): set default to `true`
152+
153+
if (strictTraceContinuation) {
154+
// With strict continuation enabled, start new trace if:
155+
// - Baggage has org ID but SDK doesn't have one
156+
// - SDK has org ID but baggage doesn't have one
157+
if ((baggageOrgId && !sdkOptionOrgId) || (!baggageOrgId && sdkOptionOrgId)) {
158+
DEBUG_BUILD &&
159+
logger.info(
160+
`Starting a new trace because strict trace continuation is enabled and one org ID is missing (incoming baggage: ${baggageOrgId}, SDK options: ${sdkOptionOrgId})`,
161+
);
162+
return false;
163+
}
164+
}
165+
166+
return true;
167+
}

packages/core/test/utils-hoist/tracing.test.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { describe, expect, it, test } from 'vitest';
2-
import { extractTraceparentData, propagationContextFromHeaders } from '../../src/utils-hoist/tracing';
2+
import {
3+
extractTraceparentData,
4+
propagationContextFromHeaders,
5+
shouldContinueTrace,
6+
} from '../../src/utils-hoist/tracing';
7+
import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
38

49
const EXAMPLE_SENTRY_TRACE = '12312012123120121231201212312012-1121201211212012-1';
510
const EXAMPLE_BAGGAGE = 'sentry-release=1.2.3,sentry-foo=bar,other=baz,sentry-sample_rand=0.42';
@@ -124,3 +129,65 @@ describe('extractTraceparentData', () => {
124129
expect(extractTraceparentData('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bbbbbbbbbbbbbbbb-x')).toBeUndefined();
125130
});
126131
});
132+
133+
describe('shouldContinueTrace', () => {
134+
test('returns true when both baggage and SDK org IDs are undefined', () => {
135+
const client = new TestClient(getDefaultTestClientOptions({}));
136+
137+
const result = shouldContinueTrace(client, undefined);
138+
expect(result).toBe(true);
139+
});
140+
141+
test('returns true when org IDs match', () => {
142+
const orgId = '123456';
143+
const client = new TestClient(getDefaultTestClientOptions({ orgId }));
144+
145+
const result = shouldContinueTrace(client, orgId);
146+
expect(result).toBe(true);
147+
});
148+
149+
test('returns false when org IDs do not match', () => {
150+
const client = new TestClient(getDefaultTestClientOptions({ orgId: '123456' }));
151+
152+
const result = shouldContinueTrace(client, '654321');
153+
expect(result).toBe(false);
154+
});
155+
156+
test('returns true when baggage org ID is undefined and strictTraceContinuation is false', () => {
157+
const client = new TestClient(getDefaultTestClientOptions({ orgId: '123456', strictTraceContinuation: false }));
158+
159+
const result = shouldContinueTrace(client, undefined);
160+
expect(result).toBe(true);
161+
});
162+
163+
test('returns true when SDK org ID is undefined and strictTraceContinuation is false', () => {
164+
const client = new TestClient(getDefaultTestClientOptions({ strictTraceContinuation: false }));
165+
166+
const result = shouldContinueTrace(client, '123456');
167+
expect(result).toBe(true);
168+
});
169+
170+
test('returns false when baggage org ID is undefined and strictTraceContinuation is true', () => {
171+
const client = new TestClient(getDefaultTestClientOptions({ orgId: '123456', strictTraceContinuation: true }));
172+
173+
const result = shouldContinueTrace(client, undefined);
174+
expect(result).toBe(false);
175+
});
176+
177+
test('returns false when SDK org ID is undefined and strictTraceContinuation is true', () => {
178+
const client = new TestClient(getDefaultTestClientOptions({ strictTraceContinuation: true }));
179+
180+
const result = shouldContinueTrace(client, '123456');
181+
expect(result).toBe(false);
182+
});
183+
184+
test('returns true when client is undefined', () => {
185+
const result = shouldContinueTrace(undefined, '123456');
186+
expect(result).toBe(true);
187+
});
188+
189+
test('returns true when both org IDs and client are undefined', () => {
190+
const result = shouldContinueTrace(undefined, undefined);
191+
expect(result).toBe(true);
192+
});
193+
});

0 commit comments

Comments
 (0)