11import type { SpanAttributes } from '@sentry/core' ;
22import {
33 browserPerformanceTimeOrigin ,
4- getActiveSpan ,
5- getClient ,
64 getCurrentScope ,
7- getRootSpan ,
85 htmlTreeAsString ,
96 logger ,
107 SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME ,
118 SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT ,
129 SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE ,
1310 SEMANTIC_ATTRIBUTE_SENTRY_OP ,
1411 SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN ,
15- spanToJSON ,
1612} from '@sentry/core' ;
1713import { DEBUG_BUILD } from '../debug-build' ;
1814import { addClsInstrumentationHandler } from './instrument' ;
1915import type { WebVitalReportEvent } from './utils' ;
20- import { msToSec , startStandaloneWebVitalSpan , supportsWebVital } from './utils' ;
21- import { onHidden } from './web-vitals/lib/onHidden' ;
22- import { runOnce } from './web-vitals/lib/runOnce' ;
16+ import { listenForWebVitalReportEvents , msToSec , startStandaloneWebVitalSpan , supportsWebVital } from './utils' ;
2317
2418/**
2519 * Starts tracking the Cumulative Layout Shift on the current page and collects the value once
@@ -33,21 +27,11 @@ import { runOnce } from './web-vitals/lib/runOnce';
3327export function trackClsAsStandaloneSpan ( ) : void {
3428 let standaloneCLsValue = 0 ;
3529 let standaloneClsEntry : LayoutShift | undefined ;
36- let pageloadSpanId : string | undefined ;
3730
3831 if ( ! supportsWebVital ( 'layout-shift' ) ) {
3932 return ;
4033 }
4134
42- function _collectClsOnce ( reportEvent : WebVitalReportEvent ) {
43- runOnce ( ( ) => {
44- if ( pageloadSpanId ) {
45- sendStandaloneClsSpan ( standaloneCLsValue , standaloneClsEntry , pageloadSpanId , reportEvent ) ;
46- }
47- cleanupClsHandler ( ) ;
48- } ) ;
49- }
50-
5135 const cleanupClsHandler = addClsInstrumentationHandler ( ( { metric } ) => {
5236 const entry = metric . entries [ metric . entries . length - 1 ] as LayoutShift | undefined ;
5337 if ( ! entry ) {
@@ -57,37 +41,10 @@ export function trackClsAsStandaloneSpan(): void {
5741 standaloneClsEntry = entry ;
5842 } , true ) ;
5943
60- onHidden ( ( ) => {
61- _collectClsOnce ( 'pagehide' ) ;
44+ listenForWebVitalReportEvents ( ( reportEvent , pageloadSpanId ) => {
45+ sendStandaloneClsSpan ( standaloneCLsValue , standaloneClsEntry , pageloadSpanId , reportEvent ) ;
46+ cleanupClsHandler ( ) ;
6247 } ) ;
63-
64- // Since the call chain of this function is synchronous and evaluates before the SDK client is created,
65- // we need to wait with subscribing to a client hook until the client is created. Therefore, we defer
66- // to the next tick after the SDK setup.
67- setTimeout ( ( ) => {
68- const client = getClient ( ) ;
69-
70- if ( ! client ) {
71- return ;
72- }
73-
74- const unsubscribeStartNavigation = client . on ( 'beforeStartNavigationSpan' , ( _ , options ) => {
75- // we only want to collect CLS if we actually navigate. Redirects should be ignored.
76- if ( ! options ?. isRedirect ) {
77- _collectClsOnce ( 'navigation' ) ;
78- unsubscribeStartNavigation ?.( ) ;
79- }
80- } ) ;
81-
82- const activeSpan = getActiveSpan ( ) ;
83- if ( activeSpan ) {
84- const rootSpan = getRootSpan ( activeSpan ) ;
85- const spanJSON = spanToJSON ( rootSpan ) ;
86- if ( spanJSON . op === 'pageload' ) {
87- pageloadSpanId = rootSpan . spanContext ( ) . spanId ;
88- }
89- }
90- } , 0 ) ;
9148}
9249
9350function sendStandaloneClsSpan (
0 commit comments