@newrelic/browser-agent 1.322.0-rc.1 → 1.322.0-rc.11

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/README.md CHANGED
@@ -142,6 +142,27 @@ const options = {
142
142
  }
143
143
  ```
144
144
 
145
+ ## AJAX deny list
146
+
147
+ The browser agent can be configured to exclude specific domains or paths from `AjaxRequest` event tracking using the `ajax.deny_list` setting in the `init` configuration.
148
+
149
+ ```javascript
150
+ const options = {
151
+ info: { ... },
152
+ loader_config: { ... },
153
+ init: {
154
+ ajax: {
155
+ deny_list: ["mywebsite.com/photos"]
156
+ },
157
+ ...
158
+ }
159
+ }
160
+ ```
161
+
162
+ <b>Important:</b> Updating the deny list via the app settings page or NerdGraph only updates the `NREUM.init` configuration shown in the copy/paste snippet on the app's *Application settings* page. It doesn't take effect automatically for an agent installed via NPM. If you configure the deny list using one of those methods, you must manually copy over the updated configuration, then rebuild and redeploy your application for the change to take effect.
163
+
164
+ See [Configure AjaxRequest events](https://docs.newrelic.com/docs/browser/new-relic-browser/configuration/configure-ajax-request-events/) for more information.
165
+
145
166
  ## Options Parameter
146
167
 
147
168
  The `options` parameter used, or passed in, when instantiating the `BrowserAgent` class can include the following arguments:
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.322.0-rc.1";
20
+ const VERSION = exports.VERSION = "1.322.0-rc.11";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.RRWEB_PACKAGE_NAME = exports.D
17
17
  /**
18
18
  * Exposes the version of the agent
19
19
  */
20
- const VERSION = exports.VERSION = "1.322.0-rc.1";
20
+ const VERSION = exports.VERSION = "1.322.0-rc.11";
21
21
 
22
22
  /**
23
23
  * Exposes the build type of the agent
@@ -217,6 +217,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
217
217
  addKey: addStringRaw,
218
218
  addVal: addStringWithTruncation
219
219
  });
220
+
221
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
222
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
223
+ if (payloadAttrs.length) this.reportSupportabilityMetric('Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length);
220
224
  const attrParts = [...regularAttrs, ...payloadAttrs];
221
225
  fields.unshift((0, _belSerializer.numeric)(attrParts.length));
222
226
  insert += fields.join(',');
@@ -146,13 +146,18 @@ class Aggregate extends _aggregateBase.AggregateBase {
146
146
  }
147
147
  switchToFull() {
148
148
  if (!this.entitled || this.blocked) return;
149
+ const prevMode = this.mode;
149
150
  this.mode = _constants2.MODE.FULL;
151
+ this.#writeToStorage({
152
+ sessionReplayMode: this.mode
153
+ });
154
+
150
155
  // if the error was noticed AFTER the recorder was already imported....
151
156
  if (this.recorder && this.initialized) {
157
+ if (prevMode === _constants2.MODE.ERROR) {
158
+ this.agentRef.runtime.harvester.triggerHarvestFor(this);
159
+ }
152
160
  if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(_constants.TRIGGERS.SWITCH_TO_FULL, this.mode); // off --> full
153
- this.#writeToStorage({
154
- sessionReplayMode: this.mode
155
- });
156
161
  } else {
157
162
  this.initializeRecording(_constants2.MODE.FULL, true, _constants.TRIGGERS.SWITCH_TO_FULL);
158
163
  }
@@ -90,12 +90,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
90
90
  (0, _registerHandler.registerHandler)('bstApi', (...args) => this.traceStorage.storeNode(...args), this.featureName, this.ee);
91
91
  (0, _registerHandler.registerHandler)('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee);
92
92
  (0, _registerHandler.registerHandler)('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee);
93
- if (this.mode === _constants2.MODE.ERROR) {
94
- /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
95
- (0, _registerHandler.registerHandler)('trace-jserror', () => {
96
- if (this.mode === _constants2.MODE.ERROR) this.switchToFull();
97
- }, this.featureName, this.ee);
98
- }
93
+ }
94
+ if (this.mode === _constants2.MODE.ERROR) {
95
+ /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
96
+ (0, _registerHandler.registerHandler)('trace-jserror', () => {
97
+ if (this.mode === _constants2.MODE.ERROR) this.switchToFull();
98
+ }, this.featureName, this.ee);
99
99
  }
100
100
  this.agentRef.runtime.session.write({
101
101
  sessionTraceMode: this.mode
@@ -6,8 +6,11 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.AjaxNode = void 0;
7
7
  var _belSerializer = require("../../../common/serialize/bel-serializer");
8
8
  var _payloads = require("../../../common/payloads/payloads");
9
- var _constants = require("../../ajax/constants");
10
- var _constants2 = require("../constants");
9
+ var _handle = require("../../../common/event-emitter/handle");
10
+ var _features = require("../../../loaders/features/features");
11
+ var _constants = require("../../metrics/constants");
12
+ var _constants2 = require("../../ajax/constants");
13
+ var _constants3 = require("../constants");
11
14
  var _belNode = require("./bel-node");
12
15
  /**
13
16
  * Copyright 2020-2026 New Relic, Inc. All rights reserved.
@@ -17,7 +20,7 @@ var _belNode = require("./bel-node");
17
20
  class AjaxNode extends _belNode.BelNode {
18
21
  constructor(ajaxEvent, ajaxContext) {
19
22
  super();
20
- this.belType = _constants2.NODE_TYPE.AJAX;
23
+ this.belType = _constants3.NODE_TYPE.AJAX;
21
24
  this.method = ajaxEvent.method;
22
25
  this.status = ajaxEvent.status;
23
26
  this.domain = ajaxEvent.domain;
@@ -30,7 +33,7 @@ class AjaxNode extends _belNode.BelNode {
30
33
  this.spanTimestamp = ajaxEvent.spanTimestamp;
31
34
  this.gql = ajaxEvent.gql;
32
35
  this.targetAttributes = ajaxEvent.targetAttributes;
33
- this[_constants.AJAX_ID] = ajaxEvent[_constants.AJAX_ID]; // all AjaxRequest events should have a unique identifier to allow for easier grouping and analysis in the UI
36
+ this[_constants2.AJAX_ID] = ajaxEvent[_constants2.AJAX_ID]; // all AjaxRequest events should have a unique identifier to allow for easier grouping and analysis in the UI
34
37
 
35
38
  // optional payload metadata attributes
36
39
  this.requestBody = ajaxEvent.requestBody;
@@ -74,7 +77,7 @@ class AjaxNode extends _belNode.BelNode {
74
77
  addVal: addString
75
78
  });
76
79
  regularAttrs.push(...(0, _belSerializer.addCustomAttributes)({
77
- [_constants.AJAX_ID]: this[_constants.AJAX_ID]
80
+ [_constants2.AJAX_ID]: this[_constants2.AJAX_ID]
78
81
  }, {
79
82
  addKey: addStringRaw,
80
83
  addVal: addStringRaw
@@ -101,6 +104,10 @@ class AjaxNode extends _belNode.BelNode {
101
104
  addKey: addStringRaw,
102
105
  addVal: addStringWithTruncation
103
106
  });
107
+
108
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
109
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
110
+ if (payloadAttrs.length) (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length], undefined, _features.FEATURE_NAMES.metrics, agentRef.ee);
104
111
  let allAttachedNodes = [...regularAttrs, ...payloadAttrs];
105
112
  this.children.forEach(node => allAttachedNodes.push(node.serialize())); // no children is expected under ajax nodes at this time
106
113
 
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.322.0-rc.1";
14
+ export const VERSION = "1.322.0-rc.11";
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.322.0-rc.1";
14
+ export const VERSION = "1.322.0-rc.11";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -210,6 +210,10 @@ export class Aggregate extends AggregateBase {
210
210
  addKey: addStringRaw,
211
211
  addVal: addStringWithTruncation
212
212
  });
213
+
214
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
215
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
216
+ if (payloadAttrs.length) this.reportSupportabilityMetric('Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length);
213
217
  const attrParts = [...regularAttrs, ...payloadAttrs];
214
218
  fields.unshift(numeric(attrParts.length));
215
219
  insert += fields.join(',');
@@ -142,13 +142,18 @@ export class Aggregate extends AggregateBase {
142
142
  }
143
143
  switchToFull() {
144
144
  if (!this.entitled || this.blocked) return;
145
+ const prevMode = this.mode;
145
146
  this.mode = MODE.FULL;
147
+ this.#writeToStorage({
148
+ sessionReplayMode: this.mode
149
+ });
150
+
146
151
  // if the error was noticed AFTER the recorder was already imported....
147
152
  if (this.recorder && this.initialized) {
153
+ if (prevMode === MODE.ERROR) {
154
+ this.agentRef.runtime.harvester.triggerHarvestFor(this);
155
+ }
148
156
  if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(TRIGGERS.SWITCH_TO_FULL, this.mode); // off --> full
149
- this.#writeToStorage({
150
- sessionReplayMode: this.mode
151
- });
152
157
  } else {
153
158
  this.initializeRecording(MODE.FULL, true, TRIGGERS.SWITCH_TO_FULL);
154
159
  }
@@ -84,12 +84,12 @@ export class Aggregate extends AggregateBase {
84
84
  registerHandler('bstApi', (...args) => this.traceStorage.storeNode(...args), this.featureName, this.ee);
85
85
  registerHandler('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee);
86
86
  registerHandler('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee);
87
- if (this.mode === MODE.ERROR) {
88
- /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
89
- registerHandler('trace-jserror', () => {
90
- if (this.mode === MODE.ERROR) this.switchToFull();
91
- }, this.featureName, this.ee);
92
- }
87
+ }
88
+ if (this.mode === MODE.ERROR) {
89
+ /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
90
+ registerHandler('trace-jserror', () => {
91
+ if (this.mode === MODE.ERROR) this.switchToFull();
92
+ }, this.featureName, this.ee);
93
93
  }
94
94
  this.agentRef.runtime.session.write({
95
95
  sessionTraceMode: this.mode
@@ -4,6 +4,9 @@
4
4
  */
5
5
  import { addCustomAttributes, getAddStringContext, nullable, numeric } from '../../../common/serialize/bel-serializer';
6
6
  import { createStringAdders } from '../../../common/payloads/payloads';
7
+ import { handle } from '../../../common/event-emitter/handle';
8
+ import { FEATURE_NAMES } from '../../../loaders/features/features';
9
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
7
10
  import { AJAX_ID } from '../../ajax/constants';
8
11
  import { NODE_TYPE } from '../constants';
9
12
  import { BelNode } from './bel-node';
@@ -94,6 +97,10 @@ export class AjaxNode extends BelNode {
94
97
  addKey: addStringRaw,
95
98
  addVal: addStringWithTruncation
96
99
  });
100
+
101
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
102
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
103
+ if (payloadAttrs.length) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length], undefined, FEATURE_NAMES.metrics, agentRef.ee);
97
104
  let allAttachedNodes = [...regularAttrs, ...payloadAttrs];
98
105
  this.children.forEach(node => allAttachedNodes.push(node.serialize())); // no children is expected under ajax nodes at this time
99
106
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/ajax/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IAEjC,2BA6BC;IAvBC,uBAA4D;IAyB9D,0GA2FC;IAED,+CAOC;IAED,iDAuEC;CACF;8BA1N6B,4BAA4B;2BAK/B,gCAAgC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/ajax/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAAiC;IAEjC,2BA6BC;IAvBC,uBAA4D;IAyB9D,0GA2FC;IAED,+CAOC;IAED,iDA2EC;CACF;8BA9N6B,4BAA4B;2BAK/B,gCAAgC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AA2BA;IACE,2BAAiC;IAIjC,sCA+FC;IAlGD,WAAW;IAOT,uBAA0D;IAE1D,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IACnB,+DAA+D;IAC/D,wBAA0B;IAE1B,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,qBAA2B;IAE3B,cAA8C;IAI9C,kCAAqG;IAqEvG,0BAEC;IAED,0BAMC;IAED,qBAUC;IAED;;;;;;OAMG;IACH,4BALW,OAAO,iBACP,OAAO;;;;;;QAEL,IAAI,CA+ChB;IAED,2BAUC;IAED,0BA0CC;IAED;;;;OAIG;IACH,6BAHW,MAAM,EAAE,GACN;QAAE,UAAU,EAAE,MAAM,GAAC,SAAS,CAAC;QAAC,SAAS,EAAE,MAAM,GAAC,SAAS,CAAA;KAAE,CAUzE;IAED;;;;;;;;;;MAsEC;IAED,sCAcC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,+CASC;;CAOF;8BAjY6B,4BAA4B;2BAe/B,gCAAgC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/aggregate/index.js"],"names":[],"mappings":"AA2BA;IACE,2BAAiC;IAIjC,sCA+FC;IAlGD,WAAW;IAOT,uBAA0D;IAE1D,iFAAiF;IACjF,qBAAwB;IAGxB,2CAA2C;IAC3C,sDAAwB;IACxB,6CAA6C;IAC7C,gDAAmB;IACnB,+DAA+D;IAC/D,wBAA0B;IAE1B,0BAA0B;IAC1B,kBAAqB;IACrB,6CAA6C;IAC7C,gBAA2B;IAE3B,qBAA2B;IAE3B,cAA8C;IAI9C,kCAAqG;IAqEvG,0BAEC;IAED,0BAMC;IAED,qBAeC;IAED;;;;;;OAMG;IACH,4BALW,OAAO,iBACP,OAAO;;;;;;QAEL,IAAI,CA+ChB;IAED,2BAUC;IAED,0BA0CC;IAED;;;;OAIG;IACH,6BAHW,MAAM,EAAE,GACN;QAAE,UAAU,EAAE,MAAM,GAAC,SAAS,CAAC;QAAC,SAAS,EAAE,MAAM,GAAC,SAAS,CAAA;KAAE,CAUzE;IAED;;;;;;;;;;MAsEC;IAED,sCAcC;IAED;;;;OAIG;IACH,mCAKC;IAED,yDAAyD;IACzD,+CASC;;CAOF;8BAtY6B,4BAA4B;2BAe/B,gCAAgC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ajax-node.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/ajax-node.js"],"names":[],"mappings":"AAUA;IACE,8CA8BC;IA5BC,gBAA6B;IAC7B,YAA8B;IAC9B,YAA8B;IAC9B,YAA8B;IAC9B,UAA0B;IAC1B,YAAmC;IACnC,YAAoC;IACpC,+BAAwD;IACxD,YAA8B;IAC9B,aAAgC;IAChC,mBAA4C;IAC5C,SAAwB;IACxB,sBAAkD;IAIlD,iBAAwC;IACxC,oBAA8C;IAC9C,kBAA0C;IAC1C,kBAA0C;IAC1C,qBAAgD;IAK9C,iBAAoE;IAKxE,iFAkDC;IAnEC,sBAAkC;CAoErC;wBAtFuB,YAAY"}
1
+ {"version":3,"file":"ajax-node.d.ts","sourceRoot":"","sources":["../../../../../src/features/soft_navigations/aggregate/ajax-node.js"],"names":[],"mappings":"AAaA;IACE,8CA8BC;IA5BC,gBAA6B;IAC7B,YAA8B;IAC9B,YAA8B;IAC9B,YAA8B;IAC9B,UAA0B;IAC1B,YAAmC;IACnC,YAAoC;IACpC,+BAAwD;IACxD,YAA8B;IAC9B,aAAgC;IAChC,mBAA4C;IAC5C,SAAwB;IACxB,sBAAkD;IAIlD,iBAAwC;IACxC,oBAA8C;IAC9C,kBAA0C;IAC1C,kBAA0C;IAC1C,qBAAgD;IAK9C,iBAAoE;IAKxE,iFAsDC;IAvEC,sBAAkC;CAwErC;wBA1FuB,YAAY"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.322.0-rc.1",
3
+ "version": "1.322.0-rc.11",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -212,6 +212,10 @@ export class Aggregate extends AggregateBase {
212
212
  ...(event.responseHeaders ? { responseHeaders: event.responseHeaders } : {})
213
213
  }, { addKey: addStringRaw, addVal: addStringWithTruncation })
214
214
 
215
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
216
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
217
+ if (payloadAttrs.length) this.reportSupportabilityMetric('Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length)
218
+
215
219
  const attrParts = [...regularAttrs, ...payloadAttrs]
216
220
  fields.unshift(numeric(attrParts.length))
217
221
 
@@ -141,11 +141,16 @@ export class Aggregate extends AggregateBase {
141
141
 
142
142
  switchToFull () {
143
143
  if (!this.entitled || this.blocked) return
144
+ const prevMode = this.mode
144
145
  this.mode = MODE.FULL
146
+ this.#writeToStorage({ sessionReplayMode: this.mode })
147
+
145
148
  // if the error was noticed AFTER the recorder was already imported....
146
149
  if (this.recorder && this.initialized) {
150
+ if (prevMode === MODE.ERROR) {
151
+ this.agentRef.runtime.harvester.triggerHarvestFor(this)
152
+ }
147
153
  if (!this.agentRef.runtime.isRecording) this.recorder.startRecording(TRIGGERS.SWITCH_TO_FULL, this.mode) // off --> full
148
- this.#writeToStorage({ sessionReplayMode: this.mode })
149
154
  } else {
150
155
  this.initializeRecording(MODE.FULL, true, TRIGGERS.SWITCH_TO_FULL)
151
156
  }
@@ -90,13 +90,13 @@ export class Aggregate extends AggregateBase {
90
90
  registerHandler('bstApi', (...args) => this.traceStorage.storeNode(...args), this.featureName, this.ee)
91
91
  registerHandler('trace-jserror', (...args) => this.traceStorage.storeErrorAgg(...args), this.featureName, this.ee)
92
92
  registerHandler('pvtAdded', (...args) => this.traceStorage.processPVT(...args), this.featureName, this.ee)
93
+ }
93
94
 
94
- if (this.mode === MODE.ERROR) {
95
- /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
96
- registerHandler('trace-jserror', () => {
97
- if (this.mode === MODE.ERROR) this.switchToFull()
98
- }, this.featureName, this.ee)
99
- }
95
+ if (this.mode === MODE.ERROR) {
96
+ /** A separate handler for noticing errors, and switching to "full" mode if running in "error" mode */
97
+ registerHandler('trace-jserror', () => {
98
+ if (this.mode === MODE.ERROR) this.switchToFull()
99
+ }, this.featureName, this.ee)
100
100
  }
101
101
  this.agentRef.runtime.session.write({ sessionTraceMode: this.mode })
102
102
 
@@ -4,6 +4,9 @@
4
4
  */
5
5
  import { addCustomAttributes, getAddStringContext, nullable, numeric } from '../../../common/serialize/bel-serializer'
6
6
  import { createStringAdders } from '../../../common/payloads/payloads'
7
+ import { handle } from '../../../common/event-emitter/handle'
8
+ import { FEATURE_NAMES } from '../../../loaders/features/features'
9
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
7
10
  import { AJAX_ID } from '../../ajax/constants'
8
11
  import { NODE_TYPE } from '../constants'
9
12
  import { BelNode } from './bel-node'
@@ -83,6 +86,10 @@ export class AjaxNode extends BelNode {
83
86
  ...(this.responseHeaders ? { responseHeaders: this.responseHeaders } : {})
84
87
  }, { addKey: addStringRaw, addVal: addStringWithTruncation })
85
88
 
89
+ // .length is UTF-16 code units, not true UTF-8 byte size, so this undercounts multi-byte characters -- but it reuses the
90
+ // already-serialized payloadAttrs strings instead of re-stringifying/byte-counting, which is worth the imprecision here.
91
+ if (payloadAttrs.length) handle(SUPPORTABILITY_METRIC_CHANNEL, ['Ajax/Events/Payload/Bytes-Added', payloadAttrs.join(';').length], undefined, FEATURE_NAMES.metrics, agentRef.ee)
92
+
86
93
  let allAttachedNodes = [...regularAttrs, ...payloadAttrs]
87
94
  this.children.forEach(node => allAttachedNodes.push(node.serialize())) // no children is expected under ajax nodes at this time
88
95