@sentry-internal/browser-utils
Advanced tools
Comparing version 8.17.0 to 8.18.0
@@ -21,2 +21,3 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
exports.startTrackingInteractions = browserMetrics.startTrackingInteractions; | ||
exports.startTrackingLongAnimationFrames = browserMetrics.startTrackingLongAnimationFrames; | ||
exports.startTrackingLongTasks = browserMetrics.startTrackingLongTasks; | ||
@@ -23,0 +24,0 @@ exports.startTrackingWebVitals = browserMetrics.startTrackingWebVitals; |
@@ -79,2 +79,55 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
/** | ||
* Start tracking long animation frames. | ||
*/ | ||
function startTrackingLongAnimationFrames() { | ||
// NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so | ||
// we directly observe `long-animation-frame` events instead of through the web-vitals | ||
// `observe` helper function. | ||
const observer = new PerformanceObserver(list => { | ||
for (const entry of list.getEntries() ) { | ||
if (!core.getActiveSpan()) { | ||
return; | ||
} | ||
if (!entry.scripts[0]) { | ||
return; | ||
} | ||
const startTime = utils.msToSec((utils$1.browserPerformanceTimeOrigin ) + entry.startTime); | ||
const duration = utils.msToSec(entry.duration); | ||
const attributes = { | ||
[core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics', | ||
}; | ||
const initialScript = entry.scripts[0]; | ||
if (initialScript) { | ||
const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript; | ||
attributes['browser.script.invoker'] = invoker; | ||
attributes['browser.script.invoker_type'] = invokerType; | ||
if (sourceURL) { | ||
attributes['code.filepath'] = sourceURL; | ||
} | ||
if (sourceFunctionName) { | ||
attributes['code.function'] = sourceFunctionName; | ||
} | ||
if (sourceCharPosition !== -1) { | ||
attributes['browser.script.source_char_position'] = sourceCharPosition; | ||
} | ||
} | ||
const span = core.startInactiveSpan({ | ||
name: 'Main UI thread blocked', | ||
op: 'ui.long-animation-frame', | ||
startTime, | ||
attributes, | ||
}); | ||
if (span) { | ||
span.end(startTime + duration); | ||
} | ||
} | ||
}); | ||
observer.observe({ type: 'long-animation-frame', buffered: true }); | ||
} | ||
/** | ||
* Start tracking interaction events. | ||
@@ -547,4 +600,5 @@ */ | ||
exports.startTrackingInteractions = startTrackingInteractions; | ||
exports.startTrackingLongAnimationFrames = startTrackingLongAnimationFrames; | ||
exports.startTrackingLongTasks = startTrackingLongTasks; | ||
exports.startTrackingWebVitals = startTrackingWebVitals; | ||
//# sourceMappingURL=browserMetrics.js.map |
@@ -5,9 +5,8 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
const utils$1 = require('@sentry/utils'); | ||
const types = require('../types.js'); | ||
const instrument = require('./instrument.js'); | ||
const utils = require('./utils.js'); | ||
// We only care about name here | ||
const LAST_INTERACTIONS = []; | ||
const INTERACTIONS_ROUTE_MAP = new Map(); | ||
const INTERACTIONS_SPAN_MAP = new Map(); | ||
@@ -84,10 +83,11 @@ /** | ||
// We first try to lookup the route name from our INTERACTIONS_ROUTE_MAP, | ||
// We first try to lookup the span from our INTERACTIONS_SPAN_MAP, | ||
// where we cache the route per interactionId | ||
const cachedRouteName = interactionId != null ? INTERACTIONS_ROUTE_MAP.get(interactionId) : undefined; | ||
const cachedSpan = interactionId != null ? INTERACTIONS_SPAN_MAP.get(interactionId) : undefined; | ||
const spanToUse = cachedSpan || rootSpan; | ||
// Else, we try to use the active span. | ||
// Finally, we fall back to look at the transactionName on the scope | ||
const routeName = | ||
cachedRouteName || (rootSpan ? core.spanToJSON(rootSpan).description : scope.getScopeData().transactionName); | ||
const routeName = spanToUse ? core.spanToJSON(spanToUse).description : scope.getScopeData().transactionName; | ||
@@ -121,2 +121,5 @@ const user = scope.getUser(); | ||
replay_id: replayId || undefined, | ||
// INP score calculation in the sentry backend relies on the user agent | ||
// to account for different INP values being reported from different browsers | ||
'user_agent.original': types.WINDOW.navigator && types.WINDOW.navigator.userAgent, | ||
}); | ||
@@ -143,7 +146,13 @@ | ||
/** Register a listener to cache route information for INP interactions. */ | ||
function registerInpInteractionListener(latestRoute) { | ||
/** | ||
* Register a listener to cache route information for INP interactions. | ||
* TODO(v9): `latestRoute` no longer needs to be passed in and will be removed in v9. | ||
*/ | ||
function registerInpInteractionListener(_latestRoute) { | ||
const handleEntries = ({ entries }) => { | ||
const activeSpan = core.getActiveSpan(); | ||
const activeRootSpan = activeSpan && core.getRootSpan(activeSpan); | ||
entries.forEach(entry => { | ||
if (!instrument.isPerformanceEventTiming(entry) || !latestRoute.name) { | ||
if (!instrument.isPerformanceEventTiming(entry) || !activeRootSpan) { | ||
return; | ||
@@ -158,3 +167,3 @@ } | ||
// If the interaction was already recorded before, nothing more to do | ||
if (INTERACTIONS_ROUTE_MAP.has(interactionId)) { | ||
if (INTERACTIONS_SPAN_MAP.has(interactionId)) { | ||
return; | ||
@@ -166,10 +175,9 @@ } | ||
const last = LAST_INTERACTIONS.shift() ; | ||
INTERACTIONS_ROUTE_MAP.delete(last); | ||
INTERACTIONS_SPAN_MAP.delete(last); | ||
} | ||
// We add the interaction to the list of recorded interactions | ||
// and store the route information for this interaction | ||
// (we clone the object because it is mutated when it changes) | ||
// and store the span for this interaction | ||
LAST_INTERACTIONS.push(interactionId); | ||
INTERACTIONS_ROUTE_MAP.set(interactionId, latestRoute.name); | ||
INTERACTIONS_SPAN_MAP.set(interactionId, activeRootSpan); | ||
}); | ||
@@ -176,0 +184,0 @@ }; |
export { addClsInstrumentationHandler, addFidInstrumentationHandler, addInpInstrumentationHandler, addLcpInstrumentationHandler, addPerformanceInstrumentationHandler, addTtfbInstrumentationHandler } from './metrics/instrument.js'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingWebVitals } from './metrics/browserMetrics.js'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingWebVitals } from './metrics/browserMetrics.js'; | ||
export { addClickKeypressInstrumentationHandler } from './instrument/dom.js'; | ||
@@ -4,0 +4,0 @@ export { addHistoryInstrumentationHandler } from './instrument/history.js'; |
@@ -1,2 +0,2 @@ | ||
import { spanToJSON, setMeasurement, getActiveSpan, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; | ||
import { getActiveSpan, startInactiveSpan, spanToJSON, setMeasurement, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; | ||
import { browserPerformanceTimeOrigin, logger, parseUrl, htmlTreeAsString, getComponentName } from '@sentry/utils'; | ||
@@ -77,2 +77,55 @@ import { DEBUG_BUILD } from '../debug-build.js'; | ||
/** | ||
* Start tracking long animation frames. | ||
*/ | ||
function startTrackingLongAnimationFrames() { | ||
// NOTE: the current web-vitals version (3.5.2) does not support long-animation-frame, so | ||
// we directly observe `long-animation-frame` events instead of through the web-vitals | ||
// `observe` helper function. | ||
const observer = new PerformanceObserver(list => { | ||
for (const entry of list.getEntries() ) { | ||
if (!getActiveSpan()) { | ||
return; | ||
} | ||
if (!entry.scripts[0]) { | ||
return; | ||
} | ||
const startTime = msToSec((browserPerformanceTimeOrigin ) + entry.startTime); | ||
const duration = msToSec(entry.duration); | ||
const attributes = { | ||
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics', | ||
}; | ||
const initialScript = entry.scripts[0]; | ||
if (initialScript) { | ||
const { invoker, invokerType, sourceURL, sourceFunctionName, sourceCharPosition } = initialScript; | ||
attributes['browser.script.invoker'] = invoker; | ||
attributes['browser.script.invoker_type'] = invokerType; | ||
if (sourceURL) { | ||
attributes['code.filepath'] = sourceURL; | ||
} | ||
if (sourceFunctionName) { | ||
attributes['code.function'] = sourceFunctionName; | ||
} | ||
if (sourceCharPosition !== -1) { | ||
attributes['browser.script.source_char_position'] = sourceCharPosition; | ||
} | ||
} | ||
const span = startInactiveSpan({ | ||
name: 'Main UI thread blocked', | ||
op: 'ui.long-animation-frame', | ||
startTime, | ||
attributes, | ||
}); | ||
if (span) { | ||
span.end(startTime + duration); | ||
} | ||
} | ||
}); | ||
observer.observe({ type: 'long-animation-frame', buffered: true }); | ||
} | ||
/** | ||
* Start tracking interaction events. | ||
@@ -541,3 +594,3 @@ */ | ||
export { _addMeasureSpans, _addResourceSpans, addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingWebVitals }; | ||
export { _addMeasureSpans, _addResourceSpans, addPerformanceEntries, startTrackingInteractions, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingWebVitals }; | ||
//# sourceMappingURL=browserMetrics.js.map |
import { getClient, getCurrentScope, getActiveSpan, getRootSpan, spanToJSON, SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_UNIT, SEMANTIC_ATTRIBUTE_SENTRY_MEASUREMENT_VALUE } from '@sentry/core'; | ||
import { browserPerformanceTimeOrigin, htmlTreeAsString, dropUndefinedKeys } from '@sentry/utils'; | ||
import { WINDOW } from '../types.js'; | ||
import { addInpInstrumentationHandler, addPerformanceInstrumentationHandler, isPerformanceEventTiming } from './instrument.js'; | ||
import { getBrowserPerformanceAPI, msToSec } from './utils.js'; | ||
// We only care about name here | ||
const LAST_INTERACTIONS = []; | ||
const INTERACTIONS_ROUTE_MAP = new Map(); | ||
const INTERACTIONS_SPAN_MAP = new Map(); | ||
@@ -81,10 +80,11 @@ /** | ||
// We first try to lookup the route name from our INTERACTIONS_ROUTE_MAP, | ||
// We first try to lookup the span from our INTERACTIONS_SPAN_MAP, | ||
// where we cache the route per interactionId | ||
const cachedRouteName = interactionId != null ? INTERACTIONS_ROUTE_MAP.get(interactionId) : undefined; | ||
const cachedSpan = interactionId != null ? INTERACTIONS_SPAN_MAP.get(interactionId) : undefined; | ||
const spanToUse = cachedSpan || rootSpan; | ||
// Else, we try to use the active span. | ||
// Finally, we fall back to look at the transactionName on the scope | ||
const routeName = | ||
cachedRouteName || (rootSpan ? spanToJSON(rootSpan).description : scope.getScopeData().transactionName); | ||
const routeName = spanToUse ? spanToJSON(spanToUse).description : scope.getScopeData().transactionName; | ||
@@ -118,2 +118,5 @@ const user = scope.getUser(); | ||
replay_id: replayId || undefined, | ||
// INP score calculation in the sentry backend relies on the user agent | ||
// to account for different INP values being reported from different browsers | ||
'user_agent.original': WINDOW.navigator && WINDOW.navigator.userAgent, | ||
}); | ||
@@ -140,7 +143,13 @@ | ||
/** Register a listener to cache route information for INP interactions. */ | ||
function registerInpInteractionListener(latestRoute) { | ||
/** | ||
* Register a listener to cache route information for INP interactions. | ||
* TODO(v9): `latestRoute` no longer needs to be passed in and will be removed in v9. | ||
*/ | ||
function registerInpInteractionListener(_latestRoute) { | ||
const handleEntries = ({ entries }) => { | ||
const activeSpan = getActiveSpan(); | ||
const activeRootSpan = activeSpan && getRootSpan(activeSpan); | ||
entries.forEach(entry => { | ||
if (!isPerformanceEventTiming(entry) || !latestRoute.name) { | ||
if (!isPerformanceEventTiming(entry) || !activeRootSpan) { | ||
return; | ||
@@ -155,3 +164,3 @@ } | ||
// If the interaction was already recorded before, nothing more to do | ||
if (INTERACTIONS_ROUTE_MAP.has(interactionId)) { | ||
if (INTERACTIONS_SPAN_MAP.has(interactionId)) { | ||
return; | ||
@@ -163,10 +172,9 @@ } | ||
const last = LAST_INTERACTIONS.shift() ; | ||
INTERACTIONS_ROUTE_MAP.delete(last); | ||
INTERACTIONS_SPAN_MAP.delete(last); | ||
} | ||
// We add the interaction to the list of recorded interactions | ||
// and store the route information for this interaction | ||
// (we clone the object because it is mutated when it changes) | ||
// and store the span for this interaction | ||
LAST_INTERACTIONS.push(interactionId); | ||
INTERACTIONS_ROUTE_MAP.set(interactionId, latestRoute.name); | ||
INTERACTIONS_SPAN_MAP.set(interactionId, activeRootSpan); | ||
}); | ||
@@ -173,0 +181,0 @@ }; |
export { addPerformanceInstrumentationHandler, addClsInstrumentationHandler, addFidInstrumentationHandler, addTtfbInstrumentationHandler, addLcpInstrumentationHandler, addInpInstrumentationHandler, } from './metrics/instrument'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingWebVitals, startTrackingINP, registerInpInteractionListener, } from './metrics/browserMetrics'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingLongAnimationFrames, startTrackingWebVitals, startTrackingINP, registerInpInteractionListener, } from './metrics/browserMetrics'; | ||
export { addClickKeypressInstrumentationHandler } from './instrument/dom'; | ||
@@ -4,0 +4,0 @@ export { addHistoryInstrumentationHandler } from './instrument/history'; |
@@ -14,2 +14,6 @@ import { Span } from '@sentry/types'; | ||
/** | ||
* Start tracking long animation frames. | ||
*/ | ||
export declare function startTrackingLongAnimationFrames(): void; | ||
/** | ||
* Start tracking interaction events. | ||
@@ -16,0 +20,0 @@ */ |
@@ -1,4 +0,1 @@ | ||
interface PartialRouteInfo { | ||
name: string | undefined; | ||
} | ||
/** | ||
@@ -8,5 +5,7 @@ * Start tracking INP webvital events. | ||
export declare function startTrackingINP(): () => void; | ||
/** Register a listener to cache route information for INP interactions. */ | ||
export declare function registerInpInteractionListener(latestRoute: PartialRouteInfo): void; | ||
export {}; | ||
/** | ||
* Register a listener to cache route information for INP interactions. | ||
* TODO(v9): `latestRoute` no longer needs to be passed in and will be removed in v9. | ||
*/ | ||
export declare function registerInpInteractionListener(_latestRoute?: unknown): void; | ||
//# sourceMappingURL=inp.d.ts.map |
@@ -17,2 +17,12 @@ type InstrumentHandlerTypePerformanceObserver = 'longtask' | 'event' | 'navigation' | 'paint' | 'resource' | 'first-input'; | ||
} | ||
interface PerformanceScriptTiming extends PerformanceEntry { | ||
sourceURL: string; | ||
sourceFunctionName: string; | ||
sourceCharPosition: number; | ||
invoker: string; | ||
invokerType: string; | ||
} | ||
export interface PerformanceLongAnimationFrameTiming extends PerformanceEntry { | ||
scripts: PerformanceScriptTiming[]; | ||
} | ||
interface Metric { | ||
@@ -19,0 +29,0 @@ /** |
export { addPerformanceInstrumentationHandler, addClsInstrumentationHandler, addFidInstrumentationHandler, addTtfbInstrumentationHandler, addLcpInstrumentationHandler, addInpInstrumentationHandler, } from './metrics/instrument'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingWebVitals, startTrackingINP, registerInpInteractionListener, } from './metrics/browserMetrics'; | ||
export { addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingLongAnimationFrames, startTrackingWebVitals, startTrackingINP, registerInpInteractionListener, } from './metrics/browserMetrics'; | ||
export { addClickKeypressInstrumentationHandler } from './instrument/dom'; | ||
@@ -4,0 +4,0 @@ export { addHistoryInstrumentationHandler } from './instrument/history'; |
@@ -14,2 +14,6 @@ import type { Span } from '@sentry/types'; | ||
/** | ||
* Start tracking long animation frames. | ||
*/ | ||
export declare function startTrackingLongAnimationFrames(): void; | ||
/** | ||
* Start tracking interaction events. | ||
@@ -16,0 +20,0 @@ */ |
@@ -1,4 +0,1 @@ | ||
interface PartialRouteInfo { | ||
name: string | undefined; | ||
} | ||
/** | ||
@@ -8,5 +5,7 @@ * Start tracking INP webvital events. | ||
export declare function startTrackingINP(): () => void; | ||
/** Register a listener to cache route information for INP interactions. */ | ||
export declare function registerInpInteractionListener(latestRoute: PartialRouteInfo): void; | ||
export {}; | ||
/** | ||
* Register a listener to cache route information for INP interactions. | ||
* TODO(v9): `latestRoute` no longer needs to be passed in and will be removed in v9. | ||
*/ | ||
export declare function registerInpInteractionListener(_latestRoute?: unknown): void; | ||
//# sourceMappingURL=inp.d.ts.map |
@@ -17,2 +17,12 @@ type InstrumentHandlerTypePerformanceObserver = 'longtask' | 'event' | 'navigation' | 'paint' | 'resource' | 'first-input'; | ||
} | ||
interface PerformanceScriptTiming extends PerformanceEntry { | ||
sourceURL: string; | ||
sourceFunctionName: string; | ||
sourceCharPosition: number; | ||
invoker: string; | ||
invokerType: string; | ||
} | ||
export interface PerformanceLongAnimationFrameTiming extends PerformanceEntry { | ||
scripts: PerformanceScriptTiming[]; | ||
} | ||
interface Metric { | ||
@@ -19,0 +29,0 @@ /** |
{ | ||
"name": "@sentry-internal/browser-utils", | ||
"version": "8.17.0", | ||
"version": "8.18.0", | ||
"description": "Browser Utilities for all Sentry JavaScript SDKs", | ||
@@ -42,5 +42,5 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
"dependencies": { | ||
"@sentry/core": "8.17.0", | ||
"@sentry/types": "8.17.0", | ||
"@sentry/utils": "8.17.0" | ||
"@sentry/core": "8.18.0", | ||
"@sentry/types": "8.18.0", | ||
"@sentry/utils": "8.18.0" | ||
}, | ||
@@ -47,0 +47,0 @@ "scripts": { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
660025
7069
+ Added@sentry/core@8.18.0(transitive)
+ Added@sentry/types@8.18.0(transitive)
+ Added@sentry/utils@8.18.0(transitive)
- Removed@sentry/core@8.17.0(transitive)
- Removed@sentry/types@8.17.0(transitive)
- Removed@sentry/utils@8.17.0(transitive)
Updated@sentry/core@8.18.0
Updated@sentry/types@8.18.0
Updated@sentry/utils@8.18.0