Skip to content

Commit 21ba125

Browse files
committed
ref(v8): Remove metadata on transaction
Instead, we freeze the DSC explicitly onto the transaction now. Apply suggestions from code review Co-authored-by: Lukas Stracke <[email protected]> fix comments fix linting
1 parent 14c7c6b commit 21ba125

File tree

7 files changed

+69
-179
lines changed

7 files changed

+69
-179
lines changed

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,7 @@ 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',

packages/core/src/tracing/dynamicSamplingContext.ts

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
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+
/**
10+
* If you change this value, also update the terser plugin config to
11+
* avoid minification of the object property!
12+
*/
13+
const FROZEN_DSC_FIELD = '_frozenDsc';
14+
15+
type SpanWithMaybeDsc = Span & {
16+
[FROZEN_DSC_FIELD]?: Partial<DynamicSamplingContext> | undefined;
17+
};
18+
19+
/**
20+
* Freeze the given DSC on the given span.
21+
*/
22+
export function freezeDscOnSpan(span: Span, dsc: Partial<DynamicSamplingContext>): void {
23+
const spanWithMaybeDsc = span as SpanWithMaybeDsc;
24+
addNonEnumerableProperty(spanWithMaybeDsc, FROZEN_DSC_FIELD, dsc);
25+
}
26+
927
/**
1028
* Creates a dynamic sampling context from a client.
1129
*
@@ -28,11 +46,6 @@ export function getDynamicSamplingContextFromClient(trace_id: string, client: Cl
2846
return dsc;
2947
}
3048

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

4962
const dsc = getDynamicSamplingContextFromClient(spanToJSON(span).trace_id || '', client);
5063

51-
// TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
5264
const rootSpan = getRootSpan(span);
5365
if (!rootSpan) {
5466
return dsc;
5567
}
5668

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;
69+
const frozenDsc = (rootSpan as SpanWithMaybeDsc)[FROZEN_DSC_FIELD];
70+
if (frozenDsc) {
71+
return frozenDsc;
6372
}
6473

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 || {};
74+
const jsonSpan = spanToJSON(rootSpan);
75+
const attributes = jsonSpan.data || {};
76+
const maybeSampleRate = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE];
77+
6978
if (maybeSampleRate != null) {
7079
dsc.sample_rate = `${maybeSampleRate}`;
7180
}
7281

7382
// 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];
83+
const source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];
7784

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

packages/core/src/tracing/trace.ts

Lines changed: 6 additions & 17 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(),
@@ -254,19 +251,11 @@ function createChildSpanOrTransaction({
254251
parentSpanId,
255252
parentSampled: sampled,
256253
...spanContext,
257-
metadata: {
258-
dynamicSamplingContext: dsc,
259-
// eslint-disable-next-line deprecation/deprecation
260-
...spanContext.metadata,
261-
},
262254
});
263-
}
264255

265-
// TODO v8: Technically `startTransaction` can return undefined, which is not reflected by the types
266-
// This happens if tracing extensions have not been added
267-
// In this case, we just want to return a non-recording span
268-
if (!span) {
269-
return new SentryNonRecordingSpan();
256+
if (dsc) {
257+
freezeDscOnSpan(span, dsc);
258+
}
270259
}
271260

272261
setCapturedScopesOnSpan(span, scope, isolationScope);

packages/core/src/tracing/transaction.ts

Lines changed: 25 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type {
22
Contexts,
3-
DynamicSamplingContext,
43
Hub,
54
MeasurementUnit,
65
Measurements,
@@ -9,15 +8,14 @@ import type {
98
Transaction as TransactionInterface,
109
TransactionArguments,
1110
TransactionEvent,
12-
TransactionMetadata,
1311
TransactionSource,
1412
} from '@sentry/types';
1513
import { dropUndefinedKeys, logger } from '@sentry/utils';
1614

1715
import { DEBUG_BUILD } from '../debug-build';
1816
import { getCurrentHub } from '../hub';
1917
import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary';
20-
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
18+
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from '../semanticAttributes';
2119
import { getSpanDescendants, spanTimeInputToSeconds, spanToJSON, spanToTraceContext } from '../utils/spanUtils';
2220
import { getDynamicSamplingContextFromSpan } from './dynamicSamplingContext';
2321
import { SentrySpan } from './sentrySpan';
@@ -38,11 +36,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
3836

3937
private _trimEnd?: boolean | undefined;
4038

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

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

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

7159
this._attributes = {
7260
[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'custom',
7361
...this._attributes,
7462
};
75-
76-
// If Dynamic Sampling Context is provided during the creation of the transaction, we freeze it as it usually means
77-
// there is incoming Dynamic Sampling Context. (Either through an incoming request, a baggage meta-tag, or other means)
78-
const incomingDynamicSamplingContext = this._metadata.dynamicSamplingContext;
79-
if (incomingDynamicSamplingContext) {
80-
// We shallow copy this in case anything writes to the original reference of the passed in `dynamicSamplingContext`
81-
this._frozenDynamicSamplingContext = { ...incomingDynamicSamplingContext };
82-
}
8363
}
8464

85-
// This sadly conflicts with the getter/setter ordering :(
86-
87-
/**
88-
* Get the metadata for this transaction.
89-
* @deprecated Use `spanGetMetadata(transaction)` instead.
90-
*/
91-
public get metadata(): TransactionMetadata {
92-
// We merge attributes in for backwards compatibility
93-
return {
94-
// Legacy metadata
95-
...this._metadata,
96-
97-
// From attributes
98-
...(this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] && {
99-
sampleRate: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] as TransactionMetadata['sampleRate'],
100-
}),
101-
};
102-
}
103-
104-
/**
105-
* Update the metadata for this transaction.
106-
* @deprecated Use `spanGetMetadata(transaction)` instead.
107-
*/
108-
public set metadata(metadata: TransactionMetadata) {
109-
this._metadata = metadata;
110-
}
111-
112-
/* eslint-enable @typescript-eslint/member-ordering */
113-
11465
/** @inheritdoc */
11566
public updateName(name: string): this {
11667
this._name = name;
@@ -127,14 +78,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
12778
this._measurements[name] = { value, unit };
12879
}
12980

130-
/**
131-
* Store metadata on this transaction.
132-
* @deprecated Use attributes or store data on the scope instead.
133-
*/
134-
public setMetadata(newMetadata: Partial<TransactionMetadata>): void {
135-
this._metadata = { ...this._metadata, ...newMetadata };
136-
}
137-
13881
/**
13982
* @inheritDoc
14083
*/
@@ -148,6 +91,30 @@ export class Transaction extends SentrySpan implements TransactionInterface {
14891
return this._hub.captureEvent(transaction);
14992
}
15093

94+
/**
95+
* @inheritDoc
96+
*/
97+
public toContext(): TransactionArguments {
98+
// eslint-disable-next-line deprecation/deprecation
99+
const spanContext = super.toContext();
100+
101+
return dropUndefinedKeys({
102+
...spanContext,
103+
name: this._name,
104+
trimEnd: this._trimEnd,
105+
});
106+
}
107+
108+
/**
109+
* Override the current hub with a new one.
110+
* Used if you want another hub to finish the transaction.
111+
*
112+
* @internal
113+
*/
114+
public setHub(hub: Hub): void {
115+
this._hub = hub;
116+
}
117+
151118
/**
152119
* Finish the transaction & prepare the event to send to Sentry.
153120
*/
@@ -198,9 +165,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
198165

199166
const { scope: capturedSpanScope, isolationScope: capturedSpanIsolationScope } = getCapturedScopesOnSpan(this);
200167

201-
// eslint-disable-next-line deprecation/deprecation
202-
const { metadata } = this;
203-
204168
const source = this._attributes['sentry.source'] as TransactionSource | undefined;
205169

206170
const transaction: TransactionEvent = {
@@ -215,7 +179,6 @@ export class Transaction extends SentrySpan implements TransactionInterface {
215179
transaction: this._name,
216180
type: 'transaction',
217181
sdkProcessingMetadata: {
218-
...metadata,
219182
capturedSpanScope,
220183
capturedSpanIsolationScope,
221184
...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)