Skip to content

Commit be86d82

Browse files
committed
ref(v8): Remove metadata on transaction
Instead, we freeze the DSC explicitly onto the transaction now.
1 parent 4085728 commit be86d82

File tree

7 files changed

+45
-203
lines changed

7 files changed

+45
-203
lines changed

dev-packages/rollup-utils/plugins/bundlePlugins.mjs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,14 @@ export function makeTerserPlugin() {
121121
// These are used by instrument.ts in utils for identifying HTML elements & events
122122
'_sentryCaptured',
123123
'_sentryId',
124-
// For v7 backwards-compatibility we need to access txn._frozenDynamicSamplingContext
125-
// TODO (v8): Remove this reserved word
126-
'_frozenDynamicSamplingContext',
124+
'_frozenDsc',
127125
// These are used to keep span & scope relationships
128126
'_sentryRootSpan',
129127
'_sentryChildSpans',
130128
'_sentrySpan',
131129
'_sentryScope',
132130
'_sentryIsolationScope',
131+
133132
],
134133
},
135134
},

packages/core/src/tracing/dynamicSamplingContext.ts

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
1-
import type { Client, DynamicSamplingContext, Span, Transaction } from '@sentry/types';
2-
import { dropUndefinedKeys } from '@sentry/utils';
1+
import type { Client, DynamicSamplingContext, Span } from '@sentry/types';
2+
import { addNonEnumerableProperty, dropUndefinedKeys } from '@sentry/utils';
33

44
import { DEFAULT_ENVIRONMENT } from '../constants';
55
import { getClient } from '../currentScopes';
6-
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
6+
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
77
import { getRootSpan, spanIsSampled, spanToJSON } from '../utils/spanUtils';
88

9+
const FROZEN_DSC_FIELD = '_frozenDsc';
10+
11+
type SpanWithMaybeDsc = Span & {
12+
[FROZEN_DSC_FIELD]?: Partial<DynamicSamplingContext> | undefined;
13+
};
14+
15+
/**
16+
* Freeze the given DSC on the given span.
17+
*/
18+
export function freezeDscOnSpan(span: Span, dsc: Partial<DynamicSamplingContext>): void {
19+
const spanWithMaybeDsc = span as SpanWithMaybeDsc;
20+
addNonEnumerableProperty(spanWithMaybeDsc, FROZEN_DSC_FIELD, dsc);
21+
}
22+
923
/**
1024
* Creates a dynamic sampling context from a client.
1125
*
@@ -28,11 +42,6 @@ export function getDynamicSamplingContextFromClient(trace_id: string, client: Cl
2842
return dsc;
2943
}
3044

31-
/**
32-
* A Span with a frozen dynamic sampling context.
33-
*/
34-
type TransactionWithV7FrozenDsc = Transaction & { _frozenDynamicSamplingContext?: DynamicSamplingContext };
35-
3645
/**
3746
* Creates a dynamic sampling context from a span (and client and scope)
3847
*
@@ -48,32 +57,26 @@ export function getDynamicSamplingContextFromSpan(span: Span): Readonly<Partial<
4857

4958
const dsc = getDynamicSamplingContextFromClient(spanToJSON(span).trace_id || '', client);
5059

51-
// TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
5260
const rootSpan = getRootSpan(span);
5361
if (!rootSpan) {
5462
return dsc;
5563
}
5664

57-
// TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
58-
// For now we need to avoid breaking users who directly created a txn with a DSC, where this field is still set.
59-
// @see Transaction class constructor
60-
const v7FrozenDsc = rootSpan && (rootSpan as TransactionWithV7FrozenDsc)._frozenDynamicSamplingContext;
61-
if (v7FrozenDsc) {
62-
return v7FrozenDsc;
65+
const frozenDsc = (rootSpan as SpanWithMaybeDsc)[FROZEN_DSC_FIELD];
66+
if (frozenDsc) {
67+
return frozenDsc;
6368
}
6469

65-
// TODO (v8): Replace txn.metadata with txn.attributes[]
66-
// We can't do this yet because attributes aren't always set yet.
67-
// eslint-disable-next-line deprecation/deprecation
68-
const { sampleRate: maybeSampleRate } = (rootSpan as TransactionWithV7FrozenDsc).metadata || {};
70+
const jsonSpan = spanToJSON(rootSpan);
71+
const attributes = jsonSpan.data || {};
72+
const maybeSampleRate = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE];
73+
6974
if (maybeSampleRate != null) {
7075
dsc.sample_rate = `${maybeSampleRate}`;
7176
}
7277

7378
// We don't want to have a transaction name in the DSC if the source is "url" because URLs might contain PII
74-
const jsonSpan = spanToJSON(rootSpan);
75-
76-
const source = (jsonSpan.data || {})[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
79+
const source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
7780

7881
// after JSON conversion, txn.name becomes jsonSpan.description
7982
if (source && source !== 'url') {

packages/core/src/tracing/trace.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
spanTimeInputToSeconds,
1818
spanToJSON,
1919
} from '../utils/spanUtils';
20-
import { getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
20+
import { freezeDscOnSpan, getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
2121
import { sampleSpan } from './sampling';
2222
import { SentryNonRecordingSpan } from './sentryNonRecordingSpan';
2323
import type { SentrySpan } from './sentrySpan';
@@ -237,12 +237,9 @@ function createChildSpanOrTransaction({
237237
parentSpanId,
238238
parentSampled: sampled,
239239
...spanContext,
240-
metadata: {
241-
dynamicSamplingContext: dsc,
242-
// eslint-disable-next-line deprecation/deprecation
243-
...spanContext.metadata,
244-
},
245240
});
241+
242+
freezeDscOnSpan(span, dsc);
246243
} else {
247244
const { traceId, dsc, parentSpanId, sampled } = {
248245
...isolationScope.getPropagationContext(),
@@ -253,13 +250,14 @@ function createChildSpanOrTransaction({
253250
traceId,
254251
parentSpanId,
255252
parentSampled: sampled,
253+
// TODO: We should probably only set this if we know we are continuing a trace
254+
// For now, there isn't really a way to know this from in here, though...
256255
...spanContext,
257-
metadata: {
258-
dynamicSamplingContext: dsc,
259-
// eslint-disable-next-line deprecation/deprecation
260-
...spanContext.metadata,
261-
},
262256
});
257+
258+
if (dsc) {
259+
freezeDscOnSpan(span, dsc);
260+
}
263261
}
264262

265263
// TODO v8: Technically `startTransaction` can return undefined, which is not reflected by the types

packages/core/src/tracing/transaction.ts

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import type {
22
Context,
33
Contexts,
4-
DynamicSamplingContext,
54
Hub,
65
MeasurementUnit,
76
Measurements,
@@ -10,15 +9,14 @@ import type {
109
Transaction as TransactionInterface,
1110
TransactionArguments,
1211
TransactionEvent,
13-
TransactionMetadata,
1412
TransactionSource,
1513
} from '@sentry/types';
1614
import { dropUndefinedKeys, logger } from '@sentry/utils';
1715

1816
import { DEBUG_BUILD } from '../debug-build';
1917
import { getCurrentHub } from '../hub';
2018
import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary';
21-
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
19+
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
2220
import { getSpanDescendants, spanTimeInputToSeconds, spanToJSON, spanToTraceContext } from '../utils/spanUtils';
2321
import { getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
2422
import { SentrySpan } from './sentrySpan';
@@ -39,11 +37,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
3937

4038
private _trimEnd?: boolean | undefined;
4139

42-
// DO NOT yet remove this property, it is used in a hack for v7 backwards compatibility.
43-
private _frozenDynamicSamplingContext: Readonly<Partial<DynamicSamplingContext>> | undefined;
44-
45-
private _metadata: Partial<TransactionMetadata>;
46-
4740
/**
4841
* This constructor should never be called manually.
4942
* @internal
@@ -62,11 +55,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
6255

6356
this._name = transactionContext.name || '';
6457

65-
this._metadata = {
66-
// eslint-disable-next-line deprecation/deprecation
67-
...transactionContext.metadata,
68-
};
69-
7058
this._trimEnd = transactionContext.trimEnd;
7159

7260
this._attributes = {
@@ -78,45 +66,8 @@ export class Transaction extends SentrySpan implements TransactionInterface {
7866
// TODO (v8): Replace this with another way to set the root span
7967
// eslint-disable-next-line deprecation/deprecation
8068
this.transaction = this;
81-
82-
// If Dynamic Sampling Context is provided during the creation of the transaction, we freeze it as it usually means
83-
// there is incoming Dynamic Sampling Context. (Either through an incoming request, a baggage meta-tag, or other means)
84-
const incomingDynamicSamplingContext = this._metadata.dynamicSamplingContext;
85-
if (incomingDynamicSamplingContext) {
86-
// We shallow copy this in case anything writes to the original reference of the passed in `dynamicSamplingContext`
87-
this._frozenDynamicSamplingContext = { ...incomingDynamicSamplingContext };
88-
}
89-
}
90-
91-
// This sadly conflicts with the getter/setter ordering :(
92-
93-
/**
94-
* Get the metadata for this transaction.
95-
* @deprecated Use `spanGetMetadata(transaction)` instead.
96-
*/
97-
public get metadata(): TransactionMetadata {
98-
// We merge attributes in for backwards compatibility
99-
return {
100-
// Legacy metadata
101-
...this._metadata,
102-
103-
// From attributes
104-
...(this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] && {
105-
sampleRate: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] as TransactionMetadata['sampleRate'],
106-
}),
107-
};
108-
}
109-
110-
/**
111-
* Update the metadata for this transaction.
112-
* @deprecated Use `spanGetMetadata(transaction)` instead.
113-
*/
114-
public set metadata(metadata: TransactionMetadata) {
115-
this._metadata = metadata;
11669
}
11770

118-
/* eslint-enable @typescript-eslint/member-ordering */
119-
12071
/** @inheritdoc */
12172
public updateName(name: string): this {
12273
this._name = name;
@@ -146,14 +97,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
14697
this._measurements[name] = { value, unit };
14798
}
14899

149-
/**
150-
* Store metadata on this transaction.
151-
* @deprecated Use attributes or store data on the scope instead.
152-
*/
153-
public setMetadata(newMetadata: Partial<TransactionMetadata>): void {
154-
this._metadata = { ...this._metadata, ...newMetadata };
155-
}
156-
157100
/**
158101
* @inheritDoc
159102
*/
@@ -181,17 +124,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
181124
});
182125
}
183126

184-
/**
185-
* @inheritdoc
186-
*
187-
* @experimental
188-
*
189-
* @deprecated Use top-level `getDynamicSamplingContextFromSpan` instead.
190-
*/
191-
public getDynamicSamplingContext(): Readonly<Partial<DynamicSamplingContext>> {
192-
return getDynamicSamplingContextFromSpan(this);
193-
}
194-
195127
/**
196128
* Override the current hub with a new one.
197129
* Used if you want another hub to finish the transaction.
@@ -252,9 +184,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
252184

253185
const { scope: capturedSpanScope, isolationScope: capturedSpanIsolationScope } = getCapturedScopesOnSpan(this);
254186

255-
// eslint-disable-next-line deprecation/deprecation
256-
const { metadata } = this;
257-
258187
const source = this._attributes['sentry.source'] as TransactionSource | undefined;
259188

260189
const transaction: TransactionEvent = {
@@ -269,7 +198,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
269198
transaction: this._name,
270199
type: 'transaction',
271200
sdkProcessingMetadata: {
272-
...metadata,
273201
capturedSpanScope,
274202
capturedSpanIsolationScope,
275203
...dropUndefinedKeys({

packages/core/test/lib/tracing/dynamicSamplingContext.test.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
getDynamicSamplingContextFromSpan,
1111
startInactiveSpan,
1212
} from '../../../src/tracing';
13+
import { freezeDscOnSpan } from '../../../src/tracing/dynamicSamplingContext';
1314
import { TestClient, getDefaultTestClientOptions } from '../../mocks/client';
1415

1516
describe('getDynamicSamplingContextFromSpan', () => {
@@ -25,13 +26,15 @@ describe('getDynamicSamplingContextFromSpan', () => {
2526
jest.resetAllMocks();
2627
});
2728

28-
test('returns the DSC provided during transaction creation', () => {
29+
test('uses frozen DSC from span', () => {
2930
// eslint-disable-next-line deprecation/deprecation -- using old API on purpose
3031
const transaction = new Transaction({
3132
name: 'tx',
32-
metadata: { dynamicSamplingContext: { environment: 'myEnv' } },
33+
sampled: true,
3334
});
3435

36+
freezeDscOnSpan(transaction, { environment: 'myEnv' });
37+
3538
const dynamicSamplingContext = getDynamicSamplingContextFromSpan(transaction);
3639

3740
expect(dynamicSamplingContext).toStrictEqual({ environment: 'myEnv' });
@@ -77,10 +80,8 @@ describe('getDynamicSamplingContextFromSpan', () => {
7780
// eslint-disable-next-line deprecation/deprecation -- using old API on purpose
7881
const transaction = new Transaction({
7982
name: 'tx',
80-
metadata: {
81-
sampleRate: 0.56,
82-
},
8383
attributes: {
84+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 0.56,
8485
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'route',
8586
},
8687
sampled: true,
@@ -103,11 +104,9 @@ describe('getDynamicSamplingContextFromSpan', () => {
103104
// eslint-disable-next-line deprecation/deprecation -- using old API on purpose
104105
const transaction = new Transaction({
105106
name: 'tx',
106-
metadata: {
107-
sampleRate: 0.56,
108-
},
109107
attributes: {
110108
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
109+
[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE]: 0.56,
111110
},
112111
});
113112

0 commit comments

Comments
 (0)