@sentry/browser-utils 11.0.0-rc.0 → 11.0.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 (51) hide show
  1. package/build/cjs/instrumentation/performanceObserver.js.map +1 -1
  2. package/build/cjs/performance/entries.js +33 -22
  3. package/build/cjs/performance/entries.js.map +1 -1
  4. package/build/cjs/performance/interactions.js +38 -11
  5. package/build/cjs/performance/interactions.js.map +1 -1
  6. package/build/cjs/web-vitals/emitSpan.js +1 -14
  7. package/build/cjs/web-vitals/emitSpan.js.map +1 -1
  8. package/build/cjs/web-vitals/inp.js +1 -0
  9. package/build/cjs/web-vitals/inp.js.map +1 -1
  10. package/build/cjs/web-vitals/reportEvents.js +4 -4
  11. package/build/cjs/web-vitals/reportEvents.js.map +1 -1
  12. package/build/cjs/web-vitals/softNavs.js +25 -5
  13. package/build/cjs/web-vitals/softNavs.js.map +1 -1
  14. package/build/cjs/web-vitals/spans.js +61 -29
  15. package/build/cjs/web-vitals/spans.js.map +1 -1
  16. package/build/cjs/web-vitals/tracking.js +7 -0
  17. package/build/cjs/web-vitals/tracking.js.map +1 -1
  18. package/build/esm/instrumentation/performanceObserver.js.map +1 -1
  19. package/build/esm/package.json +1 -1
  20. package/build/esm/performance/entries.js +35 -25
  21. package/build/esm/performance/entries.js.map +1 -1
  22. package/build/esm/performance/interactions.js +40 -13
  23. package/build/esm/performance/interactions.js.map +1 -1
  24. package/build/esm/web-vitals/emitSpan.js +1 -14
  25. package/build/esm/web-vitals/emitSpan.js.map +1 -1
  26. package/build/esm/web-vitals/inp.js +1 -1
  27. package/build/esm/web-vitals/inp.js.map +1 -1
  28. package/build/esm/web-vitals/reportEvents.js +4 -4
  29. package/build/esm/web-vitals/reportEvents.js.map +1 -1
  30. package/build/esm/web-vitals/softNavs.js +25 -5
  31. package/build/esm/web-vitals/softNavs.js.map +1 -1
  32. package/build/esm/web-vitals/spans.js +54 -22
  33. package/build/esm/web-vitals/spans.js.map +1 -1
  34. package/build/esm/web-vitals/tracking.js +8 -1
  35. package/build/esm/web-vitals/tracking.js.map +1 -1
  36. package/build/types/instrumentation/performanceObserver.d.ts +1 -2
  37. package/build/types/instrumentation/performanceObserver.d.ts.map +1 -1
  38. package/build/types/performance/entries.d.ts +6 -1
  39. package/build/types/performance/entries.d.ts.map +1 -1
  40. package/build/types/performance/interactions.d.ts.map +1 -1
  41. package/build/types/web-vitals/emitSpan.d.ts +0 -2
  42. package/build/types/web-vitals/emitSpan.d.ts.map +1 -1
  43. package/build/types/web-vitals/inp.d.ts +2 -0
  44. package/build/types/web-vitals/inp.d.ts.map +1 -1
  45. package/build/types/web-vitals/reportEvents.d.ts +4 -7
  46. package/build/types/web-vitals/reportEvents.d.ts.map +1 -1
  47. package/build/types/web-vitals/softNavs.d.ts.map +1 -1
  48. package/build/types/web-vitals/spans.d.ts +2 -3
  49. package/build/types/web-vitals/spans.d.ts.map +1 -1
  50. package/build/types/web-vitals/tracking.d.ts.map +1 -1
  51. package/package.json +2 -2
@@ -1,9 +1,10 @@
1
- import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, debug, timestampInSeconds, getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME } from '@sentry/core';
1
+ import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, debug, getClient, timestampInSeconds, getActiveSpan, getRootSpan, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK, UI_INTERACTION_PRESS_SPAN_NAME_FALLBACK, UI_INTERACTION_DRAG_SPAN_NAME_FALLBACK, UI_INTERACTION_HOVER_SPAN_NAME_FALLBACK, UI_INTERACTION_CLICK_SPAN_NAME_FALLBACK, UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK } from '@sentry/core';
2
2
  import { DEBUG_BUILD } from '../debug-build.js';
3
3
  import { htmlTreeAsString } from '../htmlTreeAsString.js';
4
- import { MAX_PLAUSIBLE_INP_DURATION, INP_ENTRY_MAP, getCachedInteractionContext } from './inp.js';
4
+ import { getComponentName } from '../component-name.js';
5
+ import { MAX_PLAUSIBLE_INP_DURATION, INP_ENTRY_MAP, getCachedInteractionContext, UNKNOWN_ELEMENT_NAME } from './inp.js';
5
6
  import { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from '../instrumentation/performanceObserver.js';
6
- import { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes';
7
+ import { BROWSER_NAVIGATION_TYPE, UI_COMPONENT_NAME } from '@sentry/conventions/attributes';
7
8
  import { _emitWebVitalSpan } from './emitSpan.js';
8
9
  import { isValidLcpMetric } from './lcp.js';
9
10
  import { listenForWebVitalReportEvents } from './reportEvents.js';
@@ -17,6 +18,12 @@ const INTERACTION_TYPE_TO_SPAN_OP = {
17
18
  drag: UI_INTERACTION_DRAG,
18
19
  press: UI_INTERACTION_PRESS
19
20
  };
21
+ const INTERACTION_TYPE_TO_SPAN_NAME_FALLBACK = {
22
+ click: UI_INTERACTION_CLICK_SPAN_NAME_FALLBACK,
23
+ hover: UI_INTERACTION_HOVER_SPAN_NAME_FALLBACK,
24
+ drag: UI_INTERACTION_DRAG_SPAN_NAME_FALLBACK,
25
+ press: UI_INTERACTION_PRESS_SPAN_NAME_FALLBACK
26
+ };
20
27
  function trackWebVitalPerNavigation(client, addInstrumentationHandler, send) {
21
28
  let pageloadSpan;
22
29
  client.on("afterStartPageLoadSpan", (span) => {
@@ -25,7 +32,7 @@ function trackWebVitalPerNavigation(client, addInstrumentationHandler, send) {
25
32
  let bfcacheNavigationSpan;
26
33
  client.on("spanStart", (span) => {
27
34
  const attributes = spanToJSON(span).attributes;
28
- if (attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === NAVIGATION && attributes[BROWSER_NAVIGATION_TYPE] === "bfcache") {
35
+ if (attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === NAVIGATION && attributes[BROWSER_NAVIGATION_TYPE] === "back-forward-cache") {
29
36
  bfcacheNavigationSpan = span;
30
37
  }
31
38
  });
@@ -57,7 +64,6 @@ function trackLcpAsSpan(client, perNavigation = false) {
57
64
  metric.value,
58
65
  entry,
59
66
  parentSpan,
60
- void 0,
61
67
  softNavigationId,
62
68
  metric.navigationType,
63
69
  metric.navigationStartTime
@@ -77,12 +83,12 @@ function trackLcpAsSpan(client, perNavigation = false) {
77
83
  lcpValue = metric.value;
78
84
  lcpEntry = entry;
79
85
  }, true);
80
- listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {
81
- _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, reportEvent, void 0, lcpNavigationType);
86
+ listenForWebVitalReportEvents(client, (pageloadSpan) => {
87
+ _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, void 0, lcpNavigationType);
82
88
  cleanupLcpHandler();
83
89
  });
84
90
  }
85
- function _sendLcpSpan(lcpValue, entry, pageloadSpan, reportEvent, softNavigationId, navigationType, navigationStartTime) {
91
+ function _sendLcpSpan(lcpValue, entry, pageloadSpan, softNavigationId, navigationType, navigationStartTime) {
86
92
  if (!isValidLcpMetric(lcpValue)) {
87
93
  return;
88
94
  }
@@ -90,9 +96,18 @@ function _sendLcpSpan(lcpValue, entry, pageloadSpan, reportEvent, softNavigation
90
96
  const performanceTimeOrigin = browserPerformanceTimeOrigin() || 0;
91
97
  const startTime = msToSec(performanceTimeOrigin + (navigationStartTime || 0));
92
98
  const endTime = entry ? msToSec(performanceTimeOrigin + entry.startTime) : startTime + msToSec(lcpValue);
93
- const name = entry ? htmlTreeAsString(entry.element) : "Largest contentful paint";
99
+ const selector = entry ? htmlTreeAsString(entry.element) : void 0;
100
+ const componentName = entry?.element ? getComponentName(entry.element) : null;
101
+ const client = getClient();
102
+ const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);
103
+ const name = hasSpanStreaming ? componentName || UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK : selector ?? UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK;
94
104
  const attributes = {};
95
- entry?.element && (attributes["browser.web_vital.lcp.element"] = htmlTreeAsString(entry.element));
105
+ if (selector) {
106
+ attributes["browser.web_vital.lcp.element"] = selector;
107
+ }
108
+ if (componentName) {
109
+ attributes[UI_COMPONENT_NAME] = componentName;
110
+ }
96
111
  entry?.id && (attributes["browser.web_vital.lcp.id"] = entry.id);
97
112
  entry?.url && (attributes["browser.web_vital.lcp.url"] = entry.url);
98
113
  entry?.loadTime != null && (attributes["browser.web_vital.lcp.load_time"] = entry.loadTime);
@@ -106,7 +121,6 @@ function _sendLcpSpan(lcpValue, entry, pageloadSpan, reportEvent, softNavigation
106
121
  value: lcpValue,
107
122
  attributes,
108
123
  parentSpan: pageloadSpan,
109
- reportEvent,
110
124
  startTime,
111
125
  endTime,
112
126
  softNavigationId,
@@ -124,7 +138,6 @@ function trackClsAsSpan(client, perNavigation = false) {
124
138
  metric.value,
125
139
  entry,
126
140
  parentSpan,
127
- void 0,
128
141
  softNavigationId,
129
142
  metric.navigationType,
130
143
  metric.navigationStartTime
@@ -144,18 +157,26 @@ function trackClsAsSpan(client, perNavigation = false) {
144
157
  clsValue = metric.value;
145
158
  clsEntry = entry;
146
159
  }, true);
147
- listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => {
148
- _sendClsSpan(clsValue, clsEntry, pageloadSpan, reportEvent, void 0, clsNavigationType);
160
+ listenForWebVitalReportEvents(client, (pageloadSpan) => {
161
+ _sendClsSpan(clsValue, clsEntry, pageloadSpan, void 0, clsNavigationType);
149
162
  cleanupClsHandler();
150
163
  });
151
164
  }
152
- function _sendClsSpan(clsValue, entry, pageloadSpan, reportEvent, softNavigationId, navigationType, navigationStartTime) {
165
+ function _sendClsSpan(clsValue, entry, pageloadSpan, softNavigationId, navigationType, navigationStartTime) {
153
166
  DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);
154
167
  const performanceTimeOrigin = browserPerformanceTimeOrigin();
155
168
  const offset = entry?.startTime ?? navigationStartTime ?? 0;
156
169
  const startTime = performanceTimeOrigin ? msToSec(performanceTimeOrigin + offset) : timestampInSeconds();
157
- const name = entry ? htmlTreeAsString(entry.sources[0]?.node) : "Layout shift";
170
+ const firstSourceNode = entry?.sources[0]?.node;
171
+ const selector = entry ? htmlTreeAsString(firstSourceNode) : void 0;
172
+ const componentName = firstSourceNode ? getComponentName(firstSourceNode) : null;
173
+ const client = getClient();
174
+ const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);
175
+ const name = hasSpanStreaming ? componentName || UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK : selector ?? UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK;
158
176
  const attributes = {};
177
+ if (componentName) {
178
+ attributes[UI_COMPONENT_NAME] = componentName;
179
+ }
159
180
  if (entry?.sources) {
160
181
  entry.sources.forEach((source, index) => {
161
182
  attributes[`browser.web_vital.cls.source.${index + 1}`] = htmlTreeAsString(source.node);
@@ -169,7 +190,6 @@ function _sendClsSpan(clsValue, entry, pageloadSpan, reportEvent, softNavigation
169
190
  value: clsValue,
170
191
  attributes,
171
192
  parentSpan: pageloadSpan,
172
- reportEvent,
173
193
  startTime,
174
194
  softNavigationId,
175
195
  navigationType
@@ -208,21 +228,33 @@ function _sendInpSpan(inpValue, entry, standalone = false, attributedSpan, softN
208
228
  browserPerformanceTimeOrigin() + (entry?.startTime ?? metric?.navigationStartTime ?? 0)
209
229
  );
210
230
  const duration = msToSec(inpValue);
211
- const interactionType = entry && INP_ENTRY_MAP[entry.name] || "click";
231
+ const entryInteractionType = entry && INP_ENTRY_MAP[entry.name];
232
+ const interactionType = entryInteractionType || "click";
212
233
  const cachedContext = entry && getCachedInteractionContext(entry.interactionId);
213
234
  const activeSpan = getActiveSpan();
214
235
  const rootSpan = activeSpan ? getRootSpan(activeSpan) : void 0;
215
236
  const spanToUse = attributedSpan || cachedContext?.span || rootSpan;
216
- const name = cachedContext?.elementName || (entry ? htmlTreeAsString(entry.target) : "Interaction to next paint");
237
+ const selector = cachedContext?.elementName || (entry ? htmlTreeAsString(entry.target) : void 0);
238
+ const componentName = entry?.target ? getComponentName(entry.target) : null;
239
+ const client = getClient();
240
+ const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);
241
+ const fallbackName = INTERACTION_TYPE_TO_SPAN_NAME_FALLBACK[interactionType];
242
+ const name = hasSpanStreaming ? componentName || fallbackName : selector ?? "Interaction to next paint";
243
+ const attributes = {
244
+ [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry?.duration ?? inpValue
245
+ };
246
+ selector && selector !== UNKNOWN_ELEMENT_NAME && (attributes["browser.web_vital.inp.target"] = selector);
247
+ entryInteractionType && (attributes["browser.web_vital.inp.interaction_type"] = entryInteractionType);
248
+ if (componentName) {
249
+ attributes[UI_COMPONENT_NAME] = componentName;
250
+ }
217
251
  _emitWebVitalSpan({
218
252
  name,
219
253
  op: INTERACTION_TYPE_TO_SPAN_OP[interactionType],
220
254
  origin: "auto.http.browser.inp",
221
255
  metricName: "inp",
222
256
  value: inpValue,
223
- attributes: {
224
- [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry?.duration ?? inpValue
225
- },
257
+ attributes,
226
258
  startTime,
227
259
  endTime: startTime + duration,
228
260
  navigationType: metric?.navigationType,
@@ -1 +1 @@
1
- {"version":3,"file":"spans.js","sources":["../../../src/web-vitals/spans.ts"],"sourcesContent":["import type { Client, Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getActiveSpan,\n getRootSpan,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n timestampInSeconds,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport type { InteractionType } from './inp';\nimport { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION } from './inp';\nimport type { InstrumentationHandlerCallback, MetricNavigationType } from '../instrumentation/performanceObserver';\nimport {\n addClsInstrumentationHandler,\n addInpInstrumentationHandler,\n addLcpInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport type { LargestContentfulPaint, LayoutShift } from './emitSpan';\nimport { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes';\nimport { _emitWebVitalSpan } from './emitSpan';\nimport { isValidLcpMetric } from './lcp';\nimport type { WebVitalReportEvent } from './reportEvents';\nimport { listenForWebVitalReportEvents } from './reportEvents';\nimport { getNavigationSpanForMetric } from './softNavs';\nimport { getBrowserPerformanceAPI, msToSec, supportsWebVital } from '../performance/utils';\nimport type { PerformanceEventTiming } from '../instrumentation/performanceObserver';\nimport {\n NAVIGATION,\n UI_INTERACTION_CLICK,\n UI_INTERACTION_DRAG,\n UI_INTERACTION_HOVER,\n UI_INTERACTION_PRESS,\n UI_WEBVITAL_CLS,\n UI_WEBVITAL_LCP,\n} from '@sentry/conventions/op';\n\nconst INTERACTION_TYPE_TO_SPAN_OP: Record<InteractionType, string> = {\n click: UI_INTERACTION_CLICK,\n hover: UI_INTERACTION_HOVER,\n drag: UI_INTERACTION_DRAG,\n press: UI_INTERACTION_PRESS,\n};\n\ntype WebVitalMetric = Parameters<Parameters<typeof addLcpInstrumentationHandler>[0]>[0]['metric'];\ntype InpMetric = Parameters<InstrumentationHandlerCallback>[0]['metric'];\n\n/**\n * Reports a web vital once per navigation, rather than once per page load.\n *\n * web-vitals restarts the metric on every soft navigation and force-reports the previous one just\n * before it does (and again on pagehide), and re-reports every metric after a bfcache restore.\n * Since `reportAllChanges` is off in this mode, every value we're handed is already the final one\n * for its navigation, so there is nothing to accumulate: each report is a span.\n */\nfunction trackWebVitalPerNavigation<M extends WebVitalMetric>(\n client: Client,\n addInstrumentationHandler: (callback: (data: { metric: M }) => void) => unknown,\n send: (metric: M, parentSpan: Span | undefined, softNavigationId: number | undefined) => void,\n): void {\n let pageloadSpan: Span | undefined;\n client.on('afterStartPageLoadSpan', span => {\n pageloadSpan = span;\n });\n\n // Remembered when the restore happens rather than read back at report time: the restore\n // navigation span is an idle span, and CLS and INP are only finalized on pagehide, by which point\n // it has long ended and is no longer what is active.\n let bfcacheNavigationSpan: Span | undefined;\n client.on('spanStart', span => {\n // The op has to be checked too: the web vital spans emitted for a restore carry the same\n // `bfcache` navigation type, so matching on that alone lets the first of them replace the\n // navigation span, and every later vital then hangs off a sibling vital instead.\n const attributes = spanToJSON(span).attributes;\n if (\n attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === NAVIGATION &&\n attributes[BROWSER_NAVIGATION_TYPE] === 'bfcache'\n ) {\n bfcacheNavigationSpan = span;\n }\n });\n\n addInstrumentationHandler(({ metric }) => {\n const navigationSpan = getNavigationSpanForMetric(metric);\n if (metric.navigationType === 'soft-navigation') {\n // Reporting an uncorrelated soft navigation vital would attribute it to the wrong route, so\n // it's dropped instead.\n if (navigationSpan) {\n send(metric, navigationSpan, metric.navigationId);\n } else {\n DEBUG_BUILD &&\n debug.log(`[SoftNav] Dropping ${metric.name} for uncorrelated soft navigation ${metric.navigationId}`);\n }\n return;\n }\n\n if (metric.navigationType === 'back-forward-cache') {\n // A restore reuses the frozen document, so the pageload span above belongs to the page view\n // from before the freeze. The navigation span started for the restore is the page view these\n // values were actually measured on.\n send(metric, bfcacheNavigationSpan, undefined);\n return;\n }\n\n send(metric, pageloadSpan, undefined);\n });\n}\n\n/**\n * Tracks LCP as a streamed span.\n */\nexport function trackLcpAsSpan(client: Client, perNavigation = false): void {\n if (!supportsWebVital('largest-contentful-paint')) {\n return;\n }\n\n if (perNavigation) {\n trackWebVitalPerNavigation(client, addLcpInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n const entry = metric.entries[metric.entries.length - 1] as LargestContentfulPaint | undefined;\n _sendLcpSpan(\n metric.value,\n entry,\n parentSpan,\n undefined,\n softNavigationId,\n metric.navigationType,\n metric.navigationStartTime,\n );\n });\n return;\n }\n\n let lcpValue = 0;\n let lcpEntry: LargestContentfulPaint | undefined;\n let lcpNavigationType: MetricNavigationType | undefined;\n\n const cleanupLcpHandler = addLcpInstrumentationHandler(({ metric }) => {\n // The navigation type describes the page, not the entry, so it is worth keeping even for a\n // report we otherwise discard.\n lcpNavigationType = metric.navigationType;\n\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, undefined, lcpNavigationType);\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 softNavigationId?: number,\n navigationType?: MetricNavigationType,\n navigationStartTime?: number,\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 // A soft navigation's LCP is measured from the triggering interaction, not the document time\n // origin. Starting the span there too keeps it inside the navigation span it is parented to and\n // keeps its duration equal to the value it reports.\n const startTime = msToSec(performanceTimeOrigin + (navigationStartTime || 0));\n // Without an entry there is no render time to end at, so the span lasts the value it reports,\n // like an entry-less INP does. Ending at the time origin instead would invert the span.\n const endTime = entry ? msToSec(performanceTimeOrigin + entry.startTime) : startTime + msToSec(lcpValue);\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,\n endTime,\n softNavigationId,\n navigationType,\n });\n}\n\n/**\n * Tracks CLS as a streamed span.\n */\nexport function trackClsAsSpan(client: Client, perNavigation = false): void {\n if (!supportsWebVital('layout-shift')) {\n return;\n }\n\n if (perNavigation) {\n trackWebVitalPerNavigation(client, addClsInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n _sendClsSpan(\n metric.value,\n entry,\n parentSpan,\n undefined,\n softNavigationId,\n metric.navigationType,\n metric.navigationStartTime,\n );\n });\n return;\n }\n\n let clsValue = 0;\n let clsEntry: LayoutShift | undefined;\n let clsNavigationType: MetricNavigationType | undefined;\n\n const cleanupClsHandler = addClsInstrumentationHandler(({ metric }) => {\n // A CLS of 0 is reported with no entries and still emits a span, so the navigation type has to\n // be captured before the entry check rather than alongside the value.\n clsNavigationType = metric.navigationType;\n\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, undefined, clsNavigationType);\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 softNavigationId?: number,\n navigationType?: MetricNavigationType,\n navigationStartTime?: number,\n): void {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const performanceTimeOrigin = browserPerformanceTimeOrigin();\n // A CLS of 0 has no shift to place the span at. It is reported when the navigation it was\n // measured on is already over - the next soft navigation, or pagehide - so the current time would\n // land it outside that navigation, on the route that follows it.\n const offset = entry?.startTime ?? navigationStartTime ?? 0;\n const startTime = performanceTimeOrigin ? msToSec(performanceTimeOrigin + offset) : 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 softNavigationId,\n navigationType,\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, perNavigation = false): 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 if (perNavigation) {\n // INP restarts per navigation and reports once that navigation is over, by which point the\n // navigation span has ended and the interaction cache no longer knows about it. The metric\n // says which navigation it belongs to, so INP is attributed exactly like LCP and CLS.\n trackWebVitalPerNavigation(client, addInpInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n if (isPlausibleInp(metric)) {\n _sendInpSpan(metric.value, findInpEntry(metric), standalone, parentSpan, softNavigationId, metric);\n }\n });\n return;\n }\n\n const onInp: InstrumentationHandlerCallback = ({ metric }) => {\n if (isPlausibleInp(metric)) {\n _sendInpSpan(metric.value, findInpEntry(metric), standalone, undefined, undefined, metric);\n }\n };\n\n addInpInstrumentationHandler(onInp);\n}\n\nfunction isPlausibleInp(metric: InpMetric): boolean {\n return metric.value != null && msToSec(metric.value) <= MAX_PLAUSIBLE_INP_DURATION;\n}\n\n/**\n * The entry an INP span is built from: the one whose duration the reported value came from.\n *\n * There isn't always one. When every interaction of a soft navigation stayed below the Event Timing\n * threshold, web-vitals reports a synthetic value with no entries at all - see\n * `_estimateP98LongestInteraction`. The span still gets reported in that case, just without the\n * element and interaction type an entry would have supplied.\n */\nfunction findInpEntry(metric: InpMetric): PerformanceEventTiming | undefined {\n return metric.entries.find(e => e.duration === metric.value && INP_ENTRY_MAP[e.name]);\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendInpSpan(\n inpValue: number,\n entry: PerformanceEventTiming | undefined,\n standalone = false,\n attributedSpan?: Span,\n softNavigationId?: number,\n metric?: InpMetric,\n): void {\n DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);\n\n // A web vital span carries the metric, not a real interaction timing, so an INP without an entry\n // is still worth reporting. It just has no element or interaction type to describe, and is placed\n // at the start of the navigation it belongs to rather than at the interaction.\n const startTime = msToSec(\n (browserPerformanceTimeOrigin() as number) + (entry?.startTime ?? metric?.navigationStartTime ?? 0),\n );\n const duration = msToSec(inpValue);\n // An INP without an entry has no interaction type to report. It still has to land inside the\n // `ui.interaction.*` family, because falling outside it would hide exactly the fast navigations\n // that web-vitals synthesizes these values for (GoogleChrome/web-vitals#724), reintroducing the\n // reporting bias they were added to remove.\n const interactionType = (entry && INP_ENTRY_MAP[entry.name]) || 'click';\n\n const cachedContext = entry && getCachedInteractionContext(entry.interactionId);\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n // With soft navigations the caller knows exactly which navigation the metric belongs to. Without\n // them we fall back to the span that was active when the interaction was observed.\n const spanToUse = attributedSpan || cachedContext?.span || rootSpan;\n const name = cachedContext?.elementName || (entry ? htmlTreeAsString(entry.target) : 'Interaction to next paint');\n\n _emitWebVitalSpan({\n name,\n op: INTERACTION_TYPE_TO_SPAN_OP[interactionType],\n origin: 'auto.http.browser.inp',\n metricName: 'inp',\n value: inpValue,\n attributes: {\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry?.duration ?? inpValue,\n },\n startTime,\n endTime: startTime + duration,\n navigationType: metric?.navigationType,\n parentSpan: spanToUse,\n standalone,\n softNavigationId,\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spans.js","sources":["../../../src/web-vitals/spans.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, Span, SpanAttributes } from '@sentry/core';\nimport {\n browserPerformanceTimeOrigin,\n debug,\n getActiveSpan,\n getClient,\n getRootSpan,\n hasSpanStreamingEnabled,\n SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n spanToJSON,\n timestampInSeconds,\n UI_INTERACTION_CLICK_SPAN_NAME_FALLBACK,\n UI_INTERACTION_DRAG_SPAN_NAME_FALLBACK,\n UI_INTERACTION_HOVER_SPAN_NAME_FALLBACK,\n UI_INTERACTION_PRESS_SPAN_NAME_FALLBACK,\n UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK,\n UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport { getComponentName } from '../component-name';\nimport type { InteractionType } from './inp';\nimport { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION, UNKNOWN_ELEMENT_NAME } from './inp';\nimport type { InstrumentationHandlerCallback, MetricNavigationType } from '../instrumentation/performanceObserver';\nimport {\n addClsInstrumentationHandler,\n addInpInstrumentationHandler,\n addLcpInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport type { LargestContentfulPaint, LayoutShift } from './emitSpan';\nimport { BROWSER_NAVIGATION_TYPE, UI_COMPONENT_NAME } from '@sentry/conventions/attributes';\nimport { _emitWebVitalSpan } from './emitSpan';\nimport { isValidLcpMetric } from './lcp';\nimport { listenForWebVitalReportEvents } from './reportEvents';\nimport { getNavigationSpanForMetric } from './softNavs';\nimport { getBrowserPerformanceAPI, msToSec, supportsWebVital } from '../performance/utils';\nimport type { PerformanceEventTiming } from '../instrumentation/performanceObserver';\nimport {\n NAVIGATION,\n UI_INTERACTION_CLICK,\n UI_INTERACTION_DRAG,\n UI_INTERACTION_HOVER,\n UI_INTERACTION_PRESS,\n UI_WEBVITAL_CLS,\n UI_WEBVITAL_LCP,\n} from '@sentry/conventions/op';\n\nconst INTERACTION_TYPE_TO_SPAN_OP: Record<InteractionType, string> = {\n click: UI_INTERACTION_CLICK,\n hover: UI_INTERACTION_HOVER,\n drag: UI_INTERACTION_DRAG,\n press: UI_INTERACTION_PRESS,\n};\n\nconst INTERACTION_TYPE_TO_SPAN_NAME_FALLBACK: Record<InteractionType, string> = {\n click: UI_INTERACTION_CLICK_SPAN_NAME_FALLBACK,\n hover: UI_INTERACTION_HOVER_SPAN_NAME_FALLBACK,\n drag: UI_INTERACTION_DRAG_SPAN_NAME_FALLBACK,\n press: UI_INTERACTION_PRESS_SPAN_NAME_FALLBACK,\n};\n\ntype WebVitalMetric = Parameters<Parameters<typeof addLcpInstrumentationHandler>[0]>[0]['metric'];\ntype InpMetric = Parameters<InstrumentationHandlerCallback>[0]['metric'];\n\n/**\n * Reports a web vital once per navigation, rather than once per page load.\n *\n * web-vitals restarts the metric on every soft navigation and force-reports the previous one just\n * before it does (and again on pagehide), and re-reports every metric after a bfcache restore.\n * Since `reportAllChanges` is off in this mode, every value we're handed is already the final one\n * for its navigation, so there is nothing to accumulate: each report is a span.\n */\nfunction trackWebVitalPerNavigation<M extends WebVitalMetric>(\n client: Client,\n addInstrumentationHandler: (callback: (data: { metric: M }) => void) => unknown,\n send: (metric: M, parentSpan: Span | undefined, softNavigationId: number | undefined) => void,\n): void {\n let pageloadSpan: Span | undefined;\n client.on('afterStartPageLoadSpan', span => {\n pageloadSpan = span;\n });\n\n // Remembered when the restore happens rather than read back at report time: the restore\n // navigation span is an idle span, and CLS and INP are only finalized on pagehide, by which point\n // it has long ended and is no longer what is active.\n let bfcacheNavigationSpan: Span | undefined;\n client.on('spanStart', span => {\n // The op has to be checked too: the web vital spans emitted for a restore carry the same\n // `back-forward-cache` navigation type, so matching on that alone lets the first of them replace the\n // navigation span, and every later vital then hangs off a sibling vital instead.\n const attributes = spanToJSON(span).attributes;\n if (\n attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === NAVIGATION &&\n attributes[BROWSER_NAVIGATION_TYPE] === 'back-forward-cache'\n ) {\n bfcacheNavigationSpan = span;\n }\n });\n\n addInstrumentationHandler(({ metric }) => {\n const navigationSpan = getNavigationSpanForMetric(metric);\n if (metric.navigationType === 'soft-navigation') {\n // Reporting an uncorrelated soft navigation vital would attribute it to the wrong route, so\n // it's dropped instead.\n if (navigationSpan) {\n send(metric, navigationSpan, metric.navigationId);\n } else {\n DEBUG_BUILD &&\n debug.log(`[SoftNav] Dropping ${metric.name} for uncorrelated soft navigation ${metric.navigationId}`);\n }\n return;\n }\n\n if (metric.navigationType === 'back-forward-cache') {\n // A restore reuses the frozen document, so the pageload span above belongs to the page view\n // from before the freeze. The navigation span started for the restore is the page view these\n // values were actually measured on.\n send(metric, bfcacheNavigationSpan, undefined);\n return;\n }\n\n send(metric, pageloadSpan, undefined);\n });\n}\n\n/**\n * Tracks LCP as a streamed span.\n */\nexport function trackLcpAsSpan(client: Client, perNavigation = false): void {\n if (!supportsWebVital('largest-contentful-paint')) {\n return;\n }\n\n if (perNavigation) {\n trackWebVitalPerNavigation(client, addLcpInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n const entry = metric.entries[metric.entries.length - 1] as LargestContentfulPaint | undefined;\n _sendLcpSpan(\n metric.value,\n entry,\n parentSpan,\n softNavigationId,\n metric.navigationType,\n metric.navigationStartTime,\n );\n });\n return;\n }\n\n let lcpValue = 0;\n let lcpEntry: LargestContentfulPaint | undefined;\n let lcpNavigationType: MetricNavigationType | undefined;\n\n const cleanupLcpHandler = addLcpInstrumentationHandler(({ metric }) => {\n // The navigation type describes the page, not the entry, so it is worth keeping even for a\n // report we otherwise discard.\n lcpNavigationType = metric.navigationType;\n\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, pageloadSpan => {\n _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, undefined, lcpNavigationType);\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 softNavigationId?: number,\n navigationType?: MetricNavigationType,\n navigationStartTime?: number,\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 // A soft navigation's LCP is measured from the triggering interaction, not the document time\n // origin. Starting the span there too keeps it inside the navigation span it is parented to and\n // keeps its duration equal to the value it reports.\n const startTime = msToSec(performanceTimeOrigin + (navigationStartTime || 0));\n // Without an entry there is no render time to end at, so the span lasts the value it reports,\n // like an entry-less INP does. Ending at the time origin instead would invert the span.\n const endTime = entry ? msToSec(performanceTimeOrigin + entry.startTime) : startTime + msToSec(lcpValue);\n const selector = entry ? htmlTreeAsString(entry.element) : undefined;\n const componentName = entry?.element ? getComponentName(entry.element) : null;\n const client = getClient();\n const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);\n const name = hasSpanStreaming\n ? componentName || UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK\n : (selector ?? UI_WEBVITAL_LCP_SPAN_NAME_FALLBACK);\n\n const attributes: SpanAttributes = {};\n\n if (selector) {\n attributes['browser.web_vital.lcp.element'] = selector;\n }\n if (componentName) {\n attributes[UI_COMPONENT_NAME] = componentName;\n }\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 startTime,\n endTime,\n softNavigationId,\n navigationType,\n });\n}\n\n/**\n * Tracks CLS as a streamed span.\n */\nexport function trackClsAsSpan(client: Client, perNavigation = false): void {\n if (!supportsWebVital('layout-shift')) {\n return;\n }\n\n if (perNavigation) {\n trackWebVitalPerNavigation(client, addClsInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n _sendClsSpan(\n metric.value,\n entry,\n parentSpan,\n softNavigationId,\n metric.navigationType,\n metric.navigationStartTime,\n );\n });\n return;\n }\n\n let clsValue = 0;\n let clsEntry: LayoutShift | undefined;\n let clsNavigationType: MetricNavigationType | undefined;\n\n const cleanupClsHandler = addClsInstrumentationHandler(({ metric }) => {\n // A CLS of 0 is reported with no entries and still emits a span, so the navigation type has to\n // be captured before the entry check rather than alongside the value.\n clsNavigationType = metric.navigationType;\n\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, pageloadSpan => {\n _sendClsSpan(clsValue, clsEntry, pageloadSpan, undefined, clsNavigationType);\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 softNavigationId?: number,\n navigationType?: MetricNavigationType,\n navigationStartTime?: number,\n): void {\n DEBUG_BUILD && debug.log(`Sending CLS span (${clsValue})`);\n\n const performanceTimeOrigin = browserPerformanceTimeOrigin();\n // A CLS of 0 has no shift to place the span at. It is reported when the navigation it was\n // measured on is already over - the next soft navigation, or pagehide - so the current time would\n // land it outside that navigation, on the route that follows it.\n const offset = entry?.startTime ?? navigationStartTime ?? 0;\n const startTime = performanceTimeOrigin ? msToSec(performanceTimeOrigin + offset) : timestampInSeconds();\n const firstSourceNode = entry?.sources[0]?.node;\n const selector = entry ? htmlTreeAsString(firstSourceNode) : undefined;\n const componentName = firstSourceNode ? getComponentName(firstSourceNode) : null;\n const client = getClient();\n const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);\n const name = hasSpanStreaming\n ? componentName || UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK\n : (selector ?? UI_WEBVITAL_CLS_SPAN_NAME_FALLBACK);\n\n const attributes: SpanAttributes = {};\n\n if (componentName) {\n attributes[UI_COMPONENT_NAME] = componentName;\n }\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 startTime,\n softNavigationId,\n navigationType,\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, perNavigation = false): 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 if (perNavigation) {\n // INP restarts per navigation and reports once that navigation is over, by which point the\n // navigation span has ended and the interaction cache no longer knows about it. The metric\n // says which navigation it belongs to, so INP is attributed exactly like LCP and CLS.\n trackWebVitalPerNavigation(client, addInpInstrumentationHandler, (metric, parentSpan, softNavigationId) => {\n if (isPlausibleInp(metric)) {\n _sendInpSpan(metric.value, findInpEntry(metric), standalone, parentSpan, softNavigationId, metric);\n }\n });\n return;\n }\n\n const onInp: InstrumentationHandlerCallback = ({ metric }) => {\n if (isPlausibleInp(metric)) {\n _sendInpSpan(metric.value, findInpEntry(metric), standalone, undefined, undefined, metric);\n }\n };\n\n addInpInstrumentationHandler(onInp);\n}\n\nfunction isPlausibleInp(metric: InpMetric): boolean {\n return metric.value != null && msToSec(metric.value) <= MAX_PLAUSIBLE_INP_DURATION;\n}\n\n/**\n * The entry an INP span is built from: the one whose duration the reported value came from.\n *\n * There isn't always one. When every interaction of a soft navigation stayed below the Event Timing\n * threshold, web-vitals reports a synthetic value with no entries at all - see\n * `_estimateP98LongestInteraction`. The span still gets reported in that case, just without the\n * element and interaction type an entry would have supplied.\n */\nfunction findInpEntry(metric: InpMetric): PerformanceEventTiming | undefined {\n return metric.entries.find(e => e.duration === metric.value && INP_ENTRY_MAP[e.name]);\n}\n\n/**\n * Exported only for testing.\n */\nexport function _sendInpSpan(\n inpValue: number,\n entry: PerformanceEventTiming | undefined,\n standalone = false,\n attributedSpan?: Span,\n softNavigationId?: number,\n metric?: InpMetric,\n): void {\n DEBUG_BUILD && debug.log(`Sending INP span (${inpValue})`);\n\n // A web vital span carries the metric, not a real interaction timing, so an INP without an entry\n // is still worth reporting. It just has no element or interaction type to describe, and is placed\n // at the start of the navigation it belongs to rather than at the interaction.\n const startTime = msToSec(\n (browserPerformanceTimeOrigin() as number) + (entry?.startTime ?? metric?.navigationStartTime ?? 0),\n );\n const duration = msToSec(inpValue);\n // An INP without an entry has no interaction type to report. It still has to land inside the\n // `ui.interaction.*` family, because falling outside it would hide exactly the fast navigations\n // that web-vitals synthesizes these values for (GoogleChrome/web-vitals#724), reintroducing the\n // reporting bias they were added to remove.\n const entryInteractionType = entry && INP_ENTRY_MAP[entry.name];\n const interactionType = entryInteractionType || 'click';\n\n const cachedContext = entry && getCachedInteractionContext(entry.interactionId);\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined;\n\n // With soft navigations the caller knows exactly which navigation the metric belongs to. Without\n // them we fall back to the span that was active when the interaction was observed.\n const spanToUse = attributedSpan || cachedContext?.span || rootSpan;\n const selector = cachedContext?.elementName || (entry ? htmlTreeAsString(entry.target) : undefined);\n const componentName = entry?.target ? getComponentName(entry.target) : null;\n const client = getClient();\n const hasSpanStreaming = !!client && hasSpanStreamingEnabled(client);\n const fallbackName = INTERACTION_TYPE_TO_SPAN_NAME_FALLBACK[interactionType];\n const name = hasSpanStreaming ? componentName || fallbackName : (selector ?? 'Interaction to next paint');\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry?.duration ?? inpValue,\n };\n\n // The span's name and op always have a value, even for an INP without an entry, so they can't\n // say whether there was an interaction to describe. These attributes can: they are only set for\n // what was actually observed. The name no longer holds the selector either, now that it is the\n // component name or the op's fallback under span streaming.\n // TODO: use the `@sentry/conventions` constants once getsentry/sentry-conventions#641 is released.\n selector && selector !== UNKNOWN_ELEMENT_NAME && (attributes['browser.web_vital.inp.target'] = selector);\n entryInteractionType && (attributes['browser.web_vital.inp.interaction_type'] = entryInteractionType);\n\n if (componentName) {\n attributes[UI_COMPONENT_NAME] = componentName;\n }\n\n _emitWebVitalSpan({\n name,\n op: INTERACTION_TYPE_TO_SPAN_OP[interactionType],\n origin: 'auto.http.browser.inp',\n metricName: 'inp',\n value: inpValue,\n attributes,\n startTime,\n endTime: startTime + duration,\n navigationType: metric?.navigationType,\n parentSpan: spanToUse,\n standalone,\n softNavigationId,\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { browserPerformanceTimeOrigin, spanToJSON, setMeasurement, debug } from '@sentry/core';
2
- import { SENTRY_OP } from '@sentry/conventions/attributes';
2
+ import { SENTRY_OP, BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { htmlTreeAsString } from '../htmlTreeAsString.js';
5
5
  import { addLcpInstrumentationHandler, addClsInstrumentationHandler, addTtfbInstrumentationHandler, addFcpInstrumentationHandler, addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver.js';
@@ -10,6 +10,7 @@ import { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './
10
10
  let _measurements = {};
11
11
  let _lcpEntry;
12
12
  let _clsEntry;
13
+ let _navigationType;
13
14
  function startTrackingWebVitals({ trackCls, trackLcp }) {
14
15
  const performance = getBrowserPerformanceAPI();
15
16
  if (performance && browserPerformanceTimeOrigin()) {
@@ -50,6 +51,7 @@ function _trackLCP() {
50
51
  }
51
52
  function _trackTtfb() {
52
53
  return addTtfbInstrumentationHandler(({ metric }) => {
54
+ _navigationType = metric.navigationType;
53
55
  const entry = metric.entries[metric.entries.length - 1];
54
56
  if (!entry) {
55
57
  return;
@@ -59,6 +61,7 @@ function _trackTtfb() {
59
61
  }
60
62
  function _trackFcp() {
61
63
  return addFcpInstrumentationHandler(({ metric }) => {
64
+ _navigationType = metric.navigationType;
62
65
  _measurements["fcp"] = { value: metric.value, unit: "millisecond" };
63
66
  });
64
67
  }
@@ -109,6 +112,9 @@ function addWebVitalsToSpan(span, options) {
109
112
  });
110
113
  _setWebVitalAttributes(span, options);
111
114
  }
115
+ if (_navigationType) {
116
+ span.setAttribute(BROWSER_NAVIGATION_TYPE, _navigationType);
117
+ }
112
118
  span.setAttribute(spanStreamingEnabled ? "browser.performance.time_origin" : "performance.timeOrigin", timeOrigin);
113
119
  span.setAttribute(
114
120
  spanStreamingEnabled ? "browser.performance.navigation.activation_start" : "performance.activationStart",
@@ -120,6 +126,7 @@ function addWebVitalsToSpan(span, options) {
120
126
  function resetWebVitalState() {
121
127
  _lcpEntry = void 0;
122
128
  _clsEntry = void 0;
129
+ _navigationType = void 0;
123
130
  _measurements = {};
124
131
  }
125
132
  function _setWebVitalAttributes(span, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"tracking.js","sources":["../../../src/web-vitals/tracking.ts"],"sourcesContent":["import type { Client, Measurements, Span } from '@sentry/core';\nimport { browserPerformanceTimeOrigin, debug, setMeasurement, spanToJSON } from '@sentry/core';\nimport { SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport {\n addClsInstrumentationHandler,\n addFcpInstrumentationHandler,\n addLcpInstrumentationHandler,\n addPerformanceInstrumentationHandler,\n addTtfbInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport { getBrowserPerformanceAPI, msToSec } from '../performance/utils';\nimport { isValidLcpMetric } from './lcp';\nimport { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './utils';\n\nlet _measurements: Measurements = {};\nlet _lcpEntry: LargestContentfulPaint | undefined;\nlet _clsEntry: LayoutShift | undefined;\n\ninterface StartTrackingWebVitalsOptions {\n trackCls: boolean;\n trackLcp: boolean;\n client: Client;\n}\n\n/**\n * Start tracking web vitals.\n * The callback returned by this function can be used to stop tracking & ensure all measurements are final & captured.\n *\n * @returns A function that forces web vitals collection\n */\nexport function startTrackingWebVitals({ trackCls, trackLcp }: StartTrackingWebVitalsOptions): () => void {\n const performance = getBrowserPerformanceAPI();\n if (performance && browserPerformanceTimeOrigin()) {\n const lcpCleanupCallback = trackLcp ? _trackLCP() : undefined;\n const clsCleanupCallback = trackCls ? _trackCLS() : undefined;\n const ttfbCleanupCallback = _trackTtfb();\n const fcpCleanupCallback = _trackFcp();\n const fpCleanupCallback = _trackFp();\n\n return (): void => {\n ttfbCleanupCallback();\n fcpCleanupCallback();\n fpCleanupCallback();\n lcpCleanupCallback?.();\n clsCleanupCallback?.();\n };\n }\n\n return () => undefined;\n}\n\nexport { registerInpInteractionListener } from './inp';\n\n/**\n * Starts tracking the Cumulative Layout Shift on the current page and collects the value and last entry\n * to the `_measurements` object which ultimately is applied to the pageload span's measurements.\n */\nfunction _trackCLS(): () => void {\n return addClsInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n if (!entry) {\n return;\n }\n _measurements['cls'] = { value: metric.value, unit: '' };\n _clsEntry = entry;\n }, true);\n}\n\n/** Starts tracking the Largest Contentful Paint on the current page. */\nfunction _trackLCP(): () => void {\n return addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n\n _measurements['lcp'] = { value: metric.value, unit: 'millisecond' };\n _lcpEntry = entry as LargestContentfulPaint;\n }, true);\n}\n\nfunction _trackTtfb(): () => void {\n return addTtfbInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry) {\n return;\n }\n\n _measurements['ttfb'] = { value: metric.value, unit: 'millisecond' };\n });\n}\n\n/** Starts tracking the First Contentful Paint on the current page. */\nfunction _trackFcp(): () => void {\n return addFcpInstrumentationHandler(({ metric }) => {\n _measurements['fcp'] = { value: metric.value, unit: 'millisecond' };\n });\n}\n\n/**\n * Starts tracking First Paint on the current page.\n *\n * web-vitals has no `onFP`, so this stays on the raw paint observer, and mirrors the one thing\n * `onFCP` does inline: skip the vital if the page was hidden before it. The raw `startTime` is\n * stored as-is; rebasing it against `activationStart` happens in `_rebaseFpAgainstActivationStart`\n * when the span ends, because this observer can run before the page is activated.\n */\nfunction _trackFp(): () => void {\n return addPerformanceInstrumentationHandler('paint', ({ entries }) => {\n const firstHidden = getVisibilityWatcher();\n for (const entry of entries) {\n if (entry.name === 'first-paint' && entry.startTime < firstHidden.firstHiddenTime) {\n _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' };\n }\n }\n });\n}\n\ninterface AddWebVitalsToSpanOptions {\n /**\n * Flag to determine if CLS should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordClsOnPageloadSpan: boolean;\n\n /**\n * Flag to determine if LCP should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordLcpOnPageloadSpan: boolean;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/**\n * Writes the collected web vitals (LCP, CLS, INP, TTFB, FP, FCP) onto the pageload span,\n * either as measurements/attributes (v1) or as web vital attributes (span streaming).\n *\n * This should be called when the pageload span ends, after the web vitals have been finalized.\n * It is a no-op for non-pageload spans, but always resets the collected web vital state so it\n * doesn't leak into a subsequent navigation.\n */\nexport function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOptions): void {\n const origin = browserPerformanceTimeOrigin();\n if (!getBrowserPerformanceAPI()?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n resetWebVitalState();\n return;\n }\n\n const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;\n const timeOrigin = msToSec(origin);\n\n // Measurements are only available for pageload transactions\n if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n _addTtfbRequestTimeToMeasurements(_measurements);\n _rebaseFpAgainstActivationStart(_measurements);\n\n if (spanStreamingEnabled) {\n const setAttr = (shortWebVitalName: string, value: number, customAttrName?: string) => {\n const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;\n span.setAttribute(attrKey, value);\n DEBUG_BUILD && debug.log('Setting web vital attribute', { [attrKey]: value }, 'on pageload span');\n };\n // for streamed pageload spans, we add the web vital measurements as attributes.\n // We omit LCP, CLS and INP because they're tracked separately as spans\n ['ttfb', 'fp', 'fcp'].forEach(measurementName => {\n if (_measurements[measurementName]) {\n setAttr(measurementName, _measurements[measurementName].value);\n }\n });\n if (_measurements['ttfb.requestTime']) {\n setAttr('ttfb.requestTime', _measurements['ttfb.requestTime'].value, 'browser.web_vital.ttfb.request_time');\n }\n } else {\n // If CLS is tracked as a span (span streaming), don't record CLS as a measurement\n if (!recordClsOnPageloadSpan) {\n delete _measurements.cls;\n }\n\n // If LCP is tracked as a span (span streaming), don't record LCP as a measurement\n if (!recordLcpOnPageloadSpan) {\n delete _measurements.lcp;\n }\n\n Object.entries(_measurements).forEach(([measurementName, measurement]) => {\n setMeasurement(measurementName, measurement.value, measurement.unit, span);\n });\n\n _setWebVitalAttributes(span, options);\n }\n\n // Set timeOrigin which denotes the timestamp which to base the LCP/FCP/FP/TTFB measurements on\n span.setAttribute(spanStreamingEnabled ? 'browser.performance.time_origin' : 'performance.timeOrigin', timeOrigin);\n\n // In prerendering scenarios, where a page might be prefetched and pre-rendered before the user clicks the link,\n // the navigation starts earlier than when the user clicks it. Web Vitals should always be based on the\n // user-perceived time, so they are not reported from the actual start of the navigation, but rather from the\n // time where the user actively started the navigation, for example by clicking a link.\n // This is user action is called \"activation\" and the time between navigation and activation is stored in\n // the `activationStart` attribute of the \"navigation\" PerformanceEntry.\n span.setAttribute(\n spanStreamingEnabled ? 'browser.performance.navigation.activation_start' : 'performance.activationStart',\n getActivationStart(),\n );\n }\n\n resetWebVitalState();\n}\n\nfunction resetWebVitalState(): void {\n _lcpEntry = undefined;\n _clsEntry = undefined;\n _measurements = {};\n}\n\n/** Add LCP / CLS data to span to allow debugging */\nfunction _setWebVitalAttributes(span: Span, options: AddWebVitalsToSpanOptions): void {\n // Only add LCP attributes if LCP is being recorded on the pageload span\n if (_lcpEntry && options.recordLcpOnPageloadSpan) {\n // Capture Properties of the LCP element that contributes to the LCP.\n\n if (_lcpEntry.element) {\n span.setAttribute('lcp.element', htmlTreeAsString(_lcpEntry.element));\n }\n\n if (_lcpEntry.id) {\n span.setAttribute('lcp.id', _lcpEntry.id);\n }\n\n if (_lcpEntry.url) {\n // Trim URL to the first 200 characters.\n span.setAttribute('lcp.url', _lcpEntry.url.trim().slice(0, 200));\n }\n\n if (_lcpEntry.loadTime != null) {\n // loadTime is the time of LCP that's related to receiving the LCP element response..\n span.setAttribute('lcp.loadTime', _lcpEntry.loadTime);\n }\n\n if (_lcpEntry.renderTime != null) {\n // renderTime is loadTime + rendering time\n // it's 0 if the LCP element is loaded from a 3rd party origin that doesn't send the\n // `Timing-Allow-Origin` header.\n span.setAttribute('lcp.renderTime', _lcpEntry.renderTime);\n }\n\n span.setAttribute('lcp.size', _lcpEntry.size);\n }\n\n // Only add CLS attributes if CLS is being recorded on the pageload span\n if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {\n _clsEntry.sources.forEach((source, index) =>\n span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString(source.node)),\n );\n }\n}\n\n/**\n * Rebases First Paint against `activationStart`, so a prerendered page reports time-to-paint from\n * the moment the user activated it rather than from the (much earlier) prerender navigation start.\n *\n * The vitals that come from web-vitals do this themselves, when they compute their value: they only\n * start observing once the page is activated, so `activationStart` is known by then. FP has no\n * web-vitals equivalent and is read off a `buffered` paint observer registered at SDK init, which\n * on a prerendered page runs while `document.prerendering` is still true and `activationStart` is\n * still 0. Correcting there would be a no-op, so it happens here, at span end, by which point the\n * activation time is known.\n */\nfunction _rebaseFpAgainstActivationStart(measurements: Measurements): void {\n const fp = measurements['fp'];\n if (fp) {\n fp.value = Math.max(fp.value - getActivationStart(), 0);\n }\n}\n\n/**\n * Add ttfb request time information to measurements.\n *\n * ttfb information is added via the web vitals library.\n */\nfunction _addTtfbRequestTimeToMeasurements(_measurements: Measurements): void {\n const navEntry = getNavigationEntry(false);\n if (!navEntry) {\n return;\n }\n\n const { responseStart, requestStart } = navEntry;\n\n if (requestStart <= responseStart) {\n _measurements['ttfb.requestTime'] = {\n value: responseStart - requestStart,\n unit: 'millisecond',\n };\n }\n}\n"],"names":["_measurements"],"mappings":"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"}
1
+ {"version":3,"file":"tracking.js","sources":["../../../src/web-vitals/tracking.ts"],"sourcesContent":["import type { Client, Measurements, Span } from '@sentry/core';\nimport { browserPerformanceTimeOrigin, debug, setMeasurement, spanToJSON } from '@sentry/core';\nimport { BROWSER_NAVIGATION_TYPE, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { htmlTreeAsString } from '../htmlTreeAsString';\nimport type { MetricNavigationType } from '../instrumentation/performanceObserver';\nimport {\n addClsInstrumentationHandler,\n addFcpInstrumentationHandler,\n addLcpInstrumentationHandler,\n addPerformanceInstrumentationHandler,\n addTtfbInstrumentationHandler,\n} from '../instrumentation/performanceObserver';\nimport { getBrowserPerformanceAPI, msToSec } from '../performance/utils';\nimport { isValidLcpMetric } from './lcp';\nimport { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './utils';\n\nlet _measurements: Measurements = {};\nlet _lcpEntry: LargestContentfulPaint | undefined;\nlet _clsEntry: LayoutShift | undefined;\nlet _navigationType: MetricNavigationType | undefined;\n\ninterface StartTrackingWebVitalsOptions {\n trackCls: boolean;\n trackLcp: boolean;\n client: Client;\n}\n\n/**\n * Start tracking web vitals.\n * The callback returned by this function can be used to stop tracking & ensure all measurements are final & captured.\n *\n * @returns A function that forces web vitals collection\n */\nexport function startTrackingWebVitals({ trackCls, trackLcp }: StartTrackingWebVitalsOptions): () => void {\n const performance = getBrowserPerformanceAPI();\n if (performance && browserPerformanceTimeOrigin()) {\n const lcpCleanupCallback = trackLcp ? _trackLCP() : undefined;\n const clsCleanupCallback = trackCls ? _trackCLS() : undefined;\n const ttfbCleanupCallback = _trackTtfb();\n const fcpCleanupCallback = _trackFcp();\n const fpCleanupCallback = _trackFp();\n\n return (): void => {\n ttfbCleanupCallback();\n fcpCleanupCallback();\n fpCleanupCallback();\n lcpCleanupCallback?.();\n clsCleanupCallback?.();\n };\n }\n\n return () => undefined;\n}\n\nexport { registerInpInteractionListener } from './inp';\n\n/**\n * Starts tracking the Cumulative Layout Shift on the current page and collects the value and last entry\n * to the `_measurements` object which ultimately is applied to the pageload span's measurements.\n */\nfunction _trackCLS(): () => void {\n return addClsInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1] as LayoutShift | undefined;\n if (!entry) {\n return;\n }\n _measurements['cls'] = { value: metric.value, unit: '' };\n _clsEntry = entry;\n }, true);\n}\n\n/** Starts tracking the Largest Contentful Paint on the current page. */\nfunction _trackLCP(): () => void {\n return addLcpInstrumentationHandler(({ metric }) => {\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry || !isValidLcpMetric(metric.value)) {\n return;\n }\n\n _measurements['lcp'] = { value: metric.value, unit: 'millisecond' };\n _lcpEntry = entry as LargestContentfulPaint;\n }, true);\n}\n\nfunction _trackTtfb(): () => void {\n return addTtfbInstrumentationHandler(({ metric }) => {\n _navigationType = metric.navigationType;\n\n const entry = metric.entries[metric.entries.length - 1];\n if (!entry) {\n return;\n }\n\n _measurements['ttfb'] = { value: metric.value, unit: 'millisecond' };\n });\n}\n\n/** Starts tracking the First Contentful Paint on the current page. */\nfunction _trackFcp(): () => void {\n return addFcpInstrumentationHandler(({ metric }) => {\n _navigationType = metric.navigationType;\n _measurements['fcp'] = { value: metric.value, unit: 'millisecond' };\n });\n}\n\n/**\n * Starts tracking First Paint on the current page.\n *\n * web-vitals has no `onFP`, so this stays on the raw paint observer, and mirrors the one thing\n * `onFCP` does inline: skip the vital if the page was hidden before it. The raw `startTime` is\n * stored as-is; rebasing it against `activationStart` happens in `_rebaseFpAgainstActivationStart`\n * when the span ends, because this observer can run before the page is activated.\n */\nfunction _trackFp(): () => void {\n return addPerformanceInstrumentationHandler('paint', ({ entries }) => {\n const firstHidden = getVisibilityWatcher();\n for (const entry of entries) {\n if (entry.name === 'first-paint' && entry.startTime < firstHidden.firstHiddenTime) {\n _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' };\n }\n }\n });\n}\n\ninterface AddWebVitalsToSpanOptions {\n /**\n * Flag to determine if CLS should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordClsOnPageloadSpan: boolean;\n\n /**\n * Flag to determine if LCP should be recorded as a measurement on the pageload span or\n * sent as a standalone span instead.\n * Sending it as a standalone span will yield more accurate LCP values.\n *\n * Default: `false` for backwards compatibility.\n */\n recordLcpOnPageloadSpan: boolean;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/**\n * Writes the collected web vitals (LCP, CLS, INP, TTFB, FP, FCP) onto the pageload span,\n * either as measurements/attributes (v1) or as web vital attributes (span streaming).\n *\n * This should be called when the pageload span ends, after the web vitals have been finalized.\n * It is a no-op for non-pageload spans, but always resets the collected web vital state so it\n * doesn't leak into a subsequent navigation.\n */\nexport function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOptions): void {\n const origin = browserPerformanceTimeOrigin();\n if (!getBrowserPerformanceAPI()?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n resetWebVitalState();\n return;\n }\n\n const { spanStreamingEnabled, recordClsOnPageloadSpan, recordLcpOnPageloadSpan } = options;\n const timeOrigin = msToSec(origin);\n\n // Measurements are only available for pageload transactions\n if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n _addTtfbRequestTimeToMeasurements(_measurements);\n _rebaseFpAgainstActivationStart(_measurements);\n\n if (spanStreamingEnabled) {\n const setAttr = (shortWebVitalName: string, value: number, customAttrName?: string) => {\n const attrKey = customAttrName ?? `browser.web_vital.${shortWebVitalName}.value`;\n span.setAttribute(attrKey, value);\n DEBUG_BUILD && debug.log('Setting web vital attribute', { [attrKey]: value }, 'on pageload span');\n };\n // for streamed pageload spans, we add the web vital measurements as attributes.\n // We omit LCP, CLS and INP because they're tracked separately as spans\n ['ttfb', 'fp', 'fcp'].forEach(measurementName => {\n if (_measurements[measurementName]) {\n setAttr(measurementName, _measurements[measurementName].value);\n }\n });\n if (_measurements['ttfb.requestTime']) {\n setAttr('ttfb.requestTime', _measurements['ttfb.requestTime'].value, 'browser.web_vital.ttfb.request_time');\n }\n } else {\n // If CLS is tracked as a span (span streaming), don't record CLS as a measurement\n if (!recordClsOnPageloadSpan) {\n delete _measurements.cls;\n }\n\n // If LCP is tracked as a span (span streaming), don't record LCP as a measurement\n if (!recordLcpOnPageloadSpan) {\n delete _measurements.lcp;\n }\n\n Object.entries(_measurements).forEach(([measurementName, measurement]) => {\n setMeasurement(measurementName, measurement.value, measurement.unit, span);\n });\n\n _setWebVitalAttributes(span, options);\n }\n\n // TTFB, FP and FCP are attributes of this span rather than spans of their own, so the navigation\n // type they were measured on is reported here for them to be read against.\n if (_navigationType) {\n span.setAttribute(BROWSER_NAVIGATION_TYPE, _navigationType);\n }\n\n // Set timeOrigin which denotes the timestamp which to base the LCP/FCP/FP/TTFB measurements on\n span.setAttribute(spanStreamingEnabled ? 'browser.performance.time_origin' : 'performance.timeOrigin', timeOrigin);\n\n // In prerendering scenarios, where a page might be prefetched and pre-rendered before the user clicks the link,\n // the navigation starts earlier than when the user clicks it. Web Vitals should always be based on the\n // user-perceived time, so they are not reported from the actual start of the navigation, but rather from the\n // time where the user actively started the navigation, for example by clicking a link.\n // This is user action is called \"activation\" and the time between navigation and activation is stored in\n // the `activationStart` attribute of the \"navigation\" PerformanceEntry.\n span.setAttribute(\n spanStreamingEnabled ? 'browser.performance.navigation.activation_start' : 'performance.activationStart',\n getActivationStart(),\n );\n }\n\n resetWebVitalState();\n}\n\nfunction resetWebVitalState(): void {\n _lcpEntry = undefined;\n _clsEntry = undefined;\n _navigationType = undefined;\n _measurements = {};\n}\n\n/** Add LCP / CLS data to span to allow debugging */\nfunction _setWebVitalAttributes(span: Span, options: AddWebVitalsToSpanOptions): void {\n // Only add LCP attributes if LCP is being recorded on the pageload span\n if (_lcpEntry && options.recordLcpOnPageloadSpan) {\n // Capture Properties of the LCP element that contributes to the LCP.\n\n if (_lcpEntry.element) {\n span.setAttribute('lcp.element', htmlTreeAsString(_lcpEntry.element));\n }\n\n if (_lcpEntry.id) {\n span.setAttribute('lcp.id', _lcpEntry.id);\n }\n\n if (_lcpEntry.url) {\n // Trim URL to the first 200 characters.\n span.setAttribute('lcp.url', _lcpEntry.url.trim().slice(0, 200));\n }\n\n if (_lcpEntry.loadTime != null) {\n // loadTime is the time of LCP that's related to receiving the LCP element response..\n span.setAttribute('lcp.loadTime', _lcpEntry.loadTime);\n }\n\n if (_lcpEntry.renderTime != null) {\n // renderTime is loadTime + rendering time\n // it's 0 if the LCP element is loaded from a 3rd party origin that doesn't send the\n // `Timing-Allow-Origin` header.\n span.setAttribute('lcp.renderTime', _lcpEntry.renderTime);\n }\n\n span.setAttribute('lcp.size', _lcpEntry.size);\n }\n\n // Only add CLS attributes if CLS is being recorded on the pageload span\n if (_clsEntry?.sources && options.recordClsOnPageloadSpan) {\n _clsEntry.sources.forEach((source, index) =>\n span.setAttribute(`cls.source.${index + 1}`, htmlTreeAsString(source.node)),\n );\n }\n}\n\n/**\n * Rebases First Paint against `activationStart`, so a prerendered page reports time-to-paint from\n * the moment the user activated it rather than from the (much earlier) prerender navigation start.\n *\n * The vitals that come from web-vitals do this themselves, when they compute their value: they only\n * start observing once the page is activated, so `activationStart` is known by then. FP has no\n * web-vitals equivalent and is read off a `buffered` paint observer registered at SDK init, which\n * on a prerendered page runs while `document.prerendering` is still true and `activationStart` is\n * still 0. Correcting there would be a no-op, so it happens here, at span end, by which point the\n * activation time is known.\n */\nfunction _rebaseFpAgainstActivationStart(measurements: Measurements): void {\n const fp = measurements['fp'];\n if (fp) {\n fp.value = Math.max(fp.value - getActivationStart(), 0);\n }\n}\n\n/**\n * Add ttfb request time information to measurements.\n *\n * ttfb information is added via the web vitals library.\n */\nfunction _addTtfbRequestTimeToMeasurements(_measurements: Measurements): void {\n const navEntry = getNavigationEntry(false);\n if (!navEntry) {\n return;\n }\n\n const { responseStart, requestStart } = navEntry;\n\n if (requestStart <= responseStart) {\n _measurements['ttfb.requestTime'] = {\n value: responseStart - requestStart,\n unit: 'millisecond',\n };\n }\n}\n"],"names":["_measurements"],"mappings":"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"}
@@ -34,8 +34,7 @@ export interface PerformanceLongAnimationFrameTiming extends PerformanceEntry {
34
34
  scripts: PerformanceScriptTiming[];
35
35
  }
36
36
  /**
37
- * The navigation types web-vitals reports a metric for. Wider than the set the
38
- * `browser.navigation.type` attribute uses - see `toBrowserNavigationType`.
37
+ * The navigation types web-vitals reports a metric for, reported as-is on `browser.navigation.type`.
39
38
  */
40
39
  export type MetricNavigationType = 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore' | 'soft-navigation';
41
40
  interface Metric {
@@ -1 +1 @@
1
- {"version":3,"file":"performanceObserver.d.ts","sourceRoot":"","sources":["../../../src/instrumentation/performanceObserver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"performanceObserver.d.ts","sourceRoot":"","sources":["../../../src/instrumentation/performanceObserver.ts"],"names":[],"mappings":"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"}
@@ -21,11 +21,16 @@ interface AddPerformanceEntriesOptions {
21
21
  }
22
22
  /** Add performance related spans to a transaction */
23
23
  export declare function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void;
24
+ /**
25
+ * Create a span for a browser paint performance entry.
26
+ * Exported only for tests.
27
+ */
28
+ export declare function _addPaintSpan(span: Span, entry: PerformanceEntry, startTime: number, duration: number, timeOrigin: number): void;
24
29
  /**
25
30
  * Instrument navigation entries
26
31
  * exported only for tests
27
32
  */
28
- export declare function _addNavigationSpans(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number): void;
33
+ export declare function _addNavigationSpans(span: Span, entry: PerformanceNavigationTiming, timeOrigin: number, spanStreamingEnabled?: boolean): void;
29
34
  /**
30
35
  * Create resource-related spans.
31
36
  * Exported only for tests.
@@ -1 +1 @@
1
- {"version":3,"file":"entries.d.ts","sourceRoot":"","sources":["../../../src/performance/entries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA6FzD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA8B7C;AAED;;GAEG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAyDvD;AAED,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,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,4BAA4B,GAAG,IAAI,CA+D7F;AAqBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,2BAA2B,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAW5G;AA6FD;;;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,EACtC,oBAAoB,CAAC,EAAE,OAAO,GAC7B,IAAI,CAoEN;AAsDD,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":"entries.d.ts","sourceRoot":"","sources":["../../../src/performance/entries.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAgGzD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CA8B7C;AAED;;GAEG;AACH,wBAAgB,gCAAgC,IAAI,IAAI,CAyDvD;AAED,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,qDAAqD;AACrD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,4BAA4B,GAAG,IAAI,CA+D7F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,gBAAgB,EACvB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,IAAI,CAaN;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,2BAA2B,EAClC,UAAU,EAAE,MAAM,EAClB,oBAAoB,CAAC,EAAE,OAAO,GAC7B,IAAI,CAWN;AA8GD;;;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,EACtC,oBAAoB,CAAC,EAAE,OAAO,GAC7B,IAAI,CAoEN;AAsDD,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 +1 @@
1
- {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../../src/performance/interactions.ts"],"names":[],"mappings":"AA6BA,UAAU,mBAAmB;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAqDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,uBAAuB;;CAA8C,CAAC"}
1
+ {"version":3,"file":"interactions.d.ts","sourceRoot":"","sources":["../../../src/performance/interactions.ts"],"names":[],"mappings":"AAwCA,UAAU,mBAAmB;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAuED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,uBAAuB;;CAA8C,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import type { Span, SpanAttributes } from '@sentry/core';
2
2
  import type { MetricNavigationType } from '../instrumentation/performanceObserver';
3
- import type { WebVitalReportEvent } from './reportEvents';
4
3
  export interface LayoutShift extends PerformanceEntry {
5
4
  value: number;
6
5
  sources: Array<{
@@ -24,7 +23,6 @@ interface WebVitalSpanOptions {
24
23
  value: number;
25
24
  attributes?: SpanAttributes;
26
25
  parentSpan?: Span;
27
- reportEvent?: WebVitalReportEvent;
28
26
  startTime: number;
29
27
  endTime?: number;
30
28
  /** Set when the vital was reported for a soft navigation rather than the initial page load. */
@@ -1 +1 @@
1
- {"version":3,"file":"emitSpan.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/emitSpan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,IAAI,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAoBtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AACnF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAoB1D,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACtC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CA2EpE"}
1
+ {"version":3,"file":"emitSpan.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/emitSpan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,IAAI,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAoBtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAMnF,MAAM,WAAW,WAAY,SAAQ,gBAAgB;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IACtC,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,QAAQ,CAAC,UAAU,EAAE,mBAAmB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAClC;AAED,UAAU,mBAAmB;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,UAAU,CAAC,EAAE,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAsEpE"}
@@ -3,6 +3,8 @@ interface InteractionContext {
3
3
  span: Span | undefined;
4
4
  elementName: string;
5
5
  }
6
+ /** What `htmlTreeAsString` returns when it cannot describe the target. */
7
+ export declare const UNKNOWN_ELEMENT_NAME = "<unknown>";
6
8
  /**
7
9
  * 60 seconds is the maximum for a plausible INP value
8
10
  * (source: Me)
@@ -1 +1 @@
1
- {"version":3,"file":"inp.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/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;AAWD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA2BzD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAE7G;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CA2GrD"}
1
+ {"version":3,"file":"inp.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/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;AAMD,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAIhD;;;GAGG;AACH,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAE7C,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA2BzD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,kBAAkB,GAAG,SAAS,CAE7G;AAED;;GAEG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CA2GrD"}
@@ -1,5 +1,4 @@
1
1
  import type { Client, Span } from '@sentry/core';
2
- export type WebVitalReportEvent = 'pagehide' | 'navigation';
3
2
  /**
4
3
  * Listens for events on which we want to collect a previously accumulated web vital value.
5
4
  * Currently, this includes:
@@ -7,12 +6,10 @@ export type WebVitalReportEvent = 'pagehide' | 'navigation';
7
6
  * - pagehide (i.e. user minimizes browser window, hides tab, etc)
8
7
  * - soft navigation (we only care about the vital of the initially loaded route)
9
8
  *
10
- * As a "side-effect", this function will also collect the span id of the pageload span.
9
+ * As a "side-effect", this function will also collect the pageload span.
11
10
  *
12
- * @param collectorCallback the callback to be called when the first of these events is triggered. Parameters:
13
- * - event: the event that triggered the reporting of the web vital value.
14
- * - pageloadSpanId: the span id of the pageload span. This is used to link the web vital span to the pageload span.
15
- * - pageloadSpan: the pageload span instance. This is used for full access to the pageload span for span streaming.
11
+ * @param collectorCallback the callback to be called when the first of these events is triggered. It is passed the
12
+ * pageload span, which the web vital span is parented to.
16
13
  */
17
- export declare function listenForWebVitalReportEvents(client: Client, collectorCallback: (event: WebVitalReportEvent, pageloadSpanId: string, pageloadSpan?: Span) => void): void;
14
+ export declare function listenForWebVitalReportEvents(client: Client, collectorCallback: (pageloadSpan: Span) => void): void;
18
15
  //# sourceMappingURL=reportEvents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reportEvents.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/reportEvents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,YAAY,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,iBAAiB,EAAE,CAAC,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,IAAI,KAAK,IAAI,QA6BrG"}
1
+ {"version":3,"file":"reportEvents.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/reportEvents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAGjD;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC,YAAY,EAAE,IAAI,KAAK,IAAI,QA4B5G"}
@@ -1 +1 @@
1
- {"version":3,"file":"softNavs.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/softNavs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAoBjD,UAAU,aAAa;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAkBD;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAejD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA8DnE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAgBlF"}
1
+ {"version":3,"file":"softNavs.d.ts","sourceRoot":"","sources":["../../../src/web-vitals/softNavs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAoBjD,UAAU,aAAa;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAiCD;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,OAAO,CAejD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAyFnE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,GAAG,SAAS,CAgBlF"}
@@ -1,7 +1,6 @@
1
1
  import type { Client, Span } from '@sentry/core';
2
2
  import type { InstrumentationHandlerCallback, MetricNavigationType } from '../instrumentation/performanceObserver';
3
3
  import type { LargestContentfulPaint, LayoutShift } from './emitSpan';
4
- import type { WebVitalReportEvent } from './reportEvents';
5
4
  import type { PerformanceEventTiming } from '../instrumentation/performanceObserver';
6
5
  type InpMetric = Parameters<InstrumentationHandlerCallback>[0]['metric'];
7
6
  /**
@@ -11,7 +10,7 @@ export declare function trackLcpAsSpan(client: Client, perNavigation?: boolean):
11
10
  /**
12
11
  * Exported only for testing.
13
12
  */
14
- export declare function _sendLcpSpan(lcpValue: number, entry: LargestContentfulPaint | undefined, pageloadSpan?: Span, reportEvent?: WebVitalReportEvent, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number): void;
13
+ export declare function _sendLcpSpan(lcpValue: number, entry: LargestContentfulPaint | undefined, pageloadSpan?: Span, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number): void;
15
14
  /**
16
15
  * Tracks CLS as a streamed span.
17
16
  */
@@ -19,7 +18,7 @@ export declare function trackClsAsSpan(client: Client, perNavigation?: boolean):
19
18
  /**
20
19
  * Exported only for testing.
21
20
  */
22
- export declare function _sendClsSpan(clsValue: number, entry: LayoutShift | undefined, pageloadSpan?: Span, reportEvent?: WebVitalReportEvent, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number): void;
21
+ export declare function _sendClsSpan(clsValue: number, entry: LayoutShift | undefined, pageloadSpan?: Span, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number): void;
23
22
  /**
24
23
  * Tracks INP and emits it as a web vital span, as a child of the interaction's root span.
25
24
  * Requires `registerInpInteractionListener()` to be called separately for cached element names and