@newrelic/browser-agent 1.271.0 → 1.273.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/aggregate/aggregator.js +23 -30
- package/dist/cjs/common/aggregate/event-aggregator.js +84 -0
- package/dist/cjs/common/config/init.js +8 -4
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvest-scheduler.js +1 -1
- package/dist/cjs/common/harvest/harvest.js +1 -5
- package/dist/cjs/common/harvest/types.js +0 -1
- package/dist/cjs/features/ajax/aggregate/index.js +52 -62
- package/dist/cjs/features/generic_events/aggregate/index.js +57 -36
- package/dist/cjs/features/generic_events/instrument/index.js +1 -1
- package/dist/cjs/features/jserrors/aggregate/index.js +23 -69
- package/dist/cjs/features/logging/aggregate/index.js +52 -59
- package/dist/cjs/features/metrics/aggregate/index.js +8 -5
- package/dist/cjs/features/page_view_timing/aggregate/index.js +8 -25
- package/dist/cjs/features/session_replay/aggregate/index.js +11 -10
- package/dist/cjs/features/session_replay/shared/recorder-events.js +2 -2
- package/dist/cjs/features/session_trace/aggregate/index.js +77 -88
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +22 -13
- package/dist/cjs/features/soft_navigations/aggregate/index.js +10 -20
- package/dist/cjs/features/soft_navigations/instrument/index.js +5 -9
- package/dist/cjs/features/spa/aggregate/index.js +10 -26
- package/dist/cjs/features/utils/aggregate-base.js +37 -0
- package/dist/cjs/features/utils/event-buffer.js +36 -87
- package/dist/cjs/features/utils/instrument-base.js +3 -3
- package/dist/cjs/loaders/features/features.js +13 -1
- package/dist/esm/common/aggregate/aggregator.js +23 -30
- package/dist/esm/common/aggregate/event-aggregator.js +78 -0
- package/dist/esm/common/config/init.js +8 -4
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +1 -1
- package/dist/esm/common/harvest/harvest.js +1 -5
- package/dist/esm/common/harvest/types.js +0 -1
- package/dist/esm/features/ajax/aggregate/index.js +53 -62
- package/dist/esm/features/generic_events/aggregate/index.js +57 -36
- package/dist/esm/features/generic_events/instrument/index.js +1 -1
- package/dist/esm/features/jserrors/aggregate/index.js +24 -70
- package/dist/esm/features/logging/aggregate/index.js +52 -59
- package/dist/esm/features/metrics/aggregate/index.js +8 -5
- package/dist/esm/features/page_view_timing/aggregate/index.js +9 -26
- package/dist/esm/features/session_replay/aggregate/index.js +12 -11
- package/dist/esm/features/session_replay/shared/recorder-events.js +2 -2
- package/dist/esm/features/session_trace/aggregate/index.js +77 -88
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +22 -13
- package/dist/esm/features/soft_navigations/aggregate/index.js +11 -21
- package/dist/esm/features/soft_navigations/instrument/index.js +5 -9
- package/dist/esm/features/spa/aggregate/index.js +11 -27
- package/dist/esm/features/utils/aggregate-base.js +37 -0
- package/dist/esm/features/utils/event-buffer.js +36 -88
- package/dist/esm/features/utils/instrument-base.js +3 -3
- package/dist/esm/loaders/features/features.js +12 -0
- package/dist/types/common/aggregate/aggregator.d.ts +4 -6
- package/dist/types/common/aggregate/aggregator.d.ts.map +1 -1
- package/dist/types/common/aggregate/event-aggregator.d.ts +26 -0
- package/dist/types/common/aggregate/event-aggregator.d.ts.map +1 -0
- package/dist/types/common/config/init.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/harvest/types.d.ts +1 -4
- package/dist/types/common/harvest/types.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +2 -10
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +5 -11
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +4 -7
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +10 -28
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -9
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +3 -4
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder-events.d.ts +1 -1
- package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +17 -19
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +10 -6
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +3 -9
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +2 -3
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +14 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/event-buffer.d.ts +19 -56
- package/dist/types/features/utils/event-buffer.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +3 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/common/aggregate/aggregator.js +22 -32
- package/src/common/aggregate/event-aggregator.js +76 -0
- package/src/common/config/init.js +6 -2
- package/src/common/harvest/harvest-scheduler.js +1 -1
- package/src/common/harvest/harvest.js +1 -5
- package/src/common/harvest/types.js +0 -1
- package/src/features/ajax/aggregate/index.js +60 -67
- package/src/features/generic_events/aggregate/index.js +48 -38
- package/src/features/generic_events/instrument/index.js +2 -0
- package/src/features/jserrors/aggregate/index.js +21 -77
- package/src/features/logging/aggregate/index.js +46 -60
- package/src/features/metrics/aggregate/index.js +6 -4
- package/src/features/page_view_timing/aggregate/index.js +9 -30
- package/src/features/session_replay/aggregate/index.js +10 -14
- package/src/features/session_replay/shared/recorder-events.js +2 -2
- package/src/features/session_trace/aggregate/index.js +64 -73
- package/src/features/session_trace/aggregate/trace/storage.js +25 -14
- package/src/features/soft_navigations/aggregate/index.js +11 -22
- package/src/features/soft_navigations/instrument/index.js +6 -9
- package/src/features/spa/aggregate/index.js +12 -27
- package/src/features/utils/aggregate-base.js +39 -0
- package/src/features/utils/event-buffer.js +36 -83
- package/src/features/utils/instrument-base.js +3 -3
- package/src/loaders/features/features.js +13 -0
- package/dist/cjs/features/ajax/aggregate/chunk.js +0 -51
- package/dist/esm/features/ajax/aggregate/chunk.js +0 -44
- package/dist/types/features/ajax/aggregate/chunk.d.ts +0 -8
- package/dist/types/features/ajax/aggregate/chunk.d.ts.map +0 -1
- package/src/features/ajax/aggregate/chunk.js +0 -52
|
@@ -16,7 +16,6 @@ var _runtime = require("../../../common/constants/runtime");
|
|
|
16
16
|
var _constants = require("../constants");
|
|
17
17
|
var _features = require("../../../loaders/features/features");
|
|
18
18
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
19
|
-
var _nreum = require("../../../common/window/nreum");
|
|
20
19
|
var _now = require("../../../common/timing/now");
|
|
21
20
|
var _traverse = require("../../../common/util/traverse");
|
|
22
21
|
var _internalErrors = require("./internal-errors");
|
|
@@ -38,7 +37,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
38
37
|
this.observedAt = {};
|
|
39
38
|
this.pageviewReported = {};
|
|
40
39
|
this.bufferedErrorsUnderSpa = {};
|
|
41
|
-
this.currentBody = undefined;
|
|
42
40
|
this.errorOnPage = false;
|
|
43
41
|
|
|
44
42
|
// this will need to change to match whatever ee we use in the instrument
|
|
@@ -48,14 +46,19 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
48
46
|
(0, _registerHandler.registerHandler)('softNavFlush', (interactionId, wasFinished, softNavAttrs) => this.onSoftNavNotification(interactionId, wasFinished, softNavAttrs), this.featureName, this.ee); // when an ixn is done or cancelled
|
|
49
47
|
|
|
50
48
|
const harvestTimeSeconds = agentRef.init.jserrors.harvestTimeSeconds || 10;
|
|
49
|
+
const aggregatorTypes = ['err', 'ierr', 'xhr']; // the types in EventAggregator this feature cares about
|
|
51
50
|
|
|
52
51
|
// 0 == off, 1 == on
|
|
53
52
|
this.waitForFlags(['err']).then(([errFlag]) => {
|
|
54
53
|
if (errFlag) {
|
|
55
|
-
const scheduler = new _harvestScheduler.HarvestScheduler(
|
|
56
|
-
onFinished:
|
|
54
|
+
const scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
|
|
55
|
+
onFinished: result => this.postHarvestCleanup(result.sent && result.retry, {
|
|
56
|
+
aggregatorTypes
|
|
57
|
+
})
|
|
57
58
|
}, this);
|
|
58
|
-
scheduler.harvest.on(
|
|
59
|
+
scheduler.harvest.on(_features.FEATURE_TO_ENDPOINT[this.featureName], options => this.makeHarvestPayload(options.retry, {
|
|
60
|
+
aggregatorTypes
|
|
61
|
+
}));
|
|
59
62
|
scheduler.startTimer(harvestTimeSeconds);
|
|
60
63
|
this.drain();
|
|
61
64
|
} else {
|
|
@@ -64,49 +67,22 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
64
67
|
}
|
|
65
68
|
});
|
|
66
69
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
qs: {}
|
|
76
|
-
};
|
|
77
|
-
var releaseIds = (0, _stringify.stringify)(this.agentRef.runtime.releaseIds);
|
|
78
|
-
if (releaseIds !== '{}') {
|
|
79
|
-
payload.qs.ri = releaseIds;
|
|
80
|
-
}
|
|
81
|
-
if (body && body.err && body.err.length) {
|
|
82
|
-
this.#runCrossFeatureChecks(body.err);
|
|
70
|
+
serializer(aggregatorTypeToBucketsMap) {
|
|
71
|
+
return (0, _traverse.applyFnToProps)(aggregatorTypeToBucketsMap, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string');
|
|
72
|
+
}
|
|
73
|
+
queryStringsBuilder(aggregatorTakeReturnedData) {
|
|
74
|
+
const qs = {};
|
|
75
|
+
const releaseIds = (0, _stringify.stringify)(this.agentRef.runtime.releaseIds);
|
|
76
|
+
if (releaseIds !== '{}') qs.ri = releaseIds;
|
|
77
|
+
if (aggregatorTakeReturnedData?.err?.length) {
|
|
83
78
|
if (!this.errorOnPage) {
|
|
84
|
-
|
|
79
|
+
qs.pve = '1';
|
|
85
80
|
this.errorOnPage = true;
|
|
86
81
|
}
|
|
82
|
+
// For assurance, erase any `hasReplay` flag from all errors if replay is not recording, not-yet imported, or not running at all.
|
|
83
|
+
if (!this.agentRef.features?.[_features.FEATURE_NAMES.sessionReplay]?.featAggregate?.replayIsActive()) aggregatorTakeReturnedData.err.forEach(error => delete error.params.hasReplay);
|
|
87
84
|
}
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
onHarvestFinished(result) {
|
|
91
|
-
if (result.retry && this.currentBody) {
|
|
92
|
-
Object.entries(this.currentBody || {}).forEach(([key, value]) => {
|
|
93
|
-
for (var i = 0; i < value.length; i++) {
|
|
94
|
-
var bucket = value[i];
|
|
95
|
-
var name = this.getBucketName(key, bucket.params, bucket.custom);
|
|
96
|
-
this.agentRef.sharedAggregator.merge(key, name, bucket.metrics, bucket.params, bucket.custom);
|
|
97
|
-
}
|
|
98
|
-
});
|
|
99
|
-
this.currentBody = null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
nameHash(params) {
|
|
103
|
-
return (0, _stringHashCode.stringHashCode)("".concat(params.exceptionClass, "_").concat(params.message, "_").concat(params.stack_trace || params.browser_stack_hash));
|
|
104
|
-
}
|
|
105
|
-
getBucketName(objType, params, customParams) {
|
|
106
|
-
if (objType === 'xhr') {
|
|
107
|
-
return (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(params)) + ':' + (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(customParams));
|
|
108
|
-
}
|
|
109
|
-
return this.nameHash(params) + ':' + (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(customParams));
|
|
85
|
+
return qs;
|
|
110
86
|
}
|
|
111
87
|
|
|
112
88
|
/**
|
|
@@ -213,7 +189,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
213
189
|
params._interactionId = err.__newrelic[this.agentIdentifier].interactionId;
|
|
214
190
|
params._interactionNodeId = err.__newrelic[this.agentIdentifier].interactionNodeId;
|
|
215
191
|
}
|
|
216
|
-
const softNavInUse = Boolean(
|
|
192
|
+
const softNavInUse = Boolean(this.agentRef.features?.[_features.FEATURE_NAMES.softNav]);
|
|
217
193
|
// Note: the following are subject to potential race cond wherein if the other feature aren't fully initialized, it'll be treated as there being no associated interaction.
|
|
218
194
|
// They each will also tack on their respective properties to the params object as part of the decision flow.
|
|
219
195
|
if (softNavInUse) (0, _handle.handle)('jserror', [params, time], undefined, _features.FEATURE_NAMES.softNav, this.ee);else (0, _handle.handle)('spa-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.spa, this.ee);
|
|
@@ -248,7 +224,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
248
224
|
|
|
249
225
|
const jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
|
|
250
226
|
const aggregateHash = bucketHash + ':' + jsAttributesHash;
|
|
251
|
-
this.
|
|
227
|
+
this.events.add(type, aggregateHash, params, newMetrics, allCustomAttrs);
|
|
252
228
|
function setCustom(key, val) {
|
|
253
229
|
allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
|
|
254
230
|
}
|
|
@@ -272,7 +248,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
272
248
|
var hash = wasSaved ? item[1] + interaction.root.attrs.id : item[1];
|
|
273
249
|
var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
|
|
274
250
|
var aggregateHash = hash + ':' + jsAttributesHash;
|
|
275
|
-
this.
|
|
251
|
+
this.events.add(item[0], aggregateHash, params, item[3], allCustomAttrs);
|
|
276
252
|
function setCustom([key, val]) {
|
|
277
253
|
allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
|
|
278
254
|
}
|
|
@@ -285,27 +261,5 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
285
261
|
);
|
|
286
262
|
delete this.bufferedErrorsUnderSpa[interactionId]; // wipe the list of jserrors so they aren't duplicated by another call to the same id
|
|
287
263
|
}
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Dispatches a cross-feature communication event to allow other
|
|
291
|
-
* features to provide flags and data that can be used to mutation
|
|
292
|
-
* to the payload and to allow features to know about a feature
|
|
293
|
-
* harvest happening.
|
|
294
|
-
* @param {any[]} errors Array of errors from the payload body
|
|
295
|
-
*/
|
|
296
|
-
#runCrossFeatureChecks(errors) {
|
|
297
|
-
const errorHashes = errors.map(error => error.params.stackHash);
|
|
298
|
-
const crossFeatureData = {
|
|
299
|
-
errorHashes
|
|
300
|
-
};
|
|
301
|
-
this.ee.emit("cfc.".concat(this.featureName), [crossFeatureData]);
|
|
302
|
-
let hasReplayFlag = errors.find(err => err.params.hasReplay);
|
|
303
|
-
if (hasReplayFlag && !crossFeatureData.hasReplay) {
|
|
304
|
-
// Some errors have `hasReplay` and a replay is not being recorded
|
|
305
|
-
errors.forEach(error => {
|
|
306
|
-
delete error.params.hasReplay;
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
264
|
}
|
|
311
265
|
exports.Aggregate = Aggregate;
|
|
@@ -16,20 +16,17 @@ var _log = require("../shared/log");
|
|
|
16
16
|
var _utils = require("../shared/utils");
|
|
17
17
|
var _traverse = require("../../../common/util/traverse");
|
|
18
18
|
var _agentConstants = require("../../../common/constants/agent-constants");
|
|
19
|
-
var
|
|
19
|
+
var _features = require("../../../loaders/features/features");
|
|
20
20
|
class Aggregate extends _aggregateBase.AggregateBase {
|
|
21
21
|
static featureName = _constants2.FEATURE_NAME;
|
|
22
22
|
constructor(agentRef) {
|
|
23
23
|
super(agentRef, _constants2.FEATURE_NAME);
|
|
24
|
-
|
|
25
|
-
/** held logs before sending */
|
|
26
|
-
this.bufferedLogs = new _eventBuffer.EventBuffer();
|
|
27
24
|
this.harvestTimeSeconds = agentRef.init.logging.harvestTimeSeconds;
|
|
28
25
|
this.waitForFlags([]).then(() => {
|
|
29
|
-
this.scheduler = new _harvestScheduler.HarvestScheduler(
|
|
30
|
-
onFinished: this.
|
|
26
|
+
this.scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
|
|
27
|
+
onFinished: result => this.postHarvestCleanup(result.sent && result.retry),
|
|
31
28
|
retryDelay: this.harvestTimeSeconds,
|
|
32
|
-
getPayload: this.
|
|
29
|
+
getPayload: options => this.makeHarvestPayload(options.retry),
|
|
33
30
|
raw: true
|
|
34
31
|
}, this);
|
|
35
32
|
/** emitted by instrument class (wrapped loggers) or the api methods directly */
|
|
@@ -62,64 +59,60 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
62
59
|
const log = new _log.Log(Math.floor(this.agentRef.runtime.timeKeeper.correctRelativeTimestamp(timestamp)), message, attributes, level);
|
|
63
60
|
const logBytes = log.message.length + (0, _stringify.stringify)(log.attributes).length + log.level.length + 10; // timestamp == 10 chars
|
|
64
61
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} else {
|
|
71
|
-
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Failed/Seen', logBytes]);
|
|
72
|
-
(0, _console.warn)(31, log.message.slice(0, 25) + '...');
|
|
73
|
-
}
|
|
62
|
+
const failToHarvestMessage = 'Logging/Harvest/Failed/Seen';
|
|
63
|
+
if (logBytes > _agentConstants.MAX_PAYLOAD_SIZE) {
|
|
64
|
+
// cannot possibly send this, even with an empty buffer
|
|
65
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
|
|
66
|
+
(0, _console.warn)(31, log.message.slice(0, 25) + '...');
|
|
74
67
|
return;
|
|
75
68
|
}
|
|
76
|
-
this.
|
|
69
|
+
if (this.events.wouldExceedMaxSize(logBytes)) {
|
|
70
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['Logging/Harvest/Early/Seen', this.events.bytes + logBytes]);
|
|
71
|
+
this.scheduler.runHarvest(); // force a harvest to try adding again
|
|
72
|
+
}
|
|
73
|
+
if (!this.events.add(log)) {
|
|
74
|
+
// still failed after a harvest attempt despite not being too large would mean harvest failed with options.retry
|
|
75
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, [failToHarvestMessage, logBytes]);
|
|
76
|
+
(0, _console.warn)(31, log.message.slice(0, 25) + '...');
|
|
77
|
+
}
|
|
77
78
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
qs: {
|
|
89
|
-
browser_monitoring_key: this.agentRef.info.licenseKey
|
|
90
|
-
},
|
|
91
|
-
body: [{
|
|
92
|
-
common: {
|
|
93
|
-
/** Attributes in the `common` section are added to `all` logs generated in the payload */
|
|
94
|
-
attributes: {
|
|
95
|
-
'entity.guid': this.agentRef.runtime.appMetadata?.agents?.[0]?.entityGuid,
|
|
96
|
-
// browser entity guid as provided from RUM response
|
|
97
|
-
session: this.agentRef.runtime.session?.state.value || '0',
|
|
79
|
+
serializer(eventBuffer) {
|
|
80
|
+
const sessionEntity = this.agentRef.runtime.session;
|
|
81
|
+
return [{
|
|
82
|
+
common: {
|
|
83
|
+
/** Attributes in the `common` section are added to `all` logs generated in the payload */
|
|
84
|
+
attributes: {
|
|
85
|
+
'entity.guid': this.agentRef.runtime.appMetadata?.agents?.[0]?.entityGuid,
|
|
86
|
+
// browser entity guid as provided from RUM response
|
|
87
|
+
...(sessionEntity && {
|
|
88
|
+
session: sessionEntity.state.value || '0',
|
|
98
89
|
// The session ID that we generate and keep across page loads
|
|
99
|
-
hasReplay:
|
|
90
|
+
hasReplay: sessionEntity.state.sessionReplayMode === 1,
|
|
100
91
|
// True if a session replay recording is running
|
|
101
|
-
hasTrace:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
92
|
+
hasTrace: sessionEntity.state.sessionTraceMode === 1 // True if a session trace recording is running
|
|
93
|
+
}),
|
|
94
|
+
ptid: this.agentRef.runtime.ptid,
|
|
95
|
+
// page trace id
|
|
96
|
+
appId: this.agentRef.info.applicationID,
|
|
97
|
+
// Application ID from info object,
|
|
98
|
+
standalone: Boolean(this.agentRef.info.sa),
|
|
99
|
+
// copy paste (true) vs APM (false)
|
|
100
|
+
agentVersion: this.agentRef.runtime.version,
|
|
101
|
+
// browser agent version
|
|
102
|
+
// The following 3 attributes are evaluated and dropped at ingest processing time and do not get stored on NRDB:
|
|
103
|
+
'instrumentation.provider': 'browser',
|
|
104
|
+
'instrumentation.version': this.agentRef.runtime.version,
|
|
105
|
+
'instrumentation.name': this.agentRef.runtime.loaderType
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
/** logs section contains individual unique log entries */
|
|
109
|
+
logs: (0, _traverse.applyFnToProps)(eventBuffer, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')
|
|
110
|
+
}];
|
|
120
111
|
}
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
queryStringsBuilder() {
|
|
113
|
+
return {
|
|
114
|
+
browser_monitoring_key: this.agentRef.info.licenseKey
|
|
115
|
+
};
|
|
123
116
|
}
|
|
124
117
|
}
|
|
125
118
|
exports.Aggregate = Aggregate;
|
|
@@ -13,6 +13,7 @@ var _load = require("../../../common/window/load");
|
|
|
13
13
|
var _eventListenerOpts = require("../../../common/event-listener/event-listener-opts");
|
|
14
14
|
var _runtime = require("../../../common/constants/runtime");
|
|
15
15
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
16
|
+
var _features = require("../../../loaders/features/features");
|
|
16
17
|
var _iframe = require("../../../common/dom/iframe");
|
|
17
18
|
// import { WEBSOCKET_TAG } from '../../../common/wrap/wrap-websocket'
|
|
18
19
|
// import { handleWebsocketEvents } from './websocket-detection'
|
|
@@ -21,15 +22,17 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
21
22
|
static featureName = _constants.FEATURE_NAME;
|
|
22
23
|
constructor(agentRef) {
|
|
23
24
|
super(agentRef, _constants.FEATURE_NAME);
|
|
25
|
+
const aggregatorTypes = ['cm', 'sm']; // the types in EventAggregator this feature cares about
|
|
26
|
+
|
|
24
27
|
this.waitForFlags(['err']).then(([errFlag]) => {
|
|
25
28
|
if (errFlag) {
|
|
26
29
|
// *cli, Mar 23 - Per NR-94597, this feature should only harvest ONCE at the (potential) EoL time of the page.
|
|
27
|
-
const scheduler = new _harvestScheduler.HarvestScheduler(
|
|
30
|
+
const scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
|
|
28
31
|
onUnload: () => this.unload()
|
|
29
32
|
}, this);
|
|
30
33
|
// this is needed to ensure EoL is "on" and sent
|
|
31
|
-
scheduler.harvest.on(
|
|
32
|
-
|
|
34
|
+
scheduler.harvest.on(_features.FEATURE_TO_ENDPOINT[this.featureName], () => this.makeHarvestPayload(undefined, {
|
|
35
|
+
aggregatorTypes
|
|
33
36
|
}));
|
|
34
37
|
this.drain();
|
|
35
38
|
} else {
|
|
@@ -50,7 +53,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
50
53
|
const params = {
|
|
51
54
|
name
|
|
52
55
|
};
|
|
53
|
-
this.
|
|
56
|
+
this.events.addMetric(type, name, params, value);
|
|
54
57
|
}
|
|
55
58
|
storeEventMetrics(name, metrics) {
|
|
56
59
|
if (this.blocked) return;
|
|
@@ -58,7 +61,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
58
61
|
const params = {
|
|
59
62
|
name
|
|
60
63
|
};
|
|
61
|
-
this.
|
|
64
|
+
this.events.add(type, name, params, metrics);
|
|
62
65
|
}
|
|
63
66
|
singleChecks() {
|
|
64
67
|
// report loaderType
|
|
@@ -20,7 +20,6 @@ var _largestContentfulPaint = require("../../../common/vitals/largest-contentful
|
|
|
20
20
|
var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
|
|
21
21
|
var _pageVisibility = require("../../../common/window/page-visibility");
|
|
22
22
|
var _constants2 = require("../../../common/vitals/constants");
|
|
23
|
-
var _eventBuffer = require("../../utils/event-buffer");
|
|
24
23
|
/*
|
|
25
24
|
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
26
25
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -37,7 +36,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
37
36
|
};
|
|
38
37
|
constructor(agentRef) {
|
|
39
38
|
super(agentRef, _constants.FEATURE_NAME);
|
|
40
|
-
this.timings = new _eventBuffer.EventBuffer();
|
|
41
39
|
this.curSessEndRecorded = false;
|
|
42
40
|
(0, _registerHandler.registerHandler)('docHidden', msTimestamp => this.endCurrentSession(msTimestamp), this.featureName, this.ee);
|
|
43
41
|
// Add the time of _window pagehide event_ firing to the next PVT harvest == NRDB windowUnload attr:
|
|
@@ -69,9 +67,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
69
67
|
this.addTiming(name, value * 1000, attrs);
|
|
70
68
|
}, true); // CLS node should only reports on vis change rather than on every change
|
|
71
69
|
|
|
72
|
-
const scheduler = new _harvestScheduler.HarvestScheduler(
|
|
73
|
-
onFinished:
|
|
74
|
-
getPayload:
|
|
70
|
+
const scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
|
|
71
|
+
onFinished: result => this.postHarvestCleanup(result.sent && result.retry),
|
|
72
|
+
getPayload: options => this.makeHarvestPayload(options.retry)
|
|
75
73
|
}, this);
|
|
76
74
|
scheduler.startTimer(harvestTimeSeconds);
|
|
77
75
|
this.drain();
|
|
@@ -104,16 +102,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
104
102
|
if (name !== _constants2.VITAL_NAMES.CUMULATIVE_LAYOUT_SHIFT && _cumulativeLayoutShift.cumulativeLayoutShift.current.value >= 0) {
|
|
105
103
|
attrs.cls = _cumulativeLayoutShift.cumulativeLayoutShift.current.value;
|
|
106
104
|
}
|
|
107
|
-
this.
|
|
105
|
+
this.events.add({
|
|
108
106
|
name,
|
|
109
107
|
value,
|
|
110
108
|
attrs
|
|
111
109
|
});
|
|
112
110
|
(0, _handle.handle)('pvtAdded', [name, value, attrs], undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
|
|
113
111
|
}
|
|
114
|
-
onHarvestFinished(result) {
|
|
115
|
-
if (result.retry && this.timings.held.hasData) this.timings.unhold();else this.timings.held.clear();
|
|
116
|
-
}
|
|
117
112
|
appendGlobalCustomAttributes(timing) {
|
|
118
113
|
var timingAttributes = timing.attrs || {};
|
|
119
114
|
var reservedAttributes = ['size', 'eid', 'cls', 'type', 'fid', 'elTag', 'elUrl', 'net-type', 'net-etype', 'net-rtt', 'net-dlink'];
|
|
@@ -124,24 +119,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
124
119
|
});
|
|
125
120
|
}
|
|
126
121
|
|
|
127
|
-
// serialize and return current timing data, clear and save current data for retry
|
|
128
|
-
prepareHarvest(options) {
|
|
129
|
-
if (!this.timings.hasData) return;
|
|
130
|
-
var payload = this.getPayload(this.timings.buffer);
|
|
131
|
-
if (options.retry) this.timings.hold();else this.timings.clear();
|
|
132
|
-
return {
|
|
133
|
-
body: {
|
|
134
|
-
e: payload
|
|
135
|
-
}
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
122
|
// serialize array of timing data
|
|
140
|
-
|
|
123
|
+
serializer(eventBuffer) {
|
|
141
124
|
var addString = (0, _belSerializer.getAddStringContext)(this.agentIdentifier);
|
|
142
125
|
var payload = 'bel.6;';
|
|
143
|
-
for (var i = 0; i <
|
|
144
|
-
var timing =
|
|
126
|
+
for (var i = 0; i < eventBuffer.length; i++) {
|
|
127
|
+
var timing = eventBuffer[i];
|
|
145
128
|
payload += 'e,';
|
|
146
129
|
payload += addString(timing.name) + ',';
|
|
147
130
|
payload += (0, _belSerializer.nullable)(timing.value, _belSerializer.numeric, false) + ',';
|
|
@@ -150,7 +133,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
150
133
|
if (attrParts && attrParts.length > 0) {
|
|
151
134
|
payload += (0, _belSerializer.numeric)(attrParts.length) + ';' + attrParts.join(';');
|
|
152
135
|
}
|
|
153
|
-
if (i + 1 <
|
|
136
|
+
if (i + 1 < eventBuffer.length) payload += ';';
|
|
154
137
|
}
|
|
155
138
|
return payload;
|
|
156
139
|
}
|
|
@@ -55,9 +55,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
55
55
|
this.recorder = args?.recorder;
|
|
56
56
|
this.errorNoticed = args?.errorNoticed || false;
|
|
57
57
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/Enabled'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
58
|
-
this.ee.on("cfc.".concat(_features.FEATURE_NAMES.jserrors), crossFeatureData => {
|
|
59
|
-
crossFeatureData.hasReplay = !!(this.scheduler?.started && this.recorder && this.mode === _constants3.MODE.FULL && !this.blocked && this.entitled);
|
|
60
|
-
});
|
|
61
58
|
|
|
62
59
|
// The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
|
|
63
60
|
this.ee.on(_constants3.SESSION_EVENTS.RESET, () => {
|
|
@@ -83,10 +80,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
83
80
|
});
|
|
84
81
|
|
|
85
82
|
// Bespoke logic for blobs endpoint.
|
|
86
|
-
this.scheduler = new _harvestScheduler.HarvestScheduler(
|
|
87
|
-
onFinished: this.
|
|
83
|
+
this.scheduler = new _harvestScheduler.HarvestScheduler(_features.FEATURE_TO_ENDPOINT[this.featureName], {
|
|
84
|
+
onFinished: result => this.postHarvestCleanup(result),
|
|
88
85
|
retryDelay: this.harvestTimeSeconds,
|
|
89
|
-
getPayload:
|
|
86
|
+
getPayload: ({
|
|
87
|
+
retry,
|
|
88
|
+
...opts
|
|
89
|
+
}) => this.makeHarvestPayload(retry, opts),
|
|
90
90
|
raw: true
|
|
91
91
|
}, this);
|
|
92
92
|
(0, _registerHandler.registerHandler)(_constants.SR_EVENT_EMITTER_TYPES.PAUSE, () => {
|
|
@@ -135,6 +135,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
135
135
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/SamplingRate/Value', sampling_rate], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
136
136
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/ErrorSamplingRate/Value', error_sampling_rate], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
137
137
|
}
|
|
138
|
+
replayIsActive() {
|
|
139
|
+
return Boolean(this.scheduler?.started && this.recorder && this.mode === _constants3.MODE.FULL && !this.blocked && this.entitled);
|
|
140
|
+
}
|
|
138
141
|
handleError(e) {
|
|
139
142
|
if (this.recorder) this.recorder.currentBufferTarget.hasError = true;
|
|
140
143
|
// run once
|
|
@@ -242,9 +245,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
242
245
|
// compressor failed to load, but we can still record without compression as a last ditch effort
|
|
243
246
|
}
|
|
244
247
|
}
|
|
245
|
-
|
|
246
|
-
opts
|
|
247
|
-
} = {}) {
|
|
248
|
+
makeHarvestPayload(shouldRetryOnFail, opts) {
|
|
248
249
|
if (!this.recorder || !this.timeKeeper?.ready || !this.recorder.hasSeenSnapshot) return;
|
|
249
250
|
const recorderEvents = this.recorder.getEvents();
|
|
250
251
|
// get the event type and use that to trigger another harvest if needed
|
|
@@ -380,7 +381,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
380
381
|
body: events
|
|
381
382
|
};
|
|
382
383
|
}
|
|
383
|
-
|
|
384
|
+
postHarvestCleanup(result) {
|
|
384
385
|
// The mutual decision for now is to stop recording and clear buffers if ingest is experiencing 429 rate limiting
|
|
385
386
|
if (result.status === 429) {
|
|
386
387
|
this.abort(_constants.ABORT_REASONS.TOO_MANY);
|
|
@@ -27,12 +27,12 @@ class RecorderEvents {
|
|
|
27
27
|
this.#events.add(event);
|
|
28
28
|
}
|
|
29
29
|
get events() {
|
|
30
|
-
return this.#events.
|
|
30
|
+
return this.#events.get();
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/** A value which increments with every new mutation node reported. Resets after a harvest is sent */
|
|
34
34
|
get payloadBytesEstimation() {
|
|
35
|
-
return this.#events.
|
|
35
|
+
return this.#events.byteSize();
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
exports.RecorderEvents = RecorderEvents;
|