@newrelic/browser-agent 1.272.0 → 1.273.1

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 (135) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/common/aggregate/aggregator.js +23 -30
  3. package/dist/cjs/common/aggregate/event-aggregator.js +84 -0
  4. package/dist/cjs/common/constants/env.cdn.js +1 -1
  5. package/dist/cjs/common/constants/env.npm.js +1 -1
  6. package/dist/cjs/common/harvest/harvest-scheduler.js +1 -1
  7. package/dist/cjs/common/harvest/harvest.js +1 -5
  8. package/dist/cjs/common/harvest/types.js +0 -1
  9. package/dist/cjs/features/ajax/aggregate/index.js +52 -62
  10. package/dist/cjs/features/generic_events/aggregate/index.js +18 -36
  11. package/dist/cjs/features/jserrors/aggregate/index.js +23 -69
  12. package/dist/cjs/features/logging/aggregate/index.js +52 -59
  13. package/dist/cjs/features/metrics/aggregate/index.js +8 -5
  14. package/dist/cjs/features/page_view_timing/aggregate/index.js +8 -25
  15. package/dist/cjs/features/session_replay/aggregate/index.js +11 -10
  16. package/dist/cjs/features/session_replay/shared/recorder-events.js +2 -2
  17. package/dist/cjs/features/session_trace/aggregate/index.js +77 -88
  18. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +22 -13
  19. package/dist/cjs/features/soft_navigations/aggregate/index.js +10 -20
  20. package/dist/cjs/features/soft_navigations/instrument/index.js +5 -9
  21. package/dist/cjs/features/spa/aggregate/index.js +10 -26
  22. package/dist/cjs/features/utils/agent-session.js +14 -19
  23. package/dist/cjs/features/utils/aggregate-base.js +37 -0
  24. package/dist/cjs/features/utils/event-buffer.js +36 -87
  25. package/dist/cjs/features/utils/instrument-base.js +4 -4
  26. package/dist/cjs/loaders/agent-base.js +6 -103
  27. package/dist/cjs/loaders/features/features.js +13 -1
  28. package/dist/cjs/loaders/micro-agent-base.js +117 -0
  29. package/dist/cjs/loaders/micro-agent.js +43 -56
  30. package/dist/esm/common/aggregate/aggregator.js +23 -30
  31. package/dist/esm/common/aggregate/event-aggregator.js +78 -0
  32. package/dist/esm/common/constants/env.cdn.js +1 -1
  33. package/dist/esm/common/constants/env.npm.js +1 -1
  34. package/dist/esm/common/harvest/harvest-scheduler.js +1 -1
  35. package/dist/esm/common/harvest/harvest.js +1 -5
  36. package/dist/esm/common/harvest/types.js +0 -1
  37. package/dist/esm/features/ajax/aggregate/index.js +53 -62
  38. package/dist/esm/features/generic_events/aggregate/index.js +18 -36
  39. package/dist/esm/features/jserrors/aggregate/index.js +24 -70
  40. package/dist/esm/features/logging/aggregate/index.js +52 -59
  41. package/dist/esm/features/metrics/aggregate/index.js +8 -5
  42. package/dist/esm/features/page_view_timing/aggregate/index.js +9 -26
  43. package/dist/esm/features/session_replay/aggregate/index.js +12 -11
  44. package/dist/esm/features/session_replay/shared/recorder-events.js +2 -2
  45. package/dist/esm/features/session_trace/aggregate/index.js +77 -88
  46. package/dist/esm/features/session_trace/aggregate/trace/storage.js +22 -13
  47. package/dist/esm/features/soft_navigations/aggregate/index.js +11 -21
  48. package/dist/esm/features/soft_navigations/instrument/index.js +5 -9
  49. package/dist/esm/features/spa/aggregate/index.js +11 -27
  50. package/dist/esm/features/utils/agent-session.js +14 -19
  51. package/dist/esm/features/utils/aggregate-base.js +37 -0
  52. package/dist/esm/features/utils/event-buffer.js +36 -88
  53. package/dist/esm/features/utils/instrument-base.js +4 -4
  54. package/dist/esm/loaders/agent-base.js +6 -103
  55. package/dist/esm/loaders/features/features.js +12 -0
  56. package/dist/esm/loaders/micro-agent-base.js +110 -0
  57. package/dist/esm/loaders/micro-agent.js +43 -56
  58. package/dist/types/common/aggregate/aggregator.d.ts +4 -6
  59. package/dist/types/common/aggregate/aggregator.d.ts.map +1 -1
  60. package/dist/types/common/aggregate/event-aggregator.d.ts +26 -0
  61. package/dist/types/common/aggregate/event-aggregator.d.ts.map +1 -0
  62. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  63. package/dist/types/common/harvest/types.d.ts +1 -4
  64. package/dist/types/common/harvest/types.d.ts.map +1 -1
  65. package/dist/types/features/ajax/aggregate/index.d.ts +2 -10
  66. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  67. package/dist/types/features/generic_events/aggregate/index.d.ts +5 -11
  68. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  69. package/dist/types/features/jserrors/aggregate/index.d.ts +4 -7
  70. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  71. package/dist/types/features/logging/aggregate/index.d.ts +10 -28
  72. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  73. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  74. package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -9
  75. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  76. package/dist/types/features/session_replay/aggregate/index.d.ts +3 -4
  77. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  78. package/dist/types/features/session_replay/shared/recorder-events.d.ts +1 -1
  79. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
  80. package/dist/types/features/session_replay/shared/recorder.d.ts +1 -1
  81. package/dist/types/features/session_trace/aggregate/index.d.ts +17 -19
  82. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  83. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +10 -6
  84. package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
  85. package/dist/types/features/soft_navigations/aggregate/index.d.ts +3 -9
  86. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  87. package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
  88. package/dist/types/features/spa/aggregate/index.d.ts +2 -3
  89. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  90. package/dist/types/features/utils/agent-session.d.ts +1 -1
  91. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  92. package/dist/types/features/utils/aggregate-base.d.ts +14 -0
  93. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  94. package/dist/types/features/utils/event-buffer.d.ts +19 -56
  95. package/dist/types/features/utils/event-buffer.d.ts.map +1 -1
  96. package/dist/types/loaders/agent-base.d.ts +5 -76
  97. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  98. package/dist/types/loaders/features/features.d.ts +3 -0
  99. package/dist/types/loaders/features/features.d.ts.map +1 -1
  100. package/dist/types/loaders/micro-agent-base.d.ts +75 -0
  101. package/dist/types/loaders/micro-agent-base.d.ts.map +1 -0
  102. package/dist/types/loaders/micro-agent.d.ts +4 -5
  103. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  104. package/package.json +1 -1
  105. package/src/common/aggregate/aggregator.js +22 -32
  106. package/src/common/aggregate/event-aggregator.js +76 -0
  107. package/src/common/harvest/harvest-scheduler.js +1 -1
  108. package/src/common/harvest/harvest.js +1 -5
  109. package/src/common/harvest/types.js +0 -1
  110. package/src/features/ajax/aggregate/index.js +60 -67
  111. package/src/features/generic_events/aggregate/index.js +14 -39
  112. package/src/features/jserrors/aggregate/index.js +21 -77
  113. package/src/features/logging/aggregate/index.js +46 -60
  114. package/src/features/metrics/aggregate/index.js +6 -4
  115. package/src/features/page_view_timing/aggregate/index.js +9 -30
  116. package/src/features/session_replay/aggregate/index.js +10 -14
  117. package/src/features/session_replay/shared/recorder-events.js +2 -2
  118. package/src/features/session_trace/aggregate/index.js +64 -73
  119. package/src/features/session_trace/aggregate/trace/storage.js +25 -14
  120. package/src/features/soft_navigations/aggregate/index.js +11 -22
  121. package/src/features/soft_navigations/instrument/index.js +6 -9
  122. package/src/features/spa/aggregate/index.js +12 -27
  123. package/src/features/utils/agent-session.js +12 -18
  124. package/src/features/utils/aggregate-base.js +39 -0
  125. package/src/features/utils/event-buffer.js +36 -83
  126. package/src/features/utils/instrument-base.js +4 -4
  127. package/src/loaders/agent-base.js +6 -104
  128. package/src/loaders/features/features.js +13 -0
  129. package/src/loaders/micro-agent-base.js +113 -0
  130. package/src/loaders/micro-agent.js +42 -55
  131. package/dist/cjs/features/ajax/aggregate/chunk.js +0 -51
  132. package/dist/esm/features/ajax/aggregate/chunk.js +0 -44
  133. package/dist/types/features/ajax/aggregate/chunk.d.ts +0 -8
  134. package/dist/types/features/ajax/aggregate/chunk.d.ts.map +0 -1
  135. package/src/features/ajax/aggregate/chunk.js +0 -52
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.273.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.273.0...v1.273.1) (2024-11-18)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Multiple MicroAgent undefined session and limit available API ([#1252](https://github.com/newrelic/newrelic-browser-agent/issues/1252)) ([19cbb63](https://github.com/newrelic/newrelic-browser-agent/commit/19cbb634b5016e3e8ce0c40a6bf1ee59156c78eb))
12
+
13
+ ## [1.273.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.272.0...v1.273.0) (2024-11-11)
14
+
15
+
16
+ ### Features
17
+
18
+ * Refactor feature storages ([#1241](https://github.com/newrelic/newrelic-browser-agent/issues/1241)) ([f77380b](https://github.com/newrelic/newrelic-browser-agent/commit/f77380b01e9b57db0b5c782d6d512431229bcd79))
19
+ * Remove wrap-events usage from soft nav ([#1244](https://github.com/newrelic/newrelic-browser-agent/issues/1244)) ([911d8d1](https://github.com/newrelic/newrelic-browser-agent/commit/911d8d1d78b49fa4252257596e013806885ace9b))
20
+
6
21
  ## [1.272.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.271.0...v1.272.0) (2024-11-07)
7
22
 
8
23
 
@@ -4,15 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Aggregator = void 0;
7
- var _sharedContext = require("../context/shared-context");
8
7
  /*
9
8
  * Copyright 2020 New Relic Corporation. All rights reserved.
10
9
  * SPDX-License-Identifier: Apache-2.0
11
10
  */
12
-
13
- class Aggregator extends _sharedContext.SharedContext {
14
- constructor(parent) {
15
- super(parent);
11
+ class Aggregator {
12
+ constructor() {
16
13
  this.aggregatedData = {};
17
14
  }
18
15
 
@@ -21,12 +18,14 @@ class Aggregator extends _sharedContext.SharedContext {
21
18
  // metrics are the numeric values to be aggregated
22
19
 
23
20
  store(type, name, params, newMetrics, customParams) {
24
- var bucket = this.getBucket(type, name, params, customParams);
21
+ var bucket = this.#getBucket(type, name, params, customParams);
25
22
  bucket.metrics = aggregateMetrics(newMetrics, bucket.metrics);
26
23
  return bucket;
27
24
  }
28
- merge(type, name, metrics, params, customParams) {
29
- var bucket = this.getBucket(type, name, params, customParams);
25
+ merge(type, name, metrics, params, customParams, overwriteParams = false) {
26
+ var bucket = this.#getBucket(type, name, params, customParams);
27
+ if (overwriteParams) bucket.params = params; // replace current params with incoming params obj
28
+
30
29
  if (!bucket.metrics) {
31
30
  bucket.metrics = metrics;
32
31
  return;
@@ -51,11 +50,25 @@ class Aggregator extends _sharedContext.SharedContext {
51
50
  });
52
51
  }
53
52
  storeMetric(type, name, params, value) {
54
- var bucket = this.getBucket(type, name, params);
53
+ var bucket = this.#getBucket(type, name, params);
55
54
  bucket.stats = updateMetric(value, bucket.stats);
56
55
  return bucket;
57
56
  }
58
- getBucket(type, name, params, customParams) {
57
+
58
+ // Get all listed types buckets and it deletes the retrieved content from the aggregatedData
59
+ take(types, deleteWhenRetrieved = true) {
60
+ var results = {};
61
+ var type = '';
62
+ var hasData = false;
63
+ for (var i = 0; i < types.length; i++) {
64
+ type = types[i];
65
+ results[type] = Object.values(this.aggregatedData[type] || {});
66
+ if (results[type].length) hasData = true;
67
+ if (deleteWhenRetrieved) delete this.aggregatedData[type];
68
+ }
69
+ return hasData ? results : null;
70
+ }
71
+ #getBucket(type, name, params, customParams) {
59
72
  if (!this.aggregatedData[type]) this.aggregatedData[type] = {};
60
73
  var bucket = this.aggregatedData[type][name];
61
74
  if (!bucket) {
@@ -68,26 +81,6 @@ class Aggregator extends _sharedContext.SharedContext {
68
81
  }
69
82
  return bucket;
70
83
  }
71
- get(type, name) {
72
- // if name is passed, get a single bucket
73
- if (name) return this.aggregatedData[type] && this.aggregatedData[type][name];
74
- // else, get all buckets of that type
75
- return this.aggregatedData[type];
76
- }
77
-
78
- // Like get, but for many types and it deletes the retrieved content from the aggregatedData
79
- take(types) {
80
- var results = {};
81
- var type = '';
82
- var hasData = false;
83
- for (var i = 0; i < types.length; i++) {
84
- type = types[i];
85
- results[type] = Object.values(this.aggregatedData[type] || {});
86
- if (results[type].length) hasData = true;
87
- delete this.aggregatedData[type];
88
- }
89
- return hasData ? results : null;
90
- }
91
84
  }
92
85
  exports.Aggregator = Aggregator;
93
86
  function aggregateMetrics(newMetrics, oldMetrics) {
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EventAggregator = void 0;
7
+ var _aggregator = require("./aggregator");
8
+ /**
9
+ * An extension of the Aggregator class that provides an interface similar to that of EventBuffer class.
10
+ * This typecasting allow features that uses Aggregator as their event handler to share the same AggregateBase.events utilization by those features.
11
+ */
12
+ class EventAggregator {
13
+ #aggregator = new _aggregator.Aggregator();
14
+ #savedNamesToBuckets = {};
15
+ isEmpty({
16
+ aggregatorTypes
17
+ }) {
18
+ if (!aggregatorTypes) return Object.keys(this.#aggregator.aggregatedData).length === 0;
19
+ return aggregatorTypes.every(type => !this.#aggregator.aggregatedData[type]); // no bucket exist for any of the types we're looking for
20
+ }
21
+ add(type, name, params, newMetrics, customParams) {
22
+ // Do we need to track byte size here like EventBuffer?
23
+ this.#aggregator.store(type, name, params, newMetrics, customParams);
24
+ return true;
25
+ }
26
+ addMetric(type, name, params, value) {
27
+ this.#aggregator.storeMetric(type, name, params, value);
28
+ return true;
29
+ }
30
+ save({
31
+ aggregatorTypes
32
+ }) {
33
+ const key = aggregatorTypes.toString(); // the stringified types serve as the key to each save call, e.g. ['err', 'ierr', 'xhr'] => 'err,ierr,xhr'
34
+ const backupAggregatedDataSubset = {};
35
+ aggregatorTypes.forEach(type => backupAggregatedDataSubset[type] = this.#aggregator.aggregatedData[type]); // make a subset of the aggregatedData for each of the types we want to save
36
+ this.#savedNamesToBuckets[key] = backupAggregatedDataSubset;
37
+ /*
38
+ { 'err,ierr,xhr': {
39
+ 'err': {
40
+ <aggregateHash>: { metrics: { count: 1, time, ... }, params: {}, custom: {} },
41
+ <otherHashName>: { metrics: { count: 1, ... }, ... }
42
+ },
43
+ 'ierr': { ... },
44
+ 'xhr': { ... }
45
+ }
46
+ }
47
+ */
48
+ }
49
+ get(opts) {
50
+ const aggregatorTypes = Array.isArray(opts) ? opts : opts.aggregatorTypes;
51
+ return this.#aggregator.take(aggregatorTypes, false);
52
+ }
53
+ clear({
54
+ aggregatorTypes
55
+ } = {}) {
56
+ if (!aggregatorTypes) {
57
+ this.#aggregator.aggregatedData = {};
58
+ return;
59
+ }
60
+ aggregatorTypes.forEach(type => delete this.#aggregator.aggregatedData[type]);
61
+ }
62
+ reloadSave({
63
+ aggregatorTypes
64
+ }) {
65
+ const key = aggregatorTypes.toString();
66
+ const backupAggregatedDataSubset = this.#savedNamesToBuckets[key];
67
+ // Grabs the previously stored subset and merge it back into aggregatedData.
68
+ aggregatorTypes.forEach(type => {
69
+ Object.keys(backupAggregatedDataSubset[type] || {}).forEach(name => {
70
+ const bucket = backupAggregatedDataSubset[type][name];
71
+ // The older aka saved params take effect over the newer one. This is especially important when merging back for a failed harvest retry if, for example,
72
+ // the first-ever occurrence of an error is in the retry: it contains the params.stack_trace whereas the newer or current bucket.params would not.
73
+ this.#aggregator.merge(type, name, bucket.metrics, bucket.params, bucket.custom, true);
74
+ });
75
+ });
76
+ }
77
+ clearSave({
78
+ aggregatorTypes
79
+ }) {
80
+ const key = aggregatorTypes.toString();
81
+ delete this.#savedNamesToBuckets[key];
82
+ }
83
+ }
84
+ exports.EventAggregator = EventAggregator;
@@ -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 = exports.VERSION = "1.272.0";
15
+ const VERSION = exports.VERSION = "1.273.1";
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 = exports.VERSION = "1.272.0";
15
+ const VERSION = exports.VERSION = "1.273.1";
16
16
 
17
17
  /**
18
18
  * Exposes the build type of the agent
@@ -102,7 +102,7 @@ class HarvestScheduler extends _sharedContext.SharedContext {
102
102
  let submitMethod;
103
103
  let payload;
104
104
  if (this.opts.getPayload) {
105
- // Ajax & PVT & SR features provide a callback function to get data for harvesting
105
+ // Ajax, PVT, Softnav, Logging, SR & ST features provide a single callback function to get data for harvesting
106
106
  submitMethod = submitData.getSubmitMethod({
107
107
  isFinalHarvest: opts?.unload
108
108
  });
@@ -128,11 +128,7 @@ class Harvest extends _sharedContext.SharedContext {
128
128
  const fullUrl = "".concat(url, "?").concat(baseParams).concat(payloadParams);
129
129
  const gzip = !!qs?.attributes?.includes('gzip');
130
130
  if (!gzip) {
131
- if (endpoint === 'events') {
132
- body = body.e;
133
- } else {
134
- body = (0, _stringify.stringify)(body);
135
- }
131
+ if (endpoint !== 'events') body = (0, _stringify.stringify)(body); // all features going to /events/ endpoint should already be serialized & stringified
136
132
  /** Warn --once per endpoint-- if the agent tries to send large payloads */
137
133
  if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) (0, _console.warn)(28, endpoint);
138
134
  }
@@ -18,7 +18,6 @@ exports.unused = void 0;
18
18
  * @typedef {object} HarvestPayload
19
19
  * @property {object} qs Map of values that should be sent as part of the request query string.
20
20
  * @property {object} body Map of values that should be sent as the body of the request.
21
- * @property {string} body.e Special case of body used for browser interactions.
22
21
  */
23
22
 
24
23
  /**
@@ -14,10 +14,7 @@ var _features = require("../../../loaders/features/features");
14
14
  var _constants2 = require("../../metrics/constants");
15
15
  var _aggregateBase = require("../../utils/aggregate-base");
16
16
  var _gql = require("./gql");
17
- var _nreum = require("../../../common/window/nreum");
18
- var _chunk = _interopRequireDefault(require("./chunk"));
19
- var _eventBuffer = require("../../utils/event-buffer");
20
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
17
+ var _belSerializer = require("../../../common/serialize/bel-serializer");
21
18
  /*
22
19
  * Copyright 2020 New Relic Corporation. All rights reserved.
23
20
  * SPDX-License-Identifier: Apache-2.0
@@ -29,31 +26,30 @@ class Aggregate extends _aggregateBase.AggregateBase {
29
26
  super(agentRef, _constants.FEATURE_NAME);
30
27
  const harvestTimeSeconds = agentRef.init.ajax.harvestTimeSeconds || 10;
31
28
  (0, _denyList.setDenyList)(agentRef.runtime.denyList);
32
- this.ajaxEvents = new _eventBuffer.EventBuffer();
33
- this.spaAjaxEvents = {};
29
+ this.underSpaEvents = {};
34
30
  const classThis = this;
35
31
 
36
32
  // --- v Used by old spa feature
37
33
  this.ee.on('interactionDone', (interaction, wasSaved) => {
38
- if (!this.spaAjaxEvents[interaction.id]?.hasData) return;
34
+ if (!this.underSpaEvents[interaction.id]) return;
39
35
  if (!wasSaved) {
40
36
  // if the ixn was saved, then its ajax reqs are part of the payload whereas if it was discarded, it should still be harvested in the ajax feature itself
41
- this.ajaxEvents.merge(this.spaAjaxEvents[interaction.id]);
37
+ this.underSpaEvents[interaction.id].forEach(item => this.events.add(item));
42
38
  }
43
- delete this.spaAjaxEvents[interaction.id];
39
+ delete this.underSpaEvents[interaction.id];
44
40
  });
45
41
  // --- ^
46
42
  // --- v Used by new soft nav
47
- (0, _registerHandler.registerHandler)('returnAjax', event => this.ajaxEvents.add(event), this.featureName, this.ee);
43
+ (0, _registerHandler.registerHandler)('returnAjax', event => this.events.add(event), this.featureName, this.ee);
48
44
  // --- ^
49
45
  (0, _registerHandler.registerHandler)('xhr', function () {
50
46
  // the EE-drain system not only switches "this" but also passes a new EventContext with info. Should consider platform refactor to another system which passes a mutable context around separately and predictably to avoid problems like this.
51
47
  classThis.storeXhr(...arguments, this); // this switches the context back to the class instance while passing the NR context as an argument -- see "ctx" in storeXhr
52
48
  }, this.featureName, this.ee);
53
49
  this.waitForFlags([]).then(() => {
54
- const scheduler = new _harvestScheduler.HarvestScheduler('events', {
55
- onFinished: this.onEventsHarvestFinished.bind(this),
56
- getPayload: this.prepareHarvest.bind(this)
50
+ const scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
51
+ onFinished: result => this.postHarvestCleanup(result.sent && result.retry),
52
+ getPayload: options => this.makeHarvestPayload(options.retry)
57
53
  }, this);
58
54
  scheduler.startTimer(harvestTimeSeconds);
59
55
  this.drain();
@@ -71,10 +67,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
71
67
  }
72
68
  const shouldCollect = (0, _denyList.shouldCollectEvent)(params);
73
69
  const shouldOmitAjaxMetrics = this.agentRef.init.feature_flags?.includes('ajax_metrics_deny_list');
70
+ const jserrorsInUse = Boolean(this.agentRef.features?.[_features.FEATURE_NAMES.jserrors]);
74
71
 
75
- // store for timeslice metric (harvested by jserrors feature)
76
- if (shouldCollect || !shouldOmitAjaxMetrics) {
77
- this.agentRef.sharedAggregator.store('xhr', hash, params, metrics);
72
+ // Report ajax timeslice metric (to be harvested by jserrors feature, but only if it's running).
73
+ if (jserrorsInUse && (shouldCollect || !shouldOmitAjaxMetrics)) {
74
+ this.agentRef.sharedAggregator.add('xhr', hash, params, metrics);
78
75
  }
79
76
  if (!shouldCollect) {
80
77
  if (params.hostname === this.agentRef.info.errorBeacon || this.agentRef.init.proxy?.beacon && params.hostname === this.agentRef.init.proxy.beacon) {
@@ -113,63 +110,56 @@ class Aggregate extends _aggregateBase.AggregateBase {
113
110
  query: ctx.parsedOrigin?.search
114
111
  });
115
112
  if (event.gql) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/GraphQL/Bytes-Added', (0, _stringify.stringify)(event.gql).length], undefined, _features.FEATURE_NAMES.metrics, this.ee);
116
- const softNavInUse = Boolean((0, _nreum.getNREUMInitializedAgent)(this.agentIdentifier)?.features?.[_features.FEATURE_NAMES.softNav]);
113
+ const softNavInUse = Boolean(this.agentRef.features?.[_features.FEATURE_NAMES.softNav]);
117
114
  if (softNavInUse) {
118
115
  // For newer soft nav (when running), pass the event to it for evaluation -- either part of an interaction or is given back
119
116
  (0, _handle.handle)('ajax', [event], undefined, _features.FEATURE_NAMES.softNav, this.ee);
120
117
  } else if (ctx.spaNode) {
121
118
  // For old spa (when running), if the ajax happened inside an interaction, hold it until the interaction finishes
122
119
  const interactionId = ctx.spaNode.interaction.id;
123
- this.spaAjaxEvents[interactionId] ??= new _eventBuffer.EventBuffer();
124
- this.spaAjaxEvents[interactionId].add(event);
120
+ this.underSpaEvents[interactionId] ??= [];
121
+ this.underSpaEvents[interactionId].push(event);
125
122
  } else {
126
- this.ajaxEvents.add(event);
123
+ this.events.add(event);
127
124
  }
128
125
  }
129
- prepareHarvest(options) {
130
- options = options || {};
131
- if (this.ajaxEvents.buffer.length === 0) return null;
132
- const payload = this.#getPayload(this.ajaxEvents.buffer);
133
- const payloadObjs = [];
134
- for (let i = 0; i < payload.length; i++) payloadObjs.push({
135
- body: {
136
- e: payload[i]
137
- }
138
- });
139
- if (options.retry) this.ajaxEvents.hold();else this.ajaxEvents.clear();
140
- return payloadObjs;
141
- }
142
- onEventsHarvestFinished(result) {
143
- if (result.retry && this.ajaxEvents.held.hasData) this.ajaxEvents.unhold();else this.ajaxEvents.held.clear();
144
- }
145
- #getPayload(events, numberOfChunks) {
146
- numberOfChunks = numberOfChunks || 1;
147
- const payload = [];
148
- const chunkSize = events.length / numberOfChunks;
149
- const eventChunks = splitChunks.call(this, events, chunkSize);
150
- let tooBig = false;
151
- for (let i = 0; i < eventChunks.length; i++) {
152
- const currentChunk = eventChunks[i];
153
- if (currentChunk.tooBig) {
154
- if (currentChunk.events.length > 1) {
155
- tooBig = true;
156
- break; // if the payload is too big BUT is made of more than 1 event, we can split it down again
157
- }
158
- // Otherwise, if it consists of one sole event, we do not send it (discarded) since we cannot break it apart any further.
159
- } else {
160
- payload.push(currentChunk.payload);
161
- }
162
- }
163
- // Check if the current payload string is too big, if so then run getPayload again with more buckets.
164
- return tooBig ? this.#getPayload(events, ++numberOfChunks) : payload;
165
- function splitChunks(arr, chunkSize) {
166
- chunkSize = chunkSize || arr.length;
167
- const chunks = [];
168
- for (let i = 0, len = arr.length; i < len; i += chunkSize) {
169
- chunks.push(new _chunk.default(arr.slice(i, i + chunkSize), this));
126
+ serializer(eventBuffer) {
127
+ const addString = (0, _belSerializer.getAddStringContext)(this.agentIdentifier);
128
+ let payload = 'bel.7;';
129
+ for (let i = 0; i < eventBuffer.length; i++) {
130
+ const event = eventBuffer[i];
131
+ const fields = [(0, _belSerializer.numeric)(event.startTime), (0, _belSerializer.numeric)(event.endTime - event.startTime), (0, _belSerializer.numeric)(0),
132
+ // callbackEnd
133
+ (0, _belSerializer.numeric)(0),
134
+ // no callbackDuration for non-SPA events
135
+ addString(event.method), (0, _belSerializer.numeric)(event.status), addString(event.domain), addString(event.path), (0, _belSerializer.numeric)(event.requestSize), (0, _belSerializer.numeric)(event.responseSize), event.type === 'fetch' ? 1 : '', addString(0),
136
+ // nodeId
137
+ (0, _belSerializer.nullable)(event.spanId, addString, true) +
138
+ // guid
139
+ (0, _belSerializer.nullable)(event.traceId, addString, true) +
140
+ // traceId
141
+ (0, _belSerializer.nullable)(event.spanTimestamp, _belSerializer.numeric, false) // timestamp
142
+ ];
143
+ let insert = '2,';
144
+
145
+ // Since configuration objects (like info) are created new each time they are set, we have to grab the current pointer to the attr object here.
146
+ const jsAttributes = this.agentRef.info.jsAttributes;
147
+
148
+ // add custom attributes
149
+ // gql decorators are added as custom attributes to alleviate need for new BEL schema
150
+ const attrParts = (0, _belSerializer.addCustomAttributes)({
151
+ ...(jsAttributes || {}),
152
+ ...(event.gql || {})
153
+ }, addString);
154
+ fields.unshift((0, _belSerializer.numeric)(attrParts.length));
155
+ insert += fields.join(',');
156
+ if (attrParts && attrParts.length > 0) {
157
+ insert += ';' + attrParts.join(';');
170
158
  }
171
- return chunks;
159
+ if (i + 1 < eventBuffer.length) insert += ';';
160
+ payload += insert;
172
161
  }
162
+ return payload;
173
163
  }
174
164
  }
175
165
  exports.Aggregate = Aggregate;
@@ -14,9 +14,9 @@ var _console = require("../../../common/util/console");
14
14
  var _now = require("../../../common/timing/now");
15
15
  var _registerHandler = require("../../../common/event-emitter/register-handler");
16
16
  var _constants2 = require("../../metrics/constants");
17
- var _eventBuffer = require("../../utils/event-buffer");
18
17
  var _traverse = require("../../../common/util/traverse");
19
18
  var _agentConstants = require("../../../common/constants/agent-constants");
19
+ var _features = require("../../../loaders/features/features");
20
20
  var _userActionsAggregator = require("./user-actions/user-actions-aggregator");
21
21
  var _iframe = require("../../../common/dom/iframe");
22
22
  /*
@@ -31,14 +31,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
31
31
  this.eventsPerHarvest = 1000;
32
32
  this.harvestTimeSeconds = agentRef.init.generic_events.harvestTimeSeconds;
33
33
  this.referrerUrl = _runtime.isBrowserScope && document.referrer ? (0, _cleanUrl.cleanURL)(document.referrer) : undefined;
34
- this.events = new _eventBuffer.EventBuffer();
35
34
  this.waitForFlags(['ins']).then(([ins]) => {
36
35
  if (!ins) {
37
36
  this.blocked = true;
38
37
  this.deregisterDrain();
39
38
  return;
40
39
  }
41
- const preHarvestMethods = [];
42
40
  if (agentRef.init.page_action.enabled) {
43
41
  (0, _registerHandler.registerHandler)('api-addPageAction', (timestamp, name, attributes) => {
44
42
  this.addEvent({
@@ -55,9 +53,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
55
53
  });
56
54
  }, this.featureName, this.ee);
57
55
  }
56
+ let addUserAction;
58
57
  if (_runtime.isBrowserScope && agentRef.init.user_actions.enabled) {
59
58
  this.userActionAggregator = new _userActionsAggregator.UserActionsAggregator();
60
- this.addUserAction = aggregatedUserAction => {
59
+ addUserAction = aggregatedUserAction => {
61
60
  try {
62
61
  /** The aggregator process only returns an event when it is "done" aggregating -
63
62
  * so we still need to validate that an event was given to this method before we try to add */
@@ -99,13 +98,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
99
98
  };
100
99
  (0, _registerHandler.registerHandler)('ua', evt => {
101
100
  /** the processor will return the previously aggregated event if it has been completed by processing the current event */
102
- this.addUserAction(this.userActionAggregator.process(evt));
101
+ addUserAction(this.userActionAggregator.process(evt));
103
102
  }, this.featureName, this.ee);
104
- preHarvestMethods.push((options = {}) => {
105
- /** send whatever UserActions have been aggregated up to this point
106
- * if we are in a final harvest. By accessing the aggregationEvent, the aggregation is then force-cleared */
107
- if (options.isFinalHarvest) this.addUserAction(this.userActionAggregator.aggregationEvent);
108
- });
109
103
  }
110
104
 
111
105
  /**
@@ -146,13 +140,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
146
140
  // Something failed in our set up, likely the browser does not support PO's... do nothing
147
141
  }
148
142
  }
149
- this.harvestScheduler = new _harvestScheduler.HarvestScheduler('ins', {
150
- onFinished: (...args) => this.onHarvestFinished(...args)
143
+ this.harvestScheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
144
+ onFinished: result => this.postHarvestCleanup(result.sent && result.retry),
145
+ onUnload: () => addUserAction?.(this.userActionAggregator.aggregationEvent)
151
146
  }, this);
152
- this.harvestScheduler.harvest.on('ins', (...args) => {
153
- preHarvestMethods.forEach(fn => fn(...args));
154
- return this.onHarvestStarted(...args);
155
- });
147
+ this.harvestScheduler.harvest.on(_features.FEATURE_TO_ENDPOINT[this.featureName], options => this.makeHarvestPayload(options.retry));
156
148
  this.harvestScheduler.startTimer(this.harvestTimeSeconds, 0);
157
149
  this.drain();
158
150
  });
@@ -199,30 +191,20 @@ class Aggregate extends _aggregateBase.AggregateBase {
199
191
  this.events.add(eventAttributes);
200
192
  this.checkEventLimits();
201
193
  }
202
- onHarvestStarted(options) {
203
- const {
204
- userAttributes,
205
- atts
206
- } = this.agentRef.info;
207
- if (!this.events.hasData) return;
208
- var payload = {
209
- qs: {
210
- ua: userAttributes,
211
- at: atts
212
- },
213
- body: (0, _traverse.applyFnToProps)({
214
- ins: this.events.buffer
215
- }, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')
216
- };
217
- if (options.retry) this.events.hold();else this.events.clear();
218
- return payload;
194
+ serializer(eventBuffer) {
195
+ return (0, _traverse.applyFnToProps)({
196
+ ins: eventBuffer
197
+ }, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string');
219
198
  }
220
- onHarvestFinished(result) {
221
- if (result && result?.sent && result?.retry && this.events.held.hasData) this.events.unhold();else this.events.held.clear();
199
+ queryStringsBuilder() {
200
+ return {
201
+ ua: this.agentRef.info.userAttributes,
202
+ at: this.agentRef.info.atts
203
+ };
222
204
  }
223
205
  checkEventLimits() {
224
206
  // check if we've reached any harvest limits...
225
- if (this.events.bytes > _agentConstants.IDEAL_PAYLOAD_SIZE) {
207
+ if (this.events.byteSize() > _agentConstants.IDEAL_PAYLOAD_SIZE) {
226
208
  this.ee.emit(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
227
209
  this.harvestScheduler.runHarvest();
228
210
  }