@statsig/client-core 3.31.0 → 3.31.1-beta.2
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/package.json +1 -1
- package/src/BatchedEventsQueue.d.ts +14 -0
- package/src/BatchedEventsQueue.js +51 -0
- package/src/ClientInterfaces.d.ts +34 -1
- package/src/ClientInterfaces.js +71 -0
- package/src/ErrorBoundary.d.ts +2 -0
- package/src/ErrorBoundary.js +23 -3
- package/src/EventLogger.d.ts +14 -23
- package/src/EventLogger.js +85 -185
- package/src/EventRetryConstants.d.ts +3 -1
- package/src/EventRetryConstants.js +3 -1
- package/src/EventSender.d.ts +23 -0
- package/src/EventSender.js +96 -0
- package/src/FlushCoordinator.d.ts +50 -0
- package/src/FlushCoordinator.js +332 -0
- package/src/FlushInterval.d.ts +13 -0
- package/src/FlushInterval.js +44 -0
- package/src/FlushTypes.d.ts +7 -0
- package/src/FlushTypes.js +12 -0
- package/src/NetworkCore.d.ts +1 -0
- package/src/NetworkCore.js +5 -3
- package/src/PendingEvents.d.ts +10 -0
- package/src/PendingEvents.js +26 -0
- package/src/SessionID.d.ts +1 -1
- package/src/SessionID.js +8 -7
- package/src/StatsigClientBase.js +1 -1
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +1 -1
- package/src/StatsigUser.d.ts +1 -0
- package/src/StatsigUser.js +13 -1
package/src/EventLogger.js
CHANGED
|
@@ -10,22 +10,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.EventLogger = void 0;
|
|
13
|
+
const BatchedEventsQueue_1 = require("./BatchedEventsQueue");
|
|
13
14
|
const CacheKey_1 = require("./CacheKey");
|
|
15
|
+
const EventRetryConstants_1 = require("./EventRetryConstants");
|
|
16
|
+
const FlushCoordinator_1 = require("./FlushCoordinator");
|
|
14
17
|
const Hashing_1 = require("./Hashing");
|
|
15
18
|
const Log_1 = require("./Log");
|
|
16
19
|
const NetworkConfig_1 = require("./NetworkConfig");
|
|
20
|
+
const PendingEvents_1 = require("./PendingEvents");
|
|
17
21
|
const SafeJs_1 = require("./SafeJs");
|
|
18
22
|
const StatsigEvent_1 = require("./StatsigEvent");
|
|
19
23
|
const StatsigOptionsCommon_1 = require("./StatsigOptionsCommon");
|
|
20
24
|
const StorageProvider_1 = require("./StorageProvider");
|
|
21
25
|
const UrlConfiguration_1 = require("./UrlConfiguration");
|
|
22
26
|
const VisibilityObserving_1 = require("./VisibilityObserving");
|
|
23
|
-
const DEFAULT_QUEUE_SIZE = 100;
|
|
24
|
-
const DEFAULT_FLUSH_INTERVAL_MS = 10000;
|
|
25
27
|
const MAX_DEDUPER_KEYS = 1000;
|
|
26
28
|
const DEDUPER_WINDOW_DURATION_MS = 600000;
|
|
27
|
-
const MAX_FAILED_LOGS = 500;
|
|
28
|
-
const QUICK_FLUSH_WINDOW_MS = 200;
|
|
29
29
|
const EVENT_LOGGER_MAP = {};
|
|
30
30
|
class EventLogger {
|
|
31
31
|
static _safeFlushAndForget(sdkKey) {
|
|
@@ -34,21 +34,17 @@ class EventLogger {
|
|
|
34
34
|
// noop
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
var _a;
|
|
39
|
-
(_a = EVENT_LOGGER_MAP[sdkKey]) === null || _a === void 0 ? void 0 : _a._retryFailedLogs();
|
|
40
|
-
}
|
|
41
|
-
constructor(_sdkKey, _emitter, _network, _options) {
|
|
37
|
+
constructor(_sdkKey, _emitter, _network, _options, _errorBoundary) {
|
|
42
38
|
var _a, _b;
|
|
43
39
|
this._sdkKey = _sdkKey;
|
|
44
40
|
this._emitter = _emitter;
|
|
45
41
|
this._network = _network;
|
|
46
42
|
this._options = _options;
|
|
47
|
-
this.
|
|
43
|
+
this._errorBoundary = _errorBoundary;
|
|
48
44
|
this._lastExposureTimeMap = {};
|
|
49
45
|
this._nonExposedChecks = {};
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
46
|
+
this._isShuttingDown = false;
|
|
47
|
+
this._storageKey = null;
|
|
52
48
|
this._loggingEnabled =
|
|
53
49
|
(_a = _options === null || _options === void 0 ? void 0 : _options.loggingEnabled) !== null && _a !== void 0 ? _a : ((_options === null || _options === void 0 ? void 0 : _options.disableLogging) === true
|
|
54
50
|
? StatsigOptionsCommon_1.LoggingEnabledOption.disabled
|
|
@@ -56,34 +52,45 @@ class EventLogger {
|
|
|
56
52
|
if ((_options === null || _options === void 0 ? void 0 : _options.loggingEnabled) && _options.disableLogging !== undefined) {
|
|
57
53
|
Log_1.Log.warn('Detected both loggingEnabled and disableLogging options. loggingEnabled takes precedence - please remove disableLogging.');
|
|
58
54
|
}
|
|
59
|
-
this._maxQueueSize = (_b = _options === null || _options === void 0 ? void 0 : _options.loggingBufferMaxSize) !== null && _b !== void 0 ? _b : DEFAULT_QUEUE_SIZE;
|
|
60
55
|
const config = _options === null || _options === void 0 ? void 0 : _options.networkConfig;
|
|
61
56
|
this._logEventUrlConfig = new UrlConfiguration_1.UrlConfiguration(NetworkConfig_1.Endpoint._rgstr, config === null || config === void 0 ? void 0 : config.logEventUrl, config === null || config === void 0 ? void 0 : config.api, config === null || config === void 0 ? void 0 : config.logEventFallbackUrls);
|
|
57
|
+
const batchSize = (_b = _options === null || _options === void 0 ? void 0 : _options.loggingBufferMaxSize) !== null && _b !== void 0 ? _b : EventRetryConstants_1.EventRetryConstants.DEFAULT_BATCH_SIZE;
|
|
58
|
+
this._pendingEvents = new PendingEvents_1.PendingEvents(batchSize);
|
|
59
|
+
this._batchQueue = new BatchedEventsQueue_1.BatchQueue(batchSize);
|
|
60
|
+
this._flushCoordinator = new FlushCoordinator_1.FlushCoordinator(this._batchQueue, this._pendingEvents, () => this.appendAndResetNonExposedChecks(), this._sdkKey, this._network, this._emitter, this._logEventUrlConfig, this._options, this._loggingEnabled, this._errorBoundary);
|
|
62
61
|
}
|
|
63
62
|
setLogEventCompressionMode(mode) {
|
|
64
|
-
this.
|
|
63
|
+
this._flushCoordinator.setLogEventCompressionMode(mode);
|
|
65
64
|
}
|
|
66
65
|
setLoggingEnabled(loggingEnabled) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
const wasDisabled = this._loggingEnabled === 'disabled';
|
|
67
|
+
const isNowEnabled = loggingEnabled !== 'disabled';
|
|
68
|
+
this._loggingEnabled = loggingEnabled;
|
|
69
|
+
this._flushCoordinator.setLoggingEnabled(loggingEnabled);
|
|
70
|
+
if (wasDisabled && isNowEnabled) {
|
|
71
|
+
const events = this._loadStoredEvents();
|
|
72
|
+
Log_1.Log.debug(`Loaded ${events.length} stored event(s) from storage`);
|
|
73
|
+
if (events.length > 0) {
|
|
74
|
+
events.forEach((event) => {
|
|
75
|
+
this._flushCoordinator.addEvent(event);
|
|
76
|
+
});
|
|
77
|
+
this.flush().catch((error) => {
|
|
78
|
+
Log_1.Log.warn('Failed to flush events after enabling logging:', error);
|
|
79
|
+
});
|
|
73
80
|
}
|
|
74
|
-
StorageProvider_1.Storage.removeItem(storageKey);
|
|
75
81
|
}
|
|
76
|
-
this._loggingEnabled = loggingEnabled;
|
|
77
82
|
}
|
|
78
83
|
enqueue(event) {
|
|
79
84
|
if (!this._shouldLogEvent(event)) {
|
|
80
85
|
return;
|
|
81
86
|
}
|
|
82
|
-
this.
|
|
83
|
-
this.
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
const normalizedEvent = this._normalizeEvent(event);
|
|
88
|
+
if (this._loggingEnabled === 'disabled') {
|
|
89
|
+
this._storeEventToStorage(normalizedEvent);
|
|
90
|
+
return;
|
|
86
91
|
}
|
|
92
|
+
this._flushCoordinator.addEvent(normalizedEvent);
|
|
93
|
+
this._flushCoordinator.checkQuickFlush();
|
|
87
94
|
}
|
|
88
95
|
incrementNonExposureCount(name) {
|
|
89
96
|
var _a;
|
|
@@ -110,47 +117,41 @@ class EventLogger {
|
|
|
110
117
|
EventLogger._safeFlushAndForget(this._sdkKey);
|
|
111
118
|
}
|
|
112
119
|
else if (visibility === 'foreground') {
|
|
113
|
-
|
|
120
|
+
this._flushCoordinator.startScheduledFlushCycle();
|
|
114
121
|
}
|
|
115
122
|
});
|
|
116
123
|
}
|
|
117
|
-
this.
|
|
118
|
-
|
|
124
|
+
this._flushCoordinator.loadAndRetryShutdownFailedEvents().catch((error) => {
|
|
125
|
+
Log_1.Log.warn('Failed to load failed shutdown events:', error);
|
|
126
|
+
});
|
|
127
|
+
this._flushCoordinator.startScheduledFlushCycle();
|
|
119
128
|
}
|
|
120
129
|
stop() {
|
|
121
130
|
return __awaiter(this, void 0, void 0, function* () {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
this._flushIntervalId = null;
|
|
125
|
-
}
|
|
131
|
+
this._isShuttingDown = true;
|
|
132
|
+
yield this._flushCoordinator.processShutdown();
|
|
126
133
|
delete EVENT_LOGGER_MAP[this._sdkKey];
|
|
127
|
-
yield this.flush();
|
|
128
134
|
});
|
|
129
135
|
}
|
|
130
136
|
flush() {
|
|
131
137
|
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
-
this.
|
|
133
|
-
if (this._queue.length === 0) {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
const events = this._queue;
|
|
137
|
-
this._queue = [];
|
|
138
|
-
yield this._sendEvents(events);
|
|
138
|
+
return this._flushCoordinator.processManualFlush();
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
* within the quick flush window
|
|
144
|
-
*/
|
|
145
|
-
_quickFlushIfNeeded() {
|
|
146
|
-
if (this._hasRunQuickFlush) {
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
this._hasRunQuickFlush = true;
|
|
150
|
-
if (Date.now() - this._creationTime > QUICK_FLUSH_WINDOW_MS) {
|
|
141
|
+
appendAndResetNonExposedChecks() {
|
|
142
|
+
if (Object.keys(this._nonExposedChecks).length === 0) {
|
|
151
143
|
return;
|
|
152
144
|
}
|
|
153
|
-
|
|
145
|
+
const event = this._normalizeEvent({
|
|
146
|
+
eventName: 'statsig::non_exposed_checks',
|
|
147
|
+
user: null,
|
|
148
|
+
time: Date.now(),
|
|
149
|
+
metadata: {
|
|
150
|
+
checks: Object.assign({}, this._nonExposedChecks),
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
this._flushCoordinator.addEvent(event);
|
|
154
|
+
this._nonExposedChecks = {};
|
|
154
155
|
}
|
|
155
156
|
_shouldLogEvent(event) {
|
|
156
157
|
var _a;
|
|
@@ -185,118 +186,54 @@ class EventLogger {
|
|
|
185
186
|
this._lastExposureTimeMap[key] = now;
|
|
186
187
|
return true;
|
|
187
188
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
try {
|
|
196
|
-
const isClosing = (0, VisibilityObserving_1._isUnloading)();
|
|
197
|
-
const shouldUseBeacon = isClosing &&
|
|
198
|
-
this._network.isBeaconSupported() &&
|
|
199
|
-
((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.networkOverrideFunc) == null;
|
|
200
|
-
this._emitter({
|
|
201
|
-
name: 'pre_logs_flushed',
|
|
202
|
-
events,
|
|
203
|
-
});
|
|
204
|
-
const response = shouldUseBeacon
|
|
205
|
-
? this._sendEventsViaBeacon(events)
|
|
206
|
-
: yield this._sendEventsViaPost(events);
|
|
207
|
-
if (response.success) {
|
|
208
|
-
this._emitter({
|
|
209
|
-
name: 'logs_flushed',
|
|
210
|
-
events,
|
|
211
|
-
});
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
Log_1.Log.warn('Failed to flush events.');
|
|
216
|
-
this._saveFailedLogsToStorage(events);
|
|
217
|
-
return false;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
catch (_c) {
|
|
221
|
-
Log_1.Log.warn('Failed to flush events.');
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
_sendEventsViaPost(events) {
|
|
227
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
228
|
-
var _a;
|
|
229
|
-
const result = yield this._network.post(this._getRequestData(events));
|
|
230
|
-
const code = (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : -1;
|
|
231
|
-
return { success: code >= 200 && code < 300 };
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
_sendEventsViaBeacon(events) {
|
|
235
|
-
return {
|
|
236
|
-
success: this._network.beacon(this._getRequestData(events)),
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
_getRequestData(events) {
|
|
240
|
-
return {
|
|
241
|
-
sdkKey: this._sdkKey,
|
|
242
|
-
data: {
|
|
243
|
-
events,
|
|
244
|
-
},
|
|
245
|
-
urlConfig: this._logEventUrlConfig,
|
|
246
|
-
retries: 3,
|
|
247
|
-
isCompressable: true,
|
|
248
|
-
params: {
|
|
249
|
-
[NetworkConfig_1.NetworkParam.EventCount]: String(events.length),
|
|
250
|
-
},
|
|
251
|
-
credentials: 'same-origin',
|
|
252
|
-
};
|
|
189
|
+
_getCurrentPageUrl() {
|
|
190
|
+
var _a;
|
|
191
|
+
if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.includeCurrentPageUrlWithEvents) === false) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
return (0, SafeJs_1._getCurrentPageUrlSafe)();
|
|
253
195
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
196
|
+
_getStorageKey() {
|
|
197
|
+
if (!this._storageKey) {
|
|
198
|
+
this._storageKey = `statsig.pending_events.${(0, Hashing_1._DJB2)(this._sdkKey)}`;
|
|
257
199
|
}
|
|
200
|
+
return this._storageKey;
|
|
201
|
+
}
|
|
202
|
+
_storeEventToStorage(event) {
|
|
258
203
|
const storageKey = this._getStorageKey();
|
|
259
204
|
try {
|
|
260
|
-
|
|
261
|
-
|
|
205
|
+
let existingEvents = this._getEventsFromStorage(storageKey);
|
|
206
|
+
existingEvents.push(event);
|
|
207
|
+
if (existingEvents.length > EventRetryConstants_1.EventRetryConstants.MAX_LOCAL_STORAGE) {
|
|
208
|
+
existingEvents = existingEvents.slice(-EventRetryConstants_1.EventRetryConstants.MAX_LOCAL_STORAGE);
|
|
209
|
+
}
|
|
210
|
+
(0, StorageProvider_1._setObjectInStorage)(storageKey, existingEvents);
|
|
262
211
|
}
|
|
263
|
-
catch (
|
|
264
|
-
Log_1.Log.warn('Unable to save
|
|
212
|
+
catch (error) {
|
|
213
|
+
Log_1.Log.warn('Unable to save events to storage');
|
|
265
214
|
}
|
|
266
215
|
}
|
|
267
|
-
|
|
268
|
-
let savedEvents = [];
|
|
216
|
+
_getEventsFromStorage(storageKey) {
|
|
269
217
|
try {
|
|
270
|
-
const
|
|
271
|
-
if (Array.isArray(
|
|
272
|
-
|
|
218
|
+
const events = (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
219
|
+
if (Array.isArray(events)) {
|
|
220
|
+
return events;
|
|
273
221
|
}
|
|
274
|
-
return
|
|
222
|
+
return [];
|
|
275
223
|
}
|
|
276
224
|
catch (_a) {
|
|
277
225
|
return [];
|
|
278
226
|
}
|
|
279
227
|
}
|
|
280
|
-
|
|
228
|
+
_loadStoredEvents() {
|
|
281
229
|
const storageKey = this._getStorageKey();
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
yield StorageProvider_1.Storage.isReadyResolver();
|
|
285
|
-
}
|
|
286
|
-
const events = (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
287
|
-
if (!events) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
230
|
+
const events = this._getEventsFromStorage(storageKey);
|
|
231
|
+
if (events.length > 0) {
|
|
290
232
|
StorageProvider_1.Storage.removeItem(storageKey);
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
Log_1.Log.warn('Failed to flush stored logs');
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
_getStorageKey() {
|
|
297
|
-
return `statsig.failed_logs.${(0, Hashing_1._DJB2)(this._sdkKey)}`;
|
|
233
|
+
}
|
|
234
|
+
return events;
|
|
298
235
|
}
|
|
299
|
-
|
|
236
|
+
_normalizeEvent(event) {
|
|
300
237
|
if (event.user) {
|
|
301
238
|
event.user = Object.assign({}, event.user);
|
|
302
239
|
delete event.user.privateAttributes;
|
|
@@ -306,44 +243,7 @@ class EventLogger {
|
|
|
306
243
|
if (currentPage) {
|
|
307
244
|
extras.statsigMetadata = { currentPage };
|
|
308
245
|
}
|
|
309
|
-
|
|
310
|
-
Log_1.Log.debug('Enqueued Event:', final);
|
|
311
|
-
this._queue.push(final);
|
|
312
|
-
}
|
|
313
|
-
_appendAndResetNonExposedChecks() {
|
|
314
|
-
if (Object.keys(this._nonExposedChecks).length === 0) {
|
|
315
|
-
return;
|
|
316
|
-
}
|
|
317
|
-
this._normalizeAndAppendEvent({
|
|
318
|
-
eventName: 'statsig::non_exposed_checks',
|
|
319
|
-
user: null,
|
|
320
|
-
time: Date.now(),
|
|
321
|
-
metadata: {
|
|
322
|
-
checks: Object.assign({}, this._nonExposedChecks),
|
|
323
|
-
},
|
|
324
|
-
});
|
|
325
|
-
this._nonExposedChecks = {};
|
|
326
|
-
}
|
|
327
|
-
_getCurrentPageUrl() {
|
|
328
|
-
var _a;
|
|
329
|
-
if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.includeCurrentPageUrlWithEvents) === false) {
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
return (0, SafeJs_1._getCurrentPageUrlSafe)();
|
|
333
|
-
}
|
|
334
|
-
_startBackgroundFlushInterval() {
|
|
335
|
-
var _a, _b;
|
|
336
|
-
const flushInterval = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.loggingIntervalMs) !== null && _b !== void 0 ? _b : DEFAULT_FLUSH_INTERVAL_MS;
|
|
337
|
-
const intervalId = setInterval(() => {
|
|
338
|
-
const logger = EVENT_LOGGER_MAP[this._sdkKey];
|
|
339
|
-
if (!logger || logger._flushIntervalId !== intervalId) {
|
|
340
|
-
clearInterval(intervalId);
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
EventLogger._safeFlushAndForget(this._sdkKey);
|
|
344
|
-
}
|
|
345
|
-
}, flushInterval);
|
|
346
|
-
this._flushIntervalId = intervalId;
|
|
246
|
+
return Object.assign(Object.assign({}, event), extras);
|
|
347
247
|
}
|
|
348
248
|
}
|
|
349
249
|
exports.EventLogger = EventLogger;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export declare const EventRetryConstants: {
|
|
2
2
|
readonly MAX_RETRY_ATTEMPTS: 5;
|
|
3
3
|
readonly DEFAULT_BATCH_SIZE: 100;
|
|
4
|
-
readonly MAX_PENDING_BATCHES:
|
|
4
|
+
readonly MAX_PENDING_BATCHES: 30;
|
|
5
5
|
readonly TICK_INTERVAL_MS: 1000;
|
|
6
|
+
readonly QUICK_FLUSH_WINDOW_MS: 200;
|
|
7
|
+
readonly MAX_LOCAL_STORAGE: 500;
|
|
6
8
|
readonly MAX_QUEUED_EVENTS: number;
|
|
7
9
|
};
|
|
@@ -4,8 +4,10 @@ exports.EventRetryConstants = void 0;
|
|
|
4
4
|
exports.EventRetryConstants = {
|
|
5
5
|
MAX_RETRY_ATTEMPTS: 5,
|
|
6
6
|
DEFAULT_BATCH_SIZE: 100,
|
|
7
|
-
MAX_PENDING_BATCHES:
|
|
7
|
+
MAX_PENDING_BATCHES: 30,
|
|
8
8
|
TICK_INTERVAL_MS: 1000,
|
|
9
|
+
QUICK_FLUSH_WINDOW_MS: 200,
|
|
10
|
+
MAX_LOCAL_STORAGE: 500,
|
|
9
11
|
get MAX_QUEUED_EVENTS() {
|
|
10
12
|
return this.DEFAULT_BATCH_SIZE * this.MAX_PENDING_BATCHES;
|
|
11
13
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { EventBatch } from './EventBatch';
|
|
2
|
+
import { NetworkCore } from './NetworkCore';
|
|
3
|
+
import { StatsigClientEmitEventFunc } from './StatsigClientBase';
|
|
4
|
+
import { LogEventCompressionMode, LoggingEnabledOption, NetworkConfigCommon, StatsigOptionsCommon } from './StatsigOptionsCommon';
|
|
5
|
+
import { UrlConfiguration } from './UrlConfiguration';
|
|
6
|
+
export declare class EventSender {
|
|
7
|
+
private _network;
|
|
8
|
+
private _sdkKey;
|
|
9
|
+
private _options;
|
|
10
|
+
private _logEventUrlConfig;
|
|
11
|
+
private _emitter;
|
|
12
|
+
private _loggingEnabled;
|
|
13
|
+
constructor(sdkKey: string, network: NetworkCore, emitter: StatsigClientEmitEventFunc, logEventUrlConfig: UrlConfiguration, options: StatsigOptionsCommon<NetworkConfigCommon> | null, loggingEnabled: LoggingEnabledOption);
|
|
14
|
+
setLogEventCompressionMode(mode: LogEventCompressionMode): void;
|
|
15
|
+
setLoggingEnabled(enabled: LoggingEnabledOption): void;
|
|
16
|
+
sendBatch(batch: EventBatch): Promise<{
|
|
17
|
+
success: boolean;
|
|
18
|
+
statusCode: number;
|
|
19
|
+
}>;
|
|
20
|
+
private _sendEventsViaPost;
|
|
21
|
+
private _sendEventsViaBeacon;
|
|
22
|
+
private _getRequestData;
|
|
23
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EventSender = void 0;
|
|
13
|
+
const Log_1 = require("./Log");
|
|
14
|
+
const NetworkConfig_1 = require("./NetworkConfig");
|
|
15
|
+
const VisibilityObserving_1 = require("./VisibilityObserving");
|
|
16
|
+
class EventSender {
|
|
17
|
+
constructor(sdkKey, network, emitter, logEventUrlConfig, options, loggingEnabled) {
|
|
18
|
+
this._sdkKey = sdkKey;
|
|
19
|
+
this._network = network;
|
|
20
|
+
this._emitter = emitter;
|
|
21
|
+
this._options = options;
|
|
22
|
+
this._logEventUrlConfig = logEventUrlConfig;
|
|
23
|
+
this._loggingEnabled = loggingEnabled;
|
|
24
|
+
}
|
|
25
|
+
setLogEventCompressionMode(mode) {
|
|
26
|
+
this._network.setLogEventCompressionMode(mode);
|
|
27
|
+
}
|
|
28
|
+
setLoggingEnabled(enabled) {
|
|
29
|
+
this._loggingEnabled = enabled;
|
|
30
|
+
}
|
|
31
|
+
sendBatch(batch) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
var _a, _b;
|
|
34
|
+
try {
|
|
35
|
+
const isClosing = (0, VisibilityObserving_1._isUnloading)();
|
|
36
|
+
const shouldUseBeacon = isClosing &&
|
|
37
|
+
this._network.isBeaconSupported() &&
|
|
38
|
+
((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.networkOverrideFunc) == null;
|
|
39
|
+
this._emitter({
|
|
40
|
+
name: 'pre_logs_flushed',
|
|
41
|
+
events: batch.events,
|
|
42
|
+
});
|
|
43
|
+
const response = shouldUseBeacon
|
|
44
|
+
? this._sendEventsViaBeacon(batch)
|
|
45
|
+
: yield this._sendEventsViaPost(batch);
|
|
46
|
+
if (response.success) {
|
|
47
|
+
this._emitter({
|
|
48
|
+
name: 'logs_flushed',
|
|
49
|
+
events: batch.events,
|
|
50
|
+
});
|
|
51
|
+
return response;
|
|
52
|
+
}
|
|
53
|
+
return { success: false, statusCode: -1 };
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
Log_1.Log.warn('Failed to send batch:', error);
|
|
57
|
+
return { success: false, statusCode: -1 };
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
_sendEventsViaPost(batch) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
var _a;
|
|
64
|
+
const result = yield this._network.post(this._getRequestData(batch));
|
|
65
|
+
const code = (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : -1;
|
|
66
|
+
return { success: code >= 200 && code < 300, statusCode: code };
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
_sendEventsViaBeacon(batch) {
|
|
70
|
+
const success = this._network.beacon(this._getRequestData(batch));
|
|
71
|
+
return {
|
|
72
|
+
success,
|
|
73
|
+
statusCode: success ? 200 : -1,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
_getRequestData(batch) {
|
|
77
|
+
return {
|
|
78
|
+
sdkKey: this._sdkKey,
|
|
79
|
+
data: {
|
|
80
|
+
events: batch.events,
|
|
81
|
+
},
|
|
82
|
+
urlConfig: this._logEventUrlConfig,
|
|
83
|
+
retries: 3,
|
|
84
|
+
isCompressable: true,
|
|
85
|
+
params: {
|
|
86
|
+
[NetworkConfig_1.NetworkParam.EventCount]: String(batch.events.length),
|
|
87
|
+
},
|
|
88
|
+
headers: {
|
|
89
|
+
'statsig-event-count': String(batch.events.length),
|
|
90
|
+
'statsig-retry-count': String(batch.attempts),
|
|
91
|
+
},
|
|
92
|
+
credentials: 'same-origin',
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.EventSender = EventSender;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { BatchQueue } from './BatchedEventsQueue';
|
|
2
|
+
import { ErrorBoundary } from './ErrorBoundary';
|
|
3
|
+
import { NetworkCore } from './NetworkCore';
|
|
4
|
+
import { PendingEvents } from './PendingEvents';
|
|
5
|
+
import { StatsigClientEmitEventFunc } from './StatsigClientBase';
|
|
6
|
+
import { StatsigEventInternal } from './StatsigEvent';
|
|
7
|
+
import { LogEventCompressionMode, LoggingEnabledOption, NetworkConfigCommon, StatsigOptionsCommon } from './StatsigOptionsCommon';
|
|
8
|
+
import { UrlConfiguration } from './UrlConfiguration';
|
|
9
|
+
type PrepareFlushCallBack = () => void;
|
|
10
|
+
export declare class FlushCoordinator {
|
|
11
|
+
private _flushInterval;
|
|
12
|
+
private _batchQueue;
|
|
13
|
+
private _pendingEvents;
|
|
14
|
+
private _eventSender;
|
|
15
|
+
private _onPrepareFlush;
|
|
16
|
+
private _errorBoundary;
|
|
17
|
+
private _cooldownTimer;
|
|
18
|
+
private _maxIntervalTimer;
|
|
19
|
+
private _hasRunQuickFlush;
|
|
20
|
+
private _currentFlushPromise;
|
|
21
|
+
private _creationTime;
|
|
22
|
+
private _sdkKey;
|
|
23
|
+
private _storageKey;
|
|
24
|
+
constructor(batchQueue: BatchQueue, pendingEvents: PendingEvents, onPrepareFlush: PrepareFlushCallBack, sdkKey: string, network: NetworkCore, emitter: StatsigClientEmitEventFunc, logEventUrlConfig: UrlConfiguration, options: StatsigOptionsCommon<NetworkConfigCommon> | null, loggingEnabled: LoggingEnabledOption, errorBoundary: ErrorBoundary);
|
|
25
|
+
setLoggingEnabled(loggingEnabled: LoggingEnabledOption): void;
|
|
26
|
+
setLogEventCompressionMode(mode: LogEventCompressionMode): void;
|
|
27
|
+
startScheduledFlushCycle(): void;
|
|
28
|
+
stopScheduledFlushCycle(): void;
|
|
29
|
+
addEvent(event: StatsigEventInternal): void;
|
|
30
|
+
processManualFlush(): Promise<void>;
|
|
31
|
+
processShutdown(): Promise<void>;
|
|
32
|
+
private _executeFlush;
|
|
33
|
+
checkQuickFlush(): void;
|
|
34
|
+
private _attemptScheduledFlush;
|
|
35
|
+
processLimitFlush(): void;
|
|
36
|
+
private _processLimitFlushInternal;
|
|
37
|
+
private _scheduleNextFlush;
|
|
38
|
+
private _clearAllTimers;
|
|
39
|
+
private _processNextBatch;
|
|
40
|
+
private _processOneBatch;
|
|
41
|
+
private _prepareQueueForFlush;
|
|
42
|
+
containsAtLeastOneFullBatch(): boolean;
|
|
43
|
+
convertPendingEventsToBatches(): number;
|
|
44
|
+
private _handleFailure;
|
|
45
|
+
loadAndRetryShutdownFailedEvents(): Promise<void>;
|
|
46
|
+
private _getStorageKey;
|
|
47
|
+
private _saveShutdownFailedEventsToStorage;
|
|
48
|
+
private _getShutdownFailedEventsFromStorage;
|
|
49
|
+
}
|
|
50
|
+
export {};
|