@newrelic/browser-agent 1.274.0 → 1.275.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 +13 -0
- 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/harvest.js +21 -0
- package/dist/cjs/common/util/submit-data.js +42 -5
- package/dist/cjs/common/wrap/wrap-events.js +1 -1
- package/dist/cjs/common/wrap/wrap-logger.js +5 -1
- package/dist/cjs/common/wrap/wrap-xhr.js +1 -0
- package/dist/cjs/features/generic_events/aggregate/index.js +10 -10
- 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/harvest.js +21 -0
- package/dist/esm/common/util/submit-data.js +41 -5
- package/dist/esm/common/wrap/wrap-events.js +1 -1
- package/dist/esm/common/wrap/wrap-logger.js +5 -2
- package/dist/esm/common/wrap/wrap-xhr.js +1 -0
- package/dist/esm/features/generic_events/aggregate/index.js +10 -10
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/util/submit-data.d.ts +18 -1
- package/dist/types/common/util/submit-data.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-logger.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +0 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/harvest/harvest.js +19 -0
- package/src/common/util/submit-data.js +37 -4
- package/src/common/wrap/wrap-events.js +1 -1
- package/src/common/wrap/wrap-logger.js +7 -2
- package/src/common/wrap/wrap-xhr.js +2 -0
- package/src/features/generic_events/aggregate/index.js +10 -12
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,19 @@
|
|
|
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.275.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.274.0...v1.275.0) (2024-12-03)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Allow logs api wrapper to update custom attributes ([#1265](https://github.com/newrelic/newrelic-browser-agent/issues/1265)) ([8d10e14](https://github.com/newrelic/newrelic-browser-agent/commit/8d10e14953f9a5b9ba97e865ba5476fc527ba384))
|
|
12
|
+
* Enable the browser agent to run in extension background contexts ([#1206](https://github.com/newrelic/newrelic-browser-agent/issues/1206)) ([37e976b](https://github.com/newrelic/newrelic-browser-agent/commit/37e976bf360c209efd163855e7fbe84d665e444b))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* Harvest generic events when max size is reached ([#1250](https://github.com/newrelic/newrelic-browser-agent/issues/1250)) ([e00a469](https://github.com/newrelic/newrelic-browser-agent/commit/e00a46975bcc93c48798bd9153f3a503998b0915))
|
|
18
|
+
|
|
6
19
|
## [1.274.0](https://github.com/newrelic/newrelic-browser-agent/compare/v1.273.1...v1.274.0) (2024-11-19)
|
|
7
20
|
|
|
8
21
|
|
|
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
12
12
|
/**
|
|
13
13
|
* Exposes the version of the agent
|
|
14
14
|
*/
|
|
15
|
-
const VERSION = exports.VERSION = "1.
|
|
15
|
+
const VERSION = exports.VERSION = "1.275.0";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the build type of the agent
|
|
@@ -12,7 +12,7 @@ exports.VERSION = exports.RRWEB_VERSION = exports.DIST_METHOD = exports.BUILD_EN
|
|
|
12
12
|
/**
|
|
13
13
|
* Exposes the version of the agent
|
|
14
14
|
*/
|
|
15
|
-
const VERSION = exports.VERSION = "1.
|
|
15
|
+
const VERSION = exports.VERSION = "1.275.0";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Exposes the build type of the agent
|
|
@@ -174,6 +174,27 @@ class Harvest extends _sharedContext.SharedContext {
|
|
|
174
174
|
}
|
|
175
175
|
cbFinished(cbResult);
|
|
176
176
|
}, (0, _eventListenerOpts.eventListenerOpts)(false));
|
|
177
|
+
} else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
|
|
178
|
+
const harvestScope = this;
|
|
179
|
+
result.then(async function (response) {
|
|
180
|
+
const status = response.status;
|
|
181
|
+
const cbResult = {
|
|
182
|
+
sent: true,
|
|
183
|
+
status,
|
|
184
|
+
fullUrl,
|
|
185
|
+
fetchResponse: response
|
|
186
|
+
};
|
|
187
|
+
if (response.status === 429) {
|
|
188
|
+
cbResult.retry = true;
|
|
189
|
+
cbResult.delay = harvestScope.tooManyRequestsDelay;
|
|
190
|
+
} else if (status === 408 || status === 500 || status === 503) {
|
|
191
|
+
cbResult.retry = true;
|
|
192
|
+
}
|
|
193
|
+
if (opts.needResponse) {
|
|
194
|
+
cbResult.responseText = await response.text();
|
|
195
|
+
}
|
|
196
|
+
cbFinished(cbResult);
|
|
197
|
+
});
|
|
177
198
|
}
|
|
178
199
|
return result;
|
|
179
200
|
}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.beacon = beacon;
|
|
7
7
|
exports.getSubmitMethod = getSubmitMethod;
|
|
8
8
|
exports.xhr = xhr;
|
|
9
|
+
exports.xhrFetch = xhrFetch;
|
|
9
10
|
var _runtime = require("../constants/runtime");
|
|
10
11
|
/**
|
|
11
12
|
* @file Contains common methods used to transmit harvested data.
|
|
@@ -26,11 +27,47 @@ var _runtime = require("../constants/runtime");
|
|
|
26
27
|
function getSubmitMethod({
|
|
27
28
|
isFinalHarvest = false
|
|
28
29
|
} = {}) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (isFinalHarvest && _runtime.isBrowserScope) {
|
|
31
|
+
// Use sendBeacon for final harvest
|
|
32
|
+
return beacon;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// If not final harvest, or not browserScope, use XHR post if available
|
|
36
|
+
if (typeof XMLHttpRequest !== 'undefined') {
|
|
37
|
+
return xhr;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Fallback for web workers where XMLHttpRequest is not available
|
|
41
|
+
return xhrFetch;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* @param url
|
|
47
|
+
* @param body
|
|
48
|
+
* @param method
|
|
49
|
+
* @param headers
|
|
50
|
+
* @returns {Promise<Response>}
|
|
51
|
+
*/
|
|
52
|
+
function xhrFetch({
|
|
53
|
+
url,
|
|
54
|
+
body = null,
|
|
55
|
+
method = 'POST',
|
|
56
|
+
headers = [{
|
|
57
|
+
key: 'content-type',
|
|
58
|
+
value: 'text/plain'
|
|
59
|
+
}]
|
|
60
|
+
}) {
|
|
61
|
+
const objHeaders = {};
|
|
62
|
+
for (const header of headers) {
|
|
63
|
+
objHeaders[header.key] = header.value;
|
|
64
|
+
}
|
|
65
|
+
return fetch(url, {
|
|
66
|
+
headers: objHeaders,
|
|
67
|
+
method,
|
|
68
|
+
body,
|
|
69
|
+
credentials: 'include'
|
|
70
|
+
});
|
|
34
71
|
}
|
|
35
72
|
|
|
36
73
|
/**
|
|
@@ -44,8 +44,8 @@ function wrapEvents(sharedEE) {
|
|
|
44
44
|
// Guard against instrumenting environments w/o necessary features
|
|
45
45
|
if ('getPrototypeOf' in Object) {
|
|
46
46
|
if (_runtime.isBrowserScope) findEventListenerProtoAndCb(document, wrapNode);
|
|
47
|
+
if (XHR) findEventListenerProtoAndCb(XHR.prototype, wrapNode);
|
|
47
48
|
findEventListenerProtoAndCb(_runtime.globalScope, wrapNode);
|
|
48
|
-
findEventListenerProtoAndCb(XHR.prototype, wrapNode);
|
|
49
49
|
}
|
|
50
50
|
ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {
|
|
51
51
|
var originalListener = args[1];
|
|
@@ -18,6 +18,8 @@ var _wrapFunction = require("./wrap-function");
|
|
|
18
18
|
* This module is used by: jserrors, spa.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
const contextMap = new Map();
|
|
22
|
+
|
|
21
23
|
/**
|
|
22
24
|
* Wraps a supplied function and adds emitter events under the `-wrap-logger-` prefix
|
|
23
25
|
* @param {Object} sharedEE - The shared event emitter on which a new scoped event emitter will be based.
|
|
@@ -38,9 +40,11 @@ function wrapLogger(sharedEE, parent, loggerFn, context) {
|
|
|
38
40
|
const ctx = new _eventContext.EventContext(_contextualEe.contextId);
|
|
39
41
|
ctx.level = context.level;
|
|
40
42
|
ctx.customAttributes = context.customAttributes;
|
|
43
|
+
const contextLookupKey = parent[loggerFn]?.[_wrapFunction.flag] || parent[loggerFn];
|
|
44
|
+
contextMap.set(contextLookupKey, ctx);
|
|
41
45
|
|
|
42
46
|
/** observe calls to <loggerFn> and emit events prefixed with `wrap-logger-` */
|
|
43
|
-
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-',
|
|
47
|
+
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-', () => contextMap.get(contextLookupKey));
|
|
44
48
|
return ee;
|
|
45
49
|
}
|
|
46
50
|
|
|
@@ -33,6 +33,7 @@ const XHR_PROPS = ['open', 'send']; // these are the specific funcs being wrappe
|
|
|
33
33
|
function wrapXhr(sharedEE) {
|
|
34
34
|
var baseEE = sharedEE || _contextualEe.ee;
|
|
35
35
|
const ee = scopedEE(baseEE);
|
|
36
|
+
if (typeof _runtime.globalScope.XMLHttpRequest === 'undefined') return ee;
|
|
36
37
|
|
|
37
38
|
// Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
|
|
38
39
|
// then we increment the count to track # of feats using this at runtime.
|
|
@@ -15,7 +15,6 @@ var _now = require("../../../common/timing/now");
|
|
|
15
15
|
var _registerHandler = require("../../../common/event-emitter/register-handler");
|
|
16
16
|
var _constants2 = require("../../metrics/constants");
|
|
17
17
|
var _traverse = require("../../../common/util/traverse");
|
|
18
|
-
var _agentConstants = require("../../../common/constants/agent-constants");
|
|
19
18
|
var _features = require("../../../loaders/features/features");
|
|
20
19
|
var _userActionsAggregator = require("./user-actions/user-actions-aggregator");
|
|
21
20
|
var _iframe = require("../../../common/dom/iframe");
|
|
@@ -188,8 +187,16 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
188
187
|
/** Event-specific attributes take precedence over agent-level custom attributes and fallbacks */
|
|
189
188
|
...obj
|
|
190
189
|
};
|
|
191
|
-
this.events.add(eventAttributes);
|
|
192
|
-
this.
|
|
190
|
+
const addedEvent = this.events.add(eventAttributes);
|
|
191
|
+
if (!addedEvent && !this.events.isEmpty()) {
|
|
192
|
+
/** could not add the event because it pushed the buffer over the limit
|
|
193
|
+
* so we harvest early, and try to add it again now that the buffer is cleared
|
|
194
|
+
* if it fails again, we do nothing
|
|
195
|
+
*/
|
|
196
|
+
this.ee.emit(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
|
|
197
|
+
this.harvestScheduler.runHarvest();
|
|
198
|
+
this.events.add(eventAttributes);
|
|
199
|
+
}
|
|
193
200
|
}
|
|
194
201
|
serializer(eventBuffer) {
|
|
195
202
|
return (0, _traverse.applyFnToProps)({
|
|
@@ -202,12 +209,5 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
202
209
|
at: this.agentRef.info.atts
|
|
203
210
|
};
|
|
204
211
|
}
|
|
205
|
-
checkEventLimits() {
|
|
206
|
-
// check if we've reached any harvest limits...
|
|
207
|
-
if (this.events.byteSize() > _agentConstants.IDEAL_PAYLOAD_SIZE) {
|
|
208
|
-
this.ee.emit(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
|
|
209
|
-
this.harvestScheduler.runHarvest();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
212
|
}
|
|
213
213
|
exports.Aggregate = Aggregate;
|
|
@@ -166,6 +166,27 @@ export class Harvest extends SharedContext {
|
|
|
166
166
|
}
|
|
167
167
|
cbFinished(cbResult);
|
|
168
168
|
}, eventListenerOpts(false));
|
|
169
|
+
} else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
|
|
170
|
+
const harvestScope = this;
|
|
171
|
+
result.then(async function (response) {
|
|
172
|
+
const status = response.status;
|
|
173
|
+
const cbResult = {
|
|
174
|
+
sent: true,
|
|
175
|
+
status,
|
|
176
|
+
fullUrl,
|
|
177
|
+
fetchResponse: response
|
|
178
|
+
};
|
|
179
|
+
if (response.status === 429) {
|
|
180
|
+
cbResult.retry = true;
|
|
181
|
+
cbResult.delay = harvestScope.tooManyRequestsDelay;
|
|
182
|
+
} else if (status === 408 || status === 500 || status === 503) {
|
|
183
|
+
cbResult.retry = true;
|
|
184
|
+
}
|
|
185
|
+
if (opts.needResponse) {
|
|
186
|
+
cbResult.responseText = await response.text();
|
|
187
|
+
}
|
|
188
|
+
cbFinished(cbResult);
|
|
189
|
+
});
|
|
169
190
|
}
|
|
170
191
|
return result;
|
|
171
192
|
}
|
|
@@ -19,11 +19,47 @@ import { isBrowserScope } from '../constants/runtime';
|
|
|
19
19
|
export function getSubmitMethod({
|
|
20
20
|
isFinalHarvest = false
|
|
21
21
|
} = {}) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
if (isFinalHarvest && isBrowserScope) {
|
|
23
|
+
// Use sendBeacon for final harvest
|
|
24
|
+
return beacon;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// If not final harvest, or not browserScope, use XHR post if available
|
|
28
|
+
if (typeof XMLHttpRequest !== 'undefined') {
|
|
29
|
+
return xhr;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Fallback for web workers where XMLHttpRequest is not available
|
|
33
|
+
return xhrFetch;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
*
|
|
38
|
+
* @param url
|
|
39
|
+
* @param body
|
|
40
|
+
* @param method
|
|
41
|
+
* @param headers
|
|
42
|
+
* @returns {Promise<Response>}
|
|
43
|
+
*/
|
|
44
|
+
export function xhrFetch({
|
|
45
|
+
url,
|
|
46
|
+
body = null,
|
|
47
|
+
method = 'POST',
|
|
48
|
+
headers = [{
|
|
49
|
+
key: 'content-type',
|
|
50
|
+
value: 'text/plain'
|
|
51
|
+
}]
|
|
52
|
+
}) {
|
|
53
|
+
const objHeaders = {};
|
|
54
|
+
for (const header of headers) {
|
|
55
|
+
objHeaders[header.key] = header.value;
|
|
56
|
+
}
|
|
57
|
+
return fetch(url, {
|
|
58
|
+
headers: objHeaders,
|
|
59
|
+
method,
|
|
60
|
+
body,
|
|
61
|
+
credentials: 'include'
|
|
62
|
+
});
|
|
27
63
|
}
|
|
28
64
|
|
|
29
65
|
/**
|
|
@@ -36,8 +36,8 @@ export function wrapEvents(sharedEE) {
|
|
|
36
36
|
// Guard against instrumenting environments w/o necessary features
|
|
37
37
|
if ('getPrototypeOf' in Object) {
|
|
38
38
|
if (isBrowserScope) findEventListenerProtoAndCb(document, wrapNode);
|
|
39
|
+
if (XHR) findEventListenerProtoAndCb(XHR.prototype, wrapNode);
|
|
39
40
|
findEventListenerProtoAndCb(globalScope, wrapNode);
|
|
40
|
-
findEventListenerProtoAndCb(XHR.prototype, wrapNode);
|
|
41
41
|
}
|
|
42
42
|
ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {
|
|
43
43
|
var originalListener = args[1];
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee';
|
|
11
11
|
import { EventContext } from '../event-emitter/event-context';
|
|
12
12
|
import { warn } from '../util/console';
|
|
13
|
-
import { createWrapperWithEmitter as wfn } from './wrap-function';
|
|
13
|
+
import { flag, createWrapperWithEmitter as wfn } from './wrap-function';
|
|
14
|
+
const contextMap = new Map();
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Wraps a supplied function and adds emitter events under the `-wrap-logger-` prefix
|
|
@@ -32,9 +33,11 @@ export function wrapLogger(sharedEE, parent, loggerFn, context) {
|
|
|
32
33
|
const ctx = new EventContext(contextId);
|
|
33
34
|
ctx.level = context.level;
|
|
34
35
|
ctx.customAttributes = context.customAttributes;
|
|
36
|
+
const contextLookupKey = parent[loggerFn]?.[flag] || parent[loggerFn];
|
|
37
|
+
contextMap.set(contextLookupKey, ctx);
|
|
35
38
|
|
|
36
39
|
/** observe calls to <loggerFn> and emit events prefixed with `wrap-logger-` */
|
|
37
|
-
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-',
|
|
40
|
+
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-', () => contextMap.get(contextLookupKey));
|
|
38
41
|
return ee;
|
|
39
42
|
}
|
|
40
43
|
|
|
@@ -26,6 +26,7 @@ const XHR_PROPS = ['open', 'send']; // these are the specific funcs being wrappe
|
|
|
26
26
|
export function wrapXhr(sharedEE) {
|
|
27
27
|
var baseEE = sharedEE || contextualEE;
|
|
28
28
|
const ee = scopedEE(baseEE);
|
|
29
|
+
if (typeof globalScope.XMLHttpRequest === 'undefined') return ee;
|
|
29
30
|
|
|
30
31
|
// Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
|
|
31
32
|
// then we increment the count to track # of feats using this at runtime.
|
|
@@ -13,7 +13,6 @@ import { now } from '../../../common/timing/now';
|
|
|
13
13
|
import { registerHandler } from '../../../common/event-emitter/register-handler';
|
|
14
14
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
|
|
15
15
|
import { applyFnToProps } from '../../../common/util/traverse';
|
|
16
|
-
import { IDEAL_PAYLOAD_SIZE } from '../../../common/constants/agent-constants';
|
|
17
16
|
import { FEATURE_TO_ENDPOINT } from '../../../loaders/features/features';
|
|
18
17
|
import { UserActionsAggregator } from './user-actions/user-actions-aggregator';
|
|
19
18
|
import { isIFrameWindow } from '../../../common/dom/iframe';
|
|
@@ -181,8 +180,16 @@ export class Aggregate extends AggregateBase {
|
|
|
181
180
|
/** Event-specific attributes take precedence over agent-level custom attributes and fallbacks */
|
|
182
181
|
...obj
|
|
183
182
|
};
|
|
184
|
-
this.events.add(eventAttributes);
|
|
185
|
-
this.
|
|
183
|
+
const addedEvent = this.events.add(eventAttributes);
|
|
184
|
+
if (!addedEvent && !this.events.isEmpty()) {
|
|
185
|
+
/** could not add the event because it pushed the buffer over the limit
|
|
186
|
+
* so we harvest early, and try to add it again now that the buffer is cleared
|
|
187
|
+
* if it fails again, we do nothing
|
|
188
|
+
*/
|
|
189
|
+
this.ee.emit(SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
|
|
190
|
+
this.harvestScheduler.runHarvest();
|
|
191
|
+
this.events.add(eventAttributes);
|
|
192
|
+
}
|
|
186
193
|
}
|
|
187
194
|
serializer(eventBuffer) {
|
|
188
195
|
return applyFnToProps({
|
|
@@ -195,11 +202,4 @@ export class Aggregate extends AggregateBase {
|
|
|
195
202
|
at: this.agentRef.info.atts
|
|
196
203
|
};
|
|
197
204
|
}
|
|
198
|
-
checkEventLimits() {
|
|
199
|
-
// check if we've reached any harvest limits...
|
|
200
|
-
if (this.events.byteSize() > IDEAL_PAYLOAD_SIZE) {
|
|
201
|
-
this.ee.emit(SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen']);
|
|
202
|
-
this.harvestScheduler.runHarvest();
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
205
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harvest.d.ts","sourceRoot":"","sources":["../../../../src/common/harvest/harvest.js"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH;IAII,0BAA2H;IAC3H,gBAA2E;IAE3E,YAAiB;IAGnB;;;;;OAKG;IACH,aAFW,eAAe,WAWzB;IAED;;;OAGG;IACH,YAFW,eAAe,WAMzB;IAED;;;;;;OAMG;IACH,gGAJW,eAAe,GACb,OAAO,
|
|
1
|
+
{"version":3,"file":"harvest.d.ts","sourceRoot":"","sources":["../../../../src/common/harvest/harvest.js"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH;IAII,0BAA2H;IAC3H,gBAA2E;IAE3E,YAAiB;IAGnB;;;;;OAKG;IACH,aAFW,eAAe,WAWzB;IAED;;;OAGG;IACH,YAFW,eAAe,WAMzB;IAED;;;;;;OAMG;IACH,gGAJW,eAAe,GACb,OAAO,CAkGnB;IAGD,gDAqBC;IAED;;;;;;;OAOG;IACH,wBALW,yBAAyB,WACzB,6BAA6B,GAE3B,cAAc,CA2B1B;IAED;;;;;;;OAOG;IACH,uBAHW,cAAc,GACZ,cAAc,CAuB1B;IAED;;;;;OAKG;IACH,aAHW,yBAAyB,YACzB,sBAAsB,QAQhC;CACF;8BA1PY,OAAO,YAAY,EAAE,eAAe;wCACpC,OAAO,YAAY,EAAE,yBAAyB;6BAC9C,OAAO,YAAY,EAAE,cAAc;qCACnC,OAAO,YAAY,EAAE,sBAAsB;4CAC3C,OAAO,YAAY,EAAE,6BAA6B;8BAbjC,2BAA2B"}
|
|
@@ -9,7 +9,24 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export function getSubmitMethod({ isFinalHarvest }?: {
|
|
11
11
|
isFinalHarvest: boolean;
|
|
12
|
-
}): typeof xhr | typeof beacon;
|
|
12
|
+
}): typeof xhr | typeof beacon | typeof xhrFetch;
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @param url
|
|
16
|
+
* @param body
|
|
17
|
+
* @param method
|
|
18
|
+
* @param headers
|
|
19
|
+
* @returns {Promise<Response>}
|
|
20
|
+
*/
|
|
21
|
+
export function xhrFetch({ url, body, method, headers }: {
|
|
22
|
+
url: any;
|
|
23
|
+
body?: null | undefined;
|
|
24
|
+
method?: string | undefined;
|
|
25
|
+
headers?: {
|
|
26
|
+
key: string;
|
|
27
|
+
value: string;
|
|
28
|
+
}[] | undefined;
|
|
29
|
+
}): Promise<Response>;
|
|
13
30
|
/**
|
|
14
31
|
* Send via XHR
|
|
15
32
|
* @param {Object} args - The args.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-data.d.ts","sourceRoot":"","sources":["../../../../src/common/util/submit-data.js"],"names":[],"mappings":"AAQA;;GAEG;AAEH;;;;;GAKG;AACH,qDAHG;IAAsB,cAAc,EAA5B,OAAO;CAEjB,
|
|
1
|
+
{"version":3,"file":"submit-data.d.ts","sourceRoot":"","sources":["../../../../src/common/util/submit-data.js"],"names":[],"mappings":"AAQA;;GAEG;AAEH;;;;;GAKG;AACH,qDAHG;IAAsB,cAAc,EAA5B,OAAO;CAEjB,gDAcA;AAED;;;;;;;GAOG;AACH;;;;;;;;IAFa,OAAO,CAAC,QAAQ,CAAC,CAkB7B;AAED;;;;;;;;;GASG;AACH,0DAPG;IAAqB,GAAG,EAAhB,MAAM;IACQ,IAAI,GAAlB,MAAM,YAAC;IACQ,IAAI,GAAnB,OAAO,YAAC;IACO,MAAM,GAArB,MAAM,YAAC;IAC+B,OAAO;aAAvC,MAAM;eAAS,MAAM;;CACnC,GAAU,cAAc,CAmB1B;AAED;;;;;;GAMG;AACH,sCAJG;IAAqB,GAAG,EAAhB,MAAM;IACQ,IAAI,GAAlB,MAAM,YAAC;CACf,GAAU,OAAO,CAanB;6BAjGY,0BAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"AAgBA;;;;;;GAMG;AAEH,qCANW,MAAM,UACN,MAAM,YACN,MAAM,iBACJ,MAAM,CAuBlB;AAED;;;;;;GAMG;AACH,mCAJW,MAAM,GAEJ,MAAM,CAIlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap-xhr.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-xhr.js"],"names":[],"mappings":"AAmBA;;;;;GAKG;AAEH,kCAJW,MAAM,GACJ,MAAM,
|
|
1
|
+
{"version":3,"file":"wrap-xhr.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-xhr.js"],"names":[],"mappings":"AAmBA;;;;;GAKG;AAEH,kCAJW,MAAM,GACJ,MAAM,CAiLlB;AAED;;;;;;GAMG;AACH,mCAJW,MAAM,GAEJ,MAAM,CAIlB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/generic_events/aggregate/index.js"],"names":[],"mappings":"AAmBA;IACE,2BAAiC;IACjC,2BAiHC;IA9GC,yBAA4B;IAC5B,wBAAyE;IAEzE,gCAAkG;IA4B9F,4CAAuD;IAsEzD,mCAGQ;IASZ;;;;;;;;;;;OAWG;IACH,eAHW,MAAM,YAAC,QA0CjB;IAED,qCAEC;IAED;;;MAEC;CACF;8BA5L6B,4BAA4B;sCAOpB,wCAAwC;iCAX7C,2CAA2C"}
|
package/package.json
CHANGED
|
@@ -144,6 +144,25 @@ export class Harvest extends SharedContext {
|
|
|
144
144
|
}
|
|
145
145
|
cbFinished(cbResult)
|
|
146
146
|
}, eventListenerOpts(false))
|
|
147
|
+
} else if (!opts.unload && cbFinished && submitMethod === submitData.xhrFetch) {
|
|
148
|
+
const harvestScope = this
|
|
149
|
+
result.then(async function (response) {
|
|
150
|
+
const status = response.status
|
|
151
|
+
const cbResult = { sent: true, status, fullUrl, fetchResponse: response }
|
|
152
|
+
|
|
153
|
+
if (response.status === 429) {
|
|
154
|
+
cbResult.retry = true
|
|
155
|
+
cbResult.delay = harvestScope.tooManyRequestsDelay
|
|
156
|
+
} else if (status === 408 || status === 500 || status === 503) {
|
|
157
|
+
cbResult.retry = true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (opts.needResponse) {
|
|
161
|
+
cbResult.responseText = await response.text()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
cbFinished(cbResult)
|
|
165
|
+
})
|
|
147
166
|
}
|
|
148
167
|
|
|
149
168
|
return result
|
|
@@ -17,11 +17,44 @@ import { isBrowserScope } from '../constants/runtime'
|
|
|
17
17
|
* a final harvest within the agent.
|
|
18
18
|
*/
|
|
19
19
|
export function getSubmitMethod ({ isFinalHarvest = false } = {}) {
|
|
20
|
-
|
|
20
|
+
if (isFinalHarvest && isBrowserScope) {
|
|
21
21
|
// Use sendBeacon for final harvest
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
return beacon
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// If not final harvest, or not browserScope, use XHR post if available
|
|
26
|
+
if (typeof XMLHttpRequest !== 'undefined') {
|
|
27
|
+
return xhr
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Fallback for web workers where XMLHttpRequest is not available
|
|
31
|
+
return xhrFetch
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
*
|
|
36
|
+
* @param url
|
|
37
|
+
* @param body
|
|
38
|
+
* @param method
|
|
39
|
+
* @param headers
|
|
40
|
+
* @returns {Promise<Response>}
|
|
41
|
+
*/
|
|
42
|
+
export function xhrFetch ({
|
|
43
|
+
url,
|
|
44
|
+
body = null,
|
|
45
|
+
method = 'POST',
|
|
46
|
+
headers = [{
|
|
47
|
+
key: 'content-type',
|
|
48
|
+
value: 'text/plain'
|
|
49
|
+
}]
|
|
50
|
+
}) {
|
|
51
|
+
const objHeaders = {}
|
|
52
|
+
|
|
53
|
+
for (const header of headers) {
|
|
54
|
+
objHeaders[header.key] = header.value
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return fetch(url, { headers: objHeaders, method, body, credentials: 'include' })
|
|
25
58
|
}
|
|
26
59
|
|
|
27
60
|
/**
|
|
@@ -37,8 +37,8 @@ export function wrapEvents (sharedEE) {
|
|
|
37
37
|
// Guard against instrumenting environments w/o necessary features
|
|
38
38
|
if ('getPrototypeOf' in Object) {
|
|
39
39
|
if (isBrowserScope) findEventListenerProtoAndCb(document, wrapNode)
|
|
40
|
+
if (XHR) findEventListenerProtoAndCb(XHR.prototype, wrapNode)
|
|
40
41
|
findEventListenerProtoAndCb(globalScope, wrapNode)
|
|
41
|
-
findEventListenerProtoAndCb(XHR.prototype, wrapNode)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
ee.on(ADD_EVENT_LISTENER + '-start', function (args, target) {
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
import { ee as baseEE, contextId } from '../event-emitter/contextual-ee'
|
|
11
11
|
import { EventContext } from '../event-emitter/event-context'
|
|
12
12
|
import { warn } from '../util/console'
|
|
13
|
-
import { createWrapperWithEmitter as wfn } from './wrap-function'
|
|
13
|
+
import { flag, createWrapperWithEmitter as wfn } from './wrap-function'
|
|
14
|
+
|
|
15
|
+
const contextMap = new Map()
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Wraps a supplied function and adds emitter events under the `-wrap-logger-` prefix
|
|
@@ -33,8 +35,11 @@ export function wrapLogger(sharedEE, parent, loggerFn, context) {
|
|
|
33
35
|
ctx.level = context.level
|
|
34
36
|
ctx.customAttributes = context.customAttributes
|
|
35
37
|
|
|
38
|
+
const contextLookupKey = parent[loggerFn]?.[flag] || parent[loggerFn]
|
|
39
|
+
contextMap.set(contextLookupKey, ctx)
|
|
40
|
+
|
|
36
41
|
/** observe calls to <loggerFn> and emit events prefixed with `wrap-logger-` */
|
|
37
|
-
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-',
|
|
42
|
+
wrapFn.inPlace(parent, [loggerFn], 'wrap-logger-', () => contextMap.get(contextLookupKey))
|
|
38
43
|
|
|
39
44
|
return ee
|
|
40
45
|
}
|
|
@@ -28,6 +28,8 @@ export function wrapXhr (sharedEE) {
|
|
|
28
28
|
var baseEE = sharedEE || contextualEE
|
|
29
29
|
const ee = scopedEE(baseEE)
|
|
30
30
|
|
|
31
|
+
if (typeof globalScope.XMLHttpRequest === 'undefined') return ee
|
|
32
|
+
|
|
31
33
|
// Notice if our wrapping never ran yet, the falsy NaN will not early return; but if it has,
|
|
32
34
|
// then we increment the count to track # of feats using this at runtime.
|
|
33
35
|
if (wrapped[ee.debugId]++) return ee
|
|
@@ -13,7 +13,6 @@ import { now } from '../../../common/timing/now'
|
|
|
13
13
|
import { registerHandler } from '../../../common/event-emitter/register-handler'
|
|
14
14
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
|
|
15
15
|
import { applyFnToProps } from '../../../common/util/traverse'
|
|
16
|
-
import { IDEAL_PAYLOAD_SIZE } from '../../../common/constants/agent-constants'
|
|
17
16
|
import { FEATURE_TO_ENDPOINT } from '../../../loaders/features/features'
|
|
18
17
|
import { UserActionsAggregator } from './user-actions/user-actions-aggregator'
|
|
19
18
|
import { isIFrameWindow } from '../../../common/dom/iframe'
|
|
@@ -177,9 +176,16 @@ export class Aggregate extends AggregateBase {
|
|
|
177
176
|
...obj
|
|
178
177
|
}
|
|
179
178
|
|
|
180
|
-
this.events.add(eventAttributes)
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
const addedEvent = this.events.add(eventAttributes)
|
|
180
|
+
if (!addedEvent && !this.events.isEmpty()) {
|
|
181
|
+
/** could not add the event because it pushed the buffer over the limit
|
|
182
|
+
* so we harvest early, and try to add it again now that the buffer is cleared
|
|
183
|
+
* if it fails again, we do nothing
|
|
184
|
+
*/
|
|
185
|
+
this.ee.emit(SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen'])
|
|
186
|
+
this.harvestScheduler.runHarvest()
|
|
187
|
+
this.events.add(eventAttributes)
|
|
188
|
+
}
|
|
183
189
|
}
|
|
184
190
|
|
|
185
191
|
serializer (eventBuffer) {
|
|
@@ -189,12 +195,4 @@ export class Aggregate extends AggregateBase {
|
|
|
189
195
|
queryStringsBuilder () {
|
|
190
196
|
return { ua: this.agentRef.info.userAttributes, at: this.agentRef.info.atts }
|
|
191
197
|
}
|
|
192
|
-
|
|
193
|
-
checkEventLimits () {
|
|
194
|
-
// check if we've reached any harvest limits...
|
|
195
|
-
if (this.events.byteSize() > IDEAL_PAYLOAD_SIZE) {
|
|
196
|
-
this.ee.emit(SUPPORTABILITY_METRIC_CHANNEL, ['GenericEvents/Harvest/Max/Seen'])
|
|
197
|
-
this.harvestScheduler.runHarvest()
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
198
|
}
|