@statsig/client-core 0.0.1-beta.9 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -3
- package/package.json +1 -1
- package/src/$_StatsigGlobal.d.ts +9 -1
- package/src/$_StatsigGlobal.js +29 -12
- package/src/CacheKey.d.ts +4 -0
- package/src/CacheKey.js +27 -0
- package/src/ClientInterfaces.d.ts +46 -12
- package/src/DataAdapterCore.d.ts +31 -0
- package/src/DataAdapterCore.js +192 -0
- package/src/Diagnostics.d.ts +1 -3
- package/src/Diagnostics.js +4 -49
- package/src/DownloadConfigSpecsResponse.d.ts +41 -0
- package/src/DownloadConfigSpecsResponse.js +2 -0
- package/src/ErrorBoundary.d.ts +7 -2
- package/src/ErrorBoundary.js +81 -88
- package/src/EvaluationOptions.d.ts +20 -0
- package/src/EvaluationOptions.js +2 -0
- package/src/EvaluationTypes.d.ts +39 -0
- package/src/EvaluationTypes.js +2 -0
- package/src/EventLogger.d.ts +15 -10
- package/src/EventLogger.js +216 -256
- package/src/Hashing.d.ts +2 -1
- package/src/Hashing.js +26 -7
- package/src/InitializeResponse.d.ts +20 -0
- package/src/InitializeResponse.js +2 -0
- package/src/Log.js +15 -34
- package/src/NetworkConfig.d.ts +19 -0
- package/src/NetworkConfig.js +19 -0
- package/src/NetworkCore.d.ts +17 -7
- package/src/NetworkCore.js +173 -196
- package/src/OverrideAdapter.d.ts +9 -0
- package/src/OverrideAdapter.js +2 -0
- package/src/SDKType.d.ts +8 -0
- package/src/SDKType.js +19 -0
- package/src/SafeJs.d.ts +6 -0
- package/src/SafeJs.js +41 -0
- package/src/SessionID.d.ts +17 -1
- package/src/SessionID.js +89 -8
- package/src/StableID.js +24 -53
- package/src/StatsigClientBase.d.ts +56 -19
- package/src/StatsigClientBase.js +126 -48
- package/src/StatsigClientEventEmitter.d.ts +54 -33
- package/src/StatsigDataAdapter.d.ts +103 -17
- package/src/StatsigDataAdapter.js +2 -0
- package/src/StatsigEvent.d.ts +10 -18
- package/src/StatsigEvent.js +41 -39
- package/src/StatsigMetadata.d.ts +1 -1
- package/src/StatsigMetadata.js +7 -18
- package/src/StatsigOptionsCommon.d.ts +84 -20
- package/src/StatsigTypeFactories.d.ts +6 -0
- package/src/StatsigTypeFactories.js +50 -0
- package/src/StatsigTypes.d.ts +28 -22
- package/src/StatsigTypes.js +0 -29
- package/src/StatsigUser.d.ts +7 -8
- package/src/StatsigUser.js +11 -24
- package/src/StorageProvider.d.ts +13 -8
- package/src/StorageProvider.js +66 -85
- package/src/TypedJsonParse.d.ts +8 -0
- package/src/TypedJsonParse.js +27 -0
- package/src/UUID.js +9 -5
- package/src/UrlOverrides.d.ts +1 -0
- package/src/UrlOverrides.js +15 -0
- package/src/UtitlityTypes.d.ts +3 -0
- package/src/UtitlityTypes.js +2 -0
- package/src/VisibilityObserving.d.ts +9 -0
- package/src/VisibilityObserving.js +39 -0
- package/src/index.d.ts +20 -4
- package/src/index.js +26 -18
- package/src/Monitoring.d.ts +0 -3
- package/src/Monitoring.js +0 -33
- package/src/VisibilityChangeObserver.d.ts +0 -13
- package/src/VisibilityChangeObserver.js +0 -48
- package/src/__tests__/MockLocalStorage.d.ts +0 -9
- package/src/__tests__/MockLocalStorage.js +0 -37
package/src/EventLogger.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -19,113 +8,100 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
19
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
9
|
});
|
|
21
10
|
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
12
|
exports.EventLogger = void 0;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
13
|
+
const Hashing_1 = require("./Hashing");
|
|
14
|
+
const Log_1 = require("./Log");
|
|
15
|
+
const NetworkConfig_1 = require("./NetworkConfig");
|
|
16
|
+
const SafeJs_1 = require("./SafeJs");
|
|
17
|
+
const StatsigEvent_1 = require("./StatsigEvent");
|
|
18
|
+
const StorageProvider_1 = require("./StorageProvider");
|
|
19
|
+
const UrlOverrides_1 = require("./UrlOverrides");
|
|
20
|
+
const VisibilityObserving_1 = require("./VisibilityObserving");
|
|
21
|
+
const DEFAULT_QUEUE_SIZE = 50;
|
|
22
|
+
const DEFAULT_FLUSH_INTERVAL_MS = 10000;
|
|
23
|
+
const MAX_DEDUPER_KEYS = 1000;
|
|
24
|
+
const DEDUPER_WINDOW_DURATION_MS = 60000;
|
|
25
|
+
const MAX_FAILED_LOGS = 500;
|
|
26
|
+
const QUICK_FLUSH_WINDOW_MS = 200;
|
|
27
|
+
const EVENT_LOGGER_MAP = {};
|
|
28
|
+
const _safeFlushAndForget = (sdkKey) => {
|
|
29
|
+
var _a;
|
|
30
|
+
(_a = EVENT_LOGGER_MAP[sdkKey]) === null || _a === void 0 ? void 0 : _a.flush().catch(() => {
|
|
31
|
+
// noop
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
class EventLogger {
|
|
35
|
+
constructor(_sdkKey, _emitter, _network, _options) {
|
|
36
|
+
var _a;
|
|
68
37
|
this._sdkKey = _sdkKey;
|
|
69
38
|
this._emitter = _emitter;
|
|
70
39
|
this._network = _network;
|
|
71
40
|
this._options = _options;
|
|
72
41
|
this._queue = [];
|
|
73
|
-
this.
|
|
42
|
+
this._lastExposureTimeMap = {};
|
|
43
|
+
this._nonExposedChecks = {};
|
|
74
44
|
this._hasRunQuickFlush = false;
|
|
75
45
|
this._creationTime = Date.now();
|
|
46
|
+
EVENT_LOGGER_MAP[_sdkKey] = this;
|
|
47
|
+
this._isLoggingDisabled = (_options === null || _options === void 0 ? void 0 : _options.disableLogging) === true;
|
|
76
48
|
this._maxQueueSize = (_a = _options === null || _options === void 0 ? void 0 : _options.loggingBufferMaxSize) !== null && _a !== void 0 ? _a : DEFAULT_QUEUE_SIZE;
|
|
77
|
-
|
|
78
|
-
this.
|
|
79
|
-
|
|
80
|
-
|
|
49
|
+
const config = _options === null || _options === void 0 ? void 0 : _options.networkConfig;
|
|
50
|
+
this._logEventUrl = (0, UrlOverrides_1._getOverridableUrl)(config === null || config === void 0 ? void 0 : config.logEventUrl, config === null || config === void 0 ? void 0 : config.api, '/rgstr', NetworkConfig_1.NetworkDefault.eventsApi);
|
|
51
|
+
(0, VisibilityObserving_1._subscribeToVisiblityChanged)((visibility) => {
|
|
52
|
+
if (visibility === 'background') {
|
|
53
|
+
_safeFlushAndForget(_sdkKey);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
81
56
|
this._retryFailedLogs();
|
|
57
|
+
this._startBackgroundFlushInterval();
|
|
82
58
|
}
|
|
83
|
-
|
|
59
|
+
setLoggingDisabled(isDisabled) {
|
|
60
|
+
this._isLoggingDisabled = isDisabled;
|
|
61
|
+
}
|
|
62
|
+
enqueue(event) {
|
|
84
63
|
if (!this._shouldLogEvent(event)) {
|
|
85
64
|
return;
|
|
86
65
|
}
|
|
87
|
-
|
|
88
|
-
event.user = __assign({}, event.user);
|
|
89
|
-
delete event.user.privateAttributes;
|
|
90
|
-
}
|
|
91
|
-
var _a = StatsigMetadata_1.StatsigMetadataProvider.get(), sdkType = _a.sdkType, sdkVersion = _a.sdkVersion;
|
|
92
|
-
this._queue.push(__assign(__assign({}, event), { statsigMetadata: { sdkType: sdkType, sdkVersion: sdkVersion } }));
|
|
66
|
+
this._normalizeAndAppendEvent(event);
|
|
93
67
|
this._quickFlushIfNeeded();
|
|
94
68
|
if (this._queue.length > this._maxQueueSize) {
|
|
95
|
-
this.
|
|
69
|
+
_safeFlushAndForget(this._sdkKey);
|
|
96
70
|
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
71
|
+
}
|
|
72
|
+
incrementNonExposureCount(name) {
|
|
73
|
+
var _a;
|
|
74
|
+
const current = (_a = this._nonExposedChecks[name]) !== null && _a !== void 0 ? _a : 0;
|
|
75
|
+
this._nonExposedChecks[name] = current + 1;
|
|
76
|
+
}
|
|
77
|
+
reset() {
|
|
78
|
+
this._lastExposureTimeMap = {};
|
|
79
|
+
}
|
|
80
|
+
shutdown() {
|
|
81
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
if (this._flushIntervalId) {
|
|
83
|
+
clearInterval(this._flushIntervalId);
|
|
84
|
+
this._flushIntervalId = null;
|
|
85
|
+
}
|
|
86
|
+
yield this.flush();
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
flush() {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
this._appendAndResetNonExposedChecks();
|
|
92
|
+
if (this._queue.length === 0) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const events = this._queue;
|
|
96
|
+
this._queue = [];
|
|
97
|
+
return this._sendEvents(events);
|
|
121
98
|
});
|
|
122
|
-
}
|
|
99
|
+
}
|
|
123
100
|
/**
|
|
124
101
|
* We 'Quick Flush' following the very first event enqueued
|
|
125
102
|
* within the quick flush window
|
|
126
103
|
*/
|
|
127
|
-
|
|
128
|
-
var _this = this;
|
|
104
|
+
_quickFlushIfNeeded() {
|
|
129
105
|
if (this._hasRunQuickFlush) {
|
|
130
106
|
return;
|
|
131
107
|
}
|
|
@@ -133,183 +109,167 @@ var EventLogger = /** @class */ (function () {
|
|
|
133
109
|
if (Date.now() - this._creationTime > QUICK_FLUSH_WINDOW_MS) {
|
|
134
110
|
return;
|
|
135
111
|
}
|
|
136
|
-
setTimeout(
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (!(0, StatsigEvent_1.isExposureEvent)(event)) {
|
|
112
|
+
setTimeout(() => _safeFlushAndForget(this._sdkKey), QUICK_FLUSH_WINDOW_MS);
|
|
113
|
+
}
|
|
114
|
+
_shouldLogEvent(event) {
|
|
115
|
+
if (!(0, StatsigEvent_1._isExposureEvent)(event)) {
|
|
141
116
|
return true;
|
|
142
117
|
}
|
|
143
|
-
|
|
118
|
+
const user = event.user ? event.user : {};
|
|
119
|
+
const metadata = event.metadata ? event.metadata : {};
|
|
120
|
+
const key = [
|
|
144
121
|
event.eventName,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
122
|
+
user.userID,
|
|
123
|
+
metadata['gate'],
|
|
124
|
+
metadata['config'],
|
|
125
|
+
metadata['ruleID'],
|
|
149
126
|
].join('|');
|
|
150
|
-
|
|
151
|
-
|
|
127
|
+
const previous = this._lastExposureTimeMap[key];
|
|
128
|
+
const now = Date.now();
|
|
152
129
|
if (previous && now - previous < DEDUPER_WINDOW_DURATION_MS) {
|
|
153
130
|
return false;
|
|
154
131
|
}
|
|
155
|
-
if (Object.keys(this.
|
|
156
|
-
this.
|
|
132
|
+
if (Object.keys(this._lastExposureTimeMap).length > MAX_DEDUPER_KEYS) {
|
|
133
|
+
this._lastExposureTimeMap = {};
|
|
157
134
|
}
|
|
158
|
-
this.
|
|
135
|
+
this._lastExposureTimeMap[key] = now;
|
|
159
136
|
return true;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
this._flush().catch(function () {
|
|
163
|
-
// noop
|
|
164
|
-
});
|
|
165
|
-
};
|
|
166
|
-
EventLogger.prototype._flush = function () {
|
|
167
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
168
|
-
var events;
|
|
169
|
-
return __generator(this, function (_a) {
|
|
170
|
-
switch (_a.label) {
|
|
171
|
-
case 0:
|
|
172
|
-
if (this._queue.length === 0) {
|
|
173
|
-
return [2 /*return*/];
|
|
174
|
-
}
|
|
175
|
-
events = this._queue;
|
|
176
|
-
this._queue = [];
|
|
177
|
-
return [4 /*yield*/, this._sendEvents(events)];
|
|
178
|
-
case 1:
|
|
179
|
-
_a.sent();
|
|
180
|
-
return [2 /*return*/];
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
};
|
|
185
|
-
EventLogger.prototype._sendEvents = function (events) {
|
|
137
|
+
}
|
|
138
|
+
_sendEvents(events) {
|
|
186
139
|
var _a, _b;
|
|
187
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
response = _c;
|
|
206
|
-
if (response.success) {
|
|
207
|
-
this._emitter({
|
|
208
|
-
event: 'logs_flushed',
|
|
209
|
-
events: events,
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
this._saveFailedLogsToStorage(events);
|
|
214
|
-
}
|
|
215
|
-
return [3 /*break*/, 6];
|
|
216
|
-
case 5:
|
|
217
|
-
_d = _e.sent();
|
|
218
|
-
Log_1.Log.warn('Failed to flush events.');
|
|
219
|
-
return [3 /*break*/, 6];
|
|
220
|
-
case 6: return [2 /*return*/];
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
};
|
|
225
|
-
EventLogger.prototype._sendEventsViaPost = function (api, events) {
|
|
226
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
227
|
-
var result;
|
|
228
|
-
return __generator(this, function (_a) {
|
|
229
|
-
switch (_a.label) {
|
|
230
|
-
case 0: return [4 /*yield*/, this._network.post({
|
|
231
|
-
sdkKey: this._sdkKey,
|
|
232
|
-
data: {
|
|
233
|
-
events: events,
|
|
234
|
-
},
|
|
235
|
-
url: "".concat(api, "/rgstr"),
|
|
236
|
-
retries: 3,
|
|
237
|
-
params: {
|
|
238
|
-
// ec = Event Count
|
|
239
|
-
ec: String(events.length),
|
|
240
|
-
},
|
|
241
|
-
})];
|
|
242
|
-
case 1:
|
|
243
|
-
result = _a.sent();
|
|
244
|
-
if (result === null || result === void 0 ? void 0 : result.body) {
|
|
245
|
-
return [2 /*return*/, JSON.parse(result.body)];
|
|
246
|
-
}
|
|
247
|
-
return [2 /*return*/, { success: false }];
|
|
140
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
+
if (this._isLoggingDisabled) {
|
|
142
|
+
this._saveFailedLogsToStorage(events);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
const isInBackground = !(0, VisibilityObserving_1._isCurrentlyVisible)();
|
|
147
|
+
const shouldUseBeacon = isInBackground &&
|
|
148
|
+
this._network.isBeaconSupported() &&
|
|
149
|
+
((_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.networkConfig) === null || _b === void 0 ? void 0 : _b.networkOverrideFunc) == null;
|
|
150
|
+
const response = shouldUseBeacon
|
|
151
|
+
? yield this._sendEventsViaBeacon(events)
|
|
152
|
+
: yield this._sendEventsViaPost(events);
|
|
153
|
+
if (response.success) {
|
|
154
|
+
this._emitter({
|
|
155
|
+
name: 'logs_flushed',
|
|
156
|
+
events,
|
|
157
|
+
});
|
|
248
158
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
};
|
|
252
|
-
EventLogger.prototype._sendEventsViaBeacon = function (api, events) {
|
|
253
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
254
|
-
var _a;
|
|
255
|
-
return __generator(this, function (_b) {
|
|
256
|
-
switch (_b.label) {
|
|
257
|
-
case 0:
|
|
258
|
-
_a = {};
|
|
259
|
-
return [4 /*yield*/, this._network.beacon({
|
|
260
|
-
sdkKey: this._sdkKey,
|
|
261
|
-
data: {
|
|
262
|
-
events: events,
|
|
263
|
-
},
|
|
264
|
-
url: "".concat(api, "/log_event_beacon"),
|
|
265
|
-
})];
|
|
266
|
-
case 1: return [2 /*return*/, (_a.success = _b.sent(),
|
|
267
|
-
_a)];
|
|
159
|
+
else {
|
|
160
|
+
this._saveFailedLogsToStorage(events);
|
|
268
161
|
}
|
|
269
|
-
}
|
|
162
|
+
}
|
|
163
|
+
catch (_c) {
|
|
164
|
+
Log_1.Log.warn('Failed to flush events.');
|
|
165
|
+
}
|
|
270
166
|
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return (typeof navigator !== 'undefined' &&
|
|
274
|
-
typeof (navigator === null || navigator === void 0 ? void 0 : navigator.sendBeacon) === 'function');
|
|
275
|
-
};
|
|
276
|
-
EventLogger.prototype._saveFailedLogsToStorage = function (events) {
|
|
167
|
+
}
|
|
168
|
+
_sendEventsViaPost(events) {
|
|
277
169
|
var _a;
|
|
278
|
-
(
|
|
279
|
-
|
|
280
|
-
|
|
170
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
171
|
+
const result = yield this._network.post(this._getRequestData(events));
|
|
172
|
+
const code = (_a = result === null || result === void 0 ? void 0 : result.code) !== null && _a !== void 0 ? _a : -1;
|
|
173
|
+
return { success: code >= 200 && code < 300 };
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
_sendEventsViaBeacon(events) {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
178
|
+
return {
|
|
179
|
+
success: yield this._network.beacon(this._getRequestData(events)),
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
_getRequestData(events) {
|
|
184
|
+
return {
|
|
185
|
+
sdkKey: this._sdkKey,
|
|
186
|
+
data: {
|
|
187
|
+
events,
|
|
188
|
+
},
|
|
189
|
+
url: this._logEventUrl,
|
|
190
|
+
retries: 3,
|
|
191
|
+
isCompressable: true,
|
|
192
|
+
params: {
|
|
193
|
+
[NetworkConfig_1.NetworkParam.EventCount]: String(events.length),
|
|
194
|
+
},
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
_saveFailedLogsToStorage(events) {
|
|
198
|
+
while (events.length > MAX_FAILED_LOGS) {
|
|
199
|
+
events.shift();
|
|
281
200
|
}
|
|
282
|
-
|
|
283
|
-
(0, StorageProvider_1.
|
|
201
|
+
const storageKey = this._getStorageKey();
|
|
202
|
+
(0, StorageProvider_1._setObjectInStorage)(storageKey, events).catch(() => {
|
|
284
203
|
Log_1.Log.warn('Unable to save failed logs to storage');
|
|
285
204
|
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
return [2 /*return*/];
|
|
299
|
-
}
|
|
300
|
-
return [4 /*yield*/, this._sendEvents(events)];
|
|
301
|
-
case 2:
|
|
302
|
-
_a.sent();
|
|
303
|
-
return [2 /*return*/];
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
}); })().catch(function () {
|
|
307
|
-
Log_1.Log.warn('Unable to flush stored logs');
|
|
205
|
+
}
|
|
206
|
+
_retryFailedLogs() {
|
|
207
|
+
const storageKey = this._getStorageKey();
|
|
208
|
+
(() => __awaiter(this, void 0, void 0, function* () {
|
|
209
|
+
const events = yield (0, StorageProvider_1._getObjectFromStorage)(storageKey);
|
|
210
|
+
if (!events) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
yield StorageProvider_1.Storage._removeItem(storageKey);
|
|
214
|
+
yield this._sendEvents(events);
|
|
215
|
+
}))().catch(() => {
|
|
216
|
+
Log_1.Log.warn('Failed to flush stored logs');
|
|
308
217
|
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
return
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
|
|
218
|
+
}
|
|
219
|
+
_getStorageKey() {
|
|
220
|
+
return `statsig.failed_logs.${(0, Hashing_1._DJB2)(this._sdkKey)}`;
|
|
221
|
+
}
|
|
222
|
+
_normalizeAndAppendEvent(event) {
|
|
223
|
+
if (event.user) {
|
|
224
|
+
event.user = Object.assign({}, event.user);
|
|
225
|
+
delete event.user.privateAttributes;
|
|
226
|
+
}
|
|
227
|
+
const extras = {};
|
|
228
|
+
const currentPage = this._getCurrentPageUrl();
|
|
229
|
+
if (currentPage) {
|
|
230
|
+
extras.statsigMetadata = { currentPage };
|
|
231
|
+
}
|
|
232
|
+
const final = Object.assign(Object.assign({}, event), extras);
|
|
233
|
+
Log_1.Log.debug('Enqueued Event:', final);
|
|
234
|
+
this._queue.push(final);
|
|
235
|
+
}
|
|
236
|
+
_appendAndResetNonExposedChecks() {
|
|
237
|
+
if (Object.keys(this._nonExposedChecks).length === 0) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
this._normalizeAndAppendEvent({
|
|
241
|
+
eventName: 'statsig::non_exposed_checks',
|
|
242
|
+
user: null,
|
|
243
|
+
time: Date.now(),
|
|
244
|
+
metadata: {
|
|
245
|
+
checks: Object.assign({}, this._nonExposedChecks),
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
this._nonExposedChecks = {};
|
|
249
|
+
}
|
|
250
|
+
_getCurrentPageUrl() {
|
|
251
|
+
var _a;
|
|
252
|
+
if (((_a = this._options) === null || _a === void 0 ? void 0 : _a.includeCurrentPageUrlWithEvents) === false) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
return (0, SafeJs_1._getCurrentPageUrlSafe)();
|
|
256
|
+
}
|
|
257
|
+
_startBackgroundFlushInterval() {
|
|
258
|
+
var _a, _b;
|
|
259
|
+
if (!(0, SafeJs_1._isBrowserEnv)()) {
|
|
260
|
+
return; // do not run in server environments
|
|
261
|
+
}
|
|
262
|
+
const flushInterval = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.loggingIntervalMs) !== null && _b !== void 0 ? _b : DEFAULT_FLUSH_INTERVAL_MS;
|
|
263
|
+
const intervalId = setInterval(() => {
|
|
264
|
+
const logger = EVENT_LOGGER_MAP[this._sdkKey];
|
|
265
|
+
if (logger._flushIntervalId !== intervalId) {
|
|
266
|
+
clearInterval(intervalId);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
_safeFlushAndForget(this._sdkKey);
|
|
270
|
+
}
|
|
271
|
+
}, flushInterval);
|
|
272
|
+
this._flushIntervalId = intervalId;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
315
275
|
exports.EventLogger = EventLogger;
|
package/src/Hashing.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export declare
|
|
1
|
+
export declare const _DJB2: (value: string) => string;
|
|
2
|
+
export declare const _DJB2Object: (value: Record<string, unknown> | null) => string;
|
package/src/Hashing.js
CHANGED
|
@@ -1,13 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
for (
|
|
7
|
-
|
|
3
|
+
exports._DJB2Object = exports._DJB2 = void 0;
|
|
4
|
+
const _DJB2 = (value) => {
|
|
5
|
+
let hash = 0;
|
|
6
|
+
for (let i = 0; i < value.length; i++) {
|
|
7
|
+
const character = value.charCodeAt(i);
|
|
8
8
|
hash = (hash << 5) - hash + character;
|
|
9
9
|
hash = hash & hash; // Convert to 32bit integer
|
|
10
10
|
}
|
|
11
11
|
return String(hash >>> 0);
|
|
12
|
-
}
|
|
13
|
-
exports.
|
|
12
|
+
};
|
|
13
|
+
exports._DJB2 = _DJB2;
|
|
14
|
+
const _DJB2Object = (value) => {
|
|
15
|
+
return (0, exports._DJB2)(JSON.stringify(_getSortedObject(value)));
|
|
16
|
+
};
|
|
17
|
+
exports._DJB2Object = _DJB2Object;
|
|
18
|
+
const _getSortedObject = (object) => {
|
|
19
|
+
if (object == null) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const keys = Object.keys(object).sort();
|
|
23
|
+
const sortedObject = {};
|
|
24
|
+
keys.forEach((key) => {
|
|
25
|
+
let value = object[key];
|
|
26
|
+
if (!Array.isArray(value) && value instanceof Object) {
|
|
27
|
+
value = _getSortedObject(value);
|
|
28
|
+
}
|
|
29
|
+
sortedObject[key] = value;
|
|
30
|
+
});
|
|
31
|
+
return sortedObject;
|
|
32
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DynamicConfigEvaluation, GateEvaluation, LayerEvaluation } from './EvaluationTypes';
|
|
2
|
+
import { StatsigUser } from './StatsigUser';
|
|
3
|
+
type SessionReplayFields = {
|
|
4
|
+
can_record_session?: boolean;
|
|
5
|
+
session_recording_rate?: number;
|
|
6
|
+
};
|
|
7
|
+
export type InitializeResponseWithUpdates = SessionReplayFields & {
|
|
8
|
+
feature_gates: Record<string, GateEvaluation>;
|
|
9
|
+
dynamic_configs: Record<string, DynamicConfigEvaluation>;
|
|
10
|
+
layer_configs: Record<string, LayerEvaluation>;
|
|
11
|
+
time: number;
|
|
12
|
+
has_updates: true;
|
|
13
|
+
hash_used: 'none' | 'sha256' | 'djb2';
|
|
14
|
+
derived_fields?: Record<string, unknown>;
|
|
15
|
+
user?: StatsigUser;
|
|
16
|
+
};
|
|
17
|
+
export type InitializeResponse = InitializeResponseWithUpdates | {
|
|
18
|
+
has_updates: false;
|
|
19
|
+
};
|
|
20
|
+
export {};
|
package/src/Log.js
CHANGED
|
@@ -14,46 +14,27 @@ var LogLevel;
|
|
|
14
14
|
LogLevel[LogLevel["Info"] = 3] = "Info";
|
|
15
15
|
LogLevel[LogLevel["Debug"] = 4] = "Debug";
|
|
16
16
|
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
Log.info = function () {
|
|
21
|
-
var args = [];
|
|
22
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
23
|
-
args[_i] = arguments[_i];
|
|
24
|
-
}
|
|
17
|
+
class Log {
|
|
18
|
+
static info(...args) {
|
|
25
19
|
if (this.level >= LogLevel.Info) {
|
|
26
|
-
console.info
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
Log.debug = function () {
|
|
30
|
-
var args = [];
|
|
31
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
32
|
-
args[_i] = arguments[_i];
|
|
20
|
+
console.info(...addTag(args));
|
|
33
21
|
}
|
|
22
|
+
}
|
|
23
|
+
static debug(...args) {
|
|
34
24
|
if (this.level >= LogLevel.Debug) {
|
|
35
|
-
console.debug
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
Log.warn = function () {
|
|
39
|
-
var args = [];
|
|
40
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
41
|
-
args[_i] = arguments[_i];
|
|
25
|
+
console.debug(...addTag(args));
|
|
42
26
|
}
|
|
27
|
+
}
|
|
28
|
+
static warn(...args) {
|
|
43
29
|
if (this.level >= LogLevel.Warn) {
|
|
44
|
-
console.warn
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
Log.error = function () {
|
|
48
|
-
var args = [];
|
|
49
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
50
|
-
args[_i] = arguments[_i];
|
|
30
|
+
console.warn(...addTag(args));
|
|
51
31
|
}
|
|
32
|
+
}
|
|
33
|
+
static error(...args) {
|
|
52
34
|
if (this.level >= LogLevel.Error) {
|
|
53
|
-
console.error
|
|
35
|
+
console.error(...addTag(args));
|
|
54
36
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return Log;
|
|
58
|
-
}());
|
|
37
|
+
}
|
|
38
|
+
}
|
|
59
39
|
exports.Log = Log;
|
|
40
|
+
Log.level = LogLevel.Error;
|