@splitsoftware/splitio-commons 1.6.2-rc.6 → 1.6.2-rc.7
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 -0
- package/cjs/consent/sdkUserConsent.js +2 -2
- package/cjs/listeners/browser.js +2 -1
- package/cjs/logger/constants.js +2 -1
- package/cjs/sdkClient/sdkClient.js +3 -1
- package/cjs/sdkFactory/index.js +26 -5
- package/cjs/services/splitApi.js +20 -0
- package/cjs/storages/KeyBuilderSS.js +6 -0
- package/cjs/storages/inLocalStorage/index.js +4 -0
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +5 -1
- package/cjs/storages/inMemory/InMemoryStorageCS.js +5 -1
- package/cjs/storages/inMemory/uniqueKeysCacheInMemory.js +73 -0
- package/cjs/storages/inMemory/uniqueKeysCacheInMemoryCS.js +78 -0
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +49 -0
- package/cjs/storages/inRedis/constants.js +4 -1
- package/cjs/storages/inRedis/index.js +15 -1
- package/cjs/storages/inRedis/uniqueKeysCacheInRedis.js +56 -0
- package/cjs/sync/submitters/submitterManager.js +3 -0
- package/cjs/sync/submitters/telemetrySubmitter.js +1 -0
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +26 -0
- 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/settingsValidation/impressionsMode.js +2 -2
- package/cjs/utils/settingsValidation/index.js +4 -0
- package/esm/consent/sdkUserConsent.js +2 -2
- package/esm/listeners/browser.js +3 -2
- package/esm/logger/constants.js +1 -0
- package/esm/sdkClient/sdkClient.js +3 -1
- package/esm/sdkFactory/index.js +26 -5
- package/esm/services/splitApi.js +20 -0
- package/esm/storages/KeyBuilderSS.js +6 -0
- package/esm/storages/inLocalStorage/index.js +5 -1
- package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +12 -1
- package/esm/storages/inMemory/InMemoryStorage.js +6 -2
- package/esm/storages/inMemory/InMemoryStorageCS.js +6 -2
- package/esm/storages/inMemory/uniqueKeysCacheInMemory.js +70 -0
- package/esm/storages/inMemory/uniqueKeysCacheInMemoryCS.js +75 -0
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +46 -0
- package/esm/storages/inRedis/constants.js +3 -0
- package/esm/storages/inRedis/index.js +16 -2
- package/esm/storages/inRedis/uniqueKeysCacheInRedis.js +53 -0
- package/esm/sync/submitters/submitterManager.js +3 -0
- package/esm/sync/submitters/telemetrySubmitter.js +2 -1
- package/esm/sync/submitters/uniqueKeysSubmitter.js +22 -0
- 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/settingsValidation/impressionsMode.js +3 -3
- package/esm/utils/settingsValidation/index.js +4 -0
- package/package.json +1 -1
- package/src/consent/sdkUserConsent.ts +2 -2
- package/src/listeners/browser.ts +3 -2
- package/src/logger/constants.ts +1 -0
- package/src/sdkClient/sdkClient.ts +3 -1
- package/src/sdkFactory/index.ts +29 -5
- 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 +0 -1
- package/src/storages/KeyBuilderSS.ts +8 -0
- package/src/storages/inLocalStorage/index.ts +4 -1
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +16 -1
- package/src/storages/inMemory/InMemoryStorage.ts +5 -2
- package/src/storages/inMemory/InMemoryStorageCS.ts +6 -2
- package/src/storages/inMemory/uniqueKeysCacheInMemory.ts +82 -0
- package/src/storages/inMemory/uniqueKeysCacheInMemoryCS.ts +88 -0
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +51 -0
- package/src/storages/inRedis/constants.ts +3 -0
- package/src/storages/inRedis/index.ts +12 -3
- package/src/storages/inRedis/uniqueKeysCacheInRedis.ts +63 -0
- package/src/storages/types.ts +30 -8
- package/src/sync/submitters/submitterManager.ts +2 -0
- package/src/sync/submitters/telemetrySubmitter.ts +4 -3
- package/src/sync/submitters/types.ts +20 -1
- package/src/sync/submitters/uniqueKeysSubmitter.ts +35 -0
- package/src/trackers/impressionsTracker.ts +27 -48
- 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 +5 -1
- package/src/utils/constants/index.ts +2 -0
- package/src/utils/settingsValidation/impressionsMode.ts +3 -3
- package/src/utils/settingsValidation/index.ts +5 -0
- package/types/logger/constants.d.ts +1 -0
- package/types/sdkClient/types.d.ts +18 -0
- package/types/sdkFactory/types.d.ts +4 -2
- package/types/services/types.d.ts +4 -0
- package/types/storages/KeyBuilderSS.d.ts +2 -0
- package/types/storages/inMemory/CountsCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/ImpressionCountsCacheInMemory.d.ts +5 -1
- package/types/storages/inMemory/LatenciesCacheInMemory.d.ts +20 -0
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +35 -0
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +37 -0
- package/types/storages/inRedis/CountsCacheInRedis.d.ts +9 -0
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +14 -0
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +9 -0
- package/types/storages/inRedis/constants.d.ts +3 -0
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +15 -0
- package/types/storages/types.d.ts +18 -5
- package/types/sync/offline/LocalhostFromFile.d.ts +2 -0
- package/types/sync/offline/splitsParser/splitsParserFromFile.d.ts +2 -0
- 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 +18 -1
- package/types/sync/submitters/uniqueKeysSubmitter.d.ts +5 -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/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 +5 -1
- package/types/utils/constants/index.d.ts +2 -0
- package/types/utils/settingsValidation/index.d.ts +1 -0
- package/types/utils/timeTracker/index.d.ts +70 -0
- package/src/logger/.DS_Store +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { IUniqueKeysCacheBase } from '../types';
|
|
2
|
+
import { Redis } from 'ioredis';
|
|
3
|
+
import { UniqueKeysCacheInMemory } from '../inMemory/uniqueKeysCacheInMemory';
|
|
4
|
+
import { setToArray } from '../../utils/lang/sets';
|
|
5
|
+
import { DEFAULT_CACHE_SIZE, REFRESH_RATE, TTL_REFRESH } from './constants';
|
|
6
|
+
import { LOG_PREFIX } from './constants';
|
|
7
|
+
import { ILogger } from '../../logger/types';
|
|
8
|
+
|
|
9
|
+
export class UniqueKeysCacheInRedis extends UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
10
|
+
|
|
11
|
+
private readonly log: ILogger;
|
|
12
|
+
private readonly key: string;
|
|
13
|
+
private readonly redis: Redis;
|
|
14
|
+
private readonly refreshRate: number;
|
|
15
|
+
private intervalId: any;
|
|
16
|
+
|
|
17
|
+
constructor(log: ILogger, key: string, redis: Redis, uniqueKeysQueueSize: number = DEFAULT_CACHE_SIZE, refreshRate: number = REFRESH_RATE) {
|
|
18
|
+
super(uniqueKeysQueueSize);
|
|
19
|
+
this.log = log;
|
|
20
|
+
this.key = key;
|
|
21
|
+
this.redis = redis;
|
|
22
|
+
this.refreshRate = refreshRate;
|
|
23
|
+
this.onFullQueue = () => {this.postUniqueKeysInRedis();};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
postUniqueKeysInRedis() {
|
|
27
|
+
const pipeline = this.redis.pipeline();
|
|
28
|
+
|
|
29
|
+
const featureNames = Object.keys(this.uniqueKeysTracker);
|
|
30
|
+
for (let i = 0; i < featureNames.length; i++) {
|
|
31
|
+
const featureName = featureNames[i];
|
|
32
|
+
const featureKeys = setToArray(this.uniqueKeysTracker[featureName]);
|
|
33
|
+
const uniqueKeysPayload = {
|
|
34
|
+
f: featureName,
|
|
35
|
+
ks: featureKeys
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
pipeline.rpush(this.key, JSON.stringify(uniqueKeysPayload));
|
|
39
|
+
}
|
|
40
|
+
this.clear();
|
|
41
|
+
return pipeline.exec()
|
|
42
|
+
.then(data => {
|
|
43
|
+
// If this is the creation of the key on Redis, set the expiration for it in 3600 seconds.
|
|
44
|
+
if (data.length && data.length === featureNames.length) {
|
|
45
|
+
return this.redis.expire(this.key, TTL_REFRESH);
|
|
46
|
+
}
|
|
47
|
+
})
|
|
48
|
+
.catch(err => {
|
|
49
|
+
this.log.error(`${LOG_PREFIX}Error in uniqueKeys pipeline: ${err}.`);
|
|
50
|
+
return false;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
start() {
|
|
56
|
+
this.intervalId = setInterval(this.postUniqueKeysInRedis.bind(this), this.refreshRate);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
stop() {
|
|
60
|
+
clearInterval(this.intervalId);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
package/src/storages/types.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MaybeThenable, IMetadata, ISplitFiltersValidation, ISplit } from '../dtos/types';
|
|
2
2
|
import { ILogger } from '../logger/types';
|
|
3
|
-
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent } from '../sync/submitters/types';
|
|
3
|
+
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs } from '../sync/submitters/types';
|
|
4
4
|
import { SplitIO, ImpressionDTO, SDKMode } from '../types';
|
|
5
5
|
|
|
6
6
|
/**
|
|
@@ -347,7 +347,7 @@ export interface IEventsCacheAsync extends IEventsCacheBase, IRecorderCacheProdu
|
|
|
347
347
|
* Only in memory. Named `ImpressionsCounter` in spec.
|
|
348
348
|
*/
|
|
349
349
|
export interface IImpressionCountsCacheSync extends IRecorderCacheProducerSync<Record<string, number>> {
|
|
350
|
-
|
|
350
|
+
// Used by impressions tracker
|
|
351
351
|
track(featureName: string, timeFrame: number, amount: number): void
|
|
352
352
|
|
|
353
353
|
// Used by impressions count submitter in standalone and producer mode
|
|
@@ -355,6 +355,17 @@ export interface IImpressionCountsCacheSync extends IRecorderCacheProducerSync<R
|
|
|
355
355
|
pop(toMerge?: Record<string, number> ): Record<string, number> // pop cache data
|
|
356
356
|
}
|
|
357
357
|
|
|
358
|
+
export interface IUniqueKeysCacheBase {
|
|
359
|
+
// Used by unique Keys tracker
|
|
360
|
+
track(key: string, value: string): void
|
|
361
|
+
|
|
362
|
+
// Used by unique keys submitter in standalone and producer mode
|
|
363
|
+
isEmpty(): boolean // check if cache is empty. Return true if the cache was just created or cleared.
|
|
364
|
+
pop(): UniqueKeysPayloadSs | UniqueKeysPayloadCs // pop cache data
|
|
365
|
+
/* Registers callback for full queue */
|
|
366
|
+
setOnFullQueueCb(cb: () => void): void,
|
|
367
|
+
clear(): void
|
|
368
|
+
}
|
|
358
369
|
|
|
359
370
|
/**
|
|
360
371
|
* Telemetry storage interface for standalone and partial consumer modes.
|
|
@@ -444,15 +455,18 @@ export interface IStorageBase<
|
|
|
444
455
|
TSplitsCache extends ISplitsCacheBase,
|
|
445
456
|
TSegmentsCache extends ISegmentsCacheBase,
|
|
446
457
|
TImpressionsCache extends IImpressionsCacheBase,
|
|
458
|
+
TImpressionsCountCache extends IImpressionCountsCacheSync,
|
|
447
459
|
TEventsCache extends IEventsCacheBase,
|
|
448
|
-
TTelemetryCache extends ITelemetryCacheSync | ITelemetryCacheAsync
|
|
460
|
+
TTelemetryCache extends ITelemetryCacheSync | ITelemetryCacheAsync,
|
|
461
|
+
TUniqueKeysCache extends IUniqueKeysCacheBase
|
|
449
462
|
> {
|
|
450
463
|
splits: TSplitsCache,
|
|
451
464
|
segments: TSegmentsCache,
|
|
452
465
|
impressions: TImpressionsCache,
|
|
453
|
-
impressionCounts?:
|
|
466
|
+
impressionCounts?: TImpressionsCountCache,
|
|
454
467
|
events: TEventsCache,
|
|
455
|
-
telemetry?: TTelemetryCache
|
|
468
|
+
telemetry?: TTelemetryCache,
|
|
469
|
+
uniqueKeys?: TUniqueKeysCache,
|
|
456
470
|
destroy(): void | Promise<void>,
|
|
457
471
|
shared?: (matchingKey: string, onReadyCb: (error?: any) => void) => this
|
|
458
472
|
}
|
|
@@ -461,16 +475,20 @@ export interface IStorageSync extends IStorageBase<
|
|
|
461
475
|
ISplitsCacheSync,
|
|
462
476
|
ISegmentsCacheSync,
|
|
463
477
|
IImpressionsCacheSync,
|
|
478
|
+
IImpressionCountsCacheSync,
|
|
464
479
|
IEventsCacheSync,
|
|
465
|
-
ITelemetryCacheSync
|
|
480
|
+
ITelemetryCacheSync,
|
|
481
|
+
IUniqueKeysCacheBase
|
|
466
482
|
> { }
|
|
467
483
|
|
|
468
484
|
export interface IStorageAsync extends IStorageBase<
|
|
469
485
|
ISplitsCacheAsync,
|
|
470
486
|
ISegmentsCacheAsync,
|
|
471
487
|
IImpressionsCacheAsync | IImpressionsCacheSync,
|
|
488
|
+
IImpressionCountsCacheSync,
|
|
472
489
|
IEventsCacheAsync | IEventsCacheSync,
|
|
473
|
-
ITelemetryCacheAsync
|
|
490
|
+
ITelemetryCacheAsync,
|
|
491
|
+
IUniqueKeysCacheBase
|
|
474
492
|
> { }
|
|
475
493
|
|
|
476
494
|
/** StorageFactory */
|
|
@@ -480,10 +498,14 @@ export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
|
|
|
480
498
|
export interface IStorageFactoryParams {
|
|
481
499
|
log: ILogger,
|
|
482
500
|
impressionsQueueSize?: number,
|
|
501
|
+
impressionCountsQueueSize?: number,
|
|
502
|
+
impressionCountsRefreshRate?: number,
|
|
503
|
+
uniqueKeysRefreshRate?: number,
|
|
504
|
+
uniqueKeysCacheSize?: number,
|
|
483
505
|
eventsQueueSize?: number,
|
|
484
506
|
optimize?: boolean /* whether create the `impressionCounts` cache (OPTIMIZED impression mode) or not (DEBUG impression mode) */,
|
|
485
507
|
mode: SDKMode,
|
|
486
|
-
|
|
508
|
+
impressionsMode?: string,
|
|
487
509
|
// ATM, only used by InLocalStorage
|
|
488
510
|
matchingKey?: string, /* undefined on server-side SDKs */
|
|
489
511
|
splitFiltersValidation?: ISplitFiltersValidation,
|
|
@@ -4,6 +4,7 @@ import { impressionCountsSubmitterFactory } from './impressionCountsSubmitter';
|
|
|
4
4
|
import { telemetrySubmitterFactory } from './telemetrySubmitter';
|
|
5
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
6
|
import { ISubmitterManager } from './types';
|
|
7
|
+
import { uniqueKeysSubmitterFactory } from './uniqueKeysSubmitter';
|
|
7
8
|
|
|
8
9
|
export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmitterManager {
|
|
9
10
|
|
|
@@ -15,6 +16,7 @@ export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmit
|
|
|
15
16
|
const impressionCountsSubmitter = impressionCountsSubmitterFactory(params);
|
|
16
17
|
if (impressionCountsSubmitter) submitters.push(impressionCountsSubmitter);
|
|
17
18
|
const telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
19
|
+
if (params.uniqueKeysTracker) submitters.push(uniqueKeysSubmitterFactory(params));
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
22
|
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ISegmentsCacheSync, ISplitsCacheSync, ITelemetryCacheSync } from '../../storages/types';
|
|
2
2
|
import { submitterFactory, firstPushWindowDecorator } from './submitter';
|
|
3
3
|
import { TelemetryUsageStatsPayload, TelemetryConfigStatsPayload, TelemetryConfigStats } from './types';
|
|
4
|
-
import { QUEUED, DEDUPED, DROPPED, CONSUMER_MODE, CONSUMER_ENUM, STANDALONE_MODE, CONSUMER_PARTIAL_MODE, STANDALONE_ENUM, CONSUMER_PARTIAL_ENUM, OPTIMIZED, DEBUG, DEBUG_ENUM, OPTIMIZED_ENUM, CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../../utils/constants';
|
|
4
|
+
import { QUEUED, DEDUPED, DROPPED, CONSUMER_MODE, CONSUMER_ENUM, STANDALONE_MODE, CONSUMER_PARTIAL_MODE, STANDALONE_ENUM, CONSUMER_PARTIAL_ENUM, OPTIMIZED, DEBUG, NONE, DEBUG_ENUM, OPTIMIZED_ENUM, NONE_ENUM, CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../../utils/constants';
|
|
5
5
|
import { SDK_READY, SDK_READY_FROM_CACHE } from '../../readiness/constants';
|
|
6
6
|
import { ConsentStatus, ISettings, SDKMode } from '../../types';
|
|
7
7
|
import { base } from '../../utils/settingsValidation';
|
|
@@ -52,8 +52,9 @@ const OPERATION_MODE_MAP = {
|
|
|
52
52
|
|
|
53
53
|
const IMPRESSIONS_MODE_MAP = {
|
|
54
54
|
[OPTIMIZED]: OPTIMIZED_ENUM,
|
|
55
|
-
[DEBUG]: DEBUG_ENUM
|
|
56
|
-
|
|
55
|
+
[DEBUG]: DEBUG_ENUM,
|
|
56
|
+
[NONE]: NONE_ENUM
|
|
57
|
+
} as Record<ISettings['sync']['impressionsMode'], (0 | 1 | 2)>;
|
|
57
58
|
|
|
58
59
|
const USER_CONSENT_MAP = {
|
|
59
60
|
[CONSENT_UNKNOWN]: 1,
|
|
@@ -35,6 +35,24 @@ export type ImpressionCountsPayload = {
|
|
|
35
35
|
}[]
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export type UniqueKeysPayloadSs = {
|
|
39
|
+
keys: {
|
|
40
|
+
/** Split name */
|
|
41
|
+
f: string
|
|
42
|
+
/** keyNames */
|
|
43
|
+
ks: string[]
|
|
44
|
+
}[]
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type UniqueKeysPayloadCs = {
|
|
48
|
+
keys: {
|
|
49
|
+
/** keyNames */
|
|
50
|
+
k: string
|
|
51
|
+
/** Split name */
|
|
52
|
+
fs: string[]
|
|
53
|
+
}[]
|
|
54
|
+
}
|
|
55
|
+
|
|
38
56
|
export type StoredImpressionWithMetadata = {
|
|
39
57
|
/** Metadata */
|
|
40
58
|
m: IMetadata,
|
|
@@ -148,7 +166,8 @@ export type OperationMode = STANDALONE_ENUM | CONSUMER_ENUM | CONSUMER_PARTIAL_E
|
|
|
148
166
|
|
|
149
167
|
export type OPTIMIZED_ENUM = 0;
|
|
150
168
|
export type DEBUG_ENUM = 1;
|
|
151
|
-
export type
|
|
169
|
+
export type NONE_ENUM = 2;
|
|
170
|
+
export type ImpressionsMode = OPTIMIZED_ENUM | DEBUG_ENUM | NONE_ENUM;
|
|
152
171
|
|
|
153
172
|
export type RefreshRates = {
|
|
154
173
|
sp: number, // splits
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
2
|
+
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
3
|
+
import { submitterFactory } from './submitter';
|
|
4
|
+
|
|
5
|
+
const DATA_NAME = 'uniqueKeys';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Submitter that periodically posts impression counts
|
|
9
|
+
*/
|
|
10
|
+
export function uniqueKeysSubmitterFactory(params: ISdkFactoryContextSync) {
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
settings: { log, scheduler: { uniqueKeysRefreshRate }, core: {key}},
|
|
14
|
+
splitApi: { postUniqueKeysBulkCs, postUniqueKeysBulkSs },
|
|
15
|
+
storage: { uniqueKeys }
|
|
16
|
+
} = params;
|
|
17
|
+
|
|
18
|
+
const isClientSide = key !== undefined;
|
|
19
|
+
const postUniqueKeysBulk = isClientSide ? postUniqueKeysBulkCs : postUniqueKeysBulkSs;
|
|
20
|
+
|
|
21
|
+
const syncTask = submitterFactory(log, postUniqueKeysBulk, uniqueKeys!, uniqueKeysRefreshRate, 'unique keys');
|
|
22
|
+
|
|
23
|
+
// register unique keys submitter to be executed when uniqueKeys cache is full
|
|
24
|
+
uniqueKeys!.setOnFullQueueCb(() => {
|
|
25
|
+
if (syncTask.isRunning()) {
|
|
26
|
+
log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
27
|
+
syncTask.execute();
|
|
28
|
+
}
|
|
29
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
30
|
+
// Data will be sent when submitter is resumed.
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return syncTask;
|
|
34
|
+
}
|
|
35
|
+
|
|
@@ -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);
|
|
34
|
+
|
|
35
|
+
const impressionsToListenerCount = impressionsToListener.length;
|
|
36
|
+
|
|
37
|
+
if ( impressionsToStore.length>0 ){
|
|
38
|
+
const res = impressionsCache.track(impressionsToStore);
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
});
|
|
59
|
-
|
|
60
|
-
const res = impressionsCache.track(impressionsToStore);
|
|
61
|
-
|
|
62
|
-
// If we're on an async storage, handle error and log it.
|
|
63
|
-
if (thenable(res)) {
|
|
64
|
-
res.then(() => {
|
|
65
|
-
log.info(IMPRESSIONS_TRACKER_SUCCESS, [impressionsCount]);
|
|
66
|
-
}).catch(err => {
|
|
67
|
-
log.error(ERROR_IMPRESSIONS_TRACKER, [impressionsCount, err]);
|
|
68
|
-
});
|
|
69
|
-
} else {
|
|
70
|
-
// Record when impressionsCache is sync only (standalone mode)
|
|
71
|
-
// @TODO we are not dropping impressions on full queue yet, so DROPPED stats are not recorded
|
|
72
|
-
if (telemetryCache) {
|
|
73
|
-
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(QUEUED, impressionsToStore.length);
|
|
74
|
-
(telemetryCache as ITelemetryCacheSync).recordImpressionStats(DEDUPED, impressions.length - impressionsToStore.length);
|
|
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 { IImpressionCountsCacheSync } 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: IImpressionCountsCacheSync,
|
|
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 { IImpressionCountsCacheSync } 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: IImpressionCountsCacheSync,
|
|
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
|
@@ -80,6 +80,10 @@ export interface ISettings {
|
|
|
80
80
|
featuresRefreshRate: number,
|
|
81
81
|
impressionsRefreshRate: number,
|
|
82
82
|
impressionsQueueSize: number,
|
|
83
|
+
impressionCountsRefreshRate: number,
|
|
84
|
+
impressionCountsQueueSize: number,
|
|
85
|
+
uniqueKeysRefreshRate: number,
|
|
86
|
+
uniqueKeysCacheSize: number,
|
|
83
87
|
/**
|
|
84
88
|
* @deprecated
|
|
85
89
|
*/
|
|
@@ -718,7 +722,7 @@ export namespace SplitIO {
|
|
|
718
722
|
* ImpressionsMode type
|
|
719
723
|
* @typedef {string} ImpressionsMode
|
|
720
724
|
*/
|
|
721
|
-
export type ImpressionsMode = 'OPTIMIZED' | 'DEBUG'
|
|
725
|
+
export type ImpressionsMode = 'OPTIMIZED' | 'DEBUG' | 'NONE'
|
|
722
726
|
/**
|
|
723
727
|
* Defines the format of Split data to preload on the factory storage (cache).
|
|
724
728
|
*/
|
|
@@ -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';
|
|
@@ -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
|
}
|
|
@@ -36,6 +36,8 @@ export const base = {
|
|
|
36
36
|
telemetryRefreshRate: 3600,
|
|
37
37
|
// publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
|
|
38
38
|
impressionsRefreshRate: 300,
|
|
39
|
+
// publish unique Keys each 900 sec (15 min)
|
|
40
|
+
uniqueKeysRefreshRate: 900,
|
|
39
41
|
// fetch offline changes each 15 sec
|
|
40
42
|
offlineRefreshRate: 15,
|
|
41
43
|
// publish events every 60 seconds after the first flush
|
|
@@ -130,11 +132,14 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
130
132
|
scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
|
|
131
133
|
scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
|
|
132
134
|
scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
|
|
135
|
+
scheduler.uniqueKeysRefreshRate = fromSecondsToMillis(scheduler.uniqueKeysRefreshRate);
|
|
136
|
+
scheduler.impressionCountsRefreshRate = fromSecondsToMillis(scheduler.impressionCountsRefreshRate);
|
|
133
137
|
scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
|
|
134
138
|
|
|
135
139
|
// Default impressionsRefreshRate for DEBUG mode is 60 secs
|
|
136
140
|
if (get(config, 'scheduler.impressionsRefreshRate') === undefined && withDefaults.sync.impressionsMode === DEBUG) scheduler.impressionsRefreshRate = 60;
|
|
137
141
|
scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
|
|
142
|
+
|
|
138
143
|
|
|
139
144
|
// Log deprecation for old telemetry param
|
|
140
145
|
if (scheduler.metricsRefreshRate) log.warn('`metricsRefreshRate` will be deprecated soon. For configuring telemetry rates, update `telemetryRefreshRate` value in configs');
|
|
@@ -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: ";
|