@cloudcare/browser-core 2.0.3 → 2.0.5
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/addEventListener.js +57 -0
- package/cjs/browser/pageExitObservable.js +4 -2
- package/cjs/browser/runOnReadyState.js +21 -0
- package/cjs/browser/xhrObservable.js +7 -5
- package/cjs/configuration/configuration.js +5 -3
- package/cjs/console/consoleObservable.js +3 -1
- package/cjs/dataMap.js +1 -0
- package/cjs/helper/byteUtils.js +26 -0
- package/cjs/helper/contextHistory.js +4 -2
- package/cjs/helper/createEventRateLimiter.js +3 -1
- package/cjs/helper/errorTools.js +4 -2
- package/cjs/helper/instrumentMethod.js +2 -4
- package/cjs/helper/serialisation/contextManager.js +84 -0
- package/cjs/helper/serialisation/heavyCustomerDataWarning.js +34 -0
- package/cjs/helper/serialisation/jsonStringify.js +57 -0
- package/cjs/helper/serialisation/rowData.js +50 -0
- package/cjs/helper/timer.js +29 -0
- package/cjs/helper/tools.js +10 -331
- package/cjs/index.js +117 -0
- package/cjs/init.js +6 -6
- package/cjs/report/reportObservable.js +4 -2
- package/cjs/session/sessionCookieStore.js +3 -1
- package/cjs/session/sessionManagement.js +10 -5
- package/cjs/session/sessionStore.js +10 -4
- package/cjs/transport/batch.js +40 -91
- package/cjs/transport/flushController.js +121 -0
- package/cjs/transport/httpRequest.js +6 -2
- package/cjs/transport/index.js +9 -1
- package/cjs/transport/sendWithRetryStrategy.js +8 -4
- package/cjs/transport/startBatchWithReplica.js +10 -2
- package/cjs/user/index.js +18 -0
- package/cjs/user/user.js +42 -0
- package/esm/browser/addEventListener.js +46 -0
- package/esm/browser/pageExitObservable.js +2 -1
- package/esm/browser/runOnReadyState.js +12 -0
- package/esm/browser/xhrObservable.js +6 -5
- package/esm/configuration/configuration.js +2 -1
- package/esm/console/consoleObservable.js +2 -1
- package/esm/dataMap.js +1 -0
- package/esm/helper/byteUtils.js +16 -0
- package/esm/helper/contextHistory.js +1 -0
- package/esm/helper/createEventRateLimiter.js +1 -0
- package/esm/helper/errorTools.js +2 -1
- package/esm/helper/instrumentMethod.js +1 -3
- package/esm/helper/serialisation/contextManager.js +70 -0
- package/esm/helper/serialisation/heavyCustomerDataWarning.js +20 -0
- package/esm/helper/serialisation/jsonStringify.js +46 -0
- package/esm/helper/serialisation/rowData.js +33 -0
- package/esm/helper/timer.js +14 -0
- package/esm/helper/tools.js +1 -292
- package/esm/index.js +10 -1
- package/esm/init.js +6 -6
- package/esm/report/reportObservable.js +3 -2
- package/esm/session/sessionCookieStore.js +1 -0
- package/esm/session/sessionManagement.js +5 -2
- package/esm/session/sessionStore.js +7 -2
- package/esm/transport/batch.js +31 -85
- package/esm/transport/flushController.js +114 -0
- package/esm/transport/httpRequest.js +5 -2
- package/esm/transport/index.js +2 -1
- package/esm/transport/sendWithRetryStrategy.js +3 -1
- package/esm/transport/startBatchWithReplica.js +9 -2
- package/esm/user/index.js +1 -0
- package/esm/user/user.js +32 -0
- package/package.json +22 -22
- package/src/browser/addEventListener.js +50 -0
- package/src/browser/pageExitObservable.js +4 -5
- package/src/browser/runOnReadyState.js +16 -0
- package/src/browser/xhrObservable.js +57 -32
- package/src/configuration/configuration.js +1 -1
- package/src/console/consoleObservable.js +22 -12
- package/src/dataMap.js +1 -0
- package/src/helper/byteUtils.js +17 -0
- package/src/helper/contextHistory.js +1 -1
- package/src/helper/createEventRateLimiter.js +7 -9
- package/src/helper/errorTools.js +2 -1
- package/src/helper/instrumentMethod.js +1 -2
- package/src/helper/serialisation/contextManager.js +79 -0
- package/src/helper/serialisation/heavyCustomerDataWarning.js +28 -0
- package/src/helper/serialisation/jsonStringify.js +47 -0
- package/src/helper/serialisation/rowData.js +41 -0
- package/src/helper/timer.js +21 -0
- package/src/helper/tools.js +2 -301
- package/src/index.js +11 -0
- package/src/init.js +6 -6
- package/src/report/reportObservable.js +40 -25
- package/src/session/sessionCookieStore.js +24 -14
- package/src/session/sessionManagement.js +34 -17
- package/src/session/sessionStore.js +7 -2
- package/src/transport/batch.js +39 -91
- package/src/transport/flushController.js +115 -0
- package/src/transport/httpRequest.js +13 -6
- package/src/transport/index.js +1 -0
- package/src/transport/sendWithRetryStrategy.js +3 -7
- package/src/transport/startBatchWithReplica.js +11 -7
- package/src/user/index.js +1 -0
- package/src/user/user.js +31 -0
package/esm/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export * from './helper/deviceInfo';
|
|
|
4
4
|
export * from './helper/enums';
|
|
5
5
|
export * from './helper/instrumentMethod';
|
|
6
6
|
export * from './helper/errorTools';
|
|
7
|
+
export * from './helper/byteUtils';
|
|
7
8
|
export * from './error/trackRuntimeError';
|
|
8
9
|
export * from './console/consoleObservable';
|
|
9
10
|
export * from './report/reportObservable';
|
|
@@ -17,6 +18,7 @@ export * from './helper/tools';
|
|
|
17
18
|
export * from './helper/urlPolyfill';
|
|
18
19
|
export * from './helper/mobileUtil';
|
|
19
20
|
export * from './helper/getZoneJsOriginalValue';
|
|
21
|
+
export * from './helper/timer';
|
|
20
22
|
export * from './helper/readBytesFromStream';
|
|
21
23
|
export * from './tracekit';
|
|
22
24
|
export * from './configuration/configuration';
|
|
@@ -26,6 +28,8 @@ export * from './browser/fetchObservable';
|
|
|
26
28
|
export * from './browser/xhrObservable';
|
|
27
29
|
export * from './browser/pageExitObservable';
|
|
28
30
|
export * from './browser/htmlDomUtils';
|
|
31
|
+
export * from './browser/addEventListener';
|
|
32
|
+
export * from './browser/runOnReadyState';
|
|
29
33
|
export * from './dataMap';
|
|
30
34
|
export * from './init';
|
|
31
35
|
export * from './session/sessionManagement';
|
|
@@ -33,4 +37,9 @@ export * from './session/sessionConstants';
|
|
|
33
37
|
export * from './session/sessionCookieStore';
|
|
34
38
|
export * from './session/sessionStore';
|
|
35
39
|
export * from './transport';
|
|
36
|
-
export * from './synthetics/syntheticsWorkerValues';
|
|
40
|
+
export * from './synthetics/syntheticsWorkerValues';
|
|
41
|
+
export * from './helper/serialisation/contextManager';
|
|
42
|
+
export * from './helper/serialisation/heavyCustomerDataWarning';
|
|
43
|
+
export * from './helper/serialisation/jsonStringify';
|
|
44
|
+
export * from './helper/serialisation/rowData';
|
|
45
|
+
export * from './user';
|
package/esm/init.js
CHANGED
|
@@ -14,13 +14,13 @@ export function makePublicApi(stub) {
|
|
|
14
14
|
}
|
|
15
15
|
}); // Add an "hidden" property to set debug mode. We define it that way to hide it
|
|
16
16
|
// as much as possible but of course it's not a real protection.
|
|
17
|
+
// Object.defineProperty(publicApi, '_setDebug', {
|
|
18
|
+
// get: function () {
|
|
19
|
+
// return setDebugMode
|
|
20
|
+
// },
|
|
21
|
+
// enumerable: false
|
|
22
|
+
// })
|
|
17
23
|
|
|
18
|
-
Object.defineProperty(publicApi, '_setDebug', {
|
|
19
|
-
get: function get() {
|
|
20
|
-
return setDebugMode;
|
|
21
|
-
},
|
|
22
|
-
enumerable: false
|
|
23
|
-
});
|
|
24
24
|
return publicApi;
|
|
25
25
|
}
|
|
26
26
|
export function defineGlobal(global, name, api) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { toStackTraceString } from '../helper/errorTools';
|
|
2
2
|
import { mergeObservables, Observable } from '../helper/observable';
|
|
3
|
-
import { includes,
|
|
3
|
+
import { includes, safeTruncate, filter, each } from '../helper/tools';
|
|
4
|
+
import { addEventListener } from '../browser/addEventListener';
|
|
4
5
|
import { DOM_EVENT } from '../helper/enums';
|
|
5
6
|
export var RawReportType = {
|
|
6
7
|
intervention: 'intervention',
|
|
@@ -75,7 +76,7 @@ function buildRawReportFromReport(report) {
|
|
|
75
76
|
|
|
76
77
|
function buildRawReportFromCspViolation(event) {
|
|
77
78
|
var type = RawReportType.cspViolation;
|
|
78
|
-
var message = '
|
|
79
|
+
var message = "'" + event.blockedURI + "' blocked by '" + event.effectiveDirective + "' directive";
|
|
79
80
|
return {
|
|
80
81
|
type: RawReportType.cspViolation,
|
|
81
82
|
subtype: event.effectiveDirective,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getCookie, setCookie } from '../browser/cookie';
|
|
2
2
|
import { isChromium, dateNow, isEmptyObject, UUID, objectEntries, map, each } from '../helper/tools';
|
|
3
3
|
import { SESSION_EXPIRATION_DELAY } from './sessionConstants';
|
|
4
|
+
import { setTimeout } from '../helper/timer';
|
|
4
5
|
var SESSION_ENTRY_REGEXP = /^([a-z]+)=([a-z0-9-]+)$/;
|
|
5
6
|
var SESSION_ENTRY_SEPARATOR = '&';
|
|
6
7
|
export var SESSION_COOKIE_NAME = '_dataflux_s'; // arbitrary values
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { relativeNow, clocksOrigin, ONE_MINUTE, each
|
|
1
|
+
import { relativeNow, clocksOrigin, ONE_MINUTE, each } from '../helper/tools';
|
|
2
|
+
import { addEventListeners, addEventListener } from '../browser/addEventListener';
|
|
2
3
|
import { ContextHistory } from '../helper/contextHistory';
|
|
3
4
|
import { startSessionStore } from './sessionStore';
|
|
4
5
|
import { SESSION_TIME_OUT_DELAY } from './sessionConstants';
|
|
5
6
|
import { DOM_EVENT } from '../helper/enums';
|
|
7
|
+
import { clearInterval, setInterval } from '../helper/timer';
|
|
6
8
|
export var VISIBILITY_CHECK_DELAY = ONE_MINUTE;
|
|
7
9
|
var SESSION_CONTEXT_TIMEOUT_DELAY = SESSION_TIME_OUT_DELAY;
|
|
8
10
|
var stopCallbacks = [];
|
|
@@ -42,7 +44,8 @@ export var startSessionManager = function startSessionManager(options, productKe
|
|
|
42
44
|
return sessionContextHistory.find(startTime);
|
|
43
45
|
},
|
|
44
46
|
renewObservable: sessionStore.renewObservable,
|
|
45
|
-
expireObservable: sessionStore.expireObservable
|
|
47
|
+
expireObservable: sessionStore.expireObservable,
|
|
48
|
+
expire: sessionStore.expire
|
|
46
49
|
};
|
|
47
50
|
};
|
|
48
51
|
export function stopSessionManager() {
|
|
@@ -3,6 +3,7 @@ import { Observable } from '../helper/observable';
|
|
|
3
3
|
import { dateNow, UUID, throttle } from '../helper/tools';
|
|
4
4
|
import { SESSION_TIME_OUT_DELAY } from './sessionConstants';
|
|
5
5
|
import { retrieveSession, withCookieLockAccess } from './sessionCookieStore';
|
|
6
|
+
import { clearInterval, setInterval } from '../helper/timer';
|
|
6
7
|
/**
|
|
7
8
|
* Different session concepts:
|
|
8
9
|
* - tracked, the session has an id and is updated along the user navigation
|
|
@@ -67,7 +68,7 @@ export function startSessionStore(options, productKey, computeSessionState) {
|
|
|
67
68
|
|
|
68
69
|
if (hasSessionInCache()) {
|
|
69
70
|
if (isSessionInCacheOutdated(cookieSession)) {
|
|
70
|
-
|
|
71
|
+
expireSessionInCache();
|
|
71
72
|
} else {
|
|
72
73
|
sessionCache = cookieSession;
|
|
73
74
|
}
|
|
@@ -98,7 +99,7 @@ export function startSessionStore(options, productKey, computeSessionState) {
|
|
|
98
99
|
return sessionCache.id !== cookieSession.id || sessionCache[productKey] !== cookieSession[productKey];
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
function
|
|
102
|
+
function expireSessionInCache() {
|
|
102
103
|
sessionCache = {};
|
|
103
104
|
expireObservable.notify();
|
|
104
105
|
}
|
|
@@ -132,6 +133,10 @@ export function startSessionStore(options, productKey, computeSessionState) {
|
|
|
132
133
|
},
|
|
133
134
|
renewObservable: renewObservable,
|
|
134
135
|
expireObservable: expireObservable,
|
|
136
|
+
expire: function expire() {
|
|
137
|
+
deleteSessionCookie(options);
|
|
138
|
+
synchronizeSession({});
|
|
139
|
+
},
|
|
135
140
|
stop: function stop() {
|
|
136
141
|
clearInterval(watchSessionTimeoutId);
|
|
137
142
|
}
|
package/esm/transport/batch.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { display } from '../helper/display';
|
|
2
|
-
import {
|
|
2
|
+
import { values, findByPath, each, isNumber, isArray, extend, isString, toServerDuration, isBoolean, isEmptyObject, isObject } from '../helper/tools';
|
|
3
|
+
import { escapeJsonValue, escapeRowField, escapeRowData } from '../helper/serialisation/rowData';
|
|
3
4
|
import { commonTags, dataMap, commonFields } from '../dataMap';
|
|
4
|
-
import {
|
|
5
|
+
import { RumEventType } from '../helper/enums';
|
|
6
|
+
import { computeBytesCount } from '../helper/byteUtils';
|
|
7
|
+
import { isPageExitReason } from '../browser/pageExitObservable'; // https://en.wikipedia.org/wiki/UTF-8
|
|
5
8
|
// eslint-disable-next-line no-control-regex
|
|
6
9
|
|
|
7
10
|
var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/;
|
|
@@ -124,23 +127,18 @@ export var processedMessageByDataMap = function processedMessageByDataMap(messag
|
|
|
124
127
|
};
|
|
125
128
|
};
|
|
126
129
|
|
|
127
|
-
var batch = function batch(request,
|
|
130
|
+
var batch = function batch(request, flushController, messageBytesLimit) {
|
|
128
131
|
this.pushOnlyBuffer = [];
|
|
129
132
|
this.upsertBuffer = {};
|
|
130
|
-
this.bufferBytesCount = 0;
|
|
131
|
-
this.bufferMessagesCount = 0;
|
|
132
133
|
this.request = request;
|
|
133
|
-
this.
|
|
134
|
-
this.batchBytesLimit = batchBytesLimit;
|
|
134
|
+
this.flushController = flushController;
|
|
135
135
|
this.messageBytesLimit = messageBytesLimit;
|
|
136
|
-
this.flushTimeout = flushTimeout;
|
|
137
136
|
|
|
138
137
|
var _this = this;
|
|
139
138
|
|
|
140
|
-
|
|
141
|
-
_this.flush(
|
|
139
|
+
this.flushController.flushObservable.subscribe(function (event) {
|
|
140
|
+
_this.flush(event);
|
|
142
141
|
});
|
|
143
|
-
this.flushPeriodically();
|
|
144
142
|
};
|
|
145
143
|
|
|
146
144
|
batch.prototype.add = function (message) {
|
|
@@ -151,45 +149,26 @@ batch.prototype.upsert = function (message, key) {
|
|
|
151
149
|
this.addOrUpdate(message, key);
|
|
152
150
|
};
|
|
153
151
|
|
|
154
|
-
batch.prototype.flush = function (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
152
|
+
batch.prototype.flush = function (event) {
|
|
153
|
+
var messages = this.pushOnlyBuffer.concat(values(this.upsertBuffer));
|
|
154
|
+
this.pushOnlyBuffer = [];
|
|
155
|
+
this.upsertBuffer = {};
|
|
158
156
|
|
|
159
|
-
if (
|
|
160
|
-
var
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
bytesCount: bytesCount
|
|
171
|
-
});
|
|
157
|
+
if (messages.length > 0) {
|
|
158
|
+
var payload = {
|
|
159
|
+
data: messages.join('\n'),
|
|
160
|
+
bytesCount: event.bytesCount,
|
|
161
|
+
flushReason: event.reason
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
if (isPageExitReason(event.reason)) {
|
|
165
|
+
this.request.sendOnExit(payload);
|
|
166
|
+
} else {
|
|
167
|
+
this.request.send(payload);
|
|
172
168
|
}
|
|
173
169
|
}
|
|
174
170
|
};
|
|
175
171
|
|
|
176
|
-
batch.prototype.flushOnExit = function () {
|
|
177
|
-
this.flush(this.request.sendOnExit);
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
batch.prototype.computeBytesCount = function (candidate) {
|
|
181
|
-
// Accurate bytes count computations can degrade performances when there is a lot of events to process
|
|
182
|
-
if (!HAS_MULTI_BYTES_CHARACTERS.test(candidate)) {
|
|
183
|
-
return candidate.length;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (window.TextEncoder !== undefined) {
|
|
187
|
-
return new TextEncoder().encode(candidate).length;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return new Blob([candidate]).size;
|
|
191
|
-
};
|
|
192
|
-
|
|
193
172
|
batch.prototype.addOrUpdate = function (message, key) {
|
|
194
173
|
var _process = this.process(message);
|
|
195
174
|
|
|
@@ -205,20 +184,12 @@ batch.prototype.addOrUpdate = function (message, key) {
|
|
|
205
184
|
this.remove(key);
|
|
206
185
|
}
|
|
207
186
|
|
|
208
|
-
if (this.willReachedBytesLimitWith(messageBytesCount)) {
|
|
209
|
-
this.flush();
|
|
210
|
-
}
|
|
211
|
-
|
|
212
187
|
this.push(processedMessage, messageBytesCount, key);
|
|
213
|
-
|
|
214
|
-
if (this.isFull()) {
|
|
215
|
-
this.flush();
|
|
216
|
-
}
|
|
217
188
|
};
|
|
218
189
|
|
|
219
190
|
batch.prototype.process = function (message) {
|
|
220
191
|
var processedMessage = processedMessageByDataMap(message).rowStr;
|
|
221
|
-
var messageBytesCount =
|
|
192
|
+
var messageBytesCount = computeBytesCount(processedMessage);
|
|
222
193
|
return {
|
|
223
194
|
processedMessage: processedMessage,
|
|
224
195
|
messageBytesCount: messageBytesCount
|
|
@@ -226,10 +197,8 @@ batch.prototype.process = function (message) {
|
|
|
226
197
|
};
|
|
227
198
|
|
|
228
199
|
batch.prototype.push = function (processedMessage, messageBytesCount, key) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
this.bufferBytesCount += 1;
|
|
232
|
-
}
|
|
200
|
+
var separatorBytesCount = this.flushController.getMessagesCount() > 0 ? 1 : 0;
|
|
201
|
+
this.flushController.notifyBeforeAddMessage(messageBytesCount + separatorBytesCount);
|
|
233
202
|
|
|
234
203
|
if (key !== undefined) {
|
|
235
204
|
this.upsertBuffer[key] = processedMessage;
|
|
@@ -237,43 +206,20 @@ batch.prototype.push = function (processedMessage, messageBytesCount, key) {
|
|
|
237
206
|
this.pushOnlyBuffer.push(processedMessage);
|
|
238
207
|
}
|
|
239
208
|
|
|
240
|
-
this.
|
|
241
|
-
this.bufferMessagesCount += 1;
|
|
209
|
+
this.flushController.notifyAfterAddMessage();
|
|
242
210
|
};
|
|
243
211
|
|
|
244
212
|
batch.prototype.remove = function (key) {
|
|
245
213
|
var removedMessage = this.upsertBuffer[key];
|
|
246
214
|
delete this.upsertBuffer[key];
|
|
247
|
-
var messageBytesCount =
|
|
248
|
-
this.bufferBytesCount -= messageBytesCount;
|
|
249
|
-
this.bufferMessagesCount -= 1;
|
|
215
|
+
var messageBytesCount = computeBytesCount(removedMessage); // If there are other messages, a '\n' will be added at serialization
|
|
250
216
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
}
|
|
217
|
+
var separatorBytesCount = this.flushController.getMessagesCount() > 1 ? 1 : 0;
|
|
218
|
+
this.flushController.notifyAfterRemoveMessage(messageBytesCount + separatorBytesCount);
|
|
254
219
|
};
|
|
255
220
|
|
|
256
221
|
batch.prototype.hasMessageFor = function (key) {
|
|
257
222
|
return key !== undefined && this.upsertBuffer[key] !== undefined;
|
|
258
223
|
};
|
|
259
224
|
|
|
260
|
-
batch.prototype.willReachedBytesLimitWith = function (messageBytesCount) {
|
|
261
|
-
// byte of the separator at the end of the message
|
|
262
|
-
return this.bufferBytesCount + messageBytesCount + 1 >= this.batchBytesLimit;
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
batch.prototype.isFull = function () {
|
|
266
|
-
return this.bufferMessagesCount === this.batchMessagesLimit || this.bufferBytesCount >= this.batchBytesLimit;
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
batch.prototype.flushPeriodically = function () {
|
|
270
|
-
var _this = this;
|
|
271
|
-
|
|
272
|
-
setTimeout(function () {
|
|
273
|
-
_this.flush();
|
|
274
|
-
|
|
275
|
-
_this.flushPeriodically();
|
|
276
|
-
}, this.flushTimeout);
|
|
277
|
-
};
|
|
278
|
-
|
|
279
225
|
export var Batch = batch;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Observable } from '../helper/observable';
|
|
2
|
+
import { clearTimeout, setTimeout } from '../helper/timer'; // type FlushReason = PageExitReason | 'duration_limit' | 'bytes_limit' | 'messages_limit' | 'session_expire'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns a "flush controller", responsible of notifying when flushing a pool of pending data needs
|
|
6
|
+
* to happen. The implementation is designed to support both synchronous and asynchronous usages,
|
|
7
|
+
* but relies on invariants described in each method documentation to keep a coherent state.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function createFlushController(_ref) {
|
|
11
|
+
var {
|
|
12
|
+
messagesLimit,
|
|
13
|
+
bytesLimit,
|
|
14
|
+
durationLimit,
|
|
15
|
+
pageExitObservable,
|
|
16
|
+
sessionExpireObservable
|
|
17
|
+
} = _ref;
|
|
18
|
+
var flushObservable = new Observable();
|
|
19
|
+
pageExitObservable.subscribe(function (event) {
|
|
20
|
+
return flush(event.reason);
|
|
21
|
+
});
|
|
22
|
+
sessionExpireObservable.subscribe(function () {
|
|
23
|
+
return flush('session_expire');
|
|
24
|
+
});
|
|
25
|
+
var currentBytesCount = 0;
|
|
26
|
+
var currentMessagesCount = 0;
|
|
27
|
+
|
|
28
|
+
function flush(flushReason) {
|
|
29
|
+
if (currentMessagesCount === 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
var messagesCount = currentMessagesCount;
|
|
34
|
+
var bytesCount = currentBytesCount;
|
|
35
|
+
currentMessagesCount = 0;
|
|
36
|
+
currentBytesCount = 0;
|
|
37
|
+
cancelDurationLimitTimeout();
|
|
38
|
+
flushObservable.notify({
|
|
39
|
+
reason: flushReason,
|
|
40
|
+
messagesCount: messagesCount,
|
|
41
|
+
bytesCount: bytesCount
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var durationLimitTimeoutId;
|
|
46
|
+
|
|
47
|
+
function scheduleDurationLimitTimeout() {
|
|
48
|
+
if (durationLimitTimeoutId === undefined) {
|
|
49
|
+
durationLimitTimeoutId = setTimeout(function () {
|
|
50
|
+
flush('duration_limit');
|
|
51
|
+
}, durationLimit);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function cancelDurationLimitTimeout() {
|
|
56
|
+
clearTimeout(durationLimitTimeoutId);
|
|
57
|
+
durationLimitTimeoutId = undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
flushObservable: flushObservable,
|
|
62
|
+
getMessagesCount: function getMessagesCount() {
|
|
63
|
+
return currentMessagesCount;
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Notifies that a message will be added to a pool of pending messages waiting to be flushed.
|
|
68
|
+
*
|
|
69
|
+
* This function needs to be called synchronously, right before adding the message, so no flush
|
|
70
|
+
* event can happen after `notifyBeforeAddMessage` and before adding the message.
|
|
71
|
+
*/
|
|
72
|
+
notifyBeforeAddMessage: function notifyBeforeAddMessage(messageBytesCount) {
|
|
73
|
+
if (currentBytesCount + messageBytesCount >= bytesLimit) {
|
|
74
|
+
flush('bytes_limit');
|
|
75
|
+
} // Consider the message to be added now rather than in `notifyAfterAddMessage`, because if no
|
|
76
|
+
// message was added yet and `notifyAfterAddMessage` is called asynchronously, we still want
|
|
77
|
+
// to notify when a flush is needed (for example on page exit).
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
currentMessagesCount += 1;
|
|
81
|
+
currentBytesCount += messageBytesCount;
|
|
82
|
+
scheduleDurationLimitTimeout();
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Notifies that a message *was* added to a pool of pending messages waiting to be flushed.
|
|
87
|
+
*
|
|
88
|
+
* This function can be called asynchronously after the message was added, but in this case it
|
|
89
|
+
* should not be called if a flush event occurred in between.
|
|
90
|
+
*/
|
|
91
|
+
notifyAfterAddMessage: function notifyAfterAddMessage() {
|
|
92
|
+
if (currentMessagesCount >= messagesLimit) {
|
|
93
|
+
flush('messages_limit');
|
|
94
|
+
} else if (currentBytesCount >= bytesLimit) {
|
|
95
|
+
flush('bytes_limit');
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Notifies that a message was removed from a pool of pending messages waiting to be flushed.
|
|
101
|
+
*
|
|
102
|
+
* This function needs to be called synchronously, right after removing the message, so no flush
|
|
103
|
+
* event can happen after removing the message and before `notifyAfterRemoveMessage`.
|
|
104
|
+
*/
|
|
105
|
+
notifyAfterRemoveMessage: function notifyAfterRemoveMessage(messageBytesCount) {
|
|
106
|
+
currentBytesCount -= messageBytesCount;
|
|
107
|
+
currentMessagesCount -= 1;
|
|
108
|
+
|
|
109
|
+
if (currentMessagesCount === 0) {
|
|
110
|
+
cancelDurationLimitTimeout();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { newRetryState, sendWithRetryStrategy } from './sendWithRetryStrategy';
|
|
2
|
+
import { addEventListener } from '../browser/addEventListener';
|
|
2
3
|
/**
|
|
3
4
|
* Use POST request without content type to:
|
|
4
5
|
* - avoid CORS preflight requests
|
|
@@ -95,12 +96,14 @@ function isKeepAliveSupported() {
|
|
|
95
96
|
function sendXHR(url, data, onResponse) {
|
|
96
97
|
var request = new XMLHttpRequest();
|
|
97
98
|
request.open('POST', url, true);
|
|
98
|
-
request
|
|
99
|
-
request.addEventListener('loadend', function () {
|
|
99
|
+
addEventListener(request, 'loadend', function () {
|
|
100
100
|
if (typeof onResponse === 'function') {
|
|
101
101
|
onResponse({
|
|
102
102
|
status: request.status
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
+
}, {
|
|
106
|
+
once: true
|
|
105
107
|
});
|
|
108
|
+
request.send(data);
|
|
106
109
|
}
|
package/esm/transport/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { createHttpRequest } from './httpRequest';
|
|
2
2
|
export { Batch } from './batch';
|
|
3
|
-
export { startBatchWithReplica } from './startBatchWithReplica';
|
|
3
|
+
export { startBatchWithReplica } from './startBatchWithReplica';
|
|
4
|
+
export { createFlushController } from './flushController';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { clocksNow,
|
|
1
|
+
import { clocksNow, ONE_SECOND } from '../helper/tools';
|
|
2
|
+
import { ONE_MEBI_BYTE, ONE_KIBI_BYTE } from '../helper/byteUtils';
|
|
2
3
|
import { ErrorSource } from '../helper/errorTools';
|
|
4
|
+
import { setTimeout } from '../helper/timer';
|
|
3
5
|
export var MAX_ONGOING_BYTES_COUNT = 80 * ONE_KIBI_BYTE;
|
|
4
6
|
export var MAX_ONGOING_REQUESTS = 32;
|
|
5
7
|
export var MAX_QUEUE_BYTES_COUNT = 3 * ONE_MEBI_BYTE;
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { Batch } from './batch';
|
|
2
2
|
import { createHttpRequest } from './httpRequest';
|
|
3
|
-
|
|
3
|
+
import { createFlushController } from './flushController';
|
|
4
|
+
export function startBatchWithReplica(configuration, endpointUrl, reportError, pageExitObservable, sessionExpireObservable) {
|
|
4
5
|
var primaryBatch = createBatch(endpointUrl);
|
|
5
6
|
|
|
6
7
|
function createBatch(endpointUrl) {
|
|
7
|
-
return new Batch(createHttpRequest(endpointUrl, configuration.batchBytesLimit, reportError),
|
|
8
|
+
return new Batch(createHttpRequest(endpointUrl, configuration.batchBytesLimit, reportError), createFlushController({
|
|
9
|
+
messagesLimit: configuration.batchMessagesLimit,
|
|
10
|
+
bytesLimit: configuration.batchBytesLimit,
|
|
11
|
+
durationLimit: configuration.flushTimeout,
|
|
12
|
+
pageExitObservable: pageExitObservable,
|
|
13
|
+
sessionExpireObservable: sessionExpireObservable
|
|
14
|
+
}), configuration.messageBytesLimit);
|
|
8
15
|
}
|
|
9
16
|
|
|
10
17
|
return {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './user';
|
package/esm/user/user.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { display } from '../helper/display';
|
|
2
|
+
import { assign, getType, each } from '../helper/tools';
|
|
3
|
+
/**
|
|
4
|
+
* Clone input data and ensure known user properties (id, name, email)
|
|
5
|
+
* are strings, as defined here:
|
|
6
|
+
* https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#user-related-attributes
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function sanitizeUser(newUser) {
|
|
10
|
+
// We shallow clone only to prevent mutation of user data.
|
|
11
|
+
var user = assign({}, newUser);
|
|
12
|
+
var keys = ['id', 'name', 'email'];
|
|
13
|
+
each(keys, function (key) {
|
|
14
|
+
if (key in user) {
|
|
15
|
+
user[key] = String(user[key]);
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return user;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Simple check to ensure user is valid
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export function checkUser(newUser) {
|
|
25
|
+
var isValid = getType(newUser) === 'object';
|
|
26
|
+
|
|
27
|
+
if (!isValid) {
|
|
28
|
+
display.error('Unsupported user:', newUser);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return isValid;
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
2
|
+
"name": "@cloudcare/browser-core",
|
|
3
|
+
"version": "2.0.5",
|
|
4
|
+
"main": "cjs/index.js",
|
|
5
|
+
"module": "esm/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "run-p build:cjs build:esm",
|
|
8
|
+
"build:cjs": "rm -rf cjs && babel --config-file ./babel.cjs.json --out-dir cjs ./src",
|
|
9
|
+
"build:esm": "rm -rf esm && babel --config-file ./babel.esm.json --out-dir esm ./src "
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"dataflux",
|
|
13
|
+
"logs",
|
|
14
|
+
"sdk"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"url": "https://github.com/DataFlux-cn/datakit-js",
|
|
18
|
+
"type": "git"
|
|
19
|
+
},
|
|
20
|
+
"author": "dataflux",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"description": "DataFlux RUM Web 端数据指标监控",
|
|
23
|
+
"gitHead": "d73a29f283e62c5b13fe0b0f710b7e1e186267bc"
|
|
24
24
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { each } from '../helper/tools'
|
|
2
|
+
import { getZoneJsOriginalValue } from '../helper/getZoneJsOriginalValue'
|
|
3
|
+
export function addEventListener(eventTarget, event, listener, options) {
|
|
4
|
+
return addEventListeners(eventTarget, [event], listener, options)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Add event listeners to an event emitter object (Window, Element, mock object...). This provides
|
|
9
|
+
* a few conveniences compared to using `element.addEventListener` directly:
|
|
10
|
+
*
|
|
11
|
+
* * supports IE11 by:
|
|
12
|
+
* * using an option object only if needed
|
|
13
|
+
* * emulating the `once` option
|
|
14
|
+
*
|
|
15
|
+
* * wraps the listener with a `monitor` function
|
|
16
|
+
*
|
|
17
|
+
* * returns a `stop` function to remove the listener
|
|
18
|
+
*
|
|
19
|
+
* * with `once: true`, the listener will be called at most once, even if different events are
|
|
20
|
+
* listened
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export function addEventListeners(eventTarget, events, listener, options) {
|
|
24
|
+
var wrappedListener =
|
|
25
|
+
options && options.once
|
|
26
|
+
? function (event) {
|
|
27
|
+
stop()
|
|
28
|
+
listener(event)
|
|
29
|
+
}
|
|
30
|
+
: listener
|
|
31
|
+
|
|
32
|
+
options =
|
|
33
|
+
options && options.passive
|
|
34
|
+
? { capture: options.capture, passive: options.passive }
|
|
35
|
+
: options && options.capture
|
|
36
|
+
var add = getZoneJsOriginalValue(eventTarget, 'addEventListener')
|
|
37
|
+
|
|
38
|
+
each(events, function (event) {
|
|
39
|
+
add.call(eventTarget, event, wrappedListener, options)
|
|
40
|
+
})
|
|
41
|
+
var stop = function () {
|
|
42
|
+
var remove = getZoneJsOriginalValue(eventTarget, 'removeEventListener')
|
|
43
|
+
each(events, function (event) {
|
|
44
|
+
remove.call(eventTarget, event, wrappedListener, options)
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
stop: stop
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Observable } from '../helper/observable'
|
|
2
|
+
import { includes, values } from '../helper/tools'
|
|
3
|
+
import { DOM_EVENT } from '../helper/enums'
|
|
2
4
|
import {
|
|
3
5
|
addEventListener,
|
|
4
|
-
addEventListeners
|
|
5
|
-
|
|
6
|
-
values
|
|
7
|
-
} from '../helper/tools'
|
|
8
|
-
import { DOM_EVENT } from '../helper/enums'
|
|
6
|
+
addEventListeners
|
|
7
|
+
} from '../browser/addEventListener'
|
|
9
8
|
export var PageExitReason = {
|
|
10
9
|
HIDDEN: 'visibility_hidden',
|
|
11
10
|
UNLOADING: 'before_unload',
|