Skip to content

Commit dfe7d61

Browse files
authored
ref(tracing): Sync baggage data in Http and envelope headers (#5218)
Sync the content of the trace envelope header with the baggage Http header we propagate with outgoing requests. This means that both headers will from now on have the same baggage contents (the envelope header has additional fields that are not part of Baggage)
1 parent f4e3cf4 commit dfe7d61

File tree

10 files changed

+68
-40
lines changed

10 files changed

+68
-40
lines changed

packages/core/src/baseclient.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -496,8 +496,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
496496
// For now the decision is to skip normalization of Transactions and Spans,
497497
// so this block overwrites the normalized event to add back the original
498498
// Transaction information prior to normalization.
499-
if (event.contexts && event.contexts.trace) {
500-
normalized.contexts = {};
499+
if (event.contexts && event.contexts.trace && normalized.contexts) {
501500
normalized.contexts.trace = event.contexts.trace;
502501

503502
// event.contexts.trace.data may contain circular/dangerous data so we need to normalize it

packages/core/src/envelope.ts

+18-10
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {
2+
BaggageObj,
23
DsnComponents,
34
Event,
45
EventEnvelope,
56
EventEnvelopeHeaders,
67
EventItem,
8+
EventTraceContext,
79
SdkInfo,
810
SdkMetadata,
911
Session,
@@ -99,28 +101,34 @@ function createEventEnvelopeHeaders(
99101
tunnel: string | undefined,
100102
dsn: DsnComponents,
101103
): EventEnvelopeHeaders {
104+
const baggage = event.contexts && (event.contexts.baggage as BaggageObj);
105+
const { environment, release, transaction, userid, usersegment } = baggage || {};
106+
102107
return {
103108
event_id: event.event_id as string,
104109
sent_at: new Date().toISOString(),
105110
...(sdkInfo && { sdk: sdkInfo }),
106111
...(!!tunnel && { dsn: dsnToString(dsn) }),
107112
...(event.type === 'transaction' &&
113+
// If we don't already have a trace context in the event, we can't get the trace id, which makes adding any other
114+
// trace data pointless
108115
event.contexts &&
109116
event.contexts.trace && {
110-
// TODO: Grab this from baggage
111117
trace: dropUndefinedKeys({
112118
// Trace context must be defined for transactions
113119
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
114-
trace_id: event.contexts!.trace.trace_id as string,
115-
environment: event.environment,
116-
release: event.release,
117-
transaction: event.transaction,
118-
user: event.user && {
119-
id: event.user.id,
120-
segment: event.user.segment,
121-
},
120+
trace_id: (event.contexts!.trace as Record<string, unknown>).trace_id as string,
122121
public_key: dsn.publicKey,
123-
}),
122+
environment: environment,
123+
release: release,
124+
transaction: transaction,
125+
...((userid || usersegment) && {
126+
user: {
127+
id: userid,
128+
segment: usersegment,
129+
},
130+
}),
131+
}) as EventTraceContext,
124132
}),
125133
};
126134
}

packages/core/test/lib/envelope.test.ts

+16-9
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,16 @@ describe('createEventEnvelope', () => {
3131

3232
const testTable: Array<[string, Event, EventTraceContext]> = [
3333
[
34-
'adds only baggage item',
34+
'adds one baggage item',
3535
{
3636
type: 'transaction',
37-
release: '1.0.0',
3837
contexts: {
3938
trace: {
4039
trace_id: '1234',
4140
},
41+
baggage: {
42+
release: '1.0.0',
43+
},
4244
},
4345
},
4446
{ release: '1.0.0', trace_id: '1234', public_key: 'pubKey123' },
@@ -47,28 +49,33 @@ describe('createEventEnvelope', () => {
4749
'adds two baggage items',
4850
{
4951
type: 'transaction',
50-
release: '1.0.0',
51-
environment: 'prod',
5252
contexts: {
5353
trace: {
5454
trace_id: '1234',
5555
},
56+
baggage: {
57+
environment: 'prod',
58+
release: '1.0.0',
59+
},
5660
},
5761
},
5862
{ release: '1.0.0', environment: 'prod', trace_id: '1234', public_key: 'pubKey123' },
5963
],
6064
[
61-
'adds all baggageitems',
65+
'adds all baggage items',
6266
{
6367
type: 'transaction',
64-
release: '1.0.0',
65-
environment: 'prod',
66-
user: { id: 'bob', segment: 'segmentA' },
67-
transaction: 'TX',
6868
contexts: {
6969
trace: {
7070
trace_id: '1234',
7171
},
72+
baggage: {
73+
environment: 'prod',
74+
release: '1.0.0',
75+
userid: 'bob',
76+
usersegment: 'segmentA',
77+
transaction: 'TX',
78+
},
7279
},
7380
},
7481
{

packages/integration-tests/suites/tracing/baggage/test.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ sentryTest('should send trace context data in transaction envelope header', asyn
1212
expect(envHeader.trace).toBeDefined();
1313
expect(envHeader.trace).toMatchObject({
1414
environment: 'production',
15-
transaction: 'testTransactionBaggage',
16-
user: {
17-
id: 'user123',
18-
segment: 'segmentB',
19-
},
15+
// TODO comment back in once we properly support transaction and user data in Baggage
16+
// transaction: 'testTransactionBaggage',
17+
// user: {
18+
// id: 'user123',
19+
// segment: 'segmentB',
20+
// },
2021
public_key: 'public',
2122
trace_id: expect.any(String),
2223
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { Integrations } from '@sentry/tracing';
3+
4+
window.Sentry = Sentry;
5+
6+
Sentry.init({
7+
dsn: 'https://[email protected]/1337',
8+
integrations: [new Integrations.BrowserTracing()],
9+
tracesSampleRate: 1,
10+
environment: 'staging',
11+
});

packages/integration-tests/suites/tracing/browsertracing/meta/template.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
<head>
33
<meta charset="utf-8" />
44
<meta name="sentry-trace" content="12312012123120121231201212312012-1121201211212012-1" />
5-
<meta name="baggage" content="sentry-version=2.1.12" />
5+
<meta name="baggage" content="sentry-release=2.1.12" />
66
</head>
77
</html>

packages/integration-tests/suites/tracing/browsertracing/meta/test.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,19 @@ sentryTest(
2121
},
2222
);
2323

24-
// TODO this we can't really test until we actually propagate sentry- entries in baggage
25-
// skipping for now but this must be adjusted later on
26-
sentryTest.skip(
27-
'should pick up `baggage` <meta> tag and propagate the content in transaction',
24+
sentryTest(
25+
'should pick up `baggage` <meta> tag, propagate the content in transaction and not add own data',
2826
async ({ getLocalTestPath, page }) => {
2927
const url = await getLocalTestPath({ testDir: __dirname });
3028

3129
const envHeader = await getFirstSentryEnvelopeRequest<EventEnvelopeHeaders>(page, url, envelopeHeaderRequestParser);
3230

3331
expect(envHeader.trace).toBeDefined();
34-
expect(envHeader.trace).toEqual('{version:2.1.12}');
32+
expect(envHeader.trace).toEqual({
33+
public_key: 'public',
34+
trace_id: expect.any(String),
35+
release: '2.1.12',
36+
});
3537
},
3638
);
3739

packages/tracing/src/span.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { Baggage, Hub, Primitive, Span as SpanInterface, SpanContext, Transactio
44
import {
55
createBaggage,
66
dropUndefinedKeys,
7-
isBaggageEmpty,
87
isBaggageMutable,
98
isSentryBaggageEmpty,
109
setBaggageImmutable,
@@ -312,7 +311,7 @@ export class Span implements SpanInterface {
312311
/**
313312
* @inheritdoc
314313
*/
315-
public getBaggage(): Baggage | undefined {
314+
public getBaggage(): Baggage {
316315
const existingBaggage = this.transaction && this.transaction.metadata.baggage;
317316

318317
// Only add Sentry baggage items to baggage, if baggage does not exist yet or it is still
@@ -322,7 +321,7 @@ export class Span implements SpanInterface {
322321
? this._getBaggageWithSentryValues(existingBaggage)
323322
: existingBaggage;
324323

325-
return isBaggageEmpty(finalBaggage) ? undefined : finalBaggage;
324+
return finalBaggage;
326325
}
327326

328327
/**
@@ -366,7 +365,7 @@ export class Span implements SpanInterface {
366365
*
367366
* @param baggage
368367
*
369-
* @returns modified and immutable maggage object
368+
* @returns modified and immutable baggage object
370369
*/
371370
private _getBaggageWithSentryValues(baggage: Baggage = createBaggage({})): Baggage {
372371
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any

packages/tracing/src/transaction.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
TransactionContext,
77
TransactionMetadata,
88
} from '@sentry/types';
9-
import { dropUndefinedKeys, logger } from '@sentry/utils';
9+
import { dropUndefinedKeys, getSentryBaggageItems, logger } from '@sentry/utils';
1010

1111
import { Span as SpanClass, SpanRecorder } from './span';
1212

@@ -122,6 +122,7 @@ export class Transaction extends SpanClass implements TransactionInterface {
122122
const transaction: Event = {
123123
contexts: {
124124
trace: this.getTraceContext(),
125+
baggage: getSentryBaggageItems(this.getBaggage()),
125126
},
126127
spans: finishedSpans,
127128
start_timestamp: this.startTimestamp,

packages/utils/src/baggage.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,14 @@ export function mergeAndSerializeBaggage(incomingBaggage?: Baggage, headerBaggag
151151
* Extracted this logic to a function because it's duplicated in a lot of places.
152152
*
153153
* @param rawBaggageString
154-
* @param sentryTraceData
154+
* @param sentryTraceHeader
155155
*/
156156
export function parseBaggageSetMutability(
157157
rawBaggageString: string | false | undefined | null,
158-
sentryTraceData: TraceparentData | string | false | undefined | null,
158+
sentryTraceHeader: TraceparentData | string | false | undefined | null,
159159
): Baggage {
160160
const baggage = parseBaggageString(rawBaggageString || '');
161-
if (!isSentryBaggageEmpty(baggage) || (sentryTraceData && isSentryBaggageEmpty(baggage))) {
161+
if (!isSentryBaggageEmpty(baggage) || (sentryTraceHeader && isSentryBaggageEmpty(baggage))) {
162162
setBaggageImmutable(baggage);
163163
}
164164
return baggage;

0 commit comments

Comments
 (0)