@cloudcare/browser-core 1.1.2 → 1.2.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/{cookie.js → browser/cookie.js} +6 -37
- package/cjs/browser/fetchObservable.js +91 -0
- package/cjs/browser/xhrObservable.js +118 -0
- package/cjs/configuration/configuration.js +70 -0
- package/cjs/configuration/transportConfiguration.js +64 -0
- package/cjs/console/consoleObservable.js +84 -0
- package/cjs/dataMap.js +26 -21
- package/cjs/error/trackRuntimeError.js +27 -0
- package/cjs/helper/catchUserErrors.js +20 -0
- package/cjs/helper/contextHistory.js +134 -0
- package/cjs/helper/createEventRateLimiter.js +47 -0
- package/cjs/helper/deviceInfo.js +8 -25
- package/cjs/helper/display.js +31 -0
- package/cjs/helper/enums.js +28 -2
- package/cjs/helper/errorTools.js +63 -2
- package/cjs/helper/instrumentMethod.js +93 -0
- package/cjs/helper/lifeCycle.js +5 -3
- package/cjs/helper/observable.js +40 -2
- package/cjs/helper/tools.js +217 -11
- package/cjs/index.js +153 -23
- package/cjs/init.js +17 -27
- package/cjs/report/reportObservable.js +112 -0
- package/cjs/session/sessionConstants.js +13 -0
- package/cjs/session/sessionCookieStore.js +188 -0
- package/cjs/session/sessionManagement.js +96 -0
- package/cjs/session/sessionStore.js +150 -0
- package/cjs/synthetics/syntheticsWorkerValues.js +32 -0
- package/cjs/synthetics/usr.js +32 -0
- package/cjs/tracekit/computeStackTrace.js +73 -563
- package/cjs/tracekit/index.js +3 -15
- package/cjs/tracekit/tracekit.js +113 -0
- package/cjs/transport/batch.js +332 -0
- package/cjs/transport/httpRequest.js +112 -0
- package/cjs/transport/index.js +29 -0
- package/cjs/transport/sendWithRetryStrategy.js +177 -0
- package/cjs/transport/startBatchWithReplica.js +24 -0
- package/esm/{cookie.js → browser/cookie.js} +4 -35
- package/esm/browser/fetchObservable.js +77 -0
- package/esm/browser/xhrObservable.js +106 -0
- package/esm/configuration/configuration.js +55 -0
- package/esm/configuration/transportConfiguration.js +54 -0
- package/esm/console/consoleObservable.js +70 -0
- package/esm/dataMap.js +26 -21
- package/esm/error/trackRuntimeError.js +16 -0
- package/esm/helper/catchUserErrors.js +12 -0
- package/esm/helper/contextHistory.js +106 -0
- package/esm/helper/createEventRateLimiter.js +38 -0
- package/esm/helper/deviceInfo.js +6 -25
- package/esm/helper/display.js +21 -0
- package/esm/helper/enums.js +25 -1
- package/esm/helper/errorTools.js +58 -3
- package/esm/helper/instrumentMethod.js +81 -0
- package/esm/helper/lifeCycle.js +5 -3
- package/esm/helper/observable.js +39 -3
- package/esm/helper/tools.js +173 -3
- package/esm/index.js +17 -7
- package/esm/init.js +17 -22
- package/esm/report/reportObservable.js +98 -0
- package/esm/session/sessionConstants.js +3 -0
- package/esm/session/sessionCookieStore.js +168 -0
- package/esm/session/sessionManagement.js +78 -0
- package/esm/session/sessionStore.js +139 -0
- package/esm/synthetics/syntheticsWorkerValues.js +15 -0
- package/esm/synthetics/usr.js +18 -0
- package/esm/tracekit/computeStackTrace.js +73 -557
- package/esm/tracekit/index.js +1 -1
- package/esm/tracekit/tracekit.js +103 -0
- package/esm/transport/batch.js +316 -0
- package/esm/transport/httpRequest.js +104 -0
- package/esm/transport/index.js +3 -0
- package/esm/transport/sendWithRetryStrategy.js +165 -0
- package/esm/transport/startBatchWithReplica.js +15 -0
- package/package.json +2 -2
- package/src/.DS_Store +0 -0
- package/src/{cookie.js → browser/cookie.js} +6 -34
- package/src/browser/fetchObservable.js +86 -0
- package/src/browser/xhrObservable.js +102 -0
- package/src/configuration/configuration.js +61 -0
- package/src/configuration/transportConfiguration.js +42 -0
- package/src/console/consoleObservable.js +65 -0
- package/src/dataMap.js +26 -21
- package/src/error/trackRuntimeError.js +19 -0
- package/src/helper/catchUserErrors.js +12 -0
- package/src/helper/contextHistory.js +85 -0
- package/src/helper/createEventRateLimiter.js +37 -0
- package/src/helper/deviceInfo.js +5 -51
- package/src/helper/display.js +21 -0
- package/src/helper/enums.js +38 -14
- package/src/helper/errorTools.js +76 -12
- package/src/helper/instrumentMethod.js +97 -0
- package/src/helper/lifeCycle.js +5 -3
- package/src/helper/observable.js +33 -2
- package/src/helper/tools.js +159 -5
- package/src/index.js +18 -7
- package/src/init.js +17 -18
- package/src/report/reportObservable.js +113 -0
- package/src/session/sessionConstants.js +3 -0
- package/src/session/sessionCookieStore.js +159 -0
- package/src/session/sessionManagement.js +89 -0
- package/src/session/sessionStore.js +139 -0
- package/src/synthetics/syntheticsWorkerValues.js +22 -0
- package/src/synthetics/usr.js +18 -0
- package/src/tracekit/computeStackTrace.js +75 -551
- package/src/tracekit/index.js +1 -1
- package/src/tracekit/tracekit.js +100 -0
- package/src/transport/batch.js +289 -0
- package/src/transport/httpRequest.js +109 -0
- package/src/transport/index.js +3 -0
- package/src/transport/sendWithRetryStrategy.js +186 -0
- package/src/transport/startBatchWithReplica.js +26 -0
- package/cjs/configuration.js +0 -184
- package/cjs/errorCollection.js +0 -167
- package/cjs/fetchProxy.js +0 -162
- package/cjs/helper/errorFilter.js +0 -47
- package/cjs/sessionManagement.js +0 -221
- package/cjs/tracekit/report.js +0 -289
- package/cjs/transport.js +0 -373
- package/cjs/xhrProxy.js +0 -122
- package/esm/configuration.js +0 -167
- package/esm/errorCollection.js +0 -141
- package/esm/fetchProxy.js +0 -116
- package/esm/helper/errorFilter.js +0 -38
- package/esm/sessionManagement.js +0 -195
- package/esm/tracekit/report.js +0 -273
- package/esm/transport.js +0 -357
- package/esm/xhrProxy.js +0 -110
- package/src/configuration.js +0 -156
- package/src/errorCollection.js +0 -170
- package/src/fetchProxy.js +0 -109
- package/src/helper/errorFilter.js +0 -38
- package/src/sessionManagement.js +0 -224
- package/src/tracekit/report.js +0 -284
- package/src/transport.js +0 -380
- package/src/xhrProxy.js +0 -106
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.MAX_QUEUE_BYTES_COUNT = exports.MAX_ONGOING_REQUESTS = exports.MAX_ONGOING_BYTES_COUNT = exports.MAX_BACKOFF_TIME = exports.INITIAL_BACKOFF_TIME = void 0;
|
|
7
|
+
exports.newRetryState = newRetryState;
|
|
8
|
+
exports.sendWithRetryStrategy = sendWithRetryStrategy;
|
|
9
|
+
|
|
10
|
+
var _tools = require("../helper/tools");
|
|
11
|
+
|
|
12
|
+
var _errorTools = require("../helper/errorTools");
|
|
13
|
+
|
|
14
|
+
var MAX_ONGOING_BYTES_COUNT = 80 * _tools.ONE_KIBI_BYTE;
|
|
15
|
+
exports.MAX_ONGOING_BYTES_COUNT = MAX_ONGOING_BYTES_COUNT;
|
|
16
|
+
var MAX_ONGOING_REQUESTS = 32;
|
|
17
|
+
exports.MAX_ONGOING_REQUESTS = MAX_ONGOING_REQUESTS;
|
|
18
|
+
var MAX_QUEUE_BYTES_COUNT = 3 * _tools.ONE_MEBI_BYTE;
|
|
19
|
+
exports.MAX_QUEUE_BYTES_COUNT = MAX_QUEUE_BYTES_COUNT;
|
|
20
|
+
var MAX_BACKOFF_TIME = 256 * _tools.ONE_SECOND;
|
|
21
|
+
exports.MAX_BACKOFF_TIME = MAX_BACKOFF_TIME;
|
|
22
|
+
var INITIAL_BACKOFF_TIME = _tools.ONE_SECOND;
|
|
23
|
+
exports.INITIAL_BACKOFF_TIME = INITIAL_BACKOFF_TIME;
|
|
24
|
+
var TransportStatus = {
|
|
25
|
+
UP: 'UP',
|
|
26
|
+
FAILURE_DETECTED: 'FAILURE_DETECTED',
|
|
27
|
+
DOWN: 'DOWN'
|
|
28
|
+
};
|
|
29
|
+
var RetryReason = {
|
|
30
|
+
AFTER_SUCCESS: 'AFTER_SUCCESS',
|
|
31
|
+
AFTER_RESUME: 'AFTER_RESUME'
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function sendWithRetryStrategy(payload, state, sendStrategy, reportError) {
|
|
35
|
+
if (state.transportStatus === TransportStatus.UP && state.queuedPayloads.size() === 0 && state.bandwidthMonitor.canHandle(payload)) {
|
|
36
|
+
send(payload, state, sendStrategy, {
|
|
37
|
+
onSuccess: function onSuccess() {
|
|
38
|
+
return retryQueuedPayloads(RetryReason.AFTER_SUCCESS, state, sendStrategy, reportError);
|
|
39
|
+
},
|
|
40
|
+
onFailure: function onFailure() {
|
|
41
|
+
state.queuedPayloads.enqueue(payload);
|
|
42
|
+
scheduleRetry(state, sendStrategy, reportError);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
state.queuedPayloads.enqueue(payload);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function scheduleRetry(state, sendStrategy, reportError) {
|
|
51
|
+
if (state.transportStatus !== TransportStatus.DOWN) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
setTimeout(function () {
|
|
56
|
+
var payload = state.queuedPayloads.first();
|
|
57
|
+
send(payload, state, sendStrategy, {
|
|
58
|
+
onSuccess: function onSuccess() {
|
|
59
|
+
state.queuedPayloads.dequeue(); // if (state.lastFailureStatus !== 0) {
|
|
60
|
+
// addTelemetryDebug('resuming after transport down', {
|
|
61
|
+
// failureStatus: state.lastFailureStatus,
|
|
62
|
+
// })
|
|
63
|
+
// }
|
|
64
|
+
|
|
65
|
+
state.currentBackoffTime = INITIAL_BACKOFF_TIME;
|
|
66
|
+
retryQueuedPayloads(RetryReason.AFTER_RESUME, state, sendStrategy, reportError);
|
|
67
|
+
},
|
|
68
|
+
onFailure: function onFailure() {
|
|
69
|
+
state.currentBackoffTime = Math.min(MAX_BACKOFF_TIME, state.currentBackoffTime * 2);
|
|
70
|
+
scheduleRetry(state, sendStrategy, reportError);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}, state.currentBackoffTime);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function send(payload, state, sendStrategy, responseData) {
|
|
77
|
+
var onSuccess = responseData.onSuccess;
|
|
78
|
+
var onFailure = responseData.onFailure;
|
|
79
|
+
state.bandwidthMonitor.add(payload);
|
|
80
|
+
sendStrategy(payload, function (response) {
|
|
81
|
+
state.bandwidthMonitor.remove(payload);
|
|
82
|
+
|
|
83
|
+
if (wasRequestSuccessful(response)) {
|
|
84
|
+
state.transportStatus = TransportStatus.UP;
|
|
85
|
+
onSuccess();
|
|
86
|
+
} else {
|
|
87
|
+
// do not consider transport down if another ongoing request could succeed
|
|
88
|
+
state.transportStatus = state.bandwidthMonitor.ongoingRequestCount > 0 ? TransportStatus.FAILURE_DETECTED : TransportStatus.DOWN;
|
|
89
|
+
state.lastFailureStatus = response.status;
|
|
90
|
+
onFailure();
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function retryQueuedPayloads(reason, state, sendStrategy, reportError) {
|
|
96
|
+
if (reason === RetryReason.AFTER_SUCCESS && state.queuedPayloads.isFull() && !state.queueFullReported) {
|
|
97
|
+
reportError({
|
|
98
|
+
message: 'Reached max events size queued for upload: ' + MAX_QUEUE_BYTES_COUNT / _tools.ONE_MEBI_BYTE + 'MiB',
|
|
99
|
+
source: _errorTools.ErrorSource.AGENT,
|
|
100
|
+
startClocks: (0, _tools.clocksNow)()
|
|
101
|
+
});
|
|
102
|
+
state.queueFullReported = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
var previousQueue = state.queuedPayloads;
|
|
106
|
+
state.queuedPayloads = newPayloadQueue();
|
|
107
|
+
|
|
108
|
+
while (previousQueue.size() > 0) {
|
|
109
|
+
sendWithRetryStrategy(previousQueue.dequeue(), state, sendStrategy, reportError);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function wasRequestSuccessful(response) {
|
|
114
|
+
return response.status !== 0 && response.status < 500;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function newRetryState() {
|
|
118
|
+
return {
|
|
119
|
+
transportStatus: TransportStatus.UP,
|
|
120
|
+
lastFailureStatus: 0,
|
|
121
|
+
currentBackoffTime: INITIAL_BACKOFF_TIME,
|
|
122
|
+
bandwidthMonitor: newBandwidthMonitor(),
|
|
123
|
+
queuedPayloads: newPayloadQueue(),
|
|
124
|
+
queueFullReported: false
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function newPayloadQueue() {
|
|
129
|
+
var queue = [];
|
|
130
|
+
return {
|
|
131
|
+
bytesCount: 0,
|
|
132
|
+
enqueue: function enqueue(payload) {
|
|
133
|
+
if (this.isFull()) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
queue.push(payload);
|
|
138
|
+
this.bytesCount += payload.bytesCount;
|
|
139
|
+
},
|
|
140
|
+
first: function first() {
|
|
141
|
+
return queue[0];
|
|
142
|
+
},
|
|
143
|
+
dequeue: function dequeue() {
|
|
144
|
+
var payload = queue.shift();
|
|
145
|
+
|
|
146
|
+
if (payload) {
|
|
147
|
+
this.bytesCount -= payload.bytesCount;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return payload;
|
|
151
|
+
},
|
|
152
|
+
size: function size() {
|
|
153
|
+
return queue.length;
|
|
154
|
+
},
|
|
155
|
+
isFull: function isFull() {
|
|
156
|
+
return this.bytesCount >= MAX_QUEUE_BYTES_COUNT;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function newBandwidthMonitor() {
|
|
162
|
+
return {
|
|
163
|
+
ongoingRequestCount: 0,
|
|
164
|
+
ongoingByteCount: 0,
|
|
165
|
+
canHandle: function canHandle(payload) {
|
|
166
|
+
return this.ongoingRequestCount === 0 || this.ongoingByteCount + payload.bytesCount <= MAX_ONGOING_BYTES_COUNT && this.ongoingRequestCount < MAX_ONGOING_REQUESTS;
|
|
167
|
+
},
|
|
168
|
+
add: function add(payload) {
|
|
169
|
+
this.ongoingRequestCount += 1;
|
|
170
|
+
this.ongoingByteCount += payload.bytesCount;
|
|
171
|
+
},
|
|
172
|
+
remove: function remove(payload) {
|
|
173
|
+
this.ongoingRequestCount -= 1;
|
|
174
|
+
this.ongoingByteCount -= payload.bytesCount;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.startBatchWithReplica = startBatchWithReplica;
|
|
7
|
+
|
|
8
|
+
var _batch = require("./batch");
|
|
9
|
+
|
|
10
|
+
var _httpRequest = require("./httpRequest");
|
|
11
|
+
|
|
12
|
+
function startBatchWithReplica(configuration, endpointUrl, reportError) {
|
|
13
|
+
var primaryBatch = createBatch(endpointUrl);
|
|
14
|
+
|
|
15
|
+
function createBatch(endpointUrl) {
|
|
16
|
+
return new _batch.Batch((0, _httpRequest.createHttpRequest)(endpointUrl, configuration.batchBytesLimit, reportError), configuration.batchMessagesLimit, configuration.batchBytesLimit, configuration.messageBytesLimit, configuration.flushTimeout);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
add: function add(message) {
|
|
21
|
+
primaryBatch.add(message);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -1,39 +1,5 @@
|
|
|
1
|
-
import { findCommaSeparatedValue, UUID, ONE_SECOND } from '
|
|
1
|
+
import { findCommaSeparatedValue, UUID, ONE_SECOND } from '../helper/tools';
|
|
2
2
|
export var COOKIE_ACCESS_DELAY = ONE_SECOND;
|
|
3
|
-
export function cacheCookieAccess(name, options) {
|
|
4
|
-
var timeout;
|
|
5
|
-
var cache;
|
|
6
|
-
var hasCache = false;
|
|
7
|
-
|
|
8
|
-
var cacheAccess = function cacheAccess() {
|
|
9
|
-
hasCache = true;
|
|
10
|
-
window.clearTimeout(timeout);
|
|
11
|
-
timeout = window.setTimeout(function () {
|
|
12
|
-
hasCache = false;
|
|
13
|
-
}, COOKIE_ACCESS_DELAY);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
get: function get() {
|
|
18
|
-
if (hasCache) {
|
|
19
|
-
return cache;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
cache = getCookie(name);
|
|
23
|
-
cacheAccess();
|
|
24
|
-
return cache;
|
|
25
|
-
},
|
|
26
|
-
set: function set(value, expireDelay) {
|
|
27
|
-
setCookie(name, value, expireDelay, options);
|
|
28
|
-
cache = value;
|
|
29
|
-
cacheAccess();
|
|
30
|
-
},
|
|
31
|
-
clearCache: function clearCache() {
|
|
32
|
-
window.clearTimeout(timeout);
|
|
33
|
-
hasCache = false;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
3
|
export function setCookie(name, value, expireDelay, options) {
|
|
38
4
|
var date = new Date();
|
|
39
5
|
date.setTime(date.getTime() + expireDelay);
|
|
@@ -46,6 +12,9 @@ export function setCookie(name, value, expireDelay, options) {
|
|
|
46
12
|
export function getCookie(name) {
|
|
47
13
|
return findCommaSeparatedValue(document.cookie, name);
|
|
48
14
|
}
|
|
15
|
+
export function deleteCookie(name, options) {
|
|
16
|
+
setCookie(name, '', 0, options);
|
|
17
|
+
}
|
|
49
18
|
export function areCookiesAuthorized(options) {
|
|
50
19
|
if (document.cookie === undefined || document.cookie === null) {
|
|
51
20
|
return false;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { instrumentMethod } from '../helper/instrumentMethod';
|
|
2
|
+
import { Observable } from '../helper/observable';
|
|
3
|
+
import { elapsed, clocksNow, timeStampNow } from '../helper/tools';
|
|
4
|
+
import { normalizeUrl } from '../helper/urlPolyfill';
|
|
5
|
+
var fetchObservable;
|
|
6
|
+
export function initFetchObservable() {
|
|
7
|
+
if (!fetchObservable) {
|
|
8
|
+
fetchObservable = createFetchObservable();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
return fetchObservable;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function createFetchObservable() {
|
|
15
|
+
var observable = new Observable(function () {
|
|
16
|
+
if (!window.fetch) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
var fetchMethod = instrumentMethod(window, 'fetch', function (originalFetch) {
|
|
21
|
+
return function (input, init) {
|
|
22
|
+
var responsePromise;
|
|
23
|
+
var context = beforeSend(observable, input, init);
|
|
24
|
+
|
|
25
|
+
if (context) {
|
|
26
|
+
responsePromise = originalFetch.call(this, context.input, context.init);
|
|
27
|
+
afterSend(observable, responsePromise, context);
|
|
28
|
+
} else {
|
|
29
|
+
responsePromise = originalFetch.call(this, input, init);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return responsePromise;
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
return fetchMethod.stop;
|
|
36
|
+
});
|
|
37
|
+
return observable;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function beforeSend(observable, input, init) {
|
|
41
|
+
var method = init && init.method || typeof input === 'object' && input.method || 'GET';
|
|
42
|
+
var url = normalizeUrl(typeof input === 'object' && input.url || input);
|
|
43
|
+
var startClocks = clocksNow();
|
|
44
|
+
var context = {
|
|
45
|
+
state: 'start',
|
|
46
|
+
init: init,
|
|
47
|
+
input: input,
|
|
48
|
+
method: method,
|
|
49
|
+
startClocks: startClocks,
|
|
50
|
+
url: url
|
|
51
|
+
};
|
|
52
|
+
observable.notify(context);
|
|
53
|
+
return context;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function afterSend(observable, responsePromise, startContext) {
|
|
57
|
+
var reportFetch = function reportFetch(response) {
|
|
58
|
+
var context = startContext;
|
|
59
|
+
context.state = 'complete';
|
|
60
|
+
context.duration = elapsed(context.startClocks.timeStamp, timeStampNow());
|
|
61
|
+
|
|
62
|
+
if ('stack' in response || response instanceof Error) {
|
|
63
|
+
context.status = 0;
|
|
64
|
+
context.isAborted = response instanceof DOMException && response.code === DOMException.ABORT_ERR;
|
|
65
|
+
context.error = response;
|
|
66
|
+
observable.notify(context);
|
|
67
|
+
} else if ('status' in response) {
|
|
68
|
+
context.response = response;
|
|
69
|
+
context.responseType = response.type;
|
|
70
|
+
context.status = response.status;
|
|
71
|
+
context.isAborted = false;
|
|
72
|
+
observable.notify(context);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
responsePromise.then(reportFetch, reportFetch);
|
|
77
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { instrumentMethodAndCallOriginal } from '../helper/instrumentMethod';
|
|
2
|
+
import { Observable } from '../helper/observable';
|
|
3
|
+
import { normalizeUrl } from '../helper/urlPolyfill';
|
|
4
|
+
import { shallowClone, elapsed, relativeNow, clocksNow, timeStampNow, UUID } from '../helper/tools';
|
|
5
|
+
var xhrObservable;
|
|
6
|
+
var xhrContexts = {};
|
|
7
|
+
var DATA_FLUX_REQUEST_ID_KEY = '_DATAFLUX_REQUEST_UUID';
|
|
8
|
+
export function initXhrObservable() {
|
|
9
|
+
if (!xhrObservable) {
|
|
10
|
+
xhrObservable = createXhrObservable();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return xhrObservable;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function createXhrObservable() {
|
|
17
|
+
var observable = new Observable(function () {
|
|
18
|
+
var openInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'open', {
|
|
19
|
+
before: openXhr
|
|
20
|
+
});
|
|
21
|
+
var sendInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'send', {
|
|
22
|
+
before: function before() {
|
|
23
|
+
sendXhr.call(this, observable);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
var abortInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'abort', {
|
|
27
|
+
before: abortXhr
|
|
28
|
+
});
|
|
29
|
+
return function () {
|
|
30
|
+
openInstrumentMethod.stop();
|
|
31
|
+
sendInstrumentMethod.stop();
|
|
32
|
+
abortInstrumentMethod.stop();
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
return observable;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function openXhr(method, url) {
|
|
39
|
+
var requestUUID = this[DATA_FLUX_REQUEST_ID_KEY] || UUID();
|
|
40
|
+
this[DATA_FLUX_REQUEST_ID_KEY] = requestUUID;
|
|
41
|
+
xhrContexts[requestUUID] = {
|
|
42
|
+
state: 'open',
|
|
43
|
+
method: method,
|
|
44
|
+
url: normalizeUrl(String(url))
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function sendXhr(observable) {
|
|
49
|
+
var context = xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]];
|
|
50
|
+
|
|
51
|
+
if (!context) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var startContext = context;
|
|
56
|
+
startContext.state = 'start';
|
|
57
|
+
startContext.startTime = relativeNow();
|
|
58
|
+
startContext.startClocks = clocksNow();
|
|
59
|
+
startContext.isAborted = false;
|
|
60
|
+
startContext.xhr = this;
|
|
61
|
+
var hasBeenReported = false;
|
|
62
|
+
var onreadyStateChangeInstrumentMethod = instrumentMethodAndCallOriginal(this, 'onreadystatechange', {
|
|
63
|
+
before: function before() {
|
|
64
|
+
if (this.readyState === XMLHttpRequest.DONE) {
|
|
65
|
+
// Try to report the XHR as soon as possible, because the XHR may be mutated by the
|
|
66
|
+
// application during a future event. For example, Angular is calling .abort() on
|
|
67
|
+
// completed requests during a onreadystatechange event, so the status becomes '0'
|
|
68
|
+
// before the request is collected.
|
|
69
|
+
onEnd.call(this);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
var onEnd = function onEnd() {
|
|
75
|
+
this.removeEventListener('loadend', onEnd);
|
|
76
|
+
onreadyStateChangeInstrumentMethod.stop();
|
|
77
|
+
|
|
78
|
+
if (hasBeenReported) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
hasBeenReported = true;
|
|
83
|
+
var completeContext = context;
|
|
84
|
+
completeContext.state = 'complete';
|
|
85
|
+
completeContext.duration = elapsed(startContext.startClocks.timeStamp, timeStampNow());
|
|
86
|
+
completeContext.status = this.status;
|
|
87
|
+
observable.notify(shallowClone(completeContext));
|
|
88
|
+
clearRequestId.call(this);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
this.addEventListener('loadend', onEnd);
|
|
92
|
+
observable.notify(startContext);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function clearRequestId() {
|
|
96
|
+
delete xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]];
|
|
97
|
+
delete this[DATA_FLUX_REQUEST_ID_KEY];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function abortXhr() {
|
|
101
|
+
var context = xhrContexts[this[DATA_FLUX_REQUEST_ID_KEY]];
|
|
102
|
+
|
|
103
|
+
if (context) {
|
|
104
|
+
context.isAborted = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { getCurrentSite } from '../browser/cookie';
|
|
2
|
+
import { catchUserErrors } from '../helper/catchUserErrors';
|
|
3
|
+
import { display } from '../helper/display';
|
|
4
|
+
import { assign, isPercentage, ONE_KIBI_BYTE, ONE_SECOND, isNullUndefinedDefaultValue } from '../helper/tools';
|
|
5
|
+
import { computeTransportConfiguration } from './transportConfiguration';
|
|
6
|
+
export function validateAndBuildConfiguration(initConfiguration) {
|
|
7
|
+
if (initConfiguration.sampleRate !== undefined && !isPercentage(initConfiguration.sampleRate)) {
|
|
8
|
+
display.error('Sample Rate should be a number between 0 and 100');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return assign({
|
|
13
|
+
beforeSend: initConfiguration.beforeSend && catchUserErrors(initConfiguration.beforeSend, 'beforeSend threw an error:'),
|
|
14
|
+
cookieOptions: buildCookieOptions(initConfiguration),
|
|
15
|
+
sampleRate: isNullUndefinedDefaultValue(initConfiguration.sampleRate, 100),
|
|
16
|
+
service: initConfiguration.service,
|
|
17
|
+
version: initConfiguration.version,
|
|
18
|
+
env: initConfiguration.env,
|
|
19
|
+
silentMultipleInit: !!initConfiguration.silentMultipleInit,
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* beacon payload max queue size implementation is 64kb
|
|
23
|
+
* ensure that we leave room for logs, rum and potential other users
|
|
24
|
+
*/
|
|
25
|
+
batchBytesLimit: 16 * ONE_KIBI_BYTE,
|
|
26
|
+
eventRateLimiterThreshold: 3000,
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* flush automatically, aim to be lower than ALB connection timeout
|
|
30
|
+
* to maximize connection reuse.
|
|
31
|
+
*/
|
|
32
|
+
flushTimeout: 30 * ONE_SECOND,
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Logs intake limit
|
|
36
|
+
*/
|
|
37
|
+
batchMessagesLimit: 50,
|
|
38
|
+
messageBytesLimit: 256 * ONE_KIBI_BYTE
|
|
39
|
+
}, computeTransportConfiguration(initConfiguration));
|
|
40
|
+
}
|
|
41
|
+
export function buildCookieOptions(initConfiguration) {
|
|
42
|
+
var cookieOptions = {};
|
|
43
|
+
cookieOptions.secure = mustUseSecureCookie(initConfiguration);
|
|
44
|
+
cookieOptions.crossSite = !!initConfiguration.useCrossSiteSessionCookie;
|
|
45
|
+
|
|
46
|
+
if (initConfiguration.trackSessionAcrossSubdomains) {
|
|
47
|
+
cookieOptions.domain = getCurrentSite();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return cookieOptions;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function mustUseSecureCookie(initConfiguration) {
|
|
54
|
+
return !!initConfiguration.useSecureSessionCookie || !!initConfiguration.useCrossSiteSessionCookie;
|
|
55
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { isFunction, isBoolean, some } from '../helper/tools';
|
|
2
|
+
var TRIM_REGIX = /^\s+|\s+$/g;
|
|
3
|
+
|
|
4
|
+
function getDatakitUrl(url) {
|
|
5
|
+
if (url.lastIndexOf('/') === url.length - 1) return trim(url) + 'v1/write/rum';
|
|
6
|
+
return trim(url) + '/v1/write/rum';
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function trim(str) {
|
|
10
|
+
return str.replace(TRIM_REGIX, '');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getLogsEndPoint(url) {
|
|
14
|
+
if (url.lastIndexOf('/') === url.length - 1) return trim(url) + 'v1/write/logging';
|
|
15
|
+
return trim(url) + '/v1/write/logging';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function computeTransportConfiguration(initConfiguration) {
|
|
19
|
+
var isIntakeUrl = function isIntakeUrl(url) {
|
|
20
|
+
return false;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if ('isIntakeUrl' in initConfiguration && isFunction(initConfiguration.isIntakeUrl) && isBoolean(initConfiguration.isIntakeUrl())) {
|
|
24
|
+
isIntakeUrl = initConfiguration.isIntakeUrl;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var isServerError = function isServerError(request) {
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if ('isServerError' in initConfiguration && isFunction(initConfiguration.isServerError) && isBoolean(initConfiguration.isServerError())) {
|
|
32
|
+
isServerError = initConfiguration.isServerError;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
datakitUrl: getDatakitUrl(initConfiguration.datakitUrl || initConfiguration.datakitOrigin),
|
|
37
|
+
logsEndpoint: getLogsEndPoint(initConfiguration.datakitOrigin),
|
|
38
|
+
isIntakeUrl: isIntakeUrl,
|
|
39
|
+
isServerError: isServerError
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function isIntakeRequest(url, configuration) {
|
|
43
|
+
// return haveSameOrigin(url, configuration.datakitUrl)
|
|
44
|
+
var notTakeRequest = [configuration.datakitUrl];
|
|
45
|
+
|
|
46
|
+
if (configuration.logsEndpoint) {
|
|
47
|
+
notTakeRequest.push(configuration.logsEndpoint);
|
|
48
|
+
} // datakit 地址,log 地址,以及客户自定义过滤方法定义url
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
return some(notTakeRequest, function (takeUrl) {
|
|
52
|
+
return url.indexOf(takeUrl) === 0;
|
|
53
|
+
}) || configuration.isIntakeUrl(url);
|
|
54
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { computeStackTrace } from '../tracekit';
|
|
2
|
+
import { createHandlingStack, formatErrorMessage, toStackTraceString } from '../helper/errorTools';
|
|
3
|
+
import { mergeObservables, Observable } from '../helper/observable';
|
|
4
|
+
import { find, jsonStringify, map } from '../helper/tools';
|
|
5
|
+
import { ConsoleApiName } from '../helper/display';
|
|
6
|
+
var consoleObservablesByApi = {};
|
|
7
|
+
export function initConsoleObservable(apis) {
|
|
8
|
+
var consoleObservables = map(apis, function (api) {
|
|
9
|
+
if (!consoleObservablesByApi[api]) {
|
|
10
|
+
consoleObservablesByApi[api] = createConsoleObservable(api);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return consoleObservablesByApi[api];
|
|
14
|
+
});
|
|
15
|
+
return mergeObservables.apply(this, consoleObservables);
|
|
16
|
+
}
|
|
17
|
+
/* eslint-disable no-console */
|
|
18
|
+
|
|
19
|
+
function createConsoleObservable(api) {
|
|
20
|
+
var observable = new Observable(function () {
|
|
21
|
+
var originalConsoleApi = console[api];
|
|
22
|
+
|
|
23
|
+
console[api] = function () {
|
|
24
|
+
var params = [].slice.call(arguments);
|
|
25
|
+
originalConsoleApi.apply(console, arguments);
|
|
26
|
+
var handlingStack = createHandlingStack();
|
|
27
|
+
observable.notify(buildConsoleLog(params, api, handlingStack));
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
return function () {
|
|
31
|
+
console[api] = originalConsoleApi;
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
return observable;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildConsoleLog(params, api, handlingStack) {
|
|
38
|
+
// Todo: remove console error prefix in the next major version
|
|
39
|
+
var message = map(params, function (param) {
|
|
40
|
+
return formatConsoleParameters(param);
|
|
41
|
+
}).join(' ');
|
|
42
|
+
var stack;
|
|
43
|
+
|
|
44
|
+
if (api === ConsoleApiName.error) {
|
|
45
|
+
var firstErrorParam = find(params, function (param) {
|
|
46
|
+
return param instanceof Error;
|
|
47
|
+
});
|
|
48
|
+
stack = firstErrorParam ? toStackTraceString(computeStackTrace(firstErrorParam)) : undefined;
|
|
49
|
+
message = 'console error: ' + message;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
api: api,
|
|
54
|
+
message: message,
|
|
55
|
+
stack: stack,
|
|
56
|
+
handlingStack: handlingStack
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function formatConsoleParameters(param) {
|
|
61
|
+
if (typeof param === 'string') {
|
|
62
|
+
return param;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (param instanceof Error) {
|
|
66
|
+
return formatErrorMessage(computeStackTrace(param));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return jsonStringify(param, undefined, 2);
|
|
70
|
+
}
|