@splitsoftware/splitio-commons 1.6.2-rc.7 → 1.6.2-rc.9
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 +2 -1
- package/cjs/consent/sdkUserConsent.js +2 -2
- package/cjs/evaluator/index.js +5 -5
- package/cjs/listeners/browser.js +1 -2
- package/cjs/logger/constants.js +1 -2
- package/cjs/sdkClient/client.js +19 -7
- package/cjs/sdkClient/sdkClient.js +1 -3
- package/cjs/sdkFactory/index.js +5 -26
- package/cjs/services/splitApi.js +4 -24
- package/cjs/storages/KeyBuilderSS.js +48 -15
- package/cjs/storages/inLocalStorage/index.js +1 -5
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -12
- package/cjs/storages/inMemory/InMemoryStorage.js +2 -6
- package/cjs/storages/inMemory/InMemoryStorageCS.js +2 -6
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +9 -6
- package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +100 -0
- package/cjs/storages/inRedis/constants.js +1 -4
- package/cjs/storages/inRedis/index.js +1 -15
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +126 -0
- package/cjs/storages/pluggable/index.js +19 -15
- package/cjs/sync/submitters/submitterManager.js +0 -3
- package/cjs/sync/submitters/telemetrySubmitter.js +7 -5
- package/cjs/trackers/impressionsTracker.js +41 -22
- package/cjs/utils/constants/index.js +2 -4
- package/cjs/utils/lang/maps.js +15 -7
- package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +0 -4
- package/esm/consent/sdkUserConsent.js +2 -2
- package/esm/evaluator/index.js +5 -5
- package/esm/listeners/browser.js +2 -3
- package/esm/logger/constants.js +0 -1
- package/esm/sdkClient/client.js +19 -7
- package/esm/sdkClient/sdkClient.js +1 -3
- package/esm/sdkFactory/index.js +5 -26
- package/esm/services/splitApi.js +4 -24
- package/esm/storages/KeyBuilderSS.js +44 -14
- package/esm/storages/inLocalStorage/index.js +2 -6
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -12
- package/esm/storages/inMemory/InMemoryStorage.js +4 -8
- package/esm/storages/inMemory/InMemoryStorageCS.js +3 -7
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +8 -6
- package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +100 -0
- package/esm/storages/inRedis/constants.js +0 -3
- package/esm/storages/inRedis/index.js +2 -16
- package/esm/storages/pluggable/TelemetryCachePluggable.js +126 -0
- package/esm/storages/pluggable/index.js +19 -15
- package/esm/sync/submitters/submitterManager.js +0 -3
- package/esm/sync/submitters/telemetrySubmitter.js +8 -6
- package/esm/trackers/impressionsTracker.js +41 -22
- package/esm/utils/constants/index.js +0 -2
- package/esm/utils/lang/maps.js +15 -7
- package/esm/utils/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +0 -4
- package/package.json +2 -1
- package/src/consent/sdkUserConsent.ts +2 -2
- package/src/evaluator/index.ts +6 -6
- package/src/listeners/browser.ts +2 -3
- package/src/logger/.DS_Store +0 -0
- package/src/logger/constants.ts +0 -1
- package/src/sdkClient/client.ts +21 -8
- package/src/sdkClient/sdkClient.ts +1 -3
- package/src/sdkFactory/index.ts +5 -29
- package/src/sdkFactory/types.ts +4 -7
- package/src/services/splitApi.ts +4 -26
- package/src/services/types.ts +2 -8
- package/src/storages/KeyBuilderSS.ts +53 -17
- package/src/storages/inLocalStorage/index.ts +2 -5
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +1 -16
- package/src/storages/inMemory/InMemoryStorage.ts +4 -7
- package/src/storages/inMemory/InMemoryStorageCS.ts +3 -7
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +9 -7
- package/src/storages/inRedis/EventsCacheInRedis.ts +1 -1
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +122 -2
- package/src/storages/inRedis/constants.ts +0 -3
- package/src/storages/inRedis/index.ts +3 -12
- package/src/storages/pluggable/TelemetryCachePluggable.ts +147 -2
- package/src/storages/pluggable/index.ts +20 -16
- package/src/storages/types.ts +13 -34
- package/src/sync/submitters/submitterManager.ts +0 -2
- package/src/sync/submitters/telemetrySubmitter.ts +14 -9
- package/src/sync/submitters/types.ts +40 -26
- package/src/trackers/impressionsTracker.ts +48 -27
- package/src/trackers/types.ts +0 -28
- package/src/types.ts +1 -5
- package/src/utils/constants/index.ts +0 -2
- package/src/utils/lang/maps.ts +20 -8
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +0 -5
- package/types/logger/constants.d.ts +0 -1
- package/types/sdkFactory/types.d.ts +2 -4
- package/types/services/types.d.ts +2 -6
- package/types/storages/KeyBuilderSS.d.ts +7 -4
- package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +1 -5
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +6 -3
- package/types/storages/inRedis/EventsCacheInRedis.d.ts +1 -1
- package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +16 -1
- package/types/storages/inRedis/constants.d.ts +0 -3
- package/types/storages/pluggable/TelemetryCachePluggable.d.ts +17 -1
- package/types/storages/types.d.ts +10 -21
- package/types/sync/submitters/telemetrySubmitter.d.ts +1 -1
- package/types/sync/submitters/types.d.ts +13 -24
- package/types/trackers/impressionsTracker.d.ts +6 -4
- package/types/trackers/types.d.ts +0 -23
- package/types/types.d.ts +1 -5
- package/types/utils/constants/index.d.ts +0 -2
- package/types/utils/lang/maps.d.ts +6 -2
- package/types/utils/settingsValidation/index.d.ts +0 -1
- package/cjs/storages/inMemory/uniqueKeysCacheInMemory.js +0 -73
- package/cjs/storages/inMemory/uniqueKeysCacheInMemoryCS.js +0 -78
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +0 -49
- package/cjs/storages/inRedis/uniqueKeysCacheInRedis.js +0 -56
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +0 -26
- package/cjs/trackers/strategy/strategyDebug.js +0 -25
- package/cjs/trackers/strategy/strategyNone.js +0 -29
- package/cjs/trackers/strategy/strategyOptimized.js +0 -35
- package/cjs/trackers/uniqueKeysTracker.js +0 -38
- package/esm/storages/inMemory/uniqueKeysCacheInMemory.js +0 -70
- package/esm/storages/inMemory/uniqueKeysCacheInMemoryCS.js +0 -75
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +0 -46
- package/esm/storages/inRedis/uniqueKeysCacheInRedis.js +0 -53
- package/esm/sync/submitters/uniqueKeysSubmitter.js +0 -22
- package/esm/trackers/strategy/strategyDebug.js +0 -21
- package/esm/trackers/strategy/strategyNone.js +0 -25
- package/esm/trackers/strategy/strategyOptimized.js +0 -31
- package/esm/trackers/uniqueKeysTracker.js +0 -34
- package/src/storages/inMemory/uniqueKeysCacheInMemory.ts +0 -82
- package/src/storages/inMemory/uniqueKeysCacheInMemoryCS.ts +0 -88
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +0 -51
- package/src/storages/inRedis/uniqueKeysCacheInRedis.ts +0 -63
- package/src/sync/submitters/uniqueKeysSubmitter.ts +0 -35
- package/src/trackers/strategy/strategyDebug.ts +0 -28
- package/src/trackers/strategy/strategyNone.ts +0 -34
- package/src/trackers/strategy/strategyOptimized.ts +0 -42
- package/src/trackers/uniqueKeysTracker.ts +0 -48
- package/types/sdkClient/types.d.ts +0 -18
- package/types/storages/inMemory/CountsCacheInMemory.d.ts +0 -20
- package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +0 -20
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +0 -35
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +0 -37
- package/types/storages/inRedis/CountsCacheInRedis.d.ts +0 -9
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +0 -14
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +0 -15
- package/types/sync/offline/LocalhostFromFile.d.ts +0 -2
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +0 -2
- package/types/sync/submitters/eventsSyncTask.d.ts +0 -8
- package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +0 -5
- package/types/sync/submitters/impressionCountsSyncTask.d.ts +0 -13
- package/types/sync/submitters/impressionsSyncTask.d.ts +0 -14
- package/types/sync/submitters/metricsSyncTask.d.ts +0 -12
- package/types/sync/submitters/submitterSyncTask.d.ts +0 -10
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +0 -5
- package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +0 -5
- package/types/sync/syncTaskComposite.d.ts +0 -5
- package/types/trackers/filter/bloomFilter.d.ts +0 -10
- package/types/trackers/filter/dictionaryFilter.d.ts +0 -8
- package/types/trackers/filter/types.d.ts +0 -5
- package/types/trackers/strategy/strategyDebug.d.ts +0 -9
- package/types/trackers/strategy/strategyNone.d.ts +0 -10
- package/types/trackers/strategy/strategyOptimized.d.ts +0 -11
- package/types/trackers/uniqueKeysTracker.d.ts +0 -13
- package/types/utils/timeTracker/index.d.ts +0 -70
package/src/sdkFactory/index.ts
CHANGED
|
@@ -13,11 +13,6 @@ import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
|
|
|
13
13
|
import { metadataBuilder } from '../storages/metadataBuilder';
|
|
14
14
|
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
|
|
15
15
|
import { objectAssign } from '../utils/lang/objectAssign';
|
|
16
|
-
import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
|
|
17
|
-
import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
|
|
18
|
-
import { strategyNoneFactory } from '../trackers/strategy/strategyNone';
|
|
19
|
-
import { uniqueKeysTrackerFactory } from '../trackers/uniqueKeysTracker';
|
|
20
|
-
import { NONE, OPTIMIZED } from '../utils/constants';
|
|
21
16
|
|
|
22
17
|
/**
|
|
23
18
|
* Modular SDK factory
|
|
@@ -26,8 +21,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
26
21
|
|
|
27
22
|
const { settings, platform, storageFactory, splitApiFactory, extraProps,
|
|
28
23
|
syncManagerFactory, SignalListener, impressionsObserverFactory,
|
|
29
|
-
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory
|
|
30
|
-
filterAdapterFactory } = params;
|
|
24
|
+
integrationsManagerFactory, sdkManagerFactory, sdkClientMethodFactory } = params;
|
|
31
25
|
const log = settings.log;
|
|
32
26
|
|
|
33
27
|
// @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid API Key, etc.
|
|
@@ -43,10 +37,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
43
37
|
const storageFactoryParams: IStorageFactoryParams = {
|
|
44
38
|
impressionsQueueSize: settings.scheduler.impressionsQueueSize,
|
|
45
39
|
eventsQueueSize: settings.scheduler.eventsQueueSize,
|
|
46
|
-
uniqueKeysCacheSize: settings.scheduler.uniqueKeysCacheSize,
|
|
47
|
-
impressionCountsQueueSize: settings.scheduler.impressionCountsQueueSize,
|
|
48
|
-
impressionCountsRefreshRate: settings.scheduler.impressionCountsRefreshRate,
|
|
49
|
-
uniqueKeysRefreshRate: settings.scheduler.uniqueKeysRefreshRate,
|
|
50
40
|
optimize: shouldBeOptimized(settings),
|
|
51
41
|
|
|
52
42
|
// ATM, only used by InLocalStorage
|
|
@@ -55,7 +45,6 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
55
45
|
|
|
56
46
|
// ATM, only used by PluggableStorage
|
|
57
47
|
mode: settings.mode,
|
|
58
|
-
impressionsMode: settings.sync.impressionsMode,
|
|
59
48
|
|
|
60
49
|
// Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined,
|
|
61
50
|
// or partial consumer mode, where it only has submitters, and therefore it doesn't emit readiness events.
|
|
@@ -74,28 +63,15 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
|
|
|
74
63
|
const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
|
|
75
64
|
const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
let strategy;
|
|
81
|
-
switch (storageFactoryParams.impressionsMode) {
|
|
82
|
-
case OPTIMIZED:
|
|
83
|
-
strategy = strategyOptimizedFactory(observer, storage.impressionCounts!);
|
|
84
|
-
break;
|
|
85
|
-
case NONE:
|
|
86
|
-
strategy = strategyNoneFactory(storage.impressionCounts!, uniqueKeysTracker!);
|
|
87
|
-
break;
|
|
88
|
-
default:
|
|
89
|
-
strategy = strategyDebugFactory(observer);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, strategy, integrationsManager, storage.telemetry);
|
|
66
|
+
// trackers
|
|
67
|
+
const observer = impressionsObserverFactory && impressionsObserverFactory();
|
|
68
|
+
const impressionsTracker = impressionsTrackerFactory(settings, storage.impressions, integrationsManager, observer, storage.impressionCounts, storage.telemetry);
|
|
93
69
|
const eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager, storage.telemetry);
|
|
94
70
|
|
|
95
71
|
// splitApi is used by SyncManager and Browser signal listener
|
|
96
72
|
const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
|
|
97
73
|
|
|
98
|
-
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker,
|
|
74
|
+
const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform };
|
|
99
75
|
|
|
100
76
|
const syncManager = syncManagerFactory && syncManagerFactory(ctx as ISdkFactoryContextSync);
|
|
101
77
|
ctx.syncManager = syncManager;
|
package/src/sdkFactory/types.ts
CHANGED
|
@@ -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
|
|
9
|
+
import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../trackers/types';
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -44,7 +44,6 @@ export interface ISdkFactoryContext {
|
|
|
44
44
|
eventTracker: IEventTracker,
|
|
45
45
|
telemetryTracker: ITelemetryTracker,
|
|
46
46
|
storage: IStorageSync | IStorageAsync,
|
|
47
|
-
uniqueKeysTracker?: IUniqueKeysTracker,
|
|
48
47
|
signalListener?: ISignalListener
|
|
49
48
|
splitApi?: ISplitApi
|
|
50
49
|
syncManager?: ISyncManager,
|
|
@@ -97,11 +96,6 @@ export interface ISdkFactoryParams {
|
|
|
97
96
|
// It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
|
|
98
97
|
sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
|
|
99
98
|
|
|
100
|
-
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
101
|
-
impressionsObserverFactory: () => IImpressionObserver
|
|
102
|
-
|
|
103
|
-
filterAdapterFactory?: () => IFilterAdapter
|
|
104
|
-
|
|
105
99
|
// Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
|
|
106
100
|
// Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed.
|
|
107
101
|
SignalListener?: new (
|
|
@@ -113,6 +107,9 @@ export interface ISdkFactoryParams {
|
|
|
113
107
|
// @TODO review impressionListener and integrations interfaces. What about handling impressionListener as an integration ?
|
|
114
108
|
integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined,
|
|
115
109
|
|
|
110
|
+
// Impression observer factory. If provided, will be used for impressions dedupe
|
|
111
|
+
impressionsObserverFactory?: () => IImpressionObserver
|
|
112
|
+
|
|
116
113
|
// Optional function to assign additional properties to the factory instance
|
|
117
114
|
extraProps?: (params: ISdkFactoryContext) => object
|
|
118
115
|
}
|
package/src/services/splitApi.ts
CHANGED
|
@@ -106,37 +106,15 @@ export function splitApiFactory(
|
|
|
106
106
|
const url = `${urls.events}/testImpressions/count`;
|
|
107
107
|
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT));
|
|
108
108
|
},
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Post unique keys for client side.
|
|
112
|
-
*
|
|
113
|
-
* @param body unique keys payload
|
|
114
|
-
* @param headers Optionals headers to overwrite default ones. For example, it is used in producer mode to overwrite metadata headers.
|
|
115
|
-
*/
|
|
116
|
-
postUniqueKeysBulkCs(body: string, headers?: Record<string, string>) {
|
|
117
|
-
const url = `${urls.telemetry}/v1/keys/cs`;
|
|
118
|
-
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
|
|
119
|
-
},
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Post unique keys for server side.
|
|
123
|
-
*
|
|
124
|
-
* @param body unique keys payload
|
|
125
|
-
* @param headers Optionals headers to overwrite default ones. For example, it is used in producer mode to overwrite metadata headers.
|
|
126
|
-
*/
|
|
127
|
-
postUniqueKeysBulkSs(body: string, headers?: Record<string, string>) {
|
|
128
|
-
const url = `${urls.telemetry}/v1/keys/ss`;
|
|
129
|
-
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY));
|
|
130
|
-
},
|
|
131
109
|
|
|
132
|
-
postMetricsConfig(body: string) {
|
|
110
|
+
postMetricsConfig(body: string, headers?: Record<string, string>) {
|
|
133
111
|
const url = `${urls.telemetry}/v1/metrics/config`;
|
|
134
|
-
return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
|
|
112
|
+
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), true);
|
|
135
113
|
},
|
|
136
114
|
|
|
137
|
-
postMetricsUsage(body: string) {
|
|
115
|
+
postMetricsUsage(body: string, headers?: Record<string, string>) {
|
|
138
116
|
const url = `${urls.telemetry}/v1/metrics/usage`;
|
|
139
|
-
return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
|
|
117
|
+
return splitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), true);
|
|
140
118
|
}
|
|
141
119
|
};
|
|
142
120
|
}
|
package/src/services/types.ts
CHANGED
|
@@ -43,17 +43,13 @@ export type IFetchMySegments = (userMatchingKey: string, noCache?: boolean) => P
|
|
|
43
43
|
|
|
44
44
|
export type IPostEventsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
45
45
|
|
|
46
|
-
export type IPostUniqueKeysBulkCs = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
47
|
-
|
|
48
|
-
export type IPostUniqueKeysBulkSs = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
49
|
-
|
|
50
46
|
export type IPostTestImpressionsBulk = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
51
47
|
|
|
52
48
|
export type IPostTestImpressionsCount = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
53
49
|
|
|
54
|
-
export type IPostMetricsConfig = (body: string) => Promise<IResponse>
|
|
50
|
+
export type IPostMetricsConfig = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
55
51
|
|
|
56
|
-
export type IPostMetricsUsage = (body: string) => Promise<IResponse>
|
|
52
|
+
export type IPostMetricsUsage = (body: string, headers?: Record<string, string>) => Promise<IResponse>
|
|
57
53
|
|
|
58
54
|
export interface ISplitApi {
|
|
59
55
|
getSdkAPIHealthCheck: IHealthCheckAPI
|
|
@@ -63,8 +59,6 @@ export interface ISplitApi {
|
|
|
63
59
|
fetchSegmentChanges: IFetchSegmentChanges
|
|
64
60
|
fetchMySegments: IFetchMySegments
|
|
65
61
|
postEventsBulk: IPostEventsBulk
|
|
66
|
-
postUniqueKeysBulkCs: IPostUniqueKeysBulkCs
|
|
67
|
-
postUniqueKeysBulkSs: IPostUniqueKeysBulkSs
|
|
68
62
|
postTestImpressionsBulk: IPostTestImpressionsBulk
|
|
69
63
|
postTestImpressionsCount: IPostTestImpressionsCount
|
|
70
64
|
postMetricsConfig: IPostMetricsConfig
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { KeyBuilder } from './KeyBuilder';
|
|
2
2
|
import { IMetadata } from '../dtos/types';
|
|
3
3
|
import { Method } from '../sync/submitters/types';
|
|
4
|
+
import { MAX_LATENCY_BUCKET_COUNT } from './inMemory/TelemetryCacheInMemory';
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const METHOD_NAMES: Record<Method, string> = {
|
|
6
7
|
t: 'treatment',
|
|
7
8
|
ts: 'treatments',
|
|
8
9
|
tc: 'treatmentWithConfig',
|
|
@@ -12,11 +13,17 @@ const methodNames: Record<Method, string> = {
|
|
|
12
13
|
|
|
13
14
|
export class KeyBuilderSS extends KeyBuilder {
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
latencyPrefix: string;
|
|
17
|
+
exceptionPrefix: string;
|
|
18
|
+
initPrefix: string;
|
|
19
|
+
private versionablePrefix: string;
|
|
16
20
|
|
|
17
21
|
constructor(prefix: string, metadata: IMetadata) {
|
|
18
22
|
super(prefix);
|
|
19
|
-
this.
|
|
23
|
+
this.latencyPrefix = `${this.prefix}.telemetry.latencies`;
|
|
24
|
+
this.exceptionPrefix = `${this.prefix}.telemetry.exceptions`;
|
|
25
|
+
this.initPrefix = `${this.prefix}.telemetry.init`;
|
|
26
|
+
this.versionablePrefix = `${metadata.s}/${metadata.n}/${metadata.i}`;
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
buildRegisteredSegmentsKey() {
|
|
@@ -27,14 +34,6 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
27
34
|
return `${this.prefix}.impressions`;
|
|
28
35
|
}
|
|
29
36
|
|
|
30
|
-
buildImpressionsCountKey() {
|
|
31
|
-
return `${this.prefix}.impressions.count`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
buildUniqueKeysKey() {
|
|
35
|
-
return `${this.prefix}.uniquekeys`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
37
|
buildEventsKey() {
|
|
39
38
|
return `${this.prefix}.events`;
|
|
40
39
|
}
|
|
@@ -46,19 +45,56 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
46
45
|
/* Telemetry keys */
|
|
47
46
|
|
|
48
47
|
buildLatencyKey(method: Method, bucket: number) {
|
|
49
|
-
return `${this.
|
|
48
|
+
return `${this.latencyPrefix}::${this.versionablePrefix}/${METHOD_NAMES[method]}/${bucket}`;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
buildExceptionKey(method: Method) {
|
|
53
|
-
return `${this.
|
|
52
|
+
return `${this.exceptionPrefix}::${this.versionablePrefix}/${METHOD_NAMES[method]}`;
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
buildInitKey() {
|
|
57
|
-
return `${this.
|
|
56
|
+
return `${this.initPrefix}::${this.versionablePrefix}`;
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Used by consumer methods of TelemetryCacheInRedis and TelemetryCachePluggable
|
|
62
|
+
|
|
63
|
+
const REVERSE_METHOD_NAMES = Object.keys(METHOD_NAMES).reduce((acc, key) => {
|
|
64
|
+
acc[METHOD_NAMES[key as Method]] = key as Method;
|
|
65
|
+
return acc;
|
|
66
|
+
}, {} as Record<string, Method>);
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
export function parseMetadata(field: string): [metadata: string] | string {
|
|
70
|
+
const parts = field.split('/');
|
|
71
|
+
if (parts.length !== 3) return `invalid subsection count. Expected 4, got: ${parts.length}`;
|
|
72
|
+
|
|
73
|
+
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */] = parts;
|
|
74
|
+
return [JSON.stringify({ s, n, i })];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function parseExceptionField(field: string): [metadata: string, method: Method] | string {
|
|
78
|
+
const parts = field.split('/');
|
|
79
|
+
if (parts.length !== 4) return `invalid subsection count. Expected 4, got: ${parts.length}`;
|
|
80
|
+
|
|
81
|
+
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */, m] = parts;
|
|
82
|
+
const method = REVERSE_METHOD_NAMES[m];
|
|
83
|
+
if (!method) return `unknown method '${m}'`;
|
|
84
|
+
|
|
85
|
+
return [JSON.stringify({ s, n, i }), method];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function parseLatencyField(field: string): [metadata: string, method: Method, bucket: number] | string {
|
|
89
|
+
const parts = field.split('/');
|
|
90
|
+
if (parts.length !== 5) return `invalid subsection count. Expected 5, got: ${parts.length}`;
|
|
91
|
+
|
|
92
|
+
const [s /* metadata.s */, n /* metadata.n */, i /* metadata.i */, m, b] = parts;
|
|
93
|
+
const method = REVERSE_METHOD_NAMES[m];
|
|
94
|
+
if (!method) return `unknown method '${m}'`;
|
|
95
|
+
|
|
96
|
+
const bucket = parseInt(b);
|
|
97
|
+
if (isNaN(bucket) || bucket >= MAX_LATENCY_BUCKET_COUNT) return `invalid bucket. Expected a number between 0 and 22, got: ${b}`;
|
|
63
98
|
|
|
99
|
+
return [JSON.stringify({ s, n, i }), method, bucket];
|
|
64
100
|
}
|
|
@@ -12,9 +12,8 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
|
|
|
12
12
|
import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
|
|
13
13
|
import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
|
|
14
14
|
import { LOG_PREFIX } from './constants';
|
|
15
|
-
import {
|
|
15
|
+
import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
|
|
16
16
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
|
|
17
|
-
import { UniqueKeysCacheInMemoryCS } from '../inMemory/uniqueKeysCacheInMemoryCS';
|
|
18
17
|
|
|
19
18
|
export interface InLocalStorageOptions {
|
|
20
19
|
prefix?: string
|
|
@@ -45,8 +44,7 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
45
44
|
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
46
45
|
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
47
46
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
48
|
-
telemetry:
|
|
49
|
-
uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
47
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
50
48
|
|
|
51
49
|
destroy() {
|
|
52
50
|
this.splits = new SplitsCacheInMemory();
|
|
@@ -54,7 +52,6 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
|
|
|
54
52
|
this.impressions.clear();
|
|
55
53
|
this.impressionCounts && this.impressionCounts.clear();
|
|
56
54
|
this.events.clear();
|
|
57
|
-
this.uniqueKeys?.clear();
|
|
58
55
|
},
|
|
59
56
|
|
|
60
57
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are customer per key).
|
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { truncateTimeFrame } from '../../utils/time';
|
|
2
|
-
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
3
2
|
import { IImpressionCountsCacheSync } from '../types';
|
|
4
3
|
|
|
5
4
|
export class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync {
|
|
6
|
-
|
|
7
|
-
private readonly maxStorage: number;
|
|
8
|
-
protected onFullQueue?: () => void;
|
|
9
|
-
private cacheSize = 0;
|
|
10
|
-
|
|
11
|
-
constructor(impressionCountsCacheSize: number = DEFAULT_CACHE_SIZE) {
|
|
12
|
-
this.maxStorage = impressionCountsCacheSize;
|
|
13
|
-
}
|
|
5
|
+
private cache: Record<string, number> = {};
|
|
14
6
|
|
|
15
7
|
/**
|
|
16
8
|
* Builds key to be stored in the cache with the featureName and the timeFrame truncated.
|
|
@@ -26,13 +18,6 @@ export class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync
|
|
|
26
18
|
const key = this._makeKey(featureName, timeFrame);
|
|
27
19
|
const currentAmount = this.cache[key];
|
|
28
20
|
this.cache[key] = currentAmount ? currentAmount + amount : amount;
|
|
29
|
-
if (this.onFullQueue) {
|
|
30
|
-
this.cacheSize = this.cacheSize + amount;
|
|
31
|
-
if (this.cacheSize >= this.maxStorage) {
|
|
32
|
-
this.onFullQueue();
|
|
33
|
-
this.cacheSize = 0;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
21
|
}
|
|
37
22
|
|
|
38
23
|
|
|
@@ -4,9 +4,8 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { IStorageFactoryParams, IStorageSync } from '../types';
|
|
6
6
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
7
|
-
import {
|
|
8
|
-
import { TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
-
import { UniqueKeysCacheInMemory } from './uniqueKeysCacheInMemory';
|
|
7
|
+
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
8
|
+
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
@@ -19,10 +18,9 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
19
18
|
splits: new SplitsCacheInMemory(),
|
|
20
19
|
segments: new SegmentsCacheInMemory(),
|
|
21
20
|
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
22
|
-
impressionCounts: params.
|
|
21
|
+
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
23
22
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
24
|
-
telemetry: params
|
|
25
|
-
uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemory(params.uniqueKeysCacheSize) : undefined,
|
|
23
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
26
24
|
|
|
27
25
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
28
26
|
destroy() {
|
|
@@ -31,7 +29,6 @@ export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageS
|
|
|
31
29
|
this.impressions.clear();
|
|
32
30
|
this.impressionCounts && this.impressionCounts.clear();
|
|
33
31
|
this.events.clear();
|
|
34
|
-
this.uniqueKeys?.clear();
|
|
35
32
|
}
|
|
36
33
|
};
|
|
37
34
|
}
|
|
@@ -4,9 +4,8 @@ import { ImpressionsCacheInMemory } from './ImpressionsCacheInMemory';
|
|
|
4
4
|
import { EventsCacheInMemory } from './EventsCacheInMemory';
|
|
5
5
|
import { IStorageSync, IStorageFactoryParams } from '../types';
|
|
6
6
|
import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
|
|
7
|
-
import {
|
|
7
|
+
import { STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
-
import { UniqueKeysCacheInMemoryCS } from './uniqueKeysCacheInMemoryCS';
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -19,11 +18,9 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
19
18
|
splits: new SplitsCacheInMemory(),
|
|
20
19
|
segments: new MySegmentsCacheInMemory(),
|
|
21
20
|
impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
|
|
22
|
-
impressionCounts: params.
|
|
21
|
+
impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
23
22
|
events: new EventsCacheInMemory(params.eventsQueueSize),
|
|
24
|
-
telemetry:
|
|
25
|
-
uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS(params.uniqueKeysCacheSize) : undefined,
|
|
26
|
-
|
|
23
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
|
|
27
24
|
|
|
28
25
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
29
26
|
destroy() {
|
|
@@ -32,7 +29,6 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
|
|
|
32
29
|
this.impressions.clear();
|
|
33
30
|
this.impressionCounts && this.impressionCounts.clear();
|
|
34
31
|
this.events.clear();
|
|
35
|
-
this.uniqueKeys?.clear();
|
|
36
32
|
},
|
|
37
33
|
|
|
38
34
|
// When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key)
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies } from '../../sync/submitters/types';
|
|
2
|
+
import { LOCALHOST_MODE } from '../../utils/constants';
|
|
2
3
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
3
|
-
import { ITelemetryCacheSync } from '../types';
|
|
4
|
+
import { IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
4
5
|
|
|
5
6
|
const MAX_STREAMING_EVENTS = 20;
|
|
6
7
|
const MAX_TAGS = 10;
|
|
8
|
+
export const MAX_LATENCY_BUCKET_COUNT = 23;
|
|
7
9
|
|
|
8
|
-
function newBuckets() {
|
|
9
|
-
|
|
10
|
-
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
10
|
+
export function newBuckets() {
|
|
11
|
+
return new Array(MAX_LATENCY_BUCKET_COUNT).fill(0);
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
const ACCEPTANCE_RANGE = 0.001;
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* Record telemetry if mode is not localhost.
|
|
18
|
+
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
17
19
|
*/
|
|
18
|
-
export function shouldRecordTelemetry() {
|
|
19
|
-
return Math.random() <= ACCEPTANCE_RANGE;
|
|
20
|
+
export function shouldRecordTelemetry(params: IStorageFactoryParams) {
|
|
21
|
+
return params.mode !== LOCALHOST_MODE && (params.matchingKey === undefined || Math.random() <= ACCEPTANCE_RANGE);
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
@@ -59,7 +59,7 @@ export class EventsCacheInRedis implements IEventsCacheAsync {
|
|
|
59
59
|
|
|
60
60
|
/**
|
|
61
61
|
* Pop the given number of events from the storage.
|
|
62
|
-
* The returned promise rejects if the
|
|
62
|
+
* The returned promise rejects if the redis operation fails.
|
|
63
63
|
*
|
|
64
64
|
* NOTE: this method doesn't take into account MAX_EVENT_SIZE or MAX_QUEUE_BYTE_SIZE limits.
|
|
65
65
|
* It is the submitter responsability to handle that.
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { ILogger } from '../../logger/types';
|
|
2
|
-
import { Method } from '../../sync/submitters/types';
|
|
3
|
-
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
2
|
+
import { Method, MultiConfigs, MultiMethodExceptions, MultiMethodLatencies } from '../../sync/submitters/types';
|
|
3
|
+
import { KeyBuilderSS, parseExceptionField, parseLatencyField, parseMetadata } from '../KeyBuilderSS';
|
|
4
4
|
import { ITelemetryCacheAsync } from '../types';
|
|
5
5
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
6
6
|
import { Redis } from 'ioredis';
|
|
7
7
|
import { getTelemetryConfigStats } from '../../sync/submitters/telemetrySubmitter';
|
|
8
8
|
import { CONSUMER_MODE, STORAGE_REDIS } from '../../utils/constants';
|
|
9
|
+
import { isNaNNumber, isString } from '../../utils/lang';
|
|
10
|
+
import { _Map } from '../../utils/lang/maps';
|
|
11
|
+
import { MAX_LATENCY_BUCKET_COUNT, newBuckets } from '../inMemory/TelemetryCacheInMemory';
|
|
9
12
|
|
|
10
13
|
export class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
11
14
|
|
|
@@ -22,6 +25,7 @@ export class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
|
22
25
|
return this.redis.hincrby(key, field, 1)
|
|
23
26
|
.catch(() => { /* Handle rejections for telemetry */ });
|
|
24
27
|
}
|
|
28
|
+
|
|
25
29
|
recordException(method: Method) {
|
|
26
30
|
const [key, field] = this.keys.buildExceptionKey(method).split('::');
|
|
27
31
|
return this.redis.hincrby(key, field, 1)
|
|
@@ -33,4 +37,120 @@ export class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
|
33
37
|
const value = JSON.stringify(getTelemetryConfigStats(CONSUMER_MODE, STORAGE_REDIS));
|
|
34
38
|
return this.redis.hset(key, field, value).catch(() => { /* Handle rejections for telemetry */ });
|
|
35
39
|
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Pop telemetry latencies.
|
|
43
|
+
* The returned promise rejects if redis operations fail.
|
|
44
|
+
*/
|
|
45
|
+
popLatencies(): Promise<MultiMethodLatencies> {
|
|
46
|
+
return this.redis.hgetall(this.keys.latencyPrefix).then(latencies => {
|
|
47
|
+
|
|
48
|
+
const result: MultiMethodLatencies = new _Map();
|
|
49
|
+
|
|
50
|
+
Object.keys(latencies).forEach(field => {
|
|
51
|
+
|
|
52
|
+
const parsedField = parseLatencyField(field);
|
|
53
|
+
if (isString(parsedField)) {
|
|
54
|
+
this.log.error(`Ignoring invalid latency field: ${field}: ${parsedField}`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const count = parseInt(latencies[field]);
|
|
59
|
+
if (isNaNNumber(count)) {
|
|
60
|
+
this.log.error(`Ignoring latency with invalid count: ${latencies[field]}`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const [metadata, method, bucket] = parsedField;
|
|
65
|
+
|
|
66
|
+
if (bucket >= MAX_LATENCY_BUCKET_COUNT) {
|
|
67
|
+
this.log.error(`Ignoring latency with invalid bucket: ${bucket}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (!result.has(metadata)) result.set(metadata, {
|
|
72
|
+
t: newBuckets(),
|
|
73
|
+
ts: newBuckets(),
|
|
74
|
+
tc: newBuckets(),
|
|
75
|
+
tcs: newBuckets(),
|
|
76
|
+
tr: newBuckets(),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
result.get(metadata)![method][bucket] = count;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return this.redis.del(this.keys.latencyPrefix).then(() => result);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Pop telemetry exceptions.
|
|
88
|
+
* The returned promise rejects if redis operations fail.
|
|
89
|
+
*/
|
|
90
|
+
popExceptions(): Promise<MultiMethodExceptions> {
|
|
91
|
+
return this.redis.hgetall(this.keys.exceptionPrefix).then(exceptions => {
|
|
92
|
+
|
|
93
|
+
const result: MultiMethodExceptions = new _Map();
|
|
94
|
+
|
|
95
|
+
Object.keys(exceptions).forEach(field => {
|
|
96
|
+
|
|
97
|
+
const parsedField = parseExceptionField(field);
|
|
98
|
+
if (isString(parsedField)) {
|
|
99
|
+
this.log.error(`Ignoring invalid exception field: ${field}: ${parsedField}`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const count = parseInt(exceptions[field]);
|
|
104
|
+
if (isNaNNumber(count)) {
|
|
105
|
+
this.log.error(`Ignoring exception with invalid count: ${exceptions[field]}`);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const [metadata, method] = parsedField;
|
|
110
|
+
|
|
111
|
+
if (!result.has(metadata)) result.set(metadata, {
|
|
112
|
+
t: 0,
|
|
113
|
+
ts: 0,
|
|
114
|
+
tc: 0,
|
|
115
|
+
tcs: 0,
|
|
116
|
+
tr: 0,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
result.get(metadata)![method] = count;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return this.redis.del(this.keys.exceptionPrefix).then(() => result);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Pop telemetry configs.
|
|
128
|
+
* The returned promise rejects if redis operations fail.
|
|
129
|
+
*/
|
|
130
|
+
popConfigs(): Promise<MultiConfigs> {
|
|
131
|
+
return this.redis.hgetall(this.keys.initPrefix).then(configs => {
|
|
132
|
+
|
|
133
|
+
const result: MultiConfigs = new _Map();
|
|
134
|
+
|
|
135
|
+
Object.keys(configs).forEach(field => {
|
|
136
|
+
|
|
137
|
+
const parsedField = parseMetadata(field);
|
|
138
|
+
if (isString(parsedField)) {
|
|
139
|
+
this.log.error(`Ignoring invalid config field: ${field}: ${parsedField}`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const [metadata] = parsedField;
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const config = JSON.parse(configs[field]);
|
|
147
|
+
result.set(metadata, config);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
this.log.error(`Ignoring invalid config: ${configs[field]}`);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
return this.redis.del(this.keys.initPrefix).then(() => result);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
36
156
|
}
|