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