@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.
Files changed (97) hide show
  1. package/cjs/browser/addEventListener.js +57 -0
  2. package/cjs/browser/pageExitObservable.js +4 -2
  3. package/cjs/browser/runOnReadyState.js +21 -0
  4. package/cjs/browser/xhrObservable.js +7 -5
  5. package/cjs/configuration/configuration.js +5 -3
  6. package/cjs/console/consoleObservable.js +3 -1
  7. package/cjs/dataMap.js +1 -0
  8. package/cjs/helper/byteUtils.js +26 -0
  9. package/cjs/helper/contextHistory.js +4 -2
  10. package/cjs/helper/createEventRateLimiter.js +3 -1
  11. package/cjs/helper/errorTools.js +4 -2
  12. package/cjs/helper/instrumentMethod.js +2 -4
  13. package/cjs/helper/serialisation/contextManager.js +84 -0
  14. package/cjs/helper/serialisation/heavyCustomerDataWarning.js +34 -0
  15. package/cjs/helper/serialisation/jsonStringify.js +57 -0
  16. package/cjs/helper/serialisation/rowData.js +50 -0
  17. package/cjs/helper/timer.js +29 -0
  18. package/cjs/helper/tools.js +10 -331
  19. package/cjs/index.js +117 -0
  20. package/cjs/init.js +6 -6
  21. package/cjs/report/reportObservable.js +4 -2
  22. package/cjs/session/sessionCookieStore.js +3 -1
  23. package/cjs/session/sessionManagement.js +10 -5
  24. package/cjs/session/sessionStore.js +10 -4
  25. package/cjs/transport/batch.js +40 -91
  26. package/cjs/transport/flushController.js +121 -0
  27. package/cjs/transport/httpRequest.js +6 -2
  28. package/cjs/transport/index.js +9 -1
  29. package/cjs/transport/sendWithRetryStrategy.js +8 -4
  30. package/cjs/transport/startBatchWithReplica.js +10 -2
  31. package/cjs/user/index.js +18 -0
  32. package/cjs/user/user.js +42 -0
  33. package/esm/browser/addEventListener.js +46 -0
  34. package/esm/browser/pageExitObservable.js +2 -1
  35. package/esm/browser/runOnReadyState.js +12 -0
  36. package/esm/browser/xhrObservable.js +6 -5
  37. package/esm/configuration/configuration.js +2 -1
  38. package/esm/console/consoleObservable.js +2 -1
  39. package/esm/dataMap.js +1 -0
  40. package/esm/helper/byteUtils.js +16 -0
  41. package/esm/helper/contextHistory.js +1 -0
  42. package/esm/helper/createEventRateLimiter.js +1 -0
  43. package/esm/helper/errorTools.js +2 -1
  44. package/esm/helper/instrumentMethod.js +1 -3
  45. package/esm/helper/serialisation/contextManager.js +70 -0
  46. package/esm/helper/serialisation/heavyCustomerDataWarning.js +20 -0
  47. package/esm/helper/serialisation/jsonStringify.js +46 -0
  48. package/esm/helper/serialisation/rowData.js +33 -0
  49. package/esm/helper/timer.js +14 -0
  50. package/esm/helper/tools.js +1 -292
  51. package/esm/index.js +10 -1
  52. package/esm/init.js +6 -6
  53. package/esm/report/reportObservable.js +3 -2
  54. package/esm/session/sessionCookieStore.js +1 -0
  55. package/esm/session/sessionManagement.js +5 -2
  56. package/esm/session/sessionStore.js +7 -2
  57. package/esm/transport/batch.js +31 -85
  58. package/esm/transport/flushController.js +114 -0
  59. package/esm/transport/httpRequest.js +5 -2
  60. package/esm/transport/index.js +2 -1
  61. package/esm/transport/sendWithRetryStrategy.js +3 -1
  62. package/esm/transport/startBatchWithReplica.js +9 -2
  63. package/esm/user/index.js +1 -0
  64. package/esm/user/user.js +32 -0
  65. package/package.json +22 -22
  66. package/src/browser/addEventListener.js +50 -0
  67. package/src/browser/pageExitObservable.js +4 -5
  68. package/src/browser/runOnReadyState.js +16 -0
  69. package/src/browser/xhrObservable.js +57 -32
  70. package/src/configuration/configuration.js +1 -1
  71. package/src/console/consoleObservable.js +22 -12
  72. package/src/dataMap.js +1 -0
  73. package/src/helper/byteUtils.js +17 -0
  74. package/src/helper/contextHistory.js +1 -1
  75. package/src/helper/createEventRateLimiter.js +7 -9
  76. package/src/helper/errorTools.js +2 -1
  77. package/src/helper/instrumentMethod.js +1 -2
  78. package/src/helper/serialisation/contextManager.js +79 -0
  79. package/src/helper/serialisation/heavyCustomerDataWarning.js +28 -0
  80. package/src/helper/serialisation/jsonStringify.js +47 -0
  81. package/src/helper/serialisation/rowData.js +41 -0
  82. package/src/helper/timer.js +21 -0
  83. package/src/helper/tools.js +2 -301
  84. package/src/index.js +11 -0
  85. package/src/init.js +6 -6
  86. package/src/report/reportObservable.js +40 -25
  87. package/src/session/sessionCookieStore.js +24 -14
  88. package/src/session/sessionManagement.js +34 -17
  89. package/src/session/sessionStore.js +7 -2
  90. package/src/transport/batch.js +39 -91
  91. package/src/transport/flushController.js +115 -0
  92. package/src/transport/httpRequest.js +13 -6
  93. package/src/transport/index.js +1 -0
  94. package/src/transport/sendWithRetryStrategy.js +3 -7
  95. package/src/transport/startBatchWithReplica.js +11 -7
  96. package/src/user/index.js +1 -0
  97. package/src/user/user.js +31 -0
@@ -8,6 +8,8 @@ exports.stopSessionManager = stopSessionManager;
8
8
 
9
9
  var _tools = require("../helper/tools");
10
10
 
11
+ var _addEventListener2 = require("../browser/addEventListener");
12
+
11
13
  var _contextHistory = require("../helper/contextHistory");
12
14
 
13
15
  var _sessionStore = require("./sessionStore");
@@ -16,6 +18,8 @@ var _sessionConstants = require("./sessionConstants");
16
18
 
17
19
  var _enums = require("../helper/enums");
18
20
 
21
+ var _timer = require("../helper/timer");
22
+
19
23
  var VISIBILITY_CHECK_DELAY = _tools.ONE_MINUTE;
20
24
  exports.VISIBILITY_CHECK_DELAY = VISIBILITY_CHECK_DELAY;
21
25
  var SESSION_CONTEXT_TIMEOUT_DELAY = _sessionConstants.SESSION_TIME_OUT_DELAY;
@@ -57,7 +61,8 @@ var startSessionManager = function startSessionManager(options, productKey, comp
57
61
  return sessionContextHistory.find(startTime);
58
62
  },
59
63
  renewObservable: sessionStore.renewObservable,
60
- expireObservable: sessionStore.expireObservable
64
+ expireObservable: sessionStore.expireObservable,
65
+ expire: sessionStore.expire
61
66
  };
62
67
  };
63
68
 
@@ -71,7 +76,7 @@ function stopSessionManager() {
71
76
  }
72
77
 
73
78
  function trackActivity(expandOrRenewSession) {
74
- var _addEventListeners = (0, _tools.addEventListeners)(window, [_enums.DOM_EVENT.CLICK, _enums.DOM_EVENT.TOUCH_START, _enums.DOM_EVENT.KEY_DOWN, _enums.DOM_EVENT.SCROLL], expandOrRenewSession, {
79
+ var _addEventListeners = (0, _addEventListener2.addEventListeners)(window, [_enums.DOM_EVENT.CLICK, _enums.DOM_EVENT.TOUCH_START, _enums.DOM_EVENT.KEY_DOWN, _enums.DOM_EVENT.SCROLL], expandOrRenewSession, {
75
80
  capture: true,
76
81
  passive: true
77
82
  });
@@ -86,11 +91,11 @@ function trackVisibility(expandSession) {
86
91
  }
87
92
  };
88
93
 
89
- var _addEventListener = (0, _tools.addEventListener)(document, _enums.DOM_EVENT.VISIBILITY_CHANGE, expandSessionWhenVisible);
94
+ var _addEventListener = (0, _addEventListener2.addEventListener)(document, _enums.DOM_EVENT.VISIBILITY_CHANGE, expandSessionWhenVisible);
90
95
 
91
96
  stopCallbacks.push(_addEventListener.stop);
92
- var visibilityCheckInterval = setInterval(expandSessionWhenVisible, VISIBILITY_CHECK_DELAY);
97
+ var visibilityCheckInterval = (0, _timer.setInterval)(expandSessionWhenVisible, VISIBILITY_CHECK_DELAY);
93
98
  stopCallbacks.push(function () {
94
- clearInterval(visibilityCheckInterval);
99
+ (0, _timer.clearInterval)(visibilityCheckInterval);
95
100
  });
96
101
  }
@@ -15,6 +15,8 @@ var _sessionConstants = require("./sessionConstants");
15
15
 
16
16
  var _sessionCookieStore = require("./sessionCookieStore");
17
17
 
18
+ var _timer = require("../helper/timer");
19
+
18
20
  /**
19
21
  * Different session concepts:
20
22
  * - tracked, the session has an id and is updated along the user navigation
@@ -24,7 +26,7 @@ var _sessionCookieStore = require("./sessionCookieStore");
24
26
  function startSessionStore(options, productKey, computeSessionState) {
25
27
  var renewObservable = new _observable.Observable();
26
28
  var expireObservable = new _observable.Observable();
27
- var watchSessionTimeoutId = setInterval(watchSession, _cookie.COOKIE_ACCESS_DELAY);
29
+ var watchSessionTimeoutId = (0, _timer.setInterval)(watchSession, _cookie.COOKIE_ACCESS_DELAY);
28
30
  var sessionCache = retrieveActiveSession();
29
31
 
30
32
  function expandOrRenewSession() {
@@ -78,7 +80,7 @@ function startSessionStore(options, productKey, computeSessionState) {
78
80
 
79
81
  if (hasSessionInCache()) {
80
82
  if (isSessionInCacheOutdated(cookieSession)) {
81
- expireSession();
83
+ expireSessionInCache();
82
84
  } else {
83
85
  sessionCache = cookieSession;
84
86
  }
@@ -109,7 +111,7 @@ function startSessionStore(options, productKey, computeSessionState) {
109
111
  return sessionCache.id !== cookieSession.id || sessionCache[productKey] !== cookieSession[productKey];
110
112
  }
111
113
 
112
- function expireSession() {
114
+ function expireSessionInCache() {
113
115
  sessionCache = {};
114
116
  expireObservable.notify();
115
117
  }
@@ -143,8 +145,12 @@ function startSessionStore(options, productKey, computeSessionState) {
143
145
  },
144
146
  renewObservable: renewObservable,
145
147
  expireObservable: expireObservable,
148
+ expire: function expire() {
149
+ deleteSessionCookie(options);
150
+ synchronizeSession({});
151
+ },
146
152
  stop: function stop() {
147
- clearInterval(watchSessionTimeoutId);
153
+ (0, _timer.clearInterval)(watchSessionTimeoutId);
148
154
  }
149
155
  };
150
156
  }
@@ -9,10 +9,16 @@ var _display = require("../helper/display");
9
9
 
10
10
  var _tools = require("../helper/tools");
11
11
 
12
+ var _rowData = require("../helper/serialisation/rowData");
13
+
12
14
  var _dataMap = require("../dataMap");
13
15
 
14
16
  var _enums = require("../helper/enums");
15
17
 
18
+ var _byteUtils = require("../helper/byteUtils");
19
+
20
+ var _pageExitObservable = require("../browser/pageExitObservable");
21
+
16
22
  // https://en.wikipedia.org/wiki/UTF-8
17
23
  // eslint-disable-next-line no-control-regex
18
24
  var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/;
@@ -43,8 +49,8 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
43
49
  filterFileds.push(_key);
44
50
 
45
51
  if (_value || (0, _tools.isNumber)(_value)) {
46
- rowData.tags[_key] = (0, _tools.escapeJsonValue)(_value);
47
- tagsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowData)(_value));
52
+ rowData.tags[_key] = (0, _rowData.escapeJsonValue)(_value);
53
+ tagsStr.push((0, _rowData.escapeRowData)(_key) + '=' + (0, _rowData.escapeRowData)(_value));
48
54
  }
49
55
  });
50
56
  var fieldsStr = [];
@@ -67,7 +73,7 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
67
73
  // '"'
68
74
  // : escapeRowData(_valueData)
69
75
 
70
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_valueData));
76
+ fieldsStr.push((0, _rowData.escapeRowData)(_key) + '=' + (0, _rowData.escapeRowField)(_valueData));
71
77
  }
72
78
  } else if ((0, _tools.isString)(_value)) {
73
79
  var _valueData = (0, _tools.findByPath)(message, _value);
@@ -77,7 +83,7 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
77
83
  if (_valueData || (0, _tools.isNumber)(_valueData)) {
78
84
  rowData.fields[_key] = _valueData; // 这里不需要转译
79
85
 
80
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_valueData));
86
+ fieldsStr.push((0, _rowData.escapeRowData)(_key) + '=' + (0, _rowData.escapeRowField)(_valueData));
81
87
  }
82
88
  }
83
89
  });
@@ -95,13 +101,13 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
95
101
 
96
102
  rowData.fields[_key] = _value; // 这里不需要转译
97
103
 
98
- fieldsStr.push((0, _tools.escapeRowData)(_key) + '=' + (0, _tools.escapeRowField)(_value));
104
+ fieldsStr.push((0, _rowData.escapeRowData)(_key) + '=' + (0, _rowData.escapeRowField)(_value));
99
105
  }
100
106
  });
101
107
 
102
108
  if (_tagKeys.length) {
103
- rowData.fields[CUSTOM_KEYS] = (0, _tools.escapeRowField)(_tagKeys);
104
- fieldsStr.push((0, _tools.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _tools.escapeRowField)(_tagKeys));
109
+ rowData.fields[CUSTOM_KEYS] = (0, _rowData.escapeRowField)(_tagKeys);
110
+ fieldsStr.push((0, _rowData.escapeRowData)(CUSTOM_KEYS) + '=' + (0, _rowData.escapeRowField)(_tagKeys));
105
111
  }
106
112
  }
107
113
 
@@ -111,7 +117,7 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
111
117
  if (filterFileds.indexOf(key) === -1 && ((0, _tools.isNumber)(value) || (0, _tools.isString)(value) || (0, _tools.isBoolean)(value))) {
112
118
  rowData.fields[key] = value; // 这里不需要转译
113
119
 
114
- fieldsStr.push((0, _tools.escapeRowData)(key) + '=' + (0, _tools.escapeRowField)(value));
120
+ fieldsStr.push((0, _rowData.escapeRowData)(key) + '=' + (0, _rowData.escapeRowField)(value));
115
121
  }
116
122
  });
117
123
  }
@@ -138,23 +144,18 @@ var processedMessageByDataMap = function processedMessageByDataMap(message) {
138
144
 
139
145
  exports.processedMessageByDataMap = processedMessageByDataMap;
140
146
 
141
- var batch = function batch(request, batchMessagesLimit, batchBytesLimit, messageBytesLimit, flushTimeout, pageExitObservable) {
147
+ var batch = function batch(request, flushController, messageBytesLimit) {
142
148
  this.pushOnlyBuffer = [];
143
149
  this.upsertBuffer = {};
144
- this.bufferBytesCount = 0;
145
- this.bufferMessagesCount = 0;
146
150
  this.request = request;
147
- this.batchMessagesLimit = batchMessagesLimit;
148
- this.batchBytesLimit = batchBytesLimit;
151
+ this.flushController = flushController;
149
152
  this.messageBytesLimit = messageBytesLimit;
150
- this.flushTimeout = flushTimeout;
151
153
 
152
154
  var _this = this;
153
155
 
154
- pageExitObservable.subscribe(function () {
155
- _this.flush(_this.request.sendOnExit);
156
+ this.flushController.flushObservable.subscribe(function (event) {
157
+ _this.flush(event);
156
158
  });
157
- this.flushPeriodically();
158
159
  };
159
160
 
160
161
  batch.prototype.add = function (message) {
@@ -165,45 +166,26 @@ batch.prototype.upsert = function (message, key) {
165
166
  this.addOrUpdate(message, key);
166
167
  };
167
168
 
168
- batch.prototype.flush = function (sendFn) {
169
- if (typeof sendFn !== 'function') {
170
- sendFn = this.request.send;
171
- }
169
+ batch.prototype.flush = function (event) {
170
+ var messages = this.pushOnlyBuffer.concat((0, _tools.values)(this.upsertBuffer));
171
+ this.pushOnlyBuffer = [];
172
+ this.upsertBuffer = {};
172
173
 
173
- if (this.bufferMessagesCount !== 0) {
174
- var messages = this.pushOnlyBuffer.concat((0, _tools.values)(this.upsertBuffer));
175
- var bytesCount = this.bufferBytesCount;
176
- this.pushOnlyBuffer = [];
177
- this.upsertBuffer = {};
178
- this.bufferBytesCount = 0;
179
- this.bufferMessagesCount = 0;
180
-
181
- if (messages.length > 0) {
182
- sendFn({
183
- data: messages.join('\n'),
184
- bytesCount: bytesCount
185
- });
174
+ if (messages.length > 0) {
175
+ var payload = {
176
+ data: messages.join('\n'),
177
+ bytesCount: event.bytesCount,
178
+ flushReason: event.reason
179
+ };
180
+
181
+ if ((0, _pageExitObservable.isPageExitReason)(event.reason)) {
182
+ this.request.sendOnExit(payload);
183
+ } else {
184
+ this.request.send(payload);
186
185
  }
187
186
  }
188
187
  };
189
188
 
190
- batch.prototype.flushOnExit = function () {
191
- this.flush(this.request.sendOnExit);
192
- };
193
-
194
- batch.prototype.computeBytesCount = function (candidate) {
195
- // Accurate bytes count computations can degrade performances when there is a lot of events to process
196
- if (!HAS_MULTI_BYTES_CHARACTERS.test(candidate)) {
197
- return candidate.length;
198
- }
199
-
200
- if (window.TextEncoder !== undefined) {
201
- return new TextEncoder().encode(candidate).length;
202
- }
203
-
204
- return new Blob([candidate]).size;
205
- };
206
-
207
189
  batch.prototype.addOrUpdate = function (message, key) {
208
190
  var _process = this.process(message);
209
191
 
@@ -220,20 +202,12 @@ batch.prototype.addOrUpdate = function (message, key) {
220
202
  this.remove(key);
221
203
  }
222
204
 
223
- if (this.willReachedBytesLimitWith(messageBytesCount)) {
224
- this.flush();
225
- }
226
-
227
205
  this.push(processedMessage, messageBytesCount, key);
228
-
229
- if (this.isFull()) {
230
- this.flush();
231
- }
232
206
  };
233
207
 
234
208
  batch.prototype.process = function (message) {
235
209
  var processedMessage = processedMessageByDataMap(message).rowStr;
236
- var messageBytesCount = this.computeBytesCount(processedMessage);
210
+ var messageBytesCount = (0, _byteUtils.computeBytesCount)(processedMessage);
237
211
  return {
238
212
  processedMessage: processedMessage,
239
213
  messageBytesCount: messageBytesCount
@@ -241,10 +215,8 @@ batch.prototype.process = function (message) {
241
215
  };
242
216
 
243
217
  batch.prototype.push = function (processedMessage, messageBytesCount, key) {
244
- if (this.bufferMessagesCount > 0) {
245
- // \n separator at serialization
246
- this.bufferBytesCount += 1;
247
- }
218
+ var separatorBytesCount = this.flushController.getMessagesCount() > 0 ? 1 : 0;
219
+ this.flushController.notifyBeforeAddMessage(messageBytesCount + separatorBytesCount);
248
220
 
249
221
  if (key !== undefined) {
250
222
  this.upsertBuffer[key] = processedMessage;
@@ -252,44 +224,21 @@ batch.prototype.push = function (processedMessage, messageBytesCount, key) {
252
224
  this.pushOnlyBuffer.push(processedMessage);
253
225
  }
254
226
 
255
- this.bufferBytesCount += messageBytesCount;
256
- this.bufferMessagesCount += 1;
227
+ this.flushController.notifyAfterAddMessage();
257
228
  };
258
229
 
259
230
  batch.prototype.remove = function (key) {
260
231
  var removedMessage = this.upsertBuffer[key];
261
232
  delete this.upsertBuffer[key];
262
- var messageBytesCount = this.computeBytesCount(removedMessage);
263
- this.bufferBytesCount -= messageBytesCount;
264
- this.bufferMessagesCount -= 1;
233
+ var messageBytesCount = (0, _byteUtils.computeBytesCount)(removedMessage); // If there are other messages, a '\n' will be added at serialization
265
234
 
266
- if (this.bufferMessagesCount > 0) {
267
- this.bufferBytesCount -= 1;
268
- }
235
+ var separatorBytesCount = this.flushController.getMessagesCount() > 1 ? 1 : 0;
236
+ this.flushController.notifyAfterRemoveMessage(messageBytesCount + separatorBytesCount);
269
237
  };
270
238
 
271
239
  batch.prototype.hasMessageFor = function (key) {
272
240
  return key !== undefined && this.upsertBuffer[key] !== undefined;
273
241
  };
274
242
 
275
- batch.prototype.willReachedBytesLimitWith = function (messageBytesCount) {
276
- // byte of the separator at the end of the message
277
- return this.bufferBytesCount + messageBytesCount + 1 >= this.batchBytesLimit;
278
- };
279
-
280
- batch.prototype.isFull = function () {
281
- return this.bufferMessagesCount === this.batchMessagesLimit || this.bufferBytesCount >= this.batchBytesLimit;
282
- };
283
-
284
- batch.prototype.flushPeriodically = function () {
285
- var _this = this;
286
-
287
- setTimeout(function () {
288
- _this.flush();
289
-
290
- _this.flushPeriodically();
291
- }, this.flushTimeout);
292
- };
293
-
294
243
  var Batch = batch;
295
244
  exports.Batch = Batch;
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createFlushController = createFlushController;
7
+
8
+ var _observable = require("../helper/observable");
9
+
10
+ var _timer = require("../helper/timer");
11
+
12
+ // type FlushReason = PageExitReason | 'duration_limit' | 'bytes_limit' | 'messages_limit' | 'session_expire'
13
+
14
+ /**
15
+ * Returns a "flush controller", responsible of notifying when flushing a pool of pending data needs
16
+ * to happen. The implementation is designed to support both synchronous and asynchronous usages,
17
+ * but relies on invariants described in each method documentation to keep a coherent state.
18
+ */
19
+ function createFlushController(_ref) {
20
+ var messagesLimit = _ref.messagesLimit,
21
+ bytesLimit = _ref.bytesLimit,
22
+ durationLimit = _ref.durationLimit,
23
+ pageExitObservable = _ref.pageExitObservable,
24
+ sessionExpireObservable = _ref.sessionExpireObservable;
25
+ var flushObservable = new _observable.Observable();
26
+ pageExitObservable.subscribe(function (event) {
27
+ return flush(event.reason);
28
+ });
29
+ sessionExpireObservable.subscribe(function () {
30
+ return flush('session_expire');
31
+ });
32
+ var currentBytesCount = 0;
33
+ var currentMessagesCount = 0;
34
+
35
+ function flush(flushReason) {
36
+ if (currentMessagesCount === 0) {
37
+ return;
38
+ }
39
+
40
+ var messagesCount = currentMessagesCount;
41
+ var bytesCount = currentBytesCount;
42
+ currentMessagesCount = 0;
43
+ currentBytesCount = 0;
44
+ cancelDurationLimitTimeout();
45
+ flushObservable.notify({
46
+ reason: flushReason,
47
+ messagesCount: messagesCount,
48
+ bytesCount: bytesCount
49
+ });
50
+ }
51
+
52
+ var durationLimitTimeoutId;
53
+
54
+ function scheduleDurationLimitTimeout() {
55
+ if (durationLimitTimeoutId === undefined) {
56
+ durationLimitTimeoutId = (0, _timer.setTimeout)(function () {
57
+ flush('duration_limit');
58
+ }, durationLimit);
59
+ }
60
+ }
61
+
62
+ function cancelDurationLimitTimeout() {
63
+ (0, _timer.clearTimeout)(durationLimitTimeoutId);
64
+ durationLimitTimeoutId = undefined;
65
+ }
66
+
67
+ return {
68
+ flushObservable: flushObservable,
69
+ getMessagesCount: function getMessagesCount() {
70
+ return currentMessagesCount;
71
+ },
72
+
73
+ /**
74
+ * Notifies that a message will be added to a pool of pending messages waiting to be flushed.
75
+ *
76
+ * This function needs to be called synchronously, right before adding the message, so no flush
77
+ * event can happen after `notifyBeforeAddMessage` and before adding the message.
78
+ */
79
+ notifyBeforeAddMessage: function notifyBeforeAddMessage(messageBytesCount) {
80
+ if (currentBytesCount + messageBytesCount >= bytesLimit) {
81
+ flush('bytes_limit');
82
+ } // Consider the message to be added now rather than in `notifyAfterAddMessage`, because if no
83
+ // message was added yet and `notifyAfterAddMessage` is called asynchronously, we still want
84
+ // to notify when a flush is needed (for example on page exit).
85
+
86
+
87
+ currentMessagesCount += 1;
88
+ currentBytesCount += messageBytesCount;
89
+ scheduleDurationLimitTimeout();
90
+ },
91
+
92
+ /**
93
+ * Notifies that a message *was* added to a pool of pending messages waiting to be flushed.
94
+ *
95
+ * This function can be called asynchronously after the message was added, but in this case it
96
+ * should not be called if a flush event occurred in between.
97
+ */
98
+ notifyAfterAddMessage: function notifyAfterAddMessage() {
99
+ if (currentMessagesCount >= messagesLimit) {
100
+ flush('messages_limit');
101
+ } else if (currentBytesCount >= bytesLimit) {
102
+ flush('bytes_limit');
103
+ }
104
+ },
105
+
106
+ /**
107
+ * Notifies that a message was removed from a pool of pending messages waiting to be flushed.
108
+ *
109
+ * This function needs to be called synchronously, right after removing the message, so no flush
110
+ * event can happen after removing the message and before `notifyAfterRemoveMessage`.
111
+ */
112
+ notifyAfterRemoveMessage: function notifyAfterRemoveMessage(messageBytesCount) {
113
+ currentBytesCount -= messageBytesCount;
114
+ currentMessagesCount -= 1;
115
+
116
+ if (currentMessagesCount === 0) {
117
+ cancelDurationLimitTimeout();
118
+ }
119
+ }
120
+ };
121
+ }
@@ -8,6 +8,8 @@ exports.fetchKeepAliveStrategy = fetchKeepAliveStrategy;
8
8
 
9
9
  var _sendWithRetryStrategy = require("./sendWithRetryStrategy");
10
10
 
11
+ var _addEventListener = require("../browser/addEventListener");
12
+
11
13
  /**
12
14
  * Use POST request without content type to:
13
15
  * - avoid CORS preflight requests
@@ -103,12 +105,14 @@ function isKeepAliveSupported() {
103
105
  function sendXHR(url, data, onResponse) {
104
106
  var request = new XMLHttpRequest();
105
107
  request.open('POST', url, true);
106
- request.send(data);
107
- request.addEventListener('loadend', function () {
108
+ (0, _addEventListener.addEventListener)(request, 'loadend', function () {
108
109
  if (typeof onResponse === 'function') {
109
110
  onResponse({
110
111
  status: request.status
111
112
  });
112
113
  }
114
+ }, {
115
+ once: true
113
116
  });
117
+ request.send(data);
114
118
  }
@@ -9,6 +9,12 @@ Object.defineProperty(exports, "Batch", {
9
9
  return _batch.Batch;
10
10
  }
11
11
  });
12
+ Object.defineProperty(exports, "createFlushController", {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _flushController.createFlushController;
16
+ }
17
+ });
12
18
  Object.defineProperty(exports, "createHttpRequest", {
13
19
  enumerable: true,
14
20
  get: function get() {
@@ -26,4 +32,6 @@ var _httpRequest = require("./httpRequest");
26
32
 
27
33
  var _batch = require("./batch");
28
34
 
29
- var _startBatchWithReplica = require("./startBatchWithReplica");
35
+ var _startBatchWithReplica = require("./startBatchWithReplica");
36
+
37
+ var _flushController = require("./flushController");
@@ -9,13 +9,17 @@ exports.sendWithRetryStrategy = sendWithRetryStrategy;
9
9
 
10
10
  var _tools = require("../helper/tools");
11
11
 
12
+ var _byteUtils = require("../helper/byteUtils");
13
+
12
14
  var _errorTools = require("../helper/errorTools");
13
15
 
14
- var MAX_ONGOING_BYTES_COUNT = 80 * _tools.ONE_KIBI_BYTE;
16
+ var _timer = require("../helper/timer");
17
+
18
+ var MAX_ONGOING_BYTES_COUNT = 80 * _byteUtils.ONE_KIBI_BYTE;
15
19
  exports.MAX_ONGOING_BYTES_COUNT = MAX_ONGOING_BYTES_COUNT;
16
20
  var MAX_ONGOING_REQUESTS = 32;
17
21
  exports.MAX_ONGOING_REQUESTS = MAX_ONGOING_REQUESTS;
18
- var MAX_QUEUE_BYTES_COUNT = 3 * _tools.ONE_MEBI_BYTE;
22
+ var MAX_QUEUE_BYTES_COUNT = 3 * _byteUtils.ONE_MEBI_BYTE;
19
23
  exports.MAX_QUEUE_BYTES_COUNT = MAX_QUEUE_BYTES_COUNT;
20
24
  var MAX_BACKOFF_TIME = 256 * _tools.ONE_SECOND;
21
25
  exports.MAX_BACKOFF_TIME = MAX_BACKOFF_TIME;
@@ -52,7 +56,7 @@ function scheduleRetry(state, sendStrategy, reportError) {
52
56
  return;
53
57
  }
54
58
 
55
- setTimeout(function () {
59
+ (0, _timer.setTimeout)(function () {
56
60
  var payload = state.queuedPayloads.first();
57
61
  send(payload, state, sendStrategy, {
58
62
  onSuccess: function onSuccess() {
@@ -95,7 +99,7 @@ function send(payload, state, sendStrategy, responseData) {
95
99
  function retryQueuedPayloads(reason, state, sendStrategy, reportError) {
96
100
  if (reason === RetryReason.AFTER_SUCCESS && state.queuedPayloads.isFull() && !state.queueFullReported) {
97
101
  reportError({
98
- message: 'Reached max events size queued for upload: ' + MAX_QUEUE_BYTES_COUNT / _tools.ONE_MEBI_BYTE + 'MiB',
102
+ message: 'Reached max events size queued for upload: ' + MAX_QUEUE_BYTES_COUNT / _byteUtils.ONE_MEBI_BYTE + 'MiB',
99
103
  source: _errorTools.ErrorSource.AGENT,
100
104
  startClocks: (0, _tools.clocksNow)()
101
105
  });
@@ -9,11 +9,19 @@ var _batch = require("./batch");
9
9
 
10
10
  var _httpRequest = require("./httpRequest");
11
11
 
12
- function startBatchWithReplica(configuration, endpointUrl, reportError, pageExitObservable) {
12
+ var _flushController = require("./flushController");
13
+
14
+ function startBatchWithReplica(configuration, endpointUrl, reportError, pageExitObservable, sessionExpireObservable) {
13
15
  var primaryBatch = createBatch(endpointUrl);
14
16
 
15
17
  function createBatch(endpointUrl) {
16
- return new _batch.Batch((0, _httpRequest.createHttpRequest)(endpointUrl, configuration.batchBytesLimit, reportError), configuration.batchMessagesLimit, configuration.batchBytesLimit, configuration.messageBytesLimit, configuration.flushTimeout, pageExitObservable);
18
+ return new _batch.Batch((0, _httpRequest.createHttpRequest)(endpointUrl, configuration.batchBytesLimit, reportError), (0, _flushController.createFlushController)({
19
+ messagesLimit: configuration.batchMessagesLimit,
20
+ bytesLimit: configuration.batchBytesLimit,
21
+ durationLimit: configuration.flushTimeout,
22
+ pageExitObservable: pageExitObservable,
23
+ sessionExpireObservable: sessionExpireObservable
24
+ }), configuration.messageBytesLimit);
17
25
  }
18
26
 
19
27
  return {
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _user = require("./user");
8
+
9
+ Object.keys(_user).forEach(function (key) {
10
+ if (key === "default" || key === "__esModule") return;
11
+ if (key in exports && exports[key] === _user[key]) return;
12
+ Object.defineProperty(exports, key, {
13
+ enumerable: true,
14
+ get: function get() {
15
+ return _user[key];
16
+ }
17
+ });
18
+ });
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.checkUser = checkUser;
7
+ exports.sanitizeUser = sanitizeUser;
8
+
9
+ var _display = require("../helper/display");
10
+
11
+ var _tools = require("../helper/tools");
12
+
13
+ /**
14
+ * Clone input data and ensure known user properties (id, name, email)
15
+ * are strings, as defined here:
16
+ * https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#user-related-attributes
17
+ */
18
+ function sanitizeUser(newUser) {
19
+ // We shallow clone only to prevent mutation of user data.
20
+ var user = (0, _tools.assign)({}, newUser);
21
+ var keys = ['id', 'name', 'email'];
22
+ (0, _tools.each)(keys, function (key) {
23
+ if (key in user) {
24
+ user[key] = String(user[key]);
25
+ }
26
+ });
27
+ return user;
28
+ }
29
+ /**
30
+ * Simple check to ensure user is valid
31
+ */
32
+
33
+
34
+ function checkUser(newUser) {
35
+ var isValid = (0, _tools.getType)(newUser) === 'object';
36
+
37
+ if (!isValid) {
38
+ _display.display.error('Unsupported user:', newUser);
39
+ }
40
+
41
+ return isValid;
42
+ }
@@ -0,0 +1,46 @@
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
+ * Add event listeners to an event emitter object (Window, Element, mock object...). This provides
8
+ * a few conveniences compared to using `element.addEventListener` directly:
9
+ *
10
+ * * supports IE11 by:
11
+ * * using an option object only if needed
12
+ * * emulating the `once` option
13
+ *
14
+ * * wraps the listener with a `monitor` function
15
+ *
16
+ * * returns a `stop` function to remove the listener
17
+ *
18
+ * * with `once: true`, the listener will be called at most once, even if different events are
19
+ * listened
20
+ */
21
+
22
+ export function addEventListeners(eventTarget, events, listener, options) {
23
+ var wrappedListener = options && options.once ? function (event) {
24
+ stop();
25
+ listener(event);
26
+ } : listener;
27
+ options = options && options.passive ? {
28
+ capture: options.capture,
29
+ passive: options.passive
30
+ } : options && options.capture;
31
+ var add = getZoneJsOriginalValue(eventTarget, 'addEventListener');
32
+ each(events, function (event) {
33
+ add.call(eventTarget, event, wrappedListener, options);
34
+ });
35
+
36
+ var stop = function stop() {
37
+ var remove = getZoneJsOriginalValue(eventTarget, 'removeEventListener');
38
+ each(events, function (event) {
39
+ remove.call(eventTarget, event, wrappedListener, options);
40
+ });
41
+ };
42
+
43
+ return {
44
+ stop: stop
45
+ };
46
+ }