UNPKG

datadog-ux-utils

Version:

Datadog RUM focused UX & performance toolkit: API guards (retry, breaker, rate), React telemetry (error boundary, profiler, Suspense), web vitals & resource observers, offline queues.

1 lines 29.1 kB
{"version":3,"file":"webVitals-CZZDMzzU.cjs","sources":["../src/perf/idle.ts","../src/perf/layoutShifts.ts","../src/perf/longTasks.ts","../src/perf/memory.ts","../src/perf/memoryPeak.ts","../src/perf/resources.ts","../src/perf/webVitals.ts"],"sourcesContent":["/**\n * @file idle.ts\n * @description Tracks user idle/active state in the browser. Useful for:\n * - Detecting long periods of inactivity to pause expensive operations.\n * - Reporting idle sessions to Datadog for UX metrics.\n * - Automatically logging out users after inactivity.\n *\n * This uses `mousemove`, `keydown`, and visibility changes to detect activity.\n */\n\nimport { safeAddAction } from \"../datadog.ts\";\n\n/**\n * Configuration options for idle tracking.\n */\nexport interface IdleTrackerOptions {\n /**\n * Time in milliseconds before the user is considered idle.\n * @default 60000 (1 minute)\n */\n idleAfterMs?: number;\n\n /**\n * Whether to automatically send an action to Datadog when idle/active state changes.\n * @default true\n */\n reportToDatadog?: boolean;\n\n /**\n * Optional callback fired when the idle state changes.\n * @param isIdle - `true` if the user is now idle, `false` if active.\n */\n onChange?: (isIdle: boolean) => void;\n}\n\nlet _idleTimeout: ReturnType<typeof setTimeout> | null = null;\nlet _isIdle = false;\nlet _opts: Required<IdleTrackerOptions>;\n\n/**\n * Starts tracking user idle state.\n *\n * @param opts - Idle tracking configuration.\n * @returns A function to stop idle tracking.\n *\n * @example\n * ```ts\n * import { startIdleTracker } from \"datadog-ux-utils/idle\";\n *\n * const stop = startIdleTracker({\n * idleAfterMs: 2 * 60 * 1000, // 2 minutes\n * onChange: (isIdle) => {\n * console.log(isIdle ? \"User is idle\" : \"User is active\");\n * },\n * });\n *\n * // Later, if you want to stop tracking:\n * stop();\n * ```\n */\nexport function startIdleTracker(opts: IdleTrackerOptions = {}): () => void {\n _opts = {\n idleAfterMs: opts.idleAfterMs ?? 60_000,\n reportToDatadog: opts.reportToDatadog ?? true,\n onChange: opts.onChange ?? (() => {}),\n };\n\n const resetIdleTimer = () => {\n if (_isIdle) {\n _isIdle = false;\n _opts.onChange(false);\n if (_opts.reportToDatadog) {\n safeAddAction(\"user_active\");\n }\n }\n\n if (_idleTimeout) {\n clearTimeout(_idleTimeout);\n }\n\n _idleTimeout = setTimeout(() => {\n _isIdle = true;\n _opts.onChange(true);\n if (_opts.reportToDatadog) {\n safeAddAction(\"user_idle\", { idleAfterMs: _opts.idleAfterMs });\n }\n }, _opts.idleAfterMs);\n };\n\n const activityEvents = [\"mousemove\", \"keydown\", \"mousedown\", \"touchstart\"];\n activityEvents.forEach((event) =>\n window.addEventListener(event, resetIdleTimer, { passive: true })\n );\n document.addEventListener(\"visibilitychange\", () => {\n if (!document.hidden) {\n resetIdleTimer();\n }\n });\n\n // Kick off initial timer\n resetIdleTimer();\n\n return () => {\n if (_idleTimeout) {\n clearTimeout(_idleTimeout);\n _idleTimeout = null;\n }\n activityEvents.forEach((event) =>\n window.removeEventListener(event, resetIdleTimer)\n );\n document.removeEventListener(\"visibilitychange\", resetIdleTimer);\n };\n}\n\n/**\n * Returns whether the user is currently considered idle.\n *\n * @example\n * ```ts\n * import { isUserIdle } from \"datadog-ux-utils/idle\";\n * console.log(\"Is idle?\", isUserIdle());\n * ```\n */\nexport function isUserIdle(): boolean {\n return _isIdle;\n}\n","/**\n * @file layoutShifts.ts\n * @description Monitors layout shift events using the PerformanceObserver API to\n * calculate and report Cumulative Layout Shift (CLS) scores.\n * CLS measures unexpected layout shifts that occur during a page's lifecycle,\n * which impact user experience.\n */\n\nimport { safeAddAction } from \"../datadog.ts\";\nimport { LayoutShiftOptions } from \"../types/types.ts\";\n\nlet _clsValue = 0;\nlet _observer: PerformanceObserver | null = null;\nlet _opts: Required<LayoutShiftOptions>;\n\n/**\n * Starts tracking Cumulative Layout Shift (CLS) for the current page.\n *\n * @param opts - Configuration for tracking layout shifts.\n * @returns A function to stop tracking CLS.\n *\n * @example\n * ```ts\n * import { startLayoutShiftTracking } from \"datadog-ux-utils/layoutShifts\";\n *\n * const stopTracking = startLayoutShiftTracking({\n * onChange: (cls, entry) => {\n * console.log(\"CLS updated:\", cls, entry);\n * }\n * });\n *\n * // Stop tracking later:\n * stopTracking();\n * ```\n */\nexport function startLayoutShiftTracking(\n opts: LayoutShiftOptions = {}\n): () => void {\n if (\n typeof window === \"undefined\" ||\n typeof PerformanceObserver === \"undefined\"\n ) {\n return () => {};\n }\n\n _opts = {\n reportToDatadog: opts.reportToDatadog ?? true,\n onChange: opts.onChange ?? (() => {}),\n };\n\n try {\n _observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as LayoutShift[]) {\n // Ignore shifts triggered by user input\n if (!entry.hadRecentInput) {\n _clsValue += entry.value;\n _opts.onChange(_clsValue, entry);\n\n if (_opts.reportToDatadog) {\n safeAddAction(\"layout_shift\", {\n clsValue: _clsValue,\n value: entry.value,\n sources: entry.sources?.map((s) => s.node?.nodeName),\n });\n }\n }\n }\n });\n\n _observer.observe({ type: \"layout-shift\", buffered: true });\n } catch {\n // swallow: CLS tracking not supported in this browser\n }\n\n return () => {\n if (_observer) {\n _observer.disconnect();\n _observer = null;\n }\n };\n}\n\n/**\n * Returns the current cumulative layout shift score.\n *\n * @example\n * ```ts\n * import { getCLSValue } from \"datadog-ux-utils/layoutShifts\";\n * console.log(\"Current CLS:\", getCLSValue());\n * ```\n */\nexport function getCLSValue(): number {\n return _clsValue;\n}\n","/**\n * @file longTasks.ts\n * @description Observes long tasks in the browser main thread and reports them to Datadog RUM.\n */\nimport { datadogRum } from \"@datadog/browser-rum\";\nimport { getUxConfig } from \"../config.ts\";\n\nlet obs: PerformanceObserver | null = null;\n\n/**\n * Starts observing long tasks and reports them to Datadog RUM if enabled.\n */\nexport const startLongTaskObserver = () => {\n const cfg = getUxConfig();\n if (!cfg.captureLongTasks || obs || !(\"PerformanceObserver\" in window))\n return;\n\n obs = new PerformanceObserver((list) => {\n for (const entry of list.getEntries() as PerformanceEntryList) {\n // report only the very long ones to keep noise low\n if ((entry as any).duration >= 100) {\n datadogRum.addAction(\"long_task\", {\n name: entry.name,\n duration_ms: Math.round((entry as any).duration),\n startTime: Math.round(entry.startTime),\n });\n }\n }\n });\n try {\n obs.observe({ type: \"longtask\", buffered: true as any });\n } catch {\n /* older browsers */\n }\n};\n/**\n * Stops the long task observer.\n */\nexport const stopLongTaskObserver = () => {\n obs?.disconnect();\n obs = null;\n};\n","/**\n * @file memory.ts\n * @description Utility to track JavaScript heap memory usage via the\n * `performance.memory` API (Chrome-only), with optional Datadog reporting.\n */\n\nimport { safeAddAction } from \"../datadog.ts\";\nimport { MemoryMetrics, MemoryTrackingOptions } from \"../types/types.ts\";\n\nlet _timer: number | null = null;\nlet _opts: Required<MemoryTrackingOptions>;\n\n/**\n * Reads the current JS heap memory metrics.\n * Works only in browsers that implement the non-standard `performance.memory` API.\n *\n * @returns Memory metrics, or `null` if unsupported.\n *\n * @example\n * ```ts\n * import { getMemoryUsage } from \"datadog-ux-utils/memory\";\n * const metrics = getMemoryUsage();\n * if (metrics) {\n * console.log(\"Used heap MB:\", metrics.usedJSHeapSize / 1024 / 1024);\n * }\n * ```\n */\nexport function getMemoryUsage(): MemoryMetrics | null {\n const anyPerf = performance as any;\n if (anyPerf && anyPerf.memory) {\n const { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit } = anyPerf.memory;\n return { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit };\n }\n return null;\n}\n\n/**\n * Starts polling for memory usage and optionally reports metrics to Datadog.\n *\n * @param opts - Tracking configuration.\n * @returns Function to stop tracking.\n *\n * @example\n * ```ts\n * import { startMemoryTracking } from \"datadog-ux-utils/memory\";\n *\n * const stop = startMemoryTracking({\n * intervalMs: 5000,\n * onChange: (metrics) => {\n * console.log(\"Heap usage (MB):\", metrics.usedJSHeapSize / 1024 / 1024);\n * }\n * });\n *\n * // Stop tracking later:\n * stop();\n * ```\n */\nexport function startMemoryTracking(\n opts: MemoryTrackingOptions = {}\n): () => void {\n if (typeof window === \"undefined\") {\n return () => {};\n }\n\n _opts = {\n intervalMs: opts.intervalMs ?? 10000,\n reportToDatadog: opts.reportToDatadog ?? true,\n onChange: opts.onChange ?? (() => {}),\n };\n\n if (_timer !== null) {\n stopMemoryTracking();\n }\n\n const poll = () => {\n const metrics = getMemoryUsage();\n if (metrics) {\n _opts.onChange(metrics);\n\n if (_opts.reportToDatadog) {\n safeAddAction(\"memory_usage\", {\n usedJSHeapSize: metrics.usedJSHeapSize,\n totalJSHeapSize: metrics.totalJSHeapSize,\n jsHeapSizeLimit: metrics.jsHeapSizeLimit,\n });\n }\n }\n };\n\n poll(); // immediate first run\n _timer = window.setInterval(poll, _opts.intervalMs);\n\n return stopMemoryTracking;\n}\n\n/**\n * Stops memory usage tracking.\n *\n * @example\n * ```ts\n * import { stopMemoryTracking } from \"datadog-ux-utils/memory\";\n * stopMemoryTracking();\n * ```\n */\nexport function stopMemoryTracking(): void {\n if (_timer !== null) {\n clearInterval(_timer);\n _timer = null;\n }\n}\n","/**\n * @file memoryPeak.ts\n * @description Lightweight tracker that records only the peak JS heap usage\n * (via `performance.memory`, when available) and reports it rarely:\n * - by default on page hide/unload (visibility change), and\n * - optionally on a low-frequency interval.\n *\n * Use this when you want a “how big did it get?” signal with minimal volume\n * and almost no runtime cost.\n */\n\nimport { safeAddAction } from \"../datadog.ts\";\nimport {\n MemoryPeak,\n MemoryPeakReportMode,\n MemoryPeakOptions,\n} from \"../types/types.ts\";\n\n/* ----------------------- state & defaults ----------------------- */\n\nconst DEFAULTS: Required<MemoryPeakOptions> = {\n mode: \"onHide\",\n intervalMs: 60_000,\n reportToDatadog: true,\n actionName: \"memory_peak\",\n onNewPeak: () => {},\n};\n\nlet peak: MemoryPeak | null = null;\nlet installed = false;\nlet opts: Required<MemoryPeakOptions> = DEFAULTS;\nlet intervalId: number | null = null;\nlet lastReportedAt = 0;\n\n/* ----------------------------- API ----------------------------- */\n\n/**\n * Start lightweight peak-memory tracking.\n *\n * - If `performance.memory` is unavailable, this becomes a no-op (safe).\n * - In \"onHide\" mode, the tracker reports at most once per page lifetime.\n * - In \"interval\" mode, it reports at a low frequency (use conservatively).\n * - In \"manual\" mode, you can call `reportMemoryPeak()` whenever you like.\n *\n * @example\n * ```ts\n * import { startMemoryPeakTracking } from \"datadog-ux-utils/memoryPeak\";\n *\n * // Default: records peaks and reports once when the tab hides/unloads\n * const stop = startMemoryPeakTracking();\n *\n * // Clean up later (SPA teardown)\n * stop();\n * ```\n *\n * @example\n * ```ts\n * // Interval mode (report every 2 minutes)\n * startMemoryPeakTracking({ mode: \"interval\", intervalMs: 120_000 });\n * ```\n */\nexport function startMemoryPeakTracking(options: MemoryPeakOptions = {}) {\n if (installed) return stopMemoryPeakTracking;\n installed = true;\n\n opts = { ...DEFAULTS, ...options };\n\n // Try an immediate sample so we have an initial baseline if supported\n sampleOnce();\n\n // Mode wiring\n if (opts.mode === \"onHide\") {\n window.addEventListener(\"visibilitychange\", onVisibilityChange, {\n passive: true,\n });\n window.addEventListener(\"pagehide\", onPageHide, { passive: true });\n window.addEventListener(\"beforeunload\", onBeforeUnload, { passive: true });\n } else if (opts.mode === \"interval\") {\n intervalId = window.setInterval(\n reportMemoryPeak,\n Math.max(15_000, opts.intervalMs)\n );\n }\n\n // Opportunistically sample at low-cost lifecycle points\n window.addEventListener(\"resize\", onLightTouchSample, { passive: true });\n window.addEventListener(\"focus\", onLightTouchSample, { passive: true });\n\n return stopMemoryPeakTracking;\n}\n\n/**\n * Stop tracking and remove listeners. Does not clear the last observed peak.\n */\nexport function stopMemoryPeakTracking() {\n if (!installed) return;\n installed = false;\n\n window.removeEventListener(\"visibilitychange\", onVisibilityChange as any);\n window.removeEventListener(\"pagehide\", onPageHide as any);\n window.removeEventListener(\"beforeunload\", onBeforeUnload as any);\n window.removeEventListener(\"resize\", onLightTouchSample as any);\n window.removeEventListener(\"focus\", onLightTouchSample as any);\n\n if (intervalId != null) {\n clearInterval(intervalId);\n intervalId = null;\n }\n}\n\n/**\n * Return the current peak snapshot (or `null` if nothing recorded / unsupported).\n *\n * @example\n * ```ts\n * import { getMemoryPeak } from \"datadog-ux-utils/memoryPeak\";\n * console.log(getMemoryPeak());\n * ```\n */\nexport function getMemoryPeak(): MemoryPeak | null {\n return peak ? { ...peak } : null;\n}\n\n/**\n * Manually force a report of the current peak (no-op if none).\n * Respects `reportToDatadog` and action naming in options.\n *\n * @example\n * ```ts\n * import { reportMemoryPeak } from \"datadog-ux-utils/memoryPeak\";\n * await someBigOperation();\n * reportMemoryPeak(); // log the current max after the operation\n * ```\n */\nexport function reportMemoryPeak() {\n if (!peak || !opts.reportToDatadog) return;\n\n // Avoid duplicate spamming if someone calls frequently\n const now = Date.now();\n if (now - lastReportedAt < 10_000) return; // 10s guard\n lastReportedAt = now;\n\n try {\n safeAddAction(opts.actionName, {\n peakUsedBytes: peak.peakUsedBytes,\n peakTotalBytes: peak.peakTotalBytes,\n peakLimitBytes: peak.peakLimitBytes,\n at: peak.at,\n peakUsedMB: bytesToMB(peak.peakUsedBytes), // handy for dashboards\n });\n } catch {\n // Intentionally ignore errors to avoid impacting UX.\n }\n}\n\n/**\n * Reset the recorded peak (useful when switching routes or completing a large workflow).\n *\n * @example\n * ```ts\n * import { resetMemoryPeak } from \"datadog-ux-utils/memoryPeak\";\n * resetMemoryPeak();\n * ```\n */\nexport function resetMemoryPeak() {\n peak = null;\n lastReportedAt = 0;\n}\n\n/* --------------------------- internals --------------------------- */\n\nfunction getPerfMemory(): {\n usedJSHeapSize: number;\n totalJSHeapSize: number;\n jsHeapSizeLimit: number;\n} | null {\n const anyPerf = performance as any;\n const m = anyPerf?.memory;\n if (!m) return null;\n const { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit } = m;\n // Guard against bogus zeros from some environments\n if (typeof usedJSHeapSize !== \"number\" || usedJSHeapSize <= 0) return null;\n return { usedJSHeapSize, totalJSHeapSize, jsHeapSizeLimit };\n}\n\n/** Take a single measurement and update peak if higher. */\nfunction sampleOnce() {\n const m = getPerfMemory();\n if (!m) return;\n\n if (!peak || m.usedJSHeapSize > peak.peakUsedBytes) {\n peak = {\n peakUsedBytes: m.usedJSHeapSize,\n peakTotalBytes: m.totalJSHeapSize,\n peakLimitBytes: m.jsHeapSizeLimit,\n at: Date.now(),\n };\n // Notify local callback when a new peak is observed\n try {\n opts.onNewPeak(peak);\n } catch {\n // Intentionally ignore\n }\n }\n}\n\nfunction onLightTouchSample() {\n // Occasional sample on benign events; avoid tight loops.\n sampleOnce();\n}\n\nfunction onVisibilityChange() {\n if (document.visibilityState === \"hidden\") {\n sampleOnce();\n reportMemoryPeak();\n } else {\n // When coming back, take a fresh sample (peaks can rise again)\n sampleOnce();\n }\n}\n\nfunction onPageHide() {\n sampleOnce();\n reportMemoryPeak();\n}\n\nfunction onBeforeUnload() {\n sampleOnce();\n reportMemoryPeak();\n}\n\n/* ---------------------------- utils ---------------------------- */\n\nfunction bytesToMB(b: number) {\n return Math.round((b / (1024 * 1024)) * 100) / 100;\n}\n\n/**\nEXAMPLES\n\n1) Default (recommended): report once on page hide/unload\nimport { startMemoryPeakTracking } from \"datadog-ux-utils/memoryPeak\";\n\nconst stop = startMemoryPeakTracking();\n// ... later\n// stop();\n\n2) Interval mode (low frequency)\nimport { startMemoryPeakTracking } from \"datadog-ux-utils/memoryPeak\";\n\n// Report every 2 minutes (be conservative to keep volume tiny)\nstartMemoryPeakTracking({ mode: \"interval\", intervalMs: 120_000 });\n\n3) Manual reporting\nimport { startMemoryPeakTracking, reportMemoryPeak } from \"datadog-ux-utils/memoryPeak\";\n\nstartMemoryPeakTracking({ mode: \"manual\", reportToDatadog: true });\n// …do some memory-heavy workflow…\nreportMemoryPeak(); // log the current peak on demand\n\n4) Reacting to new peaks locally\nimport { startMemoryPeakTracking } from \"datadog-ux-utils/memoryPeak\";\n\nstartMemoryPeakTracking({\n onNewPeak: ({ peakUsedBytes }) => {\n const mb = Math.round((peakUsedBytes / 1024 / 1024) * 10) / 10;\n if (mb > 700) {\n console.warn(\"High memory peak:\", mb, \"MB — consider shedding cache.\");\n }\n },\n});\n\n*/\n","/**\n * @file resources.ts\n * @description Reports large or slow-loading resources using the Performance API and sends summary events to Datadog RUM.\n */\nimport { datadogRum } from \"@datadog/browser-rum\";\nimport { getUxConfig } from \"../config.ts\";\n\n/**\n * Capture oversized or slow-loading resources from the Performance API\n * and send summary events to DataDog.\n */\n/**\n * Capture oversized or slow-loading resources from the Performance API and send summary events to Datadog.\n * @param opts - Optional thresholds and sample rate for reporting.\n */\nexport const reportLargeOrSlowResources = (opts?: {\n sizeKbThreshold?: number;\n durationMsThreshold?: number;\n sampleRate?: number;\n}) => {\n if (!(\"performance\" in window) || !performance.getEntriesByType) return;\n\n const cfg = getUxConfig();\n const sizeThreshold = opts?.sizeKbThreshold ?? 250; // default: >250 KB\n const durationThreshold = opts?.durationMsThreshold ?? 2000; // default: >2s load\n const sampleRate = opts?.sampleRate ?? cfg.actionSampleRate;\n\n const resources = performance.getEntriesByType(\n \"resource\"\n ) as PerformanceResourceTiming[];\n\n for (const res of resources) {\n // Skip data URIs and tracking pixels\n if (res.name.startsWith(\"data:\") || res.transferSize === 0) continue;\n\n const sizeKb = Math.round(res.transferSize / 1024);\n const durationMs = Math.round(res.duration);\n\n const isLarge = sizeKb >= sizeThreshold;\n const isSlow = durationMs >= durationThreshold;\n\n if (isLarge || isSlow) {\n maybeAction(\n \"resource_perf_issue\",\n {\n url: res.name,\n initiatorType: res.initiatorType,\n size_kb: sizeKb,\n duration_ms: durationMs,\n large_threshold_kb: sizeThreshold,\n slow_threshold_ms: durationThreshold,\n },\n sampleRate\n );\n }\n }\n};\n\n/**\n * Run on initial load, or after route changes if your app lazy-loads assets.\n * Optionally call multiple times in SPA environments.\n */\n/**\n * Reports resources on initial load or after route changes, with optional delay and thresholds.\n * @param delayMs - Delay in milliseconds before reporting.\n * @param thresholds - Optional thresholds for size and duration.\n */\nexport const reportResourcesOnLoad = (\n delayMs = 3000,\n thresholds?: { sizeKbThreshold?: number; durationMsThreshold?: number }\n) => {\n setTimeout(() => reportLargeOrSlowResources(thresholds), delayMs);\n};\n\nconst maybeAction = (\n name: string,\n attrs: Record<string, unknown>,\n rate: number\n) => {\n if (Math.random() * 100 < rate) {\n datadogRum.addAction(name, attrs);\n }\n};\n","/**\n * @file webVitals.ts\n * @description Registers web-vitals listeners and reports core metrics (CLS, LCP, FCP, INP, TTFB) to Datadog RUM if enabled in config.\n */\nimport { onCLS, onFCP, onLCP, onINP, onTTFB } from \"web-vitals\";\nimport { datadogRum } from \"@datadog/browser-rum\";\nimport { getUxConfig } from \"../config.ts\";\n\n/**\n * Registers web-vitals listeners and reports metrics to Datadog RUM if enabled in config.\n */\nexport const registerWebVitals = () => {\n if (!getUxConfig().captureWebVitals) return;\n\n const send = (name: string, value: number, meta: any = {}) =>\n datadogRum.addAction(\"web_vital\", { name, value, ...meta });\n\n onCLS(({ value }) => send(\"CLS\", value));\n onLCP(({ value, entries }) => {\n const entry = entries?.[0];\n // Only LargestContentfulPaint entries have 'element'\n const elementTag =\n entry && \"element\" in entry && (entry as any).element\n ? (entry as any).element.tagName\n : undefined;\n send(\"LCP\", value, { element: elementTag });\n });\n onFCP(({ value }) => send(\"FCP\", value));\n onINP(({ value }) => send(\"INP\", value));\n onTTFB(({ value }) => send(\"TTFB\", value));\n};\n"],"names":["_idleTimeout","_isIdle","_opts","startIdleTracker","opts","resetIdleTimer","safeAddAction","activityEvents","event","isUserIdle","_clsValue","_observer","startLayoutShiftTracking","list","entry","s","getCLSValue","obs","startLongTaskObserver","getUxConfig","datadogRum","stopLongTaskObserver","_timer","getMemoryUsage","anyPerf","usedJSHeapSize","totalJSHeapSize","jsHeapSizeLimit","startMemoryTracking","stopMemoryTracking","poll","metrics","DEFAULTS","peak","installed","intervalId","lastReportedAt","startMemoryPeakTracking","options","sampleOnce","onVisibilityChange","onPageHide","onBeforeUnload","reportMemoryPeak","onLightTouchSample","stopMemoryPeakTracking","getMemoryPeak","now","bytesToMB","resetMemoryPeak","getPerfMemory","m","b","reportLargeOrSlowResources","cfg","sizeThreshold","durationThreshold","sampleRate","resources","res","sizeKb","durationMs","isLarge","isSlow","maybeAction","reportResourcesOnLoad","delayMs","thresholds","name","attrs","rate","registerWebVitals","send","value","meta","onCLS","onLCP","entries","elementTag","onFCP","onINP","onTTFB"],"mappings":"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"}