Skip to content

Commit 453b7ad

Browse files
authored
fix(core): Normalize trace context (#5171)
1 parent be63dd9 commit 453b7ad

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

packages/core/src/baseclient.ts

+19-2
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
476476
return null;
477477
}
478478

479-
const normalized = {
479+
const normalized: Event = {
480480
...event,
481481
...(event.breadcrumbs && {
482482
breadcrumbs: event.breadcrumbs.map(b => ({
@@ -496,6 +496,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
496496
extra: normalize(event.extra, depth, maxBreadth),
497497
}),
498498
};
499+
499500
// event.contexts.trace stores information about a Transaction. Similarly,
500501
// event.spans[] stores information about child Spans. Given that a
501502
// Transaction is conceptually a Span, normalization should apply to both
@@ -504,8 +505,24 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
504505
// so this block overwrites the normalized event to add back the original
505506
// Transaction information prior to normalization.
506507
if (event.contexts && event.contexts.trace) {
507-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
508+
normalized.contexts = {};
508509
normalized.contexts.trace = event.contexts.trace;
510+
511+
// event.contexts.trace.data may contain circular/dangerous data so we need to normalize it
512+
if (event.contexts.trace.data) {
513+
normalized.contexts.trace.data = normalize(event.contexts.trace.data, depth, maxBreadth);
514+
}
515+
}
516+
517+
// event.spans[].data may contain circular/dangerous data so we need to normalize it
518+
if (event.spans) {
519+
normalized.spans = event.spans.map(span => {
520+
// We cannot use the spread operator here because `toJSON` on `span` is non-enumerable
521+
if (span.data) {
522+
span.data = normalize(span.data, depth, maxBreadth);
523+
}
524+
return span;
525+
});
509526
}
510527

511528
normalized.sdkProcessingMetadata = { ...normalized.sdkProcessingMetadata, baseClientNormalized: true };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const chicken = {};
2+
const egg = { contains: chicken };
3+
chicken.lays = egg;
4+
5+
const circularObject = chicken;
6+
7+
const transaction = Sentry.startTransaction({ name: 'circular_object_test_transaction', data: circularObject });
8+
const span = transaction.startChild({ op: 'circular_object_test_span', data: circularObject });
9+
10+
span.finish();
11+
transaction.finish();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { expect } from '@playwright/test';
2+
import { Event } from '@sentry/types';
3+
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
6+
7+
sentryTest('should be able to handle circular data', async ({ getLocalTestPath, page }) => {
8+
const url = await getLocalTestPath({ testDir: __dirname });
9+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
10+
11+
expect(eventData.type).toBe('transaction');
12+
expect(eventData.transaction).toBe('circular_object_test_transaction');
13+
14+
expect(eventData.contexts).toMatchObject({
15+
trace: {
16+
data: { lays: { contains: '[Circular ~]' } },
17+
},
18+
});
19+
20+
expect(eventData?.spans?.[0]).toMatchObject({
21+
data: { lays: { contains: '[Circular ~]' } },
22+
op: 'circular_object_test_span',
23+
});
24+
25+
await new Promise(resolve => setTimeout(resolve, 2000));
26+
});

packages/integration-tests/suites/public-api/startTransaction/init.js

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ window.Sentry = Sentry;
77
Sentry.init({
88
dsn: 'https://[email protected]/1337',
99
tracesSampleRate: 1.0,
10+
normalizeDepth: 10,
1011
});

0 commit comments

Comments
 (0)