@newrelic/browser-agent 1.301.0 → 1.302.0-rc.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 +13 -0
- package/dist/cjs/common/config/init-types.js +1 -1
- package/dist/cjs/common/config/init.js +7 -1
- package/dist/cjs/common/config/runtime.js +1 -1
- package/dist/cjs/common/constants/agent-constants.js +11 -2
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +30 -39
- package/dist/cjs/common/util/mfe.js +45 -0
- package/dist/cjs/features/ajax/aggregate/index.js +5 -1
- package/dist/cjs/features/generic_events/aggregate/index.js +9 -8
- package/dist/cjs/features/generic_events/constants.js +3 -1
- package/dist/cjs/features/generic_events/instrument/index.js +38 -32
- package/dist/cjs/features/jserrors/aggregate/index.js +18 -17
- package/dist/cjs/features/logging/aggregate/index.js +19 -15
- package/dist/cjs/features/logging/shared/utils.js +3 -3
- package/dist/cjs/features/page_view_event/aggregate/index.js +3 -33
- package/dist/cjs/features/session_replay/aggregate/index.js +13 -13
- package/dist/cjs/features/session_replay/shared/recorder.js +3 -2
- package/dist/cjs/features/session_trace/aggregate/index.js +0 -2
- package/dist/cjs/features/soft_navigations/aggregate/index.js +1 -2
- package/dist/cjs/features/utils/aggregate-base.js +45 -47
- package/dist/cjs/loaders/api/addPageAction.js +2 -2
- package/dist/cjs/loaders/api/log.js +2 -2
- package/dist/cjs/loaders/api/noticeError.js +2 -2
- package/dist/cjs/loaders/api/register-api-types.js +5 -5
- package/dist/cjs/loaders/api/register.js +80 -97
- package/dist/esm/common/config/init-types.js +1 -1
- package/dist/esm/common/config/init.js +7 -1
- package/dist/esm/common/config/runtime.js +1 -1
- package/dist/esm/common/constants/agent-constants.js +9 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/harvest/harvester.js +30 -39
- package/dist/esm/common/util/mfe.js +38 -0
- package/dist/esm/features/ajax/aggregate/index.js +5 -1
- package/dist/esm/features/generic_events/aggregate/index.js +9 -8
- package/dist/esm/features/generic_events/constants.js +3 -1
- package/dist/esm/features/generic_events/instrument/index.js +38 -32
- package/dist/esm/features/jserrors/aggregate/index.js +18 -17
- package/dist/esm/features/logging/aggregate/index.js +19 -15
- package/dist/esm/features/logging/shared/utils.js +3 -3
- package/dist/esm/features/page_view_event/aggregate/index.js +3 -33
- package/dist/esm/features/session_replay/aggregate/index.js +13 -13
- package/dist/esm/features/session_replay/shared/recorder.js +3 -2
- package/dist/esm/features/session_trace/aggregate/index.js +0 -2
- package/dist/esm/features/soft_navigations/aggregate/index.js +1 -2
- package/dist/esm/features/utils/aggregate-base.js +46 -48
- package/dist/esm/loaders/api/addPageAction.js +2 -2
- package/dist/esm/loaders/api/log.js +2 -2
- package/dist/esm/loaders/api/noticeError.js +2 -2
- package/dist/esm/loaders/api/register-api-types.js +5 -5
- package/dist/esm/loaders/api/register.js +80 -97
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/config/init-types.d.ts +4 -1
- 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/agent-constants.d.ts +7 -4
- package/dist/types/common/constants/agent-constants.d.ts.map +1 -1
- package/dist/types/common/harvest/harvester.d.ts +2 -2
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/common/util/mfe.d.ts +20 -0
- package/dist/types/common/util/mfe.d.ts.map +1 -0
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +2 -2
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/constants.d.ts +1 -0
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +3 -3
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +3 -3
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/shared/utils.d.ts +2 -2
- package/dist/types/features/logging/shared/utils.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -4
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +13 -4
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts +1 -0
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +13 -5
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/loaders/api/addPageAction.d.ts +1 -1
- package/dist/types/loaders/api/addPageAction.d.ts.map +1 -1
- package/dist/types/loaders/api/log.d.ts +1 -1
- package/dist/types/loaders/api/log.d.ts.map +1 -1
- package/dist/types/loaders/api/noticeError.d.ts +1 -1
- package/dist/types/loaders/api/noticeError.d.ts.map +1 -1
- package/dist/types/loaders/api/register-api-types.d.ts +4 -4
- package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
- package/dist/types/loaders/api/register.d.ts +8 -1
- package/dist/types/loaders/api/register.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/common/config/init-types.js +1 -1
- package/src/common/config/init.js +3 -1
- package/src/common/config/runtime.js +1 -1
- package/src/common/constants/agent-constants.js +10 -0
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvester.js +27 -32
- package/src/common/util/mfe.js +35 -0
- package/src/features/ajax/aggregate/index.js +7 -1
- package/src/features/generic_events/aggregate/index.js +9 -8
- package/src/features/generic_events/constants.js +3 -1
- package/src/features/generic_events/instrument/index.js +44 -35
- package/src/features/jserrors/aggregate/index.js +17 -17
- package/src/features/logging/aggregate/index.js +20 -13
- package/src/features/logging/shared/utils.js +3 -3
- package/src/features/page_view_event/aggregate/index.js +3 -28
- package/src/features/session_replay/aggregate/index.js +12 -10
- package/src/features/session_replay/shared/recorder.js +3 -2
- package/src/features/session_trace/aggregate/index.js +0 -2
- package/src/features/soft_navigations/aggregate/index.js +1 -2
- package/src/features/utils/aggregate-base.js +47 -42
- package/src/loaders/api/addPageAction.js +2 -2
- package/src/loaders/api/log.js +2 -2
- package/src/loaders/api/noticeError.js +2 -2
- package/src/loaders/api/register-api-types.js +5 -5
- package/src/loaders/api/register.js +62 -89
- package/dist/cjs/common/util/target.js +0 -34
- package/dist/cjs/features/utils/entity-manager.js +0 -46
- package/dist/cjs/features/utils/event-store-manager.js +0 -174
- package/dist/cjs/loaders/api/register-api.js +0 -165
- package/dist/esm/common/util/target.js +0 -27
- package/dist/esm/features/utils/entity-manager.js +0 -39
- package/dist/esm/features/utils/event-store-manager.js +0 -166
- package/dist/esm/loaders/api/register-api.js +0 -159
- package/dist/types/common/util/target.d.ts +0 -18
- package/dist/types/common/util/target.d.ts.map +0 -1
- package/dist/types/features/utils/entity-manager.d.ts +0 -11
- package/dist/types/features/utils/entity-manager.d.ts.map +0 -1
- package/dist/types/features/utils/event-store-manager.d.ts +0 -85
- package/dist/types/features/utils/event-store-manager.d.ts.map +0 -1
- package/dist/types/loaders/api/register-api.d.ts +0 -14
- package/dist/types/loaders/api/register-api.d.ts.map +0 -1
- package/src/common/util/target.js +0 -27
- package/src/features/utils/entity-manager.js +0 -45
- package/src/features/utils/event-store-manager.js +0 -165
- package/src/loaders/api/register-api.js +0 -152
|
@@ -12,10 +12,10 @@ var _constants = require("../constants");
|
|
|
12
12
|
var _log = require("../shared/log");
|
|
13
13
|
var _utils = require("../shared/utils");
|
|
14
14
|
var _traverse = require("../../../common/util/traverse");
|
|
15
|
-
var _target = require("../../../common/util/target");
|
|
16
15
|
var _constants2 = require("../../../common/session/constants");
|
|
17
16
|
var _constants3 = require("../../session_replay/constants");
|
|
18
17
|
var _featureGates = require("../../utils/feature-gates");
|
|
18
|
+
var _mfe = require("../../../common/util/mfe");
|
|
19
19
|
/**
|
|
20
20
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
21
21
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -26,6 +26,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
26
26
|
constructor(agentRef) {
|
|
27
27
|
super(agentRef, _constants.FEATURE_NAME);
|
|
28
28
|
this.isSessionTrackingEnabled = (0, _featureGates.canEnableSessionTracking)(agentRef.init) && agentRef.runtime.session;
|
|
29
|
+
|
|
30
|
+
/** set up agg-level behaviors specific to this feature */
|
|
31
|
+
this.harvestOpts.raw = true;
|
|
29
32
|
super.customAttributesAreSeparate = true;
|
|
30
33
|
|
|
31
34
|
// 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.
|
|
@@ -36,7 +39,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
36
39
|
if (this.blocked || type !== _constants2.SESSION_EVENT_TYPES.CROSS_TAB) return;
|
|
37
40
|
if (this.loggingMode !== _constants.LOGGING_MODE.OFF && data.loggingMode === _constants.LOGGING_MODE.OFF) this.abort(_constants3.ABORT_REASONS.CROSS_TAB);else this.loggingMode = data.loggingMode;
|
|
38
41
|
});
|
|
39
|
-
this.harvestOpts.raw = true;
|
|
40
42
|
this.waitForFlags(['log']).then(([loggingMode]) => {
|
|
41
43
|
const session = this.agentRef.runtime.session ?? {};
|
|
42
44
|
if (this.loggingMode === _constants.LOGGING_MODE.OFF || session.isNew && loggingMode === _constants.LOGGING_MODE.OFF) {
|
|
@@ -63,10 +65,14 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
63
65
|
loggingMode: this.loggingMode
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
|
-
handleLog(timestamp, message, attributes = {}, level = _constants.LOG_LEVELS.INFO,
|
|
67
|
-
if (!this.agentRef.runtime.entityManager.get(targetEntityGuid)) return (0, _console.warn)(56, this.featureName);
|
|
68
|
+
handleLog(timestamp, message, attributes = {}, level = _constants.LOG_LEVELS.INFO, target) {
|
|
68
69
|
if (this.blocked || !this.loggingMode) return;
|
|
69
70
|
if (!attributes || typeof attributes !== 'object') attributes = {};
|
|
71
|
+
attributes = {
|
|
72
|
+
...attributes,
|
|
73
|
+
/** Specific attributes only supplied if harvesting to endpoint version 2 */
|
|
74
|
+
...(0, _mfe.getVersion2Attributes)(target, this)
|
|
75
|
+
};
|
|
70
76
|
if (typeof level === 'string') level = level.toUpperCase();
|
|
71
77
|
if (!(0, _utils.isValidLogLevel)(level)) return (0, _console.warn)(30, level);
|
|
72
78
|
if (this.loggingMode < (_constants.LOGGING_MODE[level] || Infinity)) {
|
|
@@ -90,10 +96,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
90
96
|
}
|
|
91
97
|
if (typeof message !== 'string' || !message) return (0, _console.warn)(32);
|
|
92
98
|
const log = new _log.Log(Math.floor(this.agentRef.runtime.timeKeeper.correctRelativeTimestamp(timestamp)), message, attributes, level);
|
|
93
|
-
this.events.add(log
|
|
99
|
+
this.events.add(log);
|
|
94
100
|
}
|
|
95
|
-
serializer(eventBuffer
|
|
96
|
-
const target = this.agentRef.runtime.entityManager.get(targetEntityGuid);
|
|
101
|
+
serializer(eventBuffer) {
|
|
97
102
|
const sessionEntity = this.agentRef.runtime.session;
|
|
98
103
|
return [{
|
|
99
104
|
common: {
|
|
@@ -101,19 +106,19 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
101
106
|
attributes: {
|
|
102
107
|
...this.agentRef.info.jsAttributes,
|
|
103
108
|
// user-provided custom attributes
|
|
104
|
-
|
|
105
|
-
|
|
109
|
+
...(this.harvestEndpointVersion === 1 && {
|
|
110
|
+
'entity.guid': this.agentRef.runtime.appMetadata.agents[0].entityGuid,
|
|
111
|
+
appId: this.agentRef.info.applicationID
|
|
112
|
+
}),
|
|
106
113
|
...(sessionEntity && {
|
|
107
114
|
session: sessionEntity.state.value || '0',
|
|
108
115
|
// The session ID that we generate and keep across page loads
|
|
109
|
-
hasReplay: sessionEntity.state.sessionReplayMode === 1
|
|
116
|
+
hasReplay: sessionEntity.state.sessionReplayMode === 1,
|
|
110
117
|
// True if a session replay recording is running
|
|
111
118
|
hasTrace: sessionEntity.state.sessionTraceMode === 1 // True if a session trace recording is running
|
|
112
119
|
}),
|
|
113
120
|
ptid: this.agentRef.runtime.ptid,
|
|
114
121
|
// page trace id
|
|
115
|
-
appId: target.applicationID || this.agentRef.info.applicationID,
|
|
116
|
-
// Application ID from info object,
|
|
117
122
|
standalone: Boolean(this.agentRef.info.sa),
|
|
118
123
|
// copy paste (true) vs APM (false)
|
|
119
124
|
agentVersion: this.agentRef.runtime.version,
|
|
@@ -128,10 +133,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
128
133
|
logs: (0, _traverse.applyFnToProps)(eventBuffer, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')
|
|
129
134
|
}];
|
|
130
135
|
}
|
|
131
|
-
queryStringsBuilder(
|
|
132
|
-
const target = this.agentRef.runtime.entityManager.get(targetEntityGuid);
|
|
136
|
+
queryStringsBuilder() {
|
|
133
137
|
return {
|
|
134
|
-
browser_monitoring_key:
|
|
138
|
+
browser_monitoring_key: this.agentRef.info.licenseKey
|
|
135
139
|
};
|
|
136
140
|
}
|
|
137
141
|
|
|
@@ -20,11 +20,11 @@ var _constants2 = require("../constants");
|
|
|
20
20
|
* @param {string} message - the log message string
|
|
21
21
|
* @param {{[key: string]: *}} customAttributes - The log's custom attributes if any
|
|
22
22
|
* @param {enum} level - the log level enum
|
|
23
|
-
* @param {object=}
|
|
23
|
+
* @param {object=} target - the optional target provided by an api call
|
|
24
24
|
*/
|
|
25
|
-
function bufferLog(ee, message, customAttributes = {}, level = _constants2.LOG_LEVELS.INFO,
|
|
25
|
+
function bufferLog(ee, message, customAttributes = {}, level = _constants2.LOG_LEVELS.INFO, target, timestamp = (0, _now.now)()) {
|
|
26
26
|
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["API/logging/".concat(level.toLowerCase(), "/called")], undefined, _features.FEATURE_NAMES.metrics, ee);
|
|
27
|
-
(0, _handle.handle)(_constants2.LOGGING_EVENT_EMITTER_CHANNEL, [timestamp, message, customAttributes, level,
|
|
27
|
+
(0, _handle.handle)(_constants2.LOGGING_EVENT_EMITTER_CHANNEL, [timestamp, message, customAttributes, level, target], undefined, _features.FEATURE_NAMES.logging, ee);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
@@ -19,8 +19,6 @@ var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
|
|
|
19
19
|
var _now = require("../../../common/timing/now");
|
|
20
20
|
var _timeKeeper = require("../../../common/timing/time-keeper");
|
|
21
21
|
var _traverse = require("../../../common/util/traverse");
|
|
22
|
-
var _registerHandler = require("../../../common/event-emitter/register-handler");
|
|
23
|
-
var _target = require("../../../common/util/target");
|
|
24
22
|
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); }
|
|
25
23
|
/**
|
|
26
24
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
@@ -35,9 +33,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
35
33
|
this.firstByteToWindowLoad = 0; // our "frontend" duration
|
|
36
34
|
this.firstByteToDomContent = 0; // our "dom processing" duration
|
|
37
35
|
|
|
38
|
-
(0, _registerHandler.registerHandler)('send-rum', (customAttibutes, target) => {
|
|
39
|
-
this.sendRum(customAttibutes, target);
|
|
40
|
-
}, this.featureName, this.ee);
|
|
41
36
|
if (!(0, _info.isValid)(agentRef.info)) {
|
|
42
37
|
this.ee.abort();
|
|
43
38
|
return (0, _console.warn)(43);
|
|
@@ -65,7 +60,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
65
60
|
*
|
|
66
61
|
* @param {Function} cb A function to run once the RUM call has finished - Defaults to activateFeatures
|
|
67
62
|
* @param {*} customAttributes custom attributes to attach to the RUM call - Defaults to info.js
|
|
68
|
-
* @param {*} target The target to harvest to
|
|
63
|
+
* @param {*} target The target to harvest to
|
|
69
64
|
*/
|
|
70
65
|
sendRum(customAttributes = this.agentRef.info.jsAttributes, target = {
|
|
71
66
|
licenseKey: this.agentRef.info.licenseKey,
|
|
@@ -128,7 +123,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
128
123
|
this.rumStartTime = (0, _now.now)();
|
|
129
124
|
this.agentRef.runtime.harvester.triggerHarvestFor(this, {
|
|
130
125
|
directSend: {
|
|
131
|
-
|
|
126
|
+
target,
|
|
132
127
|
payload: {
|
|
133
128
|
qs: queryParameters,
|
|
134
129
|
body
|
|
@@ -141,8 +136,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
141
136
|
postHarvestCleanup({
|
|
142
137
|
status,
|
|
143
138
|
responseText,
|
|
144
|
-
xhr
|
|
145
|
-
targetApp
|
|
139
|
+
xhr
|
|
146
140
|
}) {
|
|
147
141
|
const rumEndTime = (0, _now.now)();
|
|
148
142
|
let app, flags;
|
|
@@ -151,14 +145,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
151
145
|
app,
|
|
152
146
|
...flags
|
|
153
147
|
} = JSON.parse(responseText));
|
|
154
|
-
this.processEntities(app.agents, targetApp);
|
|
155
148
|
} catch (error) {
|
|
156
149
|
// wont set entity stuff here, if main agent will later abort, if registered agent, nothing will happen
|
|
157
150
|
(0, _console.warn)(53, error);
|
|
158
151
|
}
|
|
159
|
-
|
|
160
|
-
/** Only run agent-wide side-effects if the harvest was for the main agent */
|
|
161
|
-
if (!(0, _target.isContainerAgentTarget)(targetApp, this.agentRef)) return;
|
|
162
152
|
if (status >= 400 || status === 0) {
|
|
163
153
|
(0, _console.warn)(18, status);
|
|
164
154
|
// Adding retry logic for the rum call will be a separate change; this.blocked will need to be changed since that prevents another triggerHarvestFor()
|
|
@@ -189,25 +179,5 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
189
179
|
this.agentRef.runtime.harvester.startTimer();
|
|
190
180
|
(0, _featureFlags.activateFeatures)(flags, this.agentRef);
|
|
191
181
|
}
|
|
192
|
-
processEntities(entities, targetApp) {
|
|
193
|
-
if (!entities || !targetApp) return;
|
|
194
|
-
entities.forEach(agent => {
|
|
195
|
-
const entityManager = this.agentRef.runtime.entityManager;
|
|
196
|
-
const entityGuid = agent.entityGuid;
|
|
197
|
-
const entity = entityManager.get(entityGuid);
|
|
198
|
-
if (entity) return; // already processed
|
|
199
|
-
|
|
200
|
-
if ((0, _target.isContainerAgentTarget)(targetApp, this.agentRef)) {
|
|
201
|
-
entityManager.setDefaultEntity({
|
|
202
|
-
...targetApp,
|
|
203
|
-
entityGuid
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
entityManager.set(agent.entityGuid, {
|
|
207
|
-
...targetApp,
|
|
208
|
-
entityGuid
|
|
209
|
-
});
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
182
|
}
|
|
213
183
|
exports.Aggregate = Aggregate;
|
|
@@ -40,6 +40,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
40
40
|
this.gzipper = undefined;
|
|
41
41
|
/** populated with the u8 string lib async */
|
|
42
42
|
this.u8 = undefined;
|
|
43
|
+
/** flips to false if the compressor libraries cannot import */
|
|
44
|
+
this.shouldCompress = true;
|
|
43
45
|
|
|
44
46
|
/** set by BCS response */
|
|
45
47
|
this.entitled = false;
|
|
@@ -211,23 +213,22 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
211
213
|
this.gzipper = gzipSync;
|
|
212
214
|
this.u8 = strToU8;
|
|
213
215
|
} catch (err) {
|
|
214
|
-
|
|
216
|
+
this.shouldCompress = false;
|
|
217
|
+
// compressor failed to load, but we can still try to record without compression as a last ditch effort
|
|
215
218
|
}
|
|
216
219
|
}
|
|
217
|
-
makeHarvestPayload(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (this.mode !== _constants2.MODE.FULL || this.blocked) return;
|
|
223
|
-
if (!this.recorder || !this.timeKeeper?.ready || !this.recorder.hasSeenSnapshot) return;
|
|
220
|
+
makeHarvestPayload() {
|
|
221
|
+
if (this.mode !== _constants2.MODE.FULL || this.blocked) return; // harvests should only be made in FULL mode, and not if the feature is blocked
|
|
222
|
+
if (this.shouldCompress && !this.gzipper) return; // if compression is enabled, but the libraries have not loaded, wait for them to load
|
|
223
|
+
if (!this.recorder || !this.timeKeeper?.ready || !(this.recorder.hasSeenSnapshot && this.recorder.hasSeenMeta)) return; // if the recorder or the timekeeper is not ready, or the recorder has not yet seen a snapshot, do not harvest
|
|
224
|
+
|
|
224
225
|
const recorderEvents = this.recorder.getEvents();
|
|
225
226
|
// get the event type and use that to trigger another harvest if needed
|
|
226
227
|
if (!recorderEvents.events.length) return;
|
|
227
228
|
const payload = this.getHarvestContents(recorderEvents);
|
|
228
229
|
if (!payload.body.length) {
|
|
229
230
|
this.recorder.clearBuffer();
|
|
230
|
-
return
|
|
231
|
+
return;
|
|
231
232
|
}
|
|
232
233
|
this.reportSupportabilityMetric('SessionReplay/Harvest/Attempts');
|
|
233
234
|
let len = 0;
|
|
@@ -242,19 +243,18 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
242
243
|
}
|
|
243
244
|
if (len > _agentConstants.MAX_PAYLOAD_SIZE) {
|
|
244
245
|
this.abort(_constants.ABORT_REASONS.TOO_BIG, len);
|
|
245
|
-
return
|
|
246
|
+
return;
|
|
246
247
|
}
|
|
248
|
+
|
|
247
249
|
// TODO -- Gracefully handle the buffer for retries.
|
|
248
250
|
if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this.syncWithSessionManager({
|
|
249
251
|
sessionReplaySentFirstChunk: true
|
|
250
252
|
});
|
|
251
253
|
this.recorder.clearBuffer();
|
|
252
|
-
if (recorderEvents.type === 'preloaded') this.agentRef.runtime.harvester.triggerHarvestFor(this);
|
|
253
|
-
payloadOutput.payload = payload;
|
|
254
254
|
if (!this.agentRef.runtime.session.state.traceHarvestStarted) {
|
|
255
255
|
(0, _console.warn)(59, JSON.stringify(this.agentRef.runtime.session.state));
|
|
256
256
|
}
|
|
257
|
-
return
|
|
257
|
+
return payload;
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
/**
|
|
@@ -49,6 +49,7 @@ class Recorder {
|
|
|
49
49
|
this.backloggedEvents = new _recorderEvents.RecorderEvents(this.shouldFix);
|
|
50
50
|
/** Only set to true once a snapshot node has been processed. Used to block harvests from sending before we know we have a snapshot */
|
|
51
51
|
this.hasSeenSnapshot = false;
|
|
52
|
+
this.hasSeenMeta = false;
|
|
52
53
|
/** Hold on to the last meta node, so that it can be re-inserted if the meta and snapshot nodes are broken up due to harvesting */
|
|
53
54
|
this.lastMeta = false;
|
|
54
55
|
/** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
|
|
@@ -203,9 +204,9 @@ class Recorder {
|
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
// meta event
|
|
206
|
-
this.events.hasMeta ||= event.type === _constants.RRWEB_EVENT_TYPES.Meta;
|
|
207
|
+
this.hasSeenMeta ||= this.events.hasMeta ||= event.type === _constants.RRWEB_EVENT_TYPES.Meta;
|
|
207
208
|
// snapshot event
|
|
208
|
-
this.
|
|
209
|
+
this.hasSeenSnapshot ||= this.events.hasSnapshot ||= event.type === _constants.RRWEB_EVENT_TYPES.FullSnapshot;
|
|
209
210
|
|
|
210
211
|
//* dont let the EventBuffer class double evaluate the event data size, it's a performance burden and we have special reasons to do it outside the event buffer */
|
|
211
212
|
this.events.add(event, eventBytes);
|
|
@@ -98,8 +98,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
98
98
|
sessionTraceMode: this.mode
|
|
99
99
|
});
|
|
100
100
|
this.drain();
|
|
101
|
-
/** try to harvest immediately. This will not send if the trace is not running in FULL mode due to the pre-harvest checks. */
|
|
102
|
-
this.agentRef.runtime.harvester.triggerHarvestFor(this);
|
|
103
101
|
}
|
|
104
102
|
preHarvestChecks() {
|
|
105
103
|
if (this.blocked || this.mode !== _constants2.MODE.FULL) return; // only allow harvest if running in full mode
|
|
@@ -53,7 +53,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
53
53
|
this.waitForFlags(['spa']).then(([spaOn]) => {
|
|
54
54
|
if (spaOn) {
|
|
55
55
|
this.drain();
|
|
56
|
-
setTimeout(() => agentRef.runtime.harvester.triggerHarvestFor(this), 0); // send the IPL ixn on next tick, giving some time for any ajax to finish; we may want to just remove this?
|
|
57
56
|
} else {
|
|
58
57
|
this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
59
58
|
this.deregisterDrain();
|
|
@@ -148,7 +147,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
148
147
|
*/
|
|
149
148
|
if (this.interactionInProgress?.isActiveDuring(timestamp)) return this.interactionInProgress;
|
|
150
149
|
let saveIxn;
|
|
151
|
-
const interactionsBuffer = this.interactionsToHarvest.get()
|
|
150
|
+
const interactionsBuffer = this.interactionsToHarvest.get();
|
|
152
151
|
if (!interactionsBuffer) return undefined; // no interactions have been staged yet, so nothing to search through)
|
|
153
152
|
for (let idx = interactionsBuffer.length - 1; idx >= 0; idx--) {
|
|
154
153
|
// reverse search for the latest completed interaction for efficiency
|
|
@@ -12,10 +12,7 @@ var _drain = require("../../common/drain/drain");
|
|
|
12
12
|
var _featureFlags = require("../../common/util/feature-flags");
|
|
13
13
|
var _obfuscate = require("../../common/util/obfuscate");
|
|
14
14
|
var _features = require("../../loaders/features/features");
|
|
15
|
-
var _eventStoreManager = require("./event-store-manager");
|
|
16
15
|
var _harvester = require("../../common/harvest/harvester");
|
|
17
|
-
var _console = require("../../common/util/console");
|
|
18
|
-
var _entityManager = require("./entity-manager");
|
|
19
16
|
var _eventBuffer = require("./event-buffer");
|
|
20
17
|
var _handle = require("../../common/event-emitter/handle");
|
|
21
18
|
var _constants = require("../metrics/constants");
|
|
@@ -46,16 +43,8 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
46
43
|
this.isRetrying = false;
|
|
47
44
|
this.harvestOpts = {}; // features aggregate classes can define custom opts for when their harvest is called
|
|
48
45
|
|
|
49
|
-
|
|
50
|
-
this
|
|
51
|
-
if (!agentEntityGuid) {
|
|
52
|
-
/** wait for the entity guid from the rum response and use to it to further configure things to set the default entity to share an indexed entity with entityGuid */
|
|
53
|
-
this.ee.on('entity-added', entity => {
|
|
54
|
-
// not all event managers have this fn, like ST and SR
|
|
55
|
-
// this allows the lookup to work for the default and an entityGuid without creating two separate buffers
|
|
56
|
-
this.events?.setEventStore?.(entity.entityGuid);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
46
|
+
this.#setupEventStore();
|
|
47
|
+
this.waitForDrain();
|
|
59
48
|
}
|
|
60
49
|
|
|
61
50
|
/**
|
|
@@ -63,7 +52,7 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
63
52
|
* @param {string} entityGuid
|
|
64
53
|
* @returns {void}
|
|
65
54
|
*/
|
|
66
|
-
#setupEventStore(
|
|
55
|
+
#setupEventStore() {
|
|
67
56
|
if (this.events) return;
|
|
68
57
|
switch (this.featureName) {
|
|
69
58
|
// SessionReplay has its own storage mechanisms.
|
|
@@ -72,19 +61,39 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
72
61
|
// Jserror and Metric features uses a singleton EventAggregator instead of a regular EventBuffer.
|
|
73
62
|
case _features.FEATURE_NAMES.jserrors:
|
|
74
63
|
case _features.FEATURE_NAMES.metrics:
|
|
75
|
-
this.events = this.agentRef.sharedAggregator ??= new
|
|
76
|
-
featureName: 'shared_aggregator'
|
|
77
|
-
});
|
|
64
|
+
this.events = this.agentRef.sharedAggregator ??= new _eventAggregator.EventAggregator();
|
|
78
65
|
break;
|
|
79
|
-
/** All other features get EventBuffer
|
|
66
|
+
/** All other features get EventBuffer by default. Note: PVE is included here, but event buffer will always be empty so future harvests will still not happen by interval or EOL.
|
|
80
67
|
This was necessary to prevent race cond. issues where the event buffer was checked before the feature could "block" itself.
|
|
81
68
|
Its easier to just keep an empty event buffer in place. */
|
|
82
69
|
default:
|
|
83
|
-
this.events = new
|
|
70
|
+
this.events = new _eventBuffer.EventBuffer(_agentConstants.MAX_PAYLOAD_SIZE, this);
|
|
84
71
|
break;
|
|
85
72
|
}
|
|
86
73
|
}
|
|
87
74
|
|
|
75
|
+
/** @type {Boolean} indicates if the feature supports registered entities and the harvest requirements therein. Also read by getter "harvestEndpointVersion". Controlled by feature flag in pre-release phase. */
|
|
76
|
+
get supportsRegisteredEntities() {
|
|
77
|
+
return this.featureName in _agentConstants.SUPPORTS_REGISTERED_ENTITIES && (_agentConstants.SUPPORTS_REGISTERED_ENTITIES[this.featureName] || this.agentRef.init.feature_flags.includes('register.' + this.featureName));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* the endpoint version the feature uses during harvests
|
|
82
|
+
* @type {number}
|
|
83
|
+
* @returns {boolean}
|
|
84
|
+
*/
|
|
85
|
+
get harvestEndpointVersion() {
|
|
86
|
+
return this.supportsRegisteredEntities && !!this.agentRef.runtime.registeredEntities.length ? 2 : 1;
|
|
87
|
+
}
|
|
88
|
+
waitForDrain() {
|
|
89
|
+
/** emitted when the feature successfully drains */
|
|
90
|
+
this.ee.on('drain-' + this.featureName, () => {
|
|
91
|
+
/** make an immediate harvest for all the features to help with harvestability for pre-load dervied data on short lived pages */
|
|
92
|
+
if (!this.drained) setTimeout(() => this.agentRef.runtime.harvester.triggerHarvestFor(this), 1);
|
|
93
|
+
this.drained = true;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
88
97
|
/**
|
|
89
98
|
* Evaluates whether a harvest should be made early by estimating the size of the current payload. Currently, this only happens if the event storage is EventBuffer, since that triggers this method directly.
|
|
90
99
|
* If conditions are met, a new harvest will be triggered immediately.
|
|
@@ -132,7 +141,6 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
132
141
|
*/
|
|
133
142
|
drain() {
|
|
134
143
|
(0, _drain.drain)(this.agentIdentifier, this.featureName);
|
|
135
|
-
this.drained = true;
|
|
136
144
|
}
|
|
137
145
|
preHarvestChecks(opts) {
|
|
138
146
|
return !this.blocked;
|
|
@@ -142,47 +150,38 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
142
150
|
* Return harvest payload. A "serializer" function can be defined on a derived class to format the payload.
|
|
143
151
|
* @param {Boolean} shouldRetryOnFail - harvester flag to backup payload for retry later if harvest request fails; this should be moved to harvester logic
|
|
144
152
|
* @param {object|undefined} opts - opts passed from the harvester to help form the payload
|
|
145
|
-
* @param {string} opts.
|
|
153
|
+
* @param {string} opts.target - the target app metadata
|
|
146
154
|
* @returns {Array} Final payload tagged with their targeting browser app. The value of `payload` can be undefined if there are no pending events for an app. This should be a minimum length of 1.
|
|
147
155
|
*/
|
|
148
156
|
makeHarvestPayload(shouldRetryOnFail = false, opts = {}) {
|
|
149
|
-
if (!this.events || this.events.isEmpty(this.harvestOpts
|
|
157
|
+
if (!this.events || this.events.isEmpty(this.harvestOpts)) return;
|
|
150
158
|
// Other conditions and things to do when preparing harvest that is required.
|
|
151
159
|
if (this.preHarvestChecks && !this.preHarvestChecks(opts)) return;
|
|
152
|
-
if (shouldRetryOnFail) this.events.save(this.harvestOpts
|
|
153
|
-
const
|
|
154
|
-
if (!
|
|
155
|
-
this.events.clear(this.harvestOpts
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// Constructs the payload `qs` for relevant features on harvest.
|
|
166
|
-
if (this.queryStringsBuilder) payload.qs = this.queryStringsBuilder(data, targetApp?.entityGuid);
|
|
167
|
-
return {
|
|
168
|
-
targetApp,
|
|
169
|
-
payload
|
|
170
|
-
};
|
|
171
|
-
});
|
|
160
|
+
if (shouldRetryOnFail) this.events.save(this.harvestOpts);
|
|
161
|
+
const data = this.events.get(this.harvestOpts);
|
|
162
|
+
if (!data) return;
|
|
163
|
+
this.events.clear(this.harvestOpts);
|
|
164
|
+
|
|
165
|
+
// A serializer or formatter assists in creating the payload `body` from stored events on harvest when defined by derived feature class.
|
|
166
|
+
const body = this.serializer ? this.serializer(data) : data;
|
|
167
|
+
const payload = {
|
|
168
|
+
body
|
|
169
|
+
};
|
|
170
|
+
// Constructs the payload `qs` for relevant features on harvest.
|
|
171
|
+
if (this.queryStringsBuilder) payload.qs = this.queryStringsBuilder(data);
|
|
172
|
+
return payload;
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
/**
|
|
175
176
|
* Cleanup task after a harvest.
|
|
176
177
|
* @param {object} result - the cbResult object from the harvester's send method
|
|
177
|
-
* @param {object=} result.targetApp - the target app object that was used to point the harvest to the correct app
|
|
178
|
-
* @param {string=} result.targetApp.entityGuid - the entity guid of the target app
|
|
179
178
|
* @param {boolean=} result.sent - whether the harvest was sent successfully
|
|
180
179
|
* @param {boolean=} result.retry - whether the harvest should be retried
|
|
181
180
|
*/
|
|
182
181
|
postHarvestCleanup(result = {}) {
|
|
183
182
|
this.isRetrying = result.sent && result.retry;
|
|
184
|
-
if (this.isRetrying) this.events.reloadSave(this.harvestOpts
|
|
185
|
-
this.events.clearSave(this.harvestOpts
|
|
183
|
+
if (this.isRetrying) this.events.reloadSave(this.harvestOpts);
|
|
184
|
+
this.events.clearSave(this.harvestOpts);
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
/**
|
|
@@ -222,7 +221,6 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
222
221
|
doOnceForAllAggregate(agentRef) {
|
|
223
222
|
if (!agentRef.runtime.obfuscator) agentRef.runtime.obfuscator = new _obfuscate.Obfuscator(agentRef);
|
|
224
223
|
this.obfuscator = agentRef.runtime.obfuscator;
|
|
225
|
-
if (!agentRef.runtime.entityManager) agentRef.runtime.entityManager = new _entityManager.EntityManager(this.agentRef);
|
|
226
224
|
if (!agentRef.runtime.harvester) agentRef.runtime.harvester = new _harvester.Harvester(agentRef);
|
|
227
225
|
}
|
|
228
226
|
|
|
@@ -18,6 +18,6 @@ var _sharedHandlers = require("./sharedHandlers");
|
|
|
18
18
|
function setupAddPageActionAPI(agent) {
|
|
19
19
|
(0, _sharedHandlers.setupAPI)(_constants.ADD_PAGE_ACTION, (name, attributes) => addPageAction(name, attributes, agent), agent);
|
|
20
20
|
}
|
|
21
|
-
function addPageAction(name, attributes, agentRef,
|
|
22
|
-
(0, _handle.handle)(_constants.prefix + _constants.ADD_PAGE_ACTION, [timestamp, name, attributes,
|
|
21
|
+
function addPageAction(name, attributes, agentRef, target, timestamp = (0, _now.now)()) {
|
|
22
|
+
(0, _handle.handle)(_constants.prefix + _constants.ADD_PAGE_ACTION, [timestamp, name, attributes, target], undefined, _features.FEATURE_NAMES.genericEvents, agentRef.ee);
|
|
23
23
|
}
|
|
@@ -21,6 +21,6 @@ function setupLogAPI(agent) {
|
|
|
21
21
|
function log(message, {
|
|
22
22
|
customAttributes = {},
|
|
23
23
|
level = _constants.LOG_LEVELS.INFO
|
|
24
|
-
} = {}, agentRef,
|
|
25
|
-
(0, _utils.bufferLog)(agentRef.ee, message, customAttributes, level,
|
|
24
|
+
} = {}, agentRef, target, timestamp = (0, _now.now)()) {
|
|
25
|
+
(0, _utils.bufferLog)(agentRef.ee, message, customAttributes, level, target, timestamp);
|
|
26
26
|
}
|
|
@@ -18,8 +18,8 @@ var _sharedHandlers = require("./sharedHandlers");
|
|
|
18
18
|
function setupNoticeErrorAPI(agent) {
|
|
19
19
|
(0, _sharedHandlers.setupAPI)(_constants.NOTICE_ERROR, (err, customAttributes) => noticeError(err, customAttributes, agent), agent);
|
|
20
20
|
}
|
|
21
|
-
function noticeError(err, customAttributes, agentRef,
|
|
21
|
+
function noticeError(err, customAttributes, agentRef, target, timestamp = (0, _now.now)()) {
|
|
22
22
|
if (typeof err === 'string') err = new Error(err);
|
|
23
|
-
(0, _handle.handle)('err', [err, timestamp, false, customAttributes, agentRef.runtime.isRecording, undefined,
|
|
23
|
+
(0, _handle.handle)('err', [err, timestamp, false, customAttributes, agentRef.runtime.isRecording, undefined, target], undefined, _features.FEATURE_NAMES.jserrors, agentRef.ee);
|
|
24
24
|
(0, _handle.handle)('uaErr', [], undefined, _features.FEATURE_NAMES.genericEvents, agentRef.ee);
|
|
25
25
|
}
|
|
@@ -21,15 +21,15 @@ exports.default = void 0;
|
|
|
21
21
|
/**
|
|
22
22
|
* @typedef {Object} RegisterAPIConstructor
|
|
23
23
|
* @property {Object} opts - The options for the registered entity.
|
|
24
|
-
* @property {string} opts.
|
|
25
|
-
* @property {string} opts.
|
|
24
|
+
* @property {string} opts.id - The unique id for the registered entity. This will be assigned to any synthesized entities.
|
|
25
|
+
* @property {string} opts.name - The readable name for the registered entity. This will be assigned to any synthesized entities.
|
|
26
26
|
*/
|
|
27
27
|
/**
|
|
28
28
|
* @typedef {Object} RegisterAPIMetadata
|
|
29
29
|
* @property {Object} customAttributes - The custom attributes for the registered entity.
|
|
30
30
|
* @property {Object} target - The options for the registered entity.
|
|
31
|
-
* @property {string} target.licenseKey - The license key for the registered entity.
|
|
32
|
-
* @property {string} target.
|
|
33
|
-
* @property {string} target.
|
|
31
|
+
* @property {string} target.licenseKey - The license key for the registered entity. If none was supplied, it will assume the license key from the main agent.
|
|
32
|
+
* @property {string} target.id - The ID for the registered entity.
|
|
33
|
+
* @property {string} target.name - The name returned for the registered entity.
|
|
34
34
|
*/
|
|
35
35
|
var _default = exports.default = {};
|