instrument.js.map 12 KB

1
  1. {"version":3,"file":"instrument.js","sources":["../../../src/browser/instrument.ts"],"sourcesContent":["import { getFunctionName, logger } from '@sentry/utils';\n\nimport { DEBUG_BUILD } from '../common/debug-build';\nimport { onCLS } from './web-vitals/getCLS';\nimport { onFID } from './web-vitals/getFID';\nimport { onLCP } from './web-vitals/getLCP';\nimport { observe } from './web-vitals/lib/observe';\n\ntype InstrumentHandlerTypePerformanceObserver = 'longtask' | 'event' | 'navigation' | 'paint' | 'resource';\n\ntype InstrumentHandlerTypeMetric = 'cls' | 'lcp' | 'fid';\n\n// We provide this here manually instead of relying on a global, as this is not available in non-browser environements\n// And we do not want to expose such types\ninterface PerformanceEntry {\n readonly duration: number;\n readonly entryType: string;\n readonly name: string;\n readonly startTime: number;\n toJSON(): Record<string, unknown>;\n}\n\ninterface Metric {\n /**\n * The name of the metric (in acronym form).\n */\n name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB';\n\n /**\n * The current value of the metric.\n */\n value: number;\n\n /**\n * The rating as to whether the metric value is within the \"good\",\n * \"needs improvement\", or \"poor\" thresholds of the metric.\n */\n rating: 'good' | 'needs-improvement' | 'poor';\n\n /**\n * The delta between the current value and the last-reported value.\n * On the first report, `delta` and `value` will always be the same.\n */\n delta: number;\n\n /**\n * A unique ID representing this particular metric instance. This ID can\n * be used by an analytics tool to dedupe multiple values sent for the same\n * metric instance, or to group multiple deltas together and calculate a\n * total. It can also be used to differentiate multiple different metric\n * instances sent from the same page, which can happen if the page is\n * restored from the back/forward cache (in that case new metrics object\n * get created).\n */\n id: string;\n\n /**\n * Any performance entries relevant to the metric value calculation.\n * The array may also be empty if the metric value was not based on any\n * entries (e.g. a CLS value of 0 given no layout shifts).\n */\n entries: PerformanceEntry[];\n\n /**\n * The type of navigation\n *\n * Navigation Timing API (or `undefined` if the browser doesn't\n * support that API). For pages that are restored from the bfcache, this\n * value will be 'back-forward-cache'.\n */\n navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender';\n}\n\ntype InstrumentHandlerType = InstrumentHandlerTypeMetric | InstrumentHandlerTypePerformanceObserver;\n\ntype StopListening = undefined | void | (() => void);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype InstrumentHandlerCallback = (data: any) => void;\n\ntype CleanupHandlerCallback = () => void;\n\nconst handlers: { [key in InstrumentHandlerType]?: InstrumentHandlerCallback[] } = {};\nconst instrumented: { [key in InstrumentHandlerType]?: boolean } = {};\n\nlet _previousCls: Metric | undefined;\nlet _previousFid: Metric | undefined;\nlet _previousLcp: Metric | undefined;\n\n/**\n * Add a callback that will be triggered when a CLS metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n *\n * Pass `stopOnCallback = true` to stop listening for CLS when the cleanup callback is called.\n * This will lead to the CLS being finalized and frozen.\n */\nexport function addClsInstrumentationHandler(\n callback: (data: { metric: Metric }) => void,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n return addMetricObserver('cls', callback, instrumentCls, _previousCls, stopOnCallback);\n}\n\n/**\n * Add a callback that will be triggered when a LCP metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n *\n * Pass `stopOnCallback = true` to stop listening for LCP when the cleanup callback is called.\n * This will lead to the LCP being finalized and frozen.\n */\nexport function addLcpInstrumentationHandler(\n callback: (data: { metric: Metric }) => void,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n return addMetricObserver('lcp', callback, instrumentLcp, _previousLcp, stopOnCallback);\n}\n\n/**\n * Add a callback that will be triggered when a FID metric is available.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n */\nexport function addFidInstrumentationHandler(callback: (data: { metric: Metric }) => void): CleanupHandlerCallback {\n return addMetricObserver('fid', callback, instrumentFid, _previousFid);\n}\n\nexport function addPerformanceInstrumentationHandler(\n type: 'event',\n callback: (data: { entries: (PerformanceEntry & { target?: unknown | null })[] }) => void,\n): CleanupHandlerCallback;\nexport function addPerformanceInstrumentationHandler(\n type: InstrumentHandlerTypePerformanceObserver,\n callback: (data: { entries: PerformanceEntry[] }) => void,\n): CleanupHandlerCallback;\n\n/**\n * Add a callback that will be triggered when a performance observer is triggered,\n * and receives the entries of the observer.\n * Returns a cleanup callback which can be called to remove the instrumentation handler.\n */\nexport function addPerformanceInstrumentationHandler(\n type: InstrumentHandlerTypePerformanceObserver,\n callback: (data: { entries: PerformanceEntry[] }) => void,\n): CleanupHandlerCallback {\n addHandler(type, callback);\n\n if (!instrumented[type]) {\n instrumentPerformanceObserver(type);\n instrumented[type] = true;\n }\n\n return getCleanupCallback(type, callback);\n}\n\n/** Trigger all handlers of a given type. */\nfunction triggerHandlers(type: InstrumentHandlerType, data: unknown): void {\n const typeHandlers = handlers[type];\n\n if (!typeHandlers || !typeHandlers.length) {\n return;\n }\n\n for (const handler of typeHandlers) {\n try {\n handler(data);\n } catch (e) {\n DEBUG_BUILD &&\n logger.error(\n `Error while triggering instrumentation handler.\\nType: ${type}\\nName: ${getFunctionName(handler)}\\nError:`,\n e,\n );\n }\n }\n}\n\nfunction instrumentCls(): StopListening {\n return onCLS(metric => {\n triggerHandlers('cls', {\n metric,\n });\n _previousCls = metric;\n });\n}\n\nfunction instrumentFid(): void {\n return onFID(metric => {\n triggerHandlers('fid', {\n metric,\n });\n _previousFid = metric;\n });\n}\n\nfunction instrumentLcp(): StopListening {\n return onLCP(metric => {\n triggerHandlers('lcp', {\n metric,\n });\n _previousLcp = metric;\n });\n}\n\nfunction addMetricObserver(\n type: InstrumentHandlerTypeMetric,\n callback: InstrumentHandlerCallback,\n instrumentFn: () => StopListening,\n previousValue: Metric | undefined,\n stopOnCallback = false,\n): CleanupHandlerCallback {\n addHandler(type, callback);\n\n let stopListening: StopListening | undefined;\n\n if (!instrumented[type]) {\n stopListening = instrumentFn();\n instrumented[type] = true;\n }\n\n if (previousValue) {\n callback({ metric: previousValue });\n }\n\n return getCleanupCallback(type, callback, stopOnCallback ? stopListening : undefined);\n}\n\nfunction instrumentPerformanceObserver(type: InstrumentHandlerTypePerformanceObserver): void {\n const options: PerformanceObserverInit = {};\n\n // Special per-type options we want to use\n if (type === 'event') {\n options.durationThreshold = 0;\n }\n\n observe(\n type,\n entries => {\n triggerHandlers(type, { entries });\n },\n options,\n );\n}\n\nfunction addHandler(type: InstrumentHandlerType, handler: InstrumentHandlerCallback): void {\n handlers[type] = handlers[type] || [];\n (handlers[type] as InstrumentHandlerCallback[]).push(handler);\n}\n\n// Get a callback which can be called to remove the instrumentation handler\nfunction getCleanupCallback(\n type: InstrumentHandlerType,\n callback: InstrumentHandlerCallback,\n stopListening: StopListening,\n): CleanupHandlerCallback {\n return () => {\n if (stopListening) {\n stopListening();\n }\n\n const typeHandlers = handlers[type];\n\n if (!typeHandlers) {\n return;\n }\n\n const index = typeHandlers.indexOf(callback);\n if (index !== -1) {\n typeHandlers.splice(index, 1);\n }\n };\n}\n"],"names":[],"mappings":"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"}