@newrelic/browser-agent 1.298.0-rc.1 → 1.298.0-rc.3
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/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/harvest/harvester.js +37 -7
- package/dist/cjs/features/metrics/aggregate/harvest-metadata.js +45 -0
- package/dist/cjs/features/metrics/aggregate/index.js +21 -0
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/harvest/harvester.js +37 -7
- package/dist/esm/features/metrics/aggregate/harvest-metadata.js +39 -0
- package/dist/esm/features/metrics/aggregate/index.js +21 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/common/harvest/harvester.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/harvest-metadata.d.ts +6 -0
- package/dist/types/features/metrics/aggregate/harvest-metadata.d.ts.map +1 -0
- package/dist/types/features/metrics/aggregate/index.d.ts +2 -0
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/harvest/harvester.js +34 -7
- package/src/features/metrics/aggregate/harvest-metadata.js +42 -0
- package/src/features/metrics/aggregate/index.js +21 -0
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.298.0-rc.
|
|
20
|
+
const VERSION = exports.VERSION = "1.298.0-rc.3";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -17,7 +17,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the version of the agent
|
|
19
19
|
*/
|
|
20
|
-
const VERSION = exports.VERSION = "1.298.0-rc.
|
|
20
|
+
const VERSION = exports.VERSION = "1.298.0-rc.3";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Exposes the build type of the agent
|
|
@@ -153,14 +153,16 @@ function send(agentRef, {
|
|
|
153
153
|
}
|
|
154
154
|
const fullUrl = "".concat(url, "?").concat(baseParams).concat(payloadParams);
|
|
155
155
|
const gzip = !!qs?.attributes?.includes('gzip');
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
156
|
+
|
|
157
|
+
// all gzipped data is already in the correct format and needs no transformation
|
|
158
|
+
// all features going to 'events' endpoint should already be serialized & stringified
|
|
159
|
+
let stringBody = gzip || endpoint === _features.EVENTS ? body : (0, _stringify.stringify)(body);
|
|
161
160
|
|
|
162
161
|
// If body is null, undefined, or an empty object or array after stringifying, send an empty string instead.
|
|
163
|
-
if (!
|
|
162
|
+
if (!stringBody || stringBody.length === 0 || stringBody === '{}' || stringBody === '[]') stringBody = '';
|
|
163
|
+
|
|
164
|
+
// Warn--once per endpoint--if the agent tries to send large payloads
|
|
165
|
+
if (endpoint !== _features.BLOBS && stringBody.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) (0, _console.warn)(28, endpoint);
|
|
164
166
|
const headers = [{
|
|
165
167
|
key: 'content-type',
|
|
166
168
|
value: 'text/plain'
|
|
@@ -172,7 +174,7 @@ function send(agentRef, {
|
|
|
172
174
|
Following the removal of img-element method. */
|
|
173
175
|
let result = submitMethod({
|
|
174
176
|
url: fullUrl,
|
|
175
|
-
body,
|
|
177
|
+
body: stringBody,
|
|
176
178
|
sync: localOpts.isFinalHarvest && _runtime.isWorkerScope,
|
|
177
179
|
headers
|
|
178
180
|
});
|
|
@@ -192,6 +194,9 @@ function send(agentRef, {
|
|
|
192
194
|
};
|
|
193
195
|
if (localOpts.needResponse) cbResult.responseText = this.responseText;
|
|
194
196
|
cbFinished(cbResult);
|
|
197
|
+
|
|
198
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
199
|
+
if (!shouldRetry(this.status)) trackHarvestMetadata();
|
|
195
200
|
}, (0, _eventListenerOpts.eventListenerOpts)(false));
|
|
196
201
|
} else if (submitMethod === _submitData.xhrFetch) {
|
|
197
202
|
result.then(async function (response) {
|
|
@@ -206,8 +211,33 @@ function send(agentRef, {
|
|
|
206
211
|
};
|
|
207
212
|
if (localOpts.needResponse) cbResult.responseText = await response.text();
|
|
208
213
|
cbFinished(cbResult);
|
|
214
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
215
|
+
if (!shouldRetry(status)) trackHarvestMetadata();
|
|
209
216
|
});
|
|
210
217
|
}
|
|
218
|
+
function trackHarvestMetadata() {
|
|
219
|
+
try {
|
|
220
|
+
if (featureName === _features.FEATURE_NAMES.jserrors && !body?.err) return;
|
|
221
|
+
const hasReplay = baseParams.includes('hr=1');
|
|
222
|
+
const hasTrace = baseParams.includes('ht=1');
|
|
223
|
+
const hasError = qs?.attributes?.includes('hasError=true');
|
|
224
|
+
(0, _handle.handle)('harvest-metadata', [{
|
|
225
|
+
[featureName]: {
|
|
226
|
+
...(hasReplay && {
|
|
227
|
+
hasReplay
|
|
228
|
+
}),
|
|
229
|
+
...(hasTrace && {
|
|
230
|
+
hasTrace
|
|
231
|
+
}),
|
|
232
|
+
...(hasError && {
|
|
233
|
+
hasError
|
|
234
|
+
})
|
|
235
|
+
}
|
|
236
|
+
}], undefined, _features.FEATURE_NAMES.metrics, agentRef.ee);
|
|
237
|
+
} catch (err) {
|
|
238
|
+
// do nothing
|
|
239
|
+
}
|
|
240
|
+
}
|
|
211
241
|
}
|
|
212
242
|
(0, _globalEvent.dispatchGlobalEvent)({
|
|
213
243
|
agentIdentifier: agentRef.agentIdentifier,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.evaluateHarvestMetadata = evaluateHarvestMetadata;
|
|
7
|
+
/**
|
|
8
|
+
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
9
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
function evaluateHarvestMetadata(pageMetadata) {
|
|
13
|
+
try {
|
|
14
|
+
const supportabilityTags = [];
|
|
15
|
+
|
|
16
|
+
// Report SM like... audit/<feature_name>/<hasReplay|hasTrace|hasError>/<true|false>/<negative|positive>
|
|
17
|
+
const formTag = (...strings) => strings.join('/');
|
|
18
|
+
|
|
19
|
+
// Track if replay/trace/error harvests actually occurred (key only exists when harvested)
|
|
20
|
+
function evaluateTag(feature, flag, hasFlag, hasHarvest) {
|
|
21
|
+
const AUDIT = 'audit';
|
|
22
|
+
if (hasFlag) {
|
|
23
|
+
// False positive: flag true, but no harvest
|
|
24
|
+
if (!hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'positive'));
|
|
25
|
+
// True positive (correct)
|
|
26
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'positive'));
|
|
27
|
+
} else {
|
|
28
|
+
// False negative: flag false, but harvest occurred
|
|
29
|
+
if (hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'negative'));
|
|
30
|
+
// True negative (correct)
|
|
31
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'negative'));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (pageMetadata.page_view_event) {
|
|
35
|
+
evaluateTag('page_view', 'hasReplay', pageMetadata.page_view_event.hasReplay, !!pageMetadata.session_replay);
|
|
36
|
+
evaluateTag('page_view', 'hasTrace', pageMetadata.page_view_event.hasTrace, !!pageMetadata.session_trace);
|
|
37
|
+
}
|
|
38
|
+
if (pageMetadata.session_replay) {
|
|
39
|
+
evaluateTag('session_replay', 'hasError', pageMetadata.session_replay.hasError, !!pageMetadata.jserrors);
|
|
40
|
+
}
|
|
41
|
+
return supportabilityTags;
|
|
42
|
+
} catch (err) {
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -13,6 +13,7 @@ var _eventListenerOpts = require("../../../common/event-listener/event-listener-
|
|
|
13
13
|
var _runtime = require("../../../common/constants/runtime");
|
|
14
14
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
15
15
|
var _iframe = require("../../../common/dom/iframe");
|
|
16
|
+
var _harvestMetadata = require("./harvest-metadata");
|
|
16
17
|
/**
|
|
17
18
|
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
18
19
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -26,6 +27,15 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
26
27
|
constructor(agentRef) {
|
|
27
28
|
super(agentRef, _constants.FEATURE_NAME);
|
|
28
29
|
this.harvestOpts.aggregatorTypes = ['cm', 'sm']; // the types in EventAggregator this feature cares about
|
|
30
|
+
|
|
31
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
32
|
+
this.harvestMetadata = {};
|
|
33
|
+
this.harvestOpts.beforeUnload = () => {
|
|
34
|
+
(0, _harvestMetadata.evaluateHarvestMetadata)(this.harvestMetadata).forEach(smTag => {
|
|
35
|
+
this.storeSupportabilityMetrics(smTag);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
29
39
|
// This feature only harvests once per potential EoL of the page, which is handled by the central harvester.
|
|
30
40
|
|
|
31
41
|
// this must be read/stored synchronously, as the currentScript is removed from the DOM after this script is executed and this lookup will be void
|
|
@@ -145,6 +155,17 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
145
155
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
146
156
|
// }, this.featureName, this.ee)
|
|
147
157
|
// })
|
|
158
|
+
|
|
159
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
160
|
+
(0, _registerHandler.registerHandler)('harvest-metadata', (harvestMetadataObject = {}) => {
|
|
161
|
+
try {
|
|
162
|
+
Object.keys(harvestMetadataObject).forEach(key => {
|
|
163
|
+
Object.assign(this.harvestMetadata[key] ??= {}, harvestMetadataObject[key]);
|
|
164
|
+
});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
// failed to merge harvest metadata... ignore
|
|
167
|
+
}
|
|
168
|
+
}, this.featureName, this.ee);
|
|
148
169
|
}
|
|
149
170
|
eachSessionChecks() {
|
|
150
171
|
if (!_runtime.isBrowserScope) return;
|
|
@@ -145,14 +145,16 @@ export function send(agentRef, {
|
|
|
145
145
|
}
|
|
146
146
|
const fullUrl = "".concat(url, "?").concat(baseParams).concat(payloadParams);
|
|
147
147
|
const gzip = !!qs?.attributes?.includes('gzip');
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
148
|
+
|
|
149
|
+
// all gzipped data is already in the correct format and needs no transformation
|
|
150
|
+
// all features going to 'events' endpoint should already be serialized & stringified
|
|
151
|
+
let stringBody = gzip || endpoint === EVENTS ? body : stringify(body);
|
|
153
152
|
|
|
154
153
|
// If body is null, undefined, or an empty object or array after stringifying, send an empty string instead.
|
|
155
|
-
if (!
|
|
154
|
+
if (!stringBody || stringBody.length === 0 || stringBody === '{}' || stringBody === '[]') stringBody = '';
|
|
155
|
+
|
|
156
|
+
// Warn--once per endpoint--if the agent tries to send large payloads
|
|
157
|
+
if (endpoint !== BLOBS && stringBody.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) warn(28, endpoint);
|
|
156
158
|
const headers = [{
|
|
157
159
|
key: 'content-type',
|
|
158
160
|
value: 'text/plain'
|
|
@@ -164,7 +166,7 @@ export function send(agentRef, {
|
|
|
164
166
|
Following the removal of img-element method. */
|
|
165
167
|
let result = submitMethod({
|
|
166
168
|
url: fullUrl,
|
|
167
|
-
body,
|
|
169
|
+
body: stringBody,
|
|
168
170
|
sync: localOpts.isFinalHarvest && isWorkerScope,
|
|
169
171
|
headers
|
|
170
172
|
});
|
|
@@ -184,6 +186,9 @@ export function send(agentRef, {
|
|
|
184
186
|
};
|
|
185
187
|
if (localOpts.needResponse) cbResult.responseText = this.responseText;
|
|
186
188
|
cbFinished(cbResult);
|
|
189
|
+
|
|
190
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
191
|
+
if (!shouldRetry(this.status)) trackHarvestMetadata();
|
|
187
192
|
}, eventListenerOpts(false));
|
|
188
193
|
} else if (submitMethod === fetchMethod) {
|
|
189
194
|
result.then(async function (response) {
|
|
@@ -198,8 +203,33 @@ export function send(agentRef, {
|
|
|
198
203
|
};
|
|
199
204
|
if (localOpts.needResponse) cbResult.responseText = await response.text();
|
|
200
205
|
cbFinished(cbResult);
|
|
206
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
207
|
+
if (!shouldRetry(status)) trackHarvestMetadata();
|
|
201
208
|
});
|
|
202
209
|
}
|
|
210
|
+
function trackHarvestMetadata() {
|
|
211
|
+
try {
|
|
212
|
+
if (featureName === FEATURE_NAMES.jserrors && !body?.err) return;
|
|
213
|
+
const hasReplay = baseParams.includes('hr=1');
|
|
214
|
+
const hasTrace = baseParams.includes('ht=1');
|
|
215
|
+
const hasError = qs?.attributes?.includes('hasError=true');
|
|
216
|
+
handle('harvest-metadata', [{
|
|
217
|
+
[featureName]: {
|
|
218
|
+
...(hasReplay && {
|
|
219
|
+
hasReplay
|
|
220
|
+
}),
|
|
221
|
+
...(hasTrace && {
|
|
222
|
+
hasTrace
|
|
223
|
+
}),
|
|
224
|
+
...(hasError && {
|
|
225
|
+
hasError
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
}], undefined, FEATURE_NAMES.metrics, agentRef.ee);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
// do nothing
|
|
231
|
+
}
|
|
232
|
+
}
|
|
203
233
|
}
|
|
204
234
|
dispatchGlobalEvent({
|
|
205
235
|
agentIdentifier: agentRef.agentIdentifier,
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function evaluateHarvestMetadata(pageMetadata) {
|
|
7
|
+
try {
|
|
8
|
+
const supportabilityTags = [];
|
|
9
|
+
|
|
10
|
+
// Report SM like... audit/<feature_name>/<hasReplay|hasTrace|hasError>/<true|false>/<negative|positive>
|
|
11
|
+
const formTag = (...strings) => strings.join('/');
|
|
12
|
+
|
|
13
|
+
// Track if replay/trace/error harvests actually occurred (key only exists when harvested)
|
|
14
|
+
function evaluateTag(feature, flag, hasFlag, hasHarvest) {
|
|
15
|
+
const AUDIT = 'audit';
|
|
16
|
+
if (hasFlag) {
|
|
17
|
+
// False positive: flag true, but no harvest
|
|
18
|
+
if (!hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'positive'));
|
|
19
|
+
// True positive (correct)
|
|
20
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'positive'));
|
|
21
|
+
} else {
|
|
22
|
+
// False negative: flag false, but harvest occurred
|
|
23
|
+
if (hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'negative'));
|
|
24
|
+
// True negative (correct)
|
|
25
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'negative'));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (pageMetadata.page_view_event) {
|
|
29
|
+
evaluateTag('page_view', 'hasReplay', pageMetadata.page_view_event.hasReplay, !!pageMetadata.session_replay);
|
|
30
|
+
evaluateTag('page_view', 'hasTrace', pageMetadata.page_view_event.hasTrace, !!pageMetadata.session_trace);
|
|
31
|
+
}
|
|
32
|
+
if (pageMetadata.session_replay) {
|
|
33
|
+
evaluateTag('session_replay', 'hasError', pageMetadata.session_replay.hasError, !!pageMetadata.jserrors);
|
|
34
|
+
}
|
|
35
|
+
return supportabilityTags;
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return [];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -11,6 +11,7 @@ import { windowAddEventListener } from '../../../common/event-listener/event-lis
|
|
|
11
11
|
import { isBrowserScope, isWorkerScope } from '../../../common/constants/runtime';
|
|
12
12
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
13
13
|
import { isIFrameWindow } from '../../../common/dom/iframe';
|
|
14
|
+
import { evaluateHarvestMetadata } from './harvest-metadata';
|
|
14
15
|
// import { WEBSOCKET_TAG } from '../../../common/wrap/wrap-websocket'
|
|
15
16
|
// import { handleWebsocketEvents } from './websocket-detection'
|
|
16
17
|
|
|
@@ -19,6 +20,15 @@ export class Aggregate extends AggregateBase {
|
|
|
19
20
|
constructor(agentRef) {
|
|
20
21
|
super(agentRef, FEATURE_NAME);
|
|
21
22
|
this.harvestOpts.aggregatorTypes = ['cm', 'sm']; // the types in EventAggregator this feature cares about
|
|
23
|
+
|
|
24
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
25
|
+
this.harvestMetadata = {};
|
|
26
|
+
this.harvestOpts.beforeUnload = () => {
|
|
27
|
+
evaluateHarvestMetadata(this.harvestMetadata).forEach(smTag => {
|
|
28
|
+
this.storeSupportabilityMetrics(smTag);
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
22
32
|
// This feature only harvests once per potential EoL of the page, which is handled by the central harvester.
|
|
23
33
|
|
|
24
34
|
// this must be read/stored synchronously, as the currentScript is removed from the DOM after this script is executed and this lookup will be void
|
|
@@ -138,6 +148,17 @@ export class Aggregate extends AggregateBase {
|
|
|
138
148
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
139
149
|
// }, this.featureName, this.ee)
|
|
140
150
|
// })
|
|
151
|
+
|
|
152
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
153
|
+
registerHandler('harvest-metadata', (harvestMetadataObject = {}) => {
|
|
154
|
+
try {
|
|
155
|
+
Object.keys(harvestMetadataObject).forEach(key => {
|
|
156
|
+
Object.assign(this.harvestMetadata[key] ??= {}, harvestMetadataObject[key]);
|
|
157
|
+
});
|
|
158
|
+
} catch (e) {
|
|
159
|
+
// failed to merge harvest metadata... ignore
|
|
160
|
+
}
|
|
161
|
+
}, this.featureName, this.ee);
|
|
141
162
|
}
|
|
142
163
|
eachSessionChecks() {
|
|
143
164
|
if (!isBrowserScope) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/monkey-patched.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/target.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/cause-string.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/aggregate/trace/utils.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/entity-manager.js","../src/features/utils/event-buffer.js","../src/features/utils/event-store-manager.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register-api.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.7.3"}
|
|
1
|
+
{"root":["../src/index.js","../src/cdn/experimental.js","../src/cdn/lite.js","../src/cdn/pro.js","../src/cdn/spa.js","../src/common/aggregate/aggregator.js","../src/common/aggregate/event-aggregator.js","../src/common/config/configurable.js","../src/common/config/info.js","../src/common/config/init-types.js","../src/common/config/init.js","../src/common/config/loader-config.js","../src/common/config/runtime.js","../src/common/constants/agent-constants.js","../src/common/constants/env.cdn.js","../src/common/constants/env.js","../src/common/constants/env.npm.js","../src/common/constants/runtime.js","../src/common/constants/shared-channel.js","../src/common/deny-list/deny-list.js","../src/common/dispatch/global-event.js","../src/common/dom/iframe.js","../src/common/dom/query-selector.js","../src/common/dom/selector-path.js","../src/common/drain/drain.js","../src/common/event-emitter/contextual-ee.js","../src/common/event-emitter/event-context.js","../src/common/event-emitter/handle.js","../src/common/event-emitter/register-handler.js","../src/common/event-listener/event-listener-opts.js","../src/common/harvest/harvester.js","../src/common/harvest/types.js","../src/common/ids/bundle-id.js","../src/common/ids/id.js","../src/common/ids/unique-id.js","../src/common/serialize/bel-serializer.js","../src/common/session/constants.js","../src/common/session/session-entity.js","../src/common/storage/local-storage.js","../src/common/timer/interaction-timer.js","../src/common/timer/timer.js","../src/common/timing/nav-timing.js","../src/common/timing/now.js","../src/common/timing/time-keeper.js","../src/common/unload/eol.js","../src/common/url/canonicalize-url.js","../src/common/url/clean-url.js","../src/common/url/encode.js","../src/common/url/location.js","../src/common/url/parse-url.js","../src/common/url/protocol.js","../src/common/util/attribute-size.js","../src/common/util/console.js","../src/common/util/data-size.js","../src/common/util/event-origin.js","../src/common/util/feature-flags.js","../src/common/util/get-or-set.js","../src/common/util/invoke.js","../src/common/util/monkey-patched.js","../src/common/util/obfuscate.js","../src/common/util/stringify.js","../src/common/util/submit-data.js","../src/common/util/target.js","../src/common/util/text.js","../src/common/util/traverse.js","../src/common/util/type-check.js","../src/common/vitals/constants.js","../src/common/vitals/cumulative-layout-shift.js","../src/common/vitals/first-contentful-paint.js","../src/common/vitals/first-paint.js","../src/common/vitals/interaction-to-next-paint.js","../src/common/vitals/largest-contentful-paint.js","../src/common/vitals/time-to-first-byte.js","../src/common/vitals/vital-metric.js","../src/common/window/load.js","../src/common/window/nreum.js","../src/common/window/page-visibility.js","../src/common/wrap/wrap-events.js","../src/common/wrap/wrap-fetch.js","../src/common/wrap/wrap-function.js","../src/common/wrap/wrap-history.js","../src/common/wrap/wrap-jsonp.js","../src/common/wrap/wrap-logger.js","../src/common/wrap/wrap-mutation.js","../src/common/wrap/wrap-promise.js","../src/common/wrap/wrap-timer.js","../src/common/wrap/wrap-websocket.js","../src/common/wrap/wrap-xhr.js","../src/features/ajax/constants.js","../src/features/ajax/index.js","../src/features/ajax/aggregate/gql.js","../src/features/ajax/aggregate/index.js","../src/features/ajax/instrument/distributed-tracing.js","../src/features/ajax/instrument/index.js","../src/features/ajax/instrument/response-size.js","../src/features/generic_events/constants.js","../src/features/generic_events/index.js","../src/features/generic_events/aggregate/index.js","../src/features/generic_events/aggregate/user-actions/aggregated-user-action.js","../src/features/generic_events/aggregate/user-actions/user-actions-aggregator.js","../src/features/generic_events/instrument/index.js","../src/features/jserrors/constants.js","../src/features/jserrors/index.js","../src/features/jserrors/aggregate/canonical-function-name.js","../src/features/jserrors/aggregate/cause-string.js","../src/features/jserrors/aggregate/compute-stack-trace.js","../src/features/jserrors/aggregate/format-stack-trace.js","../src/features/jserrors/aggregate/index.js","../src/features/jserrors/aggregate/internal-errors.js","../src/features/jserrors/aggregate/string-hash-code.js","../src/features/jserrors/instrument/index.js","../src/features/jserrors/shared/cast-error.js","../src/features/jserrors/shared/uncaught-error.js","../src/features/logging/constants.js","../src/features/logging/index.js","../src/features/logging/aggregate/index.js","../src/features/logging/instrument/index.js","../src/features/logging/shared/log.js","../src/features/logging/shared/utils.js","../src/features/metrics/constants.js","../src/features/metrics/index.js","../src/features/metrics/aggregate/framework-detection.js","../src/features/metrics/aggregate/harvest-metadata.js","../src/features/metrics/aggregate/index.js","../src/features/metrics/aggregate/websocket-detection.js","../src/features/metrics/instrument/index.js","../src/features/page_action/constants.js","../src/features/page_action/index.js","../src/features/page_action/instrument/index.js","../src/features/page_view_event/constants.js","../src/features/page_view_event/index.js","../src/features/page_view_event/aggregate/index.js","../src/features/page_view_event/aggregate/initialized-features.js","../src/features/page_view_event/instrument/index.js","../src/features/page_view_timing/constants.js","../src/features/page_view_timing/index.js","../src/features/page_view_timing/aggregate/index.js","../src/features/page_view_timing/instrument/index.js","../src/features/session_replay/constants.js","../src/features/session_replay/index.js","../src/features/session_replay/aggregate/index.js","../src/features/session_replay/instrument/index.js","../src/features/session_replay/shared/recorder-events.js","../src/features/session_replay/shared/recorder.js","../src/features/session_replay/shared/stylesheet-evaluator.js","../src/features/session_replay/shared/utils.js","../src/features/session_trace/constants.js","../src/features/session_trace/index.js","../src/features/session_trace/aggregate/index.js","../src/features/session_trace/aggregate/trace/node.js","../src/features/session_trace/aggregate/trace/storage.js","../src/features/session_trace/aggregate/trace/utils.js","../src/features/session_trace/instrument/index.js","../src/features/soft_navigations/constants.js","../src/features/soft_navigations/index.js","../src/features/soft_navigations/aggregate/ajax-node.js","../src/features/soft_navigations/aggregate/bel-node.js","../src/features/soft_navigations/aggregate/index.js","../src/features/soft_navigations/aggregate/initial-page-load-interaction.js","../src/features/soft_navigations/aggregate/interaction.js","../src/features/soft_navigations/instrument/index.js","../src/features/spa/constants.js","../src/features/spa/index.js","../src/features/spa/aggregate/index.js","../src/features/spa/aggregate/interaction-node.js","../src/features/spa/aggregate/interaction.js","../src/features/spa/aggregate/serializer.js","../src/features/spa/instrument/index.js","../src/features/utils/agent-session.js","../src/features/utils/aggregate-base.js","../src/features/utils/entity-manager.js","../src/features/utils/event-buffer.js","../src/features/utils/event-store-manager.js","../src/features/utils/feature-base.js","../src/features/utils/feature-gates.js","../src/features/utils/instrument-base.js","../src/features/utils/nr1-debugger.js","../src/interfaces/registered-entity.js","../src/loaders/agent-base.js","../src/loaders/agent.js","../src/loaders/api-base.js","../src/loaders/browser-agent.js","../src/loaders/micro-agent-base.js","../src/loaders/micro-agent.js","../src/loaders/api/addPageAction.js","../src/loaders/api/addRelease.js","../src/loaders/api/addToTrace.js","../src/loaders/api/constants.js","../src/loaders/api/finished.js","../src/loaders/api/interaction-types.js","../src/loaders/api/interaction.js","../src/loaders/api/log.js","../src/loaders/api/measure.js","../src/loaders/api/noticeError.js","../src/loaders/api/pauseReplay.js","../src/loaders/api/recordCustomEvent.js","../src/loaders/api/recordReplay.js","../src/loaders/api/register-api-types.js","../src/loaders/api/register-api.js","../src/loaders/api/register.js","../src/loaders/api/setApplicationVersion.js","../src/loaders/api/setCustomAttribute.js","../src/loaders/api/setErrorHandler.js","../src/loaders/api/setPageViewName.js","../src/loaders/api/setUserId.js","../src/loaders/api/sharedHandlers.js","../src/loaders/api/start.js","../src/loaders/api/topLevelCallers.js","../src/loaders/api/wrapLogger.js","../src/loaders/configure/configure.js","../src/loaders/configure/nonce.js","../src/loaders/configure/public-path.js","../src/loaders/features/enabled-features.js","../src/loaders/features/featureDependencies.js","../src/loaders/features/features.js"],"version":"5.7.3"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harvester.d.ts","sourceRoot":"","sources":["../../../../src/common/harvest/harvester.js"],"names":[],"mappings":"AA6GA;;;;IAII;AACJ;;;;;;;;;IAFc,OAAO,
|
|
1
|
+
{"version":3,"file":"harvester.d.ts","sourceRoot":"","sources":["../../../../src/common/harvest/harvester.js"],"names":[],"mappings":"AA6GA;;;;IAII;AACJ;;;;;;;;;IAFc,OAAO,CA0HpB;AAnND;IAIE,2BAUC;IAZD,6BAA0B;IAGxB,cAAwB;IAW1B,wCASC;IAED;;;;;OAKG;IACH,iCAJW,MAAM,cACN,MAAM,GACJ,OAAO,CA+CnB;;CACF;8BAGY,OAAO,YAAY,EAAE,eAAe"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest-metadata.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/harvest-metadata.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kEAoCC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export class Aggregate extends AggregateBase {
|
|
2
2
|
static featureName: string;
|
|
3
3
|
constructor(agentRef: any);
|
|
4
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
5
|
+
harvestMetadata: {};
|
|
4
6
|
agentNonce: string | false | undefined;
|
|
5
7
|
preHarvestChecks(opts: any): any;
|
|
6
8
|
storeSupportabilityMetrics(name: any, value: any): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAiBA;IACE,2BAAiC;IACjC,2BAgCC;IA5BC,uKAAuK;IACvK,oBAAyB;IAWzB,uCAAiE;IAkBnE,iCAAsE;IAEtE,wDAKC;IAED,iDAKC;IAED,qBAgFC;IAED,0BAOC;CACF;8BApJ6B,4BAA4B"}
|
package/package.json
CHANGED
|
@@ -135,14 +135,16 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
|
|
|
135
135
|
|
|
136
136
|
const fullUrl = `${url}?${baseParams}${payloadParams}`
|
|
137
137
|
const gzip = !!qs?.attributes?.includes('gzip')
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
}
|
|
138
|
+
|
|
139
|
+
// all gzipped data is already in the correct format and needs no transformation
|
|
140
|
+
// all features going to 'events' endpoint should already be serialized & stringified
|
|
141
|
+
let stringBody = gzip || endpoint === EVENTS ? body : stringify(body)
|
|
143
142
|
|
|
144
143
|
// If body is null, undefined, or an empty object or array after stringifying, send an empty string instead.
|
|
145
|
-
if (!
|
|
144
|
+
if (!stringBody || stringBody.length === 0 || stringBody === '{}' || stringBody === '[]') stringBody = ''
|
|
145
|
+
|
|
146
|
+
// Warn--once per endpoint--if the agent tries to send large payloads
|
|
147
|
+
if (endpoint !== BLOBS && stringBody.length > 750000 && (warnings[endpoint] = (warnings[endpoint] || 0) + 1) === 1) warn(28, endpoint)
|
|
146
148
|
|
|
147
149
|
const headers = [{ key: 'content-type', value: 'text/plain' }]
|
|
148
150
|
|
|
@@ -150,7 +152,7 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
|
|
|
150
152
|
Because they still do permit synch XHR, the idea is that at final harvest time (worker is closing),
|
|
151
153
|
we just make a BLOCKING request--trivial impact--with the remaining data as a temp fill-in for sendBeacon.
|
|
152
154
|
Following the removal of img-element method. */
|
|
153
|
-
let result = submitMethod({ url: fullUrl, body, sync: localOpts.isFinalHarvest && isWorkerScope, headers })
|
|
155
|
+
let result = submitMethod({ url: fullUrl, body: stringBody, sync: localOpts.isFinalHarvest && isWorkerScope, headers })
|
|
154
156
|
|
|
155
157
|
if (!localOpts.isFinalHarvest && cbFinished) { // final harvests don't hold onto buffer data (shouldRetryOnFail is false), so cleanup isn't needed
|
|
156
158
|
if (submitMethod === xhrMethod) {
|
|
@@ -160,6 +162,9 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
|
|
|
160
162
|
const cbResult = { sent: this.status !== 0, status: this.status, retry: shouldRetry(this.status), fullUrl, xhr: this, targetApp }
|
|
161
163
|
if (localOpts.needResponse) cbResult.responseText = this.responseText
|
|
162
164
|
cbFinished(cbResult)
|
|
165
|
+
|
|
166
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
167
|
+
if (!shouldRetry(this.status)) trackHarvestMetadata()
|
|
163
168
|
}, eventListenerOpts(false))
|
|
164
169
|
} else if (submitMethod === fetchMethod) {
|
|
165
170
|
result.then(async function (response) {
|
|
@@ -167,8 +172,30 @@ export function send (agentRef, { endpoint, targetApp, payload, localOpts = {},
|
|
|
167
172
|
const cbResult = { sent: true, status, retry: shouldRetry(status), fullUrl, fetchResponse: response, targetApp }
|
|
168
173
|
if (localOpts.needResponse) cbResult.responseText = await response.text()
|
|
169
174
|
cbFinished(cbResult)
|
|
175
|
+
/** temporary audit of consistency of harvest metadata flags */
|
|
176
|
+
if (!shouldRetry(status)) trackHarvestMetadata()
|
|
170
177
|
})
|
|
171
178
|
}
|
|
179
|
+
|
|
180
|
+
function trackHarvestMetadata () {
|
|
181
|
+
try {
|
|
182
|
+
if (featureName === FEATURE_NAMES.jserrors && !body?.err) return
|
|
183
|
+
|
|
184
|
+
const hasReplay = baseParams.includes('hr=1')
|
|
185
|
+
const hasTrace = baseParams.includes('ht=1')
|
|
186
|
+
const hasError = qs?.attributes?.includes('hasError=true')
|
|
187
|
+
|
|
188
|
+
handle('harvest-metadata', [{
|
|
189
|
+
[featureName]: {
|
|
190
|
+
...(hasReplay && { hasReplay }),
|
|
191
|
+
...(hasTrace && { hasTrace }),
|
|
192
|
+
...(hasError && { hasError })
|
|
193
|
+
}
|
|
194
|
+
}], undefined, FEATURE_NAMES.metrics, agentRef.ee)
|
|
195
|
+
} catch (err) {
|
|
196
|
+
// do nothing
|
|
197
|
+
}
|
|
198
|
+
}
|
|
172
199
|
}
|
|
173
200
|
|
|
174
201
|
dispatchGlobalEvent({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2020-2025 New Relic, Inc. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export function evaluateHarvestMetadata (pageMetadata) {
|
|
7
|
+
try {
|
|
8
|
+
const supportabilityTags = []
|
|
9
|
+
|
|
10
|
+
// Report SM like... audit/<feature_name>/<hasReplay|hasTrace|hasError>/<true|false>/<negative|positive>
|
|
11
|
+
const formTag = (...strings) => strings.join('/')
|
|
12
|
+
|
|
13
|
+
// Track if replay/trace/error harvests actually occurred (key only exists when harvested)
|
|
14
|
+
function evaluateTag (feature, flag, hasFlag, hasHarvest) {
|
|
15
|
+
const AUDIT = 'audit'
|
|
16
|
+
if (hasFlag) {
|
|
17
|
+
// False positive: flag true, but no harvest
|
|
18
|
+
if (!hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'positive'))
|
|
19
|
+
// True positive (correct)
|
|
20
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'positive'))
|
|
21
|
+
} else {
|
|
22
|
+
// False negative: flag false, but harvest occurred
|
|
23
|
+
if (hasHarvest) supportabilityTags.push(formTag(AUDIT, feature, flag, 'false', 'negative'))
|
|
24
|
+
// True negative (correct)
|
|
25
|
+
else supportabilityTags.push(formTag(AUDIT, feature, flag, 'true', 'negative'))
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (pageMetadata.page_view_event) {
|
|
30
|
+
evaluateTag('page_view', 'hasReplay', pageMetadata.page_view_event.hasReplay, !!pageMetadata.session_replay)
|
|
31
|
+
evaluateTag('page_view', 'hasTrace', pageMetadata.page_view_event.hasTrace, !!pageMetadata.session_trace)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (pageMetadata.session_replay) {
|
|
35
|
+
evaluateTag('session_replay', 'hasError', pageMetadata.session_replay.hasError, !!pageMetadata.jserrors)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return supportabilityTags
|
|
39
|
+
} catch (err) {
|
|
40
|
+
return []
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -11,6 +11,7 @@ import { windowAddEventListener } from '../../../common/event-listener/event-lis
|
|
|
11
11
|
import { isBrowserScope, isWorkerScope } from '../../../common/constants/runtime'
|
|
12
12
|
import { AggregateBase } from '../../utils/aggregate-base'
|
|
13
13
|
import { isIFrameWindow } from '../../../common/dom/iframe'
|
|
14
|
+
import { evaluateHarvestMetadata } from './harvest-metadata'
|
|
14
15
|
// import { WEBSOCKET_TAG } from '../../../common/wrap/wrap-websocket'
|
|
15
16
|
// import { handleWebsocketEvents } from './websocket-detection'
|
|
16
17
|
|
|
@@ -19,6 +20,15 @@ export class Aggregate extends AggregateBase {
|
|
|
19
20
|
constructor (agentRef) {
|
|
20
21
|
super(agentRef, FEATURE_NAME)
|
|
21
22
|
this.harvestOpts.aggregatorTypes = ['cm', 'sm'] // the types in EventAggregator this feature cares about
|
|
23
|
+
|
|
24
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
25
|
+
this.harvestMetadata = {}
|
|
26
|
+
this.harvestOpts.beforeUnload = () => {
|
|
27
|
+
evaluateHarvestMetadata(this.harvestMetadata).forEach(smTag => {
|
|
28
|
+
this.storeSupportabilityMetrics(smTag)
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
22
32
|
// This feature only harvests once per potential EoL of the page, which is handled by the central harvester.
|
|
23
33
|
|
|
24
34
|
// this must be read/stored synchronously, as the currentScript is removed from the DOM after this script is executed and this lookup will be void
|
|
@@ -126,6 +136,17 @@ export class Aggregate extends AggregateBase {
|
|
|
126
136
|
// handleWebsocketEvents(this.storeSupportabilityMetrics.bind(this), tag, ...args)
|
|
127
137
|
// }, this.featureName, this.ee)
|
|
128
138
|
// })
|
|
139
|
+
|
|
140
|
+
/** all the harvest metadata metrics need to be evaluated simulataneously at unload time so just temporarily buffer them and dont make SMs immediately from the data */
|
|
141
|
+
registerHandler('harvest-metadata', (harvestMetadataObject = {}) => {
|
|
142
|
+
try {
|
|
143
|
+
Object.keys(harvestMetadataObject).forEach(key => {
|
|
144
|
+
Object.assign(this.harvestMetadata[key] ??= {}, harvestMetadataObject[key])
|
|
145
|
+
})
|
|
146
|
+
} catch (e) {
|
|
147
|
+
// failed to merge harvest metadata... ignore
|
|
148
|
+
}
|
|
149
|
+
}, this.featureName, this.ee)
|
|
129
150
|
}
|
|
130
151
|
|
|
131
152
|
eachSessionChecks () {
|