Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module.exports = [
path: 'packages/browser/build/npm/esm/index.js',
import: createImport('init', 'browserTracingIntegration', 'replayIntegration'),
gzip: true,
limit: '66 KB',
limit: '67 KB',
modifyWebpackConfig: function (config) {
const webpack = require('webpack');
config.plugins.push(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export const ReplayRecordingData = [
data: {
value: expect.any(Number),
size: expect.any(Number),
nodeId: 16,
nodeIds: [16],
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ export const ReplayRecordingData = [
value: expect.any(Number),
size: expect.any(Number),
rating: expect.any(String),
nodeIds: expect.any(Array),
layoutShift: expect.any(Array),
},
},
},
Expand Down
4 changes: 4 additions & 0 deletions packages/replay-internal/src/types/performance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ export interface WebVitalData {
* The recording id of the web vital nodes. -1 if not found
*/
nodeIds?: number[];
/**
* The layout shifts of a CLS metric
*/
layoutShift?: { value: number; sources?: number[] }[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would give this a more generic name, otherwise we have a 'WebVitalData' type that's generic with a layoutShift property that is very specific to a type of metric.

Maybe: attributions?: {value: number; nodeIds?: number}[]? or sources?: {value: number; nodeIds?: number}[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point!

}

/**
Expand Down
38 changes: 27 additions & 11 deletions packages/replay-internal/src/util/createPerformanceEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@ export interface Metric {
* The array may also be empty if the metric value was not based on any
* entries (e.g. a CLS value of 0 given no layout shifts).
*/
entries: PerformanceEntry[] | PerformanceEventTiming[];
entries: PerformanceEntry[] | PerformanceEventTiming[] | LayoutShift[];
}

interface LayoutShift extends PerformanceEntry {
value: number;
sources: LayoutShiftAttribution[];
hadRecentInput: boolean;
}

interface LayoutShiftAttribution {
Expand Down Expand Up @@ -191,18 +197,22 @@ export function getLargestContentfulPaint(metric: Metric): ReplayPerformanceEntr
* Add a CLS event to the replay based on a CLS metric.
*/
export function getCumulativeLayoutShift(metric: Metric): ReplayPerformanceEntry<WebVitalData> {
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);
const layoutShifts = [];
for (const entry of metric.entries) {
const layoutShift = entry as LayoutShift | undefined;
if (layoutShift) {
const sources = [];
for (const source of layoutShift.sources) {
const nodeId = record.mirror.getId(source.node);
if (nodeId) {
sources.push(nodeId);
}
}
layoutShifts.push({ value: layoutShift.value, sources: sources.length ? sources : undefined });
}

}
return getWebVital(metric, 'cumulative-layout-shift', nodes);
return getWebVital(metric, 'cumulative-layout-shift', undefined, layoutShifts);
}

/**
Expand All @@ -226,7 +236,12 @@ export function getInteractionToNextPaint(metric: Metric): ReplayPerformanceEntr
/**
* Add an web vital event to the replay based on the web vital metric.
*/
function getWebVital(metric: Metric, name: string, nodes: Node[] | undefined): ReplayPerformanceEntry<WebVitalData> {
function getWebVital(
metric: Metric,
name: string,
nodes: Node[] | undefined,
layoutShift?: { value: number; sources: number[] | undefined }[],
): ReplayPerformanceEntry<WebVitalData> {
const value = metric.value;
const rating = metric.rating;

Expand All @@ -242,6 +257,7 @@ function getWebVital(metric: Metric, name: string, nodes: Node[] | undefined): R
size: value,
rating,
nodeIds: nodes ? nodes.map(node => record.mirror.getId(node)) : undefined,
layoutShift,
},
};

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't make sense to have layoutShift in a LCP entry

});
});
});
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', nodeIds: [] },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: [], layoutShift: undefined },
});
});
});
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', nodeIds: undefined },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: [], layoutShift: 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', nodeIds: undefined },
data: { value: 5108.299, size: 5108.299, rating: 'good', nodeIds: [], layoutShift: undefined },
});
});
});
Expand Down