Skip to content

Commit 03e6338

Browse files
committed
fix(browser): Fix idle span ending
1 parent 48b0a35 commit 03e6338

File tree

2 files changed

+47
-41
lines changed

2 files changed

+47
-41
lines changed

packages/core/src/tracing/idleSpan.ts

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -113,37 +113,48 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
113113
const previousActiveSpan = getActiveSpan();
114114
const span = _startIdleSpan(startSpanOptions);
115115

116-
function _endSpan(timestamp: number = timestampInSeconds()): void {
117-
// Ensure we end with the last span timestamp, if possible
118-
const spans = getSpanDescendants(span).filter(child => child !== span);
116+
// We patch span.end to ensure we can run some things before the span is ended
117+
// eslint-disable-next-line @typescript-eslint/unbound-method
118+
span.end = new Proxy(span.end, {
119+
apply(target, thisArg, args: Parameters<Span['end']>) {
120+
if (beforeSpanEnd) {
121+
beforeSpanEnd(span);
122+
}
119123

120-
// If we have no spans, we just end, nothing else to do here
121-
if (!spans.length) {
122-
span.end(timestamp);
123-
return;
124-
}
124+
onIdleSpanEnded();
125125

126-
const childEndTimestamps = spans
127-
.map(span => spanToJSON(span).timestamp)
128-
.filter(timestamp => !!timestamp) as number[];
129-
const latestSpanEndTimestamp = childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined;
130-
131-
const spanEndTimestamp = spanTimeInputToSeconds(timestamp);
132-
// In reality this should always exist here, but type-wise it may be undefined...
133-
const spanStartTimestamp = spanToJSON(span).start_timestamp;
134-
135-
// The final endTimestamp should:
136-
// * Never be before the span start timestamp
137-
// * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp
138-
// * Otherwise be the passed end timestamp
139-
// Final timestamp can never be after finalTimeout
140-
const endTimestamp = Math.min(
141-
spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity,
142-
Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)),
143-
);
144-
145-
span.end(endTimestamp);
146-
}
126+
const timestamp = args[0] || timestampInSeconds();
127+
128+
// Ensure we end with the last span timestamp, if possible
129+
const spans = getSpanDescendants(span).filter(child => child !== span);
130+
131+
// If we have no spans, we just end, nothing else to do here
132+
if (!spans.length) {
133+
return Reflect.apply(target, thisArg, args);
134+
}
135+
136+
const childEndTimestamps = spans
137+
.map(span => spanToJSON(span).timestamp)
138+
.filter(timestamp => !!timestamp) as number[];
139+
const latestSpanEndTimestamp = childEndTimestamps.length ? Math.max(...childEndTimestamps) : undefined;
140+
141+
const spanEndTimestamp = spanTimeInputToSeconds(timestamp);
142+
// In reality this should always exist here, but type-wise it may be undefined...
143+
const spanStartTimestamp = spanToJSON(span).start_timestamp;
144+
145+
// The final endTimestamp should:
146+
// * Never be before the span start timestamp
147+
// * Be the latestSpanEndTimestamp, if there is one, and it is smaller than the passed span end timestamp
148+
// * Otherwise be the passed end timestamp
149+
// Final timestamp can never be after finalTimeout
150+
const endTimestamp = Math.min(
151+
spanStartTimestamp ? spanStartTimestamp + finalTimeout / 1000 : Infinity,
152+
Math.max(spanStartTimestamp || -Infinity, Math.min(spanEndTimestamp, latestSpanEndTimestamp || Infinity)),
153+
);
154+
155+
return Reflect.apply(target, thisArg, [endTimestamp]);
156+
},
157+
});
147158

148159
/**
149160
* Cancels the existing idle timeout, if there is one.
@@ -173,7 +184,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
173184
_idleTimeoutID = setTimeout(() => {
174185
if (!_finished && activities.size === 0 && _autoFinishAllowed) {
175186
_finishReason = FINISH_REASON_IDLE_TIMEOUT;
176-
_endSpan(endTimestamp);
187+
span.end(endTimestamp);
177188
}
178189
}, idleTimeout);
179190
}
@@ -186,7 +197,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
186197
_idleTimeoutID = setTimeout(() => {
187198
if (!_finished && _autoFinishAllowed) {
188199
_finishReason = FINISH_REASON_HEARTBEAT_FAILED;
189-
_endSpan(endTimestamp);
200+
span.end(endTimestamp);
190201
}
191202
}, childSpanTimeout);
192203
}
@@ -227,10 +238,6 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
227238
_finished = true;
228239
activities.clear();
229240

230-
if (beforeSpanEnd) {
231-
beforeSpanEnd(span);
232-
}
233-
234241
_setSpanForScope(scope, previousActiveSpan);
235242

236243
const spanJSON = spanToJSON(span);
@@ -312,10 +319,6 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
312319
}
313320

314321
_popActivity(endedSpan.spanContext().spanId);
315-
316-
if (endedSpan === span) {
317-
onIdleSpanEnded();
318-
}
319322
});
320323

321324
client.on('idleSpanEnableAutoFinish', spanToAllowAutoFinish => {
@@ -338,7 +341,7 @@ export function startIdleSpan(startSpanOptions: StartSpanOptions, options: Parti
338341
if (!_finished) {
339342
span.setStatus({ code: SPAN_STATUS_ERROR, message: 'deadline_exceeded' });
340343
_finishReason = FINISH_REASON_FINAL_TIMEOUT;
341-
_endSpan();
344+
span.end();
342345
}
343346
}, finalTimeout);
344347

packages/core/src/tracing/sentrySpan.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,10 @@ export class SentrySpan implements Span {
342342

343343
if (hasMeasurements) {
344344
DEBUG_BUILD &&
345-
logger.log('[Measurements] Adding measurements to transaction', JSON.stringify(measurements, undefined, 2));
345+
logger.log(
346+
'[Measurements] Adding measurements to transaction event',
347+
JSON.stringify(measurements, undefined, 2),
348+
);
346349
transaction.measurements = measurements;
347350
}
348351

0 commit comments

Comments
 (0)