@newrelic/browser-agent 1.249.0 → 1.250.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 +13 -0
  2. package/dist/cjs/common/config/state/init.js +1 -1
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/harvest/harvest-scheduler.js +2 -2
  6. package/dist/cjs/common/harvest/harvest.js +4 -3
  7. package/dist/cjs/common/ids/unique-id.js +1 -1
  8. package/dist/cjs/common/session/constants.js +20 -2
  9. package/dist/cjs/common/session/session-entity.js +8 -26
  10. package/dist/cjs/common/url/encode.js +2 -0
  11. package/dist/cjs/features/metrics/aggregate/index.js +3 -1
  12. package/dist/cjs/features/session_replay/aggregate/index.js +114 -277
  13. package/dist/cjs/features/session_replay/constants.js +57 -2
  14. package/dist/cjs/features/session_replay/instrument/index.js +38 -16
  15. package/dist/cjs/features/session_replay/shared/recorder-events.js +31 -0
  16. package/dist/cjs/features/session_replay/shared/recorder.js +155 -0
  17. package/dist/cjs/features/session_replay/{replay-mode.js → shared/replay-mode.js} +5 -5
  18. package/dist/cjs/features/session_trace/aggregate/index.js +25 -25
  19. package/dist/esm/common/config/state/init.js +1 -1
  20. package/dist/esm/common/constants/env.cdn.js +1 -1
  21. package/dist/esm/common/constants/env.npm.js +1 -1
  22. package/dist/esm/common/harvest/harvest-scheduler.js +1 -1
  23. package/dist/esm/common/harvest/harvest.js +4 -3
  24. package/dist/esm/common/ids/unique-id.js +1 -1
  25. package/dist/esm/common/session/constants.js +16 -1
  26. package/dist/esm/common/session/session-entity.js +2 -16
  27. package/dist/esm/common/url/encode.js +2 -0
  28. package/dist/esm/features/metrics/aggregate/index.js +3 -1
  29. package/dist/esm/features/session_replay/aggregate/index.js +95 -254
  30. package/dist/esm/features/session_replay/constants.js +49 -1
  31. package/dist/esm/features/session_replay/instrument/index.js +24 -1
  32. package/dist/esm/features/session_replay/shared/recorder-events.js +24 -0
  33. package/dist/esm/features/session_replay/shared/recorder.js +148 -0
  34. package/dist/esm/features/session_replay/{replay-mode.js → shared/replay-mode.js} +4 -4
  35. package/dist/esm/features/session_trace/aggregate/index.js +2 -2
  36. package/dist/types/common/harvest/harvest.d.ts +1 -1
  37. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  38. package/dist/types/common/session/constants.d.ts +15 -0
  39. package/dist/types/common/session/session-entity.d.ts +0 -15
  40. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  41. package/dist/types/common/url/encode.d.ts +1 -1
  42. package/dist/types/common/url/encode.d.ts.map +1 -1
  43. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  44. package/dist/types/features/session_replay/aggregate/index.d.ts +7 -63
  45. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  46. package/dist/types/features/session_replay/constants.d.ts +55 -0
  47. package/dist/types/features/session_replay/constants.d.ts.map +1 -1
  48. package/dist/types/features/session_replay/instrument/index.d.ts +2 -0
  49. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  50. package/dist/types/features/session_replay/shared/recorder-events.d.ts +21 -0
  51. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -0
  52. package/dist/types/features/session_replay/shared/recorder.d.ts +40 -0
  53. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -0
  54. package/dist/types/features/session_replay/shared/replay-mode.d.ts.map +1 -0
  55. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  56. package/package.json +1 -1
  57. package/src/common/config/state/init.js +1 -1
  58. package/src/common/harvest/harvest-scheduler.js +1 -1
  59. package/src/common/harvest/harvest.js +4 -3
  60. package/src/common/ids/unique-id.js +1 -1
  61. package/src/common/session/__mocks__/session-entity.js +0 -6
  62. package/src/common/session/constants.js +18 -0
  63. package/src/common/session/session-entity.js +1 -17
  64. package/src/common/url/encode.js +2 -1
  65. package/src/features/metrics/aggregate/index.js +3 -1
  66. package/src/features/session_replay/aggregate/index.js +88 -246
  67. package/src/features/session_replay/constants.js +45 -0
  68. package/src/features/session_replay/instrument/index.js +18 -1
  69. package/src/features/session_replay/shared/recorder-events.js +25 -0
  70. package/src/features/session_replay/shared/recorder.js +145 -0
  71. package/src/features/session_replay/{replay-mode.js → shared/replay-mode.js} +4 -4
  72. package/src/features/session_trace/aggregate/index.js +2 -2
  73. package/dist/types/features/session_replay/replay-mode.d.ts.map +0 -1
  74. /package/dist/types/features/session_replay/{replay-mode.d.ts → shared/replay-mode.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,19 @@
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.250.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.249.0...v1.250.0) (2024-01-09)
7
+
8
+
9
+ ### Features
10
+
11
+ * Add a flag to note that a payload occurred during a replay ([#834](https://github.com/newrelic/newrelic-browser-agent/issues/834)) ([1b898c6](https://github.com/newrelic/newrelic-browser-agent/commit/1b898c61fa260bd0df644b4825ddb6d1c9b54b51))
12
+ * Session Replay Dynamic Loading ([#832](https://github.com/newrelic/newrelic-browser-agent/issues/832)) ([1af7b89](https://github.com/newrelic/newrelic-browser-agent/commit/1af7b896ef41c8b4855ca85e2a4e40c20a8cdfb1))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * TraceId generation regression (non-random trace ids) ([#853](https://github.com/newrelic/newrelic-browser-agent/issues/853)) ([8767f69](https://github.com/newrelic/newrelic-browser-agent/commit/8767f69122853a4099ed25f5886a91de06703c98))
18
+
6
19
  ## [1.249.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.248.0...v1.249.0) (2023-12-14)
7
20
 
8
21
 
@@ -115,7 +115,7 @@ const model = () => {
115
115
  collect_fonts: false,
116
116
  // serialize fonts for collection without public asset url, this is currently broken in RRWeb -- https://github.com/rrweb-io/rrweb/issues/1304. When fixed, revisit with test cases
117
117
  inline_images: false,
118
- // serialize images for collection without public asset url
118
+ // serialize images for collection without public asset url -- right now this is only useful for testing as it easily generates payloads too large to be harvested
119
119
  inline_stylesheet: true,
120
120
  // serialize css for collection without public asset url
121
121
  // recording config settings
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = "1.249.0";
15
+ const VERSION = "1.250.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
12
12
  /**
13
13
  * Exposes the version of the agent
14
14
  */
15
- const VERSION = "1.249.0";
15
+ const VERSION = "1.250.0";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -8,7 +8,7 @@ var submitData = _interopRequireWildcard(require("../util/submit-data"));
8
8
  var _sharedContext = require("../context/shared-context");
9
9
  var _harvest = require("./harvest");
10
10
  var _eol = require("../unload/eol");
11
- var _sessionEntity = require("../session/session-entity");
11
+ var _constants = require("../session/constants");
12
12
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
13
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
14
  /*
@@ -47,7 +47,7 @@ class HarvestScheduler extends _sharedContext.SharedContext {
47
47
  /* Flush all buffered data if session resets and give up retries. This should be synchronous to ensure that the correct `session` value is sent.
48
48
  Since session-reset generates a new session ID and the ID is grabbed at send-time, any delays or retries would cause the payload to be sent under
49
49
  the wrong session ID. */
50
- this.sharedContext?.ee.on(_sessionEntity.SESSION_EVENTS.RESET, () => this.runHarvest({
50
+ this.sharedContext?.ee.on(_constants.SESSION_EVENTS.RESET, () => this.runHarvest({
51
51
  forceNoRetry: true
52
52
  }));
53
53
  }
@@ -137,7 +137,7 @@ class Harvest extends _sharedContext.SharedContext {
137
137
  let url = "".concat(protocol, "://").concat(perceviedBeacon).concat(endpointURLPart, "/1/").concat(info.licenseKey);
138
138
  if (customUrl) url = customUrl;
139
139
  if (raw) url = "".concat(protocol, "://").concat(perceviedBeacon, "/").concat(endpoint);
140
- const baseParams = !raw && includeBaseParams ? this.baseQueryString() : '';
140
+ const baseParams = !raw && includeBaseParams ? this.baseQueryString(qs) : '';
141
141
  let payloadParams = (0, _encode.obj)(qs, agentRuntime.maxBytes);
142
142
  if (!submitMethod) {
143
143
  submitMethod = submitData.getSubmitMethod({
@@ -202,7 +202,7 @@ class Harvest extends _sharedContext.SharedContext {
202
202
  }
203
203
 
204
204
  // The stuff that gets sent every time.
205
- baseQueryString() {
205
+ baseQueryString(qs) {
206
206
  const runtime = (0, _config.getRuntime)(this.sharedContext.agentIdentifier);
207
207
  const info = (0, _config.getInfo)(this.sharedContext.agentIdentifier);
208
208
  const location = (0, _cleanUrl.cleanURL)((0, _location.getLocation)());
@@ -211,7 +211,8 @@ class Harvest extends _sharedContext.SharedContext {
211
211
  // ck param DEPRECATED - still expected by backend
212
212
  '&s=' + (runtime.session?.state.value || '0'),
213
213
  // the 0 id encaps all untrackable and default traffic
214
- (0, _encode.param)('ref', ref), (0, _encode.param)('ptid', runtime.ptid ? '' + runtime.ptid : '')].join('');
214
+ (0, _encode.param)('ref', ref), (0, _encode.param)('ptid', runtime.ptid ? '' + runtime.ptid : ''), (0, _encode.param)('hr', runtime?.session?.state.sessionReplayMode === 1 ? '1' : '0', qs) // hasReplay
215
+ ].join('');
215
216
  }
216
217
 
217
218
  /**
@@ -83,7 +83,7 @@ function generateRandomHexString(length) {
83
83
  }
84
84
  const chars = [];
85
85
  for (var i = 0; i < length; i++) {
86
- chars.push(getRandomValue(randomValueTable, ++randomValueIndex).toString(16));
86
+ chars.push(getRandomValue(randomValueTable, randomValueIndex++).toString(16));
87
87
  }
88
88
  return chars.join('');
89
89
  }
@@ -3,10 +3,28 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.PREFIX = exports.DEFAULT_INACTIVE_MS = exports.DEFAULT_EXPIRES_MS = void 0;
6
+ exports.SESSION_EVENT_TYPES = exports.SESSION_EVENTS = exports.PREFIX = exports.MODE = exports.DEFAULT_INACTIVE_MS = exports.DEFAULT_EXPIRES_MS = void 0;
7
7
  const PREFIX = 'NRBA';
8
8
  exports.PREFIX = PREFIX;
9
9
  const DEFAULT_EXPIRES_MS = 14400000;
10
10
  exports.DEFAULT_EXPIRES_MS = DEFAULT_EXPIRES_MS;
11
11
  const DEFAULT_INACTIVE_MS = 1800000;
12
- exports.DEFAULT_INACTIVE_MS = DEFAULT_INACTIVE_MS;
12
+ exports.DEFAULT_INACTIVE_MS = DEFAULT_INACTIVE_MS;
13
+ const SESSION_EVENTS = {
14
+ PAUSE: 'session-pause',
15
+ RESET: 'session-reset',
16
+ RESUME: 'session-resume',
17
+ UPDATE: 'session-update'
18
+ };
19
+ exports.SESSION_EVENTS = SESSION_EVENTS;
20
+ const SESSION_EVENT_TYPES = {
21
+ SAME_TAB: 'same-tab',
22
+ CROSS_TAB: 'cross-tab'
23
+ };
24
+ exports.SESSION_EVENT_TYPES = SESSION_EVENT_TYPES;
25
+ const MODE = {
26
+ OFF: 0,
27
+ FULL: 1,
28
+ ERROR: 2
29
+ };
30
+ exports.MODE = MODE;
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.SessionEntity = exports.SESSION_EVENT_TYPES = exports.SESSION_EVENTS = exports.MODE = void 0;
6
+ exports.SessionEntity = void 0;
7
7
  var _uniqueId = require("../ids/unique-id");
8
8
  var _console = require("../util/console");
9
9
  var _stringify = require("../util/stringify");
@@ -18,37 +18,19 @@ var _handle = require("../event-emitter/handle");
18
18
  var _constants2 = require("../../features/metrics/constants");
19
19
  var _features = require("../../loaders/features/features");
20
20
  var _eventListenerOpts = require("../event-listener/event-listener-opts");
21
- const MODE = {
22
- OFF: 0,
23
- FULL: 1,
24
- ERROR: 2
25
- };
26
21
  // this is what can be stored in local storage (not enforced but probably should be)
27
22
  // these values should sync between local storage and the parent class props
28
- exports.MODE = MODE;
29
23
  const model = {
30
24
  value: '',
31
25
  inactiveAt: 0,
32
26
  expiresAt: 0,
33
27
  updatedAt: Date.now(),
34
- sessionReplayMode: MODE.OFF,
28
+ sessionReplayMode: _constants.MODE.OFF,
35
29
  sessionReplaySentFirstChunk: false,
36
- sessionTraceMode: MODE.OFF,
30
+ sessionTraceMode: _constants.MODE.OFF,
37
31
  traceHarvestStarted: false,
38
32
  custom: {}
39
33
  };
40
- const SESSION_EVENTS = {
41
- PAUSE: 'session-pause',
42
- RESET: 'session-reset',
43
- RESUME: 'session-resume',
44
- UPDATE: 'session-update'
45
- };
46
- exports.SESSION_EVENTS = SESSION_EVENTS;
47
- const SESSION_EVENT_TYPES = {
48
- SAME_TAB: 'same-tab',
49
- CROSS_TAB: 'cross-tab'
50
- };
51
- exports.SESSION_EVENT_TYPES = SESSION_EVENT_TYPES;
52
34
  class SessionEntity {
53
35
  /**
54
36
  * Create a self-managing Session Entity. This entity is scoped to the agent identifier which triggered it, allowing for multiple simultaneous session objects to exist.
@@ -79,7 +61,7 @@ class SessionEntity {
79
61
  if (event.key === this.lookupKey) {
80
62
  const obj = typeof event.newValue === 'string' ? JSON.parse(event.newValue) : event.newValue;
81
63
  this.sync(obj);
82
- this.ee.emit(SESSION_EVENTS.UPDATE, [SESSION_EVENT_TYPES.CROSS_TAB, this.state]);
64
+ this.ee.emit(_constants.SESSION_EVENTS.UPDATE, [_constants.SESSION_EVENT_TYPES.CROSS_TAB, this.state]);
83
65
  }
84
66
  });
85
67
  }
@@ -137,11 +119,11 @@ class SessionEntity {
137
119
  // When the inactive timer refreshes, it will update the storage values with an update timestamp
138
120
  onRefresh: this.refresh.bind(this),
139
121
  onResume: () => {
140
- this.ee.emit(SESSION_EVENTS.RESUME);
122
+ this.ee.emit(_constants.SESSION_EVENTS.RESUME);
141
123
  },
142
124
  // When the inactive timer pauses, update the storage values with an update timestamp
143
125
  onPause: () => {
144
- if (this.initialized) this.ee.emit(SESSION_EVENTS.PAUSE);
126
+ if (this.initialized) this.ee.emit(_constants.SESSION_EVENTS.PAUSE);
145
127
  this.write((0, _configurable.getModeledObject)(this.state, model));
146
128
  },
147
129
  ee: this.ee,
@@ -216,7 +198,7 @@ class SessionEntity {
216
198
  //
217
199
  // TODO - compression would need happen here if we decide to do it
218
200
  this.storage.set(this.lookupKey, (0, _stringify.stringify)(this.state));
219
- this.ee.emit(SESSION_EVENTS.UPDATE, [SESSION_EVENT_TYPES.SAME_TAB, this.state]);
201
+ this.ee.emit(_constants.SESSION_EVENTS.UPDATE, [_constants.SESSION_EVENT_TYPES.SAME_TAB, this.state]);
220
202
  return data;
221
203
  } catch (e) {
222
204
  // storage is inaccessible
@@ -230,7 +212,7 @@ class SessionEntity {
230
212
  // * stop recording (stn and sr)...
231
213
  // * delete the session and start over
232
214
  try {
233
- if (this.initialized) this.ee.emit(SESSION_EVENTS.RESET);
215
+ if (this.initialized) this.ee.emit(_constants.SESSION_EVENTS.RESET);
234
216
  this.storage.remove(this.lookupKey);
235
217
  this.inactiveTimer?.abort?.();
236
218
  this.expiresTimer?.clear?.();
@@ -72,6 +72,8 @@ function obj(payload, maxBytes) {
72
72
 
73
73
  // Constructs an HTTP parameter to add to the BAM router URL
74
74
  function param(name, value) {
75
+ let base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
76
+ if (Object.keys(base).includes(name)) return ''; // we assume if feature supplied a matching qp to the base, we should honor what the feature sent over the default
75
77
  if (value && typeof value === 'string') {
76
78
  return '&' + name + '=' + qs(value);
77
79
  }
@@ -101,10 +101,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
101
101
 
102
102
  // Check if proxy for either chunks or beacon is being used
103
103
  const {
104
- proxy
104
+ proxy,
105
+ privacy
105
106
  } = (0, _config.getConfiguration)(this.agentIdentifier);
106
107
  if (proxy.assets) this.storeSupportabilityMetrics('Config/AssetsUrl/Changed');
107
108
  if (proxy.beacon) this.storeSupportabilityMetrics('Config/BeaconUrl/Changed');
109
+ if (!(_runtime.isBrowserScope && privacy.cookies_enabled)) this.storeSupportabilityMetrics('Config/SessionTracking/Disabled');
108
110
  }
109
111
  eachSessionChecks() {
110
112
  if (!_runtime.isBrowserScope) return;