@newrelic/browser-agent 1.246.0 → 1.247.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 +19 -0
- package/README.md +29 -2
- package/dist/cjs/common/config/state/info.js +2 -1
- package/dist/cjs/common/config/state/init.js +2 -1
- package/dist/cjs/common/config/state/loader-config.js +2 -1
- package/dist/cjs/common/config/state/runtime.js +2 -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/constants/runtime.js +3 -1
- package/dist/cjs/common/dispatch/global-event.js +19 -0
- package/dist/cjs/common/session/session-entity.js +14 -9
- package/dist/cjs/common/util/feature-flags.js +17 -12
- package/dist/cjs/common/window/load.js +1 -0
- package/dist/cjs/common/window/nreum.js +18 -17
- package/dist/cjs/features/metrics/aggregate/index.js +4 -2
- package/dist/cjs/features/session_replay/aggregate/index.js +56 -16
- package/dist/cjs/features/session_trace/aggregate/index.js +32 -18
- package/dist/cjs/features/spa/aggregate/index.js +2 -1
- package/dist/cjs/features/utils/aggregate-base.js +3 -1
- package/dist/cjs/features/utils/feature-base.js +2 -2
- package/dist/cjs/features/utils/instrument-base.js +3 -3
- package/dist/cjs/loaders/agent-base.js +19 -0
- package/dist/cjs/loaders/agent.js +6 -4
- package/dist/cjs/loaders/api/api.js +10 -1
- package/dist/cjs/loaders/configure/configure.js +14 -13
- package/dist/cjs/loaders/configure/nonce.js +13 -0
- package/dist/cjs/loaders/configure/nonce.npm.js +2 -0
- package/dist/cjs/loaders/micro-agent.js +5 -4
- package/dist/esm/common/config/state/info.js +3 -2
- package/dist/esm/common/config/state/init.js +3 -2
- package/dist/esm/common/config/state/loader-config.js +3 -2
- package/dist/esm/common/config/state/runtime.js +3 -2
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/constants/runtime.js +1 -0
- package/dist/esm/common/dispatch/global-event.js +13 -0
- package/dist/esm/common/session/session-entity.js +14 -9
- package/dist/esm/common/util/feature-flags.js +17 -12
- package/dist/esm/common/window/load.js +1 -1
- package/dist/esm/common/window/nreum.js +16 -16
- package/dist/esm/features/metrics/aggregate/index.js +4 -2
- package/dist/esm/features/session_replay/aggregate/index.js +56 -16
- package/dist/esm/features/session_trace/aggregate/index.js +32 -18
- package/dist/esm/features/spa/aggregate/index.js +2 -1
- package/dist/esm/features/utils/aggregate-base.js +3 -1
- package/dist/esm/features/utils/feature-base.js +2 -2
- package/dist/esm/features/utils/instrument-base.js +3 -3
- package/dist/esm/loaders/agent-base.js +19 -0
- package/dist/esm/loaders/agent.js +7 -5
- package/dist/esm/loaders/api/api.js +10 -1
- package/dist/esm/loaders/configure/configure.js +15 -14
- package/dist/esm/loaders/configure/nonce.js +11 -0
- package/dist/esm/loaders/configure/nonce.npm.js +1 -0
- package/dist/esm/loaders/micro-agent.js +6 -5
- package/dist/types/common/config/state/info.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/config/state/loader-config.d.ts.map +1 -1
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/constants/runtime.d.ts +1 -0
- package/dist/types/common/constants/runtime.d.ts.map +1 -1
- package/dist/types/common/dispatch/global-event.d.ts +2 -0
- package/dist/types/common/dispatch/global-event.d.ts.map +1 -0
- package/dist/types/common/event-emitter/contextual-ee.d.ts +2 -2
- package/dist/types/common/event-emitter/register-handler.d.ts +1 -1
- package/dist/types/common/session/session-entity.d.ts +10 -9
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/vitals/constants.d.ts +8 -8
- package/dist/types/common/window/load.d.ts +1 -0
- package/dist/types/common/window/load.d.ts.map +1 -1
- package/dist/types/common/window/nreum.d.ts +9 -3
- package/dist/types/common/window/nreum.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +2 -2
- 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 +17 -7
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/feature-base.d.ts +4 -4
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +6 -6
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +13 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +2 -0
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts +4 -11
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/configure/nonce.d.ts +1 -0
- package/dist/types/loaders/configure/nonce.d.ts.map +1 -0
- package/dist/types/loaders/configure/nonce.npm.d.ts +1 -0
- package/dist/types/loaders/configure/nonce.npm.d.ts.map +1 -0
- package/dist/types/loaders/features/features.d.ts +9 -9
- package/dist/types/loaders/micro-agent.d.ts +2 -2
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/common/config/state/info.js +3 -2
- package/src/common/config/state/init.js +3 -2
- package/src/common/config/state/loader-config.js +3 -2
- package/src/common/config/state/runtime.js +3 -2
- package/src/common/constants/runtime.js +2 -0
- package/src/common/dispatch/global-event.js +12 -0
- package/src/common/session/session-entity.js +13 -9
- package/src/common/util/feature-flags.js +15 -12
- package/src/common/window/__mocks__/nreum.js +2 -1
- package/src/common/window/load.js +1 -1
- package/src/common/window/nreum.js +15 -18
- package/src/features/metrics/aggregate/index.js +5 -1
- package/src/features/session_replay/aggregate/index.js +63 -20
- package/src/features/session_trace/aggregate/index.js +31 -14
- package/src/features/spa/aggregate/index.js +2 -1
- package/src/features/utils/aggregate-base.js +1 -1
- package/src/features/utils/feature-base.js +2 -2
- package/src/features/utils/instrument-base.js +3 -3
- package/src/loaders/agent-base.js +19 -0
- package/src/loaders/agent.js +5 -5
- package/src/loaders/api/api.js +12 -1
- package/src/loaders/configure/configure.js +17 -15
- package/src/loaders/configure/nonce.js +12 -0
- package/src/loaders/configure/nonce.npm.js +1 -0
- package/src/loaders/micro-agent.js +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,25 @@
|
|
|
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.247.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.246.1...v1.247.0) (2023-11-14)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add basic support for deferring the browser agent loader script ([#800](https://github.com/newrelic/newrelic-browser-agent/issues/800)) ([92d864c](https://github.com/newrelic/newrelic-browser-agent/commit/92d864cb12a3076fd9b623fcd411d2dc9190110c))
|
|
12
|
+
* Add relative timestamps to Session Replay payloads ([#810](https://github.com/newrelic/newrelic-browser-agent/issues/810)) ([e4d1c70](https://github.com/newrelic/newrelic-browser-agent/commit/e4d1c701228e011d7c6f9d84cdc107044c69ce79))
|
|
13
|
+
* Add session durationMs to Session Replay payloads ([#792](https://github.com/newrelic/newrelic-browser-agent/issues/792)) ([3dfc4d4](https://github.com/newrelic/newrelic-browser-agent/commit/3dfc4d43fa978eeec47ebf432f8741562d0dd864))
|
|
14
|
+
* Enable SRI and nonce attributes for async chunks ([#805](https://github.com/newrelic/newrelic-browser-agent/issues/805)) ([fd9c3f3](https://github.com/newrelic/newrelic-browser-agent/commit/fd9c3f388f17353796ac2ebf18814353ca819dcf))
|
|
15
|
+
* Expose library versions used to capture session replay data ([#809](https://github.com/newrelic/newrelic-browser-agent/issues/809)) ([bc275ee](https://github.com/newrelic/newrelic-browser-agent/commit/bc275ee20242a5208358a0a77ac75e2b7cbd11c4))
|
|
16
|
+
* Session Replay API ([#803](https://github.com/newrelic/newrelic-browser-agent/issues/803)) ([12eb453](https://github.com/newrelic/newrelic-browser-agent/commit/12eb4530cfb5eb1e0a94d858485be0df40582c21))
|
|
17
|
+
|
|
18
|
+
## [1.246.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.246.0...v1.246.1) (2023-10-31)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Bug Fixes
|
|
22
|
+
|
|
23
|
+
* Fix missing type declarations ([#791](https://github.com/newrelic/newrelic-browser-agent/issues/791)) ([c80e8d2](https://github.com/newrelic/newrelic-browser-agent/commit/c80e8d260a8919a41ebca7bdc182937819464dc7))
|
|
24
|
+
|
|
6
25
|
## [1.246.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.245.0...v1.246.0) (2023-10-23)
|
|
7
26
|
|
|
8
27
|
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Before instrumenting your app using the NPM package, a Browser App should be con
|
|
|
39
39
|
|
|
40
40
|
## Instantiating the agent
|
|
41
41
|
|
|
42
|
-
For best results, import and instantiate the `BrowserAgent` class as close to the top of the `head` element of your app's HTML output as possible. The specific location and method will vary based on your application's architecture or framework.
|
|
42
|
+
For best results, import and instantiate the `BrowserAgent` class as close to the top of the `head` element of your app's HTML output as possible. The specific location and method will vary based on your application's architecture or framework. See [Library Support](#library-support) for more information.
|
|
43
43
|
|
|
44
44
|
Populate the `options` parameter using configuration values found in the the *Copy/Paste JavaScript* box in your browser app's *Application settings* page in New Relic One.
|
|
45
45
|
|
|
@@ -171,6 +171,25 @@ try{
|
|
|
171
171
|
microAgent2.addPageAction('myData', {hello: 'world'})
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
+
## Browser Agent APIs
|
|
175
|
+
All Browser Agent APIs are exposed for use in two ways:
|
|
176
|
+
- Via the `newrelic` window-level global object
|
|
177
|
+
- At the top-level of the Agent instance
|
|
178
|
+
|
|
179
|
+
Please see our [official documentation](https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/using-browser-apis/) for more information about the Browser Agent APIs.
|
|
180
|
+
|
|
181
|
+
```js
|
|
182
|
+
newrelic.noticeError(...)
|
|
183
|
+
// or
|
|
184
|
+
const NrAgent = new BrowserAgent(...)
|
|
185
|
+
NrAgent.noticeError(...)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Session Replay
|
|
189
|
+
The Session Replay feature is currently in Limited Preview and only functional for customers participating in the early access program. To request access, please visit [this link](https://newrelic.com/platform/session-replay-early-access).
|
|
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.
|
|
192
|
+
|
|
174
193
|
## Supported browsers
|
|
175
194
|
|
|
176
195
|
Our supported browser list can be accessed [here](https://docs.newrelic.com/docs/browser/new-relic-browser/getting-started/compatibility-requirements-browser-monitoring/#browser-types).
|
|
@@ -210,6 +229,14 @@ import { Agent } from '@newrelic/browser-agent/loaders/agent'
|
|
|
210
229
|
import { Metrics } from '@newrelic/browser-agent/src/features/metrics'
|
|
211
230
|
```
|
|
212
231
|
|
|
232
|
+
## Library Support
|
|
233
|
+
|
|
234
|
+
The browser agent is written to be agnostic to any JavaScript library or framework. The agent exposes a number of [API methods](https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/using-browser-apis/) that can be incorporated into libraries and frameworks. For example, export or make available the initialized agent and create a new error boundary in your react application that calls `browserAgent.noticeError()`.
|
|
235
|
+
|
|
236
|
+
### Server-Side Rendering
|
|
237
|
+
|
|
238
|
+
A lot of new frameworks support the concept of server-side rendering the pages of an application to improve SEO and the performance of the user experience. The browser agent must be imported and instantiated within a browser context and will not work if executed on a server or in the server context of a server-side rendered application. These frameworks typically provide support for defining code that should only be run on the client. Check your frameworks documentation for more information.
|
|
239
|
+
|
|
213
240
|
## Disclaimers
|
|
214
241
|
|
|
215
242
|
The session replay library shipping with this version of the browser agent is in *limited preview* and is not turned on by default. To use the feature, users will need to be part of the limited preview customer group and configure their browser application settings in the UI.
|
|
@@ -240,6 +267,6 @@ To all contributors, we thank you! Without your contribution, this project would
|
|
|
240
267
|
|
|
241
268
|
## License
|
|
242
269
|
|
|
243
|
-
The Browser agent is licensed under the [Apache 2.0](
|
|
270
|
+
The Browser agent is licensed under the [Apache 2.0](https://apache.org/licenses/LICENSE-2.0.txt) License.
|
|
244
271
|
|
|
245
272
|
The Browser agent also uses source code from third-party libraries. Full details on which libraries are used and the terms under which they are licensed can be found in the [third-party notices document](THIRD_PARTY_NOTICES.md).
|
|
@@ -46,5 +46,6 @@ function getInfo(id) {
|
|
|
46
46
|
function setInfo(id, obj) {
|
|
47
47
|
if (!id) throw new Error('All info objects require an agent identifier!');
|
|
48
48
|
_cache[id] = (0, _configurable.getModeledObject)(obj, model);
|
|
49
|
-
(0, _nreum.
|
|
49
|
+
const agentInst = (0, _nreum.getNREUMInitializedAgent)(id);
|
|
50
|
+
if (agentInst) agentInst.info = _cache[id];
|
|
50
51
|
}
|
|
@@ -173,7 +173,8 @@ function getConfiguration(id) {
|
|
|
173
173
|
function setConfiguration(id, obj) {
|
|
174
174
|
if (!id) throw new Error(missingAgentIdError);
|
|
175
175
|
_cache[id] = (0, _configurable.getModeledObject)(obj, model());
|
|
176
|
-
(0, _nreum.
|
|
176
|
+
const agentInst = (0, _nreum.getNREUMInitializedAgent)(id);
|
|
177
|
+
if (agentInst) agentInst.init = _cache[id];
|
|
177
178
|
}
|
|
178
179
|
function getConfigurationValue(id, path) {
|
|
179
180
|
if (!id) throw new Error(missingAgentIdError);
|
|
@@ -24,5 +24,6 @@ function getLoaderConfig(id) {
|
|
|
24
24
|
function setLoaderConfig(id, obj) {
|
|
25
25
|
if (!id) throw new Error('All loader-config objects require an agent identifier!');
|
|
26
26
|
_cache[id] = (0, _configurable.getModeledObject)(obj, model);
|
|
27
|
-
(0, _nreum.
|
|
27
|
+
const agentInst = (0, _nreum.getNREUMInitializedAgent)(id);
|
|
28
|
+
if (agentInst) agentInst.loader_config = _cache[id];
|
|
28
29
|
}
|
|
@@ -38,5 +38,6 @@ function getRuntime(id) {
|
|
|
38
38
|
function setRuntime(id, obj) {
|
|
39
39
|
if (!id) throw new Error('All runtime objects require an agent identifier!');
|
|
40
40
|
_cache[id] = (0, _configurable.getModeledObject)(obj, model);
|
|
41
|
-
(0, _nreum.
|
|
41
|
+
const agentInst = (0, _nreum.getNREUMInitializedAgent)(id);
|
|
42
|
+
if (agentInst) agentInst.runtime = _cache[id];
|
|
42
43
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.supportsSendBeacon = exports.offset = exports.isiOS = exports.isWorkerScope = exports.isIE = exports.isBrowserScope = exports.initiallyHidden = exports.initialLocation = exports.iOSBelow16 = exports.globalScope = exports.ffVersion = void 0;
|
|
6
|
+
exports.supportsSendBeacon = exports.offset = exports.loadedAsDeferredBrowserScript = exports.isiOS = exports.isWorkerScope = exports.isIE = exports.isBrowserScope = exports.initiallyHidden = exports.initialLocation = exports.iOSBelow16 = exports.globalScope = exports.ffVersion = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* @file Contains constants about the environment the agent is running
|
|
9
9
|
* within. These values are derived at the time the agent is first loaded.
|
|
@@ -24,6 +24,8 @@ const isWorkerScope = typeof WorkerGlobalScope !== 'undefined' && (typeof self !
|
|
|
24
24
|
exports.isWorkerScope = isWorkerScope;
|
|
25
25
|
const globalScope = isBrowserScope ? window : typeof WorkerGlobalScope !== 'undefined' && (typeof self !== 'undefined' && self instanceof WorkerGlobalScope && self || typeof globalThis !== 'undefined' && globalThis instanceof WorkerGlobalScope && globalThis);
|
|
26
26
|
exports.globalScope = globalScope;
|
|
27
|
+
const loadedAsDeferredBrowserScript = globalScope?.document?.readyState === 'complete';
|
|
28
|
+
exports.loadedAsDeferredBrowserScript = loadedAsDeferredBrowserScript;
|
|
27
29
|
const initiallyHidden = Boolean(globalScope?.document?.visibilityState === 'hidden');
|
|
28
30
|
exports.initiallyHidden = initiallyHidden;
|
|
29
31
|
const initialLocation = '' + globalScope?.location;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.dispatchGlobalEvent = dispatchGlobalEvent;
|
|
7
|
+
var _runtime = require("../constants/runtime");
|
|
8
|
+
const GLOBAL_EVENT_NAMESPACE = 'newrelic';
|
|
9
|
+
function dispatchGlobalEvent() {
|
|
10
|
+
let detail = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
11
|
+
try {
|
|
12
|
+
_runtime.globalScope.dispatchEvent(new CustomEvent(GLOBAL_EVENT_NAMESPACE, {
|
|
13
|
+
detail
|
|
14
|
+
}));
|
|
15
|
+
} catch (err) {
|
|
16
|
+
// something happened... dispatchEvent or CustomEvent might not be supported
|
|
17
|
+
// decide what to do about it here
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -113,8 +113,8 @@ class SessionEntity {
|
|
|
113
113
|
this.expiresTimer = new _timer.Timer({
|
|
114
114
|
// When the inactive timer ends, collect a SM and reset the session
|
|
115
115
|
onEnd: () => {
|
|
116
|
-
this.collectSM('expired'
|
|
117
|
-
this.collectSM('duration'
|
|
116
|
+
this.collectSM('expired');
|
|
117
|
+
this.collectSM('duration');
|
|
118
118
|
this.reset();
|
|
119
119
|
}
|
|
120
120
|
}, this.state.expiresAt - Date.now());
|
|
@@ -130,8 +130,8 @@ class SessionEntity {
|
|
|
130
130
|
this.inactiveTimer = new _interactionTimer.InteractionTimer({
|
|
131
131
|
// When the inactive timer ends, collect a SM and reset the session
|
|
132
132
|
onEnd: () => {
|
|
133
|
-
this.collectSM('inactive'
|
|
134
|
-
this.collectSM('duration'
|
|
133
|
+
this.collectSM('inactive');
|
|
134
|
+
this.collectSM('duration');
|
|
135
135
|
this.reset();
|
|
136
136
|
},
|
|
137
137
|
// When the inactive timer refreshes, it will update the storage values with an update timestamp
|
|
@@ -181,14 +181,14 @@ class SessionEntity {
|
|
|
181
181
|
if (this.isInvalid(obj)) return {};
|
|
182
182
|
// if the session expires, collect a SM count before resetting
|
|
183
183
|
if (this.isExpired(obj.expiresAt)) {
|
|
184
|
-
this.collectSM('expired'
|
|
184
|
+
this.collectSM('expired');
|
|
185
185
|
this.collectSM('duration', obj, true);
|
|
186
186
|
return this.reset();
|
|
187
187
|
}
|
|
188
188
|
// if "inactive" timer is expired at "read" time -- esp. initial read -- reset
|
|
189
189
|
// collect a SM count before resetting
|
|
190
190
|
if (this.isExpired(obj.inactiveAt)) {
|
|
191
|
-
this.collectSM('inactive'
|
|
191
|
+
this.collectSM('inactive');
|
|
192
192
|
this.collectSM('duration', obj, true);
|
|
193
193
|
return this.reset();
|
|
194
194
|
}
|
|
@@ -279,15 +279,20 @@ class SessionEntity {
|
|
|
279
279
|
collectSM(type, data, useUpdatedAt) {
|
|
280
280
|
let value, tag;
|
|
281
281
|
if (type === 'duration') {
|
|
282
|
-
|
|
283
|
-
const endingTimestamp = useUpdatedAt ? data.updatedAt : Date.now();
|
|
284
|
-
value = endingTimestamp - startingTimestamp;
|
|
282
|
+
value = this.getDuration(data, useUpdatedAt);
|
|
285
283
|
tag = 'Session/Duration/Ms';
|
|
286
284
|
}
|
|
287
285
|
if (type === 'expired') tag = 'Session/Expired/Seen';
|
|
288
286
|
if (type === 'inactive') tag = 'Session/Inactive/Seen';
|
|
289
287
|
if (tag) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, [tag, value], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
290
288
|
}
|
|
289
|
+
getDuration() {
|
|
290
|
+
let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state;
|
|
291
|
+
let useUpdatedAt = arguments.length > 1 ? arguments[1] : undefined;
|
|
292
|
+
const startingTimestamp = data.expiresAt - this.expiresMs;
|
|
293
|
+
const endingTimestamp = !useUpdatedAt ? data.updatedAt : Date.now();
|
|
294
|
+
return endingTimestamp - startingTimestamp;
|
|
295
|
+
}
|
|
291
296
|
|
|
292
297
|
/**
|
|
293
298
|
* @param {number} futureMs - The number of ms to use to generate a future timestamp
|
|
@@ -8,6 +8,7 @@ exports.activatedFeatures = void 0;
|
|
|
8
8
|
var _contextualEe = require("../event-emitter/contextual-ee");
|
|
9
9
|
var _handle = require("../event-emitter/handle");
|
|
10
10
|
var _features = require("../../loaders/features/features");
|
|
11
|
+
var _globalEvent = require("../dispatch/global-event");
|
|
11
12
|
/*
|
|
12
13
|
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
13
14
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -26,18 +27,17 @@ const sentIds = new Set();
|
|
|
26
27
|
function activateFeatures(flags, agentIdentifier) {
|
|
27
28
|
const sharedEE = _contextualEe.ee.get(agentIdentifier);
|
|
28
29
|
if (!(flags && typeof flags === 'object')) return;
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
30
|
+
if (sentIds.has(agentIdentifier)) return;
|
|
31
|
+
Object.entries(flags).forEach(_ref => {
|
|
32
|
+
let [flag, num] = _ref;
|
|
33
|
+
if (bucketMap[flag]) {
|
|
34
|
+
bucketMap[flag].forEach(feat => {
|
|
35
|
+
if (!num) (0, _handle.handle)('block-' + flag, [], undefined, feat, sharedEE);else (0, _handle.handle)('feat-' + flag, [], undefined, feat, sharedEE);
|
|
36
|
+
(0, _handle.handle)('rumresp-' + flag, [Boolean(num)], undefined, feat, sharedEE); // this is a duplicate of feat-/block- but makes awaiting for 1 event easier than 2
|
|
37
|
+
});
|
|
38
|
+
} else if (num) (0, _handle.handle)('feat-' + flag, [], undefined, undefined, sharedEE); // not sure what other flags are overlooked, but there's a test for ones not in the map --
|
|
39
|
+
activatedFeatures[flag] = Boolean(num);
|
|
40
|
+
});
|
|
41
41
|
|
|
42
42
|
// Let the features waiting on their respective flags know that RUM response was received and that any missing flags are interpreted as bad entitlement / "off".
|
|
43
43
|
// Hence, those features will not be hanging forever if their flags aren't included in the response.
|
|
@@ -48,6 +48,11 @@ function activateFeatures(flags, agentIdentifier) {
|
|
|
48
48
|
}
|
|
49
49
|
});
|
|
50
50
|
sentIds.add(agentIdentifier);
|
|
51
|
+
|
|
52
|
+
// let any window level subscribers know that the agent is running
|
|
53
|
+
(0, _globalEvent.dispatchGlobalEvent)({
|
|
54
|
+
loaded: true
|
|
55
|
+
});
|
|
51
56
|
}
|
|
52
57
|
const activatedFeatures = {};
|
|
53
58
|
exports.activatedFeatures = activatedFeatures;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.checkState = checkState;
|
|
6
7
|
exports.onDOMContentLoaded = onDOMContentLoaded;
|
|
7
8
|
exports.onWindowLoad = onWindowLoad;
|
|
8
9
|
var _eventListenerOpts = require("../event-listener/event-listener-opts");
|
|
@@ -6,13 +6,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.NREUMinitialized = NREUMinitialized;
|
|
7
7
|
exports.addToNREUM = addToNREUM;
|
|
8
8
|
exports.defaults = void 0;
|
|
9
|
+
exports.getNREUMInitializedAgent = getNREUMInitializedAgent;
|
|
9
10
|
exports.gosCDN = gosCDN;
|
|
10
11
|
exports.gosNREUM = gosNREUM;
|
|
11
12
|
exports.gosNREUMInfo = gosNREUMInfo;
|
|
12
13
|
exports.gosNREUMInit = gosNREUMInit;
|
|
13
|
-
exports.gosNREUMInitializedAgents = gosNREUMInitializedAgents;
|
|
14
14
|
exports.gosNREUMLoaderConfig = gosNREUMLoaderConfig;
|
|
15
15
|
exports.gosNREUMOriginals = gosNREUMOriginals;
|
|
16
|
+
exports.setNREUMInitializedAgent = setNREUMInitializedAgent;
|
|
16
17
|
var _now = require("../timing/now");
|
|
17
18
|
var _runtime = require("../constants/runtime");
|
|
18
19
|
const defaults = {
|
|
@@ -71,24 +72,24 @@ function gosNREUMOriginals() {
|
|
|
71
72
|
}
|
|
72
73
|
return nr;
|
|
73
74
|
}
|
|
74
|
-
function
|
|
75
|
+
function setNREUMInitializedAgent(id, newAgentInstance) {
|
|
75
76
|
let nr = gosNREUM();
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
ms: (0, _now.now)(),
|
|
81
|
-
date: new Date()
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
nr.initializedAgents = {
|
|
85
|
-
...externallySupplied,
|
|
86
|
-
[id]: {
|
|
87
|
-
...curr,
|
|
88
|
-
[target]: obj
|
|
89
|
-
}
|
|
77
|
+
nr.initializedAgents ??= {};
|
|
78
|
+
newAgentInstance.initializedAt = {
|
|
79
|
+
ms: (0, _now.now)(),
|
|
80
|
+
date: new Date()
|
|
90
81
|
};
|
|
91
|
-
|
|
82
|
+
nr.initializedAgents[id] = newAgentInstance;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the agent instance under the associated identifier on the global newrelic object.
|
|
87
|
+
* @see setNREUMInitializedAgents
|
|
88
|
+
* @returns Existing agent instance under newrelic.initializedAgent[id], or undefined if it does not exist.
|
|
89
|
+
*/
|
|
90
|
+
function getNREUMInitializedAgent(id) {
|
|
91
|
+
let nr = gosNREUM();
|
|
92
|
+
return nr.initializedAgents?.[id];
|
|
92
93
|
}
|
|
93
94
|
function addToNREUM(fnName, fn) {
|
|
94
95
|
let nr = gosNREUM();
|
|
@@ -69,10 +69,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
69
69
|
} = (0, _config.getRuntime)(this.agentIdentifier);
|
|
70
70
|
if (loaderType) this.storeSupportabilityMetrics("Generic/LoaderType/".concat(loaderType, "/Detected"));
|
|
71
71
|
if (distMethod) this.storeSupportabilityMetrics("Generic/DistMethod/".concat(distMethod, "/Detected"));
|
|
72
|
-
|
|
73
|
-
// frameworks on page
|
|
74
72
|
if (_runtime.isBrowserScope) {
|
|
75
73
|
this.storeSupportabilityMetrics('Generic/Runtime/Browser/Detected');
|
|
74
|
+
const nonce = document?.currentScript?.nonce;
|
|
75
|
+
if (nonce && nonce !== '') {
|
|
76
|
+
this.storeSupportabilityMetrics('Generic/Runtime/Nonce/Detected');
|
|
77
|
+
}
|
|
76
78
|
|
|
77
79
|
// These SMs are used by the AppExp team
|
|
78
80
|
(0, _load.onDOMContentLoaded)(() => {
|
|
@@ -19,6 +19,7 @@ var _constants2 = require("../../metrics/constants");
|
|
|
19
19
|
var _handle = require("../../../common/event-emitter/handle");
|
|
20
20
|
var _features = require("../../../loaders/features/features");
|
|
21
21
|
var _env = require("../../../common/constants/env.npm");
|
|
22
|
+
var _now = require("../../../common/timing/now");
|
|
22
23
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
23
24
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /*
|
|
24
25
|
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
@@ -120,6 +121,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
120
121
|
|
|
121
122
|
/** 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 */
|
|
122
123
|
this.lastMeta = undefined;
|
|
124
|
+
|
|
125
|
+
/** set by BCS response */
|
|
126
|
+
this.entitled = false;
|
|
123
127
|
const shouldSetup = (0, _config.getConfigurationValue)(agentIdentifier, 'privacy.cookies_enabled') === true && (0, _config.getConfigurationValue)(agentIdentifier, 'session_trace.enabled') === true;
|
|
124
128
|
|
|
125
129
|
/** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
|
|
@@ -157,6 +161,18 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
157
161
|
getPayload: this.prepareHarvest.bind(this),
|
|
158
162
|
raw: true
|
|
159
163
|
}, this);
|
|
164
|
+
(0, _registerHandler.registerHandler)('recordReplay', () => {
|
|
165
|
+
// if it has aborted or BCS returned bad entitlements, do not allow
|
|
166
|
+
if (this.blocked || !this.entitled) return;
|
|
167
|
+
// if it isnt already (fully) initialized... initialize it
|
|
168
|
+
if (!recorder) this.initializeRecording(false, true, true);
|
|
169
|
+
// its been initialized and imported the recorder but its not recording (mode === off || error)
|
|
170
|
+
else if (this.mode !== _sessionEntity.MODE.FULL) this.switchToFull();
|
|
171
|
+
// if it gets all the way to here, that means a full session is already recording... do nothing
|
|
172
|
+
}, this.featureName, this.ee);
|
|
173
|
+
(0, _registerHandler.registerHandler)('pauseReplay', () => {
|
|
174
|
+
this.forceStop(this.mode !== _sessionEntity.MODE.ERROR);
|
|
175
|
+
}, this.featureName, this.ee);
|
|
160
176
|
|
|
161
177
|
// Wait for an error to be reported. This currently is wrapped around the "Error" feature. This is a feature-feature dependency.
|
|
162
178
|
// This was to ensure that all errors, including those on the page before load and those handled with "noticeError" are accounted for. Needs evalulation
|
|
@@ -165,37 +181,42 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
165
181
|
this.errorNoticed = true;
|
|
166
182
|
// run once
|
|
167
183
|
if (this.mode === _sessionEntity.MODE.ERROR && _runtime.globalScope?.document.visibilityState === 'visible') {
|
|
168
|
-
this.
|
|
169
|
-
// if the error was noticed AFTER the recorder was already imported....
|
|
170
|
-
if (recorder && this.initialized) {
|
|
171
|
-
this.stopRecording();
|
|
172
|
-
this.startRecording();
|
|
173
|
-
this.scheduler.startTimer(this.harvestTimeSeconds);
|
|
174
|
-
this.syncWithSessionManager({
|
|
175
|
-
sessionReplayMode: this.mode
|
|
176
|
-
});
|
|
177
|
-
}
|
|
184
|
+
this.switchToFull();
|
|
178
185
|
}
|
|
179
186
|
}, this.featureName, this.ee);
|
|
180
187
|
this.waitForFlags(['sr']).then(_ref => {
|
|
181
188
|
let [flagOn] = _ref;
|
|
182
|
-
|
|
189
|
+
this.entitled = flagOn;
|
|
190
|
+
this.initializeRecording(Math.random() * 100 < (0, _config.getConfigurationValue)(this.agentIdentifier, 'session_replay.error_sampling_rate'), Math.random() * 100 < (0, _config.getConfigurationValue)(this.agentIdentifier, 'session_replay.sampling_rate'));
|
|
183
191
|
}).then(() => _sharedChannel.sharedChannel.onReplayReady(this.mode)); // notify watchers that replay started with the mode
|
|
184
192
|
|
|
185
193
|
this.drain();
|
|
186
194
|
}
|
|
187
195
|
}
|
|
196
|
+
switchToFull() {
|
|
197
|
+
this.mode = _sessionEntity.MODE.FULL;
|
|
198
|
+
// if the error was noticed AFTER the recorder was already imported....
|
|
199
|
+
if (recorder && this.initialized) {
|
|
200
|
+
this.stopRecording();
|
|
201
|
+
this.startRecording();
|
|
202
|
+
this.scheduler.startTimer(this.harvestTimeSeconds);
|
|
203
|
+
this.syncWithSessionManager({
|
|
204
|
+
sessionReplayMode: this.mode
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
188
208
|
|
|
189
209
|
/**
|
|
190
210
|
* Evaluate entitlements and sampling before starting feature mechanics, importing and configuring recording library, and setting storage state
|
|
191
211
|
* @param {boolean} entitlements - the true/false state of the "sr" flag from RUM response
|
|
192
212
|
* @param {boolean} errorSample - the true/false state of the error sampling decision
|
|
193
213
|
* @param {boolean} fullSample - the true/false state of the full sampling decision
|
|
214
|
+
* @param {boolean} ignoreSession - whether to force the method to ignore the session state and use just the sample flags
|
|
194
215
|
* @returns {void}
|
|
195
216
|
*/
|
|
196
|
-
async initializeRecording(
|
|
217
|
+
async initializeRecording(errorSample, fullSample, ignoreSession) {
|
|
197
218
|
this.initialized = true;
|
|
198
|
-
if (!
|
|
219
|
+
if (!this.entitled || this.recording) return;
|
|
199
220
|
const {
|
|
200
221
|
session
|
|
201
222
|
} = (0, _config.getRuntime)(this.agentIdentifier);
|
|
@@ -205,7 +226,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
205
226
|
// we are not actively recording SR... DO NOT import or run the recording library
|
|
206
227
|
// session replay samples can only be decided on the first load of a session
|
|
207
228
|
// session replays can continue if already in progress
|
|
208
|
-
if (!session.isNew) {
|
|
229
|
+
if (!session.isNew && !ignoreSession) {
|
|
209
230
|
// inherit the mode of the existing session
|
|
210
231
|
this.mode = session.state.sessionReplayMode;
|
|
211
232
|
} else {
|
|
@@ -296,10 +317,12 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
296
317
|
this.events = this.events.slice(0, this.events.length - 1);
|
|
297
318
|
this.hasMeta = !!this.events.find(x => x.type === RRWEB_EVENT_TYPES.Meta);
|
|
298
319
|
}
|
|
320
|
+
const agentOffset = (0, _config.getRuntime)(this.agentIdentifier).offset;
|
|
321
|
+
const relativeNow = (0, _now.now)();
|
|
299
322
|
const firstEventTimestamp = this.events[0]?.timestamp; // from rrweb node
|
|
300
323
|
const lastEventTimestamp = this.events[this.events.length - 1]?.timestamp; // from rrweb node
|
|
301
324
|
const firstTimestamp = firstEventTimestamp || this.cycleTimestamp;
|
|
302
|
-
const lastTimestamp = lastEventTimestamp ||
|
|
325
|
+
const lastTimestamp = lastEventTimestamp || agentOffset + relativeNow;
|
|
303
326
|
return {
|
|
304
327
|
qs: {
|
|
305
328
|
browser_monitoring_key: info.licenseKey,
|
|
@@ -311,17 +334,20 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
311
334
|
content_encoding: 'gzip'
|
|
312
335
|
}),
|
|
313
336
|
'replay.firstTimestamp': firstTimestamp,
|
|
337
|
+
'replay.firstTimestampOffset': firstTimestamp - agentOffset,
|
|
314
338
|
'replay.lastTimestamp': lastTimestamp,
|
|
315
339
|
'replay.durationMs': lastTimestamp - firstTimestamp,
|
|
316
340
|
'replay.nodes': this.events.length,
|
|
341
|
+
'session.durationMs': agentRuntime.session.getDuration(),
|
|
317
342
|
agentVersion: agentRuntime.version,
|
|
318
343
|
session: agentRuntime.session.state.value,
|
|
344
|
+
rst: relativeNow,
|
|
319
345
|
hasMeta: this.hasMeta,
|
|
320
346
|
hasSnapshot: this.hasSnapshot,
|
|
321
347
|
hasError: this.hasError,
|
|
322
348
|
isFirstChunk: agentRuntime.session.state.sessionReplaySentFirstChunk === false,
|
|
323
349
|
decompressedBytes: this.payloadBytesEstimation,
|
|
324
|
-
'
|
|
350
|
+
'rrweb.version': _env.RRWEB_VERSION
|
|
325
351
|
}, MAX_PAYLOAD_SIZE - this.payloadBytesEstimation).substring(1) // remove the leading '&'
|
|
326
352
|
},
|
|
327
353
|
|
|
@@ -448,6 +474,20 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
448
474
|
return this.estimateCompression(this.payloadBytesEstimation + newBytes) + 1000;
|
|
449
475
|
}
|
|
450
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Forces the agent into OFF mode so that changing tabs or navigating
|
|
479
|
+
* does not restart the recording. This is used when the customer calls
|
|
480
|
+
* the stopRecording API.
|
|
481
|
+
*/
|
|
482
|
+
forceStop(forceHarvest) {
|
|
483
|
+
if (forceHarvest) this.scheduler.runHarvest();
|
|
484
|
+
this.mode = _sessionEntity.MODE.OFF;
|
|
485
|
+
this.stopRecording();
|
|
486
|
+
this.syncWithSessionManager({
|
|
487
|
+
sessionReplayMode: this.mode
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
451
491
|
/** Abort the feature, once aborted it will not resume */
|
|
452
492
|
abort() {
|
|
453
493
|
let reason = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -89,30 +89,44 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
89
89
|
break;
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
|
+
let seenAnError = false;
|
|
93
|
+
let mostRecentModeKnown;
|
|
94
|
+
this.ee.on(_sessionEntity.SESSION_EVENTS.UPDATE, (eventType, sessionState) => {
|
|
95
|
+
// this will only have an effect if ST is NOT already in full mode
|
|
96
|
+
if (sessionState.sessionReplayMode === _sessionEntity.MODE.FULL) switchToFull();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* The goal of switchToFull is to take external input to trigger a change from off or error to full.
|
|
101
|
+
* It will have no effect if already running in full mode.
|
|
102
|
+
* "external" input in this case means errors thrown on the page or session replay itself being triggered to run in full mode by the API, which updates the session entity.
|
|
103
|
+
*/
|
|
104
|
+
const switchToFull = () => {
|
|
105
|
+
if (mostRecentModeKnown !== _sessionEntity.MODE.FULL) {
|
|
106
|
+
const prevMode = mostRecentModeKnown;
|
|
107
|
+
mostRecentModeKnown = _sessionEntity.MODE.FULL;
|
|
108
|
+
sessionEntity.write({
|
|
109
|
+
sessionTraceMode: mostRecentModeKnown
|
|
110
|
+
});
|
|
111
|
+
this.isStandalone = false;
|
|
112
|
+
if (prevMode === _sessionEntity.MODE.ERROR && this.#scheduler) {
|
|
113
|
+
this.trimSTNs(ERROR_MODE_SECONDS_WINDOW); // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
|
|
114
|
+
this.#scheduler.runHarvest({
|
|
115
|
+
needResponse: true
|
|
116
|
+
});
|
|
117
|
+
} else {
|
|
118
|
+
controlTraceOp(_sessionEntity.MODE.FULL);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
92
122
|
if (!sessionEntity) {
|
|
93
123
|
// Since session manager isn't around, do the old Trace behavior of waiting for RUM response to decide feature activation.
|
|
94
124
|
this.isStandalone = true;
|
|
95
125
|
(0, _registerHandler.registerHandler)('rumresp-stn', on => controlTraceOp(on), this.featureName, this.ee);
|
|
96
126
|
} else {
|
|
97
|
-
let seenAnError = false;
|
|
98
|
-
let mostRecentModeKnown;
|
|
99
127
|
(0, _registerHandler.registerHandler)('errorAgg', () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
seenAnError = true;
|
|
103
|
-
/* If this cb executes before Trace has started, then no further action needed. But if...
|
|
104
|
-
- startTracing already ran under ERROR mode, then it will NOT have kicked off the harvest-scheduler so that needs to be done & switch mode.
|
|
105
|
-
- startTracing never ran because mode is OFF or Replay aborted or Traced turned off elsewhere OR trace already in FULL, then this should do nothing. */
|
|
106
|
-
if (sessionEntity.state.sessionTraceMode === _sessionEntity.MODE.ERROR && this.#scheduler) {
|
|
107
|
-
sessionEntity.write({
|
|
108
|
-
sessionTraceMode: mostRecentModeKnown = _sessionEntity.MODE.FULL
|
|
109
|
-
});
|
|
110
|
-
this.trimSTNs(ERROR_MODE_SECONDS_WINDOW); // up until now, Trace would've been just buffering nodes up to max, which needs to be trimmed to last X seconds
|
|
111
|
-
this.#scheduler.runHarvest({
|
|
112
|
-
needResponse: true
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
}
|
|
128
|
+
seenAnError = true;
|
|
129
|
+
switchToFull();
|
|
116
130
|
}, this.featureName, this.ee);
|
|
117
131
|
const stopTracePerm = () => {
|
|
118
132
|
if (sessionEntity.state.sessionTraceMode !== _sessionEntity.MODE.OFF) sessionEntity.write({
|
|
@@ -22,6 +22,7 @@ var _aggregateBase = require("../../utils/aggregate-base");
|
|
|
22
22
|
var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
|
|
23
23
|
var _firstPaint = require("../../../common/vitals/first-paint");
|
|
24
24
|
var _bundleId = require("../../../common/ids/bundle-id");
|
|
25
|
+
var _runtime = require("../../../common/constants/runtime");
|
|
25
26
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
26
27
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
27
28
|
/*
|
|
@@ -186,7 +187,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
186
187
|
var ev = args[0];
|
|
187
188
|
var evName = ev.type;
|
|
188
189
|
var eventNode = ev["__nrNode:".concat(_bundleId.bundleId)];
|
|
189
|
-
if (!state.pageLoaded && evName === 'load' && eventSource === window) {
|
|
190
|
+
if (!state.pageLoaded && (evName === 'load' && eventSource === window || _runtime.loadedAsDeferredBrowserScript)) {
|
|
190
191
|
state.pageLoaded = true;
|
|
191
192
|
// set to null so prevNode is set correctly
|
|
192
193
|
this.prevNode = state.currentNode = null;
|
|
@@ -49,7 +49,9 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
49
49
|
} catch (err) {
|
|
50
50
|
// do nothing
|
|
51
51
|
}
|
|
52
|
-
(0, _configure.configure)(
|
|
52
|
+
(0, _configure.configure)({
|
|
53
|
+
agentIdentifier: this.agentIdentifier
|
|
54
|
+
}, {
|
|
53
55
|
...(0, _nreum.gosCDN)(),
|
|
54
56
|
info: {
|
|
55
57
|
...(0, _nreum.gosCDN)().info,
|