Skip to content

Commit fb5745d

Browse files
committed
ref(tracing): Remove span.startChild()
Also refactor the span logging behavior into a logging integration, to make this consistent between core & otel-powered spans.
1 parent 14c7c6b commit fb5745d

File tree

25 files changed

+146
-150
lines changed

25 files changed

+146
-150
lines changed

packages/angular/src/sdk.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
dedupeIntegration,
1313
functionToStringIntegration,
1414
inboundFiltersIntegration,
15+
spanLoggerIntegration,
1516
} from '@sentry/core';
1617
import type { Integration } from '@sentry/types';
1718
import { logger } from '@sentry/utils';
@@ -30,7 +31,7 @@ export function getDefaultIntegrations(): Integration[] {
3031
// see:
3132
// - https://github.com/getsentry/sentry-javascript/issues/5417#issuecomment-1453407097
3233
// - https://github.com/getsentry/sentry-javascript/issues/2744
33-
return [
34+
const integrations: Integration[] = [
3435
inboundFiltersIntegration(),
3536
functionToStringIntegration(),
3637
breadcrumbsIntegration(),
@@ -39,6 +40,12 @@ export function getDefaultIntegrations(): Integration[] {
3940
dedupeIntegration(),
4041
httpContextIntegration(),
4142
];
43+
44+
if (IS_DEBUG_BUILD) {
45+
integrations.push(spanLoggerIntegration());
46+
}
47+
48+
return integrations;
4249
}
4350

4451
/**

packages/aws-serverless/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export {
9999
extraErrorDataIntegration,
100100
rewriteFramesIntegration,
101101
sessionTimingIntegration,
102+
spanLoggerIntegration,
102103
} from '@sentry/core';
103104

104105
export { getDefaultIntegrations, init, tryPatchHandler, wrapHandler } from './awslambda';

packages/browser/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export {
1010
extraErrorDataIntegration,
1111
rewriteFramesIntegration,
1212
sessionTimingIntegration,
13+
spanLoggerIntegration,
1314
} from '@sentry/core';
1415

1516
export {

packages/browser/src/integrations/breadcrumbs.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable max-lines */
21
import { addBreadcrumb, defineIntegration, getClient } from '@sentry/core';
32
import type {
43
Client,

packages/browser/src/sdk.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getCurrentScope } from '@sentry/core';
1+
import { getCurrentScope, spanLoggerIntegration } from '@sentry/core';
22
import { functionToStringIntegration, inboundFiltersIntegration } from '@sentry/core';
33
import {
44
captureSession,
@@ -36,7 +36,7 @@ export function getDefaultIntegrations(_options: Options): Integration[] {
3636
* Note: Please make sure this stays in sync with Angular SDK, which re-exports
3737
* `getDefaultIntegrations` but with an adjusted set of integrations.
3838
*/
39-
return [
39+
const integrations: Integration[] = [
4040
inboundFiltersIntegration(),
4141
functionToStringIntegration(),
4242
browserApiErrorsIntegration(),
@@ -46,6 +46,12 @@ export function getDefaultIntegrations(_options: Options): Integration[] {
4646
dedupeIntegration(),
4747
httpContextIntegration(),
4848
];
49+
50+
if (DEBUG_BUILD) {
51+
integrations.push(spanLoggerIntegration());
52+
}
53+
54+
return integrations;
4955
}
5056

5157
function applyDefaultOptions(optionsArg: BrowserOptions = {}): BrowserOptions {

packages/bun/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ export {
120120
extraErrorDataIntegration,
121121
rewriteFramesIntegration,
122122
sessionTimingIntegration,
123+
spanLoggerIntegration,
123124
} from '@sentry/core';
124125

125126
export type { BunOptions } from './types';

packages/bun/src/sdk.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
inboundFiltersIntegration,
44
linkedErrorsIntegration,
55
requestDataIntegration,
6+
spanLoggerIntegration,
67
} from '@sentry/core';
78
import {
89
consoleIntegration,
@@ -29,6 +30,7 @@ export function getDefaultIntegrations(_options: Options): Integration[] {
2930
functionToStringIntegration(),
3031
linkedErrorsIntegration(),
3132
requestDataIntegration(),
33+
spanLoggerIntegration(),
3234
// Native Wrappers
3335
consoleIntegration(),
3436
httpIntegration(),

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export { dedupeIntegration } from './integrations/dedupe';
9999
export { extraErrorDataIntegration } from './integrations/extraerrordata';
100100
export { rewriteFramesIntegration } from './integrations/rewriteframes';
101101
export { sessionTimingIntegration } from './integrations/sessiontiming';
102+
export { spanLoggerIntegration } from './integrations/spanlogger';
102103
export { metrics } from './metrics/exports';
103104
export type { MetricData } from './metrics/exports';
104105
export { metricsDefault } from './metrics/exports-default';
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import type { IntegrationFn } from '@sentry/types';
2+
import { logger } from '@sentry/utils';
3+
import { DEBUG_BUILD } from '../debug-build';
4+
import { defineIntegration } from '../integration';
5+
import { getRootSpan, spanIsSampled, spanToJSON } from '../utils/spanUtils';
6+
7+
const _spanLoggerIntegration = (() => {
8+
return {
9+
name: 'SpanLogger',
10+
setup(client) {
11+
if (!DEBUG_BUILD) return;
12+
13+
client.on('spanStart', span => {
14+
const {
15+
description = '< unknown name >',
16+
op = '< unknown op >',
17+
parent_span_id: parentSpanId,
18+
} = spanToJSON(span);
19+
const { spanId } = span.spanContext();
20+
21+
const sampled = spanIsSampled(span);
22+
const rootSpan = getRootSpan(span);
23+
const isRootSpan = rootSpan === span;
24+
25+
const header = `[Tracing] Starting ${sampled ? 'sampled' : 'unsampled'} ${isRootSpan ? 'root ' : ''}span`;
26+
27+
const infoParts: string[] = [`op: ${op}`, `name: ${description}`, `ID: ${spanId}`];
28+
29+
if (parentSpanId) {
30+
infoParts.push(`parent ID: ${parentSpanId}`);
31+
}
32+
33+
if (!isRootSpan) {
34+
const { op, description } = spanToJSON(rootSpan);
35+
infoParts.push(`root ID: ${rootSpan.spanContext().spanId}`);
36+
if (op) {
37+
infoParts.push(`root op: ${op}`);
38+
}
39+
if (description) {
40+
infoParts.push(`root description: ${description}`);
41+
}
42+
}
43+
44+
logger.log(`${header}
45+
${infoParts.join('\n ')}`);
46+
});
47+
48+
client.on('spanEnd', span => {
49+
const { description = '< unknown name >', op = '< unknown op >' } = spanToJSON(span);
50+
const { spanId } = span.spanContext();
51+
const rootSpan = getRootSpan(span);
52+
const isRootSpan = rootSpan === span;
53+
54+
const msg = `[Tracing] Finishing "${op}" ${isRootSpan ? 'root ' : ''}span "${description}" with ID ${spanId}`;
55+
logger.log(msg);
56+
});
57+
},
58+
};
59+
}) satisfies IntegrationFn;
60+
61+
/**
62+
* Log span information to the debugger.
63+
* This will not do anything if DEUBG_BUILD is disabled.
64+
*/
65+
export const spanLoggerIntegration = defineIntegration(_spanLoggerIntegration);

packages/core/src/tracing/idleSpan.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,6 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
196196
function _pushActivity(spanId: string): void {
197197
_cancelIdleTimeout();
198198
activities.set(spanId, true);
199-
DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`);
200-
DEBUG_BUILD && logger.log('[Tracing] new activities count', activities.size);
201199

202200
const endTimestamp = timestampInSeconds();
203201
// We need to add the timeout here to have the real endtimestamp of the idle span
@@ -211,9 +209,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
211209
*/
212210
function _popActivity(spanId: string): void {
213211
if (activities.has(spanId)) {
214-
DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`);
215212
activities.delete(spanId);
216-
DEBUG_BUILD && logger.log('[Tracing] new activities count', activities.size);
217213
}
218214

219215
if (activities.size === 0) {
@@ -248,8 +244,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
248244
span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, _finishReason);
249245
}
250246

251-
DEBUG_BUILD &&
252-
logger.log('[Tracing] finishing idle span', new Date(endTimestamp * 1000).toISOString(), spanJSON.op);
247+
logger.log(`[Tracing] Idle span "${spanJSON.op}" finished`);
253248

254249
const childSpans = getSpanDescendants(span).filter(child => child !== span);
255250

@@ -259,7 +254,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
259254
childSpan.setStatus({ code: SPAN_STATUS_ERROR, message: 'cancelled' });
260255
childSpan.end(endTimestamp);
261256
DEBUG_BUILD &&
262-
logger.log('[Tracing] cancelling span since span ended early', JSON.stringify(childSpan, undefined, 2));
257+
logger.log('[Tracing] Cancelling span since span ended early', JSON.stringify(childSpan, undefined, 2));
263258
}
264259

265260
const childSpanJSON = spanToJSON(childSpan);
@@ -274,18 +269,16 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
274269
if (DEBUG_BUILD) {
275270
const stringifiedSpan = JSON.stringify(childSpan, undefined, 2);
276271
if (!spanStartedBeforeIdleSpanEnd) {
277-
logger.log('[Tracing] discarding Span since it happened after idle span was finished', stringifiedSpan);
272+
logger.log('[Tracing] Discarding span since it happened after idle span was finished', stringifiedSpan);
278273
} else if (!spanEndedBeforeFinalTimeout) {
279-
logger.log('[Tracing] discarding Span since it finished after idle span final timeout', stringifiedSpan);
274+
logger.log('[Tracing] Discarding span since it finished after idle span final timeout', stringifiedSpan);
280275
}
281276
}
282277

283278
if (!spanEndedBeforeFinalTimeout || !spanStartedBeforeIdleSpanEnd) {
284279
removeChildSpanFromSpan(span, childSpan);
285280
}
286281
});
287-
288-
DEBUG_BUILD && logger.log('[Tracing] flushing idle span');
289282
}
290283

291284
client.on('spanStart', startedSpan => {
@@ -349,7 +342,7 @@ function _startIdleSpan(options: StartSpanOptions): Span {
349342

350343
_setSpanForScope(getCurrentScope(), span);
351344

352-
DEBUG_BUILD && logger.log(`Setting idle span on scope. Span ID: ${span.spanContext().spanId}`);
345+
DEBUG_BUILD && logger.log('[Tracing] Started span is an idle span');
353346

354347
return span;
355348
}

packages/core/src/tracing/sentrySpan.ts

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@ import type {
99
SpanStatus,
1010
SpanTimeInput,
1111
} from '@sentry/types';
12-
import { dropUndefinedKeys, logger, timestampInSeconds, uuid4 } from '@sentry/utils';
12+
import { dropUndefinedKeys, timestampInSeconds, uuid4 } from '@sentry/utils';
1313
import { getClient } from '../currentScopes';
1414

15-
import { DEBUG_BUILD } from '../debug-build';
1615
import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary';
1716
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '../semanticAttributes';
1817
import {
1918
TRACE_FLAG_NONE,
2019
TRACE_FLAG_SAMPLED,
21-
addChildSpanToSpan,
22-
getRootSpan,
2320
getStatusMessage,
2421
spanTimeInputToSeconds,
2522
spanToJSON,
@@ -42,8 +39,6 @@ export class SentrySpan implements Span {
4239
/** Internal keeper of the status */
4340
protected _status?: SpanStatus;
4441

45-
private _logMessage?: string;
46-
4742
/**
4843
* You should never call the constructor manually, always use `Sentry.startSpan()`
4944
* or other span methods.
@@ -87,54 +82,6 @@ export class SentrySpan implements Span {
8782
};
8883
}
8984

90-
/**
91-
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`.
92-
* Also the `sampled` decision will be inherited.
93-
*
94-
* @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
95-
*/
96-
public startChild(
97-
spanContext: Pick<
98-
SentrySpanArguments,
99-
Exclude<keyof SentrySpanArguments, 'sampled' | 'traceId' | 'parentSpanId'>
100-
> = {},
101-
): Span {
102-
const childSpan = new SentrySpan({
103-
...spanContext,
104-
parentSpanId: this._spanId,
105-
sampled: this._sampled,
106-
traceId: this._traceId,
107-
});
108-
109-
// To allow for interoperability we track the children of a span twice: Once with the span recorder (old) once with
110-
// the `addChildSpanToSpan`. Eventually we will only use `addChildSpanToSpan` and drop the span recorder.
111-
// To ensure interoperability with the `startSpan` API, `addChildSpanToSpan` is also called here.
112-
addChildSpanToSpan(this, childSpan);
113-
114-
const rootSpan = getRootSpan(this);
115-
116-
if (DEBUG_BUILD && rootSpan) {
117-
const opStr = (spanContext && spanContext.op) || '< unknown op >';
118-
const nameStr = spanToJSON(childSpan).description || '< unknown name >';
119-
const idStr = rootSpan.spanContext().spanId;
120-
121-
const logMessage = `[Tracing] Starting '${opStr}' span on transaction '${nameStr}' (${idStr}).`;
122-
logger.log(logMessage);
123-
this._logMessage = logMessage;
124-
}
125-
126-
const client = getClient();
127-
if (client) {
128-
client.emit('spanStart', childSpan);
129-
// If it has an endTimestamp, it's already ended
130-
if (spanContext.endTimestamp) {
131-
client.emit('spanEnd', childSpan);
132-
}
133-
}
134-
135-
return childSpan;
136-
}
137-
13885
/** @inheritdoc */
13986
public setAttribute(key: string, value: SpanAttributeValue | undefined): void {
14087
if (value === undefined) {
@@ -184,18 +131,6 @@ export class SentrySpan implements Span {
184131
if (this._endTime) {
185132
return;
186133
}
187-
const rootSpan = getRootSpan(this);
188-
if (
189-
DEBUG_BUILD &&
190-
// Don't call this for transactions
191-
rootSpan &&
192-
rootSpan.spanContext().spanId !== this._spanId
193-
) {
194-
const logMessage = this._logMessage;
195-
if (logMessage) {
196-
logger.log((logMessage as string).replace('Starting', 'Finishing'));
197-
}
198-
}
199134

200135
this._endTime = spanTimeInputToSeconds(endTimestamp);
201136

0 commit comments

Comments
 (0)