@newrelic/browser-agent 1.258.1 → 1.259.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 +14 -0
- package/README.md +3 -4
- package/dist/cjs/cdn/polyfills.js +3 -1
- 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/harvest-scheduler.js +4 -2
- package/dist/cjs/features/ajax/constants.js +3 -2
- package/dist/cjs/features/jserrors/aggregate/index.js +4 -2
- package/dist/cjs/features/metrics/aggregate/index.js +0 -8
- package/dist/cjs/features/page_view_event/aggregate/index.js +1 -1
- package/dist/cjs/features/session_replay/aggregate/index.js +31 -36
- package/dist/cjs/features/session_replay/constants.js +5 -2
- package/dist/cjs/features/session_replay/instrument/index.js +53 -13
- package/dist/cjs/features/session_replay/shared/utils.js +3 -5
- package/dist/cjs/features/session_trace/aggregate/index.js +181 -527
- package/dist/cjs/features/session_trace/aggregate/trace/node.js +19 -0
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +289 -0
- package/dist/cjs/features/session_trace/constants.js +3 -2
- package/dist/cjs/features/session_trace/instrument/index.js +7 -3
- package/dist/cjs/features/utils/aggregate-base.js +1 -0
- package/dist/cjs/features/utils/feature-gates.js +17 -0
- package/dist/cjs/features/utils/instrument-base.js +2 -1
- package/dist/cjs/loaders/agent-base.js +4 -0
- package/dist/cjs/loaders/api/api-methods.js +1 -1
- package/dist/cjs/loaders/api/api.js +2 -2
- package/dist/cjs/loaders/configure/configure.js +1 -0
- package/dist/esm/cdn/polyfills.js +3 -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/harvest-scheduler.js +4 -2
- package/dist/esm/features/ajax/constants.js +2 -1
- package/dist/esm/features/jserrors/aggregate/index.js +4 -2
- package/dist/esm/features/metrics/aggregate/index.js +0 -8
- package/dist/esm/features/page_view_event/aggregate/index.js +1 -1
- package/dist/esm/features/session_replay/aggregate/index.js +32 -37
- package/dist/esm/features/session_replay/constants.js +4 -1
- package/dist/esm/features/session_replay/instrument/index.js +54 -14
- package/dist/esm/features/session_replay/shared/utils.js +4 -6
- package/dist/esm/features/session_trace/aggregate/index.js +182 -527
- package/dist/esm/features/session_trace/aggregate/trace/node.js +12 -0
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +282 -0
- package/dist/esm/features/session_trace/constants.js +2 -1
- package/dist/esm/features/session_trace/instrument/index.js +7 -3
- package/dist/esm/features/utils/aggregate-base.js +1 -0
- package/dist/esm/features/utils/feature-gates.js +11 -0
- package/dist/esm/features/utils/instrument-base.js +3 -2
- package/dist/esm/loaders/agent-base.js +4 -0
- package/dist/esm/loaders/api/api-methods.js +1 -1
- package/dist/esm/loaders/api/api.js +2 -2
- package/dist/esm/loaders/configure/configure.js +1 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts +1 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/features/ajax/constants.d.ts +1 -0
- package/dist/types/features/ajax/constants.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/constants.d.ts +3 -0
- package/dist/types/features/session_replay/instrument/index.d.ts +0 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +39 -52
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/trace/node.d.ts +12 -0
- package/dist/types/features/session_trace/aggregate/trace/node.d.ts.map +1 -0
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts +43 -0
- package/dist/types/features/session_trace/aggregate/trace/storage.d.ts.map +1 -0
- package/dist/types/features/session_trace/constants.d.ts +1 -0
- package/dist/types/features/session_trace/constants.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +1 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/feature-gates.d.ts +2 -0
- package/dist/types/features/utils/feature-gates.d.ts.map +1 -0
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +1 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdn/polyfills.js +2 -0
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvest-scheduler.js +4 -2
- package/src/features/ajax/constants.js +2 -0
- package/src/features/jserrors/aggregate/index.js +4 -2
- package/src/features/metrics/aggregate/index.js +0 -8
- package/src/features/page_view_event/aggregate/index.js +1 -1
- package/src/features/session_replay/aggregate/index.js +30 -39
- package/src/features/session_replay/constants.js +4 -0
- package/src/features/session_replay/instrument/index.js +48 -8
- package/src/features/session_replay/shared/__mocks__/utils.js +0 -1
- package/src/features/session_replay/shared/utils.js +4 -7
- package/src/features/session_trace/aggregate/index.js +157 -493
- package/src/features/session_trace/aggregate/trace/node.js +12 -0
- package/src/features/session_trace/aggregate/trace/storage.js +287 -0
- package/src/features/session_trace/constants.js +1 -0
- package/src/features/session_trace/instrument/index.js +7 -2
- package/src/features/utils/__mocks__/feature-gates.js +1 -0
- package/src/features/utils/aggregate-base.js +1 -0
- package/src/features/utils/feature-gates.js +11 -0
- package/src/features/utils/instrument-base.js +3 -2
- package/src/loaders/agent-base.js +4 -0
- package/src/loaders/api/api-methods.js +1 -1
- package/src/loaders/api/api.js +2 -2
- package/src/loaders/configure/configure.js +1 -0
- package/dist/cjs/features/session_replay/shared/replay-mode.js +0 -28
- package/dist/cjs/features/utils/handler-cache.js +0 -70
- package/dist/esm/features/session_replay/shared/replay-mode.js +0 -23
- package/dist/esm/features/utils/handler-cache.js +0 -63
- package/dist/types/features/session_replay/shared/replay-mode.d.ts +0 -9
- package/dist/types/features/session_replay/shared/replay-mode.d.ts.map +0 -1
- package/dist/types/features/utils/handler-cache.d.ts +0 -23
- package/dist/types/features/utils/handler-cache.d.ts.map +0 -1
- package/src/features/session_replay/shared/replay-mode.js +0 -23
- package/src/features/utils/handler-cache.js +0 -65
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
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.259.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.258.2...v1.259.0) (2024-05-08)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Migrate Session Traces to Use Blob Consumer with Feature Flags ([#821](https://github.com/newrelic/newrelic-browser-agent/issues/821)) ([55b0e00](https://github.com/newrelic/newrelic-browser-agent/commit/55b0e00e9d8dce6d0cdbed978a98302d40123f3d))
|
|
12
|
+
|
|
13
|
+
## [1.258.2](https://github.com/newrelic/newrelic-browser-agent/compare/v1.258.1...v1.258.2) (2024-05-07)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* Prevent noticeError() API from running if not given an argument ([#1021](https://github.com/newrelic/newrelic-browser-agent/issues/1021)) ([c023a53](https://github.com/newrelic/newrelic-browser-agent/commit/c023a53c20a9f0f2472e1ba5ff78eb7210a906fa))
|
|
19
|
+
|
|
6
20
|
## [1.258.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.258.0...v1.258.1) (2024-05-07)
|
|
7
21
|
|
|
8
22
|
|
package/README.md
CHANGED
|
@@ -82,6 +82,7 @@ The following features may be disabled by adding `init` entries as shown above.
|
|
|
82
82
|
- `metrics`
|
|
83
83
|
- `page_action`
|
|
84
84
|
- `page_view_timing`
|
|
85
|
+
- `session_replay`
|
|
85
86
|
- `session_trace`
|
|
86
87
|
- `spa`
|
|
87
88
|
|
|
@@ -186,9 +187,7 @@ Please see our [official documentation](https://docs.newrelic.com/docs/browser/n
|
|
|
186
187
|
```
|
|
187
188
|
|
|
188
189
|
## Session Replay
|
|
189
|
-
The Session Replay feature is
|
|
190
|
-
|
|
191
|
-
Due to the sensitive nature of the feature, Session Replay has many configuration options, which are configurable in each browser application's *Application Settings* page on the New Relic site. These settings will only be accessible if you are participating in the limited preview. Additionally, you can control the sampling rates, obfuscation conditions and triggering rules of Session Replay.
|
|
190
|
+
The Session Replay feature is now available for limited free use by all customers. The data collected by this feature will become billable starting May 15th, 2024. Please see the [Session Replay documentation](https://docs.newrelic.com/docs/browser/browser-monitoring/browser-pro-features/session-replay/) to get started using this new feature.
|
|
192
191
|
|
|
193
192
|
## Supported browsers
|
|
194
193
|
|
|
@@ -239,7 +238,7 @@ A lot of new frameworks support the concept of server-side rendering the pages o
|
|
|
239
238
|
|
|
240
239
|
## Disclaimers
|
|
241
240
|
|
|
242
|
-
The session replay library shipping
|
|
241
|
+
The session replay library shipping as part of the browser agent is not turned on by default. For information on the use of this feature, see [Session Replay](#session-replay)
|
|
243
242
|
|
|
244
243
|
## Support
|
|
245
244
|
|
|
@@ -7,6 +7,7 @@ require("core-js/stable/array/flat");
|
|
|
7
7
|
require("core-js/stable/array/flat-map");
|
|
8
8
|
require("core-js/stable/array/from");
|
|
9
9
|
require("core-js/stable/array/some");
|
|
10
|
+
require("core-js/stable/array/find-index");
|
|
10
11
|
require("core-js/stable/object/assign");
|
|
11
12
|
require("core-js/stable/object/entries");
|
|
12
13
|
require("core-js/stable/object/values");
|
|
@@ -19,4 +20,5 @@ require("core-js/stable/object/get-own-property-descriptors");
|
|
|
19
20
|
require("core-js/stable/url");
|
|
20
21
|
require("core-js/stable/url-search-params");
|
|
21
22
|
require("core-js/stable/string/starts-with");
|
|
22
|
-
require("core-js/stable/number/is-nan");
|
|
23
|
+
require("core-js/stable/number/is-nan");
|
|
24
|
+
require("core-js/stable/string/includes");
|
|
@@ -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.259.0";
|
|
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.259.0";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the build type of the agent
|
|
@@ -83,7 +83,7 @@ function drain() {
|
|
|
83
83
|
function checkCanDrainAll(agentIdentifier) {
|
|
84
84
|
// Only when the event-groups for all features are ready to drain (staged) do we execute the drain. This has the effect
|
|
85
85
|
// that the last feature to call drain triggers drain for all features.
|
|
86
|
-
const items =
|
|
86
|
+
const items = Array.from(registry[agentIdentifier]);
|
|
87
87
|
if (items.every(_ref => {
|
|
88
88
|
let [key, values] = _ref;
|
|
89
89
|
return values.staged;
|
|
@@ -38,7 +38,7 @@ class HarvestScheduler extends _sharedContext.SharedContext {
|
|
|
38
38
|
this.started = false;
|
|
39
39
|
this.timeoutHandle = null;
|
|
40
40
|
this.aborted = false; // this controls the per-interval and final harvests for the scheduler (currently per feature specific!)
|
|
41
|
-
|
|
41
|
+
this.harvesting = false;
|
|
42
42
|
this.harvest = new _harvest.Harvest(this.sharedContext);
|
|
43
43
|
|
|
44
44
|
// unload if EOL mechanism fires
|
|
@@ -89,12 +89,14 @@ class HarvestScheduler extends _sharedContext.SharedContext {
|
|
|
89
89
|
}
|
|
90
90
|
runHarvest(opts) {
|
|
91
91
|
if (this.aborted) return;
|
|
92
|
+
this.harvesting = true;
|
|
92
93
|
|
|
93
94
|
/**
|
|
94
95
|
* This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
|
|
95
96
|
* @param {Object} result
|
|
96
97
|
*/
|
|
97
98
|
const cbRanAfterSend = result => {
|
|
99
|
+
this.harvesting = false;
|
|
98
100
|
if (opts?.forceNoRetry) result.retry = false; // discard unsent data rather than re-queuing for next harvest attempt
|
|
99
101
|
this.onHarvestFinished(opts, result);
|
|
100
102
|
};
|
|
@@ -110,7 +112,7 @@ class HarvestScheduler extends _sharedContext.SharedContext {
|
|
|
110
112
|
const retry = !opts?.unload && submitMethod === submitData.xhr;
|
|
111
113
|
payload = this.opts.getPayload({
|
|
112
114
|
retry,
|
|
113
|
-
opts
|
|
115
|
+
...opts
|
|
114
116
|
});
|
|
115
117
|
if (!payload) {
|
|
116
118
|
if (this.started) {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.FEATURE_NAME = void 0;
|
|
6
|
+
exports.MAX_PAYLOAD_SIZE = exports.FEATURE_NAME = void 0;
|
|
7
7
|
var _features = require("../../loaders/features/features");
|
|
8
|
-
const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.ajax;
|
|
8
|
+
const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.ajax;
|
|
9
|
+
const MAX_PAYLOAD_SIZE = exports.MAX_PAYLOAD_SIZE = 1000000;
|
|
@@ -140,6 +140,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
140
140
|
return canonicalStackString;
|
|
141
141
|
}
|
|
142
142
|
storeError(err, time, internal, customAttributes, hasReplay) {
|
|
143
|
+
if (!err) return;
|
|
143
144
|
// are we in an interaction
|
|
144
145
|
time = time || (0, _now.now)();
|
|
145
146
|
const agentRuntime = (0, _config.getRuntime)(this.agentIdentifier);
|
|
@@ -197,12 +198,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
197
198
|
time
|
|
198
199
|
};
|
|
199
200
|
|
|
200
|
-
//
|
|
201
|
+
// sr, stn and spa aggregators listen to this event - stn sends the error in its payload,
|
|
202
|
+
// and spa annotates the error with interaction info
|
|
201
203
|
const jsErrorEvent = [type, bucketHash, params, newMetrics, customAttributes];
|
|
202
204
|
(0, _handle.handle)('trace-jserror', jsErrorEvent, undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
|
|
203
205
|
// still send EE events for other features such as above, but stop this one from aggregating internal data
|
|
204
206
|
if (this.blocked) return;
|
|
205
|
-
if (err
|
|
207
|
+
if (err?.__newrelic?.[this.agentIdentifier]) {
|
|
206
208
|
params._interactionId = err.__newrelic[this.agentIdentifier].interactionId;
|
|
207
209
|
params._interactionNodeId = err.__newrelic[this.agentIdentifier].interactionNodeId;
|
|
208
210
|
}
|
|
@@ -124,8 +124,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
124
124
|
if (this.resourcesSent) return;
|
|
125
125
|
this.resourcesSent = true; // make sure this only gets sent once
|
|
126
126
|
|
|
127
|
-
const agentRuntime = (0, _config.getRuntime)(this.agentIdentifier);
|
|
128
|
-
|
|
129
127
|
// Capture SMs around network resources using the performance API to assess
|
|
130
128
|
// work to split this out from the ST nodes
|
|
131
129
|
// differentiate between internal+external and ajax+non-ajax
|
|
@@ -146,12 +144,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
146
144
|
}
|
|
147
145
|
});
|
|
148
146
|
|
|
149
|
-
// Capture SMs for session trace if active (`ptid` is set when returned by replay ingest).
|
|
150
|
-
// Retain these SMs while we are working through the session_replay feature
|
|
151
|
-
if (agentRuntime.ptid) {
|
|
152
|
-
this.storeSupportabilityMetrics('PageSession/Feature/SessionTrace/DurationMs', Math.round(performance.now()));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
147
|
// Capture SMs for performance markers and measures to assess the usage and possible inclusion of this
|
|
156
148
|
// data in the agent for use in NR
|
|
157
149
|
if (typeof performance !== 'undefined') {
|
|
@@ -150,7 +150,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
150
150
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
151
151
|
(0, _drain.drain)(this.agentIdentifier, _features.FEATURE_NAMES.metrics, true);
|
|
152
152
|
this.ee.abort();
|
|
153
|
-
(0, _console.warn)('Could not calculate New Relic server time. Agent shutting down.');
|
|
153
|
+
(0, _console.warn)('Could not calculate New Relic server time. Agent shutting down.', error);
|
|
154
154
|
return;
|
|
155
155
|
}
|
|
156
156
|
try {
|
|
@@ -96,15 +96,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
96
96
|
getPayload: this.prepareHarvest.bind(this),
|
|
97
97
|
raw: true
|
|
98
98
|
}, this);
|
|
99
|
-
(0, _registerHandler.registerHandler)(_constants.SR_EVENT_EMITTER_TYPES.RECORD, () => {
|
|
100
|
-
// if it has aborted or BCS returned bad entitlements, do not allow
|
|
101
|
-
if (this.blocked || !this.entitled) return;
|
|
102
|
-
// if it isnt already (fully) initialized... initialize it
|
|
103
|
-
if (!this.recorder) this.initializeRecording(false, true, true);
|
|
104
|
-
// its been initialized and imported the recorder but its not recording (mode === off || error)
|
|
105
|
-
else if (this.mode !== _constants3.MODE.FULL) this.switchToFull();
|
|
106
|
-
// if it gets all the way to here, that means a full session is already recording... do nothing
|
|
107
|
-
}, this.featureName, this.ee);
|
|
108
99
|
(0, _registerHandler.registerHandler)(_constants.SR_EVENT_EMITTER_TYPES.PAUSE, () => {
|
|
109
100
|
this.forceStop(this.mode !== _constants3.MODE.ERROR);
|
|
110
101
|
}, this.featureName, this.ee);
|
|
@@ -122,9 +113,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
122
113
|
inline_images,
|
|
123
114
|
collect_fonts
|
|
124
115
|
} = (0, _config.getConfigurationValue)(this.agentIdentifier, 'session_replay');
|
|
125
|
-
this.waitForFlags(['sr']).then(_ref => {
|
|
126
|
-
let [
|
|
127
|
-
this.entitled =
|
|
116
|
+
this.waitForFlags(['srs', 'sr']).then(_ref => {
|
|
117
|
+
let [srMode, entitled] = _ref;
|
|
118
|
+
this.entitled = !!entitled;
|
|
128
119
|
if (!this.entitled) {
|
|
129
120
|
(0, _drain.deregisterDrain)(this.agentIdentifier, this.featureName);
|
|
130
121
|
if (this.recorder?.recording) {
|
|
@@ -134,11 +125,14 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
134
125
|
return;
|
|
135
126
|
}
|
|
136
127
|
this.drain();
|
|
137
|
-
this.initializeRecording(
|
|
128
|
+
this.initializeRecording(srMode);
|
|
138
129
|
}).then(() => {
|
|
139
|
-
if (this.mode === _constants3.MODE.OFF)
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
if (this.mode === _constants3.MODE.OFF) {
|
|
131
|
+
this.recorder?.stopRecording(); // stop any conservative preload recording launched by instrument
|
|
132
|
+
while (this.recorder?.getEvents().events.length) this.recorder?.clearBuffer?.();
|
|
133
|
+
}
|
|
134
|
+
_sharedChannel.sharedChannel.onReplayReady(this.mode);
|
|
135
|
+
}); // notify watchers that replay started with the mode
|
|
142
136
|
|
|
143
137
|
/** Detect if the default configs have been altered and report a SM. This is useful to evaluate what the reasonable defaults are across a customer base over time */
|
|
144
138
|
if (!autoStart) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/AutoStart/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
@@ -181,7 +175,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
181
175
|
* @param {boolean} ignoreSession - whether to force the method to ignore the session state and use just the sample flags
|
|
182
176
|
* @returns {void}
|
|
183
177
|
*/
|
|
184
|
-
async initializeRecording(
|
|
178
|
+
async initializeRecording(srMode, ignoreSession) {
|
|
185
179
|
this.initialized = true;
|
|
186
180
|
if (!this.entitled) return;
|
|
187
181
|
|
|
@@ -196,23 +190,17 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
196
190
|
timeKeeper
|
|
197
191
|
} = (0, _config.getRuntime)(this.agentIdentifier);
|
|
198
192
|
this.timeKeeper = timeKeeper;
|
|
199
|
-
if (
|
|
193
|
+
if (this.recorder?.parent.trigger === _constants.TRIGGERS.API && this.recorder?.recording) {
|
|
194
|
+
this.mode = _constants3.MODE.FULL;
|
|
195
|
+
} else if (!session.isNew && !ignoreSession) {
|
|
200
196
|
// inherit the mode of the existing session
|
|
201
197
|
this.mode = session.state.sessionReplayMode;
|
|
202
198
|
} else {
|
|
203
199
|
// The session is new... determine the mode the new session should start in
|
|
204
|
-
|
|
205
|
-
else if (errorSample) this.mode = _constants3.MODE.ERROR;
|
|
206
|
-
// If neither are selected, then don't record (early return)
|
|
207
|
-
else {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
if (this.recorder?.getEvents().type === 'preloaded') {
|
|
212
|
-
this.prepUtils().then(() => {
|
|
213
|
-
this.scheduler.runHarvest();
|
|
214
|
-
});
|
|
200
|
+
this.mode = srMode;
|
|
215
201
|
}
|
|
202
|
+
// If off, then don't record (early return)
|
|
203
|
+
if (this.mode === _constants3.MODE.OFF) return;
|
|
216
204
|
if (!this.recorder) {
|
|
217
205
|
try {
|
|
218
206
|
// Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
|
|
@@ -230,13 +218,20 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
230
218
|
|
|
231
219
|
// If an error was noticed before the mode could be set (like in the early lifecycle of the page), immediately set to FULL mode
|
|
232
220
|
if (this.mode === _constants3.MODE.ERROR && this.errorNoticed) this.mode = _constants3.MODE.FULL;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
221
|
+
if (this.mode === _constants3.MODE.FULL) {
|
|
222
|
+
// If theres preloaded events and we are in full mode, just harvest immediately to clear up space and for consistency
|
|
223
|
+
if (this.recorder?.getEvents().type === 'preloaded') {
|
|
224
|
+
this.prepUtils().then(() => {
|
|
225
|
+
this.scheduler.runHarvest();
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
// FULL mode records AND reports from the beginning, while ERROR mode only records (but does not report).
|
|
229
|
+
// ERROR mode will do this until an error is thrown, and then switch into FULL mode.
|
|
230
|
+
// If an error happened in ERROR mode before we've gotten to this stage, it will have already set the mode to FULL
|
|
231
|
+
if (!this.scheduler.started) {
|
|
232
|
+
// We only report (harvest) in FULL mode
|
|
233
|
+
this.scheduler.startTimer(this.harvestTimeSeconds);
|
|
234
|
+
}
|
|
240
235
|
}
|
|
241
236
|
await this.prepUtils();
|
|
242
237
|
if (!this.recorder.recording) this.recorder.startRecording();
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.SR_EVENT_EMITTER_TYPES = exports.RRWEB_EVENT_TYPES = exports.QUERY_PARAM_PADDING = exports.MAX_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = exports.FEATURE_NAME = exports.CHECKOUT_MS = exports.AVG_COMPRESSION = exports.ABORT_REASONS = void 0;
|
|
6
|
+
exports.TRIGGERS = exports.SR_EVENT_EMITTER_TYPES = exports.RRWEB_EVENT_TYPES = exports.QUERY_PARAM_PADDING = exports.MAX_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = exports.FEATURE_NAME = exports.CHECKOUT_MS = exports.AVG_COMPRESSION = exports.ABORT_REASONS = void 0;
|
|
7
7
|
var _constants = require("../../common/session/constants");
|
|
8
8
|
var _features = require("../../loaders/features/features");
|
|
9
9
|
const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.sessionReplay;
|
|
@@ -59,4 +59,7 @@ const ABORT_REASONS = exports.ABORT_REASONS = {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
/** Reserved room for query param attrs */
|
|
62
|
-
const QUERY_PARAM_PADDING = exports.QUERY_PARAM_PADDING = 5000;
|
|
62
|
+
const QUERY_PARAM_PADDING = exports.QUERY_PARAM_PADDING = 5000;
|
|
63
|
+
const TRIGGERS = exports.TRIGGERS = {
|
|
64
|
+
API: 'api'
|
|
65
|
+
};
|
|
@@ -7,8 +7,8 @@ exports.Instrument = void 0;
|
|
|
7
7
|
var _handle = require("../../../common/event-emitter/handle");
|
|
8
8
|
var _constants = require("../../../common/session/constants");
|
|
9
9
|
var _instrumentBase = require("../../utils/instrument-base");
|
|
10
|
-
var _constants2 = require("../constants");
|
|
11
10
|
var _utils = require("../shared/utils");
|
|
11
|
+
var _constants2 = require("../constants");
|
|
12
12
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
13
13
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /*
|
|
14
14
|
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
@@ -22,6 +22,7 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
22
22
|
*/
|
|
23
23
|
class Instrument extends _instrumentBase.InstrumentBase {
|
|
24
24
|
static featureName = _constants2.FEATURE_NAME;
|
|
25
|
+
#mode;
|
|
25
26
|
constructor(agentIdentifier, aggregator) {
|
|
26
27
|
let auto = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
27
28
|
super(agentIdentifier, aggregator, _constants2.FEATURE_NAME, auto);
|
|
@@ -30,8 +31,12 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
30
31
|
try {
|
|
31
32
|
session = JSON.parse(localStorage.getItem("".concat(_constants.PREFIX, "_").concat(_constants.DEFAULT_KEY)));
|
|
32
33
|
} catch (err) {}
|
|
34
|
+
if ((0, _utils.hasReplayPrerequisite)(agentIdentifier)) {
|
|
35
|
+
this.ee.on('recordReplay', () => this.#apiStartOrRestartReplay());
|
|
36
|
+
}
|
|
33
37
|
if (this.#canPreloadRecorder(session)) {
|
|
34
|
-
this.#
|
|
38
|
+
this.#mode = session?.sessionReplayMode;
|
|
39
|
+
this.#preloadStartRecording();
|
|
35
40
|
} else {
|
|
36
41
|
this.importAggregator();
|
|
37
42
|
}
|
|
@@ -64,21 +69,56 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
64
69
|
return (0, _utils.isPreloadAllowed)(this.agentIdentifier);
|
|
65
70
|
}
|
|
66
71
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
#alreadyStarted = false;
|
|
73
|
+
/**
|
|
74
|
+
* This func is use for early pre-load recording prior to replay feature (agg) being loaded onto the page. It should only setup once, including if already called and in-progress.
|
|
75
|
+
*/
|
|
76
|
+
async #preloadStartRecording(trigger) {
|
|
77
|
+
if (this.#alreadyStarted) return;
|
|
78
|
+
this.#alreadyStarted = true;
|
|
79
|
+
try {
|
|
80
|
+
const {
|
|
81
|
+
Recorder
|
|
82
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require( /* webpackChunkName: "recorder" */'../shared/recorder')));
|
|
83
|
+
|
|
84
|
+
// If startReplay() has been used by this point, we must record in full mode regardless of session preload:
|
|
85
|
+
// Note: recorder starts here with w/e the mode is at this time, but this may be changed later (see #apiStartOrRestartReplay else-case)
|
|
86
|
+
this.recorder ??= new Recorder({
|
|
87
|
+
mode: this.#mode,
|
|
88
|
+
agentIdentifier: this.agentIdentifier,
|
|
89
|
+
trigger,
|
|
90
|
+
ee: this.ee
|
|
91
|
+
});
|
|
92
|
+
this.recorder.startRecording();
|
|
93
|
+
this.abortHandler = this.recorder.stopRecording;
|
|
94
|
+
} catch (e) {}
|
|
78
95
|
this.importAggregator({
|
|
79
96
|
recorder: this.recorder,
|
|
80
97
|
errorNoticed: this.errorNoticed
|
|
81
98
|
});
|
|
82
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Called whenever startReplay API is used. That could occur any time, pre or post load.
|
|
103
|
+
*/
|
|
104
|
+
#apiStartOrRestartReplay() {
|
|
105
|
+
if (this.featAggregate) {
|
|
106
|
+
// post-load; there's possibly already an ongoing recording
|
|
107
|
+
if (this.featAggregate.mode !== _constants.MODE.FULL) this.featAggregate.initializeRecording(_constants.MODE.FULL, true);
|
|
108
|
+
} else {
|
|
109
|
+
// pre-load
|
|
110
|
+
this.#mode = _constants.MODE.FULL;
|
|
111
|
+
this.#preloadStartRecording(_constants2.TRIGGERS.API);
|
|
112
|
+
// There's a race here wherein either:
|
|
113
|
+
// a. Recorder has not been initialized, and we've set the enforced mode, so we're good, or;
|
|
114
|
+
// b. Record has been initialized, possibly with the "wrong" mode, so we have to correct that + restart.
|
|
115
|
+
if (this.recorder && this.recorder.parent.mode !== _constants.MODE.FULL) {
|
|
116
|
+
this.recorder.parent.mode = _constants.MODE.FULL;
|
|
117
|
+
this.recorder.stopRecording();
|
|
118
|
+
this.recorder.startRecording();
|
|
119
|
+
this.abortHandler = this.recorder.stopRecording;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
83
123
|
}
|
|
84
124
|
exports.Instrument = Instrument;
|
|
@@ -5,17 +5,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.buildNRMetaNode = buildNRMetaNode;
|
|
7
7
|
exports.canImportReplayAgg = canImportReplayAgg;
|
|
8
|
-
exports.
|
|
8
|
+
exports.hasReplayPrerequisite = hasReplayPrerequisite;
|
|
9
9
|
exports.isPreloadAllowed = isPreloadAllowed;
|
|
10
10
|
var _config = require("../../../common/config/config");
|
|
11
|
+
var _featureGates = require("../../utils/feature-gates");
|
|
11
12
|
var _runtime = require("../../../common/constants/runtime");
|
|
12
|
-
function enableSessionTracking(agentId) {
|
|
13
|
-
return _runtime.isBrowserScope && (0, _config.getConfigurationValue)(agentId, 'privacy.cookies_enabled') === true;
|
|
14
|
-
}
|
|
15
13
|
function hasReplayPrerequisite(agentId) {
|
|
16
14
|
return !!_config.originals.MO &&
|
|
17
15
|
// Session Replay cannot work without Mutation Observer
|
|
18
|
-
|
|
16
|
+
(0, _featureGates.canEnableSessionTracking)(agentId) &&
|
|
19
17
|
// requires session tracking to be running (hence "session" replay...)
|
|
20
18
|
(0, _config.getConfigurationValue)(agentId, 'session_trace.enabled') === true; // Session Replay as of now is tightly coupled with Session Trace in the UI
|
|
21
19
|
}
|