Skip to content

Commit

Permalink
ref(replay): Update CLS web vitals to align with browserTracing (#13058)
Browse files Browse the repository at this point in the history
NodeId has been replaced with nodeIds which now accepts several nodes
since CLS scores are cumulative. Also updated CLS metrics to match CLS
captured from browserTracing.

Relates to getsentry/sentry#69881
  • Loading branch information
c298lee committed Jul 30, 2024
1 parent 51f85e6 commit 67a067a
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ module.exports = [
name: 'CDN Bundle (incl. Tracing, Replay)',
path: createCDNPath('bundle.tracing.replay.min.js'),
gzip: true,
limit: '72 KB',
limit: '73 KB',
},
{
name: 'CDN Bundle (incl. Tracing, Replay, Feedback)',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const expectedLCPPerformanceSpan = {
endTimestamp: expect.any(Number),
data: {
value: expect.any(Number),
nodeId: expect.any(Number),
nodeIds: expect.any(Array),
rating: expect.any(String),
size: expect.any(Number),
},
Expand All @@ -140,6 +140,7 @@ export const expectedCLSPerformanceSpan = {
endTimestamp: expect.any(Number),
data: {
value: expect.any(Number),
nodeIds: expect.any(Array),
rating: expect.any(String),
size: expect.any(Number),
},
Expand All @@ -154,7 +155,7 @@ export const expectedFIDPerformanceSpan = {
value: expect.any(Number),
rating: expect.any(String),
size: expect.any(Number),
nodeId: expect.any(Number),
nodeIds: expect.any(Array),
},
};

Expand All @@ -167,7 +168,7 @@ export const expectedINPPerformanceSpan = {
value: expect.any(Number),
rating: expect.any(String),
size: expect.any(Number),
nodeId: expect.any(Number),
nodeIds: expect.any(Array),
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ export const ReplayRecordingData = [
value: expect.any(Number),
size: expect.any(Number),
rating: expect.any(String),
nodeId: 16,
nodeIds: [16],
},
},
},
Expand All @@ -239,6 +239,7 @@ export const ReplayRecordingData = [
value: expect.any(Number),
size: expect.any(Number),
rating: expect.any(String),
nodeIds: expect.any(Array),
},
},
},
Expand All @@ -257,7 +258,7 @@ export const ReplayRecordingData = [
value: expect.any(Number),
size: expect.any(Number),
rating: expect.any(String),
nodeId: 10,
nodeIds: [10],
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions packages/replay-internal/src/types/performance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,9 @@ export interface WebVitalData {
*/
rating: 'good' | 'needs-improvement' | 'poor';
/**
* The recording id of the LCP node. -1 if not found
* The recording id of the web vital nodes. -1 if not found
*/
nodeId?: number;
nodeIds?: number[];
}

/**
Expand Down
34 changes: 17 additions & 17 deletions packages/replay-internal/src/util/createPerformanceEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,30 +183,34 @@ function createResourceEntry(
*/
export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntry<WebVitalData> {
const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { element?: Node }) | undefined;
const node = lastEntry ? lastEntry.element : undefined;
const node = lastEntry && lastEntry.element ? [lastEntry.element] : undefined;
return getWebVital(metric, 'largest-contentful-paint', node);
}

/**
* Add a CLS event to the replay based on a CLS metric.
*/
export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry<WebVitalData> {
// get first node that shifts
const firstEntry = metric.entries[0] as (PerformanceEntry & { sources?: LayoutShiftAttribution[] }) | undefined;
const node = firstEntry
? firstEntry.sources && firstEntry.sources[0]
? firstEntry.sources[0].node
: undefined
: undefined;
return getWebVital(metric, 'cumulative-layout-shift', node);
const lastEntry = metric.entries[metric.entries.length - 1] as
| (PerformanceEntry & { sources?: LayoutShiftAttribution[] })
| undefined;
const nodes: Node[] = [];
if (lastEntry && lastEntry.sources) {
for (const source of lastEntry.sources) {
if (source.node) {
nodes.push(source.node);
}
}
}
return getWebVital(metric, 'cumulative-layout-shift', nodes);
}

/**
* Add a FID event to the replay based on a FID metric.
*/
export function getFirstInputDelay(metric: Metric): ReplayPerformanceEntry<WebVitalData> {
const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Node }) | undefined;
const node = lastEntry ? lastEntry.target : undefined;
const node = lastEntry && lastEntry.target ? [lastEntry.target] : undefined;
return getWebVital(metric, 'first-input-delay', node);
}

Expand All @@ -215,18 +219,14 @@ export function getFirstInputDelay(metric: Metric): ReplayPerformanceEntry<WebVi
*/
export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntry<WebVitalData> {
const lastEntry = metric.entries[metric.entries.length - 1] as (PerformanceEntry & { target?: Node }) | undefined;
const node = lastEntry ? lastEntry.target : undefined;
const node = lastEntry && lastEntry.target ? [lastEntry.target] : undefined;
return getWebVital(metric, 'interaction-to-next-paint', node);
}

/**
* Add an web vital event to the replay based on the web vital metric.
*/
export function getWebVital(
metric: Metric,
name: string,
node: Node | undefined,
): ReplayPerformanceEntry<WebVitalData> {
function getWebVital(metric: Metric, name: string, nodes: Node[] | undefined): ReplayPerformanceEntry<WebVitalData> {
const value = metric.value;
const rating = metric.rating;

Expand All @@ -241,7 +241,7 @@ export function getWebVital(
value,
size: value,
rating,
nodeId: node ? record.mirror.getId(node) : undefined,
nodeIds: nodes ? nodes.map(node => record.mirror.getId(node)) : undefined,
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ describe('Unit | util | createPerformanceEntries', () => {
name: 'largest-contentful-paint',
start: 1672531205.108299,
end: 1672531205.108299,
data: { value: 5108.299, rating: 'good', size: 5108.299, nodeId: undefined },
data: { value: 5108.299, rating: 'good', size: 5108.299, nodeIds: undefined },
});
});
});

describe('getCumulativeLayoutShift', () => {
it('works with an CLS metric', async () => {
it('works with a CLS metric', async () => {
const metric = {
value: 5108.299,
rating: 'good' as const,
Expand All @@ -103,7 +103,7 @@ describe('Unit | util | createPerformanceEntries', () => {
name: 'cumulative-layout-shift',
start: 1672531205.108299,
end: 1672531205.108299,
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: [] },
});
});
});
Expand All @@ -123,7 +123,7 @@ describe('Unit | util | createPerformanceEntries', () => {
name: 'first-input-delay',
start: 1672531205.108299,
end: 1672531205.108299,
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: undefined },
});
});
});
Expand All @@ -143,7 +143,7 @@ describe('Unit | util | createPerformanceEntries', () => {
name: 'interaction-to-next-paint',
start: 1672531205.108299,
end: 1672531205.108299,
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeId: undefined },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: undefined },
});
});
});
Expand Down

0 comments on commit 67a067a

Please sign in to comment.