Skip to content

Commit fcd63fa

Browse files
authored
feat(v8): Remove data from SentrySpan & rename types (#11303)
This removes `data` from the span (there is only `attributes` left). Also, for clarity, I renamed `SpanContext` to `SentrySpanArguments`, and `TransactionContext` to `TransactionArguments`, as "Context" is heavily overloaded and IMHO this is confusing today.
1 parent ee1b96b commit fcd63fa

File tree

17 files changed

+53
-181
lines changed

17 files changed

+53
-181
lines changed

Diff for: dev-packages/browser-integration-tests/suites/public-api/startSpan/circular_data/subject.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ const chicken = {};
22
const egg = { contains: chicken };
33
chicken.lays = egg;
44

5-
Sentry.startSpan({ name: 'circular_object_test_transaction', data: { chicken } }, () => {
6-
Sentry.startSpan({ op: 'circular_object_test_span', data: { chicken } }, () => undefined);
5+
Sentry.startSpan({ name: 'circular_object_test_transaction', attributes: { chicken } }, () => {
6+
Sentry.startSpan({ op: 'circular_object_test_span', attributes: { chicken } }, () => undefined);
77
});

Diff for: dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/interactions/test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Route } from '@playwright/test';
22
import { expect } from '@playwright/test';
3-
import type { Event, SpanContext, SpanJSON } from '@sentry/types';
3+
import type { Contexts, Event, SpanJSON } from '@sentry/types';
44

55
import { sentryTest } from '../../../../utils/fixtures';
66
import {
@@ -11,7 +11,7 @@ import {
1111

1212
type TransactionJSON = SpanJSON & {
1313
spans: SpanJSON[];
14-
contexts: SpanContext;
14+
contexts: Contexts;
1515
platform: string;
1616
type: string;
1717
};

Diff for: docs/v8-new-performance-apis.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ There are three key APIs available to start spans:
4747
- `startSpanManual()`
4848
- `startInactiveSpan()`
4949

50-
All three span APIs take a `SpanContext` as a first argument, which has the following shape:
50+
All three span APIs take `StartSpanOptions` as a first argument, which has the following shape:
5151

5252
```ts
53-
interface SpanContext {
53+
interface StartSpanOptions {
5454
// The only required field - the name of the span
5555
name: string;
5656
attributes?: SpanAttributes;

Diff for: packages/core/src/tracing/sampling.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Options, SamplingContext, TransactionContext } from '@sentry/types';
1+
import type { Options, SamplingContext, TransactionArguments } from '@sentry/types';
22
import { isNaN, logger } from '@sentry/utils';
33

44
import { DEBUG_BUILD } from '../debug-build';
@@ -14,7 +14,7 @@ import { hasTracingEnabled } from '../utils/hasTracingEnabled';
1414
* It returns the same transaction, for convenience.
1515
*/
1616
export function sampleTransaction(
17-
transactionContext: TransactionContext,
17+
transactionContext: TransactionArguments,
1818
options: Pick<Options, 'tracesSampleRate' | 'tracesSampler' | 'enableTracing'>,
1919
samplingContext: SamplingContext,
2020
): [sampled: boolean, sampleRate?: number] {

Diff for: packages/core/src/tracing/sentryNonRecordingSpan.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type {
2+
SentrySpanArguments,
23
Span,
34
SpanAttributeValue,
45
SpanAttributes,
5-
SpanContext,
66
SpanContextData,
77
SpanStatus,
88
SpanTimeInput,
@@ -17,7 +17,7 @@ export class SentryNonRecordingSpan implements Span {
1717
private _traceId: string;
1818
private _spanId: string;
1919

20-
public constructor(spanContext: SpanContext = {}) {
20+
public constructor(spanContext: SentrySpanArguments = {}) {
2121
this._traceId = spanContext.traceId || uuid4();
2222
this._spanId = spanContext.spanId || uuid4().substring(16);
2323
}

Diff for: packages/core/src/tracing/sentrySpan.ts

+9-59
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import type {
2+
SentrySpanArguments,
23
Span,
34
SpanAttributeValue,
45
SpanAttributes,
5-
SpanContext,
66
SpanContextData,
77
SpanJSON,
88
SpanOrigin,
@@ -32,13 +32,6 @@ import {
3232
* Span contains all data about a span
3333
*/
3434
export class SentrySpan implements Span {
35-
/**
36-
* Data for the span.
37-
* @deprecated Use `spanToJSON(span).atttributes` instead.
38-
*/
39-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
40-
public data: { [key: string]: any };
41-
4235
/**
4336
* @inheritDoc
4437
* @deprecated Use top level `Sentry.getRootSpan()` instead
@@ -66,12 +59,10 @@ export class SentrySpan implements Span {
6659
* @hideconstructor
6760
* @hidden
6861
*/
69-
public constructor(spanContext: SpanContext = {}) {
62+
public constructor(spanContext: SentrySpanArguments = {}) {
7063
this._traceId = spanContext.traceId || uuid4();
7164
this._spanId = spanContext.spanId || uuid4().substring(16);
7265
this._startTime = spanContext.startTimestamp || timestampInSeconds();
73-
// eslint-disable-next-line deprecation/deprecation
74-
this.data = spanContext.data ? { ...spanContext.data } : {};
7566

7667
this._attributes = {};
7768
this.setAttributes({
@@ -164,7 +155,10 @@ export class SentrySpan implements Span {
164155
* @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
165156
*/
166157
public startChild(
167-
spanContext: Pick<SpanContext, Exclude<keyof SpanContext, 'sampled' | 'traceId' | 'parentSpanId'>> = {},
158+
spanContext: Pick<
159+
SentrySpanArguments,
160+
Exclude<keyof SentrySpanArguments, 'sampled' | 'traceId' | 'parentSpanId'>
161+
> = {},
168162
): Span {
169163
const childSpan = new SentrySpan({
170164
...spanContext,
@@ -206,19 +200,6 @@ export class SentrySpan implements Span {
206200
return childSpan;
207201
}
208202

209-
/**
210-
* Sets the data attribute on the current span
211-
* @param key Data key
212-
* @param value Data value
213-
* @deprecated Use `setAttribute()` instead.
214-
*/
215-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
216-
public setData(key: string, value: any): this {
217-
// eslint-disable-next-line deprecation/deprecation
218-
this.data = { ...this.data, [key]: value };
219-
return this;
220-
}
221-
222203
/** @inheritdoc */
223204
public setAttribute(key: string, value: SpanAttributeValue | undefined): void {
224205
if (value === undefined) {
@@ -291,9 +272,9 @@ export class SentrySpan implements Span {
291272
*
292273
* @deprecated Use `spanToJSON()` or access the fields directly instead.
293274
*/
294-
public toContext(): SpanContext {
275+
public toContext(): SentrySpanArguments {
295276
return dropUndefinedKeys({
296-
data: this._getData(),
277+
data: this._attributes,
297278
name: this._name,
298279
endTimestamp: this._endTime,
299280
op: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP],
@@ -325,7 +306,7 @@ export class SentrySpan implements Span {
325306
*/
326307
public getSpanJSON(): SpanJSON {
327308
return dropUndefinedKeys({
328-
data: this._getData(),
309+
data: this._attributes,
329310
description: this._name,
330311
op: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP],
331312
parent_span_id: this._parentSpanId,
@@ -352,37 +333,6 @@ export class SentrySpan implements Span {
352333
return this.getSpanJSON();
353334
}
354335

355-
/**
356-
* Get the merged data for this span.
357-
* For now, this combines `data` and `attributes` together,
358-
* until eventually we can ingest `attributes` directly.
359-
*/
360-
private _getData():
361-
| {
362-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
363-
[key: string]: any;
364-
}
365-
| undefined {
366-
// eslint-disable-next-line deprecation/deprecation
367-
const { data, _attributes: attributes } = this;
368-
369-
const hasData = Object.keys(data).length > 0;
370-
const hasAttributes = Object.keys(attributes).length > 0;
371-
372-
if (!hasData && !hasAttributes) {
373-
return undefined;
374-
}
375-
376-
if (hasData && hasAttributes) {
377-
return {
378-
...data,
379-
...attributes,
380-
};
381-
}
382-
383-
return hasData ? data : attributes;
384-
}
385-
386336
/** Emit `spanEnd` when the span is ended. */
387337
private _onSpanEnded(): void {
388338
const client = getClient();

Diff for: packages/core/src/tracing/trace.ts

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ClientOptions, Scope, Span, SpanTimeInput, StartSpanOptions, TransactionContext } from '@sentry/types';
1+
import type { ClientOptions, Scope, Span, SpanTimeInput, StartSpanOptions, TransactionArguments } from '@sentry/types';
22

33
import { propagationContextFromHeaders } from '@sentry/utils';
44
import type { AsyncContextStrategy } from '../asyncContext';
@@ -211,7 +211,7 @@ function createChildSpanOrTransaction({
211211
scope,
212212
}: {
213213
parentSpan: SentrySpan | undefined;
214-
spanContext: TransactionContext;
214+
spanContext: TransactionArguments;
215215
forceTransaction?: boolean;
216216
scope: Scope;
217217
}): Span {
@@ -275,15 +275,15 @@ function createChildSpanOrTransaction({
275275
}
276276

277277
/**
278-
* This converts StartSpanOptions to TransactionContext.
278+
* This converts StartSpanOptions to TransactionArguments.
279279
* For the most part (for now) we accept the same options,
280280
* but some of them need to be transformed.
281281
*
282282
* Eventually the StartSpanOptions will be more aligned with OpenTelemetry.
283283
*/
284-
function normalizeContext(context: StartSpanOptions): TransactionContext {
284+
function normalizeContext(context: StartSpanOptions): TransactionArguments {
285285
if (context.startTime) {
286-
const ctx: TransactionContext & { startTime?: SpanTimeInput } = { ...context };
286+
const ctx: TransactionArguments & { startTime?: SpanTimeInput } = { ...context };
287287
ctx.startTimestamp = spanTimeInputToSeconds(context.startTime);
288288
delete ctx.startTime;
289289
return ctx;
@@ -297,19 +297,15 @@ function getAcs(): AsyncContextStrategy {
297297
return getAsyncContextStrategy(carrier);
298298
}
299299

300-
function _startTransaction(transactionContext: TransactionContext): Transaction {
300+
function _startTransaction(transactionContext: TransactionArguments): Transaction {
301301
const client = getClient();
302302
const options: Partial<ClientOptions> = (client && client.getOptions()) || {};
303303

304304
const [sampled, sampleRate] = sampleTransaction(transactionContext, options, {
305305
name: transactionContext.name,
306306
parentSampled: transactionContext.parentSampled,
307307
transactionContext,
308-
attributes: {
309-
// eslint-disable-next-line deprecation/deprecation
310-
...transactionContext.data,
311-
...transactionContext.attributes,
312-
},
308+
attributes: transactionContext.attributes,
313309
});
314310

315311
// eslint-disable-next-line deprecation/deprecation

Diff for: packages/core/src/tracing/transaction.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type {
88
SpanJSON,
99
SpanTimeInput,
1010
Transaction as TransactionInterface,
11-
TransactionContext,
11+
TransactionArguments,
1212
TransactionEvent,
1313
TransactionMetadata,
1414
TransactionSource,
@@ -52,7 +52,7 @@ export class Transaction extends SentrySpan implements TransactionInterface {
5252
*
5353
* @deprecated Transactions will be removed in v8. Use spans instead.
5454
*/
55-
public constructor(transactionContext: TransactionContext, hub?: Hub) {
55+
public constructor(transactionContext: TransactionArguments, hub?: Hub) {
5656
super(transactionContext);
5757
this._measurements = {};
5858
this._contexts = {};
@@ -170,7 +170,7 @@ export class Transaction extends SentrySpan implements TransactionInterface {
170170
/**
171171
* @inheritDoc
172172
*/
173-
public toContext(): TransactionContext {
173+
public toContext(): TransactionArguments {
174174
// eslint-disable-next-line deprecation/deprecation
175175
const spanContext = super.toContext();
176176

Diff for: packages/core/test/lib/tracing/sentrySpan.test.ts

-64
Original file line numberDiff line numberDiff line change
@@ -351,68 +351,4 @@ describe('SentrySpan', () => {
351351
});
352352
});
353353
});
354-
355-
// Ensure that attributes & data are merged together
356-
describe('_getData', () => {
357-
it('works without data & attributes', () => {
358-
const span = new SentrySpan();
359-
360-
expect(span['_getData']()).toEqual({
361-
// origin is set by default to 'manual' in the SentrySpan constructor
362-
'sentry.origin': 'manual',
363-
});
364-
});
365-
366-
it('works with data only', () => {
367-
const span = new SentrySpan();
368-
// eslint-disable-next-line deprecation/deprecation
369-
span.setData('foo', 'bar');
370-
371-
expect(span['_getData']()).toEqual({
372-
foo: 'bar',
373-
// origin is set by default to 'manual' in the SentrySpan constructor
374-
'sentry.origin': 'manual',
375-
});
376-
expect(span['_getData']()).toStrictEqual({
377-
// eslint-disable-next-line deprecation/deprecation
378-
...span.data,
379-
'sentry.origin': 'manual',
380-
});
381-
});
382-
383-
it('works with attributes only', () => {
384-
const span = new SentrySpan();
385-
span.setAttribute('foo', 'bar');
386-
387-
expect(span['_getData']()).toEqual({
388-
foo: 'bar',
389-
// origin is set by default to 'manual' in the SentrySpan constructor
390-
'sentry.origin': 'manual',
391-
});
392-
// eslint-disable-next-line deprecation/deprecation
393-
expect(span['_getData']()).toBe(span.attributes);
394-
});
395-
396-
it('merges data & attributes', () => {
397-
const span = new SentrySpan();
398-
span.setAttribute('foo', 'foo');
399-
span.setAttribute('bar', 'bar');
400-
// eslint-disable-next-line deprecation/deprecation
401-
span.setData('foo', 'foo2');
402-
// eslint-disable-next-line deprecation/deprecation
403-
span.setData('baz', 'baz');
404-
405-
expect(span['_getData']()).toEqual({
406-
foo: 'foo',
407-
bar: 'bar',
408-
baz: 'baz',
409-
// origin is set by default to 'manual' in the SentrySpan constructor
410-
'sentry.origin': 'manual',
411-
});
412-
// eslint-disable-next-line deprecation/deprecation
413-
expect(span['_getData']()).not.toBe(span.attributes);
414-
// eslint-disable-next-line deprecation/deprecation
415-
expect(span['_getData']()).not.toBe(span.data);
416-
});
417-
});
418354
});

Diff for: packages/node/test/integrations/http.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getCurrentHub, getIsolationScope, setCurrentClient } from '@sentry/core
55
import { Transaction } from '@sentry/core';
66
import { getCurrentScope, setUser, spanToJSON, startInactiveSpan } from '@sentry/core';
77
import { addTracingExtensions } from '@sentry/core';
8-
import type { TransactionContext } from '@sentry/types';
8+
import type { TransactionArguments } from '@sentry/types';
99
import { TRACEPARENT_REGEXP } from '@sentry/utils';
1010
import * as nock from 'nock';
1111
import { HttpsProxyAgent } from '../../src/proxy';
@@ -38,7 +38,7 @@ describe('tracing', () => {
3838

3939
function createTransactionOnScope(
4040
customOptions: Partial<NodeClientOptions> = {},
41-
customContext?: Partial<TransactionContext>,
41+
customContext?: Partial<TransactionArguments>,
4242
) {
4343
setupMockHub(customOptions);
4444
addTracingExtensions();

Diff for: packages/react/test/profiler.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { SentrySpan } from '@sentry/core';
2-
import type { SpanContext } from '@sentry/types';
2+
import type { StartSpanOptions } from '@sentry/types';
33
import { render } from '@testing-library/react';
44
import { renderHook } from '@testing-library/react-hooks';
55
// biome-ignore lint/nursery/noUnusedImports: Need React import for JSX
@@ -8,7 +8,7 @@ import * as React from 'react';
88
import { REACT_MOUNT_OP, REACT_RENDER_OP, REACT_UPDATE_OP } from '../src/constants';
99
import { UNKNOWN_COMPONENT, useProfiler, withProfiler } from '../src/profiler';
1010

11-
const mockStartInactiveSpan = jest.fn((spanArgs: SpanContext) => ({ ...spanArgs }));
11+
const mockStartInactiveSpan = jest.fn((spanArgs: StartSpanOptions) => ({ ...spanArgs }));
1212
const mockFinish = jest.fn();
1313

1414
class MockSpan extends SentrySpan {
@@ -22,7 +22,7 @@ let activeSpan: Record<string, any>;
2222
jest.mock('@sentry/browser', () => ({
2323
...jest.requireActual('@sentry/browser'),
2424
getActiveSpan: () => activeSpan,
25-
startInactiveSpan: (ctx: SpanContext) => {
25+
startInactiveSpan: (ctx: StartSpanOptions) => {
2626
mockStartInactiveSpan(ctx);
2727
return new MockSpan(ctx);
2828
},

0 commit comments

Comments
 (0)