From 741a3f16e433adbb3bdcd2fdedd963a4482507b9 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Tue, 22 Jun 2021 13:15:30 -0700 Subject: [PATCH 1/3] Metrics: Tag CLS elements This will help people dig into pages with bad layout shifts Co-authored-by: Alberto Leal --- packages/tracing/src/browser/metrics.ts | 11 ++++++++++- packages/tracing/src/browser/web-vitals/getCLS.ts | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 73dec5cee29a..0f137acc8b3a 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -6,7 +6,7 @@ import { browserPerformanceTimeOrigin, getGlobalObject, htmlTreeAsString, isNode import { Span } from '../span'; import { Transaction } from '../transaction'; import { msToSec } from '../utils'; -import { getCLS } from './web-vitals/getCLS'; +import { getCLS, LayoutShift } from './web-vitals/getCLS'; import { getFID } from './web-vitals/getFID'; import { getLCP, LargestContentfulPaint } from './web-vitals/getLCP'; import { getFirstHidden } from './web-vitals/lib/getFirstHidden'; @@ -20,6 +20,7 @@ export class MetricsInstrumentation { private _performanceCursor: number = 0; private _lcpEntry: LargestContentfulPaint | undefined; + private _clsEntry: LayoutShift | undefined; public constructor() { if (!isNodeEnv() && global?.performance) { @@ -207,6 +208,13 @@ export class MetricsInstrumentation { transaction.setTag('lcp.size', this._lcpEntry.size); } + + if (this._clsEntry) { + logger.log('[Measurements] Adding CLS Data'); + transaction.setData('measurements.cls', { + sources: this._clsEntry.sources.map(source => htmlTreeAsString(source.node)), + }); + } } } @@ -221,6 +229,7 @@ export class MetricsInstrumentation { logger.log('[Measurements] Adding CLS'); this._measurements['cls'] = { value: metric.value }; + this._clsEntry = entry as LayoutShift; }); } diff --git a/packages/tracing/src/browser/web-vitals/getCLS.ts b/packages/tracing/src/browser/web-vitals/getCLS.ts index 530951834e47..71c6f06cec85 100644 --- a/packages/tracing/src/browser/web-vitals/getCLS.ts +++ b/packages/tracing/src/browser/web-vitals/getCLS.ts @@ -21,9 +21,17 @@ import { onHidden } from './lib/onHidden'; import { ReportHandler } from './types'; // https://wicg.github.io/layout-instability/#sec-layout-shift -interface LayoutShift extends PerformanceEntry { +export interface LayoutShift extends PerformanceEntry { value: number; hadRecentInput: boolean; + sources: Array; + toJSON(): Record; +} + +export interface LayoutShiftAttribution { + node?: Node; + previousRect: DOMRectReadOnly; + currentRect: DOMRectReadOnly; } export const getCLS = (onReport: ReportHandler, reportAllChanges = false): void => { From 20979a3f04e00a56fa30d7f91f73c9fd54577988 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Wed, 23 Jun 2021 11:23:12 -0700 Subject: [PATCH 2/3] CLS: Add as a tag See: https://github.com/getsentry/sentry-javascript/pull/3734\#discussion_r657311310 --- packages/tracing/src/browser/metrics.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 0f137acc8b3a..64074ca25a84 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -211,9 +211,9 @@ export class MetricsInstrumentation { if (this._clsEntry) { logger.log('[Measurements] Adding CLS Data'); - transaction.setData('measurements.cls', { - sources: this._clsEntry.sources.map(source => htmlTreeAsString(source.node)), - }); + this._clsEntry.sources.map((source, index) => + transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), + ); } } } From 6e31663ab54202d432d419d186da736014e8ab86 Mon Sep 17 00:00:00 2001 From: Jarred Stelfox Date: Wed, 23 Jun 2021 15:06:27 -0700 Subject: [PATCH 3/3] Refactor: Reduce complexity --- packages/tracing/src/browser/metrics.ts | 46 ++++++++++++++----------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 64074ca25a84..118de73e8510 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -188,33 +188,37 @@ export class MetricsInstrumentation { } transaction.setMeasurements(this._measurements); + this._tagMetricInfo(transaction); + } + } - if (this._lcpEntry) { - logger.log('[Measurements] Adding LCP Data'); - // Capture Properties of the LCP element that contributes to the LCP. - - if (this._lcpEntry.element) { - transaction.setTag('lcp.element', htmlTreeAsString(this._lcpEntry.element)); - } - - if (this._lcpEntry.id) { - transaction.setTag('lcp.id', this._lcpEntry.id); - } + /** Add LCP / CLS data to transaction to allow debugging */ + private _tagMetricInfo(transaction: Transaction): void { + if (this._lcpEntry) { + logger.log('[Measurements] Adding LCP Data'); + // Capture Properties of the LCP element that contributes to the LCP. - if (this._lcpEntry.url) { - // Trim URL to the first 200 characters. - transaction.setTag('lcp.url', this._lcpEntry.url.trim().slice(0, 200)); - } + if (this._lcpEntry.element) { + transaction.setTag('lcp.element', htmlTreeAsString(this._lcpEntry.element)); + } - transaction.setTag('lcp.size', this._lcpEntry.size); + if (this._lcpEntry.id) { + transaction.setTag('lcp.id', this._lcpEntry.id); } - if (this._clsEntry) { - logger.log('[Measurements] Adding CLS Data'); - this._clsEntry.sources.map((source, index) => - transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), - ); + if (this._lcpEntry.url) { + // Trim URL to the first 200 characters. + transaction.setTag('lcp.url', this._lcpEntry.url.trim().slice(0, 200)); } + + transaction.setTag('lcp.size', this._lcpEntry.size); + } + + if (this._clsEntry) { + logger.log('[Measurements] Adding CLS Data'); + this._clsEntry.sources.map((source, index) => + transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), + ); } }