@cloudcare/browser-core 1.2.11 → 2.0.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/cjs/browser/fetchObservable.js +3 -4
- package/cjs/browser/htmlDomUtils.js +45 -0
- package/cjs/browser/pageExitObservable.js +72 -0
- package/cjs/configuration/configuration.js +8 -0
- package/cjs/configuration/transportConfiguration.js +7 -0
- package/cjs/dataMap.js +12 -4
- package/cjs/helper/deviceInfo.js +44 -2
- package/cjs/helper/enums.js +3 -0
- package/cjs/helper/getZoneJsOriginalValue.js +34 -0
- package/cjs/helper/instrumentMethod.js +7 -1
- package/cjs/helper/lifeCycle.js +2 -6
- package/cjs/helper/readBytesFromStream.js +74 -0
- package/cjs/helper/tools.js +123 -46
- package/cjs/index.js +52 -0
- package/cjs/session/sessionStore.js +1 -1
- package/cjs/transport/batch.js +7 -44
- package/cjs/transport/httpRequest.js +4 -2
- package/cjs/transport/sendWithRetryStrategy.js +8 -8
- package/cjs/transport/startBatchWithReplica.js +2 -2
- package/esm/browser/fetchObservable.js +3 -4
- package/esm/browser/htmlDomUtils.js +26 -0
- package/esm/browser/pageExitObservable.js +57 -0
- package/esm/configuration/configuration.js +5 -0
- package/esm/configuration/transportConfiguration.js +7 -0
- package/esm/dataMap.js +9 -2
- package/esm/helper/contextHistory.js +1 -1
- package/esm/helper/deviceInfo.js +44 -2
- package/esm/helper/enums.js +3 -0
- package/esm/helper/getZoneJsOriginalValue.js +27 -0
- package/esm/helper/instrumentMethod.js +6 -1
- package/esm/helper/lifeCycle.js +2 -6
- package/esm/helper/readBytesFromStream.js +67 -0
- package/esm/helper/tools.js +99 -44
- package/esm/index.js +4 -0
- package/esm/session/sessionStore.js +1 -1
- package/esm/transport/batch.js +8 -45
- package/esm/transport/httpRequest.js +4 -2
- package/esm/transport/sendWithRetryStrategy.js +8 -8
- package/esm/transport/startBatchWithReplica.js +2 -2
- package/package.json +2 -2
- package/src/browser/fetchObservable.js +21 -17
- package/src/browser/htmlDomUtils.js +35 -0
- package/src/browser/pageExitObservable.js +70 -0
- package/src/configuration/configuration.js +6 -0
- package/src/configuration/transportConfiguration.js +30 -6
- package/src/dataMap.js +9 -2
- package/src/helper/contextHistory.js +1 -1
- package/src/helper/deviceInfo.js +39 -3
- package/src/helper/enums.js +40 -37
- package/src/helper/getZoneJsOriginalValue.js +27 -0
- package/src/helper/instrumentMethod.js +40 -50
- package/src/helper/lifeCycle.js +2 -7
- package/src/helper/readBytesFromStream.js +69 -0
- package/src/helper/tools.js +112 -43
- package/src/index.js +4 -1
- package/src/session/sessionStore.js +27 -24
- package/src/synthetics/syntheticsWorkerValues.js +11 -7
- package/src/transport/batch.js +70 -81
- package/src/transport/httpRequest.js +25 -25
- package/src/transport/sendWithRetryStrategy.js +14 -9
- package/src/transport/startBatchWithReplica.js +11 -5
package/esm/dataMap.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { RumEventType } from './helper/enums';
|
|
2
2
|
export var commonTags = {
|
|
3
|
-
action_id: 'action.id',
|
|
4
3
|
sdk_name: '_dd.sdk_name',
|
|
5
4
|
sdk_version: '_dd.sdk_version',
|
|
6
5
|
app_id: 'application.id',
|
|
@@ -13,6 +12,7 @@ export var commonTags = {
|
|
|
13
12
|
session_id: 'session.id',
|
|
14
13
|
session_type: 'session.type',
|
|
15
14
|
session_sampling: 'session.is_sampling',
|
|
15
|
+
session_has_replay: 'session.has_replay',
|
|
16
16
|
is_signin: 'user.is_signin',
|
|
17
17
|
os: 'device.os',
|
|
18
18
|
os_version: 'device.os_version',
|
|
@@ -32,6 +32,10 @@ export var commonTags = {
|
|
|
32
32
|
// 冗余一个字段
|
|
33
33
|
view_path_group: 'view.path_group',
|
|
34
34
|
view_url_query: 'view.url_query'
|
|
35
|
+
};
|
|
36
|
+
export var commonFields = {
|
|
37
|
+
action_id: 'action.id',
|
|
38
|
+
view_in_foreground: 'view.in_foreground'
|
|
35
39
|
}; // 需要用双引号将字符串类型的field value括起来, 这里有数组标示[string, path]
|
|
36
40
|
|
|
37
41
|
export var dataMap = {
|
|
@@ -43,6 +47,7 @@ export var dataMap = {
|
|
|
43
47
|
is_active: 'view.is_active'
|
|
44
48
|
},
|
|
45
49
|
fields: {
|
|
50
|
+
session_replay_stats: '_dd.replay_stats',
|
|
46
51
|
view_error_count: 'view.error.count',
|
|
47
52
|
view_resource_count: 'view.resource.count',
|
|
48
53
|
view_long_task_count: 'view.long_task.count',
|
|
@@ -63,7 +68,9 @@ export var dataMap = {
|
|
|
63
68
|
time_to_interactive: 'view.tti',
|
|
64
69
|
dom: 'view.dom',
|
|
65
70
|
dom_ready: 'view.dom_ready',
|
|
66
|
-
time_spent: 'view.time_spent'
|
|
71
|
+
time_spent: 'view.time_spent',
|
|
72
|
+
in_foreground_periods: 'view.in_foreground_periods',
|
|
73
|
+
frustration_count: 'view.frustration.count'
|
|
67
74
|
}
|
|
68
75
|
},
|
|
69
76
|
resource: {
|
package/esm/helper/deviceInfo.js
CHANGED
|
@@ -188,8 +188,50 @@ var MethodLibrary = {
|
|
|
188
188
|
},
|
|
189
189
|
// 获取网络状态
|
|
190
190
|
getNetwork: function getNetwork() {
|
|
191
|
-
var
|
|
192
|
-
|
|
191
|
+
var connection = window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection;
|
|
192
|
+
var result = 'unknown';
|
|
193
|
+
var type = connection ? connection.type || connection.effectiveType : null;
|
|
194
|
+
|
|
195
|
+
if (type && typeof type === 'string') {
|
|
196
|
+
switch (type) {
|
|
197
|
+
// possible type values
|
|
198
|
+
case 'bluetooth':
|
|
199
|
+
case 'cellular':
|
|
200
|
+
result = 'cellular';
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case 'none':
|
|
204
|
+
result = 'none';
|
|
205
|
+
break;
|
|
206
|
+
|
|
207
|
+
case 'ethernet':
|
|
208
|
+
case 'wifi':
|
|
209
|
+
case 'wimax':
|
|
210
|
+
result = 'wifi';
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case 'other':
|
|
214
|
+
case 'unknown':
|
|
215
|
+
result = 'unknown';
|
|
216
|
+
break;
|
|
217
|
+
// possible effectiveType values
|
|
218
|
+
|
|
219
|
+
case 'slow-2g':
|
|
220
|
+
case '2g':
|
|
221
|
+
case '3g':
|
|
222
|
+
result = 'cellular';
|
|
223
|
+
break;
|
|
224
|
+
|
|
225
|
+
case '4g':
|
|
226
|
+
result = 'wifi';
|
|
227
|
+
break;
|
|
228
|
+
|
|
229
|
+
default:
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return result;
|
|
193
235
|
},
|
|
194
236
|
// 获取当前语言
|
|
195
237
|
getLanguage: function getLanguage() {
|
package/esm/helper/enums.js
CHANGED
|
@@ -10,6 +10,9 @@ export var DOM_EVENT = {
|
|
|
10
10
|
TOUCH_END: 'touchend',
|
|
11
11
|
TOUCH_MOVE: 'touchmove',
|
|
12
12
|
VISIBILITY_CHANGE: 'visibilitychange',
|
|
13
|
+
PAGE_SHOW: 'pageshow',
|
|
14
|
+
FREEZE: 'freeze',
|
|
15
|
+
RESUME: 'resume',
|
|
13
16
|
DOM_CONTENT_LOADED: 'DOMContentLoaded',
|
|
14
17
|
POINTER_DOWN: 'pointerdown',
|
|
15
18
|
POINTER_UP: 'pointerup',
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets the original value for a DOM API that was potentially patched by Zone.js.
|
|
3
|
+
*
|
|
4
|
+
* Zone.js[1] is a library that patches a bunch of JS and DOM APIs. It usually stores the original
|
|
5
|
+
* value of the patched functions/constructors/methods in a hidden property prefixed by
|
|
6
|
+
* __zone_symbol__.
|
|
7
|
+
*
|
|
8
|
+
* In multiple occasions, we observed that Zone.js is the culprit of important issues leading to
|
|
9
|
+
* browser resource exhaustion (memory leak, high CPU usage). This method is used as a workaround to
|
|
10
|
+
* use the original DOM API instead of the one patched by Zone.js.
|
|
11
|
+
*
|
|
12
|
+
* [1]: https://github.com/angular/angular/tree/main/packages/zone.js
|
|
13
|
+
*/
|
|
14
|
+
export function getZoneJsOriginalValue(target, name) {
|
|
15
|
+
var browserWindow = window;
|
|
16
|
+
var original;
|
|
17
|
+
|
|
18
|
+
if (browserWindow.Zone && typeof browserWindow.Zone.__symbol__ === 'function') {
|
|
19
|
+
original = target[browserWindow.Zone.__symbol__(name)];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!original) {
|
|
23
|
+
original = target[name];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return original;
|
|
27
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { noop } from './tools';
|
|
2
|
+
import { getZoneJsOriginalValue } from './getZoneJsOriginalValue';
|
|
2
3
|
export function instrumentMethod(object, method, instrumentationFactory) {
|
|
3
4
|
var original = object[method];
|
|
4
5
|
var instrumentation = instrumentationFactory(original);
|
|
@@ -52,7 +53,11 @@ export function instrumentSetter(object, property, after) {
|
|
|
52
53
|
return {
|
|
53
54
|
stop: noop
|
|
54
55
|
};
|
|
55
|
-
}
|
|
56
|
+
} // Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
|
|
57
|
+
// component, see issue RUMF-1443
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
var setTimeout = getZoneJsOriginalValue(window, 'setTimeout');
|
|
56
61
|
|
|
57
62
|
var instrumentation = function instrumentation(thisObject, value) {
|
|
58
63
|
// put hooked setter into event loop to avoid of set latency
|
package/esm/helper/lifeCycle.js
CHANGED
|
@@ -1,27 +1,23 @@
|
|
|
1
1
|
import { each, filter } from './tools';
|
|
2
2
|
export var LifeCycleEventType = {
|
|
3
3
|
PERFORMANCE_ENTRIES_COLLECTED: 'PERFORMANCE_ENTRIES_COLLECTED',
|
|
4
|
-
AUTO_ACTION_CREATED: 'AUTO_ACTION_CREATED',
|
|
5
4
|
AUTO_ACTION_COMPLETED: 'AUTO_ACTION_COMPLETED',
|
|
6
5
|
VIEW_CREATED: 'VIEW_CREATED',
|
|
7
6
|
VIEW_UPDATED: 'VIEW_UPDATED',
|
|
8
7
|
VIEW_ENDED: 'VIEW_ENDED',
|
|
9
8
|
SESSION_RENEWED: 'SESSION_RENEWED',
|
|
10
9
|
SESSION_EXPIRED: 'SESSION_EXPIRED',
|
|
11
|
-
|
|
12
|
-
BEFORE_UNLOAD: 'BEFORE_UNLOAD',
|
|
10
|
+
PAGE_EXITED: 'PAGE_EXITED',
|
|
13
11
|
REQUEST_STARTED: 'REQUEST_STARTED',
|
|
14
12
|
REQUEST_COMPLETED: 'REQUEST_COMPLETED',
|
|
15
13
|
RAW_RUM_EVENT_COLLECTED: 'RAW_RUM_EVENT_COLLECTED',
|
|
16
14
|
RUM_EVENT_COLLECTED: 'RUM_EVENT_COLLECTED',
|
|
17
15
|
RAW_ERROR_COLLECTED: 'RAW_ERROR_COLLECTED',
|
|
18
|
-
RECORD_STARTED: 'RECORD_STARTED',
|
|
19
|
-
RECORD_STOPPED: 'RECORD_STOPPED',
|
|
20
16
|
RAW_LOG_COLLECTED: 'RAW_LOG_COLLECTED',
|
|
21
17
|
LOG_COLLECTED: 'LOG_COLLECTED'
|
|
22
18
|
};
|
|
23
19
|
export function LifeCycle() {
|
|
24
|
-
this.callbacks =
|
|
20
|
+
this.callbacks = {};
|
|
25
21
|
}
|
|
26
22
|
LifeCycle.prototype = {
|
|
27
23
|
notify: function notify(eventType, data) {
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { noop, each } from './tools';
|
|
2
|
+
/**
|
|
3
|
+
* Read bytes from a ReadableStream until at least `limit` bytes have been read (or until the end of
|
|
4
|
+
* the stream). The callback is invoked with the at most `limit` bytes, and indicates that the limit
|
|
5
|
+
* has been exceeded if more bytes were available.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function readBytesFromStream(stream, callback, options) {
|
|
9
|
+
var reader = stream.getReader();
|
|
10
|
+
var chunks = [];
|
|
11
|
+
var readBytesCount = 0;
|
|
12
|
+
readMore();
|
|
13
|
+
|
|
14
|
+
function readMore() {
|
|
15
|
+
reader.read().then(function (result) {
|
|
16
|
+
if (result.done) {
|
|
17
|
+
onDone();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (options.collectStreamBody) {
|
|
22
|
+
chunks.push(result.value);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
readBytesCount += result.value.length;
|
|
26
|
+
|
|
27
|
+
if (readBytesCount > options.bytesLimit) {
|
|
28
|
+
onDone();
|
|
29
|
+
} else {
|
|
30
|
+
readMore();
|
|
31
|
+
}
|
|
32
|
+
}, function (error) {
|
|
33
|
+
callback(error);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function onDone() {
|
|
38
|
+
reader.cancel().catch( // we don't care if cancel fails, but we still need to catch the error to avoid reporting it
|
|
39
|
+
// as an unhandled rejection
|
|
40
|
+
noop);
|
|
41
|
+
var bytes;
|
|
42
|
+
var limitExceeded;
|
|
43
|
+
|
|
44
|
+
if (options.collectStreamBody) {
|
|
45
|
+
var completeBuffer;
|
|
46
|
+
|
|
47
|
+
if (chunks.length === 1) {
|
|
48
|
+
// optimization: if the response is small enough to fit in a single buffer (provided by the browser), just
|
|
49
|
+
// use it directly.
|
|
50
|
+
completeBuffer = chunks[0];
|
|
51
|
+
} else {
|
|
52
|
+
// else, we need to copy buffers into a larger buffer to concatenate them.
|
|
53
|
+
completeBuffer = new Uint8Array(readBytesCount);
|
|
54
|
+
var offset = 0;
|
|
55
|
+
each(chunks, function (chunk) {
|
|
56
|
+
completeBuffer.set(chunk, offset);
|
|
57
|
+
offset += chunk.length;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
bytes = completeBuffer.slice(0, options.bytesLimit);
|
|
62
|
+
limitExceeded = completeBuffer.length > options.bytesLimit;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
callback(undefined, bytes, limitExceeded);
|
|
66
|
+
}
|
|
67
|
+
}
|
package/esm/helper/tools.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { DOM_EVENT } from './enums';
|
|
2
|
+
import { getZoneJsOriginalValue } from './getZoneJsOriginalValue';
|
|
1
3
|
var ArrayProto = Array.prototype;
|
|
2
4
|
var FuncProto = Function.prototype;
|
|
3
5
|
var ObjProto = Object.prototype;
|
|
@@ -386,49 +388,42 @@ export var getScreenOrientation = function getScreenOrientation() {
|
|
|
386
388
|
export var now = Date.now || function () {
|
|
387
389
|
return new Date().getTime();
|
|
388
390
|
};
|
|
389
|
-
export var throttle = function throttle(
|
|
390
|
-
var
|
|
391
|
-
var
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
var
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
var throttled = function throttled() {
|
|
402
|
-
args = arguments;
|
|
403
|
-
var now = new Date().getTime();
|
|
404
|
-
if (!previous && options.leading === false) previous = now; //下次触发 func 剩余的时间
|
|
405
|
-
|
|
406
|
-
var remaining = wait - (now - previous);
|
|
407
|
-
context = this; // 如果没有剩余的时间了或者你改了系统时间
|
|
408
|
-
|
|
409
|
-
if (remaining <= 0 || remaining > wait) {
|
|
410
|
-
if (timeout) {
|
|
411
|
-
clearTimeout(timeout);
|
|
412
|
-
timeout = null;
|
|
391
|
+
export var throttle = function throttle(fn, wait, options) {
|
|
392
|
+
var needLeadingExecution = options && options.leading !== undefined ? options.leading : true;
|
|
393
|
+
var needTrailingExecution = options && options.trailing !== undefined ? options.trailing : true;
|
|
394
|
+
var inWaitPeriod = false;
|
|
395
|
+
var pendingExecutionWithParameters;
|
|
396
|
+
var pendingTimeoutId;
|
|
397
|
+
var context = this;
|
|
398
|
+
return {
|
|
399
|
+
throttled: function throttled() {
|
|
400
|
+
if (inWaitPeriod) {
|
|
401
|
+
pendingExecutionWithParameters = arguments;
|
|
402
|
+
return;
|
|
413
403
|
}
|
|
414
404
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
405
|
+
if (needLeadingExecution) {
|
|
406
|
+
fn.apply(context, arguments);
|
|
407
|
+
} else {
|
|
408
|
+
pendingExecutionWithParameters = arguments;
|
|
409
|
+
}
|
|
421
410
|
|
|
422
|
-
|
|
423
|
-
|
|
411
|
+
inWaitPeriod = true;
|
|
412
|
+
pendingTimeoutId = setTimeout(function () {
|
|
413
|
+
if (needTrailingExecution && pendingExecutionWithParameters) {
|
|
414
|
+
fn.apply(context, pendingExecutionWithParameters);
|
|
415
|
+
}
|
|
424
416
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
417
|
+
inWaitPeriod = false;
|
|
418
|
+
pendingExecutionWithParameters = undefined;
|
|
419
|
+
}, wait);
|
|
420
|
+
},
|
|
421
|
+
cancel: function cancel() {
|
|
422
|
+
clearTimeout(pendingTimeoutId);
|
|
423
|
+
inWaitPeriod = false;
|
|
424
|
+
pendingExecutionWithParameters = undefined;
|
|
425
|
+
}
|
|
429
426
|
};
|
|
430
|
-
|
|
431
|
-
return throttled;
|
|
432
427
|
};
|
|
433
428
|
export var hashCode = function hashCode(str) {
|
|
434
429
|
if (typeof str !== 'string') {
|
|
@@ -1661,6 +1656,9 @@ export function currentDrift() {
|
|
|
1661
1656
|
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
1662
1657
|
return Math.round(dateNow() - (getNavigationStart() + performance.now()));
|
|
1663
1658
|
}
|
|
1659
|
+
export function addDuration(a, b) {
|
|
1660
|
+
return a + b;
|
|
1661
|
+
}
|
|
1664
1662
|
|
|
1665
1663
|
function getCorrectedTimeStamp(relativeTime) {
|
|
1666
1664
|
var correctedOrigin = dateNow() - performance.now(); // apply correction only for positive drift
|
|
@@ -1712,8 +1710,8 @@ export function safeTruncate(candidate, length) {
|
|
|
1712
1710
|
|
|
1713
1711
|
return candidate.slice(0, length);
|
|
1714
1712
|
}
|
|
1715
|
-
export function addEventListener(
|
|
1716
|
-
return addEventListeners(
|
|
1713
|
+
export function addEventListener(eventTarget, event, listener, options) {
|
|
1714
|
+
return addEventListeners(eventTarget, [event], listener, options);
|
|
1717
1715
|
}
|
|
1718
1716
|
/**
|
|
1719
1717
|
* Add event listeners to an event emitter object (Window, Element, mock object...). This provides
|
|
@@ -1731,8 +1729,8 @@ export function addEventListener(emitter, event, listener, options) {
|
|
|
1731
1729
|
* listened
|
|
1732
1730
|
*/
|
|
1733
1731
|
|
|
1734
|
-
export function addEventListeners(
|
|
1735
|
-
var
|
|
1732
|
+
export function addEventListeners(eventTarget, events, listener, options) {
|
|
1733
|
+
var wrappedListener = options && options.once ? function (event) {
|
|
1736
1734
|
stop();
|
|
1737
1735
|
listener(event);
|
|
1738
1736
|
} : listener;
|
|
@@ -1740,13 +1738,15 @@ export function addEventListeners(emitter, events, listener, options) {
|
|
|
1740
1738
|
capture: options.capture,
|
|
1741
1739
|
passive: options.passive
|
|
1742
1740
|
} : options && options.capture;
|
|
1741
|
+
var add = getZoneJsOriginalValue(eventTarget, 'addEventListener');
|
|
1743
1742
|
each(events, function (event) {
|
|
1744
|
-
|
|
1743
|
+
add.call(eventTarget, event, wrappedListener, options);
|
|
1745
1744
|
});
|
|
1746
1745
|
|
|
1747
1746
|
var stop = function stop() {
|
|
1747
|
+
var remove = getZoneJsOriginalValue(eventTarget, 'removeEventListener');
|
|
1748
1748
|
each(events, function (event) {
|
|
1749
|
-
|
|
1749
|
+
remove.call(eventTarget, event, wrappedListener, options);
|
|
1750
1750
|
});
|
|
1751
1751
|
};
|
|
1752
1752
|
|
|
@@ -1926,4 +1926,59 @@ export function isNullUndefinedDefaultValue(data, defaultValue) {
|
|
|
1926
1926
|
} else {
|
|
1927
1927
|
return defaultValue;
|
|
1928
1928
|
}
|
|
1929
|
+
}
|
|
1930
|
+
export function runOnReadyState(expectedReadyState, callback) {
|
|
1931
|
+
if (document.readyState === expectedReadyState || document.readyState === 'complete') {
|
|
1932
|
+
callback();
|
|
1933
|
+
} else {
|
|
1934
|
+
var eventName = expectedReadyState === 'complete' ? DOM_EVENT.LOAD : DOM_EVENT.DOM_CONTENT_LOADED;
|
|
1935
|
+
addEventListener(window, eventName, callback, {
|
|
1936
|
+
once: true
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
export function requestIdleCallback(callback, opts) {
|
|
1941
|
+
// Use 'requestIdleCallback' when available: it will throttle the mutation processing if the
|
|
1942
|
+
// browser is busy rendering frames (ex: when frames are below 60fps). When not available, the
|
|
1943
|
+
// fallback on 'requestAnimationFrame' will still ensure the mutations are processed after any
|
|
1944
|
+
// browser rendering process (Layout, Recalculate Style, etc.), so we can serialize DOM nodes
|
|
1945
|
+
// efficiently.
|
|
1946
|
+
if (window.requestIdleCallback) {
|
|
1947
|
+
var id = window.requestIdleCallback(callback, opts);
|
|
1948
|
+
return function () {
|
|
1949
|
+
return window.cancelIdleCallback(id);
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
var id = window.requestAnimationFrame(callback);
|
|
1954
|
+
return function () {
|
|
1955
|
+
return window.cancelAnimationFrame(id);
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
export function objectHasValue(object, value) {
|
|
1959
|
+
return some(keys(object), function (key) {
|
|
1960
|
+
return object[key] === value;
|
|
1961
|
+
});
|
|
1962
|
+
}
|
|
1963
|
+
export function startsWith(candidate, search) {
|
|
1964
|
+
return candidate.slice(0, search.length) === search;
|
|
1965
|
+
}
|
|
1966
|
+
export function endsWith(candidate, search) {
|
|
1967
|
+
return candidate.slice(-search.length) === search;
|
|
1968
|
+
}
|
|
1969
|
+
export function tryToClone(response) {
|
|
1970
|
+
try {
|
|
1971
|
+
return response.clone();
|
|
1972
|
+
} catch (e) {
|
|
1973
|
+
// clone can throw if the response has already been used by another instrumentation or is disturbed
|
|
1974
|
+
return;
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
export function isHashAnAnchor(hash) {
|
|
1978
|
+
var correspondingId = hash.substr(1);
|
|
1979
|
+
return !!document.getElementById(correspondingId);
|
|
1980
|
+
}
|
|
1981
|
+
export function getPathFromHash(hash) {
|
|
1982
|
+
var index = hash.indexOf('?');
|
|
1983
|
+
return index < 0 ? hash : hash.slice(0, index);
|
|
1929
1984
|
}
|
package/esm/index.js
CHANGED
|
@@ -16,12 +16,16 @@ export * from './helper/observable';
|
|
|
16
16
|
export * from './helper/tools';
|
|
17
17
|
export * from './helper/urlPolyfill';
|
|
18
18
|
export * from './helper/mobileUtil';
|
|
19
|
+
export * from './helper/getZoneJsOriginalValue';
|
|
20
|
+
export * from './helper/readBytesFromStream';
|
|
19
21
|
export * from './tracekit';
|
|
20
22
|
export * from './configuration/configuration';
|
|
21
23
|
export * from './configuration/transportConfiguration';
|
|
22
24
|
export * from './browser/cookie';
|
|
23
25
|
export * from './browser/fetchObservable';
|
|
24
26
|
export * from './browser/xhrObservable';
|
|
27
|
+
export * from './browser/pageExitObservable';
|
|
28
|
+
export * from './browser/htmlDomUtils';
|
|
25
29
|
export * from './dataMap';
|
|
26
30
|
export * from './init';
|
|
27
31
|
export * from './session/sessionManagement';
|
|
@@ -125,7 +125,7 @@ export function startSessionStore(options, productKey, computeSessionState) {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
return {
|
|
128
|
-
expandOrRenewSession: throttle(expandOrRenewSession, COOKIE_ACCESS_DELAY),
|
|
128
|
+
expandOrRenewSession: throttle(expandOrRenewSession, COOKIE_ACCESS_DELAY).throttled,
|
|
129
129
|
expandSession: expandSession,
|
|
130
130
|
getSession: function getSession() {
|
|
131
131
|
return sessionCache;
|
package/esm/transport/batch.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { display } from '../helper/display';
|
|
2
2
|
import { addEventListener, noop, values, findByPath, escapeRowData, each, isNumber, isArray, extend, isString, toServerDuration, isBoolean, isEmptyObject, isObject, escapeJsonValue, escapeRowField } from '../helper/tools';
|
|
3
|
-
import { commonTags, dataMap } from '../dataMap';
|
|
3
|
+
import { commonTags, dataMap, commonFields } from '../dataMap';
|
|
4
4
|
import { DOM_EVENT, RumEventType } from '../helper/enums'; // https://en.wikipedia.org/wiki/UTF-8
|
|
5
5
|
// eslint-disable-next-line no-control-regex
|
|
6
6
|
|
|
@@ -36,7 +36,8 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
|
|
|
36
36
|
}
|
|
37
37
|
});
|
|
38
38
|
var fieldsStr = [];
|
|
39
|
-
|
|
39
|
+
var fields = extend({}, commonFields, value.fields);
|
|
40
|
+
each(fields, function (_value, _key) {
|
|
40
41
|
if (isArray(_value) && _value.length === 2) {
|
|
41
42
|
var type = _value[0],
|
|
42
43
|
value_path = _value[1];
|
|
@@ -123,7 +124,7 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
|
|
|
123
124
|
};
|
|
124
125
|
};
|
|
125
126
|
|
|
126
|
-
var batch = function batch(request, batchMessagesLimit, batchBytesLimit, messageBytesLimit, flushTimeout,
|
|
127
|
+
var batch = function batch(request, batchMessagesLimit, batchBytesLimit, messageBytesLimit, flushTimeout, pageExitObservable) {
|
|
127
128
|
this.pushOnlyBuffer = [];
|
|
128
129
|
this.upsertBuffer = {};
|
|
129
130
|
this.bufferBytesCount = 0;
|
|
@@ -134,13 +135,11 @@ var batch = function batch(request, batchMessagesLimit, batchBytesLimit, message
|
|
|
134
135
|
this.messageBytesLimit = messageBytesLimit;
|
|
135
136
|
this.flushTimeout = flushTimeout;
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
this.beforeUnloadCallback = beforeUnloadCallback;
|
|
139
|
-
} else {
|
|
140
|
-
this.beforeUnloadCallback = noop;
|
|
141
|
-
}
|
|
138
|
+
var _this = this;
|
|
142
139
|
|
|
143
|
-
|
|
140
|
+
pageExitObservable.subscribe(function () {
|
|
141
|
+
_this.flush(_this.request.sendOnExit);
|
|
142
|
+
});
|
|
144
143
|
this.flushPeriodically();
|
|
145
144
|
};
|
|
146
145
|
|
|
@@ -277,40 +276,4 @@ batch.prototype.flushPeriodically = function () {
|
|
|
277
276
|
}, this.flushTimeout);
|
|
278
277
|
};
|
|
279
278
|
|
|
280
|
-
batch.prototype.setupFlushOnExit = function () {
|
|
281
|
-
/**
|
|
282
|
-
* With sendBeacon, requests are guaranteed to be successfully sent during document unload
|
|
283
|
-
*/
|
|
284
|
-
// @ts-ignore this function is not always defined
|
|
285
|
-
var _this = this;
|
|
286
|
-
|
|
287
|
-
if (navigator.sendBeacon) {
|
|
288
|
-
/**
|
|
289
|
-
* beforeunload is called before visibilitychange
|
|
290
|
-
* register first to be sure to be called before flush on beforeunload
|
|
291
|
-
* caveat: unload can still be canceled by another listener
|
|
292
|
-
*/
|
|
293
|
-
addEventListener(window, DOM_EVENT.BEFORE_UNLOAD, this.beforeUnloadCallback);
|
|
294
|
-
/**
|
|
295
|
-
* Only event that guarantee to fire on mobile devices when the page transitions to background state
|
|
296
|
-
* (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.
|
|
297
|
-
*/
|
|
298
|
-
|
|
299
|
-
addEventListener(document, DOM_EVENT.VISIBILITY_CHANGE, function () {
|
|
300
|
-
if (document.visibilityState === 'hidden') {
|
|
301
|
-
_this.flushOnExit();
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
/**
|
|
305
|
-
* Safari does not support yet to send a request during:
|
|
306
|
-
* - a visibility change during doc unload (cf: https://bugs.webkit.org/show_bug.cgi?id=194897)
|
|
307
|
-
* - a page hide transition (cf: https://bugs.webkit.org/show_bug.cgi?id=188329)
|
|
308
|
-
*/
|
|
309
|
-
|
|
310
|
-
addEventListener(window, DOM_EVENT.BEFORE_UNLOAD, function () {
|
|
311
|
-
return _this.flushOnExit();
|
|
312
|
-
});
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
|
|
316
279
|
export var Batch = batch;
|
|
@@ -65,11 +65,13 @@ export function fetchKeepAliveStrategy(endpointUrl, bytesLimit, payload, onRespo
|
|
|
65
65
|
fetch(url, {
|
|
66
66
|
method: 'POST',
|
|
67
67
|
body: data,
|
|
68
|
-
keepalive: true
|
|
68
|
+
keepalive: true,
|
|
69
|
+
mode: 'cors'
|
|
69
70
|
}).then(function (response) {
|
|
70
71
|
if (typeof onResponse === 'function') {
|
|
71
72
|
onResponse({
|
|
72
|
-
status: response.status
|
|
73
|
+
status: response.status,
|
|
74
|
+
type: response.type
|
|
73
75
|
});
|
|
74
76
|
}
|
|
75
77
|
}, function () {
|
|
@@ -6,13 +6,13 @@ export var MAX_QUEUE_BYTES_COUNT = 3 * ONE_MEBI_BYTE;
|
|
|
6
6
|
export var MAX_BACKOFF_TIME = 256 * ONE_SECOND;
|
|
7
7
|
export var INITIAL_BACKOFF_TIME = ONE_SECOND;
|
|
8
8
|
var TransportStatus = {
|
|
9
|
-
UP:
|
|
10
|
-
FAILURE_DETECTED:
|
|
11
|
-
DOWN:
|
|
9
|
+
UP: 0,
|
|
10
|
+
FAILURE_DETECTED: 1,
|
|
11
|
+
DOWN: 2
|
|
12
12
|
};
|
|
13
13
|
var RetryReason = {
|
|
14
|
-
AFTER_SUCCESS:
|
|
15
|
-
AFTER_RESUME:
|
|
14
|
+
AFTER_SUCCESS: 0,
|
|
15
|
+
AFTER_RESUME: 1
|
|
16
16
|
};
|
|
17
17
|
export function sendWithRetryStrategy(payload, state, sendStrategy, reportError) {
|
|
18
18
|
if (state.transportStatus === TransportStatus.UP && state.queuedPayloads.size() === 0 && state.bandwidthMonitor.canHandle(payload)) {
|
|
@@ -63,7 +63,7 @@ function send(payload, state, sendStrategy, responseData) {
|
|
|
63
63
|
sendStrategy(payload, function (response) {
|
|
64
64
|
state.bandwidthMonitor.remove(payload);
|
|
65
65
|
|
|
66
|
-
if (
|
|
66
|
+
if (!shouldRetryRequest(response)) {
|
|
67
67
|
state.transportStatus = TransportStatus.UP;
|
|
68
68
|
onSuccess();
|
|
69
69
|
} else {
|
|
@@ -93,8 +93,8 @@ function retryQueuedPayloads(reason, state, sendStrategy, reportError) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
function
|
|
97
|
-
return response.
|
|
96
|
+
function shouldRetryRequest(response) {
|
|
97
|
+
return response.type !== 'opaque' && (response.status === 0 && !navigator.onLine || response.status === 408 || response.status === 429 || response.status >= 500);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
export function newRetryState() {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Batch } from './batch';
|
|
2
2
|
import { createHttpRequest } from './httpRequest';
|
|
3
|
-
export function startBatchWithReplica(configuration, endpointUrl, reportError) {
|
|
3
|
+
export function startBatchWithReplica(configuration, endpointUrl, reportError, pageExitObservable) {
|
|
4
4
|
var primaryBatch = createBatch(endpointUrl);
|
|
5
5
|
|
|
6
6
|
function createBatch(endpointUrl) {
|
|
7
|
-
return new Batch(createHttpRequest(endpointUrl, configuration.batchBytesLimit, reportError), configuration.batchMessagesLimit, configuration.batchBytesLimit, configuration.messageBytesLimit, configuration.flushTimeout);
|
|
7
|
+
return new Batch(createHttpRequest(endpointUrl, configuration.batchBytesLimit, reportError), configuration.batchMessagesLimit, configuration.batchBytesLimit, configuration.messageBytesLimit, configuration.flushTimeout, pageExitObservable);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcare/browser-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"main": "cjs/index.js",
|
|
5
5
|
"module": "esm/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
"author": "dataflux",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"description": "DataFlux RUM Web 端数据指标监控",
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "bc7a044056367a5f9a0bc941462cb4e1d4d1d925"
|
|
24
24
|
}
|