{"version":3,"file":"cls.js","sources":["../../../src/metrics/cls.ts"],"sourcesContent":["import type { Client, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getCurrentScope,\n htmlTreeAsString,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT,\n SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n timestampInSeconds,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { addClsInstrumentationHandler } from './instrument';\nimport type { WebVitalReportEvent } from './utils';\nimport { listenForWebVitalReportEvents, msToSec, startStandaloneWebVitalSpan, supportsWebVital } from './utils';\n\n/**\n * Starts tracking the Cumulative Layout Shift on the current page and collects the value once\n *\n * - the page visibility is hidden\n * - a navigation span is started (to stop CLS measurement for SPA soft navigations)\n *\n * Once either of these events triggers, the CLS value is sent as a standalone span and we stop\n * measuring CLS.\n */\nexport function trackClsAsStandaloneSpan(client: Client): void {\n let standaloneCLsValue = 0;\n let standaloneClsEntry: LayoutShift | undefined;\n\n if (!supportsWebVital('layout-shift')) {\n return;\n }\n\n const cleanupClsHandler = addClsInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n if (!entry) {\n return;\n }\n standaloneCLsValue = metric.value;\n standaloneClsEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, pageloadSpanId) => {\n _sendStandaloneClsSpan(standaloneCLsValue, standaloneClsEntry, pageloadSpanId, reportEvent);\n cleanupClsHandler();\n });\n}\n\n/**\n * Exported only for testing!\n */\nexport function _sendStandaloneClsSpan(\n clsValue: number,\n entry: LayoutShift | undefined,\n pageloadSpanId: string,\n reportEvent: WebVitalReportEvent,\n) {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const startTime = entry ? msToSec((browserPerformanceTimeOrigin() || 0) + entry.startTime) : timestampInSeconds();\n const routeName = getCurrentScope().getScopeData().transactionName;\n\n const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : 'Layout shift';\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.cls',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'ui.webvital.cls',\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: 0,\n // attach the pageload span id to the CLS span so that we can link them in the UI\n 'sentry.pageload.span_id': pageloadSpanId,\n // describes what triggered the web vital to be reported\n 'sentry.report_event': reportEvent,\n };\n\n // Add CLS sources as span attributes to help with debugging layout shifts\n // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift/sources\n if (entry?.sources) {\n entry.sources.forEach((source, index) => {\n attributes[`cls.source.${index + 1}`] = htmlTreeAsString(source.node);\n });\n }\n\n const span = startStandaloneWebVitalSpan({\n name,\n transaction: routeName,\n attributes,\n startTime,\n });\n\n if (span) {\n span.addEvent('cls', {\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT]: '',\n [SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE]: clsValue,\n });\n\n // LayoutShift performance entries always have a duration of 0, so we don't need to add `entry.duration` here\n // see: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceEntry/duration\n span.end(startTime);\n }\n}\n"],"names":[],"mappings":";;;;;AAkBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,wBAAwB,CAAC,MAAM,EAAgB;AAC/D,EAAE,IAAI,kBAAA,GAAqB,CAAC;AAC5B,EAAE,IAAI,kBAAkB;;AAExB,EAAE,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,EAAE;AACzC,IAAI;AACJ,EAAE;;AAEF,EAAE,MAAM,iBAAA,GAAoB,4BAA4B,CAAC,CAAC,EAAE,MAAA,EAAQ,KAAK;AACzE,IAAI,MAAM,KAAA,GAAQ,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAA,GAAS,CAAC,CAAA;AAC1D,IAAI,IAAI,CAAC,KAAK,EAAE;AAChB,MAAM;AACN,IAAI;AACJ,IAAI,kBAAA,GAAqB,MAAM,CAAC,KAAK;AACrC,IAAI,kBAAA,GAAqB,KAAK;AAC9B,EAAE,CAAC,EAAE,IAAI,CAAC;;AAEV,EAAE,6BAA6B,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,cAAc,KAAK;AACzE,IAAI,sBAAsB,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,cAAc,EAAE,WAAW,CAAC;AAC/F,IAAI,iBAAiB,EAAE;AACvB,EAAE,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACO,SAAS,sBAAsB;AACtC,EAAE,QAAQ;AACV,EAAE,KAAK;AACP,EAAE,cAAc;AAChB,EAAE,WAAW;AACb,EAAE;AACF,EAAE,WAAA,IAAe,KAAK,CAAC,GAAG,CAAC,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;;AAE5D,EAAE,MAAM,YAAY,KAAA,GAAQ,OAAO,CAAC,CAAC,4BAA4B,EAAC,IAAK,CAAC,IAAI,KAAK,CAAC,SAAS,CAAA,GAAI,kBAAkB,EAAE;AACnH,EAAE,MAAM,SAAA,GAAY,eAAe,EAAE,CAAC,YAAY,EAAE,CAAC,eAAe;;AAEpE,EAAE,MAAM,IAAA,GAAO,KAAA,GAAQ,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAA,GAAI,cAAc;;AAEhF,EAAE,MAAM,UAAU,GAAmB;AACrC,IAAI,CAAC,gCAAgC,GAAG,uBAAuB;AAC/D,IAAI,CAAC,4BAA4B,GAAG,iBAAiB;AACrD,IAAI,CAAC,iCAAiC,GAAG,CAAC;AAC1C;AACA,IAAI,yBAAyB,EAAE,cAAc;AAC7C;AACA,IAAI,qBAAqB,EAAE,WAAW;AACtC,GAAG;;AAEH;AACA;AACA,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AACtB,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,KAAK;AAC7C,MAAM,UAAU,CAAC,CAAC,WAAW,EAAE,KAAA,GAAQ,CAAC,CAAC,CAAA,CAAA,GAAA,gBAAA,CAAA,MAAA,CAAA,IAAA,CAAA;AACA,IAAA,CAAA,CAAA;AACA,EAAA;;AAEA,EAAA,MAAA,IAAA,GAAA,2BAAA,CAAA;AACA,IAAA,IAAA;AACA,IAAA,WAAA,EAAA,SAAA;AACA,IAAA,UAAA;AACA,IAAA,SAAA;AACA,GAAA,CAAA;;AAEA,EAAA,IAAA,IAAA,EAAA;AACA,IAAA,IAAA,CAAA,QAAA,CAAA,KAAA,EAAA;AACA,MAAA,CAAA,0CAAA,GAAA,EAAA;AACA,MAAA,CAAA,2CAAA,GAAA,QAAA;AACA,KAAA,CAAA;;AAEA;AACA;AACA,IAAA,IAAA,CAAA,GAAA,CAAA,SAAA,CAAA;AACA,EAAA;AACA;;;;"}