@newrelic/browser-agent 1.252.0 → 1.252.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 +8 -0
- package/README.md +5 -5
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/session/session-entity.js +3 -1
- package/dist/cjs/features/session_replay/shared/recorder.js +5 -4
- package/dist/cjs/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/dist/cjs/loaders/api/api-methods.js +8 -0
- package/dist/cjs/loaders/api/api.js +3 -7
- package/dist/cjs/loaders/configure/configure.js +1 -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/session/session-entity.js +3 -1
- package/dist/esm/features/session_replay/shared/recorder.js +5 -4
- package/dist/esm/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/dist/esm/loaders/api/api-methods.js +2 -0
- package/dist/esm/loaders/api/api.js +3 -6
- package/dist/esm/loaders/configure/configure.js +1 -1
- package/dist/types/common/session/session-entity.d.ts +0 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/stylesheet-evaluator.d.ts.map +1 -1
- package/dist/types/loaders/api/api-methods.d.ts +3 -0
- package/dist/types/loaders/api/api-methods.d.ts.map +1 -0
- package/dist/types/loaders/api/api.d.ts +0 -1
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/session/session-entity.js +3 -1
- package/src/features/session_replay/shared/recorder.js +5 -4
- package/src/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/src/loaders/api/api-methods.js +9 -0
- package/src/loaders/api/api.js +3 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.252.1](https://github.com/newrelic/newrelic-browser-agent/compare/v1.252.0...v1.252.1) (2024-02-29)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Fix webpack imports in npm package ([#905](https://github.com/newrelic/newrelic-browser-agent/issues/905)) ([35810a8](https://github.com/newrelic/newrelic-browser-agent/commit/35810a895b7f61ab60ea5c24adfa49c4a3956191))
|
|
12
|
+
* Page load after session timeouts don't start new session ([#899](https://github.com/newrelic/newrelic-browser-agent/issues/899)) ([5c952a0](https://github.com/newrelic/newrelic-browser-agent/commit/5c952a0a212922d84dfd7e8eb388fdbd566b6c00))
|
|
13
|
+
|
|
6
14
|
## [1.252.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.251.1...v1.252.0) (2024-02-12)
|
|
7
15
|
|
|
8
16
|
|
package/README.md
CHANGED
|
@@ -24,12 +24,12 @@ $ npm install @newrelic/browser-agent --save
|
|
|
24
24
|
$ yarn add @newrelic/browser-agent
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## Creating an app in New Relic
|
|
27
|
+
## Creating an app in New Relic
|
|
28
28
|
|
|
29
|
-
Before instrumenting your app using the NPM package, a Browser App should be configured in New Relic
|
|
29
|
+
Before instrumenting your app using the NPM package, a Browser App should be configured in New Relic. This may be done with or without a corresponding APM agent. Once the app has been created, the Copy/Paste JavaScript code on the app's *Application settings* page will contain the configuration values needed to define options when instantiating the agent via the NPM package.
|
|
30
30
|
|
|
31
31
|
1. If a browser app does not already exist, create one:
|
|
32
|
-
- From the *New Relic
|
|
32
|
+
- From the *New Relic* navigation panel, click *Add Data*.
|
|
33
33
|
- Select the *Browser monitoring* data source.
|
|
34
34
|
- Choose the *APM* or *Copy/Paste* method.
|
|
35
35
|
- Select or name your app and click *Enable*.
|
|
@@ -41,7 +41,7 @@ Before instrumenting your app using the NPM package, a Browser App should be con
|
|
|
41
41
|
|
|
42
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
|
-
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
|
|
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.
|
|
45
45
|
|
|
46
46
|
```javascript
|
|
47
47
|
import { BrowserAgent } from '@newrelic/browser-agent/loaders/browser-agent'
|
|
@@ -137,7 +137,7 @@ The examples above use the `Agent` class at their core, which is ideal for most
|
|
|
137
137
|
|
|
138
138
|
Using the `MicroAgent` class, it is possible to skip the "auto" instrumentation phases of the other loader types, and provide a *very small* agent designed for capturing data in a controlled manner via the API interfaces. The `MicroAgent` captures a distinct `PageView` event when instantiated, and additional `PageAction` and `JavaScriptError` events may be captured by calling the `noticeError` and `addPageAction` methods.
|
|
139
139
|
|
|
140
|
-
Because it does not wrap the page-level globals in the same way as the base `Agent` class, the `MicroAgent` is not only smaller but can easily be instantiated multiple times on a single page with low overhead, with each instance configured to report to a different Browser App entity in New Relic
|
|
140
|
+
Because it does not wrap the page-level globals in the same way as the base `Agent` class, the `MicroAgent` is not only smaller but can easily be instantiated multiple times on a single page with low overhead, with each instance configured to report to a different Browser App entity in New Relic if desired. This accommodates specialized use cases, such as segmented UI designs (e.g., the micro front-end pattern) or applications requiring subsets of manually-handled data to be reported to different application entities.
|
|
141
141
|
|
|
142
142
|
The example below illustrates how to instantiate and interact with two separate `MicroAgent` instances on one page.
|
|
143
143
|
|
|
@@ -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.252.
|
|
15
|
+
const VERSION = exports.VERSION = "1.252.1";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the build type of the agent
|
|
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
12
12
|
/**
|
|
13
13
|
* Exposes the version of the agent
|
|
14
14
|
*/
|
|
15
|
-
const VERSION = exports.VERSION = "1.252.
|
|
15
|
+
const VERSION = exports.VERSION = "1.252.1";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the build type of the agent
|
|
@@ -135,7 +135,9 @@ class SessionEntity {
|
|
|
135
135
|
|
|
136
136
|
// The fact that the session is "new" or pre-existing is used in some places in the agent. Session Replay and Trace
|
|
137
137
|
// can use this info to inform whether to trust a new sampling decision vs continue a previous tracking effort.
|
|
138
|
-
|
|
138
|
+
/* [NR-230914] 02/2024 - the logical OR assignment is used so that isNew remains 'true' if it was already set as such. This fixes the expires and inactive timestamps timing out in localStorage
|
|
139
|
+
while no page for a given domain is in-use and the session resetting upon user returning to the page as part of a fresh session. */
|
|
140
|
+
this.isNew ||= !Object.keys(initialRead).length;
|
|
139
141
|
// if its a "new" session, we write to storage API with the default values. These values may change over the lifespan of the agent run.
|
|
140
142
|
// we can use a modeled object here to help us know and manage what values are being used. -- see "model" above
|
|
141
143
|
if (this.isNew) this.write((0, _configurable.getModeledObject)(this.state, model), true);else this.sync(initialRead);
|
|
@@ -115,14 +115,15 @@ class Recorder {
|
|
|
115
115
|
const incompletes = _stylesheetEvaluator.stylesheetEvaluator.evaluate();
|
|
116
116
|
/** Only stop ignoring data if already ignoring and a new valid snapshap is taking place (0 incompletes and we get a meta node for the snap) */
|
|
117
117
|
if (!incompletes && this.#fixing && event.type === _constants.RRWEB_EVENT_TYPES.Meta) this.#fixing = false;
|
|
118
|
-
if (incompletes) {
|
|
118
|
+
if (incompletes > 0) {
|
|
119
119
|
/** wait for the evaluator to download/replace the incompletes' src code and then take a new snap */
|
|
120
120
|
_stylesheetEvaluator.stylesheetEvaluator.fix().then(failedToFix => {
|
|
121
|
-
if (failedToFix) {
|
|
121
|
+
if (failedToFix > 0) {
|
|
122
122
|
this.currentBufferTarget.inlinedAllStylesheets = false;
|
|
123
123
|
this.shouldFix = false;
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
}
|
|
125
|
+
(0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Failed', failedToFix], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
|
|
126
|
+
(0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Fixed', incompletes - failedToFix], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
|
|
126
127
|
this.takeFullSnapshot();
|
|
127
128
|
});
|
|
128
129
|
/** Only start ignoring data if got a faulty snapshot */
|
|
@@ -24,15 +24,15 @@ class StylesheetEvaluator {
|
|
|
24
24
|
let incompletes = 0;
|
|
25
25
|
if (_runtime.isBrowserScope) {
|
|
26
26
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.#evaluated.add(ss);
|
|
27
|
+
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
28
|
+
this.#evaluated.add(document.styleSheets[i]);
|
|
30
29
|
try {
|
|
31
30
|
// eslint-disable-next-line
|
|
32
|
-
const temp =
|
|
31
|
+
const temp = document.styleSheets[i].cssRules;
|
|
33
32
|
} catch (err) {
|
|
33
|
+
if (!document.styleSheets[i].href) return;
|
|
34
34
|
incompletes++;
|
|
35
|
-
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]
|
|
35
|
+
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]));
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -59,9 +59,10 @@ class StylesheetEvaluator {
|
|
|
59
59
|
* @param {*} href - The asset href to fetch
|
|
60
60
|
* @returns {Promise}
|
|
61
61
|
*/
|
|
62
|
-
async #fetchAndOverride(target
|
|
62
|
+
async #fetchAndOverride(target) {
|
|
63
|
+
if (!target?.href) return;
|
|
63
64
|
try {
|
|
64
|
-
const stylesheetContents = await _config.originals.FETCH.bind(window)(href);
|
|
65
|
+
const stylesheetContents = await _config.originals.FETCH.bind(window)(target.href);
|
|
65
66
|
if (!stylesheetContents.ok) {
|
|
66
67
|
this.failedToFix++;
|
|
67
68
|
return;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.asyncApiMethods = exports.apiMethods = void 0;
|
|
7
|
+
const apiMethods = exports.apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', 'recordReplay', 'pauseReplay'];
|
|
8
|
+
const asyncApiMethods = exports.asyncApiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.CUSTOM_ATTR_GROUP = void 0;
|
|
7
6
|
exports.setAPI = setAPI;
|
|
8
7
|
exports.setTopLevelCallers = setTopLevelCallers;
|
|
9
8
|
var _features = require("../features/features");
|
|
@@ -17,17 +16,15 @@ var _runtime = require("../../common/constants/runtime");
|
|
|
17
16
|
var _console = require("../../common/util/console");
|
|
18
17
|
var _constants = require("../../features/metrics/constants");
|
|
19
18
|
var _nreum = require("../../common/window/nreum");
|
|
19
|
+
var _apiMethods = require("./api-methods");
|
|
20
20
|
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); }
|
|
21
21
|
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; } /*
|
|
22
22
|
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
23
23
|
* SPDX-License-Identifier: Apache-2.0
|
|
24
24
|
*/
|
|
25
|
-
const CUSTOM_ATTR_GROUP = exports.CUSTOM_ATTR_GROUP = 'CUSTOM/'; // the subgroup items should be stored under in storage API
|
|
26
|
-
|
|
27
25
|
function setTopLevelCallers() {
|
|
28
26
|
const nr = (0, _nreum.gosCDN)();
|
|
29
|
-
|
|
30
|
-
funcs.forEach(f => {
|
|
27
|
+
_apiMethods.apiMethods.forEach(f => {
|
|
31
28
|
nr[f] = function () {
|
|
32
29
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
33
30
|
args[_key] = arguments[_key];
|
|
@@ -53,12 +50,11 @@ function setAPI(agentIdentifier, forceDrain) {
|
|
|
53
50
|
const apiInterface = {};
|
|
54
51
|
var instanceEE = _contextualEe.ee.get(agentIdentifier);
|
|
55
52
|
var tracerEE = instanceEE.get('tracer');
|
|
56
|
-
var asyncApiFns = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];
|
|
57
53
|
var prefix = 'api-';
|
|
58
54
|
var spaPrefix = prefix + 'ixn-';
|
|
59
55
|
|
|
60
56
|
// Setup stub functions that queue calls for later processing.
|
|
61
|
-
|
|
57
|
+
_apiMethods.asyncApiMethods.forEach(fnName => {
|
|
62
58
|
apiInterface[fnName] = apiCall(prefix, fnName, true, 'api');
|
|
63
59
|
});
|
|
64
60
|
apiInterface.addPageAction = apiCall(prefix, 'addPageAction', true, _features.FEATURE_NAMES.pageAction);
|
|
@@ -9,7 +9,7 @@ var _nreum = require("../../common/window/nreum");
|
|
|
9
9
|
var _config = require("../../common/config/config");
|
|
10
10
|
var _featureFlags = require("../../common/util/feature-flags");
|
|
11
11
|
var _runtime = require("../../common/constants/runtime");
|
|
12
|
-
var _publicPath = require("./public-path");
|
|
12
|
+
var _publicPath = require("./public-path.npm");
|
|
13
13
|
let alreadySetOnce = false; // the configure() function can run multiple times in agent lifecycle
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -130,7 +130,9 @@ export class SessionEntity {
|
|
|
130
130
|
|
|
131
131
|
// The fact that the session is "new" or pre-existing is used in some places in the agent. Session Replay and Trace
|
|
132
132
|
// can use this info to inform whether to trust a new sampling decision vs continue a previous tracking effort.
|
|
133
|
-
|
|
133
|
+
/* [NR-230914] 02/2024 - the logical OR assignment is used so that isNew remains 'true' if it was already set as such. This fixes the expires and inactive timestamps timing out in localStorage
|
|
134
|
+
while no page for a given domain is in-use and the session resetting upon user returning to the page as part of a fresh session. */
|
|
135
|
+
this.isNew ||= !Object.keys(initialRead).length;
|
|
134
136
|
// if its a "new" session, we write to storage API with the default values. These values may change over the lifespan of the agent run.
|
|
135
137
|
// we can use a modeled object here to help us know and manage what values are being used. -- see "model" above
|
|
136
138
|
if (this.isNew) this.write(getModeledObject(this.state, model), true);else this.sync(initialRead);
|
|
@@ -109,14 +109,15 @@ export class Recorder {
|
|
|
109
109
|
const incompletes = stylesheetEvaluator.evaluate();
|
|
110
110
|
/** Only stop ignoring data if already ignoring and a new valid snapshap is taking place (0 incompletes and we get a meta node for the snap) */
|
|
111
111
|
if (!incompletes && this.#fixing && event.type === RRWEB_EVENT_TYPES.Meta) this.#fixing = false;
|
|
112
|
-
if (incompletes) {
|
|
112
|
+
if (incompletes > 0) {
|
|
113
113
|
/** wait for the evaluator to download/replace the incompletes' src code and then take a new snap */
|
|
114
114
|
stylesheetEvaluator.fix().then(failedToFix => {
|
|
115
|
-
if (failedToFix) {
|
|
115
|
+
if (failedToFix > 0) {
|
|
116
116
|
this.currentBufferTarget.inlinedAllStylesheets = false;
|
|
117
117
|
this.shouldFix = false;
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
}
|
|
119
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Failed', failedToFix], undefined, FEATURE_NAMES.metrics, this.parent.ee);
|
|
120
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Fixed', incompletes - failedToFix], undefined, FEATURE_NAMES.metrics, this.parent.ee);
|
|
120
121
|
this.takeFullSnapshot();
|
|
121
122
|
});
|
|
122
123
|
/** Only start ignoring data if got a faulty snapshot */
|
|
@@ -18,15 +18,15 @@ class StylesheetEvaluator {
|
|
|
18
18
|
let incompletes = 0;
|
|
19
19
|
if (isBrowserScope) {
|
|
20
20
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.#evaluated.add(ss);
|
|
21
|
+
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
22
|
+
this.#evaluated.add(document.styleSheets[i]);
|
|
24
23
|
try {
|
|
25
24
|
// eslint-disable-next-line
|
|
26
|
-
const temp =
|
|
25
|
+
const temp = document.styleSheets[i].cssRules;
|
|
27
26
|
} catch (err) {
|
|
27
|
+
if (!document.styleSheets[i].href) return;
|
|
28
28
|
incompletes++;
|
|
29
|
-
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]
|
|
29
|
+
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]));
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -53,9 +53,10 @@ class StylesheetEvaluator {
|
|
|
53
53
|
* @param {*} href - The asset href to fetch
|
|
54
54
|
* @returns {Promise}
|
|
55
55
|
*/
|
|
56
|
-
async #fetchAndOverride(target
|
|
56
|
+
async #fetchAndOverride(target) {
|
|
57
|
+
if (!target?.href) return;
|
|
57
58
|
try {
|
|
58
|
-
const stylesheetContents = await originals.FETCH.bind(window)(href);
|
|
59
|
+
const stylesheetContents = await originals.FETCH.bind(window)(target.href);
|
|
59
60
|
if (!stylesheetContents.ok) {
|
|
60
61
|
this.failedToFix++;
|
|
61
62
|
return;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export const apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', 'recordReplay', 'pauseReplay'];
|
|
2
|
+
export const asyncApiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];
|
|
@@ -13,12 +13,10 @@ import { isBrowserScope } from '../../common/constants/runtime';
|
|
|
13
13
|
import { warn } from '../../common/util/console';
|
|
14
14
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants';
|
|
15
15
|
import { gosCDN } from '../../common/window/nreum';
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
import { apiMethods, asyncApiMethods } from './api-methods';
|
|
18
17
|
export function setTopLevelCallers() {
|
|
19
18
|
const nr = gosCDN();
|
|
20
|
-
|
|
21
|
-
funcs.forEach(f => {
|
|
19
|
+
apiMethods.forEach(f => {
|
|
22
20
|
nr[f] = function () {
|
|
23
21
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
24
22
|
args[_key] = arguments[_key];
|
|
@@ -44,12 +42,11 @@ export function setAPI(agentIdentifier, forceDrain) {
|
|
|
44
42
|
const apiInterface = {};
|
|
45
43
|
var instanceEE = ee.get(agentIdentifier);
|
|
46
44
|
var tracerEE = instanceEE.get('tracer');
|
|
47
|
-
var asyncApiFns = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];
|
|
48
45
|
var prefix = 'api-';
|
|
49
46
|
var spaPrefix = prefix + 'ixn-';
|
|
50
47
|
|
|
51
48
|
// Setup stub functions that queue calls for later processing.
|
|
52
|
-
|
|
49
|
+
asyncApiMethods.forEach(fnName => {
|
|
53
50
|
apiInterface[fnName] = apiCall(prefix, fnName, true, 'api');
|
|
54
51
|
});
|
|
55
52
|
apiInterface.addPageAction = apiCall(prefix, 'addPageAction', true, FEATURE_NAMES.pageAction);
|
|
@@ -3,7 +3,7 @@ import { addToNREUM, gosCDN } from '../../common/window/nreum';
|
|
|
3
3
|
import { getConfiguration, setConfiguration, setInfo, setLoaderConfig, setRuntime } from '../../common/config/config';
|
|
4
4
|
import { activatedFeatures } from '../../common/util/feature-flags';
|
|
5
5
|
import { isWorkerScope } from '../../common/constants/runtime';
|
|
6
|
-
import { redefinePublicPath } from
|
|
6
|
+
import { redefinePublicPath } from "./public-path.npm";
|
|
7
7
|
let alreadySetOnce = false; // the configure() function can run multiple times in agent lifecycle
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -20,7 +20,6 @@ export class SessionEntity {
|
|
|
20
20
|
inactiveMs: number | undefined;
|
|
21
21
|
expiresTimer: Timer | undefined;
|
|
22
22
|
inactiveTimer: InteractionTimer | undefined;
|
|
23
|
-
isNew: boolean | undefined;
|
|
24
23
|
initialized: boolean | undefined;
|
|
25
24
|
get lookupKey(): string;
|
|
26
25
|
sync(data: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AA6BA;IACE;;;;;OAKG;IACH,uBA0BC;IApBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAenC;;;;
|
|
1
|
+
{"version":3,"file":"session-entity.d.ts","sourceRoot":"","sources":["../../../../src/common/session/session-entity.js"],"names":[],"mappings":"AA6BA;IACE;;;;;OAKG;IACH,uBA0BC;IApBC,qBAAsC;IACtC,aAAsB;IACtB,UAAe;IAGf,SAAc;IAEd,QAAiC;IAenC;;;;aAwEC;IAjEC,8BAA0B;IAC1B,+BAA4B;IAc1B,gCAOqC;IAUrC,4CAiBsC;IAexC,iCAAuB;IAIzB,wBAEC;IAED,sBAEC;IAED;;;OAGG;IACH,QAFa,MAAM,CA6BlB;IAED;;;;;;OAMG;IACH,YAHW,MAAM,GACJ,MAAM,CAkBlB;IAED,gBAuBC;IAED;;OAEG;IACH,gBAIC;IAED;;;OAGG;IACH,qBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;OAGG;IACH,gBAHW,MAAM,GACJ,OAAO,CAKnB;IAED,yDAUC;IAED,6DAIC;IAED;;;OAGG;IACH,6BAHW,MAAM,GACJ,MAAM,CAIlB;IAED,gDAaC;IAHG,YAAuD;CAI5D;sBApSqB,gBAAgB;iCAGL,4BAA4B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAWA;IAUE,yBAeC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAA6C;IAC7C,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAwBC;IAED;;;;;OAKG;IACH,
|
|
1
|
+
{"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAWA;IAUE,yBAeC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAA6C;IAC7C,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAwBC;IAED;;;;;OAKG;IACH,yCA0BC;IAED,0HAA0H;IAC1H,yCA2CC;IAED,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BA/L8B,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stylesheet-evaluator.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/stylesheet-evaluator.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stylesheet-evaluator.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/stylesheet-evaluator.js"],"names":[],"mappings":"AAyFA,sDAA4D;AAtF5D;IAGE;;;QAGI;IACJ,oCAAkC;IAClC,oBAAe;IAEf;;;OAGG;IACH,mBAmBC;IAED;;;OAGG;IACH,oBAMC;;CAuCF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-methods.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api-methods.js"],"names":[],"mappings":"AAAA,kCAIC;AAED,uCAEC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAiBA,2CAeC;AAED;;;;;IAkDE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;;EAwGvB"}
|
package/package.json
CHANGED
|
@@ -125,7 +125,9 @@ export class SessionEntity {
|
|
|
125
125
|
|
|
126
126
|
// The fact that the session is "new" or pre-existing is used in some places in the agent. Session Replay and Trace
|
|
127
127
|
// can use this info to inform whether to trust a new sampling decision vs continue a previous tracking effort.
|
|
128
|
-
|
|
128
|
+
/* [NR-230914] 02/2024 - the logical OR assignment is used so that isNew remains 'true' if it was already set as such. This fixes the expires and inactive timestamps timing out in localStorage
|
|
129
|
+
while no page for a given domain is in-use and the session resetting upon user returning to the page as part of a fresh session. */
|
|
130
|
+
this.isNew ||= !Object.keys(initialRead).length
|
|
129
131
|
// if its a "new" session, we write to storage API with the default values. These values may change over the lifespan of the agent run.
|
|
130
132
|
// we can use a modeled object here to help us know and manage what values are being used. -- see "model" above
|
|
131
133
|
if (this.isNew) this.write(getModeledObject(this.state, model), true)
|
|
@@ -101,14 +101,15 @@ export class Recorder {
|
|
|
101
101
|
const incompletes = stylesheetEvaluator.evaluate()
|
|
102
102
|
/** Only stop ignoring data if already ignoring and a new valid snapshap is taking place (0 incompletes and we get a meta node for the snap) */
|
|
103
103
|
if (!incompletes && this.#fixing && event.type === RRWEB_EVENT_TYPES.Meta) this.#fixing = false
|
|
104
|
-
if (incompletes) {
|
|
104
|
+
if (incompletes > 0) {
|
|
105
105
|
/** wait for the evaluator to download/replace the incompletes' src code and then take a new snap */
|
|
106
106
|
stylesheetEvaluator.fix().then((failedToFix) => {
|
|
107
|
-
if (failedToFix) {
|
|
107
|
+
if (failedToFix > 0) {
|
|
108
108
|
this.currentBufferTarget.inlinedAllStylesheets = false
|
|
109
109
|
this.shouldFix = false
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
}
|
|
111
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Failed', failedToFix], undefined, FEATURE_NAMES.metrics, this.parent.ee)
|
|
112
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Fixed', incompletes - failedToFix], undefined, FEATURE_NAMES.metrics, this.parent.ee)
|
|
112
113
|
this.takeFullSnapshot()
|
|
113
114
|
})
|
|
114
115
|
/** Only start ignoring data if got a faulty snapshot */
|
|
@@ -19,15 +19,15 @@ class StylesheetEvaluator {
|
|
|
19
19
|
let incompletes = 0
|
|
20
20
|
if (isBrowserScope) {
|
|
21
21
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.#evaluated.add(ss)
|
|
22
|
+
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
23
|
+
this.#evaluated.add(document.styleSheets[i])
|
|
25
24
|
try {
|
|
26
25
|
// eslint-disable-next-line
|
|
27
|
-
const temp =
|
|
26
|
+
const temp = document.styleSheets[i].cssRules
|
|
28
27
|
} catch (err) {
|
|
28
|
+
if (!document.styleSheets[i].href) return
|
|
29
29
|
incompletes++
|
|
30
|
-
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]
|
|
30
|
+
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]))
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -54,9 +54,10 @@ class StylesheetEvaluator {
|
|
|
54
54
|
* @param {*} href - The asset href to fetch
|
|
55
55
|
* @returns {Promise}
|
|
56
56
|
*/
|
|
57
|
-
async #fetchAndOverride (target
|
|
57
|
+
async #fetchAndOverride (target) {
|
|
58
|
+
if (!target?.href) return
|
|
58
59
|
try {
|
|
59
|
-
const stylesheetContents = await originals.FETCH.bind(window)(href)
|
|
60
|
+
const stylesheetContents = await originals.FETCH.bind(window)(target.href)
|
|
60
61
|
if (!stylesheetContents.ok) {
|
|
61
62
|
this.failedToFix++
|
|
62
63
|
return
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const apiMethods = [
|
|
2
|
+
'setErrorHandler', 'finished', 'addToTrace', 'addRelease',
|
|
3
|
+
'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute',
|
|
4
|
+
'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', 'recordReplay', 'pauseReplay'
|
|
5
|
+
]
|
|
6
|
+
|
|
7
|
+
export const asyncApiMethods = [
|
|
8
|
+
'setErrorHandler', 'finished', 'addToTrace', 'addRelease'
|
|
9
|
+
]
|
package/src/loaders/api/api.js
CHANGED
|
@@ -13,17 +13,11 @@ import { isBrowserScope } from '../../common/constants/runtime'
|
|
|
13
13
|
import { warn } from '../../common/util/console'
|
|
14
14
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants'
|
|
15
15
|
import { gosCDN } from '../../common/window/nreum'
|
|
16
|
-
|
|
17
|
-
export const CUSTOM_ATTR_GROUP = 'CUSTOM/' // the subgroup items should be stored under in storage API
|
|
16
|
+
import { apiMethods, asyncApiMethods } from './api-methods'
|
|
18
17
|
|
|
19
18
|
export function setTopLevelCallers () {
|
|
20
19
|
const nr = gosCDN()
|
|
21
|
-
|
|
22
|
-
'setErrorHandler', 'finished', 'addToTrace', 'addRelease',
|
|
23
|
-
'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute',
|
|
24
|
-
'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', 'recordReplay', 'pauseReplay'
|
|
25
|
-
]
|
|
26
|
-
funcs.forEach(f => {
|
|
20
|
+
apiMethods.forEach(f => {
|
|
27
21
|
nr[f] = (...args) => caller(f, ...args)
|
|
28
22
|
})
|
|
29
23
|
|
|
@@ -44,18 +38,11 @@ export function setAPI (agentIdentifier, forceDrain) {
|
|
|
44
38
|
var instanceEE = ee.get(agentIdentifier)
|
|
45
39
|
var tracerEE = instanceEE.get('tracer')
|
|
46
40
|
|
|
47
|
-
var asyncApiFns = [
|
|
48
|
-
'setErrorHandler',
|
|
49
|
-
'finished',
|
|
50
|
-
'addToTrace',
|
|
51
|
-
'addRelease'
|
|
52
|
-
]
|
|
53
|
-
|
|
54
41
|
var prefix = 'api-'
|
|
55
42
|
var spaPrefix = prefix + 'ixn-'
|
|
56
43
|
|
|
57
44
|
// Setup stub functions that queue calls for later processing.
|
|
58
|
-
|
|
45
|
+
asyncApiMethods.forEach(fnName => { apiInterface[fnName] = apiCall(prefix, fnName, true, 'api') })
|
|
59
46
|
|
|
60
47
|
apiInterface.addPageAction = apiCall(prefix, 'addPageAction', true, FEATURE_NAMES.pageAction)
|
|
61
48
|
apiInterface.setCurrentRouteName = apiCall(prefix, 'routeName', true, FEATURE_NAMES.spa)
|