@sentry/browser-utils 11.3.0 → 11.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"getNativeImplementation.js","sources":["../../src/getNativeImplementation.ts"],"sourcesContent":["import { debug, isNativeFunction } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { WINDOW } from './types';\n\n/**\n * We generally want to use window.fetch / window.setTimeout.\n * However, in some cases this may be wrapped (e.g. by Zone.js for Angular),\n * so we try to get an unpatched version of this from a sandboxed iframe.\n */\n\ninterface CacheableImplementations {\n setTimeout: typeof WINDOW.setTimeout;\n fetch: typeof WINDOW.fetch;\n}\n\nconst cachedImplementations: Partial<CacheableImplementations> = {};\n\n/**\n * Get the native implementation of a browser function.\n *\n * This can be used to ensure we get an unwrapped version of a function, in cases where a wrapped function can lead to problems.\n *\n * The following methods can be retrieved:\n * - `setTimeout`: This can be wrapped by e.g. Angular, causing change detection to be triggered.\n * - `fetch`: This can be wrapped by e.g. ad-blockers, causing an infinite loop when a request is blocked.\n */\nexport function getNativeImplementation<T extends keyof CacheableImplementations>(\n name: T,\n): CacheableImplementations[T] {\n const cached = cachedImplementations[name];\n if (cached) {\n return cached;\n }\n\n let impl = WINDOW[name] as CacheableImplementations[T];\n\n // Fast path to avoid DOM I/O\n if (isNativeFunction(impl)) {\n return (cachedImplementations[name] = impl.bind(WINDOW) as CacheableImplementations[T]);\n }\n\n const document = WINDOW.document;\n // eslint-disable-next-line typescript/no-deprecated\n if (document && typeof document.createElement === 'function') {\n try {\n const sandbox = document.createElement('iframe');\n sandbox.hidden = true;\n document.head.appendChild(sandbox);\n const contentWindow = sandbox.contentWindow;\n if (contentWindow?.[name]) {\n impl = contentWindow[name] as CacheableImplementations[T];\n }\n document.head.removeChild(sandbox);\n } catch (e) {\n // Could not create sandbox iframe, just use window.xxx\n DEBUG_BUILD && debug.warn(`Could not create sandbox iframe for ${name} check, bailing to window.${name}: `, e);\n }\n }\n\n // Sanity check: This _should_ not happen, but if it does, we just skip caching...\n // This can happen e.g. in tests where fetch may not be available in the env, or similar.\n if (!impl) {\n return impl;\n }\n\n return (cachedImplementations[name] = impl.bind(WINDOW) as CacheableImplementations[T]);\n}\n\n/** Clear a cached implementation. */\nexport function clearCachedImplementation(name: keyof CacheableImplementations): void {\n cachedImplementations[name] = undefined;\n}\n\n/**\n * A special usecase for incorrectly wrapped Fetch APIs in conjunction with ad-blockers.\n * Whenever someone wraps the Fetch API and returns the wrong promise chain,\n * this chain becomes orphaned and there is no possible way to capture it's rejections\n * other than allowing it bubble up to this very handler. eg.\n *\n * const f = window.fetch;\n * window.fetch = function () {\n * const p = f.apply(this, arguments);\n *\n * p.then(function() {\n * console.log('hi.');\n * });\n *\n * return p;\n * }\n *\n * `p.then(function () { ... })` is producing a completely separate promise chain,\n * however, what's returned is `p` - the result of original `fetch` call.\n *\n * This mean, that whenever we use the Fetch API to send our own requests, _and_\n * some ad-blocker blocks it, this orphaned chain will _always_ reject,\n * effectively causing another event to be captured.\n * This makes a whole process become an infinite loop, which we need to somehow\n * deal with, and break it in one way or another.\n *\n * To deal with this issue, we are making sure that we _always_ use the real\n * browser Fetch API, instead of relying on what `window.fetch` exposes.\n * The only downside to this would be missing our own requests as breadcrumbs,\n * but because we are already not doing this, it should be just fine.\n *\n * Possible failed fetch error messages per-browser:\n *\n * Chrome: Failed to fetch\n * Edge: Failed to Fetch\n * Firefox: NetworkError when attempting to fetch resource\n * Safari: resource blocked by content blocker\n */\nexport function fetch(...rest: Parameters<typeof WINDOW.fetch>): ReturnType<typeof WINDOW.fetch> {\n return getNativeImplementation('fetch')(...rest);\n}\n\n/**\n * Get an unwrapped `setTimeout` method.\n * This ensures that even if e.g. Angular wraps `setTimeout`, we get the native implementation,\n * avoiding triggering change detection.\n */\nexport function setTimeout(...rest: Parameters<typeof WINDOW.setTimeout>): ReturnType<typeof WINDOW.setTimeout> {\n return getNativeImplementation('setTimeout')(...rest);\n}\n"],"names":[],"mappings":";;;;AAeA,MAAM,wBAA2D,EAAC;AAW3D,SAAS,wBACd,IAAA,EAC6B;AAC7B,EAAA,MAAM,MAAA,GAAS,sBAAsB,IAAI,CAAA;AACzC,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,GAAO,OAAO,IAAI,CAAA;AAGtB,EAAA,IAAI,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC1B,IAAA,OAAQ,qBAAA,CAAsB,IAAI,CAAA,GAAI,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,EACxD;AAEA,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AAExB,EAAA,IAAI,QAAA,IAAY,OAAO,QAAA,CAAS,aAAA,KAAkB,UAAA,EAAY;AAC5D,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC/C,MAAA,OAAA,CAAQ,MAAA,GAAS,IAAA;AACjB,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,OAAO,CAAA;AACjC,MAAA,MAAM,gBAAgB,OAAA,CAAQ,aAAA;AAC9B,MAAA,IAAI,aAAA,GAAgB,IAAI,CAAA,EAAG;AACzB,QAAA,IAAA,GAAO,cAAc,IAAI,CAAA;AAAA,MAC3B;AACA,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,OAAO,CAAA;AAAA,IACnC,SAAS,CAAA,EAAG;AAEV,MAAA,WAAA,IAAe,MAAM,IAAA,CAAK,CAAA,oCAAA,EAAuC,IAAI,CAAA,0BAAA,EAA6B,IAAI,MAAM,CAAC,CAAA;AAAA,IAC/G;AAAA,EACF;AAIA,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAQ,qBAAA,CAAsB,IAAI,CAAA,GAAI,IAAA,CAAK,KAAK,MAAM,CAAA;AACxD;AAGO,SAAS,0BAA0B,IAAA,EAA4C;AACpF,EAAA,qBAAA,CAAsB,IAAI,CAAA,GAAI,MAAA;AAChC;AAwCO,SAAS,SAAS,IAAA,EAAwE;AAC/F,EAAA,OAAO,uBAAA,CAAwB,OAAO,CAAA,CAAE,GAAG,IAAI,CAAA;AACjD;AAOO,SAAS,cAAc,IAAA,EAAkF;AAC9G,EAAA,OAAO,uBAAA,CAAwB,YAAY,CAAA,CAAE,GAAG,IAAI,CAAA;AACtD;;;;"}
1
+ {"version":3,"file":"getNativeImplementation.js","sources":["../../src/getNativeImplementation.ts"],"sourcesContent":["import { debug, isNativeFunction } from '@sentry/core';\nimport { DEBUG_BUILD } from './debug-build';\nimport { WINDOW } from './types';\n\n/**\n * We generally want to use window.fetch / window.setTimeout.\n * However, in some cases this may be wrapped (e.g. by Zone.js for Angular),\n * so we try to get an unpatched version of this from a sandboxed iframe.\n */\n\ninterface CacheableImplementations {\n setTimeout: typeof WINDOW.setTimeout;\n fetch: typeof WINDOW.fetch;\n}\n\nconst cachedImplementations: Partial<CacheableImplementations> = {};\n\n/**\n * Get the native implementation of a browser function.\n *\n * This can be used to ensure we get an unwrapped version of a function, in cases where a wrapped function can lead to problems.\n *\n * The following methods can be retrieved:\n * - `setTimeout`: This can be wrapped by e.g. Angular, causing change detection to be triggered.\n * - `fetch`: This can be wrapped by e.g. ad-blockers, causing an infinite loop when a request is blocked.\n */\nexport function getNativeImplementation<T extends keyof CacheableImplementations>(\n name: T,\n): CacheableImplementations[T] {\n const cached = cachedImplementations[name];\n if (cached) {\n return cached;\n }\n\n let impl = WINDOW[name] as CacheableImplementations[T];\n\n // Fast path to avoid DOM I/O\n if (isNativeFunction(impl)) {\n return (cachedImplementations[name] = impl.bind(WINDOW) as CacheableImplementations[T]);\n }\n\n const document = WINDOW.document;\n // eslint-disable-next-line typescript/no-deprecated\n if (document && typeof document.createElement === 'function') {\n try {\n const sandbox = document.createElement('iframe');\n sandbox.hidden = true;\n document.head.appendChild(sandbox);\n const contentWindow = sandbox.contentWindow;\n if (contentWindow?.[name]) {\n impl = contentWindow[name] as CacheableImplementations[T];\n }\n document.head.removeChild(sandbox);\n } catch (e) {\n // Could not create sandbox iframe, just use window.xxx\n DEBUG_BUILD && debug.warn(`Could not create sandbox iframe for ${name} check, bailing to window.${name}: `, e);\n }\n }\n\n // Sanity check: This _should_ not happen, but if it does, we just skip caching...\n // This can happen e.g. in tests where fetch may not be available in the env, or similar.\n if (!impl) {\n return impl;\n }\n\n return (cachedImplementations[name] = impl.bind(WINDOW) as CacheableImplementations[T]);\n}\n\n/** Clear a cached implementation. */\nexport function clearCachedImplementation(name: keyof CacheableImplementations): void {\n cachedImplementations[name] = undefined;\n}\n\n/**\n * A special usecase for incorrectly wrapped Fetch APIs in conjunction with ad-blockers.\n * Whenever someone wraps the Fetch API and returns the wrong promise chain,\n * this chain becomes orphaned and there is no possible way to capture it's rejections\n * other than allowing it bubble up to this very handler. eg.\n *\n * const f = window.fetch;\n * window.fetch = function () {\n * const p = f.apply(this, arguments);\n *\n * p.then(function() {\n * console.log('hi.');\n * });\n *\n * return p;\n * }\n *\n * `p.then(function () { ... })` is producing a completely separate promise chain,\n * however, what's returned is `p` - the result of original `fetch` call.\n *\n * This mean, that whenever we use the Fetch API to send our own requests, _and_\n * some ad-blocker blocks it, this orphaned chain will _always_ reject,\n * effectively causing another event to be captured.\n * This makes a whole process become an infinite loop, which we need to somehow\n * deal with, and break it in one way or another.\n *\n * To deal with this issue, we are making sure that we _always_ use the real\n * browser Fetch API, instead of relying on what `window.fetch` exposes.\n * The only downside to this would be missing our own requests as breadcrumbs,\n * but because we are already not doing this, it should be just fine.\n *\n * Possible failed fetch error messages per-browser:\n *\n * Chrome: Failed to fetch\n * Edge: Failed to Fetch\n * Firefox: NetworkError when attempting to fetch resource\n * Safari: resource blocked by content blocker\n */\nexport function fetch(...rest: Parameters<typeof WINDOW.fetch>): ReturnType<typeof WINDOW.fetch> {\n return getNativeImplementation('fetch')(...rest);\n}\n\n/**\n * Get an unwrapped `setTimeout` method.\n * This ensures that even if e.g. Angular wraps `setTimeout`, we get the native implementation,\n * avoiding triggering change detection.\n */\nexport function setTimeout(...rest: Parameters<typeof WINDOW.setTimeout>): ReturnType<typeof WINDOW.setTimeout> {\n try {\n return getNativeImplementation('setTimeout')(...rest);\n } catch (e) {\n // The implementation retrieved from the (since removed) sandbox iframe may throw when invoked,\n // e.g. Firefox throws `NS_ERROR_NOT_INITIALIZED` for timers of a detached window.\n // In this case, fall back to (and cache) the window's own setTimeout.\n DEBUG_BUILD && debug.warn('Could not use native setTimeout implementation, falling back to window.setTimeout: ', e);\n const fallback = WINDOW.setTimeout.bind(WINDOW) as typeof WINDOW.setTimeout;\n cachedImplementations.setTimeout = fallback;\n return fallback(...rest);\n }\n}\n"],"names":[],"mappings":";;;;AAeA,MAAM,wBAA2D,EAAC;AAW3D,SAAS,wBACd,IAAA,EAC6B;AAC7B,EAAA,MAAM,MAAA,GAAS,sBAAsB,IAAI,CAAA;AACzC,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,IAAA,GAAO,OAAO,IAAI,CAAA;AAGtB,EAAA,IAAI,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC1B,IAAA,OAAQ,qBAAA,CAAsB,IAAI,CAAA,GAAI,IAAA,CAAK,KAAK,MAAM,CAAA;AAAA,EACxD;AAEA,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA;AAExB,EAAA,IAAI,QAAA,IAAY,OAAO,QAAA,CAAS,aAAA,KAAkB,UAAA,EAAY;AAC5D,IAAA,IAAI;AACF,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC/C,MAAA,OAAA,CAAQ,MAAA,GAAS,IAAA;AACjB,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,OAAO,CAAA;AACjC,MAAA,MAAM,gBAAgB,OAAA,CAAQ,aAAA;AAC9B,MAAA,IAAI,aAAA,GAAgB,IAAI,CAAA,EAAG;AACzB,QAAA,IAAA,GAAO,cAAc,IAAI,CAAA;AAAA,MAC3B;AACA,MAAA,QAAA,CAAS,IAAA,CAAK,YAAY,OAAO,CAAA;AAAA,IACnC,SAAS,CAAA,EAAG;AAEV,MAAA,WAAA,IAAe,MAAM,IAAA,CAAK,CAAA,oCAAA,EAAuC,IAAI,CAAA,0BAAA,EAA6B,IAAI,MAAM,CAAC,CAAA;AAAA,IAC/G;AAAA,EACF;AAIA,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAQ,qBAAA,CAAsB,IAAI,CAAA,GAAI,IAAA,CAAK,KAAK,MAAM,CAAA;AACxD;AAGO,SAAS,0BAA0B,IAAA,EAA4C;AACpF,EAAA,qBAAA,CAAsB,IAAI,CAAA,GAAI,MAAA;AAChC;AAwCO,SAAS,SAAS,IAAA,EAAwE;AAC/F,EAAA,OAAO,uBAAA,CAAwB,OAAO,CAAA,CAAE,GAAG,IAAI,CAAA;AACjD;AAOO,SAAS,cAAc,IAAA,EAAkF;AAC9G,EAAA,IAAI;AACF,IAAA,OAAO,uBAAA,CAAwB,YAAY,CAAA,CAAE,GAAG,IAAI,CAAA;AAAA,EACtD,SAAS,CAAA,EAAG;AAIV,IAAA,WAAA,IAAe,KAAA,CAAM,IAAA,CAAK,qFAAA,EAAuF,CAAC,CAAA;AAClH,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,UAAA,CAAW,IAAA,CAAK,MAAM,CAAA;AAC9C,IAAA,qBAAA,CAAsB,UAAA,GAAa,QAAA;AACnC,IAAA,OAAO,QAAA,CAAS,GAAG,IAAI,CAAA;AAAA,EACzB;AACF;;;;"}
@@ -1 +1 @@
1
- {"type":"module","version":"11.3.0","sideEffects":false}
1
+ {"type":"module","version":"11.5.0","sideEffects":false}
@@ -1,5 +1,5 @@
1
- import { browserPerformanceTimeOrigin, spanToJSON, getActiveSpan, UI_LONG_TASK_SPAN_NAME_FALLBACK, parseUrl, filterCollectedUrl, RESOURCE_SPAN_NAME_FALLBACK, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, setMeasurement, BROWSER_NAVIGATION_TIMING_SPAN_NAMES } from '@sentry/core';
2
- import { SENTRY_OP, CODE_FILE_PATH, CODE_FUNCTION_NAME, BROWSER_PAINT_TYPE, NETWORK_CONNECTION_EFFECTIVE_TYPE, NETWORK_CONNECTION_TYPE, NETWORK_CONNECTION_RTT, URL_FULL, URL_SCHEME, SERVER_ADDRESS, URL_DOMAIN, HTTP_REQUEST_SAME_ORIGIN, HTTP_RESPONSE_STATUS_CODE, HTTP_RESPONSE_SIZE, HTTP_RESPONSE_BODY_SIZE } from '@sentry/conventions/attributes';
1
+ import { browserPerformanceTimeOrigin, spanToJSON, getActiveSpan, UI_LONG_TASK_SPAN_NAME_FALLBACK, parseUrl, filterCollectedUrl, RESOURCE_SPAN_NAME_FALLBACK, setMeasurement, BROWSER_NAVIGATION_TIMING_SPAN_NAMES } from '@sentry/core';
2
+ import { SENTRY_OP, CODE_FILE_PATH, CODE_FUNCTION_NAME, BROWSER_PAINT_TYPE, SENTRY_ORIGIN, NETWORK_CONNECTION_EFFECTIVE_TYPE, NETWORK_CONNECTION_TYPE, NETWORK_CONNECTION_RTT, URL_FULL, URL_SCHEME, SERVER_ADDRESS, URL_DOMAIN, HTTP_REQUEST_SAME_ORIGIN, HTTP_RESPONSE_STATUS_CODE, HTTP_RESPONSE_SIZE, HTTP_RESPONSE_BODY_SIZE } from '@sentry/conventions/attributes';
3
3
  import { UI_LONG_ANIMATION_FRAME, RESOURCE_OTHER, BROWSER_PAINT, BROWSER_LOAD_EVENT, BROWSER_DOM_CONTENT_LOADED_EVENT, BROWSER_CONNECT, BROWSER_REDIRECT, BROWSER_UNLOAD_EVENT, BROWSER_DNS, BROWSER_CACHE, BROWSER_TLS_SSL, BROWSER_REQUEST, BROWSER_RESPONSE, UI_LONG_TASK } from '@sentry/conventions/op';
4
4
  import { addPerformanceInstrumentationHandler } from '../instrumentation/performanceObserver.js';
5
5
  import { WINDOW } from '../types.js';
@@ -25,7 +25,7 @@ function startTrackingLongTasks() {
25
25
  name: UI_LONG_TASK_SPAN_NAME_FALLBACK,
26
26
  op: UI_LONG_TASK,
27
27
  attributes: {
28
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics"
28
+ [SENTRY_ORIGIN]: "auto.ui.browser.metrics"
29
29
  }
30
30
  });
31
31
  }
@@ -51,7 +51,7 @@ function startTrackingLongAnimationFrames() {
51
51
  }
52
52
  const duration = msToSec(entry.duration);
53
53
  const attributes = {
54
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics"
54
+ [SENTRY_ORIGIN]: "auto.ui.browser.metrics"
55
55
  };
56
56
  const initialScript = entry.scripts[0];
57
57
  const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;
@@ -132,7 +132,7 @@ function _addPaintSpan(span, entry, startTime, duration, timeOrigin) {
132
132
  name: entry.name,
133
133
  attributes: {
134
134
  [SENTRY_OP]: BROWSER_PAINT,
135
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.resource.browser.metrics",
135
+ [SENTRY_ORIGIN]: "auto.resource.browser.metrics",
136
136
  [BROWSER_PAINT_TYPE]: entry.name
137
137
  }
138
138
  });
@@ -172,7 +172,7 @@ function _addPerformanceNavigationTiming(span, entry, event, timeOrigin, spanStr
172
172
  name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[op] : entry.name,
173
173
  attributes: {
174
174
  [SENTRY_OP]: op,
175
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics",
175
+ [SENTRY_ORIGIN]: "auto.ui.browser.metrics",
176
176
  [URL_FULL]: filterCollectedUrl(entry.name),
177
177
  ...event === "redirect" && entry.redirectCount != null ? { "http.redirect_count": entry.redirectCount } : {}
178
178
  }
@@ -197,7 +197,7 @@ function _addRequest(span, entry, timeOrigin, spanStreamingEnabled) {
197
197
  name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_REQUEST] : entry.name,
198
198
  attributes: {
199
199
  [SENTRY_OP]: BROWSER_REQUEST,
200
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics",
200
+ [SENTRY_ORIGIN]: "auto.ui.browser.metrics",
201
201
  [URL_FULL]: url
202
202
  }
203
203
  });
@@ -205,7 +205,7 @@ function _addRequest(span, entry, timeOrigin, spanStreamingEnabled) {
205
205
  name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_RESPONSE] : entry.name,
206
206
  attributes: {
207
207
  [SENTRY_OP]: BROWSER_RESPONSE,
208
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.ui.browser.metrics",
208
+ [SENTRY_ORIGIN]: "auto.ui.browser.metrics",
209
209
  [URL_FULL]: url
210
210
  }
211
211
  });
@@ -220,7 +220,7 @@ function _addResourceSpans(span, entry, resourceUrl, startTime, duration, timeOr
220
220
  return;
221
221
  }
222
222
  const attributes = {
223
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.resource.browser.metrics"
223
+ [SENTRY_ORIGIN]: "auto.resource.browser.metrics"
224
224
  };
225
225
  const parsedUrl = parseUrl(resourceUrl);
226
226
  if (parsedUrl.protocol) {
@@ -1 +1 @@
1
- {"version":3,"file":"entries.js","sources":["../../../src/performance/entries.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n BROWSER_NAVIGATION_TIMING_SPAN_NAMES,\n browserPerformanceTimeOrigin,\n getActiveSpan,\n parseUrl,\n RESOURCE_SPAN_NAME_FALLBACK,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n setMeasurement,\n spanToJSON,\n filterCollectedUrl,\n UI_LONG_TASK_SPAN_NAME_FALLBACK,\n} from '@sentry/core';\nimport {\n BROWSER_PAINT_TYPE,\n CODE_FILE_PATH,\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_SAME_ORIGIN,\n HTTP_RESPONSE_BODY_SIZE,\n HTTP_RESPONSE_SIZE,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_CONNECTION_EFFECTIVE_TYPE,\n NETWORK_CONNECTION_RTT,\n NETWORK_CONNECTION_TYPE,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FULL,\n URL_SCHEME,\n} from '@sentry/conventions/attributes';\nimport {\n BROWSER_CACHE,\n BROWSER_CONNECT,\n BROWSER_DNS,\n BROWSER_DOM_CONTENT_LOADED_EVENT,\n BROWSER_LOAD_EVENT,\n BROWSER_PAINT,\n BROWSER_REDIRECT,\n BROWSER_REQUEST,\n BROWSER_RESPONSE,\n BROWSER_TLS_SSL,\n BROWSER_UNLOAD_EVENT,\n RESOURCE_OTHER,\n UI_LONG_ANIMATION_FRAME,\n UI_LONG_TASK,\n} from '@sentry/conventions/op';\nimport {\n addPerformanceInstrumentationHandler,\n type PerformanceLongAnimationFrameTiming,\n} from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\nimport { resourceTimingToSpanAttributes } from './resourceTiming';\nimport { getBrowserPerformanceAPI, isMeasurementValue, msToSec, startAndEndSpan } from './utils';\n\ninterface NavigatorNetworkInformation {\n readonly connection?: NetworkInformation;\n}\n\n// http://wicg.github.io/netinfo/#connection-types\ntype ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';\n\n// http://wicg.github.io/netinfo/#effectiveconnectiontype-enum\ntype EffectiveConnectionType = '2g' | '3g' | '4g' | 'slow-2g';\n\n// http://wicg.github.io/netinfo/#dom-megabit\ntype Megabit = number;\n// http://wicg.github.io/netinfo/#dom-millisecond\ntype Millisecond = number;\n\n// http://wicg.github.io/netinfo/#networkinformation-interface\ninterface NetworkInformation extends EventTarget {\n // http://wicg.github.io/netinfo/#type-attribute\n readonly type?: ConnectionType;\n // http://wicg.github.io/netinfo/#effectivetype-attribute\n readonly effectiveType?: EffectiveConnectionType;\n // http://wicg.github.io/netinfo/#downlinkmax-attribute\n readonly downlinkMax?: Megabit;\n // http://wicg.github.io/netinfo/#downlink-attribute\n readonly downlink?: Megabit;\n // http://wicg.github.io/netinfo/#rtt-attribute\n readonly rtt?: Millisecond;\n // http://wicg.github.io/netinfo/#savedata-attribute\n readonly saveData?: boolean;\n // http://wicg.github.io/netinfo/#handling-changes-to-the-underlying-connection\n onchange?: EventListener;\n}\n\n// https://w3c.github.io/device-memory/#sec-device-memory-js-api\ninterface NavigatorDeviceMemory {\n readonly deviceMemory?: number;\n}\n\nconst MAX_INT_AS_BYTES = 2147483647;\n\nlet _performanceCursor: number = 0;\n\n/**\n * Start tracking long tasks.\n */\nexport function startTrackingLongTasks(): void {\n addPerformanceInstrumentationHandler('longtask', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n\n const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = spanToJSON(parent);\n\n for (const entry of entries) {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n if (parentAttributes[SENTRY_OP] === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding a span if the long task started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: UI_LONG_TASK_SPAN_NAME_FALLBACK,\n op: UI_LONG_TASK,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n });\n}\n\n/**\n * Start tracking long animation frames.\n */\nexport function startTrackingLongAnimationFrames(): void {\n // NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so\n // we directly observe `long-animation-frame` events instead of through the web-vitals\n // `observe` helper function.\n const observer = new PerformanceObserver(list => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of list.getEntries() as PerformanceLongAnimationFrameTiming[]) {\n if (!entry.scripts[0]) {\n continue;\n }\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n\n const {\n start_timestamp: parentStartTimestamp,\n attributes: { [SENTRY_OP]: parentOp },\n } = spanToJSON(parent);\n\n if (parentOp === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding the span if the long animation frame started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n const duration = msToSec(entry.duration);\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n };\n\n const initialScript = entry.scripts[0];\n const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;\n attributes['browser.script.invoker'] = invoker;\n attributes['browser.script.invoker_type'] = invokerType;\n if (sourceURL) {\n attributes[CODE_FILE_PATH] = sourceURL;\n }\n if (sourceFunctionName) {\n attributes[CODE_FUNCTION_NAME] = sourceFunctionName;\n }\n if (sourceCharPosition !== -1) {\n attributes['browser.script.source_char_position'] = sourceCharPosition;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: UI_LONG_TASK_SPAN_NAME_FALLBACK,\n op: UI_LONG_ANIMATION_FRAME,\n attributes,\n });\n }\n });\n\n observer.observe({ type: 'long-animation-frame', buffered: true });\n}\n\ninterface AddPerformanceEntriesOptions {\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/** Add performance related spans to a transaction */\nexport function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void {\n const performance = getBrowserPerformanceAPI();\n const origin = browserPerformanceTimeOrigin();\n if (!performance?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n return;\n }\n\n const { spanStreamingEnabled, ignoreResourceSpans } = options;\n\n const timeOrigin = msToSec(origin);\n\n const performanceEntries = performance.getEntries();\n\n const { attributes, start_timestamp: transactionStartTime } = spanToJSON(span);\n\n performanceEntries.slice(_performanceCursor).forEach(entry => {\n const startTime = msToSec(entry.startTime);\n const duration = msToSec(\n // Inexplicably, Chrome sometimes emits a negative duration. We need to work around this.\n // There is a SO post attempting to explain this, but it leaves one with open questions: https://stackoverflow.com/questions/23191918/peformance-getentries-and-negative-duration-display\n // The way we clamp the value is probably not accurate, since we have observed this happen for things that may take a while to load, like for example the replay worker.\n // TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.\n Math.max(0, entry.duration),\n );\n\n if (\n attributes[SENTRY_OP] === 'navigation' &&\n transactionStartTime &&\n timeOrigin + startTime < transactionStartTime\n ) {\n return;\n }\n\n switch (entry.entryType) {\n case 'navigation': {\n _addNavigationSpans(span, entry as PerformanceNavigationTiming, timeOrigin, spanStreamingEnabled);\n break;\n }\n case 'paint': {\n _addPaintSpan(span, entry, startTime, duration, timeOrigin);\n break;\n }\n case 'resource': {\n _addResourceSpans(\n span,\n entry as PerformanceResourceTiming,\n entry.name,\n startTime,\n duration,\n timeOrigin,\n ignoreResourceSpans,\n spanStreamingEnabled,\n );\n break;\n }\n // Ignore other entry types.\n }\n });\n\n _performanceCursor = Math.max(performanceEntries.length - 1, 0);\n\n _trackNavigator(span, spanStreamingEnabled);\n}\n\n/**\n * Create a span for a browser paint performance entry.\n * Exported only for tests.\n */\nexport function _addPaintSpan(\n span: Span,\n entry: PerformanceEntry,\n startTime: number,\n duration: number,\n timeOrigin: number,\n): void {\n const startTimestamp = timeOrigin + startTime;\n\n startAndEndSpan(span, startTimestamp, startTimestamp + duration, {\n // The entry name (`first-paint`, `first-contentful-paint`) is already the low-cardinality name\n // the conventions ask for, so only the attribute backing it has to be added.\n name: entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_PAINT,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n [BROWSER_PAINT_TYPE]: entry.name,\n },\n });\n}\n\n/**\n * Instrument navigation entries\n * exported only for tests\n */\nexport function _addNavigationSpans(\n span: Span,\n entry: PerformanceNavigationTiming,\n timeOrigin: number,\n spanStreamingEnabled?: boolean,\n): void {\n _addPerformanceNavigationTiming(span, entry, 'unloadEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'redirect', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'domContentLoadedEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'loadEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'connect', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'secureConnection', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'fetch', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'domainLookup', timeOrigin, spanStreamingEnabled);\n\n _addRequest(span, entry, timeOrigin, spanStreamingEnabled);\n}\n\ntype StartEventName =\n | 'secureConnection'\n | 'fetch'\n | 'domainLookup'\n | 'unloadEvent'\n | 'redirect'\n | 'connect'\n | 'domContentLoadedEvent'\n | 'loadEvent';\n\nconst NAVIGATION_TIMING_SPAN_OPS = {\n secureConnection: BROWSER_TLS_SSL,\n fetch: BROWSER_CACHE,\n domainLookup: BROWSER_DNS,\n unloadEvent: BROWSER_UNLOAD_EVENT,\n redirect: BROWSER_REDIRECT,\n connect: BROWSER_CONNECT,\n domContentLoadedEvent: BROWSER_DOM_CONTENT_LOADED_EVENT,\n loadEvent: BROWSER_LOAD_EVENT,\n} as const satisfies Record<StartEventName, string>;\n\ntype EndEventName =\n | 'domainLookupStart'\n | 'domainLookupEnd'\n | 'unloadEventEnd'\n | 'redirectEnd'\n | 'connectEnd'\n | 'domContentLoadedEventEnd'\n | 'loadEventEnd';\n\n/** Create performance navigation related spans */\nfunction _addPerformanceNavigationTiming(\n span: Span,\n entry: PerformanceNavigationTiming,\n event: StartEventName,\n timeOrigin: number,\n spanStreamingEnabled: boolean | undefined,\n): void {\n const eventEnd = _getEndPropertyNameForNavigationTiming(event) satisfies keyof PerformanceNavigationTiming;\n const end = entry[eventEnd];\n const start = entry[`${event}Start`];\n if (!start || !end) {\n return;\n }\n const op = NAVIGATION_TIMING_SPAN_OPS[event];\n startAndEndSpan(span, timeOrigin + msToSec(start), timeOrigin + msToSec(end), {\n // With span streaming, span names have to be low cardinality, so we can't fall back to the\n // document URL. `url.full` keeps it, and is what Relay derives the description from.\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[op] : entry.name,\n attributes: {\n [SENTRY_OP]: op,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: filterCollectedUrl(entry.name),\n ...(event === 'redirect' && entry.redirectCount != null ? { 'http.redirect_count': entry.redirectCount } : {}),\n },\n });\n}\n\nfunction _getEndPropertyNameForNavigationTiming(event: StartEventName): EndEventName {\n if (event === 'secureConnection') {\n return 'connectEnd';\n }\n if (event === 'fetch') {\n return 'domainLookupStart';\n }\n return `${event}End`;\n}\n\n/** Create request and response related spans */\nfunction _addRequest(\n span: Span,\n entry: PerformanceNavigationTiming,\n timeOrigin: number,\n spanStreamingEnabled: boolean | undefined,\n): void {\n const requestStartTimestamp = timeOrigin + msToSec(entry.requestStart);\n const responseEndTimestamp = timeOrigin + msToSec(entry.responseEnd);\n const responseStartTimestamp = timeOrigin + msToSec(entry.responseStart);\n if (entry.responseEnd) {\n // It is possible that we are collecting these metrics when the page hasn't finished loading yet, for example when the HTML slowly streams in.\n // In this case, ie. when the document request hasn't finished yet, `entry.responseEnd` will be 0.\n // In order not to produce faulty spans, where the end timestamp is before the start timestamp, we will only collect\n // these spans when the responseEnd value is available. The backend (Relay) would drop the entire span if it contained faulty spans.\n\n // With span streaming, span names have to be low cardinality, so we can't fall back to the\n // document URL. `url.full` keeps it, and is what Relay derives the description from.\n const url = filterCollectedUrl(entry.name);\n\n startAndEndSpan(span, requestStartTimestamp, responseEndTimestamp, {\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_REQUEST] : entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_REQUEST,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: url,\n },\n });\n\n startAndEndSpan(span, responseStartTimestamp, responseEndTimestamp, {\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_RESPONSE] : entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_RESPONSE,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: url,\n },\n });\n }\n}\n\n/**\n * Create resource-related spans.\n * Exported only for tests.\n */\nexport function _addResourceSpans(\n span: Span,\n entry: PerformanceResourceTiming,\n resourceUrl: string,\n startTime: number,\n duration: number,\n timeOrigin: number,\n ignoredResourceSpanOps?: Array<string>,\n spanStreamingEnabled?: boolean,\n): void {\n // we already instrument based on fetch and xhr, so we don't need to\n // duplicate spans here.\n if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {\n return;\n }\n\n const op = entry.initiatorType ? `resource.${entry.initiatorType}` : RESOURCE_OTHER;\n if (ignoredResourceSpanOps?.includes(op)) {\n return;\n }\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n };\n\n const parsedUrl = parseUrl(resourceUrl);\n\n if (parsedUrl.protocol) {\n attributes[URL_SCHEME] = parsedUrl.protocol.split(':').pop(); // the protocol returned by parseUrl includes a :, but OTEL spec does not, so we remove it.\n }\n\n // `host` is the URL authority, so it can carry userinfo, which doesn't belong on either attribute.\n const host = parsedUrl.host?.replace(/^.*@/, '');\n\n if (host) {\n attributes[SERVER_ADDRESS] = host;\n }\n\n // Unlike `server.address`, `url.domain` excludes the port.\n const domain = host?.replace(/:\\d+$/, '');\n\n if (domain) {\n attributes[URL_DOMAIN] = domain;\n }\n\n attributes[HTTP_REQUEST_SAME_ORIGIN] = resourceUrl.includes(WINDOW.location.origin);\n\n attributes[URL_FULL] = filterCollectedUrl(resourceUrl);\n\n _setResourceRequestAttributes(entry, attributes, [\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n ['responseStatus', HTTP_RESPONSE_STATUS_CODE],\n\n ['transferSize', HTTP_RESPONSE_SIZE],\n ['encodedBodySize', HTTP_RESPONSE_BODY_SIZE],\n ['decodedBodySize', 'http.response.body.decoded_size'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus\n ['renderBlockingStatus', 'resource.render_blocking_status'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n ['deliveryType', 'http.response_delivery_type'],\n ]);\n\n const attributesWithResourceTiming: SpanAttributes = { ...attributes, ...resourceTimingToSpanAttributes(entry) };\n\n const startTimestamp = timeOrigin + startTime;\n const endTimestamp = startTimestamp + duration;\n\n startAndEndSpan(span, startTimestamp, endTimestamp, {\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n name: spanStreamingEnabled\n ? domain || RESOURCE_SPAN_NAME_FALLBACK\n : resourceUrl.replace(WINDOW.location.origin, ''),\n op,\n attributes: attributesWithResourceTiming,\n });\n}\n\n/**\n * Capture the information of the user agent.\n * TODO(v12): Remove non-span-streaming attributes and measurements once the static trace lifecycle is removed\n */\nfunction _trackNavigator(span: Span, spanStreamingEnabled: boolean | undefined): void {\n const navigator = WINDOW.navigator as null | (Navigator & NavigatorNetworkInformation & NavigatorDeviceMemory);\n if (!navigator) {\n return;\n }\n\n // track network connectivity\n const connection = navigator.connection;\n if (connection) {\n if (connection.effectiveType) {\n span.setAttribute(\n spanStreamingEnabled ? NETWORK_CONNECTION_EFFECTIVE_TYPE : 'effectiveConnectionType',\n connection.effectiveType,\n );\n }\n\n if (connection.type) {\n span.setAttribute(spanStreamingEnabled ? NETWORK_CONNECTION_TYPE : 'connectionType', connection.type);\n }\n\n if (isMeasurementValue(connection.rtt)) {\n if (spanStreamingEnabled) {\n span.setAttribute(NETWORK_CONNECTION_RTT, connection.rtt);\n } else if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n // Measurements are only recorded on the pageload span, matching the historical\n // behavior where `connection.rtt` was only flushed for pageload transactions.\n setMeasurement('connection.rtt', connection.rtt, 'millisecond');\n }\n }\n }\n\n if (isMeasurementValue(navigator.deviceMemory)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.memory.estimated_capacity', navigator.deviceMemory);\n } else {\n span.setAttribute('deviceMemory', `${navigator.deviceMemory} GB`);\n }\n }\n\n if (isMeasurementValue(navigator.hardwareConcurrency)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.processor_count', navigator.hardwareConcurrency);\n } else {\n span.setAttribute('hardwareConcurrency', String(navigator.hardwareConcurrency));\n }\n }\n}\n\ntype ExperimentalResourceTimingProperty =\n | 'renderBlockingStatus'\n | 'deliveryType'\n // For some reason, TS during build, errors on `responseStatus` not being a property of\n // PerformanceResourceTiming while it actually is. Hence, we're adding it here.\n // Perhaps because response status is not yet available in Webkit/Safari.\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n | 'responseStatus';\n\n/**\n * Use this to set any attributes we can take directly form the PerformanceResourceTiming entry.\n *\n * This is just a mapping function for entry->attribute to keep bundle-size minimal.\n * Experimental properties are also accepted (see {@link ExperimentalResourceTimingProperty}).\n * Assumes that all entry properties might be undefined for browser-specific differences.\n * Only accepts string and number values for now and also sets 0-values.\n */\nexport function _setResourceRequestAttributes(\n entry: Partial<PerformanceResourceTiming> & Partial<Record<ExperimentalResourceTimingProperty, number | string>>,\n attributes: SpanAttributes,\n properties: [keyof PerformanceResourceTiming | ExperimentalResourceTimingProperty, string][],\n): void {\n properties.forEach(([entryKey, attributeKey]) => {\n const entryVal = entry[entryKey];\n if (\n entryVal != null &&\n ((typeof entryVal === 'number' && entryVal < MAX_INT_AS_BYTES) || typeof entryVal === 'string')\n ) {\n attributes[attributeKey] = entryVal;\n }\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"entries.js","sources":["../../../src/performance/entries.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Span, SpanAttributes } from '@sentry/core';\nimport {\n BROWSER_NAVIGATION_TIMING_SPAN_NAMES,\n browserPerformanceTimeOrigin,\n getActiveSpan,\n parseUrl,\n RESOURCE_SPAN_NAME_FALLBACK,\n setMeasurement,\n spanToJSON,\n filterCollectedUrl,\n UI_LONG_TASK_SPAN_NAME_FALLBACK,\n} from '@sentry/core';\nimport {\n BROWSER_PAINT_TYPE,\n CODE_FILE_PATH,\n CODE_FUNCTION_NAME,\n HTTP_REQUEST_SAME_ORIGIN,\n HTTP_RESPONSE_BODY_SIZE,\n HTTP_RESPONSE_SIZE,\n HTTP_RESPONSE_STATUS_CODE,\n NETWORK_CONNECTION_EFFECTIVE_TYPE,\n NETWORK_CONNECTION_RTT,\n NETWORK_CONNECTION_TYPE,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FULL,\n URL_SCHEME,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport {\n BROWSER_CACHE,\n BROWSER_CONNECT,\n BROWSER_DNS,\n BROWSER_DOM_CONTENT_LOADED_EVENT,\n BROWSER_LOAD_EVENT,\n BROWSER_PAINT,\n BROWSER_REDIRECT,\n BROWSER_REQUEST,\n BROWSER_RESPONSE,\n BROWSER_TLS_SSL,\n BROWSER_UNLOAD_EVENT,\n RESOURCE_OTHER,\n UI_LONG_ANIMATION_FRAME,\n UI_LONG_TASK,\n} from '@sentry/conventions/op';\nimport {\n addPerformanceInstrumentationHandler,\n type PerformanceLongAnimationFrameTiming,\n} from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\nimport { resourceTimingToSpanAttributes } from './resourceTiming';\nimport { getBrowserPerformanceAPI, isMeasurementValue, msToSec, startAndEndSpan } from './utils';\n\ninterface NavigatorNetworkInformation {\n readonly connection?: NetworkInformation;\n}\n\n// http://wicg.github.io/netinfo/#connection-types\ntype ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'mixed' | 'none' | 'other' | 'unknown' | 'wifi' | 'wimax';\n\n// http://wicg.github.io/netinfo/#effectiveconnectiontype-enum\ntype EffectiveConnectionType = '2g' | '3g' | '4g' | 'slow-2g';\n\n// http://wicg.github.io/netinfo/#dom-megabit\ntype Megabit = number;\n// http://wicg.github.io/netinfo/#dom-millisecond\ntype Millisecond = number;\n\n// http://wicg.github.io/netinfo/#networkinformation-interface\ninterface NetworkInformation extends EventTarget {\n // http://wicg.github.io/netinfo/#type-attribute\n readonly type?: ConnectionType;\n // http://wicg.github.io/netinfo/#effectivetype-attribute\n readonly effectiveType?: EffectiveConnectionType;\n // http://wicg.github.io/netinfo/#downlinkmax-attribute\n readonly downlinkMax?: Megabit;\n // http://wicg.github.io/netinfo/#downlink-attribute\n readonly downlink?: Megabit;\n // http://wicg.github.io/netinfo/#rtt-attribute\n readonly rtt?: Millisecond;\n // http://wicg.github.io/netinfo/#savedata-attribute\n readonly saveData?: boolean;\n // http://wicg.github.io/netinfo/#handling-changes-to-the-underlying-connection\n onchange?: EventListener;\n}\n\n// https://w3c.github.io/device-memory/#sec-device-memory-js-api\ninterface NavigatorDeviceMemory {\n readonly deviceMemory?: number;\n}\n\nconst MAX_INT_AS_BYTES = 2147483647;\n\nlet _performanceCursor: number = 0;\n\n/**\n * Start tracking long tasks.\n */\nexport function startTrackingLongTasks(): void {\n addPerformanceInstrumentationHandler('longtask', ({ entries }) => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n\n const { attributes: parentAttributes, start_timestamp: parentStartTimestamp } = spanToJSON(parent);\n\n for (const entry of entries) {\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n const duration = msToSec(entry.duration);\n\n if (parentAttributes[SENTRY_OP] === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding a span if the long task started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: UI_LONG_TASK_SPAN_NAME_FALLBACK,\n op: UI_LONG_TASK,\n attributes: {\n [SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n },\n });\n }\n });\n}\n\n/**\n * Start tracking long animation frames.\n */\nexport function startTrackingLongAnimationFrames(): void {\n // NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so\n // we directly observe `long-animation-frame` events instead of through the web-vitals\n // `observe` helper function.\n const observer = new PerformanceObserver(list => {\n const parent = getActiveSpan();\n if (!parent) {\n return;\n }\n for (const entry of list.getEntries() as PerformanceLongAnimationFrameTiming[]) {\n if (!entry.scripts[0]) {\n continue;\n }\n\n const startTime = msToSec((browserPerformanceTimeOrigin() as number) + entry.startTime);\n\n const {\n start_timestamp: parentStartTimestamp,\n attributes: { [SENTRY_OP]: parentOp },\n } = spanToJSON(parent);\n\n if (parentOp === 'navigation' && parentStartTimestamp && startTime < parentStartTimestamp) {\n // Skip adding the span if the long animation frame started before the navigation started.\n // `startAndEndSpan` will otherwise adjust the parent's start time to the span's start\n // time, potentially skewing the duration of the actual navigation as reported via our\n // routing instrumentations\n continue;\n }\n const duration = msToSec(entry.duration);\n\n const attributes: SpanAttributes = {\n [SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n };\n\n const initialScript = entry.scripts[0];\n const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript;\n attributes['browser.script.invoker'] = invoker;\n attributes['browser.script.invoker_type'] = invokerType;\n if (sourceURL) {\n attributes[CODE_FILE_PATH] = sourceURL;\n }\n if (sourceFunctionName) {\n attributes[CODE_FUNCTION_NAME] = sourceFunctionName;\n }\n if (sourceCharPosition !== -1) {\n attributes['browser.script.source_char_position'] = sourceCharPosition;\n }\n\n startAndEndSpan(parent, startTime, startTime + duration, {\n name: UI_LONG_TASK_SPAN_NAME_FALLBACK,\n op: UI_LONG_ANIMATION_FRAME,\n attributes,\n });\n }\n });\n\n observer.observe({ type: 'long-animation-frame', buffered: true });\n}\n\ninterface AddPerformanceEntriesOptions {\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * Whether span streaming is enabled.\n */\n spanStreamingEnabled?: boolean;\n}\n\n/** Add performance related spans to a transaction */\nexport function addPerformanceEntries(span: Span, options: AddPerformanceEntriesOptions): void {\n const performance = getBrowserPerformanceAPI();\n const origin = browserPerformanceTimeOrigin();\n if (!performance?.getEntries || !origin) {\n // Gatekeeper if performance API not available\n return;\n }\n\n const { spanStreamingEnabled, ignoreResourceSpans } = options;\n\n const timeOrigin = msToSec(origin);\n\n const performanceEntries = performance.getEntries();\n\n const { attributes, start_timestamp: transactionStartTime } = spanToJSON(span);\n\n performanceEntries.slice(_performanceCursor).forEach(entry => {\n const startTime = msToSec(entry.startTime);\n const duration = msToSec(\n // Inexplicably, Chrome sometimes emits a negative duration. We need to work around this.\n // There is a SO post attempting to explain this, but it leaves one with open questions: https://stackoverflow.com/questions/23191918/peformance-getentries-and-negative-duration-display\n // The way we clamp the value is probably not accurate, since we have observed this happen for things that may take a while to load, like for example the replay worker.\n // TODO: Investigate why this happens and how to properly mitigate. For now, this is a workaround to prevent transactions being dropped due to negative duration spans.\n Math.max(0, entry.duration),\n );\n\n if (\n attributes[SENTRY_OP] === 'navigation' &&\n transactionStartTime &&\n timeOrigin + startTime < transactionStartTime\n ) {\n return;\n }\n\n switch (entry.entryType) {\n case 'navigation': {\n _addNavigationSpans(span, entry as PerformanceNavigationTiming, timeOrigin, spanStreamingEnabled);\n break;\n }\n case 'paint': {\n _addPaintSpan(span, entry, startTime, duration, timeOrigin);\n break;\n }\n case 'resource': {\n _addResourceSpans(\n span,\n entry as PerformanceResourceTiming,\n entry.name,\n startTime,\n duration,\n timeOrigin,\n ignoreResourceSpans,\n spanStreamingEnabled,\n );\n break;\n }\n // Ignore other entry types.\n }\n });\n\n _performanceCursor = Math.max(performanceEntries.length - 1, 0);\n\n _trackNavigator(span, spanStreamingEnabled);\n}\n\n/**\n * Create a span for a browser paint performance entry.\n * Exported only for tests.\n */\nexport function _addPaintSpan(\n span: Span,\n entry: PerformanceEntry,\n startTime: number,\n duration: number,\n timeOrigin: number,\n): void {\n const startTimestamp = timeOrigin + startTime;\n\n startAndEndSpan(span, startTimestamp, startTimestamp + duration, {\n // The entry name (`first-paint`, `first-contentful-paint`) is already the low-cardinality name\n // the conventions ask for, so only the attribute backing it has to be added.\n name: entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_PAINT,\n [SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n [BROWSER_PAINT_TYPE]: entry.name,\n },\n });\n}\n\n/**\n * Instrument navigation entries\n * exported only for tests\n */\nexport function _addNavigationSpans(\n span: Span,\n entry: PerformanceNavigationTiming,\n timeOrigin: number,\n spanStreamingEnabled?: boolean,\n): void {\n _addPerformanceNavigationTiming(span, entry, 'unloadEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'redirect', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'domContentLoadedEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'loadEvent', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'connect', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'secureConnection', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'fetch', timeOrigin, spanStreamingEnabled);\n _addPerformanceNavigationTiming(span, entry, 'domainLookup', timeOrigin, spanStreamingEnabled);\n\n _addRequest(span, entry, timeOrigin, spanStreamingEnabled);\n}\n\ntype StartEventName =\n | 'secureConnection'\n | 'fetch'\n | 'domainLookup'\n | 'unloadEvent'\n | 'redirect'\n | 'connect'\n | 'domContentLoadedEvent'\n | 'loadEvent';\n\nconst NAVIGATION_TIMING_SPAN_OPS = {\n secureConnection: BROWSER_TLS_SSL,\n fetch: BROWSER_CACHE,\n domainLookup: BROWSER_DNS,\n unloadEvent: BROWSER_UNLOAD_EVENT,\n redirect: BROWSER_REDIRECT,\n connect: BROWSER_CONNECT,\n domContentLoadedEvent: BROWSER_DOM_CONTENT_LOADED_EVENT,\n loadEvent: BROWSER_LOAD_EVENT,\n} as const satisfies Record<StartEventName, string>;\n\ntype EndEventName =\n | 'domainLookupStart'\n | 'domainLookupEnd'\n | 'unloadEventEnd'\n | 'redirectEnd'\n | 'connectEnd'\n | 'domContentLoadedEventEnd'\n | 'loadEventEnd';\n\n/** Create performance navigation related spans */\nfunction _addPerformanceNavigationTiming(\n span: Span,\n entry: PerformanceNavigationTiming,\n event: StartEventName,\n timeOrigin: number,\n spanStreamingEnabled: boolean | undefined,\n): void {\n const eventEnd = _getEndPropertyNameForNavigationTiming(event) satisfies keyof PerformanceNavigationTiming;\n const end = entry[eventEnd];\n const start = entry[`${event}Start`];\n if (!start || !end) {\n return;\n }\n const op = NAVIGATION_TIMING_SPAN_OPS[event];\n startAndEndSpan(span, timeOrigin + msToSec(start), timeOrigin + msToSec(end), {\n // With span streaming, span names have to be low cardinality, so we can't fall back to the\n // document URL. `url.full` keeps it, and is what Relay derives the description from.\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[op] : entry.name,\n attributes: {\n [SENTRY_OP]: op,\n [SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: filterCollectedUrl(entry.name),\n ...(event === 'redirect' && entry.redirectCount != null ? { 'http.redirect_count': entry.redirectCount } : {}),\n },\n });\n}\n\nfunction _getEndPropertyNameForNavigationTiming(event: StartEventName): EndEventName {\n if (event === 'secureConnection') {\n return 'connectEnd';\n }\n if (event === 'fetch') {\n return 'domainLookupStart';\n }\n return `${event}End`;\n}\n\n/** Create request and response related spans */\nfunction _addRequest(\n span: Span,\n entry: PerformanceNavigationTiming,\n timeOrigin: number,\n spanStreamingEnabled: boolean | undefined,\n): void {\n const requestStartTimestamp = timeOrigin + msToSec(entry.requestStart);\n const responseEndTimestamp = timeOrigin + msToSec(entry.responseEnd);\n const responseStartTimestamp = timeOrigin + msToSec(entry.responseStart);\n if (entry.responseEnd) {\n // It is possible that we are collecting these metrics when the page hasn't finished loading yet, for example when the HTML slowly streams in.\n // In this case, ie. when the document request hasn't finished yet, `entry.responseEnd` will be 0.\n // In order not to produce faulty spans, where the end timestamp is before the start timestamp, we will only collect\n // these spans when the responseEnd value is available. The backend (Relay) would drop the entire span if it contained faulty spans.\n\n // With span streaming, span names have to be low cardinality, so we can't fall back to the\n // document URL. `url.full` keeps it, and is what Relay derives the description from.\n const url = filterCollectedUrl(entry.name);\n\n startAndEndSpan(span, requestStartTimestamp, responseEndTimestamp, {\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_REQUEST] : entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_REQUEST,\n [SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: url,\n },\n });\n\n startAndEndSpan(span, responseStartTimestamp, responseEndTimestamp, {\n name: spanStreamingEnabled ? BROWSER_NAVIGATION_TIMING_SPAN_NAMES[BROWSER_RESPONSE] : entry.name,\n attributes: {\n [SENTRY_OP]: BROWSER_RESPONSE,\n [SENTRY_ORIGIN]: 'auto.ui.browser.metrics',\n [URL_FULL]: url,\n },\n });\n }\n}\n\n/**\n * Create resource-related spans.\n * Exported only for tests.\n */\nexport function _addResourceSpans(\n span: Span,\n entry: PerformanceResourceTiming,\n resourceUrl: string,\n startTime: number,\n duration: number,\n timeOrigin: number,\n ignoredResourceSpanOps?: Array<string>,\n spanStreamingEnabled?: boolean,\n): void {\n // we already instrument based on fetch and xhr, so we don't need to\n // duplicate spans here.\n if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {\n return;\n }\n\n const op = entry.initiatorType ? `resource.${entry.initiatorType}` : RESOURCE_OTHER;\n if (ignoredResourceSpanOps?.includes(op)) {\n return;\n }\n\n const attributes: SpanAttributes = {\n [SENTRY_ORIGIN]: 'auto.resource.browser.metrics',\n };\n\n const parsedUrl = parseUrl(resourceUrl);\n\n if (parsedUrl.protocol) {\n attributes[URL_SCHEME] = parsedUrl.protocol.split(':').pop(); // the protocol returned by parseUrl includes a :, but OTEL spec does not, so we remove it.\n }\n\n // `host` is the URL authority, so it can carry userinfo, which doesn't belong on either attribute.\n const host = parsedUrl.host?.replace(/^.*@/, '');\n\n if (host) {\n attributes[SERVER_ADDRESS] = host;\n }\n\n // Unlike `server.address`, `url.domain` excludes the port.\n const domain = host?.replace(/:\\d+$/, '');\n\n if (domain) {\n attributes[URL_DOMAIN] = domain;\n }\n\n attributes[HTTP_REQUEST_SAME_ORIGIN] = resourceUrl.includes(WINDOW.location.origin);\n\n attributes[URL_FULL] = filterCollectedUrl(resourceUrl);\n\n _setResourceRequestAttributes(entry, attributes, [\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n ['responseStatus', HTTP_RESPONSE_STATUS_CODE],\n\n ['transferSize', HTTP_RESPONSE_SIZE],\n ['encodedBodySize', HTTP_RESPONSE_BODY_SIZE],\n ['decodedBodySize', 'http.response.body.decoded_size'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/renderBlockingStatus\n ['renderBlockingStatus', 'resource.render_blocking_status'],\n\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType\n ['deliveryType', 'http.response_delivery_type'],\n ]);\n\n const attributesWithResourceTiming: SpanAttributes = { ...attributes, ...resourceTimingToSpanAttributes(entry) };\n\n const startTimestamp = timeOrigin + startTime;\n const endTimestamp = startTimestamp + duration;\n\n startAndEndSpan(span, startTimestamp, endTimestamp, {\n // With span streaming, span names have to be low cardinality, so we can't fall back to the URL.\n name: spanStreamingEnabled\n ? domain || RESOURCE_SPAN_NAME_FALLBACK\n : resourceUrl.replace(WINDOW.location.origin, ''),\n op,\n attributes: attributesWithResourceTiming,\n });\n}\n\n/**\n * Capture the information of the user agent.\n * TODO(v12): Remove non-span-streaming attributes and measurements once the static trace lifecycle is removed\n */\nfunction _trackNavigator(span: Span, spanStreamingEnabled: boolean | undefined): void {\n const navigator = WINDOW.navigator as null | (Navigator & NavigatorNetworkInformation & NavigatorDeviceMemory);\n if (!navigator) {\n return;\n }\n\n // track network connectivity\n const connection = navigator.connection;\n if (connection) {\n if (connection.effectiveType) {\n span.setAttribute(\n spanStreamingEnabled ? NETWORK_CONNECTION_EFFECTIVE_TYPE : 'effectiveConnectionType',\n connection.effectiveType,\n );\n }\n\n if (connection.type) {\n span.setAttribute(spanStreamingEnabled ? NETWORK_CONNECTION_TYPE : 'connectionType', connection.type);\n }\n\n if (isMeasurementValue(connection.rtt)) {\n if (spanStreamingEnabled) {\n span.setAttribute(NETWORK_CONNECTION_RTT, connection.rtt);\n } else if (spanToJSON(span).attributes[SENTRY_OP] === 'pageload') {\n // Measurements are only recorded on the pageload span, matching the historical\n // behavior where `connection.rtt` was only flushed for pageload transactions.\n setMeasurement('connection.rtt', connection.rtt, 'millisecond');\n }\n }\n }\n\n if (isMeasurementValue(navigator.deviceMemory)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.memory.estimated_capacity', navigator.deviceMemory);\n } else {\n span.setAttribute('deviceMemory', `${navigator.deviceMemory} GB`);\n }\n }\n\n if (isMeasurementValue(navigator.hardwareConcurrency)) {\n if (spanStreamingEnabled) {\n span.setAttribute('device.processor_count', navigator.hardwareConcurrency);\n } else {\n span.setAttribute('hardwareConcurrency', String(navigator.hardwareConcurrency));\n }\n }\n}\n\ntype ExperimentalResourceTimingProperty =\n | 'renderBlockingStatus'\n | 'deliveryType'\n // For some reason, TS during build, errors on `responseStatus` not being a property of\n // PerformanceResourceTiming while it actually is. Hence, we're adding it here.\n // Perhaps because response status is not yet available in Webkit/Safari.\n // https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/responseStatus\n | 'responseStatus';\n\n/**\n * Use this to set any attributes we can take directly form the PerformanceResourceTiming entry.\n *\n * This is just a mapping function for entry->attribute to keep bundle-size minimal.\n * Experimental properties are also accepted (see {@link ExperimentalResourceTimingProperty}).\n * Assumes that all entry properties might be undefined for browser-specific differences.\n * Only accepts string and number values for now and also sets 0-values.\n */\nexport function _setResourceRequestAttributes(\n entry: Partial<PerformanceResourceTiming> & Partial<Record<ExperimentalResourceTimingProperty, number | string>>,\n attributes: SpanAttributes,\n properties: [keyof PerformanceResourceTiming | ExperimentalResourceTimingProperty, string][],\n): void {\n properties.forEach(([entryKey, attributeKey]) => {\n const entryVal = entry[entryKey];\n if (\n entryVal != null &&\n ((typeof entryVal === 'number' && entryVal < MAX_INT_AS_BYTES) || typeof entryVal === 'string')\n ) {\n attributes[attributeKey] = entryVal;\n }\n });\n}\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { getRootSpan, spanToJSON, getCurrentScope, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getClient } from '@sentry/core';
1
+ import { getRootSpan, spanToJSON, getCurrentScope, getClient } from '@sentry/core';
2
2
  import { startInactiveSpan } from '@sentry/core/browser';
3
- import { USER_AGENT_ORIGINAL, BROWSER_NAVIGATION_ID, BROWSER_NAVIGATION_TYPE, SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION, SENTRY_EXCLUSIVE_TIME, SENTRY_REPLAY_ID } from '@sentry/conventions/attributes';
3
+ import { USER_AGENT_ORIGINAL, SENTRY_OP, BROWSER_NAVIGATION_ID, BROWSER_NAVIGATION_TYPE, SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION, SENTRY_EXCLUSIVE_TIME, SENTRY_ORIGIN, SENTRY_REPLAY_ID } from '@sentry/conventions/attributes';
4
4
  import { WINDOW } from '../types.js';
5
5
 
6
6
  function _emitWebVitalSpan(options) {
@@ -21,8 +21,8 @@ function _emitWebVitalSpan(options) {
21
21
  const segmentSpan = parentSpan && getRootSpan(parentSpan);
22
22
  const segmentName = segmentSpan ? spanToJSON(segmentSpan).name : getCurrentScope().getScopeData().transactionName;
23
23
  const attributes = {
24
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,
25
- [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,
24
+ [SENTRY_ORIGIN]: origin,
25
+ [SENTRY_OP]: op,
26
26
  [SENTRY_EXCLUSIVE_TIME]: 0,
27
27
  [`browser.web_vital.${metricName}.value`]: value,
28
28
  // oxlint-disable-next-line typescript-eslint/no-deprecated
@@ -32,7 +32,7 @@ function _emitWebVitalSpan(options) {
32
32
  [USER_AGENT_ORIGINAL]: WINDOW.navigator?.userAgent,
33
33
  ...passedAttributes
34
34
  };
35
- if (parentSpan && spanToJSON(parentSpan).attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] === "pageload") {
35
+ if (parentSpan && spanToJSON(parentSpan).attributes[SENTRY_OP] === "pageload") {
36
36
  attributes["sentry.pageload.span_id"] = parentSpan.spanContext().spanId;
37
37
  }
38
38
  if (softNavigationId != null) {
@@ -1 +1 @@
1
- {"version":3,"file":"emitSpan.js","sources":["../../../src/web-vitals/emitSpan.ts"],"sourcesContent":["import type { Integration, Span, SpanAttributes } from '@sentry/core';\nimport {\n getClient,\n getCurrentScope,\n getRootSpan,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n spanToJSON,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport {\n SENTRY_EXCLUSIVE_TIME,\n BROWSER_NAVIGATION_ID,\n BROWSER_NAVIGATION_TYPE,\n SENTRY_REPLAY_ID,\n SENTRY_SEGMENT_NAME,\n SENTRY_TRANSACTION,\n USER_AGENT_ORIGINAL,\n} from '@sentry/conventions/attributes';\nimport { WINDOW } from '../types';\nimport type { MetricNavigationType } from '../instrumentation/performanceObserver';\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 startTime: number;\n endTime?: number;\n /** Set when the vital was reported for a soft navigation rather than the initial page load. */\n softNavigationId?: number;\n /** The navigation the vital was measured on, as reported by web-vitals. */\n navigationType?: MetricNavigationType;\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 startTime,\n endTime,\n standalone,\n softNavigationId,\n navigationType,\n } = options;\n\n // Taken off the segment span itself, so it can't diverge from it: a routing instrumentation may\n // rename that span (a pageload span is named `Pageload` until its route resolves), and the scope's\n // transaction name is deliberately not kept in sync with it. Only a standalone span, which is sent\n // without its segment span, has to fall back to the scope.\n const segmentSpan = parentSpan && getRootSpan(parentSpan);\n const segmentName = segmentSpan ? spanToJSON(segmentSpan).name : getCurrentScope().getScopeData().transactionName;\n\n const attributes: SpanAttributes = {\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: origin,\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,\n [SENTRY_EXCLUSIVE_TIME]: 0,\n [`browser.web_vital.${metricName}.value`]: value,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: segmentName,\n [SENTRY_SEGMENT_NAME]: segmentName,\n // Web vital score calculation relies on the user agent\n [USER_AGENT_ORIGINAL]: WINDOW.navigator?.userAgent,\n ...passedAttributes,\n };\n\n if (parentSpan && spanToJSON(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 (softNavigationId != null) {\n attributes[BROWSER_NAVIGATION_ID] = softNavigationId;\n }\n\n if (navigationType) {\n attributes[BROWSER_NAVIGATION_TYPE] = navigationType;\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 // Not the `SENTRY_REPLAY_IS_BUFFERING` convention: that one has no `sentry._internal.` prefix, and\n // the rest of the SDK sets the prefixed key (see `logs/internal.ts`, `metrics/internal.ts`).\n 'sentry._internal.replay_is_buffering': replay!.getRecordingMode() === 'buffer' ? true : undefined,\n };\n}\n"],"names":[],"mappings":";;;;;AAqEO,SAAS,kBAAkB,OAAA,EAAoC;AACpE,EAAA,MAAM;AAAA,IACJ,IAAA;AAAA,IACA,EAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA,EAAY,gBAAA;AAAA,IACZ,UAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAMJ,EAAA,MAAM,WAAA,GAAc,UAAA,IAAc,WAAA,CAAY,UAAU,CAAA;AACxD,EAAA,MAAM,WAAA,GAAc,cAAc,UAAA,CAAW,WAAW,EAAE,IAAA,GAAO,eAAA,EAAgB,CAAE,YAAA,EAAa,CAAE,eAAA;AAElG,EAAA,MAAM,UAAA,GAA6B;AAAA,IACjC,CAAC,gCAAgC,GAAG,MAAA;AAAA,IACpC,CAAC,4BAA4B,GAAG,EAAA;AAAA,IAChC,CAAC,qBAAqB,GAAG,CAAA;AAAA,IACzB,CAAC,CAAA,kBAAA,EAAqB,UAAU,CAAA,MAAA,CAAQ,GAAG,KAAA;AAAA;AAAA,IAE3C,CAAC,kBAAkB,GAAG,WAAA;AAAA,IACtB,CAAC,mBAAmB,GAAG,WAAA;AAAA;AAAA,IAEvB,CAAC,mBAAmB,GAAG,MAAA,CAAO,SAAA,EAAW,SAAA;AAAA,IACzC,GAAG;AAAA,GACL;AAEA,EAAA,IAAI,cAAc,UAAA,CAAW,UAAU,EAAE,UAAA,CAAW,4BAA4B,MAAM,UAAA,EAAY;AAEhG,IAAA,UAAA,CAAW,yBAAyB,CAAA,GAAI,UAAA,CAAW,WAAA,EAAY,CAAE,MAAA;AAAA,EACnE;AAEA,EAAA,IAAI,oBAAoB,IAAA,EAAM;AAC5B,IAAA,UAAA,CAAW,qBAAqB,CAAA,GAAI,gBAAA;AAAA,EACtC;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,UAAA,CAAW,uBAAuB,CAAA,GAAI,cAAA;AAAA,EACxC;AAOA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,mBAAA,EAAqB,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,OAAO,iBAAA,CAAkB;AAAA,IAC7B,IAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA;AAAA,IAEA,YAAA,EAAc,UAAA,GAAa,EAAE,UAAA,EAAY,MAAK,GAAI;AAAA,GACnD,CAAA;AAED,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAA,CAAK,GAAA,CAAI,WAAW,SAAS,CAAA;AAAA,EAC/B;AACF;AASA,SAAS,mBAAA,GAAsC;AAC7C,EAAA,MAAM,MAAA,GAAS,SAAA,EAAU,EAAG,oBAAA,CAAwC,QAAQ,CAAA;AAC5E,EAAA,MAAM,QAAA,GAAW,MAAA,EAAQ,WAAA,CAAY,IAAI,CAAA;AACzC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,OAAO;AAAA,IACL,CAAC,gBAAgB,GAAG,QAAA;AAAA;AAAA;AAAA,IAGpB,sCAAA,EAAwC,MAAA,CAAQ,gBAAA,EAAiB,KAAM,WAAW,IAAA,GAAO;AAAA,GAC3F;AACF;;;;"}
1
+ {"version":3,"file":"emitSpan.js","sources":["../../../src/web-vitals/emitSpan.ts"],"sourcesContent":["import type { Integration, Span, SpanAttributes } from '@sentry/core';\nimport { getClient, getCurrentScope, getRootSpan, spanToJSON } from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport {\n SENTRY_EXCLUSIVE_TIME,\n BROWSER_NAVIGATION_ID,\n BROWSER_NAVIGATION_TYPE,\n SENTRY_REPLAY_ID,\n SENTRY_SEGMENT_NAME,\n SENTRY_TRANSACTION,\n USER_AGENT_ORIGINAL,\n SENTRY_OP,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { WINDOW } from '../types';\nimport type { MetricNavigationType } from '../instrumentation/performanceObserver';\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 startTime: number;\n endTime?: number;\n /** Set when the vital was reported for a soft navigation rather than the initial page load. */\n softNavigationId?: number;\n /** The navigation the vital was measured on, as reported by web-vitals. */\n navigationType?: MetricNavigationType;\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 startTime,\n endTime,\n standalone,\n softNavigationId,\n navigationType,\n } = options;\n\n // Taken off the segment span itself, so it can't diverge from it: a routing instrumentation may\n // rename that span (a pageload span is named `Pageload` until its route resolves), and the scope's\n // transaction name is deliberately not kept in sync with it. Only a standalone span, which is sent\n // without its segment span, has to fall back to the scope.\n const segmentSpan = parentSpan && getRootSpan(parentSpan);\n const segmentName = segmentSpan ? spanToJSON(segmentSpan).name : getCurrentScope().getScopeData().transactionName;\n\n const attributes: SpanAttributes = {\n [SENTRY_ORIGIN]: origin,\n [SENTRY_OP]: op,\n [SENTRY_EXCLUSIVE_TIME]: 0,\n [`browser.web_vital.${metricName}.value`]: value,\n // oxlint-disable-next-line typescript-eslint/no-deprecated\n [SENTRY_TRANSACTION]: segmentName,\n [SENTRY_SEGMENT_NAME]: segmentName,\n // Web vital score calculation relies on the user agent\n [USER_AGENT_ORIGINAL]: WINDOW.navigator?.userAgent,\n ...passedAttributes,\n };\n\n if (parentSpan && spanToJSON(parentSpan).attributes[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 (softNavigationId != null) {\n attributes[BROWSER_NAVIGATION_ID] = softNavigationId;\n }\n\n if (navigationType) {\n attributes[BROWSER_NAVIGATION_TYPE] = navigationType;\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 // Not the `SENTRY_REPLAY_IS_BUFFERING` convention: that one has no `sentry._internal.` prefix, and\n // the rest of the SDK sets the prefixed key (see `logs/internal.ts`, `metrics/internal.ts`).\n 'sentry._internal.replay_is_buffering': replay!.getRecordingMode() === 'buffer' ? true : undefined,\n };\n}\n"],"names":[],"mappings":";;;;;AAgEO,SAAS,kBAAkB,OAAA,EAAoC;AACpE,EAAA,MAAM;AAAA,IACJ,IAAA;AAAA,IACA,EAAA;AAAA,IACA,MAAA;AAAA,IACA,UAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAA,EAAY,gBAAA;AAAA,IACZ,UAAA;AAAA,IACA,SAAA;AAAA,IACA,OAAA;AAAA,IACA,UAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AAMJ,EAAA,MAAM,WAAA,GAAc,UAAA,IAAc,WAAA,CAAY,UAAU,CAAA;AACxD,EAAA,MAAM,WAAA,GAAc,cAAc,UAAA,CAAW,WAAW,EAAE,IAAA,GAAO,eAAA,EAAgB,CAAE,YAAA,EAAa,CAAE,eAAA;AAElG,EAAA,MAAM,UAAA,GAA6B;AAAA,IACjC,CAAC,aAAa,GAAG,MAAA;AAAA,IACjB,CAAC,SAAS,GAAG,EAAA;AAAA,IACb,CAAC,qBAAqB,GAAG,CAAA;AAAA,IACzB,CAAC,CAAA,kBAAA,EAAqB,UAAU,CAAA,MAAA,CAAQ,GAAG,KAAA;AAAA;AAAA,IAE3C,CAAC,kBAAkB,GAAG,WAAA;AAAA,IACtB,CAAC,mBAAmB,GAAG,WAAA;AAAA;AAAA,IAEvB,CAAC,mBAAmB,GAAG,MAAA,CAAO,SAAA,EAAW,SAAA;AAAA,IACzC,GAAG;AAAA,GACL;AAEA,EAAA,IAAI,cAAc,UAAA,CAAW,UAAU,EAAE,UAAA,CAAW,SAAS,MAAM,UAAA,EAAY;AAE7E,IAAA,UAAA,CAAW,yBAAyB,CAAA,GAAI,UAAA,CAAW,WAAA,EAAY,CAAE,MAAA;AAAA,EACnE;AAEA,EAAA,IAAI,oBAAoB,IAAA,EAAM;AAC5B,IAAA,UAAA,CAAW,qBAAqB,CAAA,GAAI,gBAAA;AAAA,EACtC;AAEA,EAAA,IAAI,cAAA,EAAgB;AAClB,IAAA,UAAA,CAAW,uBAAuB,CAAA,GAAI,cAAA;AAAA,EACxC;AAOA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAA,CAAO,MAAA,CAAO,UAAA,EAAY,mBAAA,EAAqB,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,OAAO,iBAAA,CAAkB;AAAA,IAC7B,IAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA;AAAA,IAEA,YAAA,EAAc,UAAA,GAAa,EAAE,UAAA,EAAY,MAAK,GAAI;AAAA,GACnD,CAAA;AAED,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,IAAA,CAAK,GAAA,CAAI,WAAW,SAAS,CAAA;AAAA,EAC/B;AACF;AASA,SAAS,mBAAA,GAAsC;AAC7C,EAAA,MAAM,MAAA,GAAS,SAAA,EAAU,EAAG,oBAAA,CAAwC,QAAQ,CAAA;AAC5E,EAAA,MAAM,QAAA,GAAW,MAAA,EAAQ,WAAA,CAAY,IAAI,CAAA;AACzC,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,OAAO;AAAA,IACL,CAAC,gBAAgB,GAAG,QAAA;AAAA;AAAA;AAAA,IAGpB,sCAAA,EAAwC,MAAA,CAAQ,gBAAA,EAAiB,KAAM,WAAW,IAAA,GAAO;AAAA,GAC3F;AACF;;;;"}
@@ -1,5 +1,5 @@
1
- import { LRUMap, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, debug } from '@sentry/core';
2
- import { BROWSER_NAVIGATION_ID } from '@sentry/conventions/attributes';
1
+ import { LRUMap, spanToJSON, debug } from '@sentry/core';
2
+ import { SENTRY_OP, BROWSER_NAVIGATION_ID } from '@sentry/conventions/attributes';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver.js';
5
5
  import { WINDOW } from '../types.js';
@@ -37,7 +37,7 @@ function startSoftNavigationCorrelation(client) {
37
37
  WINDOW.addEventListener("click", onInteraction, { capture: true, passive: true });
38
38
  WINDOW.addEventListener("keydown", onInteraction, { capture: true, passive: true });
39
39
  client.on("spanStart", (span) => {
40
- if (spanToJSON(span).attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] !== "navigation") {
40
+ if (spanToJSON(span).attributes?.[SENTRY_OP] !== "navigation") {
41
41
  return;
42
42
  }
43
43
  _pendingNavigation = void 0;
@@ -1 +1 @@
1
- {"version":3,"file":"softNavs.js","sources":["../../../src/web-vitals/softNavs.ts"],"sourcesContent":["import type { Client, Span } from '@sentry/core';\nimport { debug, LRUMap, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core';\nimport { BROWSER_NAVIGATION_ID } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { PerformanceSoftNavigation } from '../instrumentation/performanceObserver';\nimport { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\n\n/**\n * A page only ever needs its most recent navigations to still be joinable: web vitals for a soft\n * navigation are finalized at the next soft navigation or on pagehide, never later than that.\n */\nconst MAX_TRACKED_NAVIGATIONS = 5;\n\n/**\n * Tolerance when matching a DOM event's `timeStamp` against the `startTime` of its Event Timing\n * entry. Both are `DOMHighResTimeStamp`s from the same clock, so this only absorbs rounding.\n */\nconst INTERACTION_MATCH_TOLERANCE_MS = 5;\n\ninterface SoftNavMetric {\n navigationType: string;\n navigationId: number;\n navigationInteractionId?: number;\n}\n\ninterface PendingNavigation {\n span: Span;\n interactionTimestamp: number;\n}\n\ninterface PendingInteraction {\n interactionId: number;\n interactionTimestamp: number;\n}\n\n// The navigation span whose triggering interaction we haven't identified yet.\nlet _pendingNavigation: PendingNavigation | undefined;\n// The interaction whose Event Timing entry arrived before any navigation span claimed it.\nlet _pendingInteraction: PendingInteraction | undefined;\n// The timestamp of the most recent trusted click/keydown, i.e. our best guess at the interaction\n// that a history change happening right now was driven by.\nlet _lastInteractionTimestamp: number | undefined;\n\nconst _interactionIdToNavigationSpan = new LRUMap<number, Span>(MAX_TRACKED_NAVIGATIONS);\nconst _navigationIdToNavigationSpan = new LRUMap<number, Span>(MAX_TRACKED_NAVIGATIONS);\n\nlet _correlationStarted = false;\n\n/**\n * Whether an Event Timing entry's `startTime` and a DOM event's `timeStamp` name the same\n * interaction.\n */\nfunction interactionMatches(entryStartTime: number, interactionTimestamp: number): boolean {\n return Math.abs(entryStartTime - interactionTimestamp) <= INTERACTION_MATCH_TOLERANCE_MS;\n}\n\n/**\n * Whether the browser can report web vitals for soft navigations.\n *\n * This mirrors web-vitals' own feature detection: passing `reportSoftNavs` on a browser that fails\n * this check is a no-op there, so it has to be a no-op here too.\n */\nexport function supportsSoftNavigations(): boolean {\n try {\n return (\n PerformanceObserver.supportedEntryTypes.includes('soft-navigation') &&\n // Older implementations exposed this as an attribute rather than a method. Only the method\n // form shipped unflagged, so it's what web-vitals gates on.\n typeof (\n WINDOW as {\n PerformanceSoftNavigation?: { prototype?: { getLargestInteractionContentfulPaint?: unknown } };\n }\n ).PerformanceSoftNavigation?.prototype?.getLargestInteractionContentfulPaint === 'function'\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Start correlating the browser's soft navigations with the SDK's navigation spans.\n *\n * A navigation span is created synchronously on the history change, but the browser only mints the\n * `soft-navigation` entry (and with it the `navigationId` that web vitals are reported against)\n * once the navigation has been confirmed by a paint. So the `navigationId` cannot be known at span\n * creation time and the two have to be joined after the fact.\n *\n * The join key is the `interactionId` of the interaction that drove the navigation: per the Soft\n * Navigations spec the `soft-navigation` entry carries the `interactionId` of the interaction that\n * triggered it, which is the same id the interaction's own `PerformanceEventTiming` entry carries.\n * So we bind a navigation span to the interaction it happened during, and the soft navigation\n * joins back to that span through the shared id.\n *\n * This is inherently partial. Navigations that don't meet the browser's soft navigation heuristic\n * (programmatic navigations, navigations that never paint, back/forward from the browser chrome)\n * produce no entry at all, so those navigation spans simply have no web vitals.\n */\nexport function startSoftNavigationCorrelation(client: Client): void {\n if (_correlationStarted || !supportsSoftNavigations()) {\n return;\n }\n _correlationStarted = true;\n\n const onInteraction = (event: Event): void => {\n if (event.isTrusted) {\n _lastInteractionTimestamp = event.timeStamp;\n }\n };\n // Only click and keydown can start a soft navigation, which is also what the SDK's redirect\n // detection listens for.\n WINDOW.addEventListener('click', onInteraction, { capture: true, passive: true });\n WINDOW.addEventListener('keydown', onInteraction, { capture: true, passive: true });\n\n client.on('spanStart', span => {\n if (spanToJSON(span).attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] !== 'navigation') {\n return;\n }\n\n // A navigation with no preceding interaction can't produce a soft navigation, so there is\n // nothing to wait for. Dropping the pending span here also keeps us from binding a stale one.\n _pendingNavigation = undefined;\n const interactionTimestamp = _lastInteractionTimestamp;\n if (interactionTimestamp == null) {\n return;\n }\n\n // The interaction's entry may already be here: the router code that starts this span races the\n // paint that flushes the entry, so either one can win.\n if (_pendingInteraction?.interactionTimestamp === interactionTimestamp) {\n _interactionIdToNavigationSpan.set(_pendingInteraction.interactionId, span);\n _pendingInteraction = undefined;\n return;\n }\n\n _pendingNavigation = { span, interactionTimestamp };\n });\n\n const bindInteractionToNavigationSpan = ({ entries }: { entries: PerformanceEntry[] }): void => {\n for (const entry of entries) {\n if (!isPerformanceEventTiming(entry) || !entry.interactionId) {\n continue;\n }\n\n const pending = _pendingNavigation;\n if (pending && interactionMatches(entry.startTime, pending.interactionTimestamp)) {\n _interactionIdToNavigationSpan.set(entry.interactionId, pending.span);\n _pendingNavigation = undefined;\n continue;\n }\n\n // Once a navigation span has claimed this interaction, only a span that is still waiting can\n // rebind it, which the check above already allows. Holding on to the interaction's remaining\n // entries would instead let an unrelated later navigation claim it.\n if (_interactionIdToNavigationSpan.get(entry.interactionId)) {\n continue;\n }\n\n // The navigation span this interaction drove may still be on its way, so hold on to the\n // interaction instead of dropping it. Only the most recent one is worth keeping:\n // `_lastInteractionTimestamp` is what `spanStart` matches against and it only moves forward,\n // so an entry that doesn't match it now can never match it later.\n if (_lastInteractionTimestamp != null && interactionMatches(entry.startTime, _lastInteractionTimestamp)) {\n _pendingInteraction = { interactionId: entry.interactionId, interactionTimestamp: _lastInteractionTimestamp };\n }\n }\n };\n\n // `durationThreshold: 0` is applied for `event` by the shared observer, which matters here:\n // interactions below the 104ms default would otherwise never surface an `interactionId`.\n addPerformanceInstrumentationHandler('event', bindInteractionToNavigationSpan);\n addPerformanceInstrumentationHandler('first-input', bindInteractionToNavigationSpan);\n\n addPerformanceInstrumentationHandler('soft-navigation', ({ entries }) => {\n for (const entry of entries as PerformanceSoftNavigation[]) {\n const span = _interactionIdToNavigationSpan.get(entry.interactionId);\n if (!span) {\n DEBUG_BUILD && debug.log(`[SoftNav] No navigation span found for soft navigation ${entry.navigationId}`, entry);\n continue;\n }\n\n _navigationIdToNavigationSpan.set(entry.navigationId, span);\n // Best effort: the soft navigation entry usually lands well within the navigation span's idle\n // window, but if the span has already been sent this attribute is dropped.\n span.setAttribute(BROWSER_NAVIGATION_ID, entry.navigationId);\n }\n });\n}\n\n/**\n * The navigation span a soft navigation web vital belongs to, or `undefined` if the metric isn't\n * for a soft navigation or we failed to correlate it.\n */\nexport function getNavigationSpanForMetric(metric: SoftNavMetric): Span | undefined {\n if (metric.navigationType !== 'soft-navigation') {\n return undefined;\n }\n\n const span = _navigationIdToNavigationSpan.get(metric.navigationId);\n if (span) {\n return span;\n }\n\n // The `soft-navigation` observer may not have run for this navigation yet - entries from\n // different observers aren't delivered in a guaranteed order - so fall back to the join key the\n // metric carries itself.\n return metric.navigationInteractionId != null\n ? _interactionIdToNavigationSpan.get(metric.navigationInteractionId)\n : undefined;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"softNavs.js","sources":["../../../src/web-vitals/softNavs.ts"],"sourcesContent":["import type { Client, Span } from '@sentry/core';\nimport { debug, LRUMap, spanToJSON } from '@sentry/core';\nimport { BROWSER_NAVIGATION_ID, SENTRY_OP } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { PerformanceSoftNavigation } from '../instrumentation/performanceObserver';\nimport { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver';\nimport { WINDOW } from '../types';\n\n/**\n * A page only ever needs its most recent navigations to still be joinable: web vitals for a soft\n * navigation are finalized at the next soft navigation or on pagehide, never later than that.\n */\nconst MAX_TRACKED_NAVIGATIONS = 5;\n\n/**\n * Tolerance when matching a DOM event's `timeStamp` against the `startTime` of its Event Timing\n * entry. Both are `DOMHighResTimeStamp`s from the same clock, so this only absorbs rounding.\n */\nconst INTERACTION_MATCH_TOLERANCE_MS = 5;\n\ninterface SoftNavMetric {\n navigationType: string;\n navigationId: number;\n navigationInteractionId?: number;\n}\n\ninterface PendingNavigation {\n span: Span;\n interactionTimestamp: number;\n}\n\ninterface PendingInteraction {\n interactionId: number;\n interactionTimestamp: number;\n}\n\n// The navigation span whose triggering interaction we haven't identified yet.\nlet _pendingNavigation: PendingNavigation | undefined;\n// The interaction whose Event Timing entry arrived before any navigation span claimed it.\nlet _pendingInteraction: PendingInteraction | undefined;\n// The timestamp of the most recent trusted click/keydown, i.e. our best guess at the interaction\n// that a history change happening right now was driven by.\nlet _lastInteractionTimestamp: number | undefined;\n\nconst _interactionIdToNavigationSpan = new LRUMap<number, Span>(MAX_TRACKED_NAVIGATIONS);\nconst _navigationIdToNavigationSpan = new LRUMap<number, Span>(MAX_TRACKED_NAVIGATIONS);\n\nlet _correlationStarted = false;\n\n/**\n * Whether an Event Timing entry's `startTime` and a DOM event's `timeStamp` name the same\n * interaction.\n */\nfunction interactionMatches(entryStartTime: number, interactionTimestamp: number): boolean {\n return Math.abs(entryStartTime - interactionTimestamp) <= INTERACTION_MATCH_TOLERANCE_MS;\n}\n\n/**\n * Whether the browser can report web vitals for soft navigations.\n *\n * This mirrors web-vitals' own feature detection: passing `reportSoftNavs` on a browser that fails\n * this check is a no-op there, so it has to be a no-op here too.\n */\nexport function supportsSoftNavigations(): boolean {\n try {\n return (\n PerformanceObserver.supportedEntryTypes.includes('soft-navigation') &&\n // Older implementations exposed this as an attribute rather than a method. Only the method\n // form shipped unflagged, so it's what web-vitals gates on.\n typeof (\n WINDOW as {\n PerformanceSoftNavigation?: { prototype?: { getLargestInteractionContentfulPaint?: unknown } };\n }\n ).PerformanceSoftNavigation?.prototype?.getLargestInteractionContentfulPaint === 'function'\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Start correlating the browser's soft navigations with the SDK's navigation spans.\n *\n * A navigation span is created synchronously on the history change, but the browser only mints the\n * `soft-navigation` entry (and with it the `navigationId` that web vitals are reported against)\n * once the navigation has been confirmed by a paint. So the `navigationId` cannot be known at span\n * creation time and the two have to be joined after the fact.\n *\n * The join key is the `interactionId` of the interaction that drove the navigation: per the Soft\n * Navigations spec the `soft-navigation` entry carries the `interactionId` of the interaction that\n * triggered it, which is the same id the interaction's own `PerformanceEventTiming` entry carries.\n * So we bind a navigation span to the interaction it happened during, and the soft navigation\n * joins back to that span through the shared id.\n *\n * This is inherently partial. Navigations that don't meet the browser's soft navigation heuristic\n * (programmatic navigations, navigations that never paint, back/forward from the browser chrome)\n * produce no entry at all, so those navigation spans simply have no web vitals.\n */\nexport function startSoftNavigationCorrelation(client: Client): void {\n if (_correlationStarted || !supportsSoftNavigations()) {\n return;\n }\n _correlationStarted = true;\n\n const onInteraction = (event: Event): void => {\n if (event.isTrusted) {\n _lastInteractionTimestamp = event.timeStamp;\n }\n };\n // Only click and keydown can start a soft navigation, which is also what the SDK's redirect\n // detection listens for.\n WINDOW.addEventListener('click', onInteraction, { capture: true, passive: true });\n WINDOW.addEventListener('keydown', onInteraction, { capture: true, passive: true });\n\n client.on('spanStart', span => {\n if (spanToJSON(span).attributes?.[SENTRY_OP] !== 'navigation') {\n return;\n }\n\n // A navigation with no preceding interaction can't produce a soft navigation, so there is\n // nothing to wait for. Dropping the pending span here also keeps us from binding a stale one.\n _pendingNavigation = undefined;\n const interactionTimestamp = _lastInteractionTimestamp;\n if (interactionTimestamp == null) {\n return;\n }\n\n // The interaction's entry may already be here: the router code that starts this span races the\n // paint that flushes the entry, so either one can win.\n if (_pendingInteraction?.interactionTimestamp === interactionTimestamp) {\n _interactionIdToNavigationSpan.set(_pendingInteraction.interactionId, span);\n _pendingInteraction = undefined;\n return;\n }\n\n _pendingNavigation = { span, interactionTimestamp };\n });\n\n const bindInteractionToNavigationSpan = ({ entries }: { entries: PerformanceEntry[] }): void => {\n for (const entry of entries) {\n if (!isPerformanceEventTiming(entry) || !entry.interactionId) {\n continue;\n }\n\n const pending = _pendingNavigation;\n if (pending && interactionMatches(entry.startTime, pending.interactionTimestamp)) {\n _interactionIdToNavigationSpan.set(entry.interactionId, pending.span);\n _pendingNavigation = undefined;\n continue;\n }\n\n // Once a navigation span has claimed this interaction, only a span that is still waiting can\n // rebind it, which the check above already allows. Holding on to the interaction's remaining\n // entries would instead let an unrelated later navigation claim it.\n if (_interactionIdToNavigationSpan.get(entry.interactionId)) {\n continue;\n }\n\n // The navigation span this interaction drove may still be on its way, so hold on to the\n // interaction instead of dropping it. Only the most recent one is worth keeping:\n // `_lastInteractionTimestamp` is what `spanStart` matches against and it only moves forward,\n // so an entry that doesn't match it now can never match it later.\n if (_lastInteractionTimestamp != null && interactionMatches(entry.startTime, _lastInteractionTimestamp)) {\n _pendingInteraction = { interactionId: entry.interactionId, interactionTimestamp: _lastInteractionTimestamp };\n }\n }\n };\n\n // `durationThreshold: 0` is applied for `event` by the shared observer, which matters here:\n // interactions below the 104ms default would otherwise never surface an `interactionId`.\n addPerformanceInstrumentationHandler('event', bindInteractionToNavigationSpan);\n addPerformanceInstrumentationHandler('first-input', bindInteractionToNavigationSpan);\n\n addPerformanceInstrumentationHandler('soft-navigation', ({ entries }) => {\n for (const entry of entries as PerformanceSoftNavigation[]) {\n const span = _interactionIdToNavigationSpan.get(entry.interactionId);\n if (!span) {\n DEBUG_BUILD && debug.log(`[SoftNav] No navigation span found for soft navigation ${entry.navigationId}`, entry);\n continue;\n }\n\n _navigationIdToNavigationSpan.set(entry.navigationId, span);\n // Best effort: the soft navigation entry usually lands well within the navigation span's idle\n // window, but if the span has already been sent this attribute is dropped.\n span.setAttribute(BROWSER_NAVIGATION_ID, entry.navigationId);\n }\n });\n}\n\n/**\n * The navigation span a soft navigation web vital belongs to, or `undefined` if the metric isn't\n * for a soft navigation or we failed to correlate it.\n */\nexport function getNavigationSpanForMetric(metric: SoftNavMetric): Span | undefined {\n if (metric.navigationType !== 'soft-navigation') {\n return undefined;\n }\n\n const span = _navigationIdToNavigationSpan.get(metric.navigationId);\n if (span) {\n return span;\n }\n\n // The `soft-navigation` observer may not have run for this navigation yet - entries from\n // different observers aren't delivered in a guaranteed order - so fall back to the join key the\n // metric carries itself.\n return metric.navigationInteractionId != null\n ? _interactionIdToNavigationSpan.get(metric.navigationInteractionId)\n : undefined;\n}\n"],"names":[],"mappings":";;;;;;AAYA,MAAM,uBAAA,GAA0B,CAAA;AAMhC,MAAM,8BAAA,GAAiC,CAAA;AAmBvC,IAAI,kBAAA;AAEJ,IAAI,mBAAA;AAGJ,IAAI,yBAAA;AAEJ,MAAM,8BAAA,GAAiC,IAAI,MAAA,CAAqB,uBAAuB,CAAA;AACvF,MAAM,6BAAA,GAAgC,IAAI,MAAA,CAAqB,uBAAuB,CAAA;AAEtF,IAAI,mBAAA,GAAsB,KAAA;AAM1B,SAAS,kBAAA,CAAmB,gBAAwB,oBAAA,EAAuC;AACzF,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,cAAA,GAAiB,oBAAoB,CAAA,IAAK,8BAAA;AAC5D;AAQO,SAAS,uBAAA,GAAmC;AACjD,EAAA,IAAI;AACF,IAAA,OACE,mBAAA,CAAoB,mBAAA,CAAoB,QAAA,CAAS,iBAAiB,CAAA;AAAA;AAAA,IAGlE,OACE,MAAA,CAGA,yBAAA,EAA2B,SAAA,EAAW,oCAAA,KAAyC,UAAA;AAAA,EAErF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAoBO,SAAS,+BAA+B,MAAA,EAAsB;AACnE,EAAA,IAAI,mBAAA,IAAuB,CAAC,uBAAA,EAAwB,EAAG;AACrD,IAAA;AAAA,EACF;AACA,EAAA,mBAAA,GAAsB,IAAA;AAEtB,EAAA,MAAM,aAAA,GAAgB,CAAC,KAAA,KAAuB;AAC5C,IAAA,IAAI,MAAM,SAAA,EAAW;AACnB,MAAA,yBAAA,GAA4B,KAAA,CAAM,SAAA;AAAA,IACpC;AAAA,EACF,CAAA;AAGA,EAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,aAAA,EAAe,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAChF,EAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,aAAA,EAAe,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAElF,EAAA,MAAA,CAAO,EAAA,CAAG,aAAa,CAAA,IAAA,KAAQ;AAC7B,IAAA,IAAI,WAAW,IAAI,CAAA,CAAE,UAAA,GAAa,SAAS,MAAM,YAAA,EAAc;AAC7D,MAAA;AAAA,IACF;AAIA,IAAA,kBAAA,GAAqB,MAAA;AACrB,IAAA,MAAM,oBAAA,GAAuB,yBAAA;AAC7B,IAAA,IAAI,wBAAwB,IAAA,EAAM;AAChC,MAAA;AAAA,IACF;AAIA,IAAA,IAAI,mBAAA,EAAqB,yBAAyB,oBAAA,EAAsB;AACtE,MAAA,8BAAA,CAA+B,GAAA,CAAI,mBAAA,CAAoB,aAAA,EAAe,IAAI,CAAA;AAC1E,MAAA,mBAAA,GAAsB,MAAA;AACtB,MAAA;AAAA,IACF;AAEA,IAAA,kBAAA,GAAqB,EAAE,MAAM,oBAAA,EAAqB;AAAA,EACpD,CAAC,CAAA;AAED,EAAA,MAAM,+BAAA,GAAkC,CAAC,EAAE,OAAA,EAAQ,KAA6C;AAC9F,IAAA,KAAA,MAAW,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,CAAC,wBAAA,CAAyB,KAAK,CAAA,IAAK,CAAC,MAAM,aAAA,EAAe;AAC5D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,OAAA,GAAU,kBAAA;AAChB,MAAA,IAAI,WAAW,kBAAA,CAAmB,KAAA,CAAM,SAAA,EAAW,OAAA,CAAQ,oBAAoB,CAAA,EAAG;AAChF,QAAA,8BAAA,CAA+B,GAAA,CAAI,KAAA,CAAM,aAAA,EAAe,OAAA,CAAQ,IAAI,CAAA;AACpE,QAAA,kBAAA,GAAqB,MAAA;AACrB,QAAA;AAAA,MACF;AAKA,MAAA,IAAI,8BAAA,CAA+B,GAAA,CAAI,KAAA,CAAM,aAAa,CAAA,EAAG;AAC3D,QAAA;AAAA,MACF;AAMA,MAAA,IAAI,6BAA6B,IAAA,IAAQ,kBAAA,CAAmB,KAAA,CAAM,SAAA,EAAW,yBAAyB,CAAA,EAAG;AACvG,QAAA,mBAAA,GAAsB,EAAE,aAAA,EAAe,KAAA,CAAM,aAAA,EAAe,sBAAsB,yBAAA,EAA0B;AAAA,MAC9G;AAAA,IACF;AAAA,EACF,CAAA;AAIA,EAAA,oCAAA,CAAqC,SAAS,+BAA+B,CAAA;AAC7E,EAAA,oCAAA,CAAqC,eAAe,+BAA+B,CAAA;AAEnF,EAAA,oCAAA,CAAqC,iBAAA,EAAmB,CAAC,EAAE,OAAA,EAAQ,KAAM;AACvE,IAAA,KAAA,MAAW,SAAS,OAAA,EAAwC;AAC1D,MAAA,MAAM,IAAA,GAAO,8BAAA,CAA+B,GAAA,CAAI,KAAA,CAAM,aAAa,CAAA;AACnE,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,WAAA,IAAe,MAAM,GAAA,CAAI,CAAA,uDAAA,EAA0D,KAAA,CAAM,YAAY,IAAI,KAAK,CAAA;AAC9G,QAAA;AAAA,MACF;AAEA,MAAA,6BAAA,CAA8B,GAAA,CAAI,KAAA,CAAM,YAAA,EAAc,IAAI,CAAA;AAG1D,MAAA,IAAA,CAAK,YAAA,CAAa,qBAAA,EAAuB,KAAA,CAAM,YAAY,CAAA;AAAA,IAC7D;AAAA,EACF,CAAC,CAAA;AACH;AAMO,SAAS,2BAA2B,MAAA,EAAyC;AAClF,EAAA,IAAI,MAAA,CAAO,mBAAmB,iBAAA,EAAmB;AAC/C,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO,6BAAA,CAA8B,GAAA,CAAI,MAAA,CAAO,YAAY,CAAA;AAClE,EAAA,IAAI,IAAA,EAAM;AACR,IAAA,OAAO,IAAA;AAAA,EACT;AAKA,EAAA,OAAO,OAAO,uBAAA,IAA2B,IAAA,GACrC,+BAA+B,GAAA,CAAI,MAAA,CAAO,uBAAuB,CAAA,GACjE,MAAA;AACN;;;;"}
@@ -1,10 +1,10 @@
1
- import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, spanToJSON, SEMANTIC_ATTRIBUTE_SENTRY_OP, debug, getClient, timestampInSeconds, getActiveSpan, getRootSpan, 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';
1
+ import { browserPerformanceTimeOrigin, hasSpanStreamingEnabled, spanToJSON, debug, getClient, timestampInSeconds, getActiveSpan, getRootSpan, 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
4
  import { getComponentName } from '../component-name.js';
5
5
  import { MAX_PLAUSIBLE_INP_DURATION, INP_ENTRY_MAP, getCachedInteractionContext, UNKNOWN_ELEMENT_NAME } from './inp.js';
6
6
  import { addClsInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler } from '../instrumentation/performanceObserver.js';
7
- import { BROWSER_NAVIGATION_TYPE, UI_COMPONENT_NAME, SENTRY_EXCLUSIVE_TIME, BROWSER_WEB_VITAL_INP_TARGET, BROWSER_WEB_VITAL_INP_INTERACTION_TYPE } from '@sentry/conventions/attributes';
7
+ import { SENTRY_OP, BROWSER_NAVIGATION_TYPE, UI_COMPONENT_NAME, SENTRY_EXCLUSIVE_TIME, BROWSER_WEB_VITAL_INP_TARGET, BROWSER_WEB_VITAL_INP_INTERACTION_TYPE } from '@sentry/conventions/attributes';
8
8
  import { _emitWebVitalSpan } from './emitSpan.js';
9
9
  import { isValidLcpMetric } from './lcp.js';
10
10
  import { listenForWebVitalReportEvents } from './reportEvents.js';
@@ -32,7 +32,7 @@ function trackWebVitalPerNavigation(client, addInstrumentationHandler, send) {
32
32
  let bfcacheNavigationSpan;
33
33
  client.on("spanStart", (span) => {
34
34
  const attributes = spanToJSON(span).attributes;
35
- if (attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] === NAVIGATION && attributes[BROWSER_NAVIGATION_TYPE] === "back-forward-cache") {
35
+ if (attributes?.[SENTRY_OP] === NAVIGATION && attributes[BROWSER_NAVIGATION_TYPE] === "back-forward-cache") {
36
36
  bfcacheNavigationSpan = span;
37
37
  }
38
38
  });
@@ -1 +1 @@
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_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 {\n SENTRY_EXCLUSIVE_TIME,\n BROWSER_NAVIGATION_TYPE,\n BROWSER_WEB_VITAL_INP_INTERACTION_TYPE,\n BROWSER_WEB_VITAL_INP_TARGET,\n UI_COMPONENT_NAME,\n} 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 [SENTRY_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 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
+ {"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 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 {\n SENTRY_EXCLUSIVE_TIME,\n BROWSER_NAVIGATION_TYPE,\n BROWSER_WEB_VITAL_INP_INTERACTION_TYPE,\n BROWSER_WEB_VITAL_INP_TARGET,\n UI_COMPONENT_NAME,\n SENTRY_OP,\n} 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 (attributes?.[SENTRY_OP] === NAVIGATION && attributes[BROWSER_NAVIGATION_TYPE] === 'back-forward-cache') {\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 [SENTRY_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 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 +1 @@
1
- {"version":3,"file":"getNativeImplementation.d.ts","sourceRoot":"","sources":["../../src/getNativeImplementation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC;;;;GAIG;AAEH,UAAU,wBAAwB;IAChC,UAAU,EAAE,OAAO,MAAM,CAAC,UAAU,CAAC;IACrC,KAAK,EAAE,OAAO,MAAM,CAAC,KAAK,CAAC;CAC5B;AAID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAC9E,IAAI,EAAE,CAAC,GACN,wBAAwB,CAAC,CAAC,CAAC,CAsC7B;AAED,qCAAqC;AACrC,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,wBAAwB,GAAG,IAAI,CAEpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,KAAK,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAE/F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,CAE9G"}
1
+ {"version":3,"file":"getNativeImplementation.d.ts","sourceRoot":"","sources":["../../src/getNativeImplementation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC;;;;GAIG;AAEH,UAAU,wBAAwB;IAChC,UAAU,EAAE,OAAO,MAAM,CAAC,UAAU,CAAC;IACrC,KAAK,EAAE,OAAO,MAAM,CAAC,KAAK,CAAC;CAC5B;AAID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS,MAAM,wBAAwB,EAC9E,IAAI,EAAE,CAAC,GACN,wBAAwB,CAAC,CAAC,CAAC,CAsC7B;AAED,qCAAqC;AACrC,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,wBAAwB,GAAG,IAAI,CAEpF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,KAAK,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,KAAK,CAAC,CAE/F;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,UAAU,CAAC,CAY9G"}