Skip to content

Commit 91316ea

Browse files
committed
make startNewTrace use a callback
1 parent 611e766 commit 91316ea

File tree

9 files changed

+86
-32
lines changed

9 files changed

+86
-32
lines changed
Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
const fetchBtn = document.getElementById('fetchBtn');
2-
fetchBtn.addEventListener('click', async () => {
3-
Sentry.startNewTrace();
4-
Sentry.startSpan({ op: 'ui.interaction.click', name: 'fetch click' }, async () => {
1+
const newTraceBtn = document.getElementById('newTrace');
2+
newTraceBtn.addEventListener('click', async () => {
3+
Sentry.startNewTrace(() => {
4+
Sentry.startSpan({ op: 'ui.interaction.click', name: 'new-trace' }, async () => {
5+
await fetch('http://example.com');
6+
});
7+
});
8+
});
9+
10+
const oldTraceBtn = document.getElementById('oldTrace');
11+
oldTraceBtn.addEventListener('click', async () => {
12+
Sentry.startSpan({ op: 'ui.interaction.click', name: 'old-trace' }, async () => {
513
await fetch('http://example.com');
614
});
715
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<button id="oldTrace">Old Trace</button>
8+
<button id="newTrace">new Trace</button>
9+
</body>
10+
</html>

dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/startNewTrace/test.ts

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,34 +47,64 @@ sentryTest('should create a new trace if `startNewTrace` is called', async ({ ge
4747
trace_id: pageloadTraceContext?.trace_id,
4848
});
4949

50-
const customTransactionPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
50+
const newTraceTransactionPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
5151
page,
5252
undefined,
5353
eventAndTraceHeaderRequestParser,
5454
);
5555

56-
await page.locator('#fetchBtn').click();
56+
await page.locator('#newTrace').click();
5757

58-
const [customTransactionEvent, customTransactionTraceHeaders] = await customTransactionPromise;
58+
const [newTraceTransactionEvent, newTraceTransactionTraceHeaders] = await newTraceTransactionPromise;
5959

60-
expect(customTransactionEvent.type).toEqual('transaction');
61-
expect(customTransactionEvent.transaction).toEqual('fetch click');
60+
expect(newTraceTransactionEvent.type).toEqual('transaction');
61+
expect(newTraceTransactionEvent.transaction).toEqual('new-trace');
6262

63-
const customTransactionTraceContext = customTransactionEvent.contexts?.trace;
64-
expect(customTransactionTraceContext).toMatchObject({
63+
const newTraceTransactionTraceContext = newTraceTransactionEvent.contexts?.trace;
64+
expect(newTraceTransactionTraceContext).toMatchObject({
6565
op: 'ui.interaction.click',
6666
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
6767
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
6868
});
6969

70-
expect(customTransactionTraceHeaders).toEqual({
70+
expect(newTraceTransactionTraceHeaders).toEqual({
7171
environment: 'production',
7272
public_key: 'public',
7373
sample_rate: '1',
7474
sampled: 'true',
75-
trace_id: customTransactionTraceContext?.trace_id,
76-
transaction: 'fetch click',
75+
trace_id: newTraceTransactionTraceContext?.trace_id,
76+
transaction: 'new-trace',
7777
});
7878

79-
expect(customTransactionTraceContext?.trace_id).not.toEqual(pageloadTraceContext?.trace_id);
79+
const oldTraceTransactionPromise = getFirstSentryEnvelopeRequest<EventAndTraceHeader>(
80+
page,
81+
undefined,
82+
eventAndTraceHeaderRequestParser,
83+
);
84+
await page.locator('#oldTrace').click();
85+
86+
const [oldTraceTransactionEvent, oldTraceTransactionTraceHeaders] = await oldTraceTransactionPromise;
87+
88+
expect(oldTraceTransactionEvent.type).toEqual('transaction');
89+
expect(oldTraceTransactionEvent.transaction).toEqual('old-trace');
90+
91+
const oldTraceTransactionEventTraceContext = oldTraceTransactionEvent.contexts?.trace;
92+
expect(oldTraceTransactionEventTraceContext).toMatchObject({
93+
op: 'ui.interaction.click',
94+
trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
95+
span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
96+
});
97+
98+
expect(oldTraceTransactionTraceHeaders).toEqual({
99+
environment: 'production',
100+
public_key: 'public',
101+
sample_rate: '1',
102+
sampled: 'true',
103+
trace_id: oldTraceTransactionTraceHeaders?.trace_id,
104+
// transaction: 'old-trace', <-- this is not in the DSC because the DSC is continued from the pageload transaction
105+
// which does not have a `transaction` field because its source is URL.
106+
});
107+
108+
expect(oldTraceTransactionEventTraceContext?.trace_id).toEqual(pageloadTraceContext?.trace_id);
109+
expect(newTraceTransactionTraceContext?.trace_id).not.toEqual(pageloadTraceContext?.trace_id);
80110
});

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type { Client, IntegrationFn, StartSpanOptions, TransactionSource } from
2828
import type { Span } from '@sentry/types';
2929
import {
3030
browserPerformanceTimeOrigin,
31+
generatePropagationContext,
3132
getDomElement,
3233
logger,
3334
propagationContextFromHeaders,
@@ -413,7 +414,8 @@ export function startBrowserTracingPageLoadSpan(
413414
* This will only do something if a browser tracing integration has been setup.
414415
*/
415416
export function startBrowserTracingNavigationSpan(client: Client, spanOptions: StartSpanOptions): Span | undefined {
416-
startNewTrace();
417+
getIsolationScope().setPropagationContext(generatePropagationContext());
418+
getCurrentScope().setPropagationContext(generatePropagationContext());
417419

418420
client.emit('startNavigationSpan', spanOptions);
419421

packages/core/src/scope.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ import type {
2121
SeverityLevel,
2222
User,
2323
} from '@sentry/types';
24-
import { dateTimestampInSeconds, isPlainObject, logger, uuid4 } from '@sentry/utils';
24+
import { dateTimestampInSeconds, generatePropagationContext, isPlainObject, logger, uuid4 } from '@sentry/utils';
2525

2626
import { updateSession } from './session';
27-
import { generatePropagationContext } from './tracing/propagationContext';
2827
import { _getSpanForScope, _setSpanForScope } from './utils/spanOnScope';
2928

3029
/**

packages/core/src/tracing/trace.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ClientOptions, Scope, SentrySpanArguments, Span, SpanTimeInput, StartSpanOptions } from '@sentry/types';
2-
import { logger, propagationContextFromHeaders, uuid4 } from '@sentry/utils';
2+
import { generatePropagationContext, logger, propagationContextFromHeaders } from '@sentry/utils';
33
import type { AsyncContextStrategy } from '../asyncContext/types';
44
import { getMainCarrier } from '../carrier';
55

@@ -14,7 +14,6 @@ import { _getSpanForScope, _setSpanForScope } from '../utils/spanOnScope';
1414
import { addChildSpanToSpan, getRootSpan, spanIsSampled, spanTimeInputToSeconds, spanToJSON } from '../utils/spanUtils';
1515
import { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
1616
import { logSpanStart } from './logSpans';
17-
import { generatePropagationContext } from './propagationContext';
1817
import { sampleSpan } from './sampling';
1918
import { SentryNonRecordingSpan } from './sentryNonRecordingSpan';
2019
import { SentrySpan } from './sentrySpan';
@@ -215,22 +214,27 @@ export function suppressTracing<T>(callback: () => T): T {
215214
}
216215

217216
/**
218-
* Starts a new trace by creating a new trace id. Spans started after this function is called
219-
* will be part of the new trace instead of a potentially previous existing trace.
217+
* Starts a new trace for the duration of the provided callback. Spans started within the
218+
* callback will be part of the new trace instead of a potentially previously started trace.
220219
*
221-
* Important: Only use this function if you want to override the default trace lifetime SDK.
222-
* Please also note that as soon as you call this function, a previously distributed can no longer be
223-
* continued. Instead, the newly created trace will also be the root of a new distributed trace.
220+
* Important: Only use this function if you want to override the default trace lifetime and
221+
* propagation mechanism of the SDK for the duration and scope of the provided callback.
222+
* The newly created trace will also be the root of a new distributed trace, for example if
223+
* you make http requests within the callback.
224+
* This function might be useful if the operation you want to instrument should not be part
225+
* of a potentially ongoing trace.
224226
*
225227
* Default behavior:
226228
* - Server-side: A new trace is started for each incoming request.
227229
* - Browser: A new trace is started for each page our route. Navigating to a new route
228230
* or page will automatically create a new trace.
229231
*/
230-
export function startNewTrace(): void {
231-
getIsolationScope().setPropagationContext(generatePropagationContext());
232-
getCurrentScope().setPropagationContext(generatePropagationContext());
233-
DEBUG_BUILD && logger.info(`Starting a new trace with id ${getCurrentScope().getPropagationContext().traceId}`);
232+
export function startNewTrace<T>(callback: () => T): T {
233+
return withScope(scope => {
234+
scope.setPropagationContext(generatePropagationContext());
235+
DEBUG_BUILD && logger.info(`Starting a new trace with id ${scope.getPropagationContext().traceId}`);
236+
return withActiveSpan(null, callback);
237+
});
234238
}
235239

236240
function createChildOrRootSpan({

packages/utils/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ export * from './eventbuilder';
3535
export * from './anr';
3636
export * from './lru';
3737
export * from './buildPolyfills';
38+
export * from './propagationContext';

packages/core/src/tracing/propagationContext.ts renamed to packages/utils/src/propagationContext.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type { PropagationContext } from '@sentry/types';
2-
import { uuid4 } from '@sentry/utils';
2+
import { uuid4 } from './misc';
33

44
/**
5-
* Generates a new minimal propagation context
5+
* Returns a new minimal propagation context
66
*/
77
export function generatePropagationContext(): PropagationContext {
88
return {

packages/core/test/lib/tracing/proagationContext.test.ts renamed to packages/utils/test/proagationContext.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { generatePropagationContext } from '../../../src/tracing/propagationContext';
1+
import { generatePropagationContext } from '../src/propagationContext';
22

33
describe('generatePropagationContext', () => {
44
it('generates a new minimal propagation context', () => {

0 commit comments

Comments
 (0)