@splitsoftware/splitio-commons 2.0.1 → 2.0.3-rc.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/CHANGES.txt +8 -0
- package/cjs/evaluator/index.js +2 -0
- package/cjs/listeners/browser.js +4 -6
- package/cjs/readiness/readinessManager.js +16 -18
- package/cjs/sdkClient/client.js +13 -13
- package/cjs/sdkClient/sdkClient.js +1 -1
- package/cjs/sdkFactory/index.js +10 -14
- package/cjs/sdkManager/index.js +2 -1
- package/cjs/services/decorateHeaders.js +6 -1
- package/cjs/services/splitHttpClient.js +1 -1
- package/cjs/storages/inLocalStorage/index.js +6 -20
- package/cjs/storages/inMemory/InMemoryStorage.js +4 -12
- package/cjs/storages/inMemory/InMemoryStorageCS.js +6 -19
- package/cjs/storages/inRedis/index.js +9 -13
- package/cjs/storages/pluggable/index.js +15 -19
- package/cjs/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/cjs/sync/submitters/submitterManager.js +3 -6
- package/cjs/trackers/impressionsTracker.js +17 -18
- package/cjs/trackers/strategy/strategyDebug.js +4 -11
- package/cjs/trackers/strategy/strategyNone.js +11 -16
- package/cjs/trackers/strategy/strategyOptimized.js +11 -21
- package/esm/evaluator/index.js +2 -0
- package/esm/listeners/browser.js +1 -3
- package/esm/readiness/readinessManager.js +16 -18
- package/esm/sdkClient/client.js +13 -13
- package/esm/sdkClient/sdkClient.js +1 -1
- package/esm/sdkFactory/index.js +11 -15
- package/esm/sdkManager/index.js +2 -1
- package/esm/services/decorateHeaders.js +4 -0
- package/esm/services/splitHttpClient.js +2 -2
- package/esm/storages/inLocalStorage/index.js +7 -21
- package/esm/storages/inMemory/InMemoryStorage.js +5 -13
- package/esm/storages/inMemory/InMemoryStorageCS.js +7 -20
- package/esm/storages/inRedis/index.js +10 -14
- package/esm/storages/pluggable/index.js +16 -20
- package/esm/sync/submitters/impressionCountsSubmitter.js +2 -4
- package/esm/sync/submitters/submitterManager.js +3 -6
- package/esm/trackers/impressionsTracker.js +17 -18
- package/esm/trackers/strategy/strategyDebug.js +4 -11
- package/esm/trackers/strategy/strategyNone.js +11 -16
- package/esm/trackers/strategy/strategyOptimized.js +11 -21
- package/package.json +1 -1
- package/src/dtos/types.ts +2 -1
- package/src/evaluator/index.ts +2 -0
- package/src/evaluator/types.ts +1 -1
- package/src/listeners/browser.ts +1 -3
- package/src/readiness/readinessManager.ts +15 -16
- package/src/sdkClient/client.ts +11 -11
- package/src/sdkClient/sdkClient.ts +1 -1
- package/src/sdkFactory/index.ts +12 -16
- package/src/sdkFactory/types.ts +1 -1
- package/src/sdkManager/index.ts +2 -1
- package/src/services/decorateHeaders.ts +5 -0
- package/src/services/splitHttpClient.ts +2 -2
- package/src/storages/inLocalStorage/index.ts +7 -20
- package/src/storages/inMemory/InMemoryStorage.ts +5 -13
- package/src/storages/inMemory/InMemoryStorageCS.ts +7 -20
- package/src/storages/inRedis/index.ts +10 -10
- package/src/storages/pluggable/index.ts +16 -20
- package/src/storages/types.ts +2 -2
- package/src/sync/submitters/impressionCountsSubmitter.ts +2 -4
- package/src/sync/submitters/submitterManager.ts +3 -4
- package/src/sync/submitters/uniqueKeysSubmitter.ts +2 -3
- package/src/trackers/impressionsTracker.ts +17 -18
- package/src/trackers/strategy/strategyDebug.ts +4 -11
- package/src/trackers/strategy/strategyNone.ts +11 -17
- package/src/trackers/strategy/strategyOptimized.ts +10 -20
- package/src/trackers/types.ts +2 -8
- package/types/splitio.d.ts +4 -0
|
@@ -7,38 +7,37 @@ var constants_1 = require("../logger/constants");
|
|
|
7
7
|
var constants_2 = require("../utils/constants");
|
|
8
8
|
/**
|
|
9
9
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
10
|
-
*
|
|
11
|
-
* @param impressionsCache - cache to save impressions
|
|
12
|
-
* @param metadata - runtime metadata (ip, hostname and version)
|
|
13
|
-
* @param impressionListener - optional impression listener
|
|
14
|
-
* @param integrationsManager - optional integrations manager
|
|
15
|
-
* @param strategy - strategy for impressions tracking.
|
|
16
10
|
*/
|
|
17
|
-
function impressionsTrackerFactory(settings, impressionsCache, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
11
|
+
function impressionsTrackerFactory(settings, impressionsCache, noneStrategy, strategy, whenInit, integrationsManager, telemetryCache) {
|
|
18
12
|
var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
|
|
19
13
|
return {
|
|
20
14
|
track: function (impressions, attributes) {
|
|
21
15
|
if (settings.userConsent === constants_2.CONSENT_DECLINED)
|
|
22
16
|
return;
|
|
23
|
-
var
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
var impressionsToStore = impressions.filter(function (_a) {
|
|
18
|
+
var impression = _a[0], track = _a[1];
|
|
19
|
+
return track === false ?
|
|
20
|
+
noneStrategy.process(impression) :
|
|
21
|
+
strategy.process(impression);
|
|
22
|
+
});
|
|
23
|
+
var impressionsLength = impressions.length;
|
|
24
|
+
var impressionsToStoreLength = impressionsToStore.length;
|
|
25
|
+
if (impressionsToStoreLength) {
|
|
26
|
+
var res = impressionsCache.track(impressionsToStore.map(function (item) { return item[0]; }));
|
|
28
27
|
// If we're on an async storage, handle error and log it.
|
|
29
28
|
if ((0, thenable_1.thenable)(res)) {
|
|
30
29
|
res.then(function () {
|
|
31
|
-
log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [
|
|
30
|
+
log.info(constants_1.IMPRESSIONS_TRACKER_SUCCESS, [impressionsLength]);
|
|
32
31
|
}).catch(function (err) {
|
|
33
|
-
log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [
|
|
32
|
+
log.error(constants_1.ERROR_IMPRESSIONS_TRACKER, [impressionsLength, err]);
|
|
34
33
|
});
|
|
35
34
|
}
|
|
36
35
|
else {
|
|
37
36
|
// Record when impressionsCache is sync only (standalone mode)
|
|
38
37
|
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
39
38
|
if (telemetryCache) {
|
|
40
|
-
telemetryCache.recordImpressionStats(constants_2.QUEUED,
|
|
41
|
-
telemetryCache.recordImpressionStats(constants_2.DEDUPED,
|
|
39
|
+
telemetryCache.recordImpressionStats(constants_2.QUEUED, impressionsToStoreLength);
|
|
40
|
+
telemetryCache.recordImpressionStats(constants_2.DEDUPED, impressionsLength - impressionsToStoreLength);
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
43
|
}
|
|
@@ -47,7 +46,7 @@ function impressionsTrackerFactory(settings, impressionsCache, strategy, whenIni
|
|
|
47
46
|
var _loop_1 = function (i) {
|
|
48
47
|
var impressionData = {
|
|
49
48
|
// copy of impression, to avoid unexpected behaviour if modified by integrations or impressionListener
|
|
50
|
-
impression: (0, objectAssign_1.objectAssign)({},
|
|
49
|
+
impression: (0, objectAssign_1.objectAssign)({}, impressions[i][0]),
|
|
51
50
|
attributes: attributes,
|
|
52
51
|
ip: ip,
|
|
53
52
|
hostname: hostname,
|
|
@@ -69,7 +68,7 @@ function impressionsTrackerFactory(settings, impressionsCache, strategy, whenIni
|
|
|
69
68
|
});
|
|
70
69
|
});
|
|
71
70
|
};
|
|
72
|
-
for (var i = 0; i <
|
|
71
|
+
for (var i = 0; i < impressionsLength; i++) {
|
|
73
72
|
_loop_1(i);
|
|
74
73
|
}
|
|
75
74
|
}
|
|
@@ -5,20 +5,13 @@ exports.strategyDebugFactory = void 0;
|
|
|
5
5
|
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
6
6
|
*
|
|
7
7
|
* @param impressionsObserver - impression observer. Previous time (pt property) is included in impression instances
|
|
8
|
-
* @returns
|
|
8
|
+
* @returns Debug strategy
|
|
9
9
|
*/
|
|
10
10
|
function strategyDebugFactory(impressionsObserver) {
|
|
11
11
|
return {
|
|
12
|
-
process: function (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
impression.pt = impressionsObserver.testAndSet(impression);
|
|
16
|
-
});
|
|
17
|
-
return {
|
|
18
|
-
impressionsToStore: impressions,
|
|
19
|
-
impressionsToListener: impressions,
|
|
20
|
-
deduped: 0
|
|
21
|
-
};
|
|
12
|
+
process: function (impression) {
|
|
13
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
14
|
+
return true;
|
|
22
15
|
}
|
|
23
16
|
};
|
|
24
17
|
}
|
|
@@ -4,25 +4,20 @@ exports.strategyNoneFactory = void 0;
|
|
|
4
4
|
/**
|
|
5
5
|
* None strategy for impressions tracker.
|
|
6
6
|
*
|
|
7
|
-
* @param
|
|
7
|
+
* @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
8
8
|
* @param uniqueKeysTracker - unique keys tracker in charge of tracking the unique keys per split.
|
|
9
|
-
* @returns
|
|
9
|
+
* @returns None strategy
|
|
10
10
|
*/
|
|
11
|
-
function strategyNoneFactory(
|
|
11
|
+
function strategyNoneFactory(impressionCounts, uniqueKeysTracker) {
|
|
12
12
|
return {
|
|
13
|
-
process: function (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
impressionsToStore: [],
|
|
23
|
-
impressionsToListener: impressions,
|
|
24
|
-
deduped: 0
|
|
25
|
-
};
|
|
13
|
+
process: function (impression) {
|
|
14
|
+
var now = Date.now();
|
|
15
|
+
// Increments impression counter per featureName
|
|
16
|
+
impressionCounts.track(impression.feature, now, 1);
|
|
17
|
+
// Keep track by unique key
|
|
18
|
+
uniqueKeysTracker.track(impression.keyName, impression.feature);
|
|
19
|
+
// Do not store impressions
|
|
20
|
+
return false;
|
|
26
21
|
}
|
|
27
22
|
};
|
|
28
23
|
}
|
|
@@ -6,29 +6,19 @@ var time_1 = require("../../utils/time");
|
|
|
6
6
|
* Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
7
7
|
*
|
|
8
8
|
* @param impressionsObserver - impression observer. previous time (pt property) is included in impression instances
|
|
9
|
-
* @param
|
|
10
|
-
* @returns
|
|
9
|
+
* @param impressionCounts - cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
10
|
+
* @returns Optimized strategy
|
|
11
11
|
*/
|
|
12
|
-
function strategyOptimizedFactory(impressionsObserver,
|
|
12
|
+
function strategyOptimizedFactory(impressionsObserver, impressionCounts) {
|
|
13
13
|
return {
|
|
14
|
-
process: function (
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// Checks if the impression should be added in queue to be sent
|
|
23
|
-
if (!impression.pt || impression.pt < (0, time_1.truncateTimeFrame)(now)) {
|
|
24
|
-
impressionsToStore.push(impression);
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
return {
|
|
28
|
-
impressionsToStore: impressionsToStore,
|
|
29
|
-
impressionsToListener: impressions,
|
|
30
|
-
deduped: impressions.length - impressionsToStore.length
|
|
31
|
-
};
|
|
14
|
+
process: function (impression) {
|
|
15
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
16
|
+
var now = Date.now();
|
|
17
|
+
// Increments impression counter per featureName
|
|
18
|
+
if (impression.pt)
|
|
19
|
+
impressionCounts.track(impression.feature, now, 1);
|
|
20
|
+
// Checks if the impression should be added in queue to be sent
|
|
21
|
+
return (!impression.pt || impression.pt < (0, time_1.truncateTimeFrame)(now)) ? true : false;
|
|
32
22
|
}
|
|
33
23
|
};
|
|
34
24
|
}
|
package/esm/evaluator/index.js
CHANGED
|
@@ -98,12 +98,14 @@ function getEvaluation(log, splitJSON, key, attributes, storage) {
|
|
|
98
98
|
return evaluation.then(function (result) {
|
|
99
99
|
result.changeNumber = split_1.getChangeNumber();
|
|
100
100
|
result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null;
|
|
101
|
+
result.track = splitJSON.trackImpressions;
|
|
101
102
|
return result;
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
else {
|
|
105
106
|
evaluation.changeNumber = split_1.getChangeNumber(); // Always sync and optional
|
|
106
107
|
evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null;
|
|
108
|
+
evaluation.track = splitJSON.trackImpressions;
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
111
|
return evaluation;
|
package/esm/listeners/browser.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { fromImpressionsCollector } from '../sync/submitters/impressionsSubmitter';
|
|
2
2
|
import { fromImpressionCountsCollector } from '../sync/submitters/impressionCountsSubmitter';
|
|
3
|
-
import { OPTIMIZED, DEBUG, NONE } from '../utils/constants';
|
|
4
3
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
5
4
|
import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
|
|
6
5
|
import { isConsentGranted } from '../consent';
|
|
@@ -60,10 +59,9 @@ var BrowserSignalListener = /** @class */ (function () {
|
|
|
60
59
|
var _a = this.settings.urls, events = _a.events, telemetry = _a.telemetry;
|
|
61
60
|
// Flush impressions & events data if there is user consent
|
|
62
61
|
if (isConsentGranted(this.settings)) {
|
|
63
|
-
var sim = this.settings.sync.impressionsMode;
|
|
64
62
|
var extraMetadata = {
|
|
65
63
|
// sim stands for Sync/Split Impressions Mode
|
|
66
|
-
sim:
|
|
64
|
+
sim: this.settings.sync.impressionsMode
|
|
67
65
|
};
|
|
68
66
|
this._flushData(events + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
|
|
69
67
|
this._flushData(events + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
|
|
@@ -25,7 +25,7 @@ function segmentsEventEmitterFactory(EventEmitter) {
|
|
|
25
25
|
/**
|
|
26
26
|
* Factory of readiness manager, which handles the ready / update event propagation.
|
|
27
27
|
*/
|
|
28
|
-
export function readinessManagerFactory(EventEmitter, settings, splits) {
|
|
28
|
+
export function readinessManagerFactory(EventEmitter, settings, splits, isShared) {
|
|
29
29
|
if (splits === void 0) { splits = splitsEventEmitterFactory(EventEmitter); }
|
|
30
30
|
var readyTimeout = settings.startup.readyTimeout;
|
|
31
31
|
var segments = segmentsEventEmitterFactory(EventEmitter);
|
|
@@ -51,22 +51,24 @@ export function readinessManagerFactory(EventEmitter, settings, splits) {
|
|
|
51
51
|
syncLastUpdate();
|
|
52
52
|
gate.emit(SDK_READY_TIMED_OUT, 'Split SDK emitted SDK_READY_TIMED_OUT event.');
|
|
53
53
|
}
|
|
54
|
-
var readyTimeoutId;
|
|
55
|
-
if (readyTimeout > 0) {
|
|
56
|
-
if (splits.hasInit)
|
|
57
|
-
readyTimeoutId = setTimeout(timeout, readyTimeout);
|
|
58
|
-
else
|
|
59
|
-
splits.initCallbacks.push(function () { readyTimeoutId = setTimeout(timeout, readyTimeout); });
|
|
60
|
-
}
|
|
61
54
|
// emit SDK_READY and SDK_UPDATE
|
|
62
55
|
var isReady = false;
|
|
63
56
|
splits.on(SDK_SPLITS_ARRIVED, checkIsReadyOrUpdate);
|
|
64
57
|
segments.on(SDK_SEGMENTS_ARRIVED, checkIsReadyOrUpdate);
|
|
65
58
|
var isDestroyed = false;
|
|
59
|
+
var readyTimeoutId;
|
|
60
|
+
function __init() {
|
|
61
|
+
isDestroyed = false;
|
|
62
|
+
if (readyTimeout > 0 && !isReady)
|
|
63
|
+
readyTimeoutId = setTimeout(timeout, readyTimeout);
|
|
64
|
+
}
|
|
65
|
+
splits.initCallbacks.push(__init);
|
|
66
|
+
if (splits.hasInit)
|
|
67
|
+
__init();
|
|
66
68
|
function checkIsReadyFromCache() {
|
|
67
69
|
isReadyFromCache = true;
|
|
68
70
|
// Don't emit SDK_READY_FROM_CACHE if SDK_READY has been emitted
|
|
69
|
-
if (!isReady) {
|
|
71
|
+
if (!isReady && !isDestroyed) {
|
|
70
72
|
try {
|
|
71
73
|
syncLastUpdate();
|
|
72
74
|
gate.emit(SDK_READY_FROM_CACHE);
|
|
@@ -78,6 +80,8 @@ export function readinessManagerFactory(EventEmitter, settings, splits) {
|
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
function checkIsReadyOrUpdate(diff) {
|
|
83
|
+
if (isDestroyed)
|
|
84
|
+
return;
|
|
81
85
|
if (isReady) {
|
|
82
86
|
try {
|
|
83
87
|
syncLastUpdate();
|
|
@@ -103,14 +107,12 @@ export function readinessManagerFactory(EventEmitter, settings, splits) {
|
|
|
103
107
|
}
|
|
104
108
|
}
|
|
105
109
|
}
|
|
106
|
-
var refCount = 1;
|
|
107
110
|
return {
|
|
108
111
|
splits: splits,
|
|
109
112
|
segments: segments,
|
|
110
113
|
gate: gate,
|
|
111
114
|
shared: function () {
|
|
112
|
-
|
|
113
|
-
return readinessManagerFactory(EventEmitter, settings, splits);
|
|
115
|
+
return readinessManagerFactory(EventEmitter, settings, splits, true);
|
|
114
116
|
},
|
|
115
117
|
// @TODO review/remove next methods when non-recoverable errors are reworked
|
|
116
118
|
// Called on consumer mode, when storage fails to connect
|
|
@@ -127,13 +129,9 @@ export function readinessManagerFactory(EventEmitter, settings, splits) {
|
|
|
127
129
|
destroy: function () {
|
|
128
130
|
isDestroyed = true;
|
|
129
131
|
syncLastUpdate();
|
|
130
|
-
segments.removeAllListeners();
|
|
131
|
-
gate.removeAllListeners();
|
|
132
132
|
clearTimeout(readyTimeoutId);
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
if (refCount === 0)
|
|
136
|
-
splits.removeAllListeners();
|
|
133
|
+
if (!isShared)
|
|
134
|
+
splits.hasInit = false;
|
|
137
135
|
},
|
|
138
136
|
isReady: function () { return isReady; },
|
|
139
137
|
isReadyFromCache: function () { return isReadyFromCache; },
|
package/esm/sdkClient/client.js
CHANGED
|
@@ -30,7 +30,7 @@ export function clientFactory(params) {
|
|
|
30
30
|
var queue = [];
|
|
31
31
|
var treatment = processEvaluation(evaluationResult, featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
32
32
|
impressionsTracker.track(queue, attributes);
|
|
33
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
33
|
+
stopTelemetryTracker(queue[0] && queue[0][0].label);
|
|
34
34
|
return treatment;
|
|
35
35
|
};
|
|
36
36
|
var evaluation = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -54,7 +54,7 @@ export function clientFactory(params) {
|
|
|
54
54
|
treatments[featureFlagName] = processEvaluation(evaluationResults[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
55
55
|
});
|
|
56
56
|
impressionsTracker.track(queue, attributes);
|
|
57
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
57
|
+
stopTelemetryTracker(queue[0] && queue[0][0].label);
|
|
58
58
|
return treatments;
|
|
59
59
|
};
|
|
60
60
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -80,7 +80,7 @@ export function clientFactory(params) {
|
|
|
80
80
|
treatments[featureFlagName] = processEvaluation(evaluations[featureFlagName], featureFlagName, key, attributes, withConfig, methodName, queue);
|
|
81
81
|
});
|
|
82
82
|
impressionsTracker.track(queue, attributes);
|
|
83
|
-
stopTelemetryTracker(queue[0] && queue[0].label);
|
|
83
|
+
stopTelemetryTracker(queue[0] && queue[0][0].label);
|
|
84
84
|
return treatments;
|
|
85
85
|
};
|
|
86
86
|
var evaluations = readinessManager.isReady() || readinessManager.isReadyFromCache() ?
|
|
@@ -103,19 +103,19 @@ export function clientFactory(params) {
|
|
|
103
103
|
function processEvaluation(evaluation, featureFlagName, key, attributes, withConfig, invokingMethodName, queue) {
|
|
104
104
|
var matchingKey = getMatching(key);
|
|
105
105
|
var bucketingKey = getBucketing(key);
|
|
106
|
-
var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a;
|
|
106
|
+
var treatment = evaluation.treatment, label = evaluation.label, changeNumber = evaluation.changeNumber, _a = evaluation.config, config = _a === void 0 ? null : _a, track = evaluation.track;
|
|
107
107
|
log.info(IMPRESSION, [featureFlagName, matchingKey, treatment, label]);
|
|
108
108
|
if (validateSplitExistence(log, readinessManager, featureFlagName, label, invokingMethodName)) {
|
|
109
109
|
log.info(IMPRESSION_QUEUEING);
|
|
110
|
-
queue.push({
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
queue.push([{
|
|
111
|
+
feature: featureFlagName,
|
|
112
|
+
keyName: matchingKey,
|
|
113
|
+
treatment: treatment,
|
|
114
|
+
time: Date.now(),
|
|
115
|
+
bucketingKey: bucketingKey,
|
|
116
|
+
label: label,
|
|
117
|
+
changeNumber: changeNumber,
|
|
118
|
+
}, track]);
|
|
119
119
|
}
|
|
120
120
|
if (withConfig) {
|
|
121
121
|
return {
|
|
@@ -47,7 +47,7 @@ export function sdkClientFactory(params, isSharedClient) {
|
|
|
47
47
|
releaseApiKey(settings.core.authorizationKey);
|
|
48
48
|
telemetryTracker.sessionLength();
|
|
49
49
|
signalListener && signalListener.stop();
|
|
50
|
-
uniqueKeysTracker
|
|
50
|
+
uniqueKeysTracker.stop();
|
|
51
51
|
}
|
|
52
52
|
// Stop background jobs
|
|
53
53
|
syncManager && syncManager.stop();
|
package/esm/sdkFactory/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
|
|
|
11
11
|
import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
|
|
12
12
|
import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
|
|
13
13
|
import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
|
|
14
|
-
import {
|
|
14
|
+
import { DEBUG, OPTIMIZED } from '../utils/constants';
|
|
15
15
|
/**
|
|
16
16
|
* Modular SDK factory
|
|
17
17
|
*/
|
|
@@ -48,19 +48,14 @@ export function sdkFactory(params) {
|
|
|
48
48
|
var telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
49
49
|
var integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings: settings, storage: storage, telemetryTracker: telemetryTracker });
|
|
50
50
|
var observer = impressionsObserverFactory();
|
|
51
|
-
var uniqueKeysTracker =
|
|
52
|
-
var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
break;
|
|
60
|
-
default:
|
|
61
|
-
strategy = strategyDebugFactory(observer);
|
|
62
|
-
}
|
|
63
|
-
var impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
51
|
+
var uniqueKeysTracker = uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory());
|
|
52
|
+
var noneStrategy = strategyNoneFactory(storage.impressionCounts, uniqueKeysTracker);
|
|
53
|
+
var strategy = impressionsMode === OPTIMIZED ?
|
|
54
|
+
strategyOptimizedFactory(observer, storage.impressionCounts) :
|
|
55
|
+
impressionsMode === DEBUG ?
|
|
56
|
+
strategyDebugFactory(observer) :
|
|
57
|
+
noneStrategy;
|
|
58
|
+
var impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, noneStrategy, strategy, whenInit, integrationsManager, storage.telemetry);
|
|
64
59
|
var eventTracker = eventTrackerFactory(settings, storage.events, whenInit, integrationsManager, storage.telemetry);
|
|
65
60
|
// splitApi is used by SyncManager and Browser signal listener
|
|
66
61
|
var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
@@ -79,7 +74,7 @@ export function sdkFactory(params) {
|
|
|
79
74
|
// We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
|
|
80
75
|
validateAndTrackApiKey(log, settings.core.authorizationKey);
|
|
81
76
|
readiness.init();
|
|
82
|
-
uniqueKeysTracker
|
|
77
|
+
uniqueKeysTracker.start();
|
|
83
78
|
syncManager && syncManager.start();
|
|
84
79
|
signalListener && signalListener.start();
|
|
85
80
|
initCallbacks.forEach(function (cb) { return cb(); });
|
|
@@ -99,6 +94,7 @@ export function sdkFactory(params) {
|
|
|
99
94
|
Logger: createLoggerAPI(log),
|
|
100
95
|
settings: settings,
|
|
101
96
|
destroy: function () {
|
|
97
|
+
hasInit = false;
|
|
102
98
|
return Promise.all(Object.keys(clients).map(function (key) { return clients[key].destroy(); })).then(function () { });
|
|
103
99
|
}
|
|
104
100
|
}, extraProps && extraProps(ctx), lazyInit ? { init: init } : init());
|
package/esm/sdkManager/index.js
CHANGED
|
@@ -25,7 +25,8 @@ function objectToView(splitObject) {
|
|
|
25
25
|
treatments: collectTreatments(splitObject),
|
|
26
26
|
configs: splitObject.configurations || {},
|
|
27
27
|
sets: splitObject.sets || [],
|
|
28
|
-
defaultTreatment: splitObject.defaultTreatment
|
|
28
|
+
defaultTreatment: splitObject.defaultTreatment,
|
|
29
|
+
trackImpressions: splitObject.trackImpressions !== false
|
|
29
30
|
};
|
|
30
31
|
}
|
|
31
32
|
function objectsToViews(splitObjects) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { ERROR_HTTP, ERROR_CLIENT_CANNOT_GET_READY } from '../logger/constants';
|
|
3
|
-
import { decorateHeaders } from './decorateHeaders';
|
|
3
|
+
import { decorateHeaders, removeNonISO88591 } from './decorateHeaders';
|
|
4
4
|
var messageNoFetch = 'Global fetch API is not available.';
|
|
5
5
|
/**
|
|
6
6
|
* Factory of Split HTTP clients, which are HTTP clients with predefined headers for Split endpoints.
|
|
@@ -25,7 +25,7 @@ export function splitHttpClientFactory(settings, _a) {
|
|
|
25
25
|
if (ip)
|
|
26
26
|
commonHeaders['SplitSDKMachineIP'] = ip;
|
|
27
27
|
if (hostname)
|
|
28
|
-
commonHeaders['SplitSDKMachineName'] = hostname;
|
|
28
|
+
commonHeaders['SplitSDKMachineName'] = removeNonISO88591(hostname);
|
|
29
29
|
return function httpClient(url, reqOpts, latencyTracker, logErrorsAsInfo) {
|
|
30
30
|
if (reqOpts === void 0) { reqOpts = {}; }
|
|
31
31
|
if (latencyTracker === void 0) { latencyTracker = function () { }; }
|
|
@@ -6,12 +6,10 @@ import { KeyBuilderCS, myLargeSegmentsKeyBuilder } from '../KeyBuilderCS';
|
|
|
6
6
|
import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
|
|
7
7
|
import { SplitsCacheInLocal } from './SplitsCacheInLocal';
|
|
8
8
|
import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
|
|
9
|
-
import { MySegmentsCacheInMemory } from '../inMemory/MySegmentsCacheInMemory';
|
|
10
|
-
import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
|
|
11
9
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
12
10
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
13
11
|
import { LOG_PREFIX } from './constants';
|
|
14
|
-
import {
|
|
12
|
+
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
15
13
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
16
14
|
import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
|
|
17
15
|
import { getMatching } from '../../utils/key';
|
|
@@ -27,7 +25,7 @@ export function InLocalStorage(options) {
|
|
|
27
25
|
params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
|
|
28
26
|
return InMemoryStorageCSFactory(params);
|
|
29
27
|
}
|
|
30
|
-
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize
|
|
28
|
+
var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
|
|
31
29
|
var matchingKey = getMatching(settings.core.key);
|
|
32
30
|
var keys = new KeyBuilderCS(prefix, matchingKey);
|
|
33
31
|
var expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
|
|
@@ -39,20 +37,11 @@ export function InLocalStorage(options) {
|
|
|
39
37
|
segments: segments,
|
|
40
38
|
largeSegments: largeSegments,
|
|
41
39
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
42
|
-
impressionCounts:
|
|
40
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
43
41
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
44
42
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
45
|
-
uniqueKeys:
|
|
46
|
-
destroy: function () {
|
|
47
|
-
var _a;
|
|
48
|
-
this.splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
49
|
-
this.segments = new MySegmentsCacheInMemory();
|
|
50
|
-
this.largeSegments = new MySegmentsCacheInMemory();
|
|
51
|
-
this.impressions.clear();
|
|
52
|
-
this.impressionCounts && this.impressionCounts.clear();
|
|
53
|
-
this.events.clear();
|
|
54
|
-
(_a = this.uniqueKeys) === null || _a === void 0 ? void 0 : _a.clear();
|
|
55
|
-
},
|
|
43
|
+
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
44
|
+
destroy: function () { },
|
|
56
45
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
|
|
57
46
|
shared: function (matchingKey) {
|
|
58
47
|
return {
|
|
@@ -63,11 +52,8 @@ export function InLocalStorage(options) {
|
|
|
63
52
|
impressionCounts: this.impressionCounts,
|
|
64
53
|
events: this.events,
|
|
65
54
|
telemetry: this.telemetry,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
this.segments = new MySegmentsCacheInMemory();
|
|
69
|
-
this.largeSegments = new MySegmentsCacheInMemory();
|
|
70
|
-
}
|
|
55
|
+
uniqueKeys: this.uniqueKeys,
|
|
56
|
+
destroy: function () { }
|
|
71
57
|
};
|
|
72
58
|
},
|
|
73
59
|
};
|
|
@@ -3,7 +3,7 @@ import { SegmentsCacheInMemory } from './SegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import {
|
|
6
|
+
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
9
9
|
/**
|
|
@@ -12,26 +12,18 @@ import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
|
12
12
|
* @param params - parameters required by EventsCacheSync
|
|
13
13
|
*/
|
|
14
14
|
export function InMemoryStorageFactory(params) {
|
|
15
|
-
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize,
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
16
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
17
17
|
var segments = new SegmentsCacheInMemory();
|
|
18
18
|
var storage = {
|
|
19
19
|
splits: splits,
|
|
20
20
|
segments: segments,
|
|
21
21
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
22
|
-
impressionCounts:
|
|
22
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
23
23
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
24
24
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
25
|
-
uniqueKeys:
|
|
26
|
-
|
|
27
|
-
destroy: function () {
|
|
28
|
-
this.splits.clear();
|
|
29
|
-
this.segments.clear();
|
|
30
|
-
this.impressions.clear();
|
|
31
|
-
this.impressionCounts && this.impressionCounts.clear();
|
|
32
|
-
this.events.clear();
|
|
33
|
-
this.uniqueKeys && this.uniqueKeys.clear();
|
|
34
|
-
}
|
|
25
|
+
uniqueKeys: new UniqueKeysCacheInMemory(),
|
|
26
|
+
destroy: function () { }
|
|
35
27
|
};
|
|
36
28
|
// @TODO revisit storage logic in localhost mode
|
|
37
29
|
// No tracking data in localhost mode to avoid memory leaks
|
|
@@ -3,7 +3,7 @@ import { MySegmentsCacheInMemory } from './MySegmentsCacheInMemory';
|
|
|
3
3
|
import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
6
|
-
import {
|
|
6
|
+
import { LOCALHOST_MODE, STORAGE_MEMORY } from '../../utils/constants';
|
|
7
7
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
8
8
|
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
9
9
|
/**
|
|
@@ -12,7 +12,7 @@ import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
|
12
12
|
* @param params - parameters required by EventsCacheSync
|
|
13
13
|
*/
|
|
14
14
|
export function InMemoryStorageCSFactory(params) {
|
|
15
|
-
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize,
|
|
15
|
+
var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, __splitFiltersValidation = _a.sync.__splitFiltersValidation;
|
|
16
16
|
var splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
17
17
|
var segments = new MySegmentsCacheInMemory();
|
|
18
18
|
var largeSegments = new MySegmentsCacheInMemory();
|
|
@@ -21,20 +21,11 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
21
21
|
segments: segments,
|
|
22
22
|
largeSegments: largeSegments,
|
|
23
23
|
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
24
|
-
impressionCounts:
|
|
24
|
+
impressionCounts: new ImpressionCountsCacheInMemory(),
|
|
25
25
|
events: new EventsCacheInMemory(eventsQueueSize),
|
|
26
26
|
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
27
|
-
uniqueKeys:
|
|
28
|
-
|
|
29
|
-
destroy: function () {
|
|
30
|
-
this.splits.clear();
|
|
31
|
-
this.segments.clear();
|
|
32
|
-
this.largeSegments.clear();
|
|
33
|
-
this.impressions.clear();
|
|
34
|
-
this.impressionCounts && this.impressionCounts.clear();
|
|
35
|
-
this.events.clear();
|
|
36
|
-
this.uniqueKeys && this.uniqueKeys.clear();
|
|
37
|
-
},
|
|
27
|
+
uniqueKeys: new UniqueKeysCacheInMemoryCS(),
|
|
28
|
+
destroy: function () { },
|
|
38
29
|
// When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
|
|
39
30
|
shared: function () {
|
|
40
31
|
return {
|
|
@@ -45,12 +36,8 @@ export function InMemoryStorageCSFactory(params) {
|
|
|
45
36
|
impressionCounts: this.impressionCounts,
|
|
46
37
|
events: this.events,
|
|
47
38
|
telemetry: this.telemetry,
|
|
48
|
-
|
|
49
|
-
destroy: function () {
|
|
50
|
-
this.splits = new SplitsCacheInMemory(__splitFiltersValidation);
|
|
51
|
-
this.segments.clear();
|
|
52
|
-
this.largeSegments.clear();
|
|
53
|
-
}
|
|
39
|
+
uniqueKeys: this.uniqueKeys,
|
|
40
|
+
destroy: function () { }
|
|
54
41
|
};
|
|
55
42
|
},
|
|
56
43
|
};
|