@splitsoftware/splitio-commons 1.8.3-rc.3 → 1.8.4-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 +3 -3
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +17 -0
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +4 -2
- package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +6 -2
- package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +16 -7
- package/cjs/sync/streaming/pushManager.js +18 -3
- package/cjs/trackers/telemetryTracker.js +5 -1
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +17 -0
- package/esm/sync/polling/updaters/splitChangesUpdater.js +4 -2
- package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +6 -2
- package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +13 -4
- package/esm/sync/streaming/pushManager.js +19 -4
- package/esm/trackers/telemetryTracker.js +5 -1
- package/package.json +2 -2
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +21 -1
- package/src/storages/types.ts +2 -1
- package/src/sync/polling/types.ts +2 -1
- package/src/sync/polling/updaters/splitChangesUpdater.ts +6 -4
- package/src/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.ts +6 -2
- package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +15 -6
- package/src/sync/streaming/pushManager.ts +18 -4
- package/src/sync/submitters/types.ts +8 -0
- package/src/trackers/telemetryTracker.ts +6 -1
- package/src/trackers/types.ts +5 -1
- package/types/sdkClient/types.d.ts +18 -0
- package/types/storages/inMemory/CountsCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +7 -1
- package/types/storages/inRedis/CountsCacheInRedis.d.ts +9 -0
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +9 -0
- package/types/storages/metadataBuilder.d.ts +3 -0
- package/types/storages/types.d.ts +2 -1
- package/types/sync/offline/LocalhostFromFile.d.ts +2 -0
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -0
- package/types/sync/polling/types.d.ts +5 -1
- package/types/sync/polling/updaters/splitChangesUpdater.d.ts +4 -1
- package/types/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.d.ts +2 -1
- package/types/sync/streaming/UpdateWorkers/SplitsUpdateWorker.d.ts +2 -1
- package/types/sync/submitters/eventsSyncTask.d.ts +8 -0
- package/types/sync/submitters/impressionCountsSubmitterInRedis.d.ts +5 -0
- package/types/sync/submitters/impressionCountsSyncTask.d.ts +13 -0
- package/types/sync/submitters/impressionsSyncTask.d.ts +14 -0
- package/types/sync/submitters/metricsSyncTask.d.ts +12 -0
- package/types/sync/submitters/submitterSyncTask.d.ts +10 -0
- package/types/sync/submitters/types.d.ts +6 -0
- package/types/sync/submitters/uniqueKeysSubmitterInRedis.d.ts +5 -0
- package/types/sync/syncTaskComposite.d.ts +5 -0
- package/types/trackers/filter/bloomFilter.d.ts +10 -0
- package/types/trackers/filter/dictionaryFilter.d.ts +8 -0
- package/types/trackers/filter/types.d.ts +5 -0
- package/types/trackers/types.d.ts +5 -1
- package/types/utils/timeTracker/index.d.ts +70 -0
- package/types/utils/inputValidation/sdkKey.d.ts +0 -7
- /package/types/storages/inMemory/{UniqueKeysCacheInMemory.d.ts → uniqueKeysCacheInMemory.d.ts} +0 -0
- /package/types/storages/inMemory/{UniqueKeysCacheInMemoryCS.d.ts → uniqueKeysCacheInMemoryCS.d.ts} +0 -0
- /package/types/storages/inRedis/{UniqueKeysCacheInRedis.d.ts → uniqueKeysCacheInRedis.d.ts} +0 -0
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { ISplit } from '../../../dtos/types';
|
|
1
2
|
import { ILogger } from '../../../logger/types';
|
|
2
3
|
import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
|
|
3
4
|
import { ISplitsEventEmitter } from '../../../readiness/types';
|
|
4
5
|
import { ISplitsCacheSync } from '../../../storages/types';
|
|
6
|
+
import { ITelemetryTracker } from '../../../trackers/types';
|
|
5
7
|
import { Backoff } from '../../../utils/Backoff';
|
|
8
|
+
import { SPLITS } from '../../../utils/constants';
|
|
6
9
|
import { ISegmentsSyncTask, ISplitsSyncTask } from '../../polling/types';
|
|
7
10
|
import { ISplitKillData, ISplitUpdateData } from '../SSEHandler/types';
|
|
8
11
|
import { FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT, FETCH_BACKOFF_MAX_RETRIES } from './constants';
|
|
@@ -11,25 +14,27 @@ import { IUpdateWorker } from './types';
|
|
|
11
14
|
/**
|
|
12
15
|
* SplitsUpdateWorker factory
|
|
13
16
|
*/
|
|
14
|
-
export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & { killSplit(event: ISplitKillData): void } {
|
|
17
|
+
export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & { killSplit(event: ISplitKillData): void } {
|
|
15
18
|
|
|
16
19
|
let maxChangeNumber = 0;
|
|
17
20
|
let handleNewEvent = false;
|
|
18
21
|
let isHandlingEvent: boolean;
|
|
19
22
|
let cdnBypass: boolean;
|
|
23
|
+
let payload: ISplit | undefined;
|
|
20
24
|
const backoff = new Backoff(__handleSplitUpdateCall, FETCH_BACKOFF_BASE, FETCH_BACKOFF_MAX_WAIT);
|
|
21
25
|
|
|
22
26
|
function __handleSplitUpdateCall() {
|
|
23
27
|
isHandlingEvent = true;
|
|
24
28
|
if (maxChangeNumber > splitsCache.getChangeNumber()) {
|
|
25
29
|
handleNewEvent = false;
|
|
26
|
-
|
|
30
|
+
const splitUpdateNotification = payload ? { payload, changeNumber: maxChangeNumber } : undefined;
|
|
27
31
|
// fetch splits revalidating data if cached
|
|
28
|
-
splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined).then(() => {
|
|
32
|
+
splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, splitUpdateNotification).then(() => {
|
|
29
33
|
if (!isHandlingEvent) return; // halt if `stop` has been called
|
|
30
34
|
if (handleNewEvent) {
|
|
31
35
|
__handleSplitUpdateCall();
|
|
32
36
|
} else {
|
|
37
|
+
if (splitUpdateNotification) telemetryTracker.trackUpdatesFromSSE(SPLITS);
|
|
33
38
|
// fetch new registered segments for server-side API. Not retrying on error
|
|
34
39
|
if (segmentsSyncTask) segmentsSyncTask.execute(true);
|
|
35
40
|
|
|
@@ -66,7 +71,7 @@ export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync,
|
|
|
66
71
|
*
|
|
67
72
|
* @param {number} changeNumber change number of the SPLIT_UPDATE notification
|
|
68
73
|
*/
|
|
69
|
-
function put({ changeNumber }:
|
|
74
|
+
function put({ changeNumber, pcn }: ISplitUpdateData, _payload?: ISplit) {
|
|
70
75
|
const currentChangeNumber = splitsCache.getChangeNumber();
|
|
71
76
|
|
|
72
77
|
if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
|
|
@@ -74,6 +79,11 @@ export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync,
|
|
|
74
79
|
maxChangeNumber = changeNumber;
|
|
75
80
|
handleNewEvent = true;
|
|
76
81
|
cdnBypass = false;
|
|
82
|
+
payload = undefined;
|
|
83
|
+
|
|
84
|
+
if (_payload && currentChangeNumber === pcn) {
|
|
85
|
+
payload = _payload;
|
|
86
|
+
}
|
|
77
87
|
|
|
78
88
|
if (backoff.timeoutID || !isHandlingEvent) __handleSplitUpdateCall();
|
|
79
89
|
backoff.reset();
|
|
@@ -81,7 +91,6 @@ export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync,
|
|
|
81
91
|
|
|
82
92
|
return {
|
|
83
93
|
put,
|
|
84
|
-
|
|
85
94
|
/**
|
|
86
95
|
* Invoked by NotificationProcessor on SPLIT_KILL event
|
|
87
96
|
*
|
|
@@ -95,7 +104,7 @@ export function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync,
|
|
|
95
104
|
splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, true);
|
|
96
105
|
}
|
|
97
106
|
// queues the SplitChanges fetch (only if changeNumber is newer)
|
|
98
|
-
put({ changeNumber });
|
|
107
|
+
put({ changeNumber } as ISplitUpdateData);
|
|
99
108
|
},
|
|
100
109
|
|
|
101
110
|
stop() {
|
|
@@ -14,7 +14,7 @@ import { getMatching } from '../../utils/key';
|
|
|
14
14
|
import { MY_SEGMENTS_UPDATE, MY_SEGMENTS_UPDATE_V2, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
|
|
15
15
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 } from '../../logger/constants';
|
|
16
16
|
import { KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
|
-
import { isInBitmap, parseBitmap, parseKeyList } from './parseUtils';
|
|
17
|
+
import { isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
|
|
18
18
|
import { ISet, _Set } from '../../utils/lang/sets';
|
|
19
19
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
20
20
|
import { IAuthTokenPushEnabled } from './AuthClient/types';
|
|
@@ -58,7 +58,7 @@ export function pushManagerFactory(
|
|
|
58
58
|
// MySegmentsUpdateWorker (client-side) are initiated in `add` method
|
|
59
59
|
const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
|
|
60
60
|
// For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
|
|
61
|
-
const splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
61
|
+
const splitsUpdateWorker = SplitsUpdateWorker(log, storage.splits, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
|
|
62
62
|
|
|
63
63
|
// [Only for client-side] map of hashes to user keys, to dispatch MY_SEGMENTS_UPDATE events to the corresponding MySegmentsUpdateWorker
|
|
64
64
|
const userKeyHashes: Record<string, string> = {};
|
|
@@ -221,7 +221,21 @@ export function pushManagerFactory(
|
|
|
221
221
|
/** Functions related to synchronization (Queues and Workers in the spec) */
|
|
222
222
|
|
|
223
223
|
pushEmitter.on(SPLIT_KILL, splitsUpdateWorker.killSplit);
|
|
224
|
-
pushEmitter.on(SPLIT_UPDATE,
|
|
224
|
+
pushEmitter.on(SPLIT_UPDATE, (parsedData) => {
|
|
225
|
+
if (parsedData.d && parsedData.c !== undefined) {
|
|
226
|
+
try {
|
|
227
|
+
const payload = parseFFUpdatePayload(parsedData.c, parsedData.d);
|
|
228
|
+
if (payload) {
|
|
229
|
+
splitsUpdateWorker.put(parsedData, payload);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
} catch (e) {
|
|
233
|
+
// @TODO define a error code for feature flags parsing
|
|
234
|
+
log.debug(e);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
splitsUpdateWorker.put(parsedData);
|
|
238
|
+
});
|
|
225
239
|
|
|
226
240
|
if (userKey) {
|
|
227
241
|
pushEmitter.on(MY_SEGMENTS_UPDATE, function handleMySegmentsUpdate(parsedData, channel) {
|
|
@@ -330,7 +344,7 @@ export function pushManagerFactory(
|
|
|
330
344
|
|
|
331
345
|
if (!userKeyHashes[hash]) {
|
|
332
346
|
userKeyHashes[hash] = userKey;
|
|
333
|
-
clients[userKey] = { hash64: hash64(userKey), worker: MySegmentsUpdateWorker(mySegmentsSyncTask) };
|
|
347
|
+
clients[userKey] = { hash64: hash64(userKey), worker: MySegmentsUpdateWorker(mySegmentsSyncTask, telemetryTracker) };
|
|
334
348
|
connectForNewClient = true; // we must reconnect on start, to listen the channel for the new user key
|
|
335
349
|
|
|
336
350
|
// Reconnects in case of a new client.
|
|
@@ -103,6 +103,7 @@ export type DROPPED = 1;
|
|
|
103
103
|
export type DEDUPED = 2;
|
|
104
104
|
export type ImpressionDataType = QUEUED | DROPPED | DEDUPED
|
|
105
105
|
export type EventDataType = QUEUED | DROPPED;
|
|
106
|
+
export type UpdatesFromSSEEnum = SPLITS | MY_SEGMENT;
|
|
106
107
|
|
|
107
108
|
export type SPLITS = 'sp';
|
|
108
109
|
export type IMPRESSIONS = 'im';
|
|
@@ -151,6 +152,12 @@ export type TelemetryUsageStats = {
|
|
|
151
152
|
mE?: MethodExceptions, // methodExceptions
|
|
152
153
|
}
|
|
153
154
|
|
|
155
|
+
// amount of instant updates that we are doing by avoiding fetching to Split servers
|
|
156
|
+
export type UpdatesFromSSE = {
|
|
157
|
+
sp: number, // splits
|
|
158
|
+
ms?: number, // my segments
|
|
159
|
+
}
|
|
160
|
+
|
|
154
161
|
// 'metrics/usage' JSON request body
|
|
155
162
|
export type TelemetryUsageStatsPayload = TelemetryUsageStats & {
|
|
156
163
|
lS: LastSync, // lastSynchronization
|
|
@@ -169,6 +176,7 @@ export type TelemetryUsageStatsPayload = TelemetryUsageStats & {
|
|
|
169
176
|
eD: number, // eventsDropped
|
|
170
177
|
sE: Array<StreamingEvent>, // streamingEvents
|
|
171
178
|
t?: Array<string>, // tags
|
|
179
|
+
ufs?: UpdatesFromSSE, //UpdatesFromSSE
|
|
172
180
|
}
|
|
173
181
|
|
|
174
182
|
/**
|
|
@@ -3,6 +3,7 @@ import { EXCEPTION, SDK_NOT_READY } from '../utils/labels';
|
|
|
3
3
|
import { ITelemetryTracker } from './types';
|
|
4
4
|
import { timer } from '../utils/timeTracker/timer';
|
|
5
5
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../utils/constants';
|
|
6
|
+
import { UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
6
7
|
|
|
7
8
|
export function telemetryTrackerFactory(
|
|
8
9
|
telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
@@ -52,6 +53,9 @@ export function telemetryTrackerFactory(
|
|
|
52
53
|
addTag(tag: string) {
|
|
53
54
|
// @ts-ignore
|
|
54
55
|
if (telemetryCache.addTag) telemetryCache.addTag(tag);
|
|
56
|
+
},
|
|
57
|
+
trackUpdatesFromSSE(type: UpdatesFromSSEEnum) {
|
|
58
|
+
(telemetryCache as ITelemetryCacheSync).recordUpdatesFromSSE(type);
|
|
55
59
|
}
|
|
56
60
|
};
|
|
57
61
|
|
|
@@ -62,7 +66,8 @@ export function telemetryTrackerFactory(
|
|
|
62
66
|
trackHttp: noopTrack,
|
|
63
67
|
sessionLength() { },
|
|
64
68
|
streamingEvent() { },
|
|
65
|
-
addTag() { }
|
|
69
|
+
addTag() { },
|
|
70
|
+
trackUpdatesFromSSE() { },
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
}
|
package/src/trackers/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SplitIO, ImpressionDTO } from '../types';
|
|
2
|
-
import { StreamingEventType, Method, OperationType } from '../sync/submitters/types';
|
|
2
|
+
import { StreamingEventType, Method, OperationType, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
3
3
|
import { IEventsCacheBase } from '../storages/types';
|
|
4
4
|
import { NetworkError } from '../services/types';
|
|
5
5
|
|
|
@@ -45,6 +45,10 @@ export interface ITelemetryTracker {
|
|
|
45
45
|
* Records tag
|
|
46
46
|
*/
|
|
47
47
|
addTag(tag: string): void
|
|
48
|
+
/**
|
|
49
|
+
* Records updates from sse
|
|
50
|
+
*/
|
|
51
|
+
trackUpdatesFromSSE(type: UpdatesFromSSEEnum): void;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
export interface IFilterAdapter {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ISignalListener } from '../listeners/types';
|
|
2
|
+
import { ISdkReadinessManager } from '../readiness/types';
|
|
3
|
+
import { IStorageAsync, IStorageSync } from '../storages/types';
|
|
4
|
+
import { ISyncManager } from '../sync/types';
|
|
5
|
+
import { IEventTracker, IImpressionsTracker } from '../trackers/types';
|
|
6
|
+
import { ISettings } from '../types';
|
|
7
|
+
export interface IClientFactoryParams {
|
|
8
|
+
storage: IStorageSync | IStorageAsync;
|
|
9
|
+
sdkReadinessManager: ISdkReadinessManager;
|
|
10
|
+
settings: ISettings;
|
|
11
|
+
impressionsTracker: IImpressionsTracker;
|
|
12
|
+
eventTracker: IEventTracker;
|
|
13
|
+
}
|
|
14
|
+
export interface ISdkClientFactoryParams extends IClientFactoryParams {
|
|
15
|
+
signalListener?: ISignalListener;
|
|
16
|
+
syncManager?: ISyncManager;
|
|
17
|
+
sharedClient?: boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ICountsCacheSync } from '../types';
|
|
2
|
+
export declare class CountsCacheInMemory implements ICountsCacheSync {
|
|
3
|
+
private counters;
|
|
4
|
+
/**
|
|
5
|
+
* Add counts.
|
|
6
|
+
*/
|
|
7
|
+
track(metricName: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Clear the collector
|
|
10
|
+
*/
|
|
11
|
+
clear(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get the collected data, used as payload for posting.
|
|
14
|
+
*/
|
|
15
|
+
state(): Record<string, number>;
|
|
16
|
+
/**
|
|
17
|
+
* Check if the cache is empty.
|
|
18
|
+
*/
|
|
19
|
+
isEmpty(): boolean;
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ILatenciesCacheSync } from '../types';
|
|
2
|
+
export declare class LatenciesCacheInMemory implements ILatenciesCacheSync {
|
|
3
|
+
private counters;
|
|
4
|
+
/**
|
|
5
|
+
* Add latencies.
|
|
6
|
+
*/
|
|
7
|
+
track(metricName: string, latency: number): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Clear the collector
|
|
10
|
+
*/
|
|
11
|
+
clear(): void;
|
|
12
|
+
/**
|
|
13
|
+
* Get the collected data, used as payload for posting.
|
|
14
|
+
*/
|
|
15
|
+
state(): Record<string, number[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Check if the cache is empty.
|
|
18
|
+
*/
|
|
19
|
+
isEmpty(): boolean;
|
|
20
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ImpressionDataType, EventDataType, StreamingEvent, Method, OperationType, TelemetryUsageStatsPayload } from '../../sync/submitters/types';
|
|
1
|
+
import { ImpressionDataType, EventDataType, StreamingEvent, Method, OperationType, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../../sync/submitters/types';
|
|
2
2
|
import { ISegmentsCacheSync, ISplitsCacheSync, IStorageFactoryParams, ITelemetryCacheSync } from '../types';
|
|
3
3
|
export declare const MAX_LATENCY_BUCKET_COUNT = 23;
|
|
4
4
|
export declare function newBuckets(): number[];
|
|
@@ -64,4 +64,10 @@ export declare class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
64
64
|
private latencies;
|
|
65
65
|
popLatencies(): Partial<Record<Method, number[]>>;
|
|
66
66
|
recordLatency(method: Method, latencyMs: number): void;
|
|
67
|
+
private updatesFromSSE;
|
|
68
|
+
popUpdatesFromSSE(): {
|
|
69
|
+
sp: number;
|
|
70
|
+
ms: number;
|
|
71
|
+
};
|
|
72
|
+
recordUpdatesFromSSE(type: UpdatesFromSSEEnum): void;
|
|
67
73
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ICountsCacheAsync } from '../types';
|
|
2
|
+
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
3
|
+
import { Redis } from 'ioredis';
|
|
4
|
+
export declare class CountsCacheInRedis implements ICountsCacheAsync {
|
|
5
|
+
private readonly redis;
|
|
6
|
+
private readonly keys;
|
|
7
|
+
constructor(keys: KeyBuilderSS, redis: Redis);
|
|
8
|
+
track(metricName: string): Promise<boolean>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ILatenciesCacheAsync } from '../types';
|
|
2
|
+
import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
3
|
+
import { Redis } from 'ioredis';
|
|
4
|
+
export declare class LatenciesCacheInRedis implements ILatenciesCacheAsync {
|
|
5
|
+
private readonly redis;
|
|
6
|
+
private readonly keys;
|
|
7
|
+
constructor(keys: KeyBuilderSS, redis: Redis);
|
|
8
|
+
track(metricName: string, latency: number): Promise<boolean>;
|
|
9
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MaybeThenable, ISplit } from '../dtos/types';
|
|
2
|
-
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload } from '../sync/submitters/types';
|
|
2
|
+
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
3
3
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
4
4
|
/**
|
|
5
5
|
* Interface of a pluggable storage wrapper.
|
|
@@ -343,6 +343,7 @@ export interface ITelemetryRuntimeProducerSync {
|
|
|
343
343
|
recordTokenRefreshes(): void;
|
|
344
344
|
recordStreamingEvents(streamingEvent: StreamingEvent): void;
|
|
345
345
|
recordSessionLength(ms: number): void;
|
|
346
|
+
recordUpdatesFromSSE(type: UpdatesFromSSEEnum): void;
|
|
346
347
|
}
|
|
347
348
|
export interface ITelemetryEvaluationProducerSync {
|
|
348
349
|
recordLatency(method: Method, latencyMs: number): void;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { ISplit } from '../../dtos/types';
|
|
1
2
|
import { IReadinessManager } from '../../readiness/types';
|
|
2
3
|
import { IStorageSync } from '../../storages/types';
|
|
3
4
|
import { ITask, ISyncTask } from '../types';
|
|
4
|
-
export interface ISplitsSyncTask extends ISyncTask<[noCache?: boolean, till?: number
|
|
5
|
+
export interface ISplitsSyncTask extends ISyncTask<[noCache?: boolean, till?: number, splitUpdateNotification?: {
|
|
6
|
+
payload: ISplit;
|
|
7
|
+
changeNumber: number;
|
|
8
|
+
}], boolean> {
|
|
5
9
|
}
|
|
6
10
|
export interface ISegmentsSyncTask extends ISyncTask<[fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number], boolean> {
|
|
7
11
|
}
|
|
@@ -4,7 +4,10 @@ import { ISplitChangesFetcher } from '../fetchers/types';
|
|
|
4
4
|
import { ISplit } from '../../../dtos/types';
|
|
5
5
|
import { ISplitsEventEmitter } from '../../../readiness/types';
|
|
6
6
|
import { ILogger } from '../../../logger/types';
|
|
7
|
-
declare type ISplitChangesUpdater = (noCache?: boolean, till?: number
|
|
7
|
+
declare type ISplitChangesUpdater = (noCache?: boolean, till?: number, splitUpdateNotification?: {
|
|
8
|
+
payload: ISplit;
|
|
9
|
+
changeNumber: number;
|
|
10
|
+
}) => Promise<boolean>;
|
|
8
11
|
/**
|
|
9
12
|
* Collect segments from a raw split definition.
|
|
10
13
|
* Exported for testing purposes.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IMySegmentsSyncTask } from '../../polling/types';
|
|
2
2
|
import { IUpdateWorker } from './types';
|
|
3
|
+
import { ITelemetryTracker } from '../../../trackers/types';
|
|
3
4
|
/**
|
|
4
5
|
* MySegmentsUpdateWorker factory
|
|
5
6
|
*/
|
|
6
|
-
export declare function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask): IUpdateWorker;
|
|
7
|
+
export declare function MySegmentsUpdateWorker(mySegmentsSyncTask: IMySegmentsSyncTask, telemetryTracker: ITelemetryTracker): IUpdateWorker;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ILogger } from '../../../logger/types';
|
|
2
2
|
import { ISplitsEventEmitter } from '../../../readiness/types';
|
|
3
3
|
import { ISplitsCacheSync } from '../../../storages/types';
|
|
4
|
+
import { ITelemetryTracker } from '../../../trackers/types';
|
|
4
5
|
import { ISegmentsSyncTask, ISplitsSyncTask } from '../../polling/types';
|
|
5
6
|
import { ISplitKillData } from '../SSEHandler/types';
|
|
6
7
|
import { IUpdateWorker } from './types';
|
|
7
8
|
/**
|
|
8
9
|
* SplitsUpdateWorker factory
|
|
9
10
|
*/
|
|
10
|
-
export declare function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & {
|
|
11
|
+
export declare function SplitsUpdateWorker(log: ILogger, splitsCache: ISplitsCacheSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker & {
|
|
11
12
|
killSplit(event: ISplitKillData): void;
|
|
12
13
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IEventsCacheSync } from '../../storages/types';
|
|
2
|
+
import { IPostEventsBulk } from '../../services/types';
|
|
3
|
+
import { ISyncTask, ITimeTracker } from '../types';
|
|
4
|
+
import { ILogger } from '../../logger/types';
|
|
5
|
+
/**
|
|
6
|
+
* Sync task that periodically posts tracked events
|
|
7
|
+
*/
|
|
8
|
+
export declare function eventsSyncTaskFactory(log: ILogger, postEventsBulk: IPostEventsBulk, eventsCache: IEventsCacheSync, eventsPushRate: number, eventsFirstPushWindow: number, latencyTracker?: ITimeTracker): ISyncTask;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ISyncTask, ITimeTracker } from '../types';
|
|
2
|
+
import { IPostTestImpressionsCount } from '../../services/types';
|
|
3
|
+
import { IImpressionCountsCacheSync } from '../../storages/types';
|
|
4
|
+
import { ImpressionCountsPayload } from './types';
|
|
5
|
+
import { ILogger } from '../../logger/types';
|
|
6
|
+
/**
|
|
7
|
+
* Converts `impressionCounts` data from cache into request payload.
|
|
8
|
+
*/
|
|
9
|
+
export declare function fromImpressionCountsCollector(impressionsCount: Record<string, number>): ImpressionCountsPayload;
|
|
10
|
+
/**
|
|
11
|
+
* Sync task that periodically posts impression counts
|
|
12
|
+
*/
|
|
13
|
+
export declare function impressionCountsSyncTaskFactory(log: ILogger, postTestImpressionsCount: IPostTestImpressionsCount, impressionCountsCache: IImpressionCountsCacheSync, latencyTracker?: ITimeTracker): ISyncTask;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ISyncTask, ITimeTracker } from '../types';
|
|
2
|
+
import { IPostTestImpressionsBulk } from '../../services/types';
|
|
3
|
+
import { IImpressionsCacheSync } from '../../storages/types';
|
|
4
|
+
import { ImpressionDTO } from '../../types';
|
|
5
|
+
import { ImpressionsPayload } from './types';
|
|
6
|
+
import { ILogger } from '../../logger/types';
|
|
7
|
+
/**
|
|
8
|
+
* Converts `impressions` data from cache into request payload.
|
|
9
|
+
*/
|
|
10
|
+
export declare function fromImpressionsCollector(sendLabels: boolean, data: ImpressionDTO[]): ImpressionsPayload;
|
|
11
|
+
/**
|
|
12
|
+
* Sync task that periodically posts impressions data
|
|
13
|
+
*/
|
|
14
|
+
export declare function impressionsSyncTaskFactory(log: ILogger, postTestImpressionsBulk: IPostTestImpressionsBulk, impressionsCache: IImpressionsCacheSync, impressionsRefreshRate: number, sendLabels?: boolean, latencyTracker?: ITimeTracker): ISyncTask;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ICountsCacheSync, ILatenciesCacheSync } from '../../storages/types';
|
|
2
|
+
import { IPostMetricsCounters, IPostMetricsTimes } from '../../services/types';
|
|
3
|
+
import { ISyncTask, ITimeTracker } from '../types';
|
|
4
|
+
import { ILogger } from '../../logger/types';
|
|
5
|
+
/**
|
|
6
|
+
* Sync task that periodically posts telemetry counts
|
|
7
|
+
*/
|
|
8
|
+
export declare function countsSyncTaskFactory(log: ILogger, postMetricsCounters: IPostMetricsCounters, countsCache: ICountsCacheSync, metricsRefreshRate: number, latencyTracker?: ITimeTracker): ISyncTask;
|
|
9
|
+
/**
|
|
10
|
+
* Sync task that periodically posts telemetry latencies
|
|
11
|
+
*/
|
|
12
|
+
export declare function latenciesSyncTaskFactory(log: ILogger, postMetricsLatencies: IPostMetricsTimes, latenciesCache: ILatenciesCacheSync, metricsRefreshRate: number, latencyTracker?: ITimeTracker): ISyncTask;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ISyncTask, ITimeTracker } from '../types';
|
|
2
|
+
import { IRecorderCacheProducerSync } from '../../storages/types';
|
|
3
|
+
import { ILogger } from '../../logger/types';
|
|
4
|
+
import { IResponse } from '../../services/types';
|
|
5
|
+
/**
|
|
6
|
+
* Base function to create submitter sync tasks, such as ImpressionsSyncTask and EventsSyncTask
|
|
7
|
+
*/
|
|
8
|
+
export declare function submitterSyncTaskFactory<TState extends {
|
|
9
|
+
length?: number;
|
|
10
|
+
}>(log: ILogger, postClient: (body: string) => Promise<IResponse>, sourceCache: IRecorderCacheProducerSync<TState>, postRate: number, dataName: string, latencyTracker?: ITimeTracker, fromCacheToPayload?: (cacheData: TState) => any, maxRetries?: number, debugLogs?: boolean): ISyncTask<[], void>;
|
|
@@ -90,6 +90,7 @@ export declare type DROPPED = 1;
|
|
|
90
90
|
export declare type DEDUPED = 2;
|
|
91
91
|
export declare type ImpressionDataType = QUEUED | DROPPED | DEDUPED;
|
|
92
92
|
export declare type EventDataType = QUEUED | DROPPED;
|
|
93
|
+
export declare type UpdatesFromSSEEnum = SPLITS | MY_SEGMENT;
|
|
93
94
|
export declare type SPLITS = 'sp';
|
|
94
95
|
export declare type IMPRESSIONS = 'im';
|
|
95
96
|
export declare type IMPRESSIONS_COUNT = 'ic';
|
|
@@ -130,6 +131,10 @@ export declare type TelemetryUsageStats = {
|
|
|
130
131
|
mL?: MethodLatencies;
|
|
131
132
|
mE?: MethodExceptions;
|
|
132
133
|
};
|
|
134
|
+
export declare type UpdatesFromSSE = {
|
|
135
|
+
sp: number;
|
|
136
|
+
ms?: number;
|
|
137
|
+
};
|
|
133
138
|
export declare type TelemetryUsageStatsPayload = TelemetryUsageStats & {
|
|
134
139
|
lS: LastSync;
|
|
135
140
|
hE: HttpErrors;
|
|
@@ -147,6 +152,7 @@ export declare type TelemetryUsageStatsPayload = TelemetryUsageStats & {
|
|
|
147
152
|
eD: number;
|
|
148
153
|
sE: Array<StreamingEvent>;
|
|
149
154
|
t?: Array<string>;
|
|
155
|
+
ufs?: UpdatesFromSSE;
|
|
150
156
|
};
|
|
151
157
|
/**
|
|
152
158
|
* Telemetry config stats
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IFilter } from './types';
|
|
2
|
+
export declare class BloomFilterImp implements IFilter {
|
|
3
|
+
private spectedInsertions;
|
|
4
|
+
private errorRate;
|
|
5
|
+
private filter;
|
|
6
|
+
constructor(spectedInsertions: number, errorRate: number);
|
|
7
|
+
add(data: string): boolean;
|
|
8
|
+
contains(data: string): boolean;
|
|
9
|
+
clear(): void;
|
|
10
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SplitIO, ImpressionDTO } from '../types';
|
|
2
|
-
import { StreamingEventType, Method, OperationType } from '../sync/submitters/types';
|
|
2
|
+
import { StreamingEventType, Method, OperationType, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
3
3
|
import { IEventsCacheBase } from '../storages/types';
|
|
4
4
|
import { NetworkError } from '../services/types';
|
|
5
5
|
/** Events tracker */
|
|
@@ -37,6 +37,10 @@ export interface ITelemetryTracker {
|
|
|
37
37
|
* Records tag
|
|
38
38
|
*/
|
|
39
39
|
addTag(tag: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Records updates from sse
|
|
42
|
+
*/
|
|
43
|
+
trackUpdatesFromSSE(type: UpdatesFromSSEEnum): void;
|
|
40
44
|
}
|
|
41
45
|
export interface IFilterAdapter {
|
|
42
46
|
add(key: string, featureName: string): boolean;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ILogger } from '../../logger/types';
|
|
2
|
+
import { IResponse } from '../../services/types';
|
|
3
|
+
interface MetricsCollector {
|
|
4
|
+
countException(): void;
|
|
5
|
+
count(status: number): void;
|
|
6
|
+
latency(ms: number): void;
|
|
7
|
+
ready(ms: number): void;
|
|
8
|
+
getTreatment(ms: number): void;
|
|
9
|
+
getTreatments(ms: number): void;
|
|
10
|
+
getTreatmentWithConfig(ms: number): void;
|
|
11
|
+
getTreatmentsWithConfig(ms: number): void;
|
|
12
|
+
[method: string]: (ms: number) => void;
|
|
13
|
+
}
|
|
14
|
+
export declare const TrackerAPI: {
|
|
15
|
+
/**
|
|
16
|
+
* "Private" method, used to attach count/countException and stop callbacks to a promise.
|
|
17
|
+
*
|
|
18
|
+
* @param {ILogger} log - Logger.
|
|
19
|
+
* @param {Promise} promise - The promise we want to attach the callbacks.
|
|
20
|
+
* @param {string} task - The name of the task.
|
|
21
|
+
* @param {number | string} modifier - (optional) The modifier for the task, if any.
|
|
22
|
+
*/
|
|
23
|
+
__attachToPromise(log: ILogger, promise: Promise<IResponse>, task: string, collector: false | MetricsCollector, modifier?: string | number | undefined): Promise<IResponse>;
|
|
24
|
+
/**
|
|
25
|
+
* Starts tracking the time for a given task. All tasks tracked are considered "unique" because
|
|
26
|
+
* there may be multiple SDK instances tracking a "generic" task, making any task non-generic.
|
|
27
|
+
*
|
|
28
|
+
* @param {ILogger} log - Logger.
|
|
29
|
+
* @param {string} task - The task we are starting.
|
|
30
|
+
* @param {Object} collectors - The collectors map.
|
|
31
|
+
* @param {Promise} promise - (optional) The promise we are tracking.
|
|
32
|
+
* @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered.
|
|
33
|
+
*/
|
|
34
|
+
start(log: ILogger, task: string, collectors?: Record<string, MetricsCollector> | undefined, promise?: Promise<IResponse> | undefined, now?: (() => number) | undefined): Promise<IResponse> | (() => number);
|
|
35
|
+
/**
|
|
36
|
+
* Setup the collector for a task that reports metrics.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} task - The task name
|
|
39
|
+
* @param {number | string} taskUniqueId - The unique identifier for this task
|
|
40
|
+
* @param {Object} collectors - The collectors map.
|
|
41
|
+
*/
|
|
42
|
+
setCollectorForTask(task: string, taskUniqueId: number | string, collectors: Record<string, MetricsCollector>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Stops the tracking of a given task.
|
|
45
|
+
*
|
|
46
|
+
* @param {ILogger} log - Logger.
|
|
47
|
+
* @param {string} task - The task we are starting.
|
|
48
|
+
* @param {number | string} modifier - (optional) The modifier for that specific task.
|
|
49
|
+
*/
|
|
50
|
+
stop(log: ILogger, task: string, modifier?: string | number | undefined): number | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* The constants shortcut for the task names.
|
|
53
|
+
*/
|
|
54
|
+
TaskNames: {
|
|
55
|
+
SDK_READY: string;
|
|
56
|
+
SDK_GET_TREATMENT: string;
|
|
57
|
+
SDK_GET_TREATMENTS: string;
|
|
58
|
+
SDK_GET_TREATMENT_WITH_CONFIG: string;
|
|
59
|
+
SDK_GET_TREATMENTS_WITH_CONFIG: string;
|
|
60
|
+
SPLITS_READY: string;
|
|
61
|
+
SEGMENTS_READY: string;
|
|
62
|
+
METRICS_PUSH: string;
|
|
63
|
+
IMPRESSIONS_PUSH: string;
|
|
64
|
+
EVENTS_PUSH: string;
|
|
65
|
+
MY_SEGMENTS_FETCH: string;
|
|
66
|
+
SEGMENTS_FETCH: string;
|
|
67
|
+
SPLITS_FETCH: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { ILogger } from '../../logger/types';
|
|
2
|
-
/** validates the given SDK key */
|
|
3
|
-
export declare function validateApiKey(log: ILogger, maybeSdkKey: any): string | false;
|
|
4
|
-
export declare const usedKeysMap: Record<string, number>;
|
|
5
|
-
/** validates the given SDK key and also warns if it is in use */
|
|
6
|
-
export declare function validateAndTrackApiKey(log: ILogger, maybeSdkKey: any): string | false;
|
|
7
|
-
export declare function releaseApiKey(sdkKey: string): void;
|
/package/types/storages/inMemory/{UniqueKeysCacheInMemory.d.ts → uniqueKeysCacheInMemory.d.ts}
RENAMED
|
File without changes
|
/package/types/storages/inMemory/{UniqueKeysCacheInMemoryCS.d.ts → uniqueKeysCacheInMemoryCS.d.ts}
RENAMED
|
File without changes
|
|
File without changes
|