import { logger, getFunctionName } from '@sentry/utils'; import { DEBUG_BUILD } from '../common/debug-build.js'; import { onCLS } from './web-vitals/getCLS.js'; import { onFID } from './web-vitals/getFID.js'; import { onLCP } from './web-vitals/getLCP.js'; import { observe } from './web-vitals/lib/observe.js'; const handlers = {}; const instrumented = {}; let _previousCls; let _previousFid; let _previousLcp; /** * Add a callback that will be triggered when a CLS metric is available. * Returns a cleanup callback which can be called to remove the instrumentation handler. * * Pass `stopOnCallback = true` to stop listening for CLS when the cleanup callback is called. * This will lead to the CLS being finalized and frozen. */ function addClsInstrumentationHandler( callback, stopOnCallback = false, ) { return addMetricObserver('cls', callback, instrumentCls, _previousCls, stopOnCallback); } /** * Add a callback that will be triggered when a LCP metric is available. * Returns a cleanup callback which can be called to remove the instrumentation handler. * * Pass `stopOnCallback = true` to stop listening for LCP when the cleanup callback is called. * This will lead to the LCP being finalized and frozen. */ function addLcpInstrumentationHandler( callback, stopOnCallback = false, ) { return addMetricObserver('lcp', callback, instrumentLcp, _previousLcp, stopOnCallback); } /** * Add a callback that will be triggered when a FID metric is available. * Returns a cleanup callback which can be called to remove the instrumentation handler. */ function addFidInstrumentationHandler(callback) { return addMetricObserver('fid', callback, instrumentFid, _previousFid); } /** * Add a callback that will be triggered when a performance observer is triggered, * and receives the entries of the observer. * Returns a cleanup callback which can be called to remove the instrumentation handler. */ function addPerformanceInstrumentationHandler( type, callback, ) { addHandler(type, callback); if (!instrumented[type]) { instrumentPerformanceObserver(type); instrumented[type] = true; } return getCleanupCallback(type, callback); } /** Trigger all handlers of a given type. */ function triggerHandlers(type, data) { const typeHandlers = handlers[type]; if (!typeHandlers || !typeHandlers.length) { return; } for (const handler of typeHandlers) { try { handler(data); } catch (e) { DEBUG_BUILD && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, ); } } } function instrumentCls() { return onCLS(metric => { triggerHandlers('cls', { metric, }); _previousCls = metric; }); } function instrumentFid() { return onFID(metric => { triggerHandlers('fid', { metric, }); _previousFid = metric; }); } function instrumentLcp() { return onLCP(metric => { triggerHandlers('lcp', { metric, }); _previousLcp = metric; }); } function addMetricObserver( type, callback, instrumentFn, previousValue, stopOnCallback = false, ) { addHandler(type, callback); let stopListening; if (!instrumented[type]) { stopListening = instrumentFn(); instrumented[type] = true; } if (previousValue) { callback({ metric: previousValue }); } return getCleanupCallback(type, callback, stopOnCallback ? stopListening : undefined); } function instrumentPerformanceObserver(type) { const options = {}; // Special per-type options we want to use if (type === 'event') { options.durationThreshold = 0; } observe( type, entries => { triggerHandlers(type, { entries }); }, options, ); } function addHandler(type, handler) { handlers[type] = handlers[type] || []; (handlers[type] ).push(handler); } // Get a callback which can be called to remove the instrumentation handler function getCleanupCallback( type, callback, stopListening, ) { return () => { if (stopListening) { stopListening(); } const typeHandlers = handlers[type]; if (!typeHandlers) { return; } const index = typeHandlers.indexOf(callback); if (index !== -1) { typeHandlers.splice(index, 1); } }; } export { addClsInstrumentationHandler, addFidInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler }; //# sourceMappingURL=instrument.js.map