@newrelic/browser-agent 1.283.2 → 1.284.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.
- package/CHANGELOG.md +15 -0
- package/LICENSE +1 -1
- package/dist/cjs/common/constants/env.cdn.js +2 -2
- package/dist/cjs/common/constants/env.npm.js +2 -2
- package/dist/cjs/common/vitals/constants.js +1 -1
- package/dist/cjs/common/vitals/interaction-to-next-paint.js +20 -1
- package/dist/cjs/features/jserrors/shared/cast-error.js +5 -5
- package/dist/cjs/features/metrics/aggregate/index.js +3 -0
- package/dist/cjs/features/metrics/instrument/index.js +7 -0
- package/dist/cjs/features/page_view_timing/aggregate/index.js +1 -2
- package/dist/cjs/features/session_replay/shared/stylesheet-evaluator.js +1 -1
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +0 -7
- package/dist/esm/common/constants/env.cdn.js +2 -2
- package/dist/esm/common/constants/env.npm.js +2 -2
- package/dist/esm/common/vitals/constants.js +1 -1
- package/dist/esm/common/vitals/interaction-to-next-paint.js +20 -1
- package/dist/esm/features/jserrors/shared/cast-error.js +5 -5
- package/dist/esm/features/metrics/aggregate/index.js +3 -0
- package/dist/esm/features/metrics/instrument/index.js +12 -2
- package/dist/esm/features/page_view_timing/aggregate/index.js +2 -3
- package/dist/esm/features/session_replay/shared/stylesheet-evaluator.js +1 -1
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +0 -7
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/vitals/constants.d.ts +1 -1
- package/dist/types/common/vitals/interaction-to-next-paint.d.ts +1 -0
- package/dist/types/common/vitals/interaction-to-next-paint.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/common/vitals/constants.js +1 -1
- package/src/common/vitals/interaction-to-next-paint.js +21 -2
- package/src/features/jserrors/shared/cast-error.js +5 -5
- package/src/features/metrics/aggregate/index.js +3 -0
- package/src/features/metrics/instrument/index.js +14 -2
- package/src/features/page_view_timing/aggregate/index.js +2 -3
- package/src/features/session_replay/shared/stylesheet-evaluator.js +1 -1
- package/src/features/session_trace/aggregate/trace/storage.js +0 -5
- package/dist/cjs/common/vitals/first-input-delay.js +0 -36
- package/dist/esm/common/vitals/first-input-delay.js +0 -29
- package/dist/types/common/vitals/first-input-delay.d.ts +0 -3
- package/dist/types/common/vitals/first-input-delay.d.ts.map +0 -1
- package/src/common/vitals/first-input-delay.js +0 -28
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,21 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.284.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.283.2...v1.284.0) (2025-03-04)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Remove FID, replace first interaction detection with INP ([#1395](https://github.com/newrelic/newrelic-browser-agent/issues/1395)) ([436ce94](https://github.com/newrelic/newrelic-browser-agent/commit/436ce94eac45e3e28d6b3be6fe9f9fcb15ac1e9b))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Bug Fixes
|
|
15
|
+
|
|
16
|
+
* bump web-vitals from 4.2.3 to 4.2.4 ([#1379](https://github.com/newrelic/newrelic-browser-agent/issues/1379)) ([d0b5b83](https://github.com/newrelic/newrelic-browser-agent/commit/d0b5b83ec50755771e9d4afbf984937f5ab00458))
|
|
17
|
+
* Deduplicate Prefixes on Unhandled Promise Rejection Messages ([#1397](https://github.com/newrelic/newrelic-browser-agent/issues/1397)) ([474fc4f](https://github.com/newrelic/newrelic-browser-agent/commit/474fc4fbc6f7b3fe6b396ce86acaaa1bc712e5fd))
|
|
18
|
+
* Guard against non-CSSStyleSheet when fixing sheets for replay ([#1396](https://github.com/newrelic/newrelic-browser-agent/issues/1396)) ([b929aba](https://github.com/newrelic/newrelic-browser-agent/commit/b929abafb5ab04287fc1f0a07397ff739f314c38))
|
|
19
|
+
* Upgrade rrweb to 18 ([#1383](https://github.com/newrelic/newrelic-browser-agent/issues/1383)) ([46b691b](https://github.com/newrelic/newrelic-browser-agent/commit/46b691b671d2090f47707eea6dfa5ae8f31d0c7b))
|
|
20
|
+
|
|
6
21
|
## [1.283.2](https://github.com/newrelic/newrelic-browser-agent/compare/v1.283.1...v1.283.2) (2025-02-21)
|
|
7
22
|
|
|
8
23
|
|
package/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright New Relic, Inc. All rights reserved.
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.
|
|
20
|
+
const VERSION = exports.VERSION = "1.284.0";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -33,4 +33,4 @@ const DIST_METHOD = exports.DIST_METHOD = 'CDN';
|
|
|
33
33
|
/**
|
|
34
34
|
* Exposes the lib version of rrweb
|
|
35
35
|
*/
|
|
36
|
-
const RRWEB_VERSION = exports.RRWEB_VERSION = "^2.0.0-alpha.
|
|
36
|
+
const RRWEB_VERSION = exports.RRWEB_VERSION = "^2.0.0-alpha.18";
|
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.
|
|
20
|
+
const VERSION = exports.VERSION = "1.284.0";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -34,4 +34,4 @@ const DIST_METHOD = exports.DIST_METHOD = 'NPM';
|
|
|
34
34
|
/**
|
|
35
35
|
* Exposes the lib version of rrweb
|
|
36
36
|
*/
|
|
37
|
-
const RRWEB_VERSION = exports.RRWEB_VERSION = "^2.0.0-alpha.
|
|
37
|
+
const RRWEB_VERSION = exports.RRWEB_VERSION = "^2.0.0-alpha.18";
|
|
@@ -11,7 +11,7 @@ exports.VITAL_NAMES = void 0;
|
|
|
11
11
|
const VITAL_NAMES = exports.VITAL_NAMES = {
|
|
12
12
|
FIRST_PAINT: 'fp',
|
|
13
13
|
FIRST_CONTENTFUL_PAINT: 'fcp',
|
|
14
|
-
|
|
14
|
+
FIRST_INTERACTION: 'fi',
|
|
15
15
|
LARGEST_CONTENTFUL_PAINT: 'lcp',
|
|
16
16
|
CUMULATIVE_LAYOUT_SHIFT: 'cls',
|
|
17
17
|
INTERACTION_TO_NEXT_PAINT: 'inp',
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.interactionToNextPaint = void 0;
|
|
6
|
+
exports.interactionToNextPaint = exports.firstInteraction = void 0;
|
|
7
7
|
var _attribution = require("web-vitals/attribution");
|
|
8
8
|
var _vitalMetric = require("./vital-metric");
|
|
9
9
|
var _constants = require("./constants");
|
|
@@ -14,7 +14,21 @@ var _runtime = require("../constants/runtime");
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
const interactionToNextPaint = exports.interactionToNextPaint = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.INTERACTION_TO_NEXT_PAINT);
|
|
17
|
+
// Note: First Interaction is a legacy NR timing event, not an actual CWV metric
|
|
18
|
+
// ('fi' used to be detected via FID. It is now represented by the first INP)
|
|
19
|
+
const firstInteraction = exports.firstInteraction = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_INTERACTION);
|
|
17
20
|
if (_runtime.isBrowserScope) {
|
|
21
|
+
const recordFirstInteraction = attribution => {
|
|
22
|
+
firstInteraction.update({
|
|
23
|
+
value: attribution.interactionTime,
|
|
24
|
+
attrs: {
|
|
25
|
+
type: attribution.interactionType,
|
|
26
|
+
eventTarget: attribution.interactionTarget,
|
|
27
|
+
loadState: attribution.loadState
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
18
32
|
/* Interaction-to-Next-Paint */
|
|
19
33
|
(0, _attribution.onINP)(({
|
|
20
34
|
value,
|
|
@@ -40,5 +54,10 @@ if (_runtime.isBrowserScope) {
|
|
|
40
54
|
value,
|
|
41
55
|
attrs
|
|
42
56
|
});
|
|
57
|
+
|
|
58
|
+
// preserve the original behavior where FID is not reported if the page is hidden before the first interaction
|
|
59
|
+
if (!firstInteraction.isValid && !_runtime.initiallyHidden) {
|
|
60
|
+
recordFirstInteraction(attribution);
|
|
61
|
+
}
|
|
43
62
|
});
|
|
44
63
|
}
|
|
@@ -37,7 +37,7 @@ function castError(error) {
|
|
|
37
37
|
* @returns {Error} An Error object with the message as the casted reason
|
|
38
38
|
*/
|
|
39
39
|
function castPromiseRejectionEvent(promiseRejectionEvent) {
|
|
40
|
-
const prefix = 'Unhandled Promise Rejection';
|
|
40
|
+
const prefix = 'Unhandled Promise Rejection: ';
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
43
|
* If the casted return value is falsy like this, it will get dropped and not produce an error event for harvest.
|
|
@@ -47,14 +47,14 @@ function castPromiseRejectionEvent(promiseRejectionEvent) {
|
|
|
47
47
|
if (!promiseRejectionEvent?.reason) return;
|
|
48
48
|
if (canTrustError(promiseRejectionEvent.reason)) {
|
|
49
49
|
try {
|
|
50
|
-
promiseRejectionEvent.reason.message = prefix +
|
|
51
|
-
return castError(promiseRejectionEvent.reason);
|
|
50
|
+
if (!promiseRejectionEvent.reason.message.startsWith(prefix)) promiseRejectionEvent.reason.message = prefix + promiseRejectionEvent.reason.message;
|
|
52
51
|
} catch (e) {
|
|
53
|
-
|
|
52
|
+
// failed to modify the message, do nothing else
|
|
54
53
|
}
|
|
54
|
+
return castError(promiseRejectionEvent.reason);
|
|
55
55
|
}
|
|
56
56
|
const error = castError(promiseRejectionEvent.reason);
|
|
57
|
-
error.message
|
|
57
|
+
if (!(error.message || '').startsWith(prefix)) error.message = prefix + error.message;
|
|
58
58
|
return error;
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -135,6 +135,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
+
// webdriver detection
|
|
139
|
+
if (navigator.webdriver) this.storeSupportabilityMetrics('Generic/WebDriver/Detected');
|
|
140
|
+
|
|
138
141
|
// WATCHABLE_WEB_SOCKET_EVENTS.forEach(tag => {
|
|
139
142
|
// registerHandler('buffered-' + WEBSOCKET_TAG + tag, (...args) => {
|
|
140
143
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
@@ -4,6 +4,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Metrics = exports.Instrument = void 0;
|
|
7
|
+
var _runtime = require("../../../common/constants/runtime");
|
|
8
|
+
var _handle = require("../../../common/event-emitter/handle");
|
|
7
9
|
var _instrumentBase = require("../../utils/instrument-base");
|
|
8
10
|
var _constants = require("../constants");
|
|
9
11
|
/**
|
|
@@ -26,6 +28,11 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
26
28
|
// })
|
|
27
29
|
// })
|
|
28
30
|
|
|
31
|
+
if (_runtime.isBrowserScope) {
|
|
32
|
+
document.addEventListener('securitypolicyviolation', e => {
|
|
33
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Generic/CSPViolation/Detected'], undefined, this.featureName, this.ee);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
29
36
|
this.importAggregator(agentRef);
|
|
30
37
|
}
|
|
31
38
|
}
|
|
@@ -12,7 +12,6 @@ var _features = require("../../../loaders/features/features");
|
|
|
12
12
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
13
13
|
var _cumulativeLayoutShift = require("../../../common/vitals/cumulative-layout-shift");
|
|
14
14
|
var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
|
|
15
|
-
var _firstInputDelay = require("../../../common/vitals/first-input-delay");
|
|
16
15
|
var _firstPaint = require("../../../common/vitals/first-paint");
|
|
17
16
|
var _interactionToNextPaint = require("../../../common/vitals/interaction-to-next-paint");
|
|
18
17
|
var _largestContentfulPaint = require("../../../common/vitals/largest-contentful-paint");
|
|
@@ -42,8 +41,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
42
41
|
this.waitForFlags([]).then(() => {
|
|
43
42
|
_firstPaint.firstPaint.subscribe(this.#handleVitalMetric);
|
|
44
43
|
_firstContentfulPaint.firstContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
45
|
-
_firstInputDelay.firstInputDelay.subscribe(this.#handleVitalMetric);
|
|
46
44
|
_largestContentfulPaint.largestContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
45
|
+
_interactionToNextPaint.firstInteraction.subscribe(this.#handleVitalMetric);
|
|
47
46
|
_interactionToNextPaint.interactionToNextPaint.subscribe(this.#handleVitalMetric);
|
|
48
47
|
_timeToFirstByte.timeToFirstByte.subscribe(({
|
|
49
48
|
attrs
|
|
@@ -30,7 +30,7 @@ class StylesheetEvaluator {
|
|
|
30
30
|
this.#brokenSheets = [];
|
|
31
31
|
if (_runtime.isBrowserScope) {
|
|
32
32
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
33
|
-
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
33
|
+
if (!this.#evaluated.has(document.styleSheets[i]) && document.styleSheets[i] instanceof CSSStyleSheet) {
|
|
34
34
|
this.#evaluated.add(document.styleSheets[i]);
|
|
35
35
|
try {
|
|
36
36
|
// eslint-disable-next-line
|
|
@@ -144,13 +144,6 @@ class TraceStorage {
|
|
|
144
144
|
this.storeTiming({
|
|
145
145
|
[name]: value
|
|
146
146
|
});
|
|
147
|
-
if (hasFID(name, attrs)) this.storeEvent({
|
|
148
|
-
type: 'fid',
|
|
149
|
-
target: 'document'
|
|
150
|
-
}, 'document', value, value + attrs.fid);
|
|
151
|
-
function hasFID(name, attrs) {
|
|
152
|
-
return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
|
|
153
|
-
}
|
|
154
147
|
}
|
|
155
148
|
storeTiming(timingEntry, isAbsoluteTimestamp = false) {
|
|
156
149
|
if (!timingEntry) return;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Exposes the version of the agent
|
|
13
13
|
*/
|
|
14
|
-
export const VERSION = "1.
|
|
14
|
+
export const VERSION = "1.284.0";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Exposes the build type of the agent
|
|
@@ -27,4 +27,4 @@ export const DIST_METHOD = 'CDN';
|
|
|
27
27
|
/**
|
|
28
28
|
* Exposes the lib version of rrweb
|
|
29
29
|
*/
|
|
30
|
-
export const RRWEB_VERSION = "^2.0.0-alpha.
|
|
30
|
+
export const RRWEB_VERSION = "^2.0.0-alpha.18";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Exposes the version of the agent
|
|
13
13
|
*/
|
|
14
|
-
export const VERSION = "1.
|
|
14
|
+
export const VERSION = "1.284.0";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Exposes the build type of the agent
|
|
@@ -28,4 +28,4 @@ export const DIST_METHOD = 'NPM';
|
|
|
28
28
|
/**
|
|
29
29
|
* Exposes the lib version of rrweb
|
|
30
30
|
*/
|
|
31
|
-
export const RRWEB_VERSION = "^2.0.0-alpha.
|
|
31
|
+
export const RRWEB_VERSION = "^2.0.0-alpha.18";
|
|
@@ -5,9 +5,23 @@
|
|
|
5
5
|
import { onINP } from 'web-vitals/attribution';
|
|
6
6
|
import { VitalMetric } from './vital-metric';
|
|
7
7
|
import { VITAL_NAMES } from './constants';
|
|
8
|
-
import { isBrowserScope } from '../constants/runtime';
|
|
8
|
+
import { initiallyHidden, isBrowserScope } from '../constants/runtime';
|
|
9
9
|
export const interactionToNextPaint = new VitalMetric(VITAL_NAMES.INTERACTION_TO_NEXT_PAINT);
|
|
10
|
+
// Note: First Interaction is a legacy NR timing event, not an actual CWV metric
|
|
11
|
+
// ('fi' used to be detected via FID. It is now represented by the first INP)
|
|
12
|
+
export const firstInteraction = new VitalMetric(VITAL_NAMES.FIRST_INTERACTION);
|
|
10
13
|
if (isBrowserScope) {
|
|
14
|
+
const recordFirstInteraction = attribution => {
|
|
15
|
+
firstInteraction.update({
|
|
16
|
+
value: attribution.interactionTime,
|
|
17
|
+
attrs: {
|
|
18
|
+
type: attribution.interactionType,
|
|
19
|
+
eventTarget: attribution.interactionTarget,
|
|
20
|
+
loadState: attribution.loadState
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
11
25
|
/* Interaction-to-Next-Paint */
|
|
12
26
|
onINP(({
|
|
13
27
|
value,
|
|
@@ -33,5 +47,10 @@ if (isBrowserScope) {
|
|
|
33
47
|
value,
|
|
34
48
|
attrs
|
|
35
49
|
});
|
|
50
|
+
|
|
51
|
+
// preserve the original behavior where FID is not reported if the page is hidden before the first interaction
|
|
52
|
+
if (!firstInteraction.isValid && !initiallyHidden) {
|
|
53
|
+
recordFirstInteraction(attribution);
|
|
54
|
+
}
|
|
36
55
|
});
|
|
37
56
|
}
|
|
@@ -29,7 +29,7 @@ export function castError(error) {
|
|
|
29
29
|
* @returns {Error} An Error object with the message as the casted reason
|
|
30
30
|
*/
|
|
31
31
|
export function castPromiseRejectionEvent(promiseRejectionEvent) {
|
|
32
|
-
const prefix = 'Unhandled Promise Rejection';
|
|
32
|
+
const prefix = 'Unhandled Promise Rejection: ';
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* If the casted return value is falsy like this, it will get dropped and not produce an error event for harvest.
|
|
@@ -39,14 +39,14 @@ export function castPromiseRejectionEvent(promiseRejectionEvent) {
|
|
|
39
39
|
if (!promiseRejectionEvent?.reason) return;
|
|
40
40
|
if (canTrustError(promiseRejectionEvent.reason)) {
|
|
41
41
|
try {
|
|
42
|
-
promiseRejectionEvent.reason.message = prefix +
|
|
43
|
-
return castError(promiseRejectionEvent.reason);
|
|
42
|
+
if (!promiseRejectionEvent.reason.message.startsWith(prefix)) promiseRejectionEvent.reason.message = prefix + promiseRejectionEvent.reason.message;
|
|
44
43
|
} catch (e) {
|
|
45
|
-
|
|
44
|
+
// failed to modify the message, do nothing else
|
|
46
45
|
}
|
|
46
|
+
return castError(promiseRejectionEvent.reason);
|
|
47
47
|
}
|
|
48
48
|
const error = castError(promiseRejectionEvent.reason);
|
|
49
|
-
error.message
|
|
49
|
+
if (!(error.message || '').startsWith(prefix)) error.message = prefix + error.message;
|
|
50
50
|
return error;
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -128,6 +128,9 @@ export class Aggregate extends AggregateBase {
|
|
|
128
128
|
});
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
// webdriver detection
|
|
132
|
+
if (navigator.webdriver) this.storeSupportabilityMetrics('Generic/WebDriver/Detected');
|
|
133
|
+
|
|
131
134
|
// WATCHABLE_WEB_SOCKET_EVENTS.forEach(tag => {
|
|
132
135
|
// registerHandler('buffered-' + WEBSOCKET_TAG + tag, (...args) => {
|
|
133
136
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
@@ -3,10 +3,15 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { isBrowserScope } from '../../../common/constants/runtime';
|
|
7
|
+
import { handle } from '../../../common/event-emitter/handle';
|
|
8
|
+
import { InstrumentBase } from '../../utils/instrument-base';
|
|
9
|
+
import { FEATURE_NAME,
|
|
10
|
+
// WATCHABLE_WEB_SOCKET_EVENTS,
|
|
11
|
+
SUPPORTABILITY_METRIC_CHANNEL } from '../constants';
|
|
6
12
|
// import { handle } from '../../../common/event-emitter/handle'
|
|
7
13
|
// import { WEBSOCKET_TAG, wrapWebSocket } from '../../../common/wrap/wrap-websocket'
|
|
8
|
-
|
|
9
|
-
import { FEATURE_NAME } from '../constants';
|
|
14
|
+
|
|
10
15
|
export class Instrument extends InstrumentBase {
|
|
11
16
|
static featureName = FEATURE_NAME;
|
|
12
17
|
constructor(agentRef, auto = true) {
|
|
@@ -19,6 +24,11 @@ export class Instrument extends InstrumentBase {
|
|
|
19
24
|
// })
|
|
20
25
|
// })
|
|
21
26
|
|
|
27
|
+
if (isBrowserScope) {
|
|
28
|
+
document.addEventListener('securitypolicyviolation', e => {
|
|
29
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/CSPViolation/Detected'], undefined, this.featureName, this.ee);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
22
32
|
this.importAggregator(agentRef);
|
|
23
33
|
}
|
|
24
34
|
}
|
|
@@ -11,9 +11,8 @@ import { FEATURE_NAMES } from '../../../loaders/features/features';
|
|
|
11
11
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
12
12
|
import { cumulativeLayoutShift } from '../../../common/vitals/cumulative-layout-shift';
|
|
13
13
|
import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint';
|
|
14
|
-
import { firstInputDelay } from '../../../common/vitals/first-input-delay';
|
|
15
14
|
import { firstPaint } from '../../../common/vitals/first-paint';
|
|
16
|
-
import { interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint';
|
|
15
|
+
import { firstInteraction, interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint';
|
|
17
16
|
import { largestContentfulPaint } from '../../../common/vitals/largest-contentful-paint';
|
|
18
17
|
import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte';
|
|
19
18
|
import { subscribeToVisibilityChange } from '../../../common/window/page-visibility';
|
|
@@ -36,8 +35,8 @@ export class Aggregate extends AggregateBase {
|
|
|
36
35
|
this.waitForFlags([]).then(() => {
|
|
37
36
|
firstPaint.subscribe(this.#handleVitalMetric);
|
|
38
37
|
firstContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
39
|
-
firstInputDelay.subscribe(this.#handleVitalMetric);
|
|
40
38
|
largestContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
39
|
+
firstInteraction.subscribe(this.#handleVitalMetric);
|
|
41
40
|
interactionToNextPaint.subscribe(this.#handleVitalMetric);
|
|
42
41
|
timeToFirstByte.subscribe(({
|
|
43
42
|
attrs
|
|
@@ -23,7 +23,7 @@ class StylesheetEvaluator {
|
|
|
23
23
|
this.#brokenSheets = [];
|
|
24
24
|
if (isBrowserScope) {
|
|
25
25
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
26
|
-
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
26
|
+
if (!this.#evaluated.has(document.styleSheets[i]) && document.styleSheets[i] instanceof CSSStyleSheet) {
|
|
27
27
|
this.#evaluated.add(document.styleSheets[i]);
|
|
28
28
|
try {
|
|
29
29
|
// eslint-disable-next-line
|
|
@@ -137,13 +137,6 @@ export class TraceStorage {
|
|
|
137
137
|
this.storeTiming({
|
|
138
138
|
[name]: value
|
|
139
139
|
});
|
|
140
|
-
if (hasFID(name, attrs)) this.storeEvent({
|
|
141
|
-
type: 'fid',
|
|
142
|
-
target: 'document'
|
|
143
|
-
}, 'document', value, value + attrs.fid);
|
|
144
|
-
function hasFID(name, attrs) {
|
|
145
|
-
return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
|
|
146
|
-
}
|
|
147
140
|
}
|
|
148
141
|
storeTiming(timingEntry, isAbsoluteTimestamp = false) {
|
|
149
142
|
if (!timingEntry) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/context/shared-context.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-
|
|
1
|
+
{"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/context/shared-context.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/event-buffer.js","../src/features/utils/event-store-manager.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/lazy-feature-loader.js","../src/features/utils/nr1-debugger.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/api-methods.js","../src/loaders/api/api.js","../src/loaders/api/apiAsync.js","../src/loaders/api/interaction-types.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.7.3"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export namespace VITAL_NAMES {
|
|
2
2
|
let FIRST_PAINT: string;
|
|
3
3
|
let FIRST_CONTENTFUL_PAINT: string;
|
|
4
|
-
let
|
|
4
|
+
let FIRST_INTERACTION: string;
|
|
5
5
|
let LARGEST_CONTENTFUL_PAINT: string;
|
|
6
6
|
let CUMULATIVE_LAYOUT_SHIFT: string;
|
|
7
7
|
let INTERACTION_TO_NEXT_PAINT: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interaction-to-next-paint.d.ts","sourceRoot":"","sources":["../../../../src/common/vitals/interaction-to-next-paint.js"],"names":[],"mappings":"AASA,iDAA4F;
|
|
1
|
+
{"version":3,"file":"interaction-to-next-paint.d.ts","sourceRoot":"","sources":["../../../../src/common/vitals/interaction-to-next-paint.js"],"names":[],"mappings":"AASA,iDAA4F;AAG5F,2CAA8E;4BAPlD,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,2BAoBC;IAED,iCAAsE;IAEtE,wDAKC;IAED,iDAKC;IAED,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,2BAoBC;IAED,iCAAsE;IAEtE,wDAKC;IAED,iDAKC;IAED,qBAsEC;IAED,0BAOC;CACF;8BA7H6B,4BAA4B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/instrument/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/instrument/index.js"],"names":[],"mappings":"AAgBA;IACE,2BAAiC;IACjC,2CAiBC;CACF;AAED,wCAAiC;+BA/BF,6BAA6B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_timing/aggregate/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_timing/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IAMjC,2BA4BC;IA1BC,4BAA+B;IA4BjC;;;OAGG;IACH,6BAFW,MAAM,QAOhB;IAED,mDAuBC;IAED,gDAUC;IAGD,qCAuBC;;CACF;8BAxH6B,4BAA4B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/session_trace/aggregate/trace/storage.js"],"names":[],"mappings":"AA6BA,+HAA+H;AAC/H;IAQE,yBAEC;IATD,kBAAa;IACb,UAAU;IACV,0BAA4B;IAC5B,wBAAmB;IACnB,2BAA4B;IAI1B,YAAoB;IAGtB,gGAAgG;IAChG,yBAcC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAED,oEAAoE;IACpE;;;;MAgBC;IAED,mEA6BC;IAED,
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/session_trace/aggregate/trace/storage.js"],"names":[],"mappings":"AA6BA,+HAA+H;AAC/H;IAQE,yBAEC;IATD,kBAAa;IACb,UAAU;IACV,0BAA4B;IAC5B,wBAAmB;IACnB,2BAA4B;IAI1B,YAAoB;IAGtB,gGAAgG;IAChG,yBAcC;IAED;;;;OAIG;IACH,2BAHW,MAAM,GACJ,MAAM,CAsBlB;IAED,oEAAoE;IACpE;;;;MAgBC;IAED,mEA6BC;IAED,oDAEC;IAED,mEAuBC;IAGD,uEAcC;IAED,oDAKC;IAED,wBAwBC;IAED,uCAuBC;IAGD,gDAEC;IAID,qCAaC;IAGD,qEAGC;IAGD,mEAGC;IAID,mBAEC;IAED,aAEC;IAED;;;;;;;QAEC;IAED,cAMC;IAED,mBAEC;IAED,kBAEC;;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/browser-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.284.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
|
|
6
6
|
"description": "New Relic Browser Agent",
|
|
@@ -207,8 +207,8 @@
|
|
|
207
207
|
},
|
|
208
208
|
"dependencies": {
|
|
209
209
|
"fflate": "0.8.2",
|
|
210
|
-
"rrweb": "^2.0.0-alpha.
|
|
211
|
-
"web-vitals": "4.2.
|
|
210
|
+
"rrweb": "^2.0.0-alpha.18",
|
|
211
|
+
"web-vitals": "4.2.4"
|
|
212
212
|
},
|
|
213
213
|
"devDependencies": {
|
|
214
214
|
"@babel/cli": "^7.23.4",
|
|
@@ -5,12 +5,26 @@
|
|
|
5
5
|
import { onINP } from 'web-vitals/attribution'
|
|
6
6
|
import { VitalMetric } from './vital-metric'
|
|
7
7
|
import { VITAL_NAMES } from './constants'
|
|
8
|
-
import { isBrowserScope } from '../constants/runtime'
|
|
8
|
+
import { initiallyHidden, isBrowserScope } from '../constants/runtime'
|
|
9
9
|
|
|
10
10
|
export const interactionToNextPaint = new VitalMetric(VITAL_NAMES.INTERACTION_TO_NEXT_PAINT)
|
|
11
|
+
// Note: First Interaction is a legacy NR timing event, not an actual CWV metric
|
|
12
|
+
// ('fi' used to be detected via FID. It is now represented by the first INP)
|
|
13
|
+
export const firstInteraction = new VitalMetric(VITAL_NAMES.FIRST_INTERACTION)
|
|
11
14
|
|
|
12
15
|
if (isBrowserScope) {
|
|
13
|
-
|
|
16
|
+
const recordFirstInteraction = (attribution) => {
|
|
17
|
+
firstInteraction.update({
|
|
18
|
+
value: attribution.interactionTime,
|
|
19
|
+
attrs: {
|
|
20
|
+
type: attribution.interactionType,
|
|
21
|
+
eventTarget: attribution.interactionTarget,
|
|
22
|
+
loadState: attribution.loadState
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Interaction-to-Next-Paint */
|
|
14
28
|
onINP(({ value, attribution, id }) => {
|
|
15
29
|
const attrs = {
|
|
16
30
|
metricId: id,
|
|
@@ -26,5 +40,10 @@ if (isBrowserScope) {
|
|
|
26
40
|
loadState: attribution.loadState
|
|
27
41
|
}
|
|
28
42
|
interactionToNextPaint.update({ value, attrs })
|
|
43
|
+
|
|
44
|
+
// preserve the original behavior where FID is not reported if the page is hidden before the first interaction
|
|
45
|
+
if (!firstInteraction.isValid && !initiallyHidden) {
|
|
46
|
+
recordFirstInteraction(attribution)
|
|
47
|
+
}
|
|
29
48
|
})
|
|
30
49
|
}
|
|
@@ -35,7 +35,7 @@ export function castError (error) {
|
|
|
35
35
|
* @returns {Error} An Error object with the message as the casted reason
|
|
36
36
|
*/
|
|
37
37
|
export function castPromiseRejectionEvent (promiseRejectionEvent) {
|
|
38
|
-
const prefix = 'Unhandled Promise Rejection'
|
|
38
|
+
const prefix = 'Unhandled Promise Rejection: '
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* If the casted return value is falsy like this, it will get dropped and not produce an error event for harvest.
|
|
@@ -46,15 +46,15 @@ export function castPromiseRejectionEvent (promiseRejectionEvent) {
|
|
|
46
46
|
|
|
47
47
|
if (canTrustError(promiseRejectionEvent.reason)) {
|
|
48
48
|
try {
|
|
49
|
-
promiseRejectionEvent.reason.message = prefix +
|
|
50
|
-
return castError(promiseRejectionEvent.reason)
|
|
49
|
+
if (!promiseRejectionEvent.reason.message.startsWith(prefix)) promiseRejectionEvent.reason.message = prefix + promiseRejectionEvent.reason.message
|
|
51
50
|
} catch (e) {
|
|
52
|
-
|
|
51
|
+
// failed to modify the message, do nothing else
|
|
53
52
|
}
|
|
53
|
+
return castError(promiseRejectionEvent.reason)
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const error = castError(promiseRejectionEvent.reason)
|
|
57
|
-
error.message
|
|
57
|
+
if (!((error.message || '').startsWith(prefix))) error.message = prefix + error.message
|
|
58
58
|
return error
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -116,6 +116,9 @@ export class Aggregate extends AggregateBase {
|
|
|
116
116
|
mo.observe(window.document.body, { childList: true, subtree: true })
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
// webdriver detection
|
|
120
|
+
if (navigator.webdriver) this.storeSupportabilityMetrics('Generic/WebDriver/Detected')
|
|
121
|
+
|
|
119
122
|
// WATCHABLE_WEB_SOCKET_EVENTS.forEach(tag => {
|
|
120
123
|
// registerHandler('buffered-' + WEBSOCKET_TAG + tag, (...args) => {
|
|
121
124
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { isBrowserScope } from '../../../common/constants/runtime'
|
|
7
|
+
import { handle } from '../../../common/event-emitter/handle'
|
|
8
|
+
import { InstrumentBase } from '../../utils/instrument-base'
|
|
9
|
+
import {
|
|
10
|
+
FEATURE_NAME,
|
|
11
|
+
// WATCHABLE_WEB_SOCKET_EVENTS,
|
|
12
|
+
SUPPORTABILITY_METRIC_CHANNEL
|
|
13
|
+
} from '../constants'
|
|
6
14
|
// import { handle } from '../../../common/event-emitter/handle'
|
|
7
15
|
// import { WEBSOCKET_TAG, wrapWebSocket } from '../../../common/wrap/wrap-websocket'
|
|
8
|
-
import { InstrumentBase } from '../../utils/instrument-base'
|
|
9
|
-
import { FEATURE_NAME } from '../constants'
|
|
10
16
|
|
|
11
17
|
export class Instrument extends InstrumentBase {
|
|
12
18
|
static featureName = FEATURE_NAME
|
|
@@ -20,6 +26,12 @@ export class Instrument extends InstrumentBase {
|
|
|
20
26
|
// })
|
|
21
27
|
// })
|
|
22
28
|
|
|
29
|
+
if (isBrowserScope) {
|
|
30
|
+
document.addEventListener('securitypolicyviolation', (e) => {
|
|
31
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/CSPViolation/Detected'], undefined, this.featureName, this.ee)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
this.importAggregator(agentRef)
|
|
24
36
|
}
|
|
25
37
|
}
|
|
@@ -11,9 +11,8 @@ import { FEATURE_NAMES } from '../../../loaders/features/features'
|
|
|
11
11
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
12
12
|
import { cumulativeLayoutShift } from '../../../common/vitals/cumulative-layout-shift'
|
|
13
13
|
import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint'
|
|
14
|
-
import { firstInputDelay } from '../../../common/vitals/first-input-delay'
|
|
15
14
|
import { firstPaint } from '../../../common/vitals/first-paint'
|
|
16
|
-
import { interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint'
|
|
15
|
+
import { firstInteraction, interactionToNextPaint } from '../../../common/vitals/interaction-to-next-paint'
|
|
17
16
|
import { largestContentfulPaint } from '../../../common/vitals/largest-contentful-paint'
|
|
18
17
|
import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte'
|
|
19
18
|
import { subscribeToVisibilityChange } from '../../../common/window/page-visibility'
|
|
@@ -37,8 +36,8 @@ export class Aggregate extends AggregateBase {
|
|
|
37
36
|
this.waitForFlags(([])).then(() => {
|
|
38
37
|
firstPaint.subscribe(this.#handleVitalMetric)
|
|
39
38
|
firstContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
40
|
-
firstInputDelay.subscribe(this.#handleVitalMetric)
|
|
41
39
|
largestContentfulPaint.subscribe(this.#handleVitalMetric)
|
|
40
|
+
firstInteraction.subscribe(this.#handleVitalMetric)
|
|
42
41
|
interactionToNextPaint.subscribe(this.#handleVitalMetric)
|
|
43
42
|
timeToFirstByte.subscribe(({ attrs }) => {
|
|
44
43
|
this.addTiming('load', Math.round(attrs.navigationEntry.loadEventEnd))
|
|
@@ -24,7 +24,7 @@ class StylesheetEvaluator {
|
|
|
24
24
|
this.#brokenSheets = []
|
|
25
25
|
if (isBrowserScope) {
|
|
26
26
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
27
|
-
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
27
|
+
if (!this.#evaluated.has(document.styleSheets[i]) && document.styleSheets[i] instanceof CSSStyleSheet) {
|
|
28
28
|
this.#evaluated.add(document.styleSheets[i])
|
|
29
29
|
try {
|
|
30
30
|
// eslint-disable-next-line
|
|
@@ -136,11 +136,6 @@ export class TraceStorage {
|
|
|
136
136
|
|
|
137
137
|
processPVT (name, value, attrs) {
|
|
138
138
|
this.storeTiming({ [name]: value })
|
|
139
|
-
if (hasFID(name, attrs)) this.storeEvent({ type: 'fid', target: 'document' }, 'document', value, value + attrs.fid)
|
|
140
|
-
|
|
141
|
-
function hasFID (name, attrs) {
|
|
142
|
-
return name === 'fi' && !!attrs && typeof attrs.fid === 'number'
|
|
143
|
-
}
|
|
144
139
|
}
|
|
145
140
|
|
|
146
141
|
storeTiming (timingEntry, isAbsoluteTimestamp = false) {
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.firstInputDelay = void 0;
|
|
7
|
-
var _attribution = require("web-vitals/attribution");
|
|
8
|
-
var _vitalMetric = require("./vital-metric");
|
|
9
|
-
var _constants = require("./constants");
|
|
10
|
-
var _runtime = require("../constants/runtime");
|
|
11
|
-
/**
|
|
12
|
-
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
13
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const firstInputDelay = exports.firstInputDelay = new _vitalMetric.VitalMetric(_constants.VITAL_NAMES.FIRST_INPUT_DELAY);
|
|
17
|
-
if (_runtime.isBrowserScope) {
|
|
18
|
-
(0, _attribution.onFID)(({
|
|
19
|
-
value,
|
|
20
|
-
attribution
|
|
21
|
-
}) => {
|
|
22
|
-
if (_runtime.initiallyHidden || firstInputDelay.isValid) return;
|
|
23
|
-
const attrs = {
|
|
24
|
-
type: attribution.eventType,
|
|
25
|
-
fid: Math.round(value),
|
|
26
|
-
eventTarget: attribution.eventTarget,
|
|
27
|
-
loadState: attribution.loadState
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
// CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
|
|
31
|
-
firstInputDelay.update({
|
|
32
|
-
value: attribution.eventTime,
|
|
33
|
-
attrs
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { onFID } from 'web-vitals/attribution';
|
|
6
|
-
import { VitalMetric } from './vital-metric';
|
|
7
|
-
import { VITAL_NAMES } from './constants';
|
|
8
|
-
import { initiallyHidden, isBrowserScope } from '../constants/runtime';
|
|
9
|
-
export const firstInputDelay = new VitalMetric(VITAL_NAMES.FIRST_INPUT_DELAY);
|
|
10
|
-
if (isBrowserScope) {
|
|
11
|
-
onFID(({
|
|
12
|
-
value,
|
|
13
|
-
attribution
|
|
14
|
-
}) => {
|
|
15
|
-
if (initiallyHidden || firstInputDelay.isValid) return;
|
|
16
|
-
const attrs = {
|
|
17
|
-
type: attribution.eventType,
|
|
18
|
-
fid: Math.round(value),
|
|
19
|
-
eventTarget: attribution.eventTarget,
|
|
20
|
-
loadState: attribution.loadState
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
|
|
24
|
-
firstInputDelay.update({
|
|
25
|
-
value: attribution.eventTime,
|
|
26
|
-
attrs
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"first-input-delay.d.ts","sourceRoot":"","sources":["../../../../src/common/vitals/first-input-delay.js"],"names":[],"mappings":"AASA,0CAA6E;4BAJjD,gBAAgB"}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { onFID } from 'web-vitals/attribution'
|
|
6
|
-
import { VitalMetric } from './vital-metric'
|
|
7
|
-
import { VITAL_NAMES } from './constants'
|
|
8
|
-
import { initiallyHidden, isBrowserScope } from '../constants/runtime'
|
|
9
|
-
|
|
10
|
-
export const firstInputDelay = new VitalMetric(VITAL_NAMES.FIRST_INPUT_DELAY)
|
|
11
|
-
|
|
12
|
-
if (isBrowserScope) {
|
|
13
|
-
onFID(({ value, attribution }) => {
|
|
14
|
-
if (initiallyHidden || firstInputDelay.isValid) return
|
|
15
|
-
const attrs = {
|
|
16
|
-
type: attribution.eventType,
|
|
17
|
-
fid: Math.round(value),
|
|
18
|
-
eventTarget: attribution.eventTarget,
|
|
19
|
-
loadState: attribution.loadState
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
|
|
23
|
-
firstInputDelay.update({
|
|
24
|
-
value: attribution.eventTime,
|
|
25
|
-
attrs
|
|
26
|
-
})
|
|
27
|
-
})
|
|
28
|
-
}
|