Skip to content

Commit ae950c7

Browse files
committed
fix(tracing): Make sure performance spans change transaction start timestamp
1 parent 82abd33 commit ae950c7

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

packages/tracing/src/browser/metrics.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Span } from '../span';
44
import { Transaction } from '../transaction';
55

66
import { msToSec } from './utils';
7+
import { TransactionContext, SpanContext } from '@sentry/types';
78

89
const global = getGlobalObject<Window>();
910

@@ -163,7 +164,7 @@ export class MetricsInstrumentation {
163164
});
164165

165166
if (entryScriptStartTimestamp !== undefined && tracingInitMarkStartTime !== undefined) {
166-
transaction.startChild({
167+
_startChild(transaction, {
167168
description: 'evaluation',
168169
endTimestamp: tracingInitMarkStartTime,
169170
op: 'script',
@@ -196,7 +197,7 @@ function addMeasureSpans(
196197
const measureStartTimestamp = timeOrigin + startTime;
197198
const measureEndTimestamp = measureStartTimestamp + duration;
198199

199-
transaction.startChild({
200+
_startChild(transaction, {
200201
description: entry.name as string,
201202
endTimestamp: measureEndTimestamp,
202203
op: entry.entryType as string,
@@ -229,7 +230,7 @@ function addResourceSpans(
229230
const startTimestamp = timeOrigin + startTime;
230231
const endTimestamp = startTimestamp + duration;
231232

232-
transaction.startChild({
233+
_startChild(transaction, {
233234
description: `${entry.initiatorType} ${resourceName}`,
234235
endTimestamp,
235236
op: 'resource',
@@ -254,7 +255,7 @@ function addPerformanceNavigationTiming(
254255
if (!start || !end) {
255256
return;
256257
}
257-
transaction.startChild({
258+
_startChild(transaction, {
258259
description: event,
259260
endTimestamp: timeOrigin + msToSec(end),
260261
op: 'browser',
@@ -264,17 +265,33 @@ function addPerformanceNavigationTiming(
264265

265266
/** Create request and response related spans */
266267
function addRequest(transaction: Transaction, entry: Record<string, any>, timeOrigin: number): void {
267-
transaction.startChild({
268+
_startChild(transaction, {
268269
description: 'request',
269270
endTimestamp: timeOrigin + msToSec(entry.responseEnd as number),
270271
op: 'browser',
271272
startTimestamp: timeOrigin + msToSec(entry.requestStart as number),
272273
});
273274

274-
transaction.startChild({
275+
_startChild(transaction, {
275276
description: 'response',
276277
endTimestamp: timeOrigin + msToSec(entry.responseEnd as number),
277278
op: 'browser',
278279
startTimestamp: timeOrigin + msToSec(entry.responseStart as number),
279280
});
280281
}
282+
283+
/**
284+
* Helper function to start child on transactions. This function will make sure that the transaction will
285+
* will use the start timestamp of the created child span if it is earlier than the transactions actual
286+
* start timestamp.
287+
*/
288+
export function _startChild(transaction: Transaction, { startTimestamp, ...ctx }: SpanContext): Span {
289+
if (startTimestamp && transaction.startTimestamp > startTimestamp) {
290+
transaction.startTimestamp = startTimestamp;
291+
}
292+
293+
return transaction.startChild({
294+
startTimestamp,
295+
...ctx,
296+
});
297+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { Span, Transaction } from '../../src';
2+
import { _startChild } from '../../src/browser/metrics';
3+
4+
describe('_startChild()', () => {
5+
it('creates a span with given properties', () => {
6+
const transaction = new Transaction({ name: 'test' });
7+
const span = _startChild(transaction, {
8+
description: 'evaluation',
9+
op: 'script',
10+
});
11+
12+
expect(span).toBeInstanceOf(Span);
13+
expect(span.description).toBe('evaluation');
14+
expect(span.op).toBe('script');
15+
});
16+
17+
it('adjusts the start timestamp if child span starts before transaction', () => {
18+
const transaction = new Transaction({ name: 'test', startTimestamp: 123 });
19+
const span = _startChild(transaction, {
20+
description: 'script.js',
21+
op: 'resource',
22+
startTimestamp: 100,
23+
});
24+
25+
expect(transaction.startTimestamp).toEqual(span.startTimestamp);
26+
expect(transaction.startTimestamp).toEqual(100);
27+
});
28+
29+
it('does not adjust start timestamp if child span starts after transaction', () => {
30+
const transaction = new Transaction({ name: 'test', startTimestamp: 123 });
31+
const span = _startChild(transaction, {
32+
description: 'script.js',
33+
op: 'resource',
34+
startTimestamp: 150,
35+
});
36+
37+
expect(transaction.startTimestamp).not.toEqual(span.startTimestamp);
38+
expect(transaction.startTimestamp).toEqual(123);
39+
});
40+
});

0 commit comments

Comments
 (0)