@splitsoftware/splitio-commons 1.6.2-rc.9 → 1.7.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 +3 -1
- package/cjs/consent/sdkUserConsent.js +2 -2
- package/cjs/listeners/browser.js +11 -12
- package/cjs/logger/constants.js +2 -1
- package/cjs/sdkClient/sdkClient.js +3 -1
- package/cjs/sdkFactory/index.js +26 -26
- package/cjs/services/splitApi.js +20 -0
- package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/KeyBuilderSS.js +10 -43
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/cjs/storages/inLocalStorage/index.js +17 -9
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +13 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +13 -6
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +60 -35
- package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +72 -0
- package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +76 -0
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +85 -0
- package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +4 -4
- package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +71 -0
- package/cjs/storages/inRedis/constants.js +4 -1
- package/cjs/storages/inRedis/index.js +20 -3
- package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +81 -0
- package/cjs/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +4 -4
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +61 -0
- package/cjs/storages/pluggable/inMemoryWrapper.js +8 -6
- package/cjs/storages/pluggable/index.js +38 -9
- package/cjs/storages/utils.js +73 -0
- package/cjs/sync/submitters/submitterManager.js +3 -0
- package/cjs/sync/submitters/telemetrySubmitter.js +5 -40
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +27 -0
- package/cjs/trackers/impressionObserver/utils.js +1 -17
- package/cjs/trackers/impressionsTracker.js +22 -41
- package/cjs/trackers/strategy/strategyDebug.js +25 -0
- package/cjs/trackers/strategy/strategyNone.js +29 -0
- package/cjs/trackers/strategy/strategyOptimized.js +35 -0
- package/cjs/trackers/uniqueKeysTracker.js +38 -0
- package/cjs/utils/constants/index.js +4 -2
- package/cjs/utils/redis/RedisMock.js +31 -0
- package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +7 -1
- package/esm/consent/sdkUserConsent.js +2 -2
- package/esm/listeners/browser.js +12 -13
- package/esm/logger/constants.js +1 -0
- package/esm/sdkClient/sdkClient.js +3 -1
- package/esm/sdkFactory/index.js +26 -26
- package/esm/services/splitApi.js +20 -0
- package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/KeyBuilderSS.js +7 -37
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/esm/storages/inLocalStorage/index.js +18 -10
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/esm/storages/inMemory/InMemoryStorage.js +14 -7
- package/esm/storages/inMemory/InMemoryStorageCS.js +14 -7
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +61 -36
- package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +68 -0
- package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +73 -0
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +82 -0
- package/esm/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +1 -1
- package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +68 -0
- package/esm/storages/inRedis/constants.js +3 -0
- package/esm/storages/inRedis/index.js +21 -4
- package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +78 -0
- package/esm/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/esm/storages/pluggable/TelemetryCachePluggable.js +1 -1
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +58 -0
- package/esm/storages/pluggable/inMemoryWrapper.js +8 -6
- package/esm/storages/pluggable/index.js +39 -10
- package/esm/storages/utils.js +65 -0
- package/esm/sync/submitters/submitterManager.js +3 -0
- package/esm/sync/submitters/telemetrySubmitter.js +5 -39
- package/esm/sync/submitters/uniqueKeysSubmitter.js +23 -0
- package/esm/trackers/impressionObserver/utils.js +1 -15
- package/esm/trackers/impressionsTracker.js +22 -41
- package/esm/trackers/strategy/strategyDebug.js +21 -0
- package/esm/trackers/strategy/strategyNone.js +25 -0
- package/esm/trackers/strategy/strategyOptimized.js +31 -0
- package/esm/trackers/uniqueKeysTracker.js +34 -0
- package/esm/utils/constants/index.js +2 -0
- package/esm/utils/redis/RedisMock.js +28 -0
- package/esm/utils/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +7 -1
- package/package.json +1 -2
- package/src/consent/sdkUserConsent.ts +2 -2
- package/src/listeners/browser.ts +12 -15
- package/src/logger/constants.ts +1 -0
- package/src/sdkClient/sdkClient.ts +3 -1
- package/src/sdkFactory/index.ts +29 -31
- package/src/sdkFactory/types.ts +7 -4
- package/src/services/splitApi.ts +22 -0
- package/src/services/types.ts +6 -0
- package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/KeyBuilderSS.ts +9 -43
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -1
- package/src/storages/inLocalStorage/index.ts +18 -10
- package/src/storages/inMemory/AttributesCacheInMemory.ts +7 -7
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +16 -1
- package/src/storages/inMemory/InMemoryStorage.ts +14 -7
- package/src/storages/inMemory/InMemoryStorageCS.ts +14 -7
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +69 -34
- package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +80 -0
- package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +86 -0
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +95 -0
- package/src/storages/inRedis/ImpressionsCacheInRedis.ts +2 -22
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +3 -2
- package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +77 -0
- package/src/storages/inRedis/constants.ts +3 -0
- package/src/storages/inRedis/index.ts +18 -5
- package/src/storages/pluggable/ImpressionCountsCachePluggable.ts +92 -0
- package/src/storages/pluggable/ImpressionsCachePluggable.ts +3 -23
- package/src/storages/pluggable/TelemetryCachePluggable.ts +3 -2
- package/src/storages/pluggable/UniqueKeysCachePluggable.ts +67 -0
- package/src/storages/pluggable/inMemoryWrapper.ts +6 -6
- package/src/storages/pluggable/index.ts +41 -9
- package/src/storages/types.ts +56 -55
- package/src/storages/utils.ts +78 -0
- package/src/sync/submitters/submitter.ts +2 -2
- package/src/sync/submitters/submitterManager.ts +2 -0
- package/src/sync/submitters/telemetrySubmitter.ts +8 -43
- package/src/sync/submitters/types.ts +29 -27
- package/src/sync/submitters/uniqueKeysSubmitter.ts +36 -0
- package/src/trackers/impressionObserver/utils.ts +1 -16
- package/src/trackers/impressionsTracker.ts +25 -46
- package/src/trackers/strategy/strategyDebug.ts +28 -0
- package/src/trackers/strategy/strategyNone.ts +34 -0
- package/src/trackers/strategy/strategyOptimized.ts +42 -0
- package/src/trackers/types.ts +28 -0
- package/src/trackers/uniqueKeysTracker.ts +48 -0
- package/src/types.ts +1 -1
- package/src/utils/constants/index.ts +2 -0
- package/src/utils/redis/RedisMock.ts +33 -0
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +5 -1
- package/types/logger/constants.d.ts +1 -0
- package/types/sdkFactory/types.d.ts +4 -2
- package/types/services/types.d.ts +4 -0
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/KeyBuilderSS.d.ts +3 -3
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +0 -1
- package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +5 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +20 -9
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +35 -0
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +35 -0
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +16 -0
- package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +0 -1
- package/types/storages/inRedis/constants.d.ts +3 -0
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +21 -0
- package/types/storages/pluggable/ImpressionCountsCachePluggable.d.ts +16 -0
- package/types/storages/pluggable/ImpressionsCachePluggable.d.ts +1 -2
- package/types/storages/pluggable/UniqueKeysCachePluggable.d.ts +20 -0
- package/types/storages/types.d.ts +39 -38
- package/types/storages/utils.d.ts +8 -0
- package/types/sync/submitters/submitter.d.ts +2 -2
- package/types/sync/submitters/telemetrySubmitter.d.ts +2 -10
- package/types/sync/submitters/types.d.ts +27 -7
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +5 -0
- package/types/trackers/impressionObserver/utils.d.ts +0 -8
- package/types/trackers/impressionsTracker.d.ts +4 -6
- package/types/trackers/strategy/strategyDebug.d.ts +9 -0
- package/types/trackers/strategy/strategyNone.d.ts +10 -0
- package/types/trackers/strategy/strategyOptimized.d.ts +11 -0
- package/types/trackers/types.d.ts +23 -0
- package/types/trackers/uniqueKeysTracker.d.ts +13 -0
- package/types/types.d.ts +1 -1
- package/types/utils/constants/index.d.ts +2 -0
- package/types/utils/redis/RedisMock.d.ts +4 -0
- package/cjs/storages/metadataBuilder.js +0 -12
- package/esm/storages/metadataBuilder.js +0 -8
- package/src/storages/metadataBuilder.ts +0 -11
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE
|
|
1
|
+
import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../../utils/constants';
|
|
2
2
|
import { ISettings } from '../../types';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* Checks if impressions previous time should be added or not.
|
|
6
|
-
*/
|
|
7
|
-
export function shouldAddPt(settings: ISettings) {
|
|
8
|
-
return [PRODUCER_MODE, STANDALONE_MODE, CONSUMER_PARTIAL_MODE].indexOf(settings.mode) > -1 ? true : false;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Checks if it should dedupe impressions or not.
|
|
13
|
-
*/
|
|
14
|
-
export function shouldBeOptimized(settings: ISettings) {
|
|
15
|
-
if (!shouldAddPt(settings)) return false;
|
|
16
|
-
return settings.sync.impressionsMode === OPTIMIZED ? true : false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
4
|
/**
|
|
20
5
|
* Storage is async if mode is consumer or partial consumer
|
|
21
6
|
*/
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { IImpressionsHandler, IImpressionsTracker } from './types';
|
|
3
|
+
import { IImpressionsCacheBase, ITelemetryCacheSync, ITelemetryCacheAsync } from '../storages/types';
|
|
4
|
+
import { IImpressionsHandler, IImpressionsTracker, IStrategy } from './types';
|
|
6
5
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
7
|
-
import { IImpressionObserver } from './impressionObserver/types';
|
|
8
6
|
import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants';
|
|
9
7
|
import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
|
|
10
8
|
|
|
@@ -15,18 +13,14 @@ import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
|
|
|
15
13
|
* @param metadata runtime metadata (ip, hostname and version)
|
|
16
14
|
* @param impressionListener optional impression listener
|
|
17
15
|
* @param integrationsManager optional integrations manager
|
|
18
|
-
* @param
|
|
19
|
-
* @param countsCache optional cache to save impressions count. If provided, impressions will be deduped (OPTIMIZED mode)
|
|
16
|
+
* @param strategy strategy for impressions tracking.
|
|
20
17
|
*/
|
|
21
18
|
export function impressionsTrackerFactory(
|
|
22
19
|
settings: ISettings,
|
|
23
20
|
impressionsCache: IImpressionsCacheBase,
|
|
21
|
+
strategy: IStrategy,
|
|
24
22
|
integrationsManager?: IImpressionsHandler,
|
|
25
|
-
|
|
26
|
-
observer?: IImpressionObserver,
|
|
27
|
-
// if countsCache is provided, it implies `isOptimized` flag (i.e., if impressions should be deduped or not)
|
|
28
|
-
countsCache?: IImpressionCountsCacheSync,
|
|
29
|
-
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync
|
|
23
|
+
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
30
24
|
): IImpressionsTracker {
|
|
31
25
|
|
|
32
26
|
const { log, impressionListener, runtime: { ip, hostname }, version } = settings;
|
|
@@ -36,51 +30,36 @@ export function impressionsTrackerFactory(
|
|
|
36
30
|
if (settings.userConsent === CONSENT_DECLINED) return;
|
|
37
31
|
|
|
38
32
|
const impressionsCount = impressions.length;
|
|
33
|
+
const { impressionsToStore, impressionsToListener, deduped } = strategy.process(impressions);
|
|
39
34
|
|
|
40
|
-
const
|
|
41
|
-
// Wraps impressions to store and adds previousTime if it corresponds
|
|
42
|
-
impressions.forEach((impression) => {
|
|
43
|
-
if (observer) {
|
|
44
|
-
// Adds previous time if it is enabled
|
|
45
|
-
impression.pt = observer.testAndSet(impression);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const now = Date.now();
|
|
49
|
-
if (countsCache) {
|
|
50
|
-
// Increments impression counter per featureName
|
|
51
|
-
countsCache.track(impression.feature, now, 1);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Checks if the impression should be added in queue to be sent
|
|
55
|
-
if (!countsCache || !impression.pt || impression.pt < truncateTimeFrame(now)) {
|
|
56
|
-
impressionsToStore.push(impression);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
35
|
+
const impressionsToListenerCount = impressionsToListener.length;
|
|
59
36
|
|
|
60
|
-
|
|
37
|
+
if ( impressionsToStore.length>0 ){
|
|
38
|
+
const res = impressionsCache.track(impressionsToStore);
|
|
61
39
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
40
|
+
// If we're on an async storage, handle error and log it.
|
|
41
|
+
if (thenable(res)) {
|
|
42
|
+
res.then(() => {
|
|
43
|
+
log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
|
|
44
|
+
}).catch(err => {
|
|
45
|
+
log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
|
|
46
|
+
});
|
|
47
|
+
} else {
|
|
48
|
+
// Record when impressionsCache is sync only (standalone mode)
|
|
49
|
+
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
50
|
+
if (telemetryCache) {
|
|
51
|
+
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED, impressionsToStore.length);
|
|
52
|
+
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED, deduped);
|
|
53
|
+
}
|
|
75
54
|
}
|
|
76
55
|
}
|
|
77
56
|
|
|
78
57
|
// @TODO next block might be handled by the integration manager. In that case, the metadata object doesn't need to be passed in the constructor
|
|
79
58
|
if (impressionListener || integrationsManager) {
|
|
80
|
-
for (let i = 0; i <
|
|
59
|
+
for (let i = 0; i < impressionsToListenerCount; i++) {
|
|
81
60
|
const impressionData: SplitIO.ImpressionData = {
|
|
82
61
|
// copy of impression, to avoid unexpected behaviour if modified by integrations or impressionListener
|
|
83
|
-
impression: objectAssign({},
|
|
62
|
+
impression: objectAssign({}, impressionsToListener[i]),
|
|
84
63
|
attributes,
|
|
85
64
|
ip,
|
|
86
65
|
hostname,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ImpressionDTO } from '../../types';
|
|
2
|
+
import { IImpressionObserver } from '../impressionObserver/types';
|
|
3
|
+
import { IStrategy } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Debug strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
7
|
+
*
|
|
8
|
+
* @param impressionsObserver impression observer. Previous time (pt property) is included in impression instances
|
|
9
|
+
* @returns IStrategyResult
|
|
10
|
+
*/
|
|
11
|
+
export function strategyDebugFactory(
|
|
12
|
+
impressionsObserver: IImpressionObserver
|
|
13
|
+
): IStrategy {
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
process(impressions: ImpressionDTO[]) {
|
|
17
|
+
impressions.forEach((impression) => {
|
|
18
|
+
// Adds previous time if it is enabled
|
|
19
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
20
|
+
});
|
|
21
|
+
return {
|
|
22
|
+
impressionsToStore: impressions,
|
|
23
|
+
impressionsToListener: impressions,
|
|
24
|
+
deduped: 0
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { IImpressionCountsCacheBase } from '../../storages/types';
|
|
2
|
+
import { ImpressionDTO } from '../../types';
|
|
3
|
+
import { IStrategy, IUniqueKeysTracker } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* None strategy for impressions tracker.
|
|
7
|
+
*
|
|
8
|
+
* @param impressionsCounter cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
9
|
+
* @param uniqueKeysTracker unique keys tracker in charge of tracking the unique keys per split.
|
|
10
|
+
* @returns IStrategyResult
|
|
11
|
+
*/
|
|
12
|
+
export function strategyNoneFactory(
|
|
13
|
+
impressionsCounter: IImpressionCountsCacheBase,
|
|
14
|
+
uniqueKeysTracker: IUniqueKeysTracker
|
|
15
|
+
): IStrategy {
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
process(impressions: ImpressionDTO[]) {
|
|
19
|
+
impressions.forEach((impression) => {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
// Increments impression counter per featureName
|
|
22
|
+
impressionsCounter.track(impression.feature, now, 1);
|
|
23
|
+
// Keep track by unique key
|
|
24
|
+
uniqueKeysTracker.track(impression.keyName, impression.feature);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
impressionsToStore: [],
|
|
29
|
+
impressionsToListener: impressions,
|
|
30
|
+
deduped: 0
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { IImpressionCountsCacheBase } from '../../storages/types';
|
|
2
|
+
import { ImpressionDTO } from '../../types';
|
|
3
|
+
import { truncateTimeFrame } from '../../utils/time';
|
|
4
|
+
import { IImpressionObserver } from '../impressionObserver/types';
|
|
5
|
+
import { IStrategy } from '../types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Optimized strategy for impressions tracker. Wraps impressions to store and adds previousTime if it corresponds
|
|
9
|
+
*
|
|
10
|
+
* @param impressionsObserver impression observer. previous time (pt property) is included in impression instances
|
|
11
|
+
* @param impressionsCounter cache to save impressions count. impressions will be deduped (OPTIMIZED mode)
|
|
12
|
+
* @returns IStrategyResult
|
|
13
|
+
*/
|
|
14
|
+
export function strategyOptimizedFactory(
|
|
15
|
+
impressionsObserver: IImpressionObserver,
|
|
16
|
+
impressionsCounter: IImpressionCountsCacheBase,
|
|
17
|
+
): IStrategy {
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
process(impressions: ImpressionDTO[]) {
|
|
21
|
+
const impressionsToStore: ImpressionDTO[] = [];
|
|
22
|
+
impressions.forEach((impression) => {
|
|
23
|
+
impression.pt = impressionsObserver.testAndSet(impression);
|
|
24
|
+
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
|
|
27
|
+
// Increments impression counter per featureName
|
|
28
|
+
if (impression.pt) impressionsCounter.track(impression.feature, now, 1);
|
|
29
|
+
|
|
30
|
+
// Checks if the impression should be added in queue to be sent
|
|
31
|
+
if (!impression.pt || impression.pt < truncateTimeFrame(now)) {
|
|
32
|
+
impressionsToStore.push(impression);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
return {
|
|
36
|
+
impressionsToStore: impressionsToStore,
|
|
37
|
+
impressionsToListener: impressions,
|
|
38
|
+
deduped: impressions.length - impressionsToStore.length
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
package/src/trackers/types.ts
CHANGED
|
@@ -46,3 +46,31 @@ export interface ITelemetryTracker {
|
|
|
46
46
|
*/
|
|
47
47
|
addTag(tag: string): void
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
export interface IFilterAdapter {
|
|
51
|
+
add(key: string, featureName: string): boolean;
|
|
52
|
+
contains(key: string, featureName: string): boolean;
|
|
53
|
+
clear(): void;
|
|
54
|
+
refreshRate?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface IImpressionSenderAdapter {
|
|
58
|
+
recordUniqueKeys(data: Object): void;
|
|
59
|
+
recordImpressionCounts(data: Object): void
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Unique keys tracker */
|
|
63
|
+
export interface IUniqueKeysTracker {
|
|
64
|
+
stop(): void;
|
|
65
|
+
track(key: string, featureName: string): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface IStrategyResult {
|
|
69
|
+
impressionsToStore: ImpressionDTO[],
|
|
70
|
+
impressionsToListener: ImpressionDTO[],
|
|
71
|
+
deduped: number
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface IStrategy {
|
|
75
|
+
process(impressions: ImpressionDTO[]): IStrategyResult
|
|
76
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { LOG_PREFIX_UNIQUE_KEYS_TRACKER } from '../logger/constants';
|
|
2
|
+
import { ILogger } from '../logger/types';
|
|
3
|
+
import { IUniqueKeysCacheBase } from '../storages/types';
|
|
4
|
+
import { IFilterAdapter, IUniqueKeysTracker } from './types';
|
|
5
|
+
|
|
6
|
+
const noopFilterAdapter = {
|
|
7
|
+
add() { return true; },
|
|
8
|
+
contains() { return true; },
|
|
9
|
+
clear() { }
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Trackes uniques keys
|
|
14
|
+
* Unique Keys Tracker will be in charge of checking if the MTK was already sent to the BE in the last period
|
|
15
|
+
* or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
|
|
16
|
+
*
|
|
17
|
+
* @param log Logger instance
|
|
18
|
+
* @param uniqueKeysCache cache to save unique keys
|
|
19
|
+
* @param filterAdapter filter adapter
|
|
20
|
+
*/
|
|
21
|
+
export function uniqueKeysTrackerFactory(
|
|
22
|
+
log: ILogger,
|
|
23
|
+
uniqueKeysCache: IUniqueKeysCacheBase,
|
|
24
|
+
filterAdapter: IFilterAdapter = noopFilterAdapter,
|
|
25
|
+
): IUniqueKeysTracker {
|
|
26
|
+
let intervalId: any;
|
|
27
|
+
|
|
28
|
+
if (filterAdapter.refreshRate) {
|
|
29
|
+
intervalId = setInterval(filterAdapter.clear, filterAdapter.refreshRate);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
|
|
34
|
+
track(key: string, featureName: string): void {
|
|
35
|
+
if (!filterAdapter.add(key, featureName)) {
|
|
36
|
+
log.debug(`${LOG_PREFIX_UNIQUE_KEYS_TRACKER}The feature ${featureName} and key ${key} exist in the filter`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
uniqueKeysCache.track(key, featureName);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
stop(): void {
|
|
43
|
+
clearInterval(intervalId);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -718,7 +718,7 @@ export namespace SplitIO {
|
|
|
718
718
|
* ImpressionsMode type
|
|
719
719
|
* @typedef {string} ImpressionsMode
|
|
720
720
|
*/
|
|
721
|
-
export type ImpressionsMode = 'OPTIMIZED' | 'DEBUG'
|
|
721
|
+
export type ImpressionsMode = 'OPTIMIZED' | 'DEBUG' | 'NONE'
|
|
722
722
|
/**
|
|
723
723
|
* Defines the format of Split data to preload on the factory storage (cache).
|
|
724
724
|
*/
|
|
@@ -19,6 +19,7 @@ export const SPLIT_EVENT = 'EVENT';
|
|
|
19
19
|
// Impression collection modes
|
|
20
20
|
export const DEBUG = 'DEBUG';
|
|
21
21
|
export const OPTIMIZED = 'OPTIMIZED';
|
|
22
|
+
export const NONE = 'NONE';
|
|
22
23
|
|
|
23
24
|
// SDK Modes
|
|
24
25
|
export const LOCALHOST_MODE: SDKMode = 'localhost';
|
|
@@ -49,6 +50,7 @@ export const CONSUMER_PARTIAL_ENUM = 2;
|
|
|
49
50
|
|
|
50
51
|
export const OPTIMIZED_ENUM = 0;
|
|
51
52
|
export const DEBUG_ENUM = 1;
|
|
53
|
+
export const NONE_ENUM = 2;
|
|
52
54
|
|
|
53
55
|
export const SPLITS = 'sp';
|
|
54
56
|
export const IMPRESSIONS = 'im';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
function identityFunction(data: any): any {
|
|
3
|
+
return data;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function asyncFunction(data: any): Promise<any> {
|
|
7
|
+
return Promise.resolve(data);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const IDENTITY_METHODS: string[] = [];
|
|
11
|
+
const ASYNC_METHODS = ['rpush', 'hincrby'];
|
|
12
|
+
const PIPELINE_METHODS = ['rpush', 'hincrby'];
|
|
13
|
+
|
|
14
|
+
export class RedisMock {
|
|
15
|
+
|
|
16
|
+
private pipelineMethods: any = { exec: jest.fn(asyncFunction) }
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
IDENTITY_METHODS.forEach(method => {
|
|
20
|
+
this[method] = jest.fn(identityFunction);
|
|
21
|
+
});
|
|
22
|
+
ASYNC_METHODS.forEach(method => {
|
|
23
|
+
this[method] = jest.fn(asyncFunction);
|
|
24
|
+
});
|
|
25
|
+
PIPELINE_METHODS.forEach(method => {
|
|
26
|
+
this.pipelineMethods[method] = this[method];
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
this.pipeline = jest.fn(() => {return this.pipelineMethods;});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
|
|
2
2
|
import { ILogger } from '../../logger/types';
|
|
3
3
|
import { SplitIO } from '../../types';
|
|
4
|
-
import { DEBUG, OPTIMIZED } from '../constants';
|
|
4
|
+
import { DEBUG, OPTIMIZED, NONE } from '../constants';
|
|
5
5
|
import { stringToUpperCase } from '../lang';
|
|
6
6
|
|
|
7
7
|
export function validImpressionsMode(log: ILogger, impressionsMode: any): SplitIO.ImpressionsMode {
|
|
8
8
|
impressionsMode = stringToUpperCase(impressionsMode);
|
|
9
9
|
|
|
10
|
-
if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1) return impressionsMode;
|
|
10
|
+
if ([DEBUG, OPTIMIZED, NONE].indexOf(impressionsMode) > -1) return impressionsMode;
|
|
11
11
|
|
|
12
|
-
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED], OPTIMIZED]);
|
|
12
|
+
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED, NONE], OPTIMIZED]);
|
|
13
13
|
return OPTIMIZED;
|
|
14
14
|
}
|
|
@@ -153,8 +153,8 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
153
153
|
if (storage) withDefaults.storage = storage(withDefaults);
|
|
154
154
|
|
|
155
155
|
// Validate key and TT (for client-side)
|
|
156
|
+
const maybeKey = withDefaults.core.key;
|
|
156
157
|
if (validationParams.acceptKey) {
|
|
157
|
-
const maybeKey = withDefaults.core.key;
|
|
158
158
|
// Although `key` is required in client-side, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used.
|
|
159
159
|
if (withDefaults.mode === LOCALHOST_MODE && maybeKey === undefined) {
|
|
160
160
|
withDefaults.core.key = 'localhost_key';
|
|
@@ -171,6 +171,10 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
171
171
|
withDefaults.core.trafficType = validateTrafficType(log, maybeTT, 'Client instantiation');
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
+
} else {
|
|
175
|
+
// On server-side, key is undefined and used to distinguish from client-side
|
|
176
|
+
if (maybeKey !== undefined) log.warn('Provided `key` is ignored in server-side SDK.'); // @ts-ignore
|
|
177
|
+
withDefaults.core.key = undefined;
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
// Current ip/hostname information
|
|
@@ -138,4 +138,5 @@ export declare const LOG_PREFIX_SYNC_POLLING: string;
|
|
|
138
138
|
export declare const LOG_PREFIX_SYNC_SUBMITTERS: string;
|
|
139
139
|
export declare const LOG_PREFIX_IMPRESSIONS_TRACKER = "impressions-tracker: ";
|
|
140
140
|
export declare const LOG_PREFIX_EVENTS_TRACKER = "events-tracker: ";
|
|
141
|
+
export declare const LOG_PREFIX_UNIQUE_KEYS_TRACKER = "unique-keys-tracker: ";
|
|
141
142
|
export declare const LOG_PREFIX_CLEANUP = "cleanup: ";
|
|
@@ -6,7 +6,7 @@ import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
|
|
|
6
6
|
import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
|
|
7
7
|
import { ISyncManager } from '../sync/types';
|
|
8
8
|
import { IImpressionObserver } from '../trackers/impressionObserver/types';
|
|
9
|
-
import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../trackers/types';
|
|
9
|
+
import { IImpressionsTracker, IEventTracker, ITelemetryTracker, IFilterAdapter, IUniqueKeysTracker } from '../trackers/types';
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
/**
|
|
12
12
|
* Environment related dependencies.
|
|
@@ -42,6 +42,7 @@ export interface ISdkFactoryContext {
|
|
|
42
42
|
eventTracker: IEventTracker;
|
|
43
43
|
telemetryTracker: ITelemetryTracker;
|
|
44
44
|
storage: IStorageSync | IStorageAsync;
|
|
45
|
+
uniqueKeysTracker?: IUniqueKeysTracker;
|
|
45
46
|
signalListener?: ISignalListener;
|
|
46
47
|
splitApi?: ISplitApi;
|
|
47
48
|
syncManager?: ISyncManager;
|
|
@@ -70,11 +71,12 @@ export interface ISdkFactoryParams {
|
|
|
70
71
|
(): SplitIO.ICsClient;
|
|
71
72
|
(key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient;
|
|
72
73
|
} | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient));
|
|
74
|
+
impressionsObserverFactory: () => IImpressionObserver;
|
|
75
|
+
filterAdapterFactory?: () => IFilterAdapter;
|
|
73
76
|
SignalListener?: new (syncManager: ISyncManager | undefined, // Used by NodeSignalListener to flush data, and by BrowserSignalListener to close streaming connection.
|
|
74
77
|
settings: ISettings, // Used by BrowserSignalListener
|
|
75
78
|
storage: IStorageSync | IStorageAsync, // Used by BrowserSignalListener
|
|
76
79
|
serviceApi: ISplitApi | undefined) => ISignalListener;
|
|
77
80
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined;
|
|
78
|
-
impressionsObserverFactory?: () => IImpressionObserver;
|
|
79
81
|
extraProps?: (params: ISdkFactoryContext) => object;
|
|
80
82
|
}
|
|
@@ -20,6 +20,8 @@ export declare type IFetchSplitChanges = (since: number, noCache?: boolean, till
|
|
|
20
20
|
export declare type IFetchSegmentChanges = (since: number, segmentName: string, noCache?: boolean, till?: number) => Promise<IResponse>;
|
|
21
21
|
export declare type IFetchMySegments = (userMatchingKey: string, noCache?: boolean) => Promise<IResponse>;
|
|
22
22
|
export declare type IPostEventsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
23
|
+
export declare type IPostUniqueKeysBulkCs = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
24
|
+
export declare type IPostUniqueKeysBulkSs = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
23
25
|
export declare type IPostTestImpressionsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
24
26
|
export declare type IPostTestImpressionsCount = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
25
27
|
export declare type IPostMetricsConfig = (body: string, headers?: Record<string, string>) => Promise<IResponse>;
|
|
@@ -32,6 +34,8 @@ export interface ISplitApi {
|
|
|
32
34
|
fetchSegmentChanges: IFetchSegmentChanges;
|
|
33
35
|
fetchMySegments: IFetchMySegments;
|
|
34
36
|
postEventsBulk: IPostEventsBulk;
|
|
37
|
+
postUniqueKeysBulkCs: IPostUniqueKeysBulkCs;
|
|
38
|
+
postUniqueKeysBulkSs: IPostUniqueKeysBulkSs;
|
|
35
39
|
postTestImpressionsBulk: IPostTestImpressionsBulk;
|
|
36
40
|
postTestImpressionsCount: IPostTestImpressionsCount;
|
|
37
41
|
postMetricsConfig: IPostMetricsConfig;
|
|
@@ -29,7 +29,7 @@ export declare abstract class AbstractSplitsCacheAsync implements ISplitsCacheAs
|
|
|
29
29
|
* @param {string} name
|
|
30
30
|
* @param {string} defaultTreatment
|
|
31
31
|
* @param {number} changeNumber
|
|
32
|
-
* @returns {Promise} a promise that is resolved once the split kill operation is performed. The fulfillment value is a boolean: `true` if the
|
|
32
|
+
* @returns {Promise} a promise that is resolved once the split kill operation is performed. The fulfillment value is a boolean: `true` if the operation successed updating the split or `false` if no split is updated,
|
|
33
33
|
* for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
34
34
|
* The promise will never be rejected.
|
|
35
35
|
*/
|
|
@@ -30,7 +30,7 @@ export declare abstract class AbstractSplitsCacheSync implements ISplitsCacheSyn
|
|
|
30
30
|
* @param {string} name
|
|
31
31
|
* @param {string} defaultTreatment
|
|
32
32
|
* @param {number} changeNumber
|
|
33
|
-
* @returns {
|
|
33
|
+
* @returns {boolean} `true` if the operation successed updating the split, or `false` if no split is updated,
|
|
34
34
|
* for instance, if the `changeNumber` is old, or if the split is not found (e.g., `/splitchanges` hasn't been fetched yet), or if the storage fails to apply the update.
|
|
35
35
|
*/
|
|
36
36
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { KeyBuilder } from './KeyBuilder';
|
|
2
2
|
import { IMetadata } from '../dtos/types';
|
|
3
3
|
import { Method } from '../sync/submitters/types';
|
|
4
|
+
export declare const METHOD_NAMES: Record<Method, string>;
|
|
4
5
|
export declare class KeyBuilderSS extends KeyBuilder {
|
|
5
6
|
latencyPrefix: string;
|
|
6
7
|
exceptionPrefix: string;
|
|
@@ -9,12 +10,11 @@ export declare class KeyBuilderSS extends KeyBuilder {
|
|
|
9
10
|
constructor(prefix: string, metadata: IMetadata);
|
|
10
11
|
buildRegisteredSegmentsKey(): string;
|
|
11
12
|
buildImpressionsKey(): string;
|
|
13
|
+
buildImpressionsCountKey(): string;
|
|
14
|
+
buildUniqueKeysKey(): string;
|
|
12
15
|
buildEventsKey(): string;
|
|
13
16
|
searchPatternForSplitKeys(): string;
|
|
14
17
|
buildLatencyKey(method: Method, bucket: number): string;
|
|
15
18
|
buildExceptionKey(method: Method): string;
|
|
16
19
|
buildInitKey(): string;
|
|
17
20
|
}
|
|
18
|
-
export declare function parseMetadata(field: string): [metadata: string] | string;
|
|
19
|
-
export declare function parseExceptionField(field: string): [metadata: string, method: Method] | string;
|
|
20
|
-
export declare function parseLatencyField(field: string): [metadata: string, method: Method, bucket: number] | string;
|
|
@@ -42,7 +42,6 @@ export declare class SplitsCacheInLocal extends AbstractSplitsCacheSync {
|
|
|
42
42
|
checkCache(): boolean;
|
|
43
43
|
/**
|
|
44
44
|
* Clean Splits cache if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
|
|
45
|
-
* Clean operation (clear) also updates `lastUpdated` timestamp with current time.
|
|
46
45
|
*
|
|
47
46
|
* @param {number | undefined} expirationTimestamp if the value is not a number, data will not be cleaned
|
|
48
47
|
*/
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { IImpressionCountsCacheSync } from '../types';
|
|
2
2
|
export declare class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync {
|
|
3
|
-
|
|
3
|
+
protected cache: Record<string, number>;
|
|
4
|
+
private readonly maxStorage;
|
|
5
|
+
protected onFullQueue?: () => void;
|
|
6
|
+
private cacheSize;
|
|
7
|
+
constructor(impressionCountsCacheSize?: number);
|
|
4
8
|
/**
|
|
5
9
|
* Builds key to be stored in the cache with the featureName and the timeFrame truncated.
|
|
6
10
|
*/
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
import { ImpressionDataType, EventDataType,
|
|
2
|
-
import { IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
1
|
+
import { ImpressionDataType, EventDataType, StreamingEvent, Method, OperationType, TelemetryUsageStatsPayload } from '../../sync/submitters/types';
|
|
2
|
+
import { ISegmentsCacheSync, ISplitsCacheSync, IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
3
3
|
export declare const MAX_LATENCY_BUCKET_COUNT = 23;
|
|
4
|
-
export declare function newBuckets():
|
|
4
|
+
export declare function newBuckets(): number[];
|
|
5
5
|
/**
|
|
6
6
|
* Record telemetry if mode is not localhost.
|
|
7
7
|
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
8
8
|
*/
|
|
9
|
-
export declare function shouldRecordTelemetry(
|
|
9
|
+
export declare function shouldRecordTelemetry({ settings }: IStorageFactoryParams): boolean;
|
|
10
10
|
export declare class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
11
|
+
private splits?;
|
|
12
|
+
private segments?;
|
|
13
|
+
constructor(splits?: ISplitsCacheSync | undefined, segments?: ISegmentsCacheSync | undefined);
|
|
14
|
+
private e;
|
|
15
|
+
isEmpty(): boolean;
|
|
16
|
+
clear(): void;
|
|
17
|
+
pop(): TelemetryUsageStatsPayload;
|
|
18
|
+
/** Config stats */
|
|
11
19
|
private timeUntilReady?;
|
|
12
20
|
getTimeUntilReady(): number | undefined;
|
|
13
21
|
recordTimeUntilReady(ms: number): void;
|
|
@@ -17,6 +25,7 @@ export declare class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
17
25
|
private notReadyUsage;
|
|
18
26
|
getNonReadyUsage(): number;
|
|
19
27
|
recordNonReadyUsage(): void;
|
|
28
|
+
/** Usage stats */
|
|
20
29
|
private impressionStats;
|
|
21
30
|
getImpressionStats(type: ImpressionDataType): number;
|
|
22
31
|
recordImpressionStats(type: ImpressionDataType, count: number): void;
|
|
@@ -24,13 +33,15 @@ export declare class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
24
33
|
getEventStats(type: EventDataType): number;
|
|
25
34
|
recordEventStats(type: EventDataType, count: number): void;
|
|
26
35
|
private lastSync;
|
|
27
|
-
getLastSynchronization():
|
|
36
|
+
getLastSynchronization(): Partial<Record<OperationType, number | undefined>>;
|
|
28
37
|
recordSuccessfulSync(resource: OperationType, timeMs: number): void;
|
|
29
38
|
private httpErrors;
|
|
30
|
-
popHttpErrors():
|
|
39
|
+
popHttpErrors(): Partial<Record<OperationType, {
|
|
40
|
+
[statusCode: string]: number;
|
|
41
|
+
}>>;
|
|
31
42
|
recordHttpError(resource: OperationType, status: number): void;
|
|
32
43
|
private httpLatencies;
|
|
33
|
-
popHttpLatencies():
|
|
44
|
+
popHttpLatencies(): Partial<Record<OperationType, number[]>>;
|
|
34
45
|
recordHttpLatency(resource: OperationType, latencyMs: number): void;
|
|
35
46
|
private authRejections;
|
|
36
47
|
popAuthRejections(): number;
|
|
@@ -48,9 +59,9 @@ export declare class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
48
59
|
getSessionLength(): number | undefined;
|
|
49
60
|
recordSessionLength(ms: number): void;
|
|
50
61
|
private exceptions;
|
|
51
|
-
popExceptions():
|
|
62
|
+
popExceptions(): Partial<Record<Method, number>>;
|
|
52
63
|
recordException(method: Method): void;
|
|
53
64
|
private latencies;
|
|
54
|
-
popLatencies():
|
|
65
|
+
popLatencies(): Partial<Record<Method, number[]>>;
|
|
55
66
|
recordLatency(method: Method, latencyMs: number): void;
|
|
56
67
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { IUniqueKeysCacheBase } from '../types';
|
|
2
|
+
import { ISet } from '../../utils/lang/sets';
|
|
3
|
+
import { UniqueKeysPayloadSs } from '../../sync/submitters/types';
|
|
4
|
+
/**
|
|
5
|
+
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
6
|
+
*/
|
|
7
|
+
export declare function fromUniqueKeysCollector(uniqueKeys: {
|
|
8
|
+
[featureName: string]: ISet<string>;
|
|
9
|
+
}): UniqueKeysPayloadSs;
|
|
10
|
+
export declare class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
11
|
+
protected onFullQueue?: () => void;
|
|
12
|
+
private readonly maxStorage;
|
|
13
|
+
private uniqueTrackerSize;
|
|
14
|
+
protected uniqueKeysTracker: {
|
|
15
|
+
[featureName: string]: ISet<string>;
|
|
16
|
+
};
|
|
17
|
+
constructor(uniqueKeysQueueSize?: number);
|
|
18
|
+
setOnFullQueueCb(cb: () => void): void;
|
|
19
|
+
/**
|
|
20
|
+
* Store unique keys per feature.
|
|
21
|
+
*/
|
|
22
|
+
track(userKey: string, featureName: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Clear the data stored on the cache.
|
|
25
|
+
*/
|
|
26
|
+
clear(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Pop the collected data, used as payload for posting.
|
|
29
|
+
*/
|
|
30
|
+
pop(): UniqueKeysPayloadSs;
|
|
31
|
+
/**
|
|
32
|
+
* Check if the cache is empty.
|
|
33
|
+
*/
|
|
34
|
+
isEmpty(): boolean;
|
|
35
|
+
}
|