@sentry/browser-utils 10.69.0 → 11.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/build/cjs/htmlTreeAsString.js.map +1 -1
  2. package/build/cjs/index.js +2 -1
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/cjs/metrics/browserMetrics.js +25 -91
  5. package/build/cjs/metrics/browserMetrics.js.map +1 -1
  6. package/build/cjs/metrics/inp.js +0 -57
  7. package/build/cjs/metrics/inp.js.map +1 -1
  8. package/build/cjs/metrics/lcp.js +0 -67
  9. package/build/cjs/metrics/lcp.js.map +1 -1
  10. package/build/cjs/metrics/userTiming.js +118 -0
  11. package/build/cjs/metrics/userTiming.js.map +1 -0
  12. package/build/cjs/metrics/utils.js +0 -43
  13. package/build/cjs/metrics/utils.js.map +1 -1
  14. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js +2 -6
  15. package/build/cjs/metrics/web-vitals/lib/getVisibilityWatcher.js.map +1 -1
  16. package/build/cjs/metrics/web-vitals/lib/initUnique.js +1 -1
  17. package/build/cjs/metrics/web-vitals/lib/initUnique.js.map +1 -1
  18. package/build/cjs/metrics/web-vitals/lib/onHidden.js +3 -4
  19. package/build/cjs/metrics/web-vitals/lib/onHidden.js.map +1 -1
  20. package/build/cjs/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +1 -1
  21. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -2
  22. package/build/cjs/metrics/web-vitals/lib/whenIdleOrHidden.js.map +1 -1
  23. package/build/cjs/metrics/webVitalSpans.js +25 -9
  24. package/build/cjs/metrics/webVitalSpans.js.map +1 -1
  25. package/build/esm/htmlTreeAsString.js.map +1 -1
  26. package/build/esm/index.js +2 -1
  27. package/build/esm/index.js.map +1 -1
  28. package/build/esm/metrics/browserMetrics.js +29 -94
  29. package/build/esm/metrics/browserMetrics.js.map +1 -1
  30. package/build/esm/metrics/inp.js +3 -57
  31. package/build/esm/metrics/inp.js.map +1 -1
  32. package/build/esm/metrics/lcp.js +1 -66
  33. package/build/esm/metrics/lcp.js.map +1 -1
  34. package/build/esm/metrics/userTiming.js +115 -0
  35. package/build/esm/metrics/userTiming.js.map +1 -0
  36. package/build/esm/metrics/utils.js +2 -44
  37. package/build/esm/metrics/utils.js.map +1 -1
  38. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js +2 -6
  39. package/build/esm/metrics/web-vitals/lib/getVisibilityWatcher.js.map +1 -1
  40. package/build/esm/metrics/web-vitals/lib/initUnique.js +1 -1
  41. package/build/esm/metrics/web-vitals/lib/initUnique.js.map +1 -1
  42. package/build/esm/metrics/web-vitals/lib/onHidden.js +3 -4
  43. package/build/esm/metrics/web-vitals/lib/onHidden.js.map +1 -1
  44. package/build/esm/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.js.map +1 -1
  45. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js +0 -2
  46. package/build/esm/metrics/web-vitals/lib/whenIdleOrHidden.js.map +1 -1
  47. package/build/esm/metrics/webVitalSpans.js +26 -10
  48. package/build/esm/metrics/webVitalSpans.js.map +1 -1
  49. package/build/esm/package.json +1 -1
  50. package/build/types/index.d.ts +2 -1
  51. package/build/types/index.d.ts.map +1 -1
  52. package/build/types/metrics/browserMetrics.d.ts +5 -29
  53. package/build/types/metrics/browserMetrics.d.ts.map +1 -1
  54. package/build/types/metrics/inp.d.ts +0 -13
  55. package/build/types/metrics/inp.d.ts.map +1 -1
  56. package/build/types/metrics/lcp.d.ts +0 -16
  57. package/build/types/metrics/lcp.d.ts.map +1 -1
  58. package/build/types/metrics/userTiming.d.ts +37 -0
  59. package/build/types/metrics/userTiming.d.ts.map +1 -0
  60. package/build/types/metrics/utils.d.ts +1 -25
  61. package/build/types/metrics/utils.d.ts.map +1 -1
  62. package/build/types/metrics/web-vitals/getCLS.d.ts.map +1 -1
  63. package/build/types/metrics/web-vitals/getINP.d.ts.map +1 -1
  64. package/build/types/metrics/web-vitals/getLCP.d.ts.map +1 -1
  65. package/build/types/metrics/web-vitals/lib/InteractionManager.d.ts.map +1 -1
  66. package/build/types/metrics/web-vitals/lib/LCPEntryManager.d.ts.map +1 -1
  67. package/build/types/metrics/web-vitals/lib/LayoutShiftManager.d.ts.map +1 -1
  68. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts +1 -1
  69. package/build/types/metrics/web-vitals/lib/bindReporter.d.ts.map +1 -1
  70. package/build/types/metrics/web-vitals/lib/getNavigationEntry.d.ts.map +1 -1
  71. package/build/types/metrics/web-vitals/lib/getVisibilityWatcher.d.ts.map +1 -1
  72. package/build/types/metrics/web-vitals/lib/initMetric.d.ts +3 -3
  73. package/build/types/metrics/web-vitals/lib/initMetric.d.ts.map +1 -1
  74. package/build/types/metrics/web-vitals/lib/observe.d.ts.map +1 -1
  75. package/build/types/metrics/web-vitals/lib/onHidden.d.ts +4 -16
  76. package/build/types/metrics/web-vitals/lib/onHidden.d.ts.map +1 -1
  77. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +1 -1
  78. package/build/types/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts.map +1 -1
  79. package/build/types/metrics/web-vitals/lib/runOnce.d.ts.map +1 -1
  80. package/build/types/metrics/web-vitals/lib/whenActivated.d.ts.map +1 -1
  81. package/build/types/metrics/web-vitals/lib/whenIdleOrHidden.d.ts.map +1 -1
  82. package/build/types/metrics/web-vitals/onFCP.d.ts.map +1 -1
  83. package/build/types/metrics/web-vitals/onTTFB.d.ts.map +1 -1
  84. package/build/types/metrics/web-vitals/types.d.ts +1 -1
  85. package/build/types/metrics/web-vitals/types.d.ts.map +1 -1
  86. package/build/types/metrics/webVitalSpans.d.ts +15 -9
  87. package/build/types/metrics/webVitalSpans.d.ts.map +1 -1
  88. package/build/types/types.d.ts +1 -1
  89. package/package.json +6 -15
  90. package/build/cjs/metrics/cls.js +0 -64
  91. package/build/cjs/metrics/cls.js.map +0 -1
  92. package/build/esm/metrics/cls.js +0 -61
  93. package/build/esm/metrics/cls.js.map +0 -1
  94. package/build/types/metrics/cls.d.ts +0 -17
  95. package/build/types/metrics/cls.d.ts.map +0 -1
  96. package/build/types-ts3.8/debug-build.d.ts +0 -7
  97. package/build/types-ts3.8/getNativeImplementation.d.ts +0 -69
  98. package/build/types-ts3.8/htmlTreeAsString.d.ts +0 -11
  99. package/build/types-ts3.8/index.d.ts +0 -17
  100. package/build/types-ts3.8/instrument/dom.d.ts +0 -11
  101. package/build/types-ts3.8/instrument/history.d.ts +0 -15
  102. package/build/types-ts3.8/instrument/location.d.ts +0 -13
  103. package/build/types-ts3.8/instrument/xhr.d.ts +0 -14
  104. package/build/types-ts3.8/is.d.ts +0 -7
  105. package/build/types-ts3.8/metrics/browserMetrics.d.ts +0 -119
  106. package/build/types-ts3.8/metrics/cls.d.ts +0 -17
  107. package/build/types-ts3.8/metrics/elementTiming.d.ts +0 -21
  108. package/build/types-ts3.8/metrics/inp.d.ts +0 -35
  109. package/build/types-ts3.8/metrics/instrument.d.ts +0 -121
  110. package/build/types-ts3.8/metrics/lcp.d.ts +0 -22
  111. package/build/types-ts3.8/metrics/resourceTiming.d.ts +0 -13
  112. package/build/types-ts3.8/metrics/utils.d.ts +0 -73
  113. package/build/types-ts3.8/metrics/web-vitals/getCLS.d.ts +0 -26
  114. package/build/types-ts3.8/metrics/web-vitals/getINP.d.ts +0 -34
  115. package/build/types-ts3.8/metrics/web-vitals/getLCP.d.ts +0 -16
  116. package/build/types-ts3.8/metrics/web-vitals/lib/InteractionManager.d.ts +0 -37
  117. package/build/types-ts3.8/metrics/web-vitals/lib/LCPEntryManager.d.ts +0 -5
  118. package/build/types-ts3.8/metrics/web-vitals/lib/LayoutShiftManager.d.ts +0 -7
  119. package/build/types-ts3.8/metrics/web-vitals/lib/bindReporter.d.ts +0 -7
  120. package/build/types-ts3.8/metrics/web-vitals/lib/generateUniqueID.d.ts +0 -7
  121. package/build/types-ts3.8/metrics/web-vitals/lib/getActivationStart.d.ts +0 -2
  122. package/build/types-ts3.8/metrics/web-vitals/lib/getNavigationEntry.d.ts +0 -2
  123. package/build/types-ts3.8/metrics/web-vitals/lib/getVisibilityWatcher.d.ts +0 -5
  124. package/build/types-ts3.8/metrics/web-vitals/lib/globalListeners.d.ts +0 -11
  125. package/build/types-ts3.8/metrics/web-vitals/lib/initMetric.d.ts +0 -21
  126. package/build/types-ts3.8/metrics/web-vitals/lib/initUnique.d.ts +0 -7
  127. package/build/types-ts3.8/metrics/web-vitals/lib/observe.d.ts +0 -23
  128. package/build/types-ts3.8/metrics/web-vitals/lib/onHidden.d.ts +0 -27
  129. package/build/types-ts3.8/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.d.ts +0 -15
  130. package/build/types-ts3.8/metrics/web-vitals/lib/runOnce.d.ts +0 -2
  131. package/build/types-ts3.8/metrics/web-vitals/lib/whenActivated.d.ts +0 -2
  132. package/build/types-ts3.8/metrics/web-vitals/lib/whenIdleOrHidden.d.ts +0 -6
  133. package/build/types-ts3.8/metrics/web-vitals/onFCP.d.ts +0 -11
  134. package/build/types-ts3.8/metrics/web-vitals/onTTFB.d.ts +0 -20
  135. package/build/types-ts3.8/metrics/web-vitals/types/base.d.ts +0 -106
  136. package/build/types-ts3.8/metrics/web-vitals/types/cls.d.ts +0 -58
  137. package/build/types-ts3.8/metrics/web-vitals/types/fcp.d.ts +0 -47
  138. package/build/types-ts3.8/metrics/web-vitals/types/inp.d.ts +0 -150
  139. package/build/types-ts3.8/metrics/web-vitals/types/lcp.d.ts +0 -74
  140. package/build/types-ts3.8/metrics/web-vitals/types/ttfb.d.ts +0 -60
  141. package/build/types-ts3.8/metrics/web-vitals/types.d.ts +0 -78
  142. package/build/types-ts3.8/metrics/webVitalSpans.d.ts +0 -65
  143. package/build/types-ts3.8/networkUtils.d.ts +0 -28
  144. package/build/types-ts3.8/types.d.ts +0 -15
@@ -1,4 +1,4 @@
1
- import { spanToJSON, withActiveSpan, startInactiveSpan, getClient, getCurrentScope } from '@sentry/core';
1
+ import { spanToJSON, withActiveSpan, startInactiveSpan } from '@sentry/core';
2
2
  import { WINDOW } from '../types.js';
3
3
  import { onHidden } from './web-vitals/lib/onHidden.js';
4
4
 
@@ -23,48 +23,6 @@ function startAndEndSpan(parentSpan, startTimeInSeconds, endTime, { ...ctx }) {
23
23
  return span;
24
24
  });
25
25
  }
26
- function startStandaloneWebVitalSpan(options) {
27
- const client = getClient();
28
- if (!client) {
29
- return;
30
- }
31
- const { name, transaction, attributes: passedAttributes, startTime } = options;
32
- const { release, environment } = client.getOptions();
33
- const { userInfo } = client.getDataCollectionOptions();
34
- const replay = client.getIntegrationByName("Replay");
35
- const replayId = replay?.getReplayId();
36
- const scope = getCurrentScope();
37
- const user = scope.getUser();
38
- const userDisplay = user !== void 0 ? user.email || user.id || user.ip_address : void 0;
39
- let profileId;
40
- try {
41
- profileId = scope.getScopeData().contexts.profile.profile_id;
42
- } catch {
43
- }
44
- const attributes = {
45
- release,
46
- environment,
47
- user: userDisplay || void 0,
48
- profile_id: profileId || void 0,
49
- replay_id: replayId || void 0,
50
- transaction,
51
- // Web vital score calculation relies on the user agent to account for different
52
- // browsers setting different thresholds for what is considered a good/meh/bad value.
53
- // For example: Chrome vs. Chrome Mobile
54
- "user_agent.original": WINDOW.navigator?.userAgent,
55
- // This tells Sentry to infer the IP address from the request
56
- "client.address": userInfo ? "{{auto}}" : void 0,
57
- ...passedAttributes
58
- };
59
- return startInactiveSpan({
60
- name,
61
- attributes,
62
- startTime,
63
- experimental: {
64
- standalone: true
65
- }
66
- });
67
- }
68
26
  function getBrowserPerformanceAPI() {
69
27
  return WINDOW.addEventListener && WINDOW.performance;
70
28
  }
@@ -124,5 +82,5 @@ function listenForWebVitalReportEvents(client, collectorCallback) {
124
82
  });
125
83
  }
126
84
 
127
- export { extractNetworkProtocol, getBrowserPerformanceAPI, isMeasurementValue, listenForWebVitalReportEvents, msToSec, startAndEndSpan, startStandaloneWebVitalSpan, supportsWebVital };
85
+ export { extractNetworkProtocol, getBrowserPerformanceAPI, isMeasurementValue, listenForWebVitalReportEvents, msToSec, startAndEndSpan, supportsWebVital };
128
86
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../src/metrics/utils.ts"],"sourcesContent":["import type {\n Client,\n Integration,\n SentrySpan,\n Span,\n SpanAttributes,\n SpanTimeInput,\n StartSpanOptions,\n} from '@sentry/core';\nimport { getClient, getCurrentScope, spanToJSON, startInactiveSpan, withActiveSpan } from '@sentry/core';\nimport { WINDOW } from '../types';\nimport { onHidden } from './web-vitals/lib/onHidden';\n\nexport type WebVitalReportEvent = 'pagehide' | 'navigation';\n\n/**\n * Checks if a given value is a valid measurement value.\n */\nexport function isMeasurementValue(value: unknown): value is number {\n return typeof value === 'number' && isFinite(value);\n}\n\n/**\n * Helper function to start child on transactions. This function will make sure that the transaction will\n * use the start timestamp of the created child span if it is earlier than the transactions actual\n * start timestamp.\n */\nexport function startAndEndSpan(\n parentSpan: Span,\n startTimeInSeconds: number,\n endTime: SpanTimeInput,\n { ...ctx }: StartSpanOptions,\n): Span | undefined {\n const parentStartTime = spanToJSON(parentSpan).start_timestamp;\n if (parentStartTime && parentStartTime > startTimeInSeconds) {\n // We can only do this for SentrySpans...\n if (typeof (parentSpan as Partial<SentrySpan>).updateStartTime === 'function') {\n (parentSpan as SentrySpan).updateStartTime(startTimeInSeconds);\n }\n }\n\n // The return value only exists for tests\n return withActiveSpan(parentSpan, () => {\n const span = startInactiveSpan({\n startTime: startTimeInSeconds,\n ...ctx,\n });\n\n if (span) {\n span.end(endTime);\n }\n\n return span;\n });\n}\n\ninterface StandaloneWebVitalSpanOptions {\n name: string;\n transaction?: string;\n attributes: SpanAttributes;\n startTime: number;\n}\n\n/**\n * Starts an inactive, standalone span used to send web vital values to Sentry.\n * DO NOT use this for arbitrary spans, as these spans require special handling\n * during ingestion to extract metrics.\n *\n * This function adds a bunch of attributes and data to the span that's shared\n * by all web vital standalone spans. However, you need to take care of adding\n * the actual web vital value as an event to the span. Also, you need to assign\n * a transaction name and some other values that are specific to the web vital.\n *\n * Ultimately, you also need to take care of ending the span to send it off.\n *\n * @param options\n *\n * @returns an inactive, standalone and NOT YET ended span\n */\nexport function startStandaloneWebVitalSpan(options: StandaloneWebVitalSpanOptions): Span | undefined {\n const client = getClient();\n if (!client) {\n return;\n }\n\n const { name, transaction, attributes: passedAttributes, startTime } = options;\n\n const { release, environment } = client.getOptions();\n const { userInfo } = client.getDataCollectionOptions();\n // We need to get the replay, user, and activeTransaction from the current scope\n // so that we can associate replay id, profile id, and a user display to the span\n const replay = client.getIntegrationByName<Integration & { getReplayId: () => string }>('Replay');\n const replayId = replay?.getReplayId();\n\n const scope = getCurrentScope();\n\n const user = scope.getUser();\n const userDisplay = user !== undefined ? user.email || user.id || user.ip_address : undefined;\n\n let profileId: string | undefined;\n try {\n // @ts-expect-error skip optional chaining to save bundle size with try catch\n profileId = scope.getScopeData().contexts.profile.profile_id;\n } catch {\n // do nothing\n }\n\n const attributes: SpanAttributes = {\n release,\n environment,\n\n user: userDisplay || undefined,\n profile_id: profileId || undefined,\n replay_id: replayId || undefined,\n\n transaction,\n\n // Web vital score calculation relies on the user agent to account for different\n // browsers setting different thresholds for what is considered a good/meh/bad value.\n // For example: Chrome vs. Chrome Mobile\n 'user_agent.original': WINDOW.navigator?.userAgent,\n\n // This tells Sentry to infer the IP address from the request\n 'client.address': userInfo ? '{{auto}}' : undefined,\n\n ...passedAttributes,\n };\n\n return startInactiveSpan({\n name,\n attributes,\n startTime,\n experimental: {\n standalone: true,\n },\n });\n}\n\n/** Get the browser performance API. */\nexport function getBrowserPerformanceAPI(): Performance | undefined {\n // @ts-expect-error we want to make sure all of these are available, even if TS is sure they are\n return WINDOW.addEventListener && WINDOW.performance;\n}\n\n/**\n * Converts from milliseconds to seconds\n * @param time time in ms\n */\nexport function msToSec(time: number): number {\n return time / 1000;\n}\n\n/**\n * Converts ALPN protocol ids to name and version.\n *\n * (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)\n * @param nextHopProtocol PerformanceResourceTiming.nextHopProtocol\n */\nexport function extractNetworkProtocol(nextHopProtocol: string): { name: string; version: string } {\n let name = 'unknown';\n let version = 'unknown';\n let _name = '';\n for (const char of nextHopProtocol) {\n // http/1.1 etc.\n if (char === '/') {\n [name, version] = nextHopProtocol.split('/') as [string, string];\n break;\n }\n // h2, h3 etc.\n if (!isNaN(Number(char))) {\n name = _name === 'h' ? 'http' : _name;\n version = nextHopProtocol.split(_name)[1] as string;\n break;\n }\n _name += char;\n }\n if (_name === nextHopProtocol) {\n // webrtc, ftp, etc.\n name = _name;\n }\n return { name, version };\n}\n\n/**\n * Generic support check for web vitals\n */\nexport function supportsWebVital(entryType: 'layout-shift' | 'largest-contentful-paint'): boolean {\n try {\n return PerformanceObserver.supportedEntryTypes.includes(entryType);\n } catch {\n return false;\n }\n}\n\n/**\n * Listens for events on which we want to collect a previously accumulated web vital value.\n * Currently, this includes:\n *\n * - pagehide (i.e. user minimizes browser window, hides tab, etc)\n * - soft navigation (we only care about the vital of the initially loaded route)\n *\n * As a \"side-effect\", this function will also collect the span id of the pageload span.\n *\n * @param collectorCallback the callback to be called when the first of these events is triggered. Parameters:\n * - event: the event that triggered the reporting of the web vital value.\n * - pageloadSpanId: the span id of the pageload span. This is used to link the web vital span to the pageload span.\n * - pageloadSpan: the pageload span instance. This is used for full access to the pageload span for span streaming.\n */\nexport function listenForWebVitalReportEvents(\n client: Client,\n collectorCallback: (event: WebVitalReportEvent, pageloadSpanId: string, pageloadSpan?: Span) => void,\n) {\n let pageloadSpan: Span | undefined;\n\n let collected = false;\n function _runCollectorCallbackOnce(event: WebVitalReportEvent) {\n if (!collected && pageloadSpan) {\n collectorCallback(event, pageloadSpan.spanContext().spanId, pageloadSpan);\n }\n collected = true;\n }\n\n // eslint-disable-next-line typescript/no-deprecated\n onHidden(() => {\n _runCollectorCallbackOnce('pagehide');\n });\n\n const unsubscribeStartNavigation = client.on('beforeStartNavigationSpan', (_, options) => {\n // we only want to collect LCP if we actually navigate. Redirects should be ignored.\n if (!options?.isRedirect) {\n _runCollectorCallbackOnce('navigation');\n unsubscribeStartNavigation();\n unsubscribeAfterStartPageLoadSpan();\n }\n });\n\n const unsubscribeAfterStartPageLoadSpan = client.on('afterStartPageLoadSpan', span => {\n pageloadSpan = span;\n unsubscribeAfterStartPageLoadSpan();\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sources":["../../../src/metrics/utils.ts"],"sourcesContent":["import type { Client, SentrySpan, Span, SpanTimeInput, StartSpanOptions } from '@sentry/core';\nimport { spanToJSON, startInactiveSpan, withActiveSpan } from '@sentry/core';\nimport { WINDOW } from '../types';\nimport { onHidden } from './web-vitals/lib/onHidden';\n\nexport type WebVitalReportEvent = 'pagehide' | 'navigation';\n\n/**\n * Checks if a given value is a valid measurement value.\n */\nexport function isMeasurementValue(value: unknown): value is number {\n return typeof value === 'number' && isFinite(value);\n}\n\n/**\n * Helper function to start child on transactions. This function will make sure that the transaction will\n * use the start timestamp of the created child span if it is earlier than the transactions actual\n * start timestamp.\n */\nexport function startAndEndSpan(\n parentSpan: Span,\n startTimeInSeconds: number,\n endTime: SpanTimeInput,\n { ...ctx }: StartSpanOptions,\n): Span | undefined {\n const parentStartTime = spanToJSON(parentSpan).start_timestamp;\n if (parentStartTime && parentStartTime > startTimeInSeconds) {\n // We can only do this for SentrySpans...\n if (typeof (parentSpan as Partial<SentrySpan>).updateStartTime === 'function') {\n (parentSpan as SentrySpan).updateStartTime(startTimeInSeconds);\n }\n }\n\n // The return value only exists for tests\n return withActiveSpan(parentSpan, () => {\n const span = startInactiveSpan({\n startTime: startTimeInSeconds,\n ...ctx,\n });\n\n if (span) {\n span.end(endTime);\n }\n\n return span;\n });\n}\n\n/** Get the browser performance API. */\nexport function getBrowserPerformanceAPI(): Performance | undefined {\n // @ts-expect-error we want to make sure all of these are available, even if TS is sure they are\n return WINDOW.addEventListener && WINDOW.performance;\n}\n\n/**\n * Converts from milliseconds to seconds\n * @param time time in ms\n */\nexport function msToSec(time: number): number {\n return time / 1000;\n}\n\n/**\n * Converts ALPN protocol ids to name and version.\n *\n * (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)\n * @param nextHopProtocol PerformanceResourceTiming.nextHopProtocol\n */\nexport function extractNetworkProtocol(nextHopProtocol: string): { name: string; version: string } {\n let name = 'unknown';\n let version = 'unknown';\n let _name = '';\n for (const char of nextHopProtocol) {\n // http/1.1 etc.\n if (char === '/') {\n [name, version] = nextHopProtocol.split('/') as [string, string];\n break;\n }\n // h2, h3 etc.\n if (!isNaN(Number(char))) {\n name = _name === 'h' ? 'http' : _name;\n version = nextHopProtocol.split(_name)[1] as string;\n break;\n }\n _name += char;\n }\n if (_name === nextHopProtocol) {\n // webrtc, ftp, etc.\n name = _name;\n }\n return { name, version };\n}\n\n/**\n * Generic support check for web vitals\n */\nexport function supportsWebVital(entryType: 'layout-shift' | 'largest-contentful-paint'): boolean {\n try {\n return PerformanceObserver.supportedEntryTypes.includes(entryType);\n } catch {\n return false;\n }\n}\n\n/**\n * Listens for events on which we want to collect a previously accumulated web vital value.\n * Currently, this includes:\n *\n * - pagehide (i.e. user minimizes browser window, hides tab, etc)\n * - soft navigation (we only care about the vital of the initially loaded route)\n *\n * As a \"side-effect\", this function will also collect the span id of the pageload span.\n *\n * @param collectorCallback the callback to be called when the first of these events is triggered. Parameters:\n * - event: the event that triggered the reporting of the web vital value.\n * - pageloadSpanId: the span id of the pageload span. This is used to link the web vital span to the pageload span.\n * - pageloadSpan: the pageload span instance. This is used for full access to the pageload span for span streaming.\n */\nexport function listenForWebVitalReportEvents(\n client: Client,\n collectorCallback: (event: WebVitalReportEvent, pageloadSpanId: string, pageloadSpan?: Span) => void,\n) {\n let pageloadSpan: Span | undefined;\n\n let collected = false;\n function _runCollectorCallbackOnce(event: WebVitalReportEvent) {\n if (!collected && pageloadSpan) {\n collectorCallback(event, pageloadSpan.spanContext().spanId, pageloadSpan);\n }\n collected = true;\n }\n\n // eslint-disable-next-line typescript/no-deprecated\n onHidden(() => {\n _runCollectorCallbackOnce('pagehide');\n });\n\n const unsubscribeStartNavigation = client.on('beforeStartNavigationSpan', (_, options) => {\n // we only want to collect LCP if we actually navigate. Redirects should be ignored.\n if (!options?.isRedirect) {\n _runCollectorCallbackOnce('navigation');\n unsubscribeStartNavigation();\n unsubscribeAfterStartPageLoadSpan();\n }\n });\n\n const unsubscribeAfterStartPageLoadSpan = client.on('afterStartPageLoadSpan', span => {\n pageloadSpan = span;\n unsubscribeAfterStartPageLoadSpan();\n });\n}\n"],"names":[],"mappings":"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"}
@@ -8,8 +8,8 @@ const initHiddenTime = () => {
8
8
  return WINDOW.document?.visibilityState === "hidden" && !WINDOW.document?.prerendering ? 0 : Infinity;
9
9
  };
10
10
  const onVisibilityUpdate = (event) => {
11
- if (isPageHidden(event) && firstHiddenTime > -1) {
12
- if (event.type === "visibilitychange" || event.type === "pagehide") {
11
+ if (WINDOW.document?.visibilityState === "hidden" && firstHiddenTime > -1) {
12
+ if (event.type === "visibilitychange") {
13
13
  for (const onHiddenFunction of onHiddenFunctions) {
14
14
  onHiddenFunction();
15
15
  }
@@ -26,7 +26,6 @@ const getVisibilityWatcher = () => {
26
26
  const firstVisibilityStateHiddenTime = !WINDOW.document.prerendering ? globalThis.performance.getEntriesByType("visibility-state").filter((e) => e.name === "hidden" && e.startTime > activationStart)[0]?.startTime : void 0;
27
27
  firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();
28
28
  addPageListener("visibilitychange", onVisibilityUpdate, true);
29
- addPageListener("pagehide", onVisibilityUpdate, true);
30
29
  addPageListener("prerenderingchange", onVisibilityUpdate, true);
31
30
  }
32
31
  return {
@@ -38,9 +37,6 @@ const getVisibilityWatcher = () => {
38
37
  }
39
38
  };
40
39
  };
41
- function isPageHidden(event) {
42
- return event.type === "pagehide" || WINDOW.document?.visibilityState === "hidden";
43
- }
44
40
 
45
41
  export { getVisibilityWatcher };
46
42
  //# sourceMappingURL=getVisibilityWatcher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getVisibilityWatcher.js","sources":["../../../../../src/metrics/web-vitals/lib/getVisibilityWatcher.ts"],"sourcesContent":["/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types';\nimport { getActivationStart } from './getActivationStart';\nimport { addPageListener, removePageListener } from './globalListeners';\n\nlet firstHiddenTime = -1;\nconst onHiddenFunctions: Set<() => void> = new Set();\n\nconst initHiddenTime = () => {\n // If the document is hidden when this code runs, assume it was always\n // hidden and the page was loaded in the background, with the one exception\n // that visibility state is always 'hidden' during prerendering, so we have\n // to ignore that case until prerendering finishes (see: `prerenderingchange`\n // event logic below).\n return WINDOW.document?.visibilityState === 'hidden' && !WINDOW.document?.prerendering ? 0 : Infinity;\n};\n\nconst onVisibilityUpdate = (event: Event) => {\n // Handle changes to hidden state\n if (isPageHidden(event) && firstHiddenTime > -1) {\n // Sentry-specific change: Also call onHidden callbacks for pagehide events\n // to support older browsers (Safari <14.4) that don't properly fire visibilitychange\n if (event.type === 'visibilitychange' || event.type === 'pagehide') {\n for (const onHiddenFunction of onHiddenFunctions) {\n onHiddenFunction();\n }\n }\n\n // If the document is 'hidden' and no previous hidden timestamp has been\n // set (so is infinity), update it based on the current event data.\n if (!isFinite(firstHiddenTime)) {\n // If the event is a 'visibilitychange' event, it means the page was\n // visible prior to this change, so the event timestamp is the first\n // hidden time.\n // However, if the event is not a 'visibilitychange' event, then it must\n // be a 'prerenderingchange' or 'pagehide' event, and the fact that the document is\n // still 'hidden' from the above check means the tab was activated\n // in a background state and so has always been hidden.\n firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;\n\n // We no longer need the `prerenderingchange` event listener now we've\n // set an initial init time so remove that\n // (we'll keep the visibilitychange and pagehide ones for onHiddenFunction above)\n removePageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n }\n};\n\nexport const getVisibilityWatcher = () => {\n if (WINDOW.document && firstHiddenTime < 0) {\n // Check if we have a previous hidden `visibility-state` performance entry.\n const activationStart = getActivationStart();\n const firstVisibilityStateHiddenTime = !WINDOW.document.prerendering\n ? globalThis.performance\n .getEntriesByType('visibility-state')\n .filter(e => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime\n : undefined;\n\n // Prefer that, but if it's not available and the document is hidden when\n // this code runs, assume it was hidden since navigation start. This isn't\n // a perfect heuristic, but it's the best we can do until the\n // `visibility-state` performance entry becomes available in all browsers.\n firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();\n // Listen for visibility changes so we can handle things like bfcache\n // restores and/or prerender without having to examine individual\n // timestamps in detail and also for onHidden function calls.\n addPageListener('visibilitychange', onVisibilityUpdate, true);\n\n // Sentry-specific change: Some browsers have buggy implementations of visibilitychange,\n // so we use pagehide in addition, just to be safe. This is also required for older\n // Safari versions (<14.4) that we still support.\n addPageListener('pagehide', onVisibilityUpdate, true);\n\n // IMPORTANT: when a page is prerendering, its `visibilityState` is\n // 'hidden', so in order to account for cases where this module checks for\n // visibility during prerendering, an additional check after prerendering\n // completes is also required.\n addPageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n\n return {\n get firstHiddenTime() {\n return firstHiddenTime;\n },\n onHidden(cb: () => void) {\n onHiddenFunctions.add(cb);\n },\n };\n};\n\n/**\n * Check if the page is hidden, uses the `pagehide` event for older browsers support that we used to have in `onHidden` function.\n * Some browsers we still support (Safari <14.4) don't fully support `visibilitychange`\n * or have known bugs w.r.t the `visibilitychange` event.\n * // TODO (v11): If we decide to drop support for Safari 14.4, we can use the logic from web-vitals 4.2.4\n */\nfunction isPageHidden(event: Event) {\n return event.type === 'pagehide' || WINDOW.document?.visibilityState === 'hidden';\n}\n"],"names":[],"mappings":";;;;AAoBA,IAAI,eAAA,GAAkB,EAAA;AACtB,MAAM,iBAAA,uBAAyC,GAAA,EAAI;AAEnD,MAAM,iBAAiB,MAAM;AAM3B,EAAA,OAAO,MAAA,CAAO,UAAU,eAAA,KAAoB,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,EAAU,eAAe,CAAA,GAAI,QAAA;AAC/F,CAAA;AAEA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiB;AAE3C,EAAA,IAAI,YAAA,CAAa,KAAK,CAAA,IAAK,eAAA,GAAkB,EAAA,EAAI;AAG/C,IAAA,IAAI,KAAA,CAAM,IAAA,KAAS,kBAAA,IAAsB,KAAA,CAAM,SAAS,UAAA,EAAY;AAClE,MAAA,KAAA,MAAW,oBAAoB,iBAAA,EAAmB;AAChD,QAAA,gBAAA,EAAiB;AAAA,MACnB;AAAA,IACF;AAIA,IAAA,IAAI,CAAC,QAAA,CAAS,eAAe,CAAA,EAAG;AAQ9B,MAAA,eAAA,GAAkB,KAAA,CAAM,IAAA,KAAS,kBAAA,GAAqB,KAAA,CAAM,SAAA,GAAY,CAAA;AAKxE,MAAA,kBAAA,CAAmB,oBAAA,EAAsB,oBAAoB,IAAI,CAAA;AAAA,IACnE;AAAA,EACF;AACF,CAAA;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAA,IAAI,MAAA,CAAO,QAAA,IAAY,eAAA,GAAkB,CAAA,EAAG;AAE1C,IAAA,MAAM,kBAAkB,kBAAA,EAAmB;AAC3C,IAAA,MAAM,8BAAA,GAAiC,CAAC,MAAA,CAAO,QAAA,CAAS,eACpD,UAAA,CAAW,WAAA,CACR,iBAAiB,kBAAkB,CAAA,CACnC,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,QAAA,IAAY,CAAA,CAAE,YAAY,eAAe,CAAA,CAAE,CAAC,CAAA,EAAG,SAAA,GACzE,MAAA;AAMJ,IAAA,eAAA,GAAkB,kCAAkC,cAAA,EAAe;AAInE,IAAA,eAAA,CAAgB,kBAAA,EAAoB,oBAAoB,IAAI,CAAA;AAK5D,IAAA,eAAA,CAAgB,UAAA,EAAY,oBAAoB,IAAI,CAAA;AAMpD,IAAA,eAAA,CAAgB,oBAAA,EAAsB,oBAAoB,IAAI,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO;AAAA,IACL,IAAI,eAAA,GAAkB;AACpB,MAAA,OAAO,eAAA;AAAA,IACT,CAAA;AAAA,IACA,SAAS,EAAA,EAAgB;AACvB,MAAA,iBAAA,CAAkB,IAAI,EAAE,CAAA;AAAA,IAC1B;AAAA,GACF;AACF;AAQA,SAAS,aAAa,KAAA,EAAc;AAClC,EAAA,OAAO,KAAA,CAAM,IAAA,KAAS,UAAA,IAAc,MAAA,CAAO,UAAU,eAAA,KAAoB,QAAA;AAC3E;;;;"}
1
+ {"version":3,"file":"getVisibilityWatcher.js","sources":["../../../../../src/metrics/web-vitals/lib/getVisibilityWatcher.ts"],"sourcesContent":["/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types';\nimport { getActivationStart } from './getActivationStart';\nimport { addPageListener, removePageListener } from './globalListeners';\n\nlet firstHiddenTime = -1;\nconst onHiddenFunctions: Set<() => void> = new Set();\n\nconst initHiddenTime = () => {\n // If the document is hidden when this code runs, assume it was always\n // hidden and the page was loaded in the background, with the one exception\n // that visibility state is always 'hidden' during prerendering, so we have\n // to ignore that case until prerendering finishes (see: `prerenderingchange`\n // event logic below).\n return WINDOW.document?.visibilityState === 'hidden' && !WINDOW.document?.prerendering ? 0 : Infinity;\n};\n\nconst onVisibilityUpdate = (event: Event) => {\n // Handle changes to hidden state\n if (WINDOW.document?.visibilityState === 'hidden' && firstHiddenTime > -1) {\n // Call onHidden callbacks when the page becomes hidden\n if (event.type === 'visibilitychange') {\n for (const onHiddenFunction of onHiddenFunctions) {\n onHiddenFunction();\n }\n }\n\n // If the document is 'hidden' and no previous hidden timestamp has been\n // set (so is infinity), update it based on the current event data.\n if (!isFinite(firstHiddenTime)) {\n // If the event is a 'visibilitychange' event, it means the page was\n // visible prior to this change, so the event timestamp is the first\n // hidden time.\n // However, if the event is not a 'visibilitychange' event, then it must\n // be a 'prerenderingchange' event, and the fact that the document is\n // still 'hidden' from the above check means the tab was activated\n // in a background state and so has always been hidden.\n firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;\n\n // We no longer need the `prerenderingchange` event listener now we've\n // set an initial init time so remove that\n // (we'll keep the visibilitychange one for onHiddenFunction above)\n removePageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n }\n};\n\nexport const getVisibilityWatcher = () => {\n if (WINDOW.document && firstHiddenTime < 0) {\n // Check if we have a previous hidden `visibility-state` performance entry.\n const activationStart = getActivationStart();\n const firstVisibilityStateHiddenTime = !WINDOW.document.prerendering\n ? globalThis.performance\n .getEntriesByType('visibility-state')\n .filter(e => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime\n : undefined;\n\n // Prefer that, but if it's not available and the document is hidden when\n // this code runs, assume it was hidden since navigation start. This isn't\n // a perfect heuristic, but it's the best we can do until the\n // `visibility-state` performance entry becomes available in all browsers.\n firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();\n // Listen for visibility changes so we can handle things like bfcache\n // restores and/or prerender without having to examine individual\n // timestamps in detail and also for onHidden function calls.\n addPageListener('visibilitychange', onVisibilityUpdate, true);\n\n // IMPORTANT: when a page is prerendering, its `visibilityState` is\n // 'hidden', so in order to account for cases where this module checks for\n // visibility during prerendering, an additional check after prerendering\n // completes is also required.\n addPageListener('prerenderingchange', onVisibilityUpdate, true);\n }\n\n return {\n get firstHiddenTime() {\n return firstHiddenTime;\n },\n onHidden(cb: () => void) {\n onHiddenFunctions.add(cb);\n },\n };\n};\n"],"names":[],"mappings":";;;;AAoBA,IAAI,eAAA,GAAkB,EAAA;AACtB,MAAM,iBAAA,uBAAyC,GAAA,EAAI;AAEnD,MAAM,iBAAiB,MAAM;AAM3B,EAAA,OAAO,MAAA,CAAO,UAAU,eAAA,KAAoB,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,EAAU,eAAe,CAAA,GAAI,QAAA;AAC/F,CAAA;AAEA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiB;AAE3C,EAAA,IAAI,MAAA,CAAO,QAAA,EAAU,eAAA,KAAoB,QAAA,IAAY,kBAAkB,EAAA,EAAI;AAEzE,IAAA,IAAI,KAAA,CAAM,SAAS,kBAAA,EAAoB;AACrC,MAAA,KAAA,MAAW,oBAAoB,iBAAA,EAAmB;AAChD,QAAA,gBAAA,EAAiB;AAAA,MACnB;AAAA,IACF;AAIA,IAAA,IAAI,CAAC,QAAA,CAAS,eAAe,CAAA,EAAG;AAQ9B,MAAA,eAAA,GAAkB,KAAA,CAAM,IAAA,KAAS,kBAAA,GAAqB,KAAA,CAAM,SAAA,GAAY,CAAA;AAKxE,MAAA,kBAAA,CAAmB,oBAAA,EAAsB,oBAAoB,IAAI,CAAA;AAAA,IACnE;AAAA,EACF;AACF,CAAA;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAA,IAAI,MAAA,CAAO,QAAA,IAAY,eAAA,GAAkB,CAAA,EAAG;AAE1C,IAAA,MAAM,kBAAkB,kBAAA,EAAmB;AAC3C,IAAA,MAAM,8BAAA,GAAiC,CAAC,MAAA,CAAO,QAAA,CAAS,eACpD,UAAA,CAAW,WAAA,CACR,iBAAiB,kBAAkB,CAAA,CACnC,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,SAAS,QAAA,IAAY,CAAA,CAAE,YAAY,eAAe,CAAA,CAAE,CAAC,CAAA,EAAG,SAAA,GACzE,MAAA;AAMJ,IAAA,eAAA,GAAkB,kCAAkC,cAAA,EAAe;AAInE,IAAA,eAAA,CAAgB,kBAAA,EAAoB,oBAAoB,IAAI,CAAA;AAM5D,IAAA,eAAA,CAAgB,oBAAA,EAAsB,oBAAoB,IAAI,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO;AAAA,IACL,IAAI,eAAA,GAAkB;AACpB,MAAA,OAAO,eAAA;AAAA,IACT,CAAA;AAAA,IACA,SAAS,EAAA,EAAgB;AACvB,MAAA,iBAAA,CAAkB,IAAI,EAAE,CAAA;AAAA,IAC1B;AAAA,GACF;AACF;;;;"}
@@ -5,7 +5,7 @@ function initUnique(identityObj, ClassObj) {
5
5
  instanceMap.set(identityObj, new ClassObj());
6
6
  }
7
7
  return instanceMap.get(identityObj);
8
- } catch (_e) {
8
+ } catch {
9
9
  return new ClassObj();
10
10
  }
11
11
  }
@@ -1 +1 @@
1
- {"version":3,"file":"initUnique.js","sources":["../../../../../src/metrics/web-vitals/lib/initUnique.ts"],"sourcesContent":["/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst instanceMap: WeakMap<object, unknown> = new WeakMap();\n\n/**\n * A function that accepts and identity object and a class object and returns\n * either a new instance of that class or an existing instance, if the\n * identity object was previously used.\n */\nexport function initUnique<T>(identityObj: object, ClassObj: new () => T): T {\n try {\n if (!instanceMap.get(identityObj)) {\n instanceMap.set(identityObj, new ClassObj());\n }\n return instanceMap.get(identityObj)! as T;\n } catch (_e) {\n // --- START Sentry-custom code (try/catch wrapping) ---\n // Fix for cases where identityObj is not a valid key for WeakMap (sometimes a problem in Safari)\n // Just return a new instance without caching it in instanceMap\n return new ClassObj();\n }\n // --- END Sentry-custom code ---\n}\n"],"names":[],"mappings":"AAgBA,MAAM,WAAA,uBAA4C,OAAA,EAAQ;AAOnD,SAAS,UAAA,CAAc,aAAqB,QAAA,EAA0B;AAC3E,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AACjC,MAAA,WAAA,CAAY,GAAA,CAAI,WAAA,EAAa,IAAI,QAAA,EAAU,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,WAAA,CAAY,IAAI,WAAW,CAAA;AAAA,EACpC,SAAS,EAAA,EAAI;AAIX,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEF;;;;"}
1
+ {"version":3,"file":"initUnique.js","sources":["../../../../../src/metrics/web-vitals/lib/initUnique.ts"],"sourcesContent":["/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst instanceMap: WeakMap<object, unknown> = new WeakMap();\n\n/**\n * A function that accepts and identity object and a class object and returns\n * either a new instance of that class or an existing instance, if the\n * identity object was previously used.\n */\nexport function initUnique<T>(identityObj: object, ClassObj: new () => T): T {\n try {\n if (!instanceMap.get(identityObj)) {\n instanceMap.set(identityObj, new ClassObj());\n }\n return instanceMap.get(identityObj)! as T;\n } catch {\n // --- START Sentry-custom code (try/catch wrapping) ---\n // Fix for cases where identityObj is not a valid key for WeakMap (sometimes a problem in Safari)\n // Just return a new instance without caching it in instanceMap\n return new ClassObj();\n }\n // --- END Sentry-custom code ---\n}\n"],"names":[],"mappings":"AAgBA,MAAM,WAAA,uBAA4C,OAAA,EAAQ;AAOnD,SAAS,UAAA,CAAc,aAAqB,QAAA,EAA0B;AAC3E,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,WAAA,CAAY,GAAA,CAAI,WAAW,CAAA,EAAG;AACjC,MAAA,WAAA,CAAY,GAAA,CAAI,WAAA,EAAa,IAAI,QAAA,EAAU,CAAA;AAAA,IAC7C;AACA,IAAA,OAAO,WAAA,CAAY,IAAI,WAAW,CAAA;AAAA,EACpC,CAAA,CAAA,MAAQ;AAIN,IAAA,OAAO,IAAI,QAAA,EAAS;AAAA,EACtB;AAEF;;;;"}
@@ -2,13 +2,12 @@ import { WINDOW } from '../../../types.js';
2
2
  import { addPageListener } from './globalListeners.js';
3
3
 
4
4
  const onHidden = (cb) => {
5
- const onHiddenOrPageHide = (event) => {
6
- if (event.type === "pagehide" || WINDOW.document?.visibilityState === "hidden") {
5
+ const onHiddenCallback = (event) => {
6
+ if (WINDOW.document?.visibilityState === "hidden") {
7
7
  cb(event);
8
8
  }
9
9
  };
10
- addPageListener("visibilitychange", onHiddenOrPageHide, { capture: true, once: true });
11
- addPageListener("pagehide", onHiddenOrPageHide, { capture: true, once: true });
10
+ addPageListener("visibilitychange", onHiddenCallback, { capture: true });
12
11
  };
13
12
 
14
13
  export { onHidden };
@@ -1 +1 @@
1
- {"version":3,"file":"onHidden.js","sources":["../../../../../src/metrics/web-vitals/lib/onHidden.ts"],"sourcesContent":["/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types';\nimport { addPageListener } from './globalListeners';\n\nexport interface OnHiddenCallback {\n (event: Event): void;\n}\n\n/**\n * Sentry-specific change:\n *\n * This function's logic was NOT updated to web-vitals 4.2.4 or 5.x but we continue\n * to use the web-vitals 3.5.2 version due to having stricter browser support.\n *\n * PR with context that made the changes:\n * https://github.com/GoogleChrome/web-vitals/pull/442/files#r1530492402\n *\n * The PR removed listening to the `pagehide` event, in favour of only listening to\n * the `visibilitychange` event. This is \"more correct\" but some browsers we still\n * support (Safari <14.4) don't fully support `visibilitychange` or have known bugs\n * with respect to the `visibilitychange` event.\n *\n * TODO (v11): If we decide to drop support for Safari 14.4, we can use the logic\n * from web-vitals 4.2.4. In this case, we also need to update the integration tests\n * that currently trigger the `pagehide` event to simulate the page being hidden.\n *\n * @param {OnHiddenCallback} cb - Callback to be executed when the page is hidden or unloaded.\n *\n * @deprecated use `whenIdleOrHidden` or `addPageListener('visibilitychange')` instead\n */\nexport const onHidden = (cb: OnHiddenCallback) => {\n const onHiddenOrPageHide = (event: Event) => {\n if (event.type === 'pagehide' || WINDOW.document?.visibilityState === 'hidden') {\n cb(event);\n }\n };\n\n addPageListener('visibilitychange', onHiddenOrPageHide, { capture: true, once: true });\n // Some browsers have buggy implementations of visibilitychange,\n // so we use pagehide in addition, just to be safe.\n addPageListener('pagehide', onHiddenOrPageHide, { capture: true, once: true });\n};\n"],"names":[],"mappings":";;;AA6CO,MAAM,QAAA,GAAW,CAAC,EAAA,KAAyB;AAChD,EAAA,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAAiB;AAC3C,IAAA,IAAI,MAAM,IAAA,KAAS,UAAA,IAAc,MAAA,CAAO,QAAA,EAAU,oBAAoB,QAAA,EAAU;AAC9E,MAAA,EAAA,CAAG,KAAK,CAAA;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,eAAA,CAAgB,oBAAoB,kBAAA,EAAoB,EAAE,SAAS,IAAA,EAAM,IAAA,EAAM,MAAM,CAAA;AAGrF,EAAA,eAAA,CAAgB,YAAY,kBAAA,EAAoB,EAAE,SAAS,IAAA,EAAM,IAAA,EAAM,MAAM,CAAA;AAC/E;;;;"}
1
+ {"version":3,"file":"onHidden.js","sources":["../../../../../src/metrics/web-vitals/lib/onHidden.ts"],"sourcesContent":["/*\n * Copyright 2020 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types';\nimport { addPageListener } from './globalListeners';\n\nexport interface OnHiddenCallback {\n (event: Event): void;\n}\n\n/**\n * Calls the passed callback when the page transitions to hidden.\n *\n * Uses the `visibilitychange` event exclusively, which is well-supported\n * across all modern browsers.\n *\n * @param {OnHiddenCallback} cb - Callback to be executed when the page is hidden.\n *\n * @deprecated use `whenIdleOrHidden` or `addPageListener('visibilitychange')` instead\n */\nexport const onHidden = (cb: OnHiddenCallback) => {\n const onHiddenCallback = (event: Event) => {\n if (WINDOW.document?.visibilityState === 'hidden') {\n cb(event);\n }\n };\n\n addPageListener('visibilitychange', onHiddenCallback, { capture: true });\n};\n"],"names":[],"mappings":";;;AAiCO,MAAM,QAAA,GAAW,CAAC,EAAA,KAAyB;AAChD,EAAA,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAAiB;AACzC,IAAA,IAAI,MAAA,CAAO,QAAA,EAAU,eAAA,KAAoB,QAAA,EAAU;AACjD,MAAA,EAAA,CAAG,KAAK,CAAA;AAAA,IACV;AAAA,EACF,CAAA;AAEA,EAAA,eAAA,CAAgB,kBAAA,EAAoB,gBAAA,EAAkB,EAAE,OAAA,EAAS,MAAM,CAAA;AACzE;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"interactionCountPolyfill.js","sources":["../../../../../../src/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.ts"],"sourcesContent":["/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { observe } from '../observe';\n\ndeclare global {\n interface Performance {\n interactionCount: number;\n }\n}\n\nlet interactionCountEstimate = 0;\nlet minKnownInteractionId = Infinity;\nlet maxKnownInteractionId = 0;\n\nconst updateEstimate = (entries: PerformanceEventTiming[]) => {\n entries.forEach(e => {\n if (e.interactionId) {\n minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId);\n maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId);\n\n interactionCountEstimate = maxKnownInteractionId ? (maxKnownInteractionId - minKnownInteractionId) / 7 + 1 : 0;\n }\n });\n};\n\nlet po: PerformanceObserver | undefined;\n\n/**\n * Returns the `interactionCount` value using the native API (if available)\n * or the polyfill estimate in this module.\n */\nexport const getInteractionCount = (): number => {\n return po ? interactionCountEstimate : performance.interactionCount || 0;\n};\n\n/**\n * Feature detects native support or initializes the polyfill if needed.\n */\nexport const initInteractionCountPolyfill = (): void => {\n if ('interactionCount' in performance || po) return;\n\n po = observe('event', updateEstimate, {\n type: 'event',\n buffered: true,\n durationThreshold: 0,\n } as PerformanceObserverInit);\n};\n"],"names":[],"mappings":";;AAwBA,IAAI,wBAAA,GAA2B,CAAA;AAC/B,IAAI,qBAAA,GAAwB,QAAA;AAC5B,IAAI,qBAAA,GAAwB,CAAA;AAE5B,MAAM,cAAA,GAAiB,CAAC,OAAA,KAAsC;AAC5D,EAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA,KAAK;AACnB,IAAA,IAAI,EAAE,aAAA,EAAe;AACnB,MAAA,qBAAA,GAAwB,IAAA,CAAK,GAAA,CAAI,qBAAA,EAAuB,CAAA,CAAE,aAAa,CAAA;AACvE,MAAA,qBAAA,GAAwB,IAAA,CAAK,GAAA,CAAI,qBAAA,EAAuB,CAAA,CAAE,aAAa,CAAA;AAEvE,MAAA,wBAAA,GAA2B,qBAAA,GAAA,CAAyB,qBAAA,GAAwB,qBAAA,IAAyB,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,IAC/G;AAAA,EACF,CAAC,CAAA;AACH,CAAA;AAEA,IAAI,EAAA;AAMG,MAAM,sBAAsB,MAAc;AAC/C,EAAA,OAAO,EAAA,GAAK,wBAAA,GAA2B,WAAA,CAAY,gBAAA,IAAoB,CAAA;AACzE;AAKO,MAAM,+BAA+B,MAAY;AACtD,EAAA,IAAI,kBAAA,IAAsB,eAAe,EAAA,EAAI;AAE7C,EAAA,EAAA,GAAK,OAAA,CAAQ,SAAS,cAAA,EAAgB;AAAA,IACpC,IAAA,EAAM,OAAA;AAAA,IACN,QAAA,EAAU,IAAA;AAAA,IACV,iBAAA,EAAmB;AAAA,GACO,CAAA;AAC9B;;;;"}
1
+ {"version":3,"file":"interactionCountPolyfill.js","sources":["../../../../../../src/metrics/web-vitals/lib/polyfills/interactionCountPolyfill.ts"],"sourcesContent":["/*\n * Copyright 2022 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { observe } from '../observe';\n\ndeclare global {\n interface Performance {\n readonly interactionCount: number;\n }\n}\n\nlet interactionCountEstimate = 0;\nlet minKnownInteractionId = Infinity;\nlet maxKnownInteractionId = 0;\n\nconst updateEstimate = (entries: PerformanceEventTiming[]) => {\n entries.forEach(e => {\n if (e.interactionId) {\n minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId);\n maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId);\n\n interactionCountEstimate = maxKnownInteractionId ? (maxKnownInteractionId - minKnownInteractionId) / 7 + 1 : 0;\n }\n });\n};\n\nlet po: PerformanceObserver | undefined;\n\n/**\n * Returns the `interactionCount` value using the native API (if available)\n * or the polyfill estimate in this module.\n */\nexport const getInteractionCount = (): number => {\n return po ? interactionCountEstimate : performance.interactionCount || 0;\n};\n\n/**\n * Feature detects native support or initializes the polyfill if needed.\n */\nexport const initInteractionCountPolyfill = (): void => {\n if ('interactionCount' in performance || po) return;\n\n po = observe('event', updateEstimate, {\n type: 'event',\n buffered: true,\n durationThreshold: 0,\n });\n};\n"],"names":[],"mappings":";;AAwBA,IAAI,wBAAA,GAA2B,CAAA;AAC/B,IAAI,qBAAA,GAAwB,QAAA;AAC5B,IAAI,qBAAA,GAAwB,CAAA;AAE5B,MAAM,cAAA,GAAiB,CAAC,OAAA,KAAsC;AAC5D,EAAA,OAAA,CAAQ,QAAQ,CAAA,CAAA,KAAK;AACnB,IAAA,IAAI,EAAE,aAAA,EAAe;AACnB,MAAA,qBAAA,GAAwB,IAAA,CAAK,GAAA,CAAI,qBAAA,EAAuB,CAAA,CAAE,aAAa,CAAA;AACvE,MAAA,qBAAA,GAAwB,IAAA,CAAK,GAAA,CAAI,qBAAA,EAAuB,CAAA,CAAE,aAAa,CAAA;AAEvE,MAAA,wBAAA,GAA2B,qBAAA,GAAA,CAAyB,qBAAA,GAAwB,qBAAA,IAAyB,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,IAC/G;AAAA,EACF,CAAC,CAAA;AACH,CAAA;AAEA,IAAI,EAAA;AAMG,MAAM,sBAAsB,MAAc;AAC/C,EAAA,OAAO,EAAA,GAAK,wBAAA,GAA2B,WAAA,CAAY,gBAAA,IAAoB,CAAA;AACzE;AAKO,MAAM,+BAA+B,MAAY;AACtD,EAAA,IAAI,kBAAA,IAAsB,eAAe,EAAA,EAAI;AAE7C,EAAA,EAAA,GAAK,OAAA,CAAQ,SAAS,cAAA,EAAgB;AAAA,IACpC,IAAA,EAAM,OAAA;AAAA,IACN,QAAA,EAAU,IAAA;AAAA,IACV,iBAAA,EAAmB;AAAA,GACpB,CAAA;AACH;;;;"}
@@ -9,11 +9,9 @@ const whenIdleOrHidden = (cb) => {
9
9
  } else {
10
10
  cb = runOnce(cb);
11
11
  addPageListener("visibilitychange", cb, { once: true, capture: true });
12
- addPageListener("pagehide", cb, { once: true, capture: true });
13
12
  rIC(() => {
14
13
  cb();
15
14
  removePageListener("visibilitychange", cb, { capture: true });
16
- removePageListener("pagehide", cb, { capture: true });
17
15
  });
18
16
  }
19
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"whenIdleOrHidden.js","sources":["../../../../../src/metrics/web-vitals/lib/whenIdleOrHidden.ts"],"sourcesContent":["/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types.js';\nimport { addPageListener, removePageListener } from './globalListeners.js';\nimport { runOnce } from './runOnce.js';\n\n/**\n * Runs the passed callback during the next idle period, or immediately\n * if the browser's visibility state is (or becomes) hidden.\n */\nexport const whenIdleOrHidden = (cb: () => void) => {\n const rIC = WINDOW.requestIdleCallback || WINDOW.setTimeout;\n\n // If the document is hidden, run the callback immediately, otherwise\n // race an idle callback with the next `visibilitychange` event.\n if (WINDOW.document?.visibilityState === 'hidden') {\n cb();\n } else {\n // eslint-disable-next-line no-param-reassign\n cb = runOnce(cb);\n addPageListener('visibilitychange', cb, { once: true, capture: true });\n // sentry: we use pagehide instead of directly listening to visibilitychange\n // because some browsers we still support (Safari <14.4) don't fully support\n // `visibilitychange` or have known bugs w.r.t the `visibilitychange` event.\n // TODO(v11): remove this once we drop support for Safari <14.4\n addPageListener('pagehide', cb, { once: true, capture: true });\n rIC(() => {\n cb();\n // Remove the above event listener since no longer required.\n // See: https://github.com/GoogleChrome/web-vitals/issues/622\n removePageListener('visibilitychange', cb, { capture: true });\n // TODO(v11): remove this once we drop support for Safari <14.4\n removePageListener('pagehide', cb, { capture: true });\n });\n }\n};\n"],"names":[],"mappings":";;;;AAwBO,MAAM,gBAAA,GAAmB,CAAC,EAAA,KAAmB;AAClD,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,mBAAA,IAAuB,MAAA,CAAO,UAAA;AAIjD,EAAA,IAAI,MAAA,CAAO,QAAA,EAAU,eAAA,KAAoB,QAAA,EAAU;AACjD,IAAA,EAAA,EAAG;AAAA,EACL,CAAA,MAAO;AAEL,IAAA,EAAA,GAAK,QAAQ,EAAE,CAAA;AACf,IAAA,eAAA,CAAgB,oBAAoB,EAAA,EAAI,EAAE,MAAM,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAKrE,IAAA,eAAA,CAAgB,YAAY,EAAA,EAAI,EAAE,MAAM,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAC7D,IAAA,GAAA,CAAI,MAAM;AACR,MAAA,EAAA,EAAG;AAGH,MAAA,kBAAA,CAAmB,kBAAA,EAAoB,EAAA,EAAI,EAAE,OAAA,EAAS,MAAM,CAAA;AAE5D,MAAA,kBAAA,CAAmB,UAAA,EAAY,EAAA,EAAI,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IACtD,CAAC,CAAA;AAAA,EACH;AACF;;;;"}
1
+ {"version":3,"file":"whenIdleOrHidden.js","sources":["../../../../../src/metrics/web-vitals/lib/whenIdleOrHidden.ts"],"sourcesContent":["/*\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { WINDOW } from '../../../types.js';\nimport { addPageListener, removePageListener } from './globalListeners.js';\nimport { runOnce } from './runOnce.js';\n\n/**\n * Runs the passed callback during the next idle period, or immediately\n * if the browser's visibility state is (or becomes) hidden.\n */\nexport const whenIdleOrHidden = (cb: () => void) => {\n const rIC = WINDOW.requestIdleCallback || WINDOW.setTimeout;\n\n // If the document is hidden, run the callback immediately, otherwise\n // race an idle callback with the next `visibilitychange` event.\n if (WINDOW.document?.visibilityState === 'hidden') {\n cb();\n } else {\n // eslint-disable-next-line no-param-reassign\n cb = runOnce(cb);\n addPageListener('visibilitychange', cb, { once: true, capture: true });\n rIC(() => {\n cb();\n // Remove the above event listener since no longer required.\n // See: https://github.com/GoogleChrome/web-vitals/issues/622\n removePageListener('visibilitychange', cb, { capture: true });\n });\n }\n};\n"],"names":[],"mappings":";;;;AAwBO,MAAM,gBAAA,GAAmB,CAAC,EAAA,KAAmB;AAClD,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,mBAAA,IAAuB,MAAA,CAAO,UAAA;AAIjD,EAAA,IAAI,MAAA,CAAO,QAAA,EAAU,eAAA,KAAoB,QAAA,EAAU;AACjD,IAAA,EAAA,EAAG;AAAA,EACL,CAAA,MAAO;AAEL,IAAA,EAAA,GAAK,QAAQ,EAAE,CAAA;AACf,IAAA,eAAA,CAAgB,oBAAoB,EAAA,EAAI,EAAE,MAAM,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AACrE,IAAA,GAAA,CAAI,MAAM;AACR,MAAA,EAAA,EAAG;AAGH,MAAA,kBAAA,CAAmB,kBAAA,EAAoB,EAAA,EAAI,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IAC9D,CAAC,CAAA;AAAA,EACH;AACF;;;;"}
@@ -1,4 +1,4 @@
1
- import { browserPerformanceTimeOrigin, debug, timestampInSeconds, getCurrentScope, spanToStreamedSpanJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, startInactiveSpan, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getActiveSpan, getRootSpan } from '@sentry/core';
1
+ import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, debug, timestampInSeconds, getCurrentScope, spanToStreamedSpanJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, startInactiveSpan, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getClient, getActiveSpan, getRootSpan } from '@sentry/core';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
3
  import { htmlTreeAsString } from '../htmlTreeAsString.js';
4
4
  import { WINDOW } from '../types.js';
@@ -19,7 +19,8 @@ function _emitWebVitalSpan(options) {
19
19
  parentSpan,
20
20
  reportEvent,
21
21
  startTime,
22
- endTime
22
+ endTime,
23
+ standalone
23
24
  } = options;
24
25
  const routeName = getCurrentScope().getScopeData().transactionName;
25
26
  const attributes = {
@@ -40,19 +41,32 @@ function _emitWebVitalSpan(options) {
40
41
  if (reportEvent) {
41
42
  attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent;
42
43
  }
44
+ if (standalone) {
45
+ Object.assign(attributes, getReplayAttributes());
46
+ }
43
47
  const span = startInactiveSpan({
44
48
  name,
45
49
  attributes,
46
50
  startTime,
47
- // if we have a pageload span, we let the web vital span start as its parent. This ensures that
48
- // it is not started as a segment span, without having to manually set it to a "standalone" v2 span
49
- // that has `segment: false` but no actual parent span.
50
- parentSpan
51
+ parentSpan,
52
+ // oxlint-disable-next-line typescript/no-deprecated -- intentional during the v1/v2 transition; see the TODO(standalone) above
53
+ experimental: standalone ? { standalone: true } : void 0
51
54
  });
52
55
  if (span) {
53
56
  span.end(endTime ?? startTime);
54
57
  }
55
58
  }
59
+ function getReplayAttributes() {
60
+ const replay = getClient()?.getIntegrationByName("Replay");
61
+ const replayId = replay?.getReplayId(true);
62
+ if (!replayId) {
63
+ return {};
64
+ }
65
+ return {
66
+ "sentry.replay_id": replayId,
67
+ "sentry._internal.replay_is_buffering": replay.getRecordingMode() === "buffer" ? true : void 0
68
+ };
69
+ }
56
70
  function trackLcpAsSpan(client) {
57
71
  let lcpValue = 0;
58
72
  let lcpEntry;
@@ -142,11 +156,12 @@ function _sendClsSpan(clsValue, entry, pageloadSpan, reportEvent) {
142
156
  startTime
143
157
  });
144
158
  }
145
- function trackInpAsSpan() {
159
+ function trackInpAsSpan(client) {
146
160
  const performance = getBrowserPerformanceAPI();
147
161
  if (!performance || !browserPerformanceTimeOrigin()) {
148
162
  return;
149
163
  }
164
+ const standalone = !hasSpanStreamingEnabled(client);
150
165
  const onInp = ({ metric }) => {
151
166
  if (metric.value == null) {
152
167
  return;
@@ -159,11 +174,11 @@ function trackInpAsSpan() {
159
174
  if (!entry) {
160
175
  return;
161
176
  }
162
- _sendInpSpan(metric.value, entry);
177
+ _sendInpSpan(metric.value, entry, standalone);
163
178
  };
164
179
  addInpInstrumentationHandler(onInp);
165
180
  }
166
- function _sendInpSpan(inpValue, entry) {
181
+ function _sendInpSpan(inpValue, entry, standalone = false) {
167
182
  DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);
168
183
  const startTime = msToSec(browserPerformanceTimeOrigin() + entry.startTime);
169
184
  const duration = msToSec(inpValue);
@@ -188,7 +203,8 @@ function _sendInpSpan(inpValue, entry) {
188
203
  },
189
204
  startTime,
190
205
  endTime: startTime + duration,
191
- parentSpan: spanToUse
206
+ parentSpan: spanToUse,
207
+ standalone
192
208
  });
193
209
  }
194
210
 
@@ -1 +1 @@
1
- {"version":3,"file":"webVitalSpans.js","sources":["../../../src/metrics/webVitalSpans.ts"],"sourcesContent":["import type { Client, Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getActiveSpan,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToStreamedSpanJSON,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { WINDOW } from '../types';\nimport { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION } from './inp';\nimport type { InstrumentationHandlerCallback } from './instrument';\nimport { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from './instrument';\nimport { isValidLcpMetric } from './lcp';\nimport type { WebVitalReportEvent } from './utils';\nimport { getBrowserPerformanceAPI, listenForWebVitalReportEvents, msToSec, supportsWebVital } from './utils';\nimport type { PerformanceEventTiming } from './instrument';\nimport { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes';\n\n// Locally-defined interfaces to avoid leaking bare global type references into the\n// generated .d.ts. The `declare global` augmentations in web-vitals/types.ts make these\n// available during this package's compilation but are NOT carried to consumers.\n// This mirrors the pattern used for PerformanceEventTiming in instrument.ts.\nexport interface LayoutShift extends PerformanceEntry {\n value: number;\n sources: Array<{ node: Node | null }>;\n hadRecentInput: boolean;\n}\n\nexport interface LargestContentfulPaint extends PerformanceEntry {\n readonly renderTime: DOMHighResTimeStamp;\n readonly loadTime: DOMHighResTimeStamp;\n readonly size: number;\n readonly id: string;\n readonly url: string;\n readonly element: Element | null;\n}\n\ninterface WebVitalSpanOptions {\n name: string;\n op: string;\n origin: string;\n metricName: 'lcp' | 'cls' | 'inp';\n value: number;\n attributes?: SpanAttributes;\n parentSpan?: Span;\n reportEvent?: WebVitalReportEvent;\n startTime: number;\n endTime?: number;\n}\n\n/**\n * Emits a web vital span that flows through the span streaming pipeline.\n */\nexport function _emitWebVitalSpan(options: WebVitalSpanOptions): void {\n const {\n name,\n op,\n origin,\n metricName,\n value,\n attributes: passedAttributes,\n parentSpan,\n reportEvent,\n startTime,\n endTime,\n } = options;\n\n const routeName = getCurrentScope().getScopeData().transactionName;\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: 0,\n [`browser.web_vital.${metricName}.value`]: value,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n // Web vital score calculation relies on the user agent\n 'user_agent.original': WINDOW.navigator?.userAgent,\n ...passedAttributes,\n };\n\n if (parentSpan && spanToStreamedSpanJSON(parentSpan).attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'pageload') {\n // for LCP and CLS, we collect the pageload span id as an attribute\n attributes['sentry.pageload.span_id'] = parentSpan.spanContext().spanId;\n }\n\n if (reportEvent) {\n attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent;\n }\n\n const span = startInactiveSpan({\n name,\n attributes,\n startTime,\n // if we have a pageload span, we let the web vital span start as its parent. This ensures that\n // it is not started as a segment span, without having to manually set it to a \"standalone\" v2 span\n // that has `segment: false` but no actual parent span.\n parentSpan: parentSpan,\n });\n\n if (span) {\n span.end(endTime ?? startTime);\n }\n}\n\n/**\n * Tracks LCP as a streamed span.\n */\nexport function trackLcpAsSpan(client: Client): void {\n let lcpValue = 0;\n let lcpEntry: LargestContentfulPaint | undefined;\n\n if (!supportsWebVital('largest-contentful-paint')) {\n return;\n }\n\n const cleanupLcpHandler = addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LargestContentfulPaint | undefined;\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n lcpValue = metric.value;\n lcpEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, reportEvent);\n cleanupLcpHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendLcpSpan(\n lcpValue: number,\n entry: LargestContentfulPaint | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n if (!isValidLcpMetric(lcpValue)) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`Sending LCP span (${lcpValue})`);\n\n const performanceTimeOrigin = browserPerformanceTimeOrigin() || 0;\n const timeOrigin = msToSec(performanceTimeOrigin);\n const endTime = msToSec(performanceTimeOrigin + (entry?.startTime || 0));\n const name = entry ? htmlTreeAsString(entry.element) : 'Largest contentful paint';\n\n const attributes: SpanAttributes = {};\n\n entry?.element && (attributes['browser.web_vital.lcp.element'] = htmlTreeAsString(entry.element));\n entry?.id && (attributes['browser.web_vital.lcp.id'] = entry.id);\n entry?.url && (attributes['browser.web_vital.lcp.url'] = entry.url);\n entry?.loadTime != null && (attributes['browser.web_vital.lcp.load_time'] = entry.loadTime);\n entry?.renderTime != null && (attributes['browser.web_vital.lcp.render_time'] = entry.renderTime);\n entry?.size != null && (attributes['browser.web_vital.lcp.size'] = entry.size);\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.lcp',\n origin: 'auto.http.browser.lcp',\n metricName: 'lcp',\n value: lcpValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime: timeOrigin,\n endTime,\n });\n}\n\n/**\n * Tracks CLS as a streamed span.\n */\nexport function trackClsAsSpan(client: Client): void {\n let clsValue = 0;\n let clsEntry: 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 clsValue = metric.value;\n clsEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendClsSpan(clsValue, clsEntry, pageloadSpan, reportEvent);\n cleanupClsHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendClsSpan(\n clsValue: number,\n entry: LayoutShift | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const startTime = entry ? msToSec((browserPerformanceTimeOrigin() || 0) + entry.startTime) : timestampInSeconds();\n const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : 'Layout shift';\n\n const attributes: SpanAttributes = {};\n\n if (entry?.sources) {\n entry.sources.forEach((source, index) => {\n attributes[`browser.web_vital.cls.source.${index + 1}`] = htmlTreeAsString(source.node);\n });\n }\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.cls',\n origin: 'auto.http.browser.cls',\n metricName: 'cls',\n value: clsValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime,\n });\n}\n\n/**\n * Tracks INP as a streamed span.\n *\n * This mirrors the standalone INP tracking logic (`startTrackingINP`) but emits\n * spans through the streaming pipeline instead of as standalone spans.\n * Requires `registerInpInteractionListener()` to be called separately for\n * cached element names and root spans per interaction.\n */\nexport function trackInpAsSpan(): void {\n const performance = getBrowserPerformanceAPI();\n if (!performance || !browserPerformanceTimeOrigin()) {\n return;\n }\n\n const onInp: InstrumentationHandlerCallback = ({ metric }) => {\n if (metric.value == null) {\n return;\n }\n\n const duration = msToSec(metric.value);\n\n if (duration > MAX_PLAUSIBLE_INP_DURATION) {\n return;\n }\n\n const entry = metric.entries.find(e => e.duration === metric.value && INP_ENTRY_MAP[e.name]);\n\n if (!entry) {\n return;\n }\n\n _sendInpSpan(metric.value, entry);\n };\n\n addInpInstrumentationHandler(onInp);\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming): void {\n DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(inpValue);\n const interactionType = INP_ENTRY_MAP[entry.name];\n\n const cachedContext = getCachedInteractionContext(entry.interactionId);\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const spanToUse = cachedContext?.span || rootSpan;\n const routeName = spanToUse\n ? spanToStreamedSpanJSON(spanToUse).name\n : getCurrentScope().getScopeData().transactionName;\n const name = cachedContext?.elementName || htmlTreeAsString(entry.target);\n\n _emitWebVitalSpan({\n name,\n op: `ui.interaction.${interactionType}`,\n origin: 'auto.http.browser.inp',\n metricName: 'inp',\n value: inpValue,\n attributes: {\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry.duration,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n },\n startTime,\n endTime: startTime + duration,\n parentSpan: spanToUse,\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"webVitalSpans.js","sources":["../../../src/metrics/webVitalSpans.ts"],"sourcesContent":["import type { Client, Integration, Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getRootSpan,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToStreamedSpanJSON,\n startInactiveSpan,\n timestampInSeconds,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { WINDOW } from '../types';\nimport { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION } from './inp';\nimport type { InstrumentationHandlerCallback } from './instrument';\nimport { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from './instrument';\nimport { isValidLcpMetric } from './lcp';\nimport type { WebVitalReportEvent } from './utils';\nimport { getBrowserPerformanceAPI, listenForWebVitalReportEvents, msToSec, supportsWebVital } from './utils';\nimport type { PerformanceEventTiming } from './instrument';\nimport { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes';\n\n// Locally-defined interfaces to avoid leaking bare global type references into the\n// generated .d.ts. The `declare global` augmentations in web-vitals/types.ts make these\n// available during this package's compilation but are NOT carried to consumers.\n// This mirrors the pattern used for PerformanceEventTiming in instrument.ts.\nexport interface LayoutShift extends PerformanceEntry {\n value: number;\n sources: Array<{ node: Node | null }>;\n hadRecentInput: boolean;\n}\n\nexport interface LargestContentfulPaint extends PerformanceEntry {\n readonly renderTime: DOMHighResTimeStamp;\n readonly loadTime: DOMHighResTimeStamp;\n readonly size: number;\n readonly id: string;\n readonly url: string;\n readonly element: Element | null;\n}\n\ninterface WebVitalSpanOptions {\n name: string;\n op: string;\n origin: string;\n metricName: 'lcp' | 'cls' | 'inp';\n value: number;\n attributes?: SpanAttributes;\n parentSpan?: Span;\n reportEvent?: WebVitalReportEvent;\n startTime: number;\n endTime?: number;\n /**\n * When `true`, the span is sent on its own as a v2 streamed span instead of being folded into a\n * transaction. Used for INP when span streaming is disabled (it reports late, so it can't ride\n * the pageload transaction).\n *\n * TODO(standalone): remove once the static (transaction) trace lifecycle is dropped and INP always streams.\n */\n standalone?: boolean;\n}\n\n/**\n * Emits a web vital span. When `standalone` is set it is sent on its own as a v2 streamed span;\n * otherwise it flows through the span streaming pipeline as a child of `parentSpan`.\n */\nexport function _emitWebVitalSpan(options: WebVitalSpanOptions): void {\n const {\n name,\n op,\n origin,\n metricName,\n value,\n attributes: passedAttributes,\n parentSpan,\n reportEvent,\n startTime,\n endTime,\n standalone,\n } = options;\n\n const routeName = getCurrentScope().getScopeData().transactionName;\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: 0,\n [`browser.web_vital.${metricName}.value`]: value,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n // Web vital score calculation relies on the user agent\n 'user_agent.original': WINDOW.navigator?.userAgent,\n ...passedAttributes,\n };\n\n if (parentSpan && spanToStreamedSpanJSON(parentSpan).attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === 'pageload') {\n // for LCP and CLS, we collect the pageload span id as an attribute\n attributes['sentry.pageload.span_id'] = parentSpan.spanContext().spanId;\n }\n\n if (reportEvent) {\n attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent;\n }\n\n // A standalone span is sent as a plain v2 span without running the `processSpan` hooks (see\n // `captureStandaloneSpanWithStaticCallback`), so Replay can't attach the replay id itself. Set it\n // here, mirroring Replay's `processSpan`, so INP keeps its replay association like it did on v1.\n // TODO(standalone): remove once the static (transaction) trace lifecycle is dropped and INP always\n // streams, at which point Replay's `processSpan` runs and attaches the replay id.\n if (standalone) {\n Object.assign(attributes, getReplayAttributes());\n }\n\n const span = startInactiveSpan({\n name,\n attributes,\n startTime,\n parentSpan,\n // oxlint-disable-next-line typescript/no-deprecated -- intentional during the v1/v2 transition; see the TODO(standalone) above\n experimental: standalone ? { standalone: true } : undefined,\n });\n\n if (span) {\n span.end(endTime ?? startTime);\n }\n}\n\ninterface ReplayIntegration extends Integration {\n getReplayId: (onlyIfSampled?: boolean) => string | undefined;\n getRecordingMode: () => 'session' | 'buffer' | undefined;\n}\n\n// TODO(standalone): remove once the static (transaction) trace lifecycle is dropped; Replay's\n// `processSpan` then attaches the replay id to the streamed INP span instead.\nfunction getReplayAttributes(): SpanAttributes {\n const replay = getClient()?.getIntegrationByName<ReplayIntegration>('Replay');\n const replayId = replay?.getReplayId(true);\n if (!replayId) {\n return {};\n }\n\n return {\n 'sentry.replay_id': replayId,\n 'sentry._internal.replay_is_buffering': replay!.getRecordingMode() === 'buffer' ? true : undefined,\n };\n}\n\n/**\n * Tracks LCP as a streamed span.\n */\nexport function trackLcpAsSpan(client: Client): void {\n let lcpValue = 0;\n let lcpEntry: LargestContentfulPaint | undefined;\n\n if (!supportsWebVital('largest-contentful-paint')) {\n return;\n }\n\n const cleanupLcpHandler = addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LargestContentfulPaint | undefined;\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n lcpValue = metric.value;\n lcpEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, reportEvent);\n cleanupLcpHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendLcpSpan(\n lcpValue: number,\n entry: LargestContentfulPaint | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n if (!isValidLcpMetric(lcpValue)) {\n return;\n }\n\n DEBUG_BUILD && debug.log(`Sending LCP span (${lcpValue})`);\n\n const performanceTimeOrigin = browserPerformanceTimeOrigin() || 0;\n const timeOrigin = msToSec(performanceTimeOrigin);\n const endTime = msToSec(performanceTimeOrigin + (entry?.startTime || 0));\n const name = entry ? htmlTreeAsString(entry.element) : 'Largest contentful paint';\n\n const attributes: SpanAttributes = {};\n\n entry?.element && (attributes['browser.web_vital.lcp.element'] = htmlTreeAsString(entry.element));\n entry?.id && (attributes['browser.web_vital.lcp.id'] = entry.id);\n entry?.url && (attributes['browser.web_vital.lcp.url'] = entry.url);\n entry?.loadTime != null && (attributes['browser.web_vital.lcp.load_time'] = entry.loadTime);\n entry?.renderTime != null && (attributes['browser.web_vital.lcp.render_time'] = entry.renderTime);\n entry?.size != null && (attributes['browser.web_vital.lcp.size'] = entry.size);\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.lcp',\n origin: 'auto.http.browser.lcp',\n metricName: 'lcp',\n value: lcpValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime: timeOrigin,\n endTime,\n });\n}\n\n/**\n * Tracks CLS as a streamed span.\n */\nexport function trackClsAsSpan(client: Client): void {\n let clsValue = 0;\n let clsEntry: 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 clsValue = metric.value;\n clsEntry = entry;\n }, true);\n\n listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {\n _sendClsSpan(clsValue, clsEntry, pageloadSpan, reportEvent);\n cleanupClsHandler();\n });\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendClsSpan(\n clsValue: number,\n entry: LayoutShift | undefined,\n pageloadSpan?: Span,\n reportEvent?: WebVitalReportEvent,\n): void {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const startTime = entry ? msToSec((browserPerformanceTimeOrigin() || 0) + entry.startTime) : timestampInSeconds();\n const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : 'Layout shift';\n\n const attributes: SpanAttributes = {};\n\n if (entry?.sources) {\n entry.sources.forEach((source, index) => {\n attributes[`browser.web_vital.cls.source.${index + 1}`] = htmlTreeAsString(source.node);\n });\n }\n\n _emitWebVitalSpan({\n name,\n op: 'ui.webvital.cls',\n origin: 'auto.http.browser.cls',\n metricName: 'cls',\n value: clsValue,\n attributes,\n parentSpan: pageloadSpan,\n reportEvent,\n startTime,\n });\n}\n\n/**\n * Tracks INP and emits it as a web vital span, as a child of the interaction's root span.\n * Requires `registerInpInteractionListener()` to be called separately for cached element names and\n * root spans per interaction.\n */\nexport function trackInpAsSpan(client: Client): void {\n const performance = getBrowserPerformanceAPI();\n if (!performance || !browserPerformanceTimeOrigin()) {\n return;\n }\n\n // INP reports late (on pagehide, after the pageload span has ended). With span streaming enabled\n // it rides the streaming pipeline. With streaming disabled it would be dropped as a late span, so\n // it is emitted as its own standalone v2 span instead (see `_emitWebVitalSpan`), overriding the\n // static trace lifecycle for INP only.\n // TODO(standalone): once the static trace lifecycle is dropped, INP always streams; drop this flag.\n const standalone = !hasSpanStreamingEnabled(client);\n\n const onInp: InstrumentationHandlerCallback = ({ metric }) => {\n if (metric.value == null) {\n return;\n }\n\n const duration = msToSec(metric.value);\n\n if (duration > MAX_PLAUSIBLE_INP_DURATION) {\n return;\n }\n\n const entry = metric.entries.find(e => e.duration === metric.value && INP_ENTRY_MAP[e.name]);\n\n if (!entry) {\n return;\n }\n\n _sendInpSpan(metric.value, entry, standalone);\n };\n\n addInpInstrumentationHandler(onInp);\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming, standalone = false): void {\n DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(inpValue);\n const interactionType = INP_ENTRY_MAP[entry.name];\n\n const cachedContext = getCachedInteractionContext(entry.interactionId);\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n const spanToUse = cachedContext?.span || rootSpan;\n const routeName = spanToUse\n ? spanToStreamedSpanJSON(spanToUse).name\n : getCurrentScope().getScopeData().transactionName;\n const name = cachedContext?.elementName || htmlTreeAsString(entry.target);\n\n _emitWebVitalSpan({\n name,\n op: `ui.interaction.${interactionType}`,\n origin: 'auto.http.browser.inp',\n metricName: 'inp',\n value: inpValue,\n attributes: {\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry.duration,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: routeName,\n [SENTRY_SEGMENT_NAME]: routeName,\n },\n startTime,\n endTime: startTime + duration,\n parentSpan: spanToUse,\n standalone,\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"type":"module","version":"10.69.0","sideEffects":false}
1
+ {"type":"module","version":"11.0.0-alpha.0","sideEffects":false}
@@ -1,6 +1,7 @@
1
1
  export { addPerformanceInstrumentationHandler, addClsInstrumentationHandler, addTtfbInstrumentationHandler, addLcpInstrumentationHandler, addInpInstrumentationHandler, } from './metrics/instrument';
2
- export { addPerformanceEntries, addWebVitalsToSpan, startTrackingInteractions, startTrackingLongTasks, startTrackingLongAnimationFrames, startTrackingWebVitals, startTrackingINP, registerInpInteractionListener, } from './metrics/browserMetrics';
2
+ export { addPerformanceEntries, addWebVitalsToSpan, startTrackingInteractions, startTrackingLongTasks, startTrackingLongAnimationFrames, startTrackingWebVitals, registerInpInteractionListener, } from './metrics/browserMetrics';
3
3
  export { elementTimingIntegration, startTrackingElementTiming } from './metrics/elementTiming';
4
+ export { userTimingIntegration } from './metrics/userTiming';
4
5
  export { extractNetworkProtocol } from './metrics/utils';
5
6
  export { trackClsAsSpan, trackInpAsSpan, trackLcpAsSpan } from './metrics/webVitalSpans';
6
7
  export { whenIdleOrHidden } from './metrics/web-vitals/lib/whenIdleOrHidden';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oCAAoC,EACpC,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,gCAAgC,EAEhC,sBAAsB,EACtB,gBAAgB,EAChB,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAE7E,OAAO,EAAE,sCAAsC,EAAE,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAElH,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEnH,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oCAAoC,EACpC,4BAA4B,EAC5B,6BAA6B,EAC7B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,gCAAgC,EAEhC,sBAAsB,EACtB,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,wBAAwB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAE7E,OAAO,EAAE,sCAAsC,EAAE,MAAM,kBAAkB,CAAC;AAE1E,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAExE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,yBAAyB,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAElH,OAAO,EAAE,4BAA4B,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAEnH,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAE1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,YAAY,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC"}
@@ -1,27 +1,16 @@
1
1
  import type { Client, Span, SpanAttributes } from '@sentry/core';
2
2
  interface StartTrackingWebVitalsOptions {
3
- /**
4
- * When `true`, CLS is tracked as a standalone span. When `false`, CLS is
5
- * recorded as a measurement on the pageload span. When `undefined`, CLS
6
- * tracking is skipped entirely (e.g. because span streaming handles it).
7
- */
8
- recordClsStandaloneSpans: boolean | undefined;
9
- /**
10
- * When `true`, LCP is tracked as a standalone span. When `false`, LCP is
11
- * recorded as a measurement on the pageload span. When `undefined`, LCP
12
- * tracking is skipped entirely (e.g. because span streaming handles it).
13
- */
14
- recordLcpStandaloneSpans: boolean | undefined;
3
+ trackCls: boolean;
4
+ trackLcp: boolean;
15
5
  client: Client;
16
6
  }
17
7
  /**
18
8
  * Start tracking web vitals.
19
9
  * The callback returned by this function can be used to stop tracking & ensure all measurements are final & captured.
20
10
  *
21
- * @deprecated this function will be removed and streamlined once we stop supporting standalone v1
22
11
  * @returns A function that forces web vitals collection
23
12
  */
24
- export declare function startTrackingWebVitals({ recordClsStandaloneSpans, recordLcpStandaloneSpans, client, }: StartTrackingWebVitalsOptions): () => void;
13
+ export declare function startTrackingWebVitals({ trackCls, trackLcp }: StartTrackingWebVitalsOptions): () => void;
25
14
  /**
26
15
  * Start tracking long tasks.
27
16
  */
@@ -34,22 +23,14 @@ export declare function startTrackingLongAnimationFrames(): void;
34
23
  * Start tracking interaction events.
35
24
  */
36
25
  export declare function startTrackingInteractions(): void;
37
- export { registerInpInteractionListener, startTrackingINP } from './inp';
26
+ export { registerInpInteractionListener } from './inp';
38
27
  interface AddPerformanceEntriesOptions {
39
28
  /**
40
29
  * Resource spans with `op`s matching strings in the array will not be emitted.
41
30
  *
42
31
  * Default: []
43
32
  */
44
- ignoreResourceSpans: Array<'resouce.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;
45
- /**
46
- * Performance spans created from browser Performance APIs,
47
- * `performance.mark(...)` nand `performance.measure(...)`
48
- * with `name`s matching strings in the array will not be emitted.
49
- *
50
- * Default: []
51
- */
52
- ignorePerformanceApiSpans: Array<string | RegExp>;
33
+ ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;
53
34
  /**
54
35
  * Whether span streaming is enabled.
55
36
  */
@@ -88,11 +69,6 @@ export declare function addPerformanceEntries(span: Span, options: AddPerformanc
88
69
  * doesn't leak into a subsequent navigation.
89
70
  */
90
71
  export declare function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOptions): void;
91
- /**
92
- * Create measure related spans.
93
- * Exported only for tests.
94
- */
95
- export declare function _addMeasureSpans(span: Span, entry: PerformanceEntry, startTime: number, duration: number, timeOrigin: number, ignorePerformanceApiSpans: AddPerformanceEntriesOptions['ignorePerformanceApiSpans']): void;
96
72
  /**
97
73
  * Instrument navigation entries
98
74
  * exported only for tests
@@ -1 +1 @@
1
- {"version":3,"file":"browserMetrics.d.ts","sourceRoot":"","sources":["../../../src/metrics/browserMetrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAgB,IAAI,EAAE,cAAc,EAAwC,MAAM,cAAc,CAAC;AA6ErH,UAAU,6BAA6B;IACrC;;;;OAIG;IACH,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9C;;;;OAIG;IACH,wBAAwB,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,wBAAwB,EACxB,wBAAwB,EACxB,MAAM,GACP,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAgC5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA8B7C;AAED;;GAEG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAsDvD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CA6BhD;AAED,OAAO,EAAE,8BAA8B,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AA0DzE,UAAU,4BAA4B;IACpC;;;;OAIG;IACH,mBAAmB,EAAE,KAAK,CAAC,gBAAgB,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,MAAM,CAAC,CAAC;IAE3G;;;;;;OAMG;IACH,yBAAyB,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAElD;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,UAAU,yBAAyB;IACjC;;;;;;OAMG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;;;;;OAMG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,4BAA4B,GAAG,IAAI,CA4D7F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAmEvF;AA0BD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,yBAAyB,EAAE,4BAA4B,CAAC,2BAA2B,CAAC,GACnF,IAAI,CA+CN;AA8CD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,2BAA2B,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAS5G;AAmFD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,yBAAyB,EAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,sBAAsB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GACrC,IAAI,CAuDN;AAgGD,KAAK,kCAAkC,GACnC,sBAAsB,GACtB,cAAc,GAKd,gBAAgB,CAAC;AAErB;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,kCAAkC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAChH,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,EAAE,MAAM,CAAC,EAAE,GAC3F,IAAI,CAUN"}
1
+ {"version":3,"file":"browserMetrics.d.ts","sourceRoot":"","sources":["../../../src/metrics/browserMetrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAgB,IAAI,EAAE,cAAc,EAAoB,MAAM,cAAc,CAAC;AA4EjG,UAAU,6BAA6B;IACrC,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,6BAA6B,GAAG,MAAM,IAAI,CAiBxG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA8B7C;AAED;;GAEG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAsDvD;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CA6BhD;AAED,OAAO,EAAE,8BAA8B,EAAE,MAAM,OAAO,CAAC;AA0DvD,UAAU,4BAA4B;IACpC;;;;OAIG;IACH,mBAAmB,EAAE,KAAK,CAAC,iBAAiB,GAAG,cAAc,GAAG,cAAc,GAAG,gBAAgB,GAAG,MAAM,CAAC,CAAC;IAE5G;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,UAAU,yBAAyB;IACjC;;;;;;OAMG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;;;;;OAMG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,4BAA4B,GAAG,IAAI,CA0D7F;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,yBAAyB,GAAG,IAAI,CAiEvF;AA2BD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,2BAA2B,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAW5G;AAmFD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,yBAAyB,EAChC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,sBAAsB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,GACrC,IAAI,CAuDN;AAgGD,KAAK,kCAAkC,GACnC,sBAAsB,GACtB,cAAc,GAKd,gBAAgB,CAAC;AAErB;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,kCAAkC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,EAChH,UAAU,EAAE,cAAc,EAC1B,UAAU,EAAE,CAAC,MAAM,yBAAyB,GAAG,kCAAkC,EAAE,MAAM,CAAC,EAAE,GAC3F,IAAI,CAUN"}
@@ -1,5 +1,4 @@
1
1
  import type { Span } from '@sentry/core';
2
- import type { InstrumentationHandlerCallback } from './instrument';
3
2
  interface InteractionContext {
4
3
  span: Span | undefined;
5
4
  elementName: string;
@@ -9,19 +8,7 @@ interface InteractionContext {
9
8
  * (source: Me)
10
9
  */
11
10
  export declare const MAX_PLAUSIBLE_INP_DURATION = 60;
12
- /**
13
- * Start tracking INP webvital events.
14
- */
15
- export declare function startTrackingINP(): () => void;
16
11
  export declare const INP_ENTRY_MAP: Record<string, 'click' | 'hover' | 'drag' | 'press'>;
17
- /** Starts tracking the Interaction to Next Paint on the current page. #
18
- * exported only for testing
19
- */
20
- export declare function _trackINP(): () => void;
21
- /**
22
- * exported only for testing
23
- */
24
- export declare const _onInp: InstrumentationHandlerCallback;
25
12
  /**
26
13
  * Look up a cached interaction context (element name + root span) by interactionId.
27
14
  * Returns undefined if no context was cached for this interaction.
@@ -1 +1 @@
1
- {"version":3,"file":"inp.d.ts","sourceRoot":"","sources":["../../../src/metrics/inp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAkB,MAAM,cAAc,CAAC;AAgBzD,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAQnE,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAC7C;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,IAAI,CAW7C;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CA2B9E,CAAC;AAEF;;GAEG;AACH,wBAAgB,SAAS,IAAI,MAAM,IAAI,CAEtC;AAED;;GAEG;AACH,eAAO,MAAM,MAAM,EAAE,8BA4DpB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAE7G;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CA6FrD"}
1
+ {"version":3,"file":"inp.d.ts","sourceRoot":"","sources":["../../../src/metrics/inp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAMzC,UAAU,kBAAkB;IAC1B,IAAI,EAAE,IAAI,GAAG,SAAS,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CA2B9E,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAE7G;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CA6FrD"}