Skip to content

Commit 832726c

Browse files
committed
fix(tracing): Make sure performance spans change transaction start timestamp
1 parent c6c54a1 commit 832726c

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
@@ -3,6 +3,7 @@ import { getGlobalObject, logger } from '@sentry/utils';
33
import { Transaction } from '../transaction';
44

55
import { msToSec } from './utils';
6+
import { TransactionContext, SpanContext } from '@sentry/types';
67

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

@@ -162,7 +163,7 @@ export class MetricsInstrumentation {
162163
});
163164

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

198-
transaction.startChild({
199+
_startChild(transaction, {
199200
description: entry.name as string,
200201
endTimestamp: measureEndTimestamp,
201202
op: entry.entryType as string,
@@ -223,7 +224,7 @@ function addResourceSpans(
223224
const startTimestamp = timeOrigin + startTime;
224225
const endTimestamp = startTimestamp + duration;
225226

226-
transaction.startChild({
227+
_startChild(transaction, {
227228
description: `${entry.initiatorType} ${resourceName}`,
228229
endTimestamp,
229230
op: 'resource',
@@ -245,7 +246,7 @@ function addPerformanceNavigationTiming(
245246
if (!start || !end) {
246247
return;
247248
}
248-
transaction.startChild({
249+
_startChild(transaction, {
249250
description: event,
250251
endTimestamp: timeOrigin + msToSec(end),
251252
op: 'browser',
@@ -255,17 +256,33 @@ function addPerformanceNavigationTiming(
255256

256257
/** Create request and response related spans */
257258
function addRequest(transaction: Transaction, entry: Record<string, any>, timeOrigin: number): void {
258-
transaction.startChild({
259+
_startChild(transaction, {
259260
description: 'request',
260261
endTimestamp: timeOrigin + msToSec(entry.responseEnd as number),
261262
op: 'browser',
262263
startTimestamp: timeOrigin + msToSec(entry.requestStart as number),
263264
});
264265

265-
transaction.startChild({
266+
_startChild(transaction, {
266267
description: 'response',
267268
endTimestamp: timeOrigin + msToSec(entry.responseEnd as number),
268269
op: 'browser',
269270
startTimestamp: timeOrigin + msToSec(entry.responseStart as number),
270271
});
271272
}
273+
274+
/**
275+
* Helper function to start child on transactions. This function will make sure that the transaction will
276+
* will use the start timestamp of the created child span if it is earlier than the transactions actual
277+
* start timestamp.
278+
*/
279+
export function _startChild(transaction: Transaction, { startTimestamp, ...ctx }: SpanContext): Span {
280+
if (startTimestamp && transaction.startTimestamp > startTimestamp) {
281+
transaction.startTimestamp = startTimestamp;
282+
}
283+
284+
return transaction.startChild({
285+
startTimestamp,
286+
...ctx,
287+
});
288+
}
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)