@newrelic/browser-agent 1.316.0 → 1.317.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/cjs/common/config/init-types.js +1 -0
- package/dist/cjs/common/config/init.js +6 -4
- package/dist/cjs/common/constants/env.cdn.js +2 -2
- package/dist/cjs/common/constants/env.npm.js +2 -2
- package/dist/cjs/common/constants/events.js +26 -0
- package/dist/cjs/common/harvest/harvester.js +12 -4
- package/dist/cjs/common/payloads/payloads.js +127 -0
- package/dist/cjs/common/serialize/bel-serializer.js +4 -3
- package/dist/cjs/common/util/data-size.js +2 -2
- package/dist/cjs/common/util/obfuscate.js +147 -3
- package/dist/cjs/common/wrap/wrap-websocket.js +2 -1
- package/dist/cjs/common/wrap/wrap-xhr.js +1 -1
- package/dist/cjs/features/ajax/aggregate/gql.js +40 -1
- package/dist/cjs/features/ajax/aggregate/index.js +51 -13
- package/dist/cjs/features/ajax/constants.js +6 -1
- package/dist/cjs/features/ajax/instrument/index.js +105 -17
- package/dist/cjs/features/generic_events/aggregate/index.js +15 -10
- package/dist/cjs/features/generic_events/constants.js +3 -2
- package/dist/cjs/features/jserrors/aggregate/format-stack-trace.js +2 -2
- package/dist/cjs/features/jserrors/aggregate/index.js +12 -3
- package/dist/cjs/features/logging/aggregate/index.js +7 -3
- package/dist/cjs/features/metrics/aggregate/index.js +5 -1
- package/dist/cjs/features/page_view_event/aggregate/index.js +7 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -1
- package/dist/cjs/features/session_replay/aggregate/index.js +7 -1
- package/dist/cjs/features/session_trace/aggregate/index.js +6 -2
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +36 -5
- package/dist/cjs/features/soft_navigations/aggregate/index.js +7 -1
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +6 -4
- package/dist/cjs/features/utils/aggregate-base.js +2 -3
- package/dist/esm/common/config/init-types.js +1 -0
- package/dist/esm/common/config/init.js +3 -1
- package/dist/esm/common/constants/env.cdn.js +2 -2
- package/dist/esm/common/constants/env.npm.js +2 -2
- package/dist/esm/common/constants/events.js +20 -0
- package/dist/esm/common/harvest/harvester.js +12 -4
- package/dist/esm/common/payloads/payloads.js +118 -0
- package/dist/esm/common/serialize/bel-serializer.js +4 -3
- package/dist/esm/common/util/data-size.js +2 -2
- package/dist/esm/common/util/obfuscate.js +147 -3
- package/dist/esm/common/wrap/wrap-websocket.js +2 -1
- package/dist/esm/common/wrap/wrap-xhr.js +1 -1
- package/dist/esm/features/ajax/aggregate/gql.js +39 -1
- package/dist/esm/features/ajax/aggregate/index.js +52 -14
- package/dist/esm/features/ajax/constants.js +5 -0
- package/dist/esm/features/ajax/instrument/index.js +106 -18
- package/dist/esm/features/generic_events/aggregate/index.js +15 -10
- package/dist/esm/features/generic_events/constants.js +3 -2
- package/dist/esm/features/jserrors/aggregate/format-stack-trace.js +2 -2
- package/dist/esm/features/jserrors/aggregate/index.js +12 -3
- package/dist/esm/features/logging/aggregate/index.js +7 -3
- package/dist/esm/features/metrics/aggregate/index.js +5 -1
- package/dist/esm/features/page_view_event/aggregate/index.js +7 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +6 -1
- package/dist/esm/features/session_replay/aggregate/index.js +7 -1
- package/dist/esm/features/session_trace/aggregate/index.js +6 -2
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +36 -5
- package/dist/esm/features/soft_navigations/aggregate/index.js +7 -1
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +6 -4
- package/dist/esm/features/utils/aggregate-base.js +2 -3
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +4 -0
- package/dist/types/common/config/init-types.d.ts.map +1 -1
- package/dist/types/common/config/init.d.ts.map +1 -1
- package/dist/types/common/constants/events.d.ts +16 -0
- package/dist/types/common/constants/events.d.ts.map +1 -0
- package/dist/types/common/harvest/harvester.d.ts +4 -1
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/payloads/payloads.d.ts +42 -0
- package/dist/types/common/payloads/payloads.d.ts.map +1 -0
- package/dist/types/common/serialize/bel-serializer.d.ts +1 -1
- package/dist/types/common/serialize/bel-serializer.d.ts.map +1 -1
- package/dist/types/common/util/obfuscate.d.ts +23 -2
- package/dist/types/common/util/obfuscate.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-websocket.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/gql.d.ts +8 -0
- package/dist/types/features/ajax/aggregate/gql.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +2 -0
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/ajax/constants.d.ts +5 -0
- package/dist/types/features/ajax/constants.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +3 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/constants.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +8 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +3 -1
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts +2 -0
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -0
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -0
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +2 -0
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +2 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +6 -1
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +3 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +3 -1
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +0 -1
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/common/config/init-types.js +1 -0
- package/src/common/config/init.js +2 -1
- package/src/common/constants/events.js +20 -0
- package/src/common/harvest/harvester.js +11 -4
- package/src/common/payloads/payloads.js +135 -0
- package/src/common/serialize/bel-serializer.js +4 -3
- package/src/common/util/data-size.js +2 -2
- package/src/common/util/obfuscate.js +154 -3
- package/src/common/wrap/wrap-websocket.js +2 -1
- package/src/common/wrap/wrap-xhr.js +1 -1
- package/src/features/ajax/aggregate/gql.js +42 -1
- package/src/features/ajax/aggregate/index.js +43 -13
- package/src/features/ajax/constants.js +5 -1
- package/src/features/ajax/instrument/index.js +114 -18
- package/src/features/generic_events/aggregate/index.js +14 -9
- package/src/features/generic_events/constants.js +3 -2
- package/src/features/jserrors/aggregate/format-stack-trace.js +3 -3
- package/src/features/jserrors/aggregate/index.js +12 -3
- package/src/features/logging/aggregate/index.js +7 -6
- package/src/features/metrics/aggregate/index.js +5 -1
- package/src/features/page_view_event/aggregate/index.js +6 -2
- package/src/features/page_view_timing/aggregate/index.js +6 -1
- package/src/features/session_replay/aggregate/index.js +7 -1
- package/src/features/session_trace/aggregate/index.js +6 -2
- package/src/features/soft_navigations/aggregate/ajax-node.js +26 -5
- package/src/features/soft_navigations/aggregate/index.js +7 -1
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +1 -1
- package/src/features/soft_navigations/aggregate/interaction.js +6 -4
- package/src/features/utils/aggregate-base.js +1 -3
|
@@ -17,9 +17,11 @@ var _stringify = require("../../../common/util/stringify");
|
|
|
17
17
|
var _stylesheetEvaluator = require("../shared/stylesheet-evaluator");
|
|
18
18
|
var _now = require("../../../common/timing/now");
|
|
19
19
|
var _agentConstants = require("../../../common/constants/agent-constants");
|
|
20
|
+
var _events = require("../../../common/constants/events");
|
|
20
21
|
var _cleanUrl = require("../../../common/url/clean-url");
|
|
21
22
|
var _featureGates = require("../../utils/feature-gates");
|
|
22
23
|
var _constants3 = require("../../../loaders/api/constants");
|
|
24
|
+
var _obfuscate = require("../../../common/util/obfuscate");
|
|
23
25
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /**
|
|
24
26
|
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
25
27
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -33,6 +35,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
33
35
|
// pass the recorder into the aggregator
|
|
34
36
|
constructor(agentRef, args) {
|
|
35
37
|
super(agentRef, _constants.FEATURE_NAME);
|
|
38
|
+
|
|
39
|
+
// Create obfuscator for session replay query params
|
|
40
|
+
this.obfuscator = new _obfuscate.Obfuscator(agentRef, _events.EVENT_TYPES.SR);
|
|
41
|
+
|
|
36
42
|
/** Set once the recorder has fully initialized after flag checks and sampling */
|
|
37
43
|
this.initialized = false;
|
|
38
44
|
/** Set once the feature has been "aborted" to prevent other side-effects from continuing */
|
|
@@ -310,7 +316,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
310
316
|
return {
|
|
311
317
|
qs: {
|
|
312
318
|
browser_monitoring_key: this.agentRef.info.licenseKey,
|
|
313
|
-
type:
|
|
319
|
+
type: _events.EVENT_TYPES.SR,
|
|
314
320
|
app_id: this.agentRef.info.applicationID,
|
|
315
321
|
protocol_version: '0',
|
|
316
322
|
timestamp: firstTimestamp,
|
|
@@ -11,9 +11,10 @@ var _storage = require("./trace/storage");
|
|
|
11
11
|
var _encode = require("../../../common/url/encode");
|
|
12
12
|
var _runtime = require("../../../common/constants/runtime");
|
|
13
13
|
var _constants2 = require("../../../common/session/constants");
|
|
14
|
-
var
|
|
14
|
+
var _obfuscate = require("../../../common/util/obfuscate");
|
|
15
15
|
var _cleanUrl = require("../../../common/url/clean-url");
|
|
16
16
|
var _console = require("../../../common/util/console");
|
|
17
|
+
var _events = require("../../../common/constants/events");
|
|
17
18
|
/**
|
|
18
19
|
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
19
20
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -27,6 +28,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
27
28
|
super(agentRef, _constants.FEATURE_NAME);
|
|
28
29
|
this.harvestOpts.raw = true;
|
|
29
30
|
|
|
31
|
+
// Create obfuscator for session trace nodes
|
|
32
|
+
this.obfuscator = new _obfuscate.Obfuscator(agentRef, _events.EVENT_TYPES.ST);
|
|
33
|
+
|
|
30
34
|
/** Tied to the entitlement flag response from BCS. Will short circuit operations of the agg if false */
|
|
31
35
|
this.entitled = undefined;
|
|
32
36
|
/** A flag used to decide if the 30 node threshold should be ignored on the first harvest to ensure sending on the first payload */
|
|
@@ -113,7 +117,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
113
117
|
serializer(stns) {
|
|
114
118
|
if (!stns.length) return; // there are no processed nodes
|
|
115
119
|
this.everHarvested = true;
|
|
116
|
-
return
|
|
120
|
+
return this.obfuscator.traverseAndObfuscateEvents(stns);
|
|
117
121
|
}
|
|
118
122
|
queryStringsBuilder(stns) {
|
|
119
123
|
const firstSessionHarvest = !this.agentRef.runtime.session.state.traceHarvestStarted;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.AjaxNode = void 0;
|
|
7
7
|
var _belSerializer = require("../../../common/serialize/bel-serializer");
|
|
8
|
+
var _payloads = require("../../../common/payloads/payloads");
|
|
8
9
|
var _constants = require("../../ajax/constants");
|
|
9
10
|
var _constants2 = require("../constants");
|
|
10
11
|
var _belNode = require("./bel-node");
|
|
@@ -31,6 +32,12 @@ class AjaxNode extends _belNode.BelNode {
|
|
|
31
32
|
this.targetAttributes = ajaxEvent.targetAttributes;
|
|
32
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
|
|
33
34
|
|
|
35
|
+
// optional payload metadata attributes
|
|
36
|
+
this.requestBody = ajaxEvent.requestBody;
|
|
37
|
+
this.requestHeaders = ajaxEvent.requestHeaders;
|
|
38
|
+
this.requestQuery = ajaxEvent.requestQuery;
|
|
39
|
+
this.responseBody = ajaxEvent.responseBody;
|
|
40
|
+
this.responseHeaders = ajaxEvent.responseHeaders;
|
|
34
41
|
this.start = ajaxEvent.startTime;
|
|
35
42
|
this.end = ajaxEvent.endTime;
|
|
36
43
|
if (ajaxContext?.latestLongtaskEnd) {
|
|
@@ -38,8 +45,11 @@ class AjaxNode extends _belNode.BelNode {
|
|
|
38
45
|
this.callbackDuration = this.callbackEnd - this.end; // callbackDuration is the time from ajax loaded to last long task observed from it
|
|
39
46
|
} else this.callbackEnd = this.end; // if no long task was observed, callbackEnd is the same as end
|
|
40
47
|
}
|
|
41
|
-
serialize(parentStartTimestamp, agentRef) {
|
|
42
|
-
const
|
|
48
|
+
serialize(parentStartTimestamp, agentRef, ajaxObfuscator) {
|
|
49
|
+
const {
|
|
50
|
+
addString,
|
|
51
|
+
addStringWithTruncation
|
|
52
|
+
} = (0, _payloads.createStringAdders)(_belSerializer.getAddStringContext, ajaxObfuscator);
|
|
43
53
|
const nodeList = [];
|
|
44
54
|
|
|
45
55
|
// IMPORTANT: The order in which addString is called matters and correlates to the order in which string shows up in the harvest payload. Do not re-order the following code.
|
|
@@ -54,11 +64,32 @@ class AjaxNode extends _belNode.BelNode {
|
|
|
54
64
|
(0, _belSerializer.numeric)(this.callbackDuration),
|
|
55
65
|
// not relative
|
|
56
66
|
addString(this.method), (0, _belSerializer.numeric)(this.status), addString(this.domain), addString(this.path), (0, _belSerializer.numeric)(this.txSize), (0, _belSerializer.numeric)(this.rxSize), this.requestedWith, addString(this.nodeId), (0, _belSerializer.nullable)(this.spanId, addString, true) + (0, _belSerializer.nullable)(this.traceId, addString, true) + (0, _belSerializer.nullable)(this.spanTimestamp, _belSerializer.numeric)];
|
|
57
|
-
|
|
58
|
-
|
|
67
|
+
// Regular attributes: obfuscate only
|
|
68
|
+
const regularAttrs = (0, _belSerializer.addCustomAttributes)({
|
|
69
|
+
[_constants.AJAX_ID]: this[_constants.AJAX_ID],
|
|
59
70
|
...(this.targetAttributes || {}),
|
|
60
|
-
|
|
71
|
+
...(this.gql || {})
|
|
61
72
|
}, addString);
|
|
73
|
+
|
|
74
|
+
// Payload attributes: obfuscate then truncate
|
|
75
|
+
const payloadAttrs = (0, _belSerializer.addCustomAttributes)({
|
|
76
|
+
...(this.requestBody ? {
|
|
77
|
+
requestBody: this.requestBody
|
|
78
|
+
} : {}),
|
|
79
|
+
...(this.requestHeaders ? {
|
|
80
|
+
requestHeaders: this.requestHeaders
|
|
81
|
+
} : {}),
|
|
82
|
+
...(this.requestQuery ? {
|
|
83
|
+
requestQuery: this.requestQuery
|
|
84
|
+
} : {}),
|
|
85
|
+
...(this.responseBody ? {
|
|
86
|
+
responseBody: this.responseBody
|
|
87
|
+
} : {}),
|
|
88
|
+
...(this.responseHeaders ? {
|
|
89
|
+
responseHeaders: this.responseHeaders
|
|
90
|
+
} : {})
|
|
91
|
+
}, addStringWithTruncation);
|
|
92
|
+
let allAttachedNodes = [...regularAttrs, ...payloadAttrs];
|
|
62
93
|
this.children.forEach(node => allAttachedNodes.push(node.serialize())); // no children is expected under ajax nodes at this time
|
|
63
94
|
|
|
64
95
|
fields[1] = (0, _belSerializer.numeric)(allAttachedNodes.length);
|
|
@@ -10,10 +10,12 @@ var _webdriverDetection = require("../../../common/util/webdriver-detection");
|
|
|
10
10
|
var _loadTime = require("../../../common/vitals/load-time");
|
|
11
11
|
var _features = require("../../../loaders/features/features");
|
|
12
12
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
13
|
+
var _obfuscate = require("../../../common/util/obfuscate");
|
|
13
14
|
var _constants = require("../constants");
|
|
14
15
|
var _ajaxNode = require("./ajax-node");
|
|
15
16
|
var _initialPageLoadInteraction = require("./initial-page-load-interaction");
|
|
16
17
|
var _interaction = require("./interaction");
|
|
18
|
+
var _events = require("../../../common/constants/events");
|
|
17
19
|
/**
|
|
18
20
|
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
19
21
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -26,6 +28,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
26
28
|
}) {
|
|
27
29
|
super(agentRef, _constants.FEATURE_NAME);
|
|
28
30
|
super.customAttributesAreSeparate = true;
|
|
31
|
+
|
|
32
|
+
// Create obfuscators for browser interactions and nested AJAX requests
|
|
33
|
+
this.interactionObfuscator = new _obfuscate.Obfuscator(agentRef, _events.EVENT_TYPES.BI);
|
|
34
|
+
this.ajaxObfuscator = new _obfuscate.Obfuscator(agentRef, _events.EVENT_TYPES.AJAX);
|
|
29
35
|
this.interactionsToHarvest = this.events;
|
|
30
36
|
this.domObserver = domObserver;
|
|
31
37
|
this.initialPageLoadInteraction = new _initialPageLoadInteraction.InitialPageLoadInteraction(agentRef);
|
|
@@ -89,7 +95,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
89
95
|
let firstIxnStartTime;
|
|
90
96
|
const serializedIxnList = [];
|
|
91
97
|
for (const interaction of eventBuffer) {
|
|
92
|
-
serializedIxnList.push(interaction.serialize(firstIxnStartTime, this.agentRef));
|
|
98
|
+
serializedIxnList.push(interaction.serialize(firstIxnStartTime, this.agentRef, this.interactionObfuscator, this.ajaxObfuscator));
|
|
93
99
|
if (firstIxnStartTime === undefined) firstIxnStartTime = Math.floor(interaction.start); // careful not to match or overwrite on 0 value!
|
|
94
100
|
}
|
|
95
101
|
return "bel.7;".concat(serializedIxnList.join(';'));
|
|
@@ -11,7 +11,7 @@ var _firstPaint = require("../../../common/vitals/first-paint");
|
|
|
11
11
|
var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
|
|
12
12
|
var _constants = require("../constants");
|
|
13
13
|
/**
|
|
14
|
-
* Copyright 2020-
|
|
14
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
15
15
|
* SPDX-License-Identifier: Apache-2.0
|
|
16
16
|
*/
|
|
17
17
|
|
|
@@ -12,7 +12,7 @@ var _cleanUrl = require("../../../common/url/clean-url");
|
|
|
12
12
|
var _constants = require("../constants");
|
|
13
13
|
var _belNode = require("./bel-node");
|
|
14
14
|
/**
|
|
15
|
-
* Copyright 2020-
|
|
15
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
16
16
|
* SPDX-License-Identifier: Apache-2.0
|
|
17
17
|
*/
|
|
18
18
|
|
|
@@ -127,11 +127,13 @@ class Interaction extends _belNode.BelNode {
|
|
|
127
127
|
* Serializes (BEL) the interaction data for transmission.
|
|
128
128
|
* @param {Number} firstStartTimeOfPayload timestamp
|
|
129
129
|
* @param {Agent} agentRef Pass in the agent reference directly so that the event itself doesnt need to store the pointers and ruin the evaluation of the event size by including unused object references.
|
|
130
|
+
* @param {Obfuscator} interactionObfuscator Obfuscator for BrowserInteraction event type
|
|
131
|
+
* @param {Obfuscator} ajaxObfuscator Obfuscator for AjaxRequest event type (passed to child AjaxNodes)
|
|
130
132
|
* @returns {String} A string that is the serialized representation of this interaction.
|
|
131
133
|
*/
|
|
132
|
-
serialize(firstStartTimeOfPayload, agentRef) {
|
|
134
|
+
serialize(firstStartTimeOfPayload, agentRef, interactionObfuscator, ajaxObfuscator) {
|
|
133
135
|
const isFirstIxnOfPayload = firstStartTimeOfPayload === undefined;
|
|
134
|
-
const addString = (0, _belSerializer.getAddStringContext)(
|
|
136
|
+
const addString = (0, _belSerializer.getAddStringContext)(interactionObfuscator);
|
|
135
137
|
const nodeList = [];
|
|
136
138
|
let ixnType;
|
|
137
139
|
if (this.trigger === _constants.IPL_TRIGGER_NAME) ixnType = _constants.INTERACTION_TYPE.INITIAL_PAGE_LOAD;else if (this.newURL !== this.oldURL) ixnType = _constants.INTERACTION_TYPE.ROUTE_CHANGE;else ixnType = _constants.INTERACTION_TYPE.UNSPECIFIED;
|
|
@@ -157,7 +159,7 @@ class Interaction extends _belNode.BelNode {
|
|
|
157
159
|
/* Querypack encoder+decoder quirkiness:
|
|
158
160
|
- If first ixn node of payload is being processed, its children's start time must be offset by this node's start. (firstStartTime should be undefined.)
|
|
159
161
|
- Else for subsequent ixns in the same payload, we go back to using that first ixn node's start to offset their children's start. */
|
|
160
|
-
this.children.forEach(node => allAttachedNodes.push(node.serialize(isFirstIxnOfPayload ? this.start : firstStartTimeOfPayload, agentRef))); // recursively add the serialized string of every child of this (ixn) bel node
|
|
162
|
+
this.children.forEach(node => allAttachedNodes.push(node.serialize(isFirstIxnOfPayload ? this.start : firstStartTimeOfPayload, agentRef, ajaxObfuscator))); // recursively add the serialized string of every child of this (ixn) bel node
|
|
161
163
|
|
|
162
164
|
fields[1] = (0, _belSerializer.numeric)(allAttachedNodes.length);
|
|
163
165
|
nodeList.push(fields);
|
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.AggregateBase = void 0;
|
|
7
7
|
var _featureBase = require("./feature-base");
|
|
8
8
|
var _drain = require("../../common/drain/drain");
|
|
9
|
-
var _obfuscate = require("../../common/util/obfuscate");
|
|
10
9
|
var _features = require("../../loaders/features/features");
|
|
11
10
|
var _harvester = require("../../common/harvest/harvester");
|
|
12
11
|
var _eventBuffer = require("./event-buffer");
|
|
@@ -183,8 +182,8 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
183
182
|
* This method should run after checkConfiguration, which may reset the agent's info/runtime object that is used here.
|
|
184
183
|
*/
|
|
185
184
|
doOnceForAllAggregate(agentRef) {
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
// Note: obfuscator is now created per-feature for their specific event types
|
|
186
|
+
|
|
188
187
|
if (!agentRef.runtime.harvester) agentRef.runtime.harvester = new _harvester.Harvester(agentRef);
|
|
189
188
|
}
|
|
190
189
|
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
* @property {boolean} [ajax.block_internal] - If true, agent requests going to harvest endpoint are treated as on deny list. In other words, agent will not self-report AJAX.
|
|
12
12
|
* @property {boolean} [ajax.enabled] - Turn on/off the ajax feature (on by default).
|
|
13
13
|
* @property {boolean} [ajax.autoStart] - If true, the agent will automatically start the ajax feature. Otherwise, it will be in a deferred state until the `start` API method is called.
|
|
14
|
+
* @property {('none'|'failures'|'all')} [ajax.capture_payloads] - Controls when AJAX request/response payloads are captured. 'none' = never capture, 'failures' = capture only on errors (4xx, 5xx, network errors, GraphQL errors), 'all' = always capture.
|
|
14
15
|
* @property {Object} [api]
|
|
15
16
|
* @property {Object} [api.register]
|
|
16
17
|
* @property {boolean} [api.register.enabled] - If true, the agent will allow registered children to be sent to the server.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import { FEATURE_FLAGS } from '../../features/generic_events/constants';
|
|
6
|
+
import { CAPTURE_PAYLOAD_SETTINGS } from '../../features/ajax/constants';
|
|
6
7
|
import { isValidSelector } from '../dom/query-selector';
|
|
7
8
|
import { DEFAULT_EXPIRES_MS, DEFAULT_INACTIVE_MS } from '../session/constants';
|
|
8
9
|
import { warn } from '../util/console';
|
|
@@ -51,7 +52,8 @@ const InitModelFn = () => {
|
|
|
51
52
|
deny_list: undefined,
|
|
52
53
|
block_internal: true,
|
|
53
54
|
enabled: true,
|
|
54
|
-
autoStart: true
|
|
55
|
+
autoStart: true,
|
|
56
|
+
capture_payloads: CAPTURE_PAYLOAD_SETTINGS.NONE
|
|
55
57
|
},
|
|
56
58
|
api: {
|
|
57
59
|
register: {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Exposes the version of the agent
|
|
13
13
|
*/
|
|
14
|
-
export const VERSION = "1.
|
|
14
|
+
export const VERSION = "1.317.0";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Exposes the build type of the agent
|
|
@@ -25,4 +25,4 @@ export const BUILD_ENV = "CDN";
|
|
|
25
25
|
export const DIST_METHOD = 'CDN';
|
|
26
26
|
export const RRWEB_PACKAGE_NAME = '@newrelic/rrweb';
|
|
27
27
|
// Babel will inline this with the rrweb (fork) version on CDN builds.
|
|
28
|
-
export const RRWEB_VERSION = "1.1.
|
|
28
|
+
export const RRWEB_VERSION = "^1.1.2";
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
/**
|
|
12
12
|
* Exposes the version of the agent
|
|
13
13
|
*/
|
|
14
|
-
export const VERSION = "1.
|
|
14
|
+
export const VERSION = "1.317.0";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Exposes the build type of the agent
|
|
@@ -26,4 +26,4 @@ export const BUILD_ENV = 'NPM';
|
|
|
26
26
|
export const DIST_METHOD = 'NPM';
|
|
27
27
|
export const RRWEB_PACKAGE_NAME = '@newrelic/rrweb';
|
|
28
28
|
// Babel will inline this with the rrweb (fork) version on NPM dist esm/cjs builds.
|
|
29
|
-
export const RRWEB_VERSION = "1.1.
|
|
29
|
+
export const RRWEB_VERSION = "^1.1.2";
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const EVENT_TYPES = {
|
|
7
|
+
AJAX: 'AjaxRequest',
|
|
8
|
+
PA: 'PageAction',
|
|
9
|
+
UA: 'UserAction',
|
|
10
|
+
BP: 'BrowserPerformance',
|
|
11
|
+
WS: 'WebSocket',
|
|
12
|
+
SPV: 'SecurityPolicyViolation',
|
|
13
|
+
JSE: 'JavaScriptError',
|
|
14
|
+
LOG: 'Log',
|
|
15
|
+
PVE: 'PageView',
|
|
16
|
+
PVT: 'PageViewTiming',
|
|
17
|
+
SR: 'SessionReplay',
|
|
18
|
+
ST: 'SessionTrace',
|
|
19
|
+
BI: 'BrowserInteraction'
|
|
20
|
+
};
|
|
@@ -16,6 +16,7 @@ import { warn } from '../util/console';
|
|
|
16
16
|
import { stringify } from '../util/stringify';
|
|
17
17
|
import { getSubmitMethod, xhr as xhrMethod, xhrFetch as fetchMethod } from '../util/submit-data';
|
|
18
18
|
import { dispatchGlobalEvent } from '../dispatch/global-event';
|
|
19
|
+
import { Obfuscator } from '../util/obfuscate';
|
|
19
20
|
const RETRY = 'Harvester/Retry/';
|
|
20
21
|
const RETRY_ATTEMPTED = RETRY + 'Attempted/';
|
|
21
22
|
const RETRY_FAILED = RETRY + 'Failed/';
|
|
@@ -25,6 +26,10 @@ export class Harvester {
|
|
|
25
26
|
initializedAggregates = [];
|
|
26
27
|
constructor(agentRef) {
|
|
27
28
|
this.agentRef = agentRef;
|
|
29
|
+
|
|
30
|
+
// Create obfuscator for harvest metadata (referrer URL, etc.)
|
|
31
|
+
// No event type specified - applies to all harvests regardless of feature
|
|
32
|
+
this.obfuscator = new Obfuscator(agentRef);
|
|
28
33
|
subscribeToEOL(() => {
|
|
29
34
|
// do one last harvest round or check
|
|
30
35
|
this.initializedAggregates.forEach(aggregateInst => {
|
|
@@ -71,6 +76,7 @@ export class Harvester {
|
|
|
71
76
|
payload: output.payload,
|
|
72
77
|
localOpts,
|
|
73
78
|
submitMethod,
|
|
79
|
+
harvesterObfuscator: this.obfuscator,
|
|
74
80
|
cbFinished,
|
|
75
81
|
raw: aggregateInst.harvestOpts.raw,
|
|
76
82
|
featureName: aggregateInst.featureName,
|
|
@@ -119,7 +125,8 @@ export function send(agentRef, {
|
|
|
119
125
|
cbFinished,
|
|
120
126
|
raw,
|
|
121
127
|
featureName,
|
|
122
|
-
endpointVersion = 1
|
|
128
|
+
endpointVersion = 1,
|
|
129
|
+
harvesterObfuscator
|
|
123
130
|
}) {
|
|
124
131
|
if (!agentRef.info.errorBeacon) return false;
|
|
125
132
|
let {
|
|
@@ -136,7 +143,7 @@ export function send(agentRef, {
|
|
|
136
143
|
const protocol = agentRef.init.ssl === false ? 'http' : 'https';
|
|
137
144
|
const perceivedBeacon = agentRef.init.proxy.beacon || agentRef.info.errorBeacon;
|
|
138
145
|
const url = raw ? "".concat(protocol, "://").concat(perceivedBeacon, "/").concat(endpoint) : "".concat(protocol, "://").concat(perceivedBeacon).concat(endpoint !== RUM ? '/' + endpoint : '', "/").concat(endpointVersion, "/").concat(agentRef.info.licenseKey);
|
|
139
|
-
const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint) : '';
|
|
146
|
+
const baseParams = !raw ? baseQueryString(agentRef, qs, endpoint, harvesterObfuscator) : '';
|
|
140
147
|
let payloadParams = obj(qs, agentRef.runtime.maxBytes);
|
|
141
148
|
if (baseParams === '' && payloadParams.startsWith('&')) {
|
|
142
149
|
payloadParams = payloadParams.substring(1);
|
|
@@ -284,8 +291,9 @@ function cleanPayload(payload = {}) {
|
|
|
284
291
|
}
|
|
285
292
|
|
|
286
293
|
// The stuff that gets sent every time.
|
|
287
|
-
function baseQueryString(agentRef, qs, endpoint) {
|
|
288
|
-
const
|
|
294
|
+
function baseQueryString(agentRef, qs, endpoint, harvesterObfuscator) {
|
|
295
|
+
const cleanedURL = cleanURL('' + globalScope.location);
|
|
296
|
+
const ref = harvesterObfuscator?.obfuscateString(cleanedURL) ?? cleanedURL;
|
|
289
297
|
const session = agentRef.runtime.session;
|
|
290
298
|
const hr = !!session?.state.sessionReplaySentFirstChunk && session?.state.sessionReplayMode === 1 && endpoint !== JSERRORS;
|
|
291
299
|
const ht = !!session?.state.traceHarvestStarted && session?.state.sessionTraceMode === 1 && ![LOGS, BLOBS].includes(endpoint);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { stringify } from '../util/stringify';
|
|
7
|
+
import { CAPTURE_PAYLOAD_SETTINGS } from '../../features/ajax/constants';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Determines whether payload data should be captured based on the capture mode setting,
|
|
11
|
+
* HTTP status code, and GraphQL error status.
|
|
12
|
+
* @param {string} captureMode - The capture mode setting ('none', 'all', or 'failures')
|
|
13
|
+
* @param {number} statusCode - The HTTP status code
|
|
14
|
+
* @param {boolean} hasGQLErrors - Whether the response contains GraphQL errors
|
|
15
|
+
* @returns {boolean} True if payload should be captured
|
|
16
|
+
*/
|
|
17
|
+
export function canCapturePayload(captureMode, statusCode, hasGQLErrors) {
|
|
18
|
+
if (captureMode === CAPTURE_PAYLOAD_SETTINGS.ALL) return true;
|
|
19
|
+
if (!captureMode || captureMode === CAPTURE_PAYLOAD_SETTINGS.NONE) return false;
|
|
20
|
+
|
|
21
|
+
// Default "failures" mode
|
|
22
|
+
return statusCode === 0 || statusCode >= 400 || hasGQLErrors === true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Parses a query string into an object of key-value pairs.
|
|
27
|
+
* @param {string} search a query string starting with "?" or without (ex. new URL(...).search)
|
|
28
|
+
* @returns {Object|undefined} Parsed query parameters as key-value pairs. Returns undefined if no valid parameters are found.
|
|
29
|
+
*/
|
|
30
|
+
export function parseQueryString(search) {
|
|
31
|
+
if (!search || search.length === 0) return;
|
|
32
|
+
const queryParams = {};
|
|
33
|
+
try {
|
|
34
|
+
const searchParams = new URLSearchParams(search);
|
|
35
|
+
searchParams.forEach(function (value, key) {
|
|
36
|
+
queryParams[key] = value;
|
|
37
|
+
});
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// Fallback for environments without URLSearchParams
|
|
40
|
+
}
|
|
41
|
+
return queryParams;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Determines if the given content type is likely to be human-readable (text-based).
|
|
46
|
+
* @param {Object} headers - The headers object containing content-type
|
|
47
|
+
* @param {*} data - The data to check
|
|
48
|
+
* @returns {boolean} True if the content type is human-readable (text-based)
|
|
49
|
+
*/
|
|
50
|
+
export function isLikelyHumanReadable(headers, data) {
|
|
51
|
+
if (!headers) return typeof data === 'string';
|
|
52
|
+
var contentType = headers['content-type'];
|
|
53
|
+
if (!contentType) return typeof data === 'string';
|
|
54
|
+
// Normalize to lowercase and extract the mime type (ignore charset, etc.)
|
|
55
|
+
var mimeType = contentType.toLowerCase().split(';')[0].trim();
|
|
56
|
+
|
|
57
|
+
// Check for text/* types
|
|
58
|
+
if (mimeType.indexOf('text/') === 0) return true;
|
|
59
|
+
|
|
60
|
+
// Check for specific application/* types
|
|
61
|
+
var readableAppTypes = ['/json', '/xml', '/xhtml+xml', '/ld+json', '/yaml', '/x-www-form-urlencoded'];
|
|
62
|
+
for (var i = 0; i < readableAppTypes.length; i++) {
|
|
63
|
+
if (mimeType === 'application' + readableAppTypes[i]) return true;
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Truncates a string to ensure its UTF-8 byte length does not exceed 4092 bytes. If truncation is necessary,
|
|
70
|
+
* the string is cut off at a character boundary to avoid breaking multi-byte characters and " ..." is appended to indicate truncation.
|
|
71
|
+
* If not a string, it is first converted to a string using JSON.stringify.
|
|
72
|
+
* @param {*} data The data to truncate.
|
|
73
|
+
* @returns {string}
|
|
74
|
+
*/
|
|
75
|
+
export function truncateAsString(data) {
|
|
76
|
+
if (!data) return data;
|
|
77
|
+
try {
|
|
78
|
+
if (typeof data !== 'string') data = stringify(data);
|
|
79
|
+
let bytes = 0;
|
|
80
|
+
let i = 0;
|
|
81
|
+
let needsEllipsis = false;
|
|
82
|
+
while (i < data.length) {
|
|
83
|
+
const c = data.charCodeAt(i);
|
|
84
|
+
const charBytes = c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0xD800 || c >= 0xE000 ? 3 : 4;
|
|
85
|
+
if (bytes + charBytes > 4092) {
|
|
86
|
+
needsEllipsis = true;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
bytes += charBytes;
|
|
90
|
+
i += charBytes === 4 ? 2 : 1;
|
|
91
|
+
}
|
|
92
|
+
return data.slice(0, i) + (needsEllipsis ? ' ...' : '');
|
|
93
|
+
} catch (e) {
|
|
94
|
+
return data;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Creates string adder functions for BEL serialization with obfuscation and optional truncation.
|
|
100
|
+
* This ensures a single string table is used while providing separate handling for regular vs payload attributes.
|
|
101
|
+
* @param {Function} getAddStringContext - Function that creates a new string table context
|
|
102
|
+
* @param {Object} obfuscator - Optional obfuscator instance for string obfuscation
|
|
103
|
+
* @returns {{addString: Function, addStringWithTruncation: Function}} Object containing both string adder functions
|
|
104
|
+
*/
|
|
105
|
+
export function createStringAdders(getAddStringContext, obfuscator) {
|
|
106
|
+
const addStringRaw = getAddStringContext();
|
|
107
|
+
const processString = (str, shouldTruncate) => {
|
|
108
|
+
if (typeof str === 'undefined' || str === '') return addStringRaw(str);
|
|
109
|
+
if (typeof str !== 'string') str = stringify(str);
|
|
110
|
+
const obfuscated = obfuscator?.obfuscateString(str) ?? str;
|
|
111
|
+
const processed = shouldTruncate ? truncateAsString(obfuscated) : obfuscated;
|
|
112
|
+
return addStringRaw(processed);
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
addString: str => processString(str, false),
|
|
116
|
+
addStringWithTruncation: str => processString(str, true)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -15,13 +15,14 @@ export function numeric(n, noDefault) {
|
|
|
15
15
|
}
|
|
16
16
|
return n === undefined || n === 0 ? '' : Math.floor(n).toString(36);
|
|
17
17
|
}
|
|
18
|
-
export function getAddStringContext(obfuscator) {
|
|
18
|
+
export function getAddStringContext(obfuscator, truncator) {
|
|
19
19
|
let stringTableIdx = 0;
|
|
20
20
|
const stringTable = Object.prototype.hasOwnProperty.call(Object, 'create') ? Object.create(null) : {};
|
|
21
21
|
return addString;
|
|
22
22
|
function addString(str) {
|
|
23
23
|
if (typeof str === 'undefined' || str === '') return '';
|
|
24
|
-
str = obfuscator
|
|
24
|
+
str = obfuscator?.obfuscateString(String(str)) ?? String(str);
|
|
25
|
+
str = truncator?.(str) ?? str;
|
|
25
26
|
if (hasOwnProp.call(stringTable, str)) {
|
|
26
27
|
return numeric(stringTable[str], true);
|
|
27
28
|
} else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Copyright 2020-
|
|
2
|
+
* Copyright 2020-2026 New Relic, Inc. All rights reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ import { stringify } from './stringify';
|
|
|
12
12
|
* @returns {(number|undefined)} - The size of the data or undefined if size cannot be determined.
|
|
13
13
|
*/
|
|
14
14
|
export function dataSize(data) {
|
|
15
|
-
if (typeof data === 'string'
|
|
15
|
+
if (typeof data === 'string') return data.length;
|
|
16
16
|
if (typeof data !== 'object') return undefined;
|
|
17
17
|
// eslint-disable-next-line
|
|
18
18
|
if (typeof ArrayBuffer !== 'undefined' && data instanceof ArrayBuffer && data.byteLength) return data.byteLength;
|