From ea1c3bbe041507b454ad4cce97aa1e865af6a1ca Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Tue, 20 Apr 2021 17:15:04 -0400 Subject: [PATCH 1/3] feat(web-vitals): Capture information about the LCP element culprit --- packages/tracing/src/browser/metrics.ts | 25 +++++++++++++++++-- .../tracing/src/browser/web-vitals/getLCP.ts | 11 ++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index f69ae92a9641..9d17cbb1f807 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -1,14 +1,14 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Measurements, SpanContext } from '@sentry/types'; -import { browserPerformanceTimeOrigin, getGlobalObject, logger } from '@sentry/utils'; +import { browserPerformanceTimeOrigin, getGlobalObject, htmlTreeAsString, logger } from '@sentry/utils'; import { Span } from '../span'; import { Transaction } from '../transaction'; import { msToSec } from '../utils'; import { getCLS } from './web-vitals/getCLS'; import { getFID } from './web-vitals/getFID'; -import { getLCP } from './web-vitals/getLCP'; +import { getLCP, LargestContentfulPaint } from './web-vitals/getLCP'; import { getTTFB } from './web-vitals/getTTFB'; import { getFirstHidden } from './web-vitals/lib/getFirstHidden'; import { NavigatorDeviceMemory, NavigatorNetworkInformation } from './web-vitals/types'; @@ -20,6 +20,7 @@ export class MetricsInstrumentation { private _measurements: Measurements = {}; private _performanceCursor: number = 0; + private _lcpEntry: LargestContentfulPaint | undefined; public constructor() { if (global && global.performance) { @@ -170,6 +171,25 @@ export class MetricsInstrumentation { } transaction.setMeasurements(this._measurements); + + 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); + } + + if (this._lcpEntry.url) { + transaction.setTag('lcp.url', this._lcpEntry.url); + } + + transaction.setTag('lcp.size', this._lcpEntry.size); + } } } @@ -241,6 +261,7 @@ export class MetricsInstrumentation { logger.log('[Measurements] Adding LCP'); this._measurements['lcp'] = { value: metric.value }; this._measurements['mark.lcp'] = { value: timeOrigin + startTime }; + this._lcpEntry = entry as LargestContentfulPaint; }); } diff --git a/packages/tracing/src/browser/web-vitals/getLCP.ts b/packages/tracing/src/browser/web-vitals/getLCP.ts index e0fdd9c7cfde..e411397aafd2 100644 --- a/packages/tracing/src/browser/web-vitals/getLCP.ts +++ b/packages/tracing/src/browser/web-vitals/getLCP.ts @@ -22,6 +22,17 @@ import { onHidden } from './lib/onHidden'; import { whenInput } from './lib/whenInput'; import { ReportHandler } from './types'; +// https://wicg.github.io/largest-contentful-paint/#sec-largest-contentful-paint-interface +export interface LargestContentfulPaint extends PerformanceEntry { + renderTime: DOMHighResTimeStamp; + loadTime: DOMHighResTimeStamp; + size: number; + id: string; + url: string; + element?: Element; + toJSON(): Record; +} + export const getLCP = (onReport: ReportHandler, reportAllChanges = false): void => { const metric = initMetric('LCP'); const firstHidden = getFirstHidden(); From 5f42677aede1828ff1e5166fa4513c8ce10dc406 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Wed, 21 Apr 2021 12:45:13 -0400 Subject: [PATCH 2/3] update toJSON() type --- packages/tracing/src/browser/web-vitals/getLCP.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tracing/src/browser/web-vitals/getLCP.ts b/packages/tracing/src/browser/web-vitals/getLCP.ts index e411397aafd2..174aa1438eeb 100644 --- a/packages/tracing/src/browser/web-vitals/getLCP.ts +++ b/packages/tracing/src/browser/web-vitals/getLCP.ts @@ -30,7 +30,7 @@ export interface LargestContentfulPaint extends PerformanceEntry { id: string; url: string; element?: Element; - toJSON(): Record; + toJSON(): Record; } export const getLCP = (onReport: ReportHandler, reportAllChanges = false): void => { From c513a29e4c18e45d344aa7ee5332f706270a7bf9 Mon Sep 17 00:00:00 2001 From: Alberto Leal Date: Thu, 22 Apr 2021 11:28:09 -0400 Subject: [PATCH 3/3] trim url to the first 200 characters --- packages/tracing/src/browser/metrics.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/tracing/src/browser/metrics.ts b/packages/tracing/src/browser/metrics.ts index 9d17cbb1f807..1611c25472bb 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -185,7 +185,8 @@ export class MetricsInstrumentation { } if (this._lcpEntry.url) { - transaction.setTag('lcp.url', 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);