@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.
Files changed (74) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/common/constants/env.cdn.js +1 -1
  3. package/dist/cjs/common/constants/env.npm.js +1 -1
  4. package/dist/cjs/common/harvest/harvester.js +29 -2
  5. package/dist/cjs/common/util/event-origin.js +36 -0
  6. package/dist/cjs/common/util/feature-flags.js +6 -1
  7. package/dist/cjs/common/vitals/interaction-to-next-paint.js +1 -20
  8. package/dist/cjs/features/ajax/instrument/index.js +3 -2
  9. package/dist/cjs/features/logging/aggregate/index.js +1 -1
  10. package/dist/cjs/features/page_view_timing/aggregate/index.js +31 -3
  11. package/dist/cjs/features/session_replay/shared/recorder.js +3 -10
  12. package/dist/cjs/features/session_replay/shared/utils.js +12 -0
  13. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +4 -21
  14. package/dist/cjs/features/utils/aggregate-base.js +2 -2
  15. package/dist/cjs/features/utils/event-store-manager.js +15 -1
  16. package/dist/cjs/loaders/api/api.js +13 -0
  17. package/dist/cjs/loaders/configure/configure.js +16 -0
  18. package/dist/cjs/loaders/features/features.js +4 -3
  19. package/dist/esm/common/constants/env.cdn.js +1 -1
  20. package/dist/esm/common/constants/env.npm.js +1 -1
  21. package/dist/esm/common/harvest/harvester.js +30 -3
  22. package/dist/esm/common/util/event-origin.js +30 -0
  23. package/dist/esm/common/util/feature-flags.js +6 -1
  24. package/dist/esm/common/vitals/interaction-to-next-paint.js +1 -20
  25. package/dist/esm/features/ajax/instrument/index.js +3 -2
  26. package/dist/esm/features/logging/aggregate/index.js +1 -1
  27. package/dist/esm/features/page_view_timing/aggregate/index.js +32 -4
  28. package/dist/esm/features/session_replay/shared/recorder.js +2 -9
  29. package/dist/esm/features/session_replay/shared/utils.js +11 -0
  30. package/dist/esm/features/session_trace/aggregate/trace/storage.js +4 -21
  31. package/dist/esm/features/utils/aggregate-base.js +2 -2
  32. package/dist/esm/features/utils/event-store-manager.js +15 -1
  33. package/dist/esm/loaders/api/api.js +13 -0
  34. package/dist/esm/loaders/configure/configure.js +16 -0
  35. package/dist/esm/loaders/features/features.js +3 -2
  36. package/dist/tsconfig.tsbuildinfo +1 -1
  37. package/dist/types/common/harvest/harvester.d.ts.map +1 -1
  38. package/dist/types/common/util/event-origin.d.ts +13 -0
  39. package/dist/types/common/util/event-origin.d.ts.map +1 -0
  40. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  41. package/dist/types/common/vitals/interaction-to-next-paint.d.ts +0 -1
  42. package/dist/types/common/vitals/interaction-to-next-paint.d.ts.map +1 -1
  43. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  44. package/dist/types/features/logging/aggregate/index.d.ts +0 -1
  45. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  46. package/dist/types/features/page_view_timing/aggregate/index.d.ts +12 -1
  47. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  48. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  49. package/dist/types/features/session_replay/shared/utils.d.ts +1 -0
  50. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
  51. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +0 -1
  52. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  53. package/dist/types/features/utils/event-store-manager.d.ts +5 -1
  54. package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
  55. package/dist/types/loaders/api/api.d.ts.map +1 -1
  56. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  57. package/dist/types/loaders/features/features.d.ts +2 -0
  58. package/dist/types/loaders/features/features.d.ts.map +1 -1
  59. package/package.json +1 -1
  60. package/src/common/harvest/harvester.js +33 -3
  61. package/src/common/util/event-origin.js +36 -0
  62. package/src/common/util/feature-flags.js +8 -1
  63. package/src/common/vitals/interaction-to-next-paint.js +1 -20
  64. package/src/features/ajax/instrument/index.js +3 -2
  65. package/src/features/logging/aggregate/index.js +2 -2
  66. package/src/features/page_view_timing/aggregate/index.js +34 -4
  67. package/src/features/session_replay/shared/recorder.js +2 -9
  68. package/src/features/session_replay/shared/utils.js +12 -0
  69. package/src/features/session_trace/aggregate/trace/storage.js +4 -28
  70. package/src/features/utils/aggregate-base.js +2 -2
  71. package/src/features/utils/event-store-manager.js +15 -1
  72. package/src/loaders/api/api.js +10 -0
  73. package/src/loaders/configure/configure.js +13 -0
  74. 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.284.0";
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.284.0";
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
- loaded: true
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 = exports.firstInteraction = void 0;
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('X-NewRelic-App-Data');
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.mode !== _constants.LOGGING_MODE.OFF && data.loggingMode === _constants.LOGGING_MODE.OFF) this.abort(_constants3.ABORT_REASONS.CROSS_TAB);else this.mode = data.loggingMode;
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
- this.events.add({
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
- const customMasker = (text, element) => {
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 = this.evtOrigin(currentEvent.target, target);
180
+ evt.o = (0, _eventOrigin.eventOrigin)(currentEvent.target, target, this.parent.ee);
180
181
  } catch (e) {
181
- evt.o = this.evtOrigin(null, target);
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 = this.evtOrigin(event.target, target);
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]: 'browser/logs',
63
+ [FEATURE_NAMES.logging]: LOGS,
63
64
  [FEATURE_NAMES.genericEvents]: 'ins'
64
65
  };
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.284.0";
14
+ export const VERSION = "1.285.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.284.0";
14
+ export const VERSION = "1.285.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent