@newrelic/browser-agent 1.284.0 → 1.285.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 +22 -0
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +29 -2
- package/dist/cjs/common/util/event-origin.js +36 -0
- package/dist/cjs/common/util/feature-flags.js +6 -1
- package/dist/cjs/common/vitals/interaction-to-next-paint.js +1 -20
- package/dist/cjs/features/ajax/instrument/index.js +3 -2
- package/dist/cjs/features/logging/aggregate/index.js +1 -1
- package/dist/cjs/features/page_view_timing/aggregate/index.js +31 -3
- package/dist/cjs/features/session_replay/shared/recorder.js +3 -10
- package/dist/cjs/features/session_replay/shared/utils.js +12 -0
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +4 -21
- package/dist/cjs/features/utils/aggregate-base.js +2 -2
- package/dist/cjs/features/utils/event-store-manager.js +15 -1
- package/dist/cjs/loaders/api/api.js +13 -0
- package/dist/cjs/loaders/configure/configure.js +16 -0
- package/dist/cjs/loaders/features/features.js +4 -3
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvester.js +30 -3
- package/dist/esm/common/util/event-origin.js +30 -0
- package/dist/esm/common/util/feature-flags.js +6 -1
- package/dist/esm/common/vitals/interaction-to-next-paint.js +1 -20
- package/dist/esm/features/ajax/instrument/index.js +3 -2
- package/dist/esm/features/logging/aggregate/index.js +1 -1
- package/dist/esm/features/page_view_timing/aggregate/index.js +32 -4
- package/dist/esm/features/session_replay/shared/recorder.js +2 -9
- package/dist/esm/features/session_replay/shared/utils.js +11 -0
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +4 -21
- package/dist/esm/features/utils/aggregate-base.js +2 -2
- package/dist/esm/features/utils/event-store-manager.js +15 -1
- package/dist/esm/loaders/api/api.js +13 -0
- package/dist/esm/loaders/configure/configure.js +16 -0
- package/dist/esm/loaders/features/features.js +3 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/util/event-origin.d.ts +13 -0
- package/dist/types/common/util/event-origin.d.ts.map +1 -0
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/vitals/interaction-to-next-paint.d.ts +0 -1
- package/dist/types/common/vitals/interaction-to-next-paint.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +0 -1
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +12 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts +1 -0
- package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +0 -1
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
- package/dist/types/features/utils/event-store-manager.d.ts +5 -1
- package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +2 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/harvest/harvester.js +33 -3
- package/src/common/util/event-origin.js +36 -0
- package/src/common/util/feature-flags.js +8 -1
- package/src/common/vitals/interaction-to-next-paint.js +1 -20
- package/src/features/ajax/instrument/index.js +3 -2
- package/src/features/logging/aggregate/index.js +2 -2
- package/src/features/page_view_timing/aggregate/index.js +34 -4
- package/src/features/session_replay/shared/recorder.js +2 -9
- package/src/features/session_replay/shared/utils.js +12 -0
- package/src/features/session_trace/aggregate/trace/storage.js +4 -28
- package/src/features/utils/aggregate-base.js +2 -2
- package/src/features/utils/event-store-manager.js +15 -1
- package/src/loaders/api/api.js +10 -0
- package/src/loaders/configure/configure.js +13 -0
- package/src/loaders/features/features.js +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
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.285.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.284.1...v1.285.0) (2025-03-18)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Decorate harvest requests with ht (hasTrace) param ([#1409](https://github.com/newrelic/newrelic-browser-agent/issues/1409)) ([b8ed2b0](https://github.com/newrelic/newrelic-browser-agent/commit/b8ed2b0aeef8b8db651ddb8001171f28785c7673))
|
|
12
|
+
* Inspection events ([#1413](https://github.com/newrelic/newrelic-browser-agent/issues/1413)) ([1832562](https://github.com/newrelic/newrelic-browser-agent/commit/1832562f52c1e2e26c49c2855ad1996d6251b803))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* Logging mode on session update ([#1417](https://github.com/newrelic/newrelic-browser-agent/issues/1417)) ([3f59afe](https://github.com/newrelic/newrelic-browser-agent/commit/3f59afef8a53848d80f7f32d28302b6b0bcf7d2f))
|
|
18
|
+
* Session Replay text masking for whitespace ([#1416](https://github.com/newrelic/newrelic-browser-agent/issues/1416)) ([97bf326](https://github.com/newrelic/newrelic-browser-agent/commit/97bf32655d6e608ea7248acc680d983b1d1e0eea))
|
|
19
|
+
|
|
20
|
+
## [1.284.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.284.0...v1.284.1) (2025-03-11)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
* Console error on some cross-origin requests without NR CAT header ([#1407](https://github.com/newrelic/newrelic-browser-agent/issues/1407)) ([6660c44](https://github.com/newrelic/newrelic-browser-agent/commit/6660c4455f73bdd90da9946f48ca6c6b377a866f))
|
|
26
|
+
* Obtain FirstInteraction directly from performance API ([#1410](https://github.com/newrelic/newrelic-browser-agent/issues/1410)) ([22ef4ff](https://github.com/newrelic/newrelic-browser-agent/commit/22ef4ffaef72729f99ee615d4851870f51a129f7))
|
|
27
|
+
|
|
6
28
|
## [1.284.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.283.2...v1.284.0) (2025-03-04)
|
|
7
29
|
|
|
8
30
|
|
|
@@ -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.285.0";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -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.285.0";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -18,6 +18,8 @@ var _encode = require("../url/encode");
|
|
|
18
18
|
var _console = require("../util/console");
|
|
19
19
|
var _stringify = require("../util/stringify");
|
|
20
20
|
var _submitData = require("../util/submit-data");
|
|
21
|
+
var _featureFlags = require("../util/feature-flags");
|
|
22
|
+
var _globalEvent = require("../dispatch/global-event");
|
|
21
23
|
/**
|
|
22
24
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
23
25
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -88,7 +90,8 @@ class Harvester {
|
|
|
88
90
|
localOpts,
|
|
89
91
|
submitMethod,
|
|
90
92
|
cbFinished,
|
|
91
|
-
raw: aggregateInst.harvestOpts.raw
|
|
93
|
+
raw: aggregateInst.harvestOpts.raw,
|
|
94
|
+
featureName: aggregateInst.featureName
|
|
92
95
|
});
|
|
93
96
|
ranSend = true;
|
|
94
97
|
});
|
|
@@ -130,7 +133,8 @@ function send(agentRef, {
|
|
|
130
133
|
localOpts = {},
|
|
131
134
|
submitMethod,
|
|
132
135
|
cbFinished,
|
|
133
|
-
raw
|
|
136
|
+
raw,
|
|
137
|
+
featureName
|
|
134
138
|
}) {
|
|
135
139
|
if (!agentRef.info.errorBeacon) return false;
|
|
136
140
|
let {
|
|
@@ -211,6 +215,22 @@ function send(agentRef, {
|
|
|
211
215
|
});
|
|
212
216
|
}
|
|
213
217
|
}
|
|
218
|
+
(0, _globalEvent.dispatchGlobalEvent)({
|
|
219
|
+
agentIdentifier: agentRef.agentIdentifier,
|
|
220
|
+
loaded: !!_featureFlags.activatedFeatures?.[agentRef.agentIdentifier],
|
|
221
|
+
type: 'data',
|
|
222
|
+
name: 'harvest',
|
|
223
|
+
feature: featureName,
|
|
224
|
+
data: {
|
|
225
|
+
endpoint,
|
|
226
|
+
headers,
|
|
227
|
+
targetApp,
|
|
228
|
+
payload,
|
|
229
|
+
submitMethod: getSubmitMethodName(),
|
|
230
|
+
raw,
|
|
231
|
+
synchronousXhr: !!(localOpts.isFinalHarvest && _runtime.isWorkerScope)
|
|
232
|
+
}
|
|
233
|
+
});
|
|
214
234
|
return true;
|
|
215
235
|
function shouldRetry(status) {
|
|
216
236
|
switch (status) {
|
|
@@ -221,6 +241,11 @@ function send(agentRef, {
|
|
|
221
241
|
}
|
|
222
242
|
return status >= 502 && status <= 504 || status >= 512 && status <= 530;
|
|
223
243
|
}
|
|
244
|
+
function getSubmitMethodName() {
|
|
245
|
+
if (submitMethod === _submitData.xhr) return 'xhr';
|
|
246
|
+
if (submitMethod === _submitData.xhrFetch) return 'fetch';
|
|
247
|
+
return 'beacon';
|
|
248
|
+
}
|
|
224
249
|
}
|
|
225
250
|
|
|
226
251
|
/**
|
|
@@ -252,12 +277,14 @@ function cleanPayload(payload = {}) {
|
|
|
252
277
|
function baseQueryString(agentRef, qs, endpoint, applicationID) {
|
|
253
278
|
const ref = agentRef.runtime.obfuscator.obfuscateString((0, _cleanUrl.cleanURL)('' + _runtime.globalScope.location));
|
|
254
279
|
const hr = agentRef.runtime.session?.state.sessionReplayMode === 1 && endpoint !== _features.JSERRORS;
|
|
280
|
+
const ht = agentRef.runtime.session?.state.sessionTraceMode === 1 && ![_features.LOGS, _features.BLOBS].includes(endpoint);
|
|
255
281
|
const qps = ['a=' + applicationID, (0, _encode.param)('sa', agentRef.info.sa ? '' + agentRef.info.sa : ''), (0, _encode.param)('v', _env.VERSION), transactionNameParam(), (0, _encode.param)('ct', agentRef.runtime.customTransaction), '&rst=' + (0, _now.now)(), '&ck=0',
|
|
256
282
|
// ck param DEPRECATED - still expected by backend
|
|
257
283
|
'&s=' + (agentRef.runtime.session?.state.value || '0'),
|
|
258
284
|
// the 0 id encaps all untrackable and default traffic
|
|
259
285
|
(0, _encode.param)('ref', ref), (0, _encode.param)('ptid', agentRef.runtime.ptid ? '' + agentRef.runtime.ptid : '')];
|
|
260
286
|
if (hr) qps.push((0, _encode.param)('hr', '1', qs));
|
|
287
|
+
if (ht) qps.push((0, _encode.param)('ht', '1', qs));
|
|
261
288
|
return qps.join('');
|
|
262
289
|
|
|
263
290
|
// Constructs the transaction name param for the beacon URL.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.eventOrigin = eventOrigin;
|
|
7
|
+
/**
|
|
8
|
+
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
9
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns a string representing the origin of an event target. Used by SessionTrace and PageViewTiming features to assign a "better" target to events
|
|
14
|
+
* @param {*} t The target to derive the origin from.
|
|
15
|
+
* @param {*} [target] A known target to compare to. If supplied, and a derived origin could not be reached, this will be referenced.
|
|
16
|
+
* @param {*} [ee] An event emitter instance to use for context retrieval, which only applies to XMLHttpRequests.
|
|
17
|
+
* @returns {string} The derived origin of the event target.
|
|
18
|
+
*/
|
|
19
|
+
function eventOrigin(t, target, ee) {
|
|
20
|
+
let origin = 'unknown';
|
|
21
|
+
if (t && t instanceof XMLHttpRequest) {
|
|
22
|
+
const params = ee.context(t).params;
|
|
23
|
+
if (!params || !params.status || !params.method || !params.host || !params.pathname) return 'xhrOriginMissing';
|
|
24
|
+
origin = params.status + ' ' + params.method + ': ' + params.host + params.pathname;
|
|
25
|
+
} else if (t && typeof t.tagName === 'string') {
|
|
26
|
+
origin = t.tagName.toLowerCase();
|
|
27
|
+
if (t.id) origin += '#' + t.id;
|
|
28
|
+
if (t.className) {
|
|
29
|
+
for (let i = 0; i < t.classList.length; i++) origin += '.' + t.classList[i];
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (origin === 'unknown') {
|
|
33
|
+
if (typeof target === 'string') origin = target;else if (target === document) origin = 'document';else if (target === window) origin = 'window';else if (target instanceof FileReader) origin = 'FileReader';
|
|
34
|
+
}
|
|
35
|
+
return origin;
|
|
36
|
+
}
|
|
@@ -35,6 +35,11 @@ function activateFeatures(flags, agentIdentifier) {
|
|
|
35
35
|
|
|
36
36
|
// let any window level subscribers know that the agent is running
|
|
37
37
|
(0, _globalEvent.dispatchGlobalEvent)({
|
|
38
|
-
|
|
38
|
+
agentIdentifier,
|
|
39
|
+
loaded: true,
|
|
40
|
+
type: 'lifecycle',
|
|
41
|
+
name: 'load',
|
|
42
|
+
feature: undefined,
|
|
43
|
+
data: flags
|
|
39
44
|
});
|
|
40
45
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.interactionToNextPaint =
|
|
6
|
+
exports.interactionToNextPaint = void 0;
|
|
7
7
|
var _attribution = require("web-vitals/attribution");
|
|
8
8
|
var _vitalMetric = require("./vital-metric");
|
|
9
9
|
var _constants = require("./constants");
|
|
@@ -14,21 +14,7 @@ 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);
|
|
20
17
|
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
|
-
|
|
32
18
|
/* Interaction-to-Next-Paint */
|
|
33
19
|
(0, _attribution.onINP)(({
|
|
34
20
|
value,
|
|
@@ -54,10 +40,5 @@ if (_runtime.isBrowserScope) {
|
|
|
54
40
|
value,
|
|
55
41
|
attrs
|
|
56
42
|
});
|
|
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
|
-
}
|
|
62
43
|
});
|
|
63
44
|
}
|
|
@@ -30,6 +30,7 @@ var handlers = ['load', 'error', 'abort', 'timeout'];
|
|
|
30
30
|
var handlersLen = handlers.length;
|
|
31
31
|
var origRequest = (0, _nreum.gosNREUMOriginals)().o.REQ;
|
|
32
32
|
var origXHR = (0, _nreum.gosNREUMOriginals)().o.XHR;
|
|
33
|
+
const NR_CAT_HEADER = 'X-NewRelic-App-Data';
|
|
33
34
|
class Instrument extends _instrumentBase.InstrumentBase {
|
|
34
35
|
static featureName = _constants.FEATURE_NAME;
|
|
35
36
|
constructor(agentRef, auto = true) {
|
|
@@ -360,8 +361,8 @@ function subscribeToEvents(agentRef, ee, handler, dt) {
|
|
|
360
361
|
ctx.params.status = xhr.status;
|
|
361
362
|
var size = (0, _responseSize.responseSizeFromXhr)(xhr, ctx.lastSize);
|
|
362
363
|
if (size) ctx.metrics.rxSize = size;
|
|
363
|
-
if (ctx.sameOrigin) {
|
|
364
|
-
var header = xhr.getResponseHeader(
|
|
364
|
+
if (ctx.sameOrigin && xhr.getAllResponseHeaders().indexOf(NR_CAT_HEADER) >= 0) {
|
|
365
|
+
var header = xhr.getResponseHeader(NR_CAT_HEADER);
|
|
365
366
|
if (header) {
|
|
366
367
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC, ['Ajax/CrossApplicationTracing/Header/Seen'], undefined, _features.FEATURE_NAMES.metrics, ee);
|
|
367
368
|
ctx.params.cat = header.split(', ').pop();
|
|
@@ -33,7 +33,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
33
33
|
});
|
|
34
34
|
this.ee.on(_constants2.SESSION_EVENTS.UPDATE, (type, data) => {
|
|
35
35
|
if (this.blocked || type !== _constants2.SESSION_EVENT_TYPES.CROSS_TAB) return;
|
|
36
|
-
if (this.
|
|
36
|
+
if (this.loggingMode !== _constants.LOGGING_MODE.OFF && data.loggingMode === _constants.LOGGING_MODE.OFF) this.abort(_constants3.ABORT_REASONS.CROSS_TAB);else this.loggingMode = data.loggingMode;
|
|
37
37
|
});
|
|
38
38
|
this.harvestOpts.raw = true;
|
|
39
39
|
this.waitForFlags(['log']).then(([loggingMode]) => {
|
|
@@ -18,6 +18,8 @@ var _largestContentfulPaint = require("../../../common/vitals/largest-contentful
|
|
|
18
18
|
var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
|
|
19
19
|
var _pageVisibility = require("../../../common/window/page-visibility");
|
|
20
20
|
var _constants2 = require("../../../common/vitals/constants");
|
|
21
|
+
var _runtime = require("../../../common/constants/runtime");
|
|
22
|
+
var _eventOrigin = require("../../../common/util/event-origin");
|
|
21
23
|
/**
|
|
22
24
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
23
25
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -35,6 +37,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
35
37
|
constructor(agentRef) {
|
|
36
38
|
super(agentRef, _constants.FEATURE_NAME);
|
|
37
39
|
this.curSessEndRecorded = false;
|
|
40
|
+
this.firstIxnRecorded = false;
|
|
38
41
|
(0, _registerHandler.registerHandler)('docHidden', msTimestamp => this.endCurrentSession(msTimestamp), this.featureName, this.ee);
|
|
39
42
|
// Add the time of _window pagehide event_ firing to the next PVT harvest == NRDB windowUnload attr:
|
|
40
43
|
(0, _registerHandler.registerHandler)('winPagehide', msTimestamp => this.addTiming('unload', msTimestamp, null), this.featureName, this.ee);
|
|
@@ -42,7 +45,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
42
45
|
_firstPaint.firstPaint.subscribe(this.#handleVitalMetric);
|
|
43
46
|
_firstContentfulPaint.firstContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
44
47
|
_largestContentfulPaint.largestContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
45
|
-
_interactionToNextPaint.firstInteraction.subscribe(this.#handleVitalMetric);
|
|
46
48
|
_interactionToNextPaint.interactionToNextPaint.subscribe(this.#handleVitalMetric);
|
|
47
49
|
_timeToFirstByte.timeToFirstByte.subscribe(({
|
|
48
50
|
attrs
|
|
@@ -92,12 +94,34 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
92
94
|
if (name !== _constants2.VITAL_NAMES.CUMULATIVE_LAYOUT_SHIFT && _cumulativeLayoutShift.cumulativeLayoutShift.current.value >= 0) {
|
|
93
95
|
attrs.cls = _cumulativeLayoutShift.cumulativeLayoutShift.current.value;
|
|
94
96
|
}
|
|
95
|
-
|
|
97
|
+
const timing = {
|
|
96
98
|
name,
|
|
97
99
|
value,
|
|
98
100
|
attrs
|
|
99
|
-
}
|
|
101
|
+
};
|
|
102
|
+
this.events.add(timing);
|
|
100
103
|
(0, _handle.handle)('pvtAdded', [name, value, attrs], undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
|
|
104
|
+
this.checkForFirstInteraction();
|
|
105
|
+
|
|
106
|
+
// makes testing easier
|
|
107
|
+
return timing;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks the performance API to see if the agent can set a first interaction event value
|
|
112
|
+
* @returns {void}
|
|
113
|
+
*/
|
|
114
|
+
checkForFirstInteraction() {
|
|
115
|
+
// preserve the original behavior where FID is not reported if the page is hidden before the first interaction
|
|
116
|
+
if (this.firstIxnRecorded || _runtime.initiallyHidden || !performance) return;
|
|
117
|
+
const firstInput = performance.getEntriesByType('first-input')[0];
|
|
118
|
+
if (!firstInput) return;
|
|
119
|
+
this.firstIxnRecorded = true;
|
|
120
|
+
this.addTiming('fi', firstInput.startTime, {
|
|
121
|
+
type: firstInput.name,
|
|
122
|
+
eventTarget: (0, _eventOrigin.eventOrigin)(firstInput.target),
|
|
123
|
+
loadState: document.readyState
|
|
124
|
+
});
|
|
101
125
|
}
|
|
102
126
|
appendGlobalCustomAttributes(timing) {
|
|
103
127
|
var timingAttributes = timing.attrs || {};
|
|
@@ -108,6 +132,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
108
132
|
}
|
|
109
133
|
});
|
|
110
134
|
}
|
|
135
|
+
preHarvestChecks() {
|
|
136
|
+
this.checkForFirstInteraction();
|
|
137
|
+
return super.preHarvestChecks();
|
|
138
|
+
}
|
|
111
139
|
|
|
112
140
|
// serialize array of timing data
|
|
113
141
|
serializer(eventBuffer) {
|
|
@@ -90,14 +90,7 @@ class Recorder {
|
|
|
90
90
|
inline_images,
|
|
91
91
|
collect_fonts
|
|
92
92
|
} = this.parent.agentRef.init.session_replay;
|
|
93
|
-
|
|
94
|
-
try {
|
|
95
|
-
if (typeof element?.type === 'string' && element.type.toLowerCase() !== 'password' && (element?.dataset?.nrUnmask !== undefined || element?.classList?.contains('nr-unmask'))) return text;
|
|
96
|
-
} catch (err) {
|
|
97
|
-
// likely an element was passed to this handler that was invalid and was missing attributes or methods
|
|
98
|
-
}
|
|
99
|
-
return '*'.repeat(text?.length || 0);
|
|
100
|
-
};
|
|
93
|
+
|
|
101
94
|
// set up rrweb configurations for maximum privacy --
|
|
102
95
|
// https://newrelic.atlassian.net/wiki/spaces/O11Y/pages/2792293280/2023+02+28+Browser+-+Session+Replay#Configuration-options
|
|
103
96
|
const stop = (0, _rrweb.record)({
|
|
@@ -108,9 +101,9 @@ class Recorder {
|
|
|
108
101
|
blockSelector: block_selector,
|
|
109
102
|
maskInputOptions: mask_input_options,
|
|
110
103
|
maskTextSelector: mask_text_selector,
|
|
111
|
-
maskTextFn: customMasker,
|
|
104
|
+
maskTextFn: _utils.customMasker,
|
|
112
105
|
maskAllInputs: mask_all_inputs,
|
|
113
|
-
maskInputFn: customMasker,
|
|
106
|
+
maskInputFn: _utils.customMasker,
|
|
114
107
|
inlineStylesheet: true,
|
|
115
108
|
inlineImages: inline_images,
|
|
116
109
|
collectFonts: collect_fonts,
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.buildNRMetaNode = buildNRMetaNode;
|
|
7
|
+
exports.customMasker = customMasker;
|
|
7
8
|
exports.hasReplayPrerequisite = hasReplayPrerequisite;
|
|
8
9
|
exports.isPreloadAllowed = isPreloadAllowed;
|
|
9
10
|
var _nreum = require("../../../common/window/nreum");
|
|
@@ -35,4 +36,15 @@ function buildNRMetaNode(timestamp, timeKeeper) {
|
|
|
35
36
|
correctedOriginTime: timeKeeper.correctedOriginTime,
|
|
36
37
|
originTimeDiff: Math.floor(_runtime.originTime - timeKeeper.correctedOriginTime)
|
|
37
38
|
};
|
|
39
|
+
}
|
|
40
|
+
function customMasker(text, element) {
|
|
41
|
+
try {
|
|
42
|
+
if (typeof element?.type === 'string') {
|
|
43
|
+
if (element.type.toLowerCase() === 'password') return '*'.repeat(text?.length || 0);
|
|
44
|
+
if (element?.dataset?.nrUnmask !== undefined || element?.classList?.contains('nr-unmask')) return text;
|
|
45
|
+
}
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// likely an element was passed to this handler that was invalid and was missing attributes or methods
|
|
48
|
+
}
|
|
49
|
+
return typeof text === 'string' ? text.replace(/[\S]/g, '*') : '*'.repeat(text?.length || 0);
|
|
38
50
|
}
|
|
@@ -8,6 +8,7 @@ var _runtime = require("../../../../common/constants/runtime");
|
|
|
8
8
|
var _constants = require("../../../../common/session/constants");
|
|
9
9
|
var _now = require("../../../../common/timing/now");
|
|
10
10
|
var _parseUrl = require("../../../../common/url/parse-url");
|
|
11
|
+
var _eventOrigin = require("../../../../common/util/event-origin");
|
|
11
12
|
var _constants2 = require("../../constants");
|
|
12
13
|
var _node = require("./node");
|
|
13
14
|
/**
|
|
@@ -176,14 +177,14 @@ class TraceStorage {
|
|
|
176
177
|
try {
|
|
177
178
|
// webcomponents-lite.js can trigger an exception on currentEvent.target getter because
|
|
178
179
|
// it does not check currentEvent.currentTarget before calling getRootNode() on it
|
|
179
|
-
evt.o =
|
|
180
|
+
evt.o = (0, _eventOrigin.eventOrigin)(currentEvent.target, target, this.parent.ee);
|
|
180
181
|
} catch (e) {
|
|
181
|
-
evt.o =
|
|
182
|
+
evt.o = (0, _eventOrigin.eventOrigin)(null, target, this.parent.ee);
|
|
182
183
|
}
|
|
183
184
|
this.storeSTN(evt);
|
|
184
185
|
}
|
|
185
186
|
shouldIgnoreEvent(event, target) {
|
|
186
|
-
const origin =
|
|
187
|
+
const origin = (0, _eventOrigin.eventOrigin)(event.target, target, this.parent.ee);
|
|
187
188
|
if (event.type in ignoredEvents.global) return true;
|
|
188
189
|
if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true;
|
|
189
190
|
return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin]);
|
|
@@ -213,24 +214,6 @@ class TraceStorage {
|
|
|
213
214
|
return type;
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
|
-
evtOrigin(t, target) {
|
|
217
|
-
let origin = 'unknown';
|
|
218
|
-
if (t && t instanceof XMLHttpRequest) {
|
|
219
|
-
const params = this.parent.ee.context(t).params;
|
|
220
|
-
if (!params || !params.status || !params.method || !params.host || !params.pathname) return 'xhrOriginMissing';
|
|
221
|
-
origin = params.status + ' ' + params.method + ': ' + params.host + params.pathname;
|
|
222
|
-
} else if (t && typeof t.tagName === 'string') {
|
|
223
|
-
origin = t.tagName.toLowerCase();
|
|
224
|
-
if (t.id) origin += '#' + t.id;
|
|
225
|
-
if (t.className) {
|
|
226
|
-
for (let i = 0; i < t.classList.length; i++) origin += '.' + t.classList[i];
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
if (origin === 'unknown') {
|
|
230
|
-
if (typeof target === 'string') origin = target;else if (target === document) origin = 'document';else if (target === window) origin = 'window';else if (target instanceof FileReader) origin = 'FileReader';
|
|
231
|
-
}
|
|
232
|
-
return origin;
|
|
233
|
-
}
|
|
234
217
|
|
|
235
218
|
// Tracks when the window history API specified by wrap-history is used.
|
|
236
219
|
storeHist(path, old, time) {
|
|
@@ -43,7 +43,7 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
43
43
|
This was necessary to prevent race cond. issues where the event buffer was checked before the feature could "block" itself.
|
|
44
44
|
Its easier to just keep an empty event buffer in place. */
|
|
45
45
|
default:
|
|
46
|
-
this.events = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 1);
|
|
46
|
+
this.events = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 1, agentRef.agentIdentifier, this.featureName);
|
|
47
47
|
break;
|
|
48
48
|
}
|
|
49
49
|
this.harvestOpts = {}; // features aggregate classes can define custom opts for when their harvest is called
|
|
@@ -170,7 +170,7 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
170
170
|
appId: agentRef.info.applicationID
|
|
171
171
|
};
|
|
172
172
|
// Create a single Aggregator for this agent if DNE yet; to be used by jserror endpoint features.
|
|
173
|
-
if (!agentRef.sharedAggregator) agentRef.sharedAggregator = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 2);
|
|
173
|
+
if (!agentRef.sharedAggregator) agentRef.sharedAggregator = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 2, agentRef.agentIdentifier, 'shared_aggregator');
|
|
174
174
|
if (!agentRef.runtime.harvester) agentRef.runtime.harvester = new _harvester.Harvester(agentRef);
|
|
175
175
|
}
|
|
176
176
|
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.EventStoreManager = void 0;
|
|
7
7
|
var _eventAggregator = require("../../common/aggregate/event-aggregator");
|
|
8
|
+
var _globalEvent = require("../../common/dispatch/global-event");
|
|
9
|
+
var _featureFlags = require("../../common/util/feature-flags");
|
|
8
10
|
var _eventBuffer = require("./event-buffer");
|
|
9
11
|
/**
|
|
10
12
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
@@ -19,12 +21,16 @@ class EventStoreManager {
|
|
|
19
21
|
/**
|
|
20
22
|
* @param {object} defaultTarget - should contain licenseKey and appId of the main app from NREUM.info at startup
|
|
21
23
|
* @param {1|2} storageChoice - the type of storage to use in this manager; 'EventBuffer' (1), 'EventAggregator' (2)
|
|
24
|
+
* @param {string} agentIdentifier - agent identifier used in inspection events
|
|
25
|
+
* @param {string} featureName - feature name used in inspection events for non-shared aggregators
|
|
22
26
|
*/
|
|
23
|
-
constructor(defaultTarget, storageChoice) {
|
|
27
|
+
constructor(defaultTarget, storageChoice, agentIdentifier, featureName) {
|
|
24
28
|
this.mainApp = defaultTarget;
|
|
25
29
|
this.StorageClass = storageChoice === 1 ? _eventBuffer.EventBuffer : _eventAggregator.EventAggregator;
|
|
26
30
|
this.appStorageMap = new Map();
|
|
27
31
|
this.appStorageMap.set(defaultTarget, new this.StorageClass());
|
|
32
|
+
this.agentIdentifier = agentIdentifier;
|
|
33
|
+
this.featureName = featureName;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
// This class must contain an union of all methods from all supported storage classes and conceptualize away the target app argument.
|
|
@@ -50,6 +56,14 @@ class EventStoreManager {
|
|
|
50
56
|
* @returns {boolean} True if the event was successfully added
|
|
51
57
|
*/
|
|
52
58
|
add(event, target) {
|
|
59
|
+
(0, _globalEvent.dispatchGlobalEvent)({
|
|
60
|
+
agentIdentifier: this.agentIdentifier,
|
|
61
|
+
loaded: !!_featureFlags.activatedFeatures?.[this.agentIdentifier],
|
|
62
|
+
type: 'data',
|
|
63
|
+
name: 'buffer',
|
|
64
|
+
feature: this.featureName,
|
|
65
|
+
data: event
|
|
66
|
+
});
|
|
53
67
|
if (target && !this.appStorageMap.has(target)) this.appStorageMap.set(target, new this.StorageClass());
|
|
54
68
|
return this.appStorageMap.get(target || this.mainApp).add(event);
|
|
55
69
|
}
|
|
@@ -23,6 +23,8 @@ var _constants3 = require("../../common/session/constants");
|
|
|
23
23
|
var _constants4 = require("../../features/logging/constants");
|
|
24
24
|
var _utils = require("../../features/logging/shared/utils");
|
|
25
25
|
var _wrapLogger = require("../../common/wrap/wrap-logger");
|
|
26
|
+
var _globalEvent = require("../../common/dispatch/global-event");
|
|
27
|
+
var _featureFlags = require("../../common/util/feature-flags");
|
|
26
28
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
27
29
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /**
|
|
28
30
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
@@ -199,6 +201,17 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
|
|
|
199
201
|
function apiCall(prefix, name, notSpa, bufferGroup) {
|
|
200
202
|
return function () {
|
|
201
203
|
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/' + name + '/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
|
|
204
|
+
(0, _globalEvent.dispatchGlobalEvent)({
|
|
205
|
+
agentIdentifier,
|
|
206
|
+
loaded: !!_featureFlags.activatedFeatures?.[agentIdentifier],
|
|
207
|
+
type: 'data',
|
|
208
|
+
name: 'api',
|
|
209
|
+
feature: prefix + name,
|
|
210
|
+
data: {
|
|
211
|
+
notSpa,
|
|
212
|
+
bufferGroup
|
|
213
|
+
}
|
|
214
|
+
});
|
|
202
215
|
if (bufferGroup) (0, _handle.handle)(prefix + name, [notSpa ? (0, _now.now)() : performance.now(), ...arguments], notSpa ? null : this, bufferGroup, instanceEE); // no bufferGroup means only the SM is emitted
|
|
203
216
|
return notSpa ? undefined : this; // returns the InteractionHandle which allows these methods to be chained
|
|
204
217
|
};
|
|
@@ -14,6 +14,7 @@ var _featureFlags = require("../../common/util/feature-flags");
|
|
|
14
14
|
var _runtime2 = require("../../common/constants/runtime");
|
|
15
15
|
var _publicPath = require("./public-path");
|
|
16
16
|
var _contextualEe = require("../../common/event-emitter/contextual-ee");
|
|
17
|
+
var _globalEvent = require("../../common/dispatch/global-event");
|
|
17
18
|
/**
|
|
18
19
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
19
20
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -70,5 +71,20 @@ function configure(agent, opts = {}, loaderType, forceDrain) {
|
|
|
70
71
|
agent.ee = _contextualEe.ee.get(agent.agentIdentifier);
|
|
71
72
|
if (agent.api === undefined) agent.api = (0, _api.setAPI)(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
|
|
72
73
|
if (agent.exposed === undefined) agent.exposed = exposed;
|
|
74
|
+
if (!alreadySetOnce) {
|
|
75
|
+
(0, _globalEvent.dispatchGlobalEvent)({
|
|
76
|
+
agentIdentifier: agent.agentIdentifier,
|
|
77
|
+
loaded: !!_featureFlags.activatedFeatures?.[agent.agentIdentifier],
|
|
78
|
+
type: 'lifecycle',
|
|
79
|
+
name: 'initialize',
|
|
80
|
+
feature: undefined,
|
|
81
|
+
data: {
|
|
82
|
+
init: updatedInit,
|
|
83
|
+
info,
|
|
84
|
+
loader_config,
|
|
85
|
+
runtime
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
73
89
|
alreadySetOnce = true;
|
|
74
90
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.featurePriority = exports.RUM = exports.JSERRORS = exports.FEATURE_TO_ENDPOINT = exports.FEATURE_NAMES = exports.EVENTS = void 0;
|
|
6
|
+
exports.featurePriority = exports.RUM = exports.LOGS = exports.JSERRORS = exports.FEATURE_TO_ENDPOINT = exports.FEATURE_NAMES = exports.EVENTS = exports.BLOBS = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
9
9
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -12,8 +12,9 @@ exports.featurePriority = exports.RUM = exports.JSERRORS = exports.FEATURE_TO_EN
|
|
|
12
12
|
// To reduce build size a bit:
|
|
13
13
|
const EVENTS = exports.EVENTS = 'events';
|
|
14
14
|
const JSERRORS = exports.JSERRORS = 'jserrors';
|
|
15
|
-
const BLOBS = 'browser/blobs';
|
|
15
|
+
const BLOBS = exports.BLOBS = 'browser/blobs';
|
|
16
16
|
const RUM = exports.RUM = 'rum';
|
|
17
|
+
const LOGS = exports.LOGS = 'browser/logs';
|
|
17
18
|
const FEATURE_NAMES = exports.FEATURE_NAMES = {
|
|
18
19
|
ajax: 'ajax',
|
|
19
20
|
genericEvents: 'generic_events',
|
|
@@ -59,6 +60,6 @@ const FEATURE_TO_ENDPOINT = exports.FEATURE_TO_ENDPOINT = {
|
|
|
59
60
|
[FEATURE_NAMES.jserrors]: JSERRORS,
|
|
60
61
|
[FEATURE_NAMES.sessionTrace]: BLOBS,
|
|
61
62
|
[FEATURE_NAMES.sessionReplay]: BLOBS,
|
|
62
|
-
[FEATURE_NAMES.logging]:
|
|
63
|
+
[FEATURE_NAMES.logging]: LOGS,
|
|
63
64
|
[FEATURE_NAMES.genericEvents]: 'ins'
|
|
64
65
|
};
|