@splitsoftware/splitio-commons 1.6.2-rc.8 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +4 -1
- package/cjs/evaluator/index.js +5 -5
- package/cjs/listeners/browser.js +9 -11
- package/cjs/sdkClient/client.js +19 -7
- package/cjs/sdkFactory/index.js +7 -25
- package/cjs/services/splitApi.js +4 -4
- package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
- package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
- package/cjs/storages/KeyBuilderSS.js +9 -9
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/cjs/storages/inLocalStorage/index.js +15 -11
- package/cjs/storages/inMemory/InMemoryStorage.js +11 -8
- package/cjs/storages/inMemory/InMemoryStorageCS.js +11 -8
- package/cjs/storages/inMemory/TelemetryCacheInMemory.js +65 -37
- package/cjs/storages/inMemory/{uniqueKeysCacheInMemory.js → UniqueKeysCacheInMemory.js} +24 -25
- package/cjs/storages/inMemory/{uniqueKeysCacheInMemoryCS.js → UniqueKeysCacheInMemoryCS.js} +10 -12
- package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +37 -2
- package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +100 -0
- package/cjs/storages/inRedis/{uniqueKeysCacheInRedis.js → UniqueKeysCacheInRedis.js} +16 -4
- package/cjs/storages/inRedis/index.js +6 -4
- package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +81 -0
- package/cjs/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +126 -0
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +61 -0
- package/cjs/storages/pluggable/inMemoryWrapper.js +8 -6
- package/cjs/storages/pluggable/index.js +51 -18
- package/cjs/storages/utils.js +73 -0
- package/cjs/sync/submitters/submitterManager.js +1 -1
- package/cjs/sync/submitters/telemetrySubmitter.js +4 -37
- package/cjs/sync/submitters/uniqueKeysSubmitter.js +4 -3
- package/cjs/trackers/impressionObserver/utils.js +1 -17
- package/cjs/trackers/uniqueKeysTracker.js +1 -1
- package/cjs/utils/lang/maps.js +15 -7
- package/cjs/utils/redis/RedisMock.js +31 -0
- package/cjs/utils/settingsValidation/index.js +7 -4
- package/esm/evaluator/index.js +5 -5
- package/esm/listeners/browser.js +9 -11
- package/esm/sdkClient/client.js +19 -7
- package/esm/sdkFactory/index.js +7 -25
- package/esm/services/splitApi.js +4 -4
- package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
- package/esm/storages/AbstractSplitsCacheSync.js +1 -1
- package/esm/storages/KeyBuilderSS.js +8 -8
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +0 -1
- package/esm/storages/inLocalStorage/index.js +16 -12
- package/esm/storages/inMemory/InMemoryStorage.js +13 -10
- package/esm/storages/inMemory/InMemoryStorageCS.js +12 -9
- package/esm/storages/inMemory/TelemetryCacheInMemory.js +64 -37
- package/esm/storages/inMemory/{uniqueKeysCacheInMemory.js → UniqueKeysCacheInMemory.js} +22 -24
- package/esm/storages/inMemory/{uniqueKeysCacheInMemoryCS.js → UniqueKeysCacheInMemoryCS.js} +10 -12
- package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
- package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +37 -2
- package/esm/storages/inRedis/ImpressionsCacheInRedis.js +2 -19
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +100 -0
- package/esm/storages/inRedis/{uniqueKeysCacheInRedis.js → UniqueKeysCacheInRedis.js} +15 -3
- package/esm/storages/inRedis/index.js +5 -3
- package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +78 -0
- package/esm/storages/pluggable/ImpressionsCachePluggable.js +2 -19
- package/esm/storages/pluggable/TelemetryCachePluggable.js +126 -0
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +58 -0
- package/esm/storages/pluggable/inMemoryWrapper.js +8 -6
- package/esm/storages/pluggable/index.js +52 -19
- package/esm/storages/utils.js +65 -0
- package/esm/sync/submitters/submitterManager.js +1 -1
- package/esm/sync/submitters/telemetrySubmitter.js +4 -36
- package/esm/sync/submitters/uniqueKeysSubmitter.js +4 -3
- package/esm/trackers/impressionObserver/utils.js +1 -15
- package/esm/trackers/uniqueKeysTracker.js +1 -1
- package/esm/utils/lang/maps.js +15 -7
- package/esm/utils/redis/RedisMock.js +28 -0
- package/esm/utils/settingsValidation/index.js +7 -4
- package/package.json +2 -2
- package/src/consent/sdkUserConsent.ts +1 -1
- package/src/evaluator/index.ts +6 -6
- package/src/listeners/browser.ts +9 -13
- package/src/logger/.DS_Store +0 -0
- package/src/sdkClient/client.ts +21 -8
- package/src/sdkClient/sdkClient.ts +1 -1
- package/src/sdkFactory/index.ts +10 -33
- package/src/sdkFactory/types.ts +2 -2
- package/src/services/splitApi.ts +6 -6
- package/src/services/types.ts +2 -2
- package/src/storages/AbstractSplitsCacheAsync.ts +1 -1
- package/src/storages/AbstractSplitsCacheSync.ts +1 -1
- package/src/storages/KeyBuilderSS.ts +13 -11
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +0 -1
- package/src/storages/inLocalStorage/index.ts +17 -12
- package/src/storages/inMemory/AttributesCacheInMemory.ts +7 -7
- package/src/storages/inMemory/ImpressionCountsCacheInMemory.ts +2 -2
- package/src/storages/inMemory/InMemoryStorage.ts +14 -10
- package/src/storages/inMemory/InMemoryStorageCS.ts +13 -10
- package/src/storages/inMemory/TelemetryCacheInMemory.ts +72 -35
- package/src/storages/inMemory/{uniqueKeysCacheInMemory.ts → UniqueKeysCacheInMemory.ts} +26 -28
- package/src/storages/inMemory/{uniqueKeysCacheInMemoryCS.ts → UniqueKeysCacheInMemoryCS.ts} +15 -17
- package/src/storages/inRedis/EventsCacheInRedis.ts +1 -1
- package/src/storages/inRedis/ImpressionCountsCacheInRedis.ts +51 -8
- package/src/storages/inRedis/ImpressionsCacheInRedis.ts +2 -22
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +122 -1
- package/src/storages/inRedis/{uniqueKeysCacheInRedis.ts → UniqueKeysCacheInRedis.ts} +25 -12
- package/src/storages/inRedis/index.ts +6 -3
- package/src/storages/pluggable/ImpressionCountsCachePluggable.ts +92 -0
- package/src/storages/pluggable/ImpressionsCachePluggable.ts +3 -23
- package/src/storages/pluggable/TelemetryCachePluggable.ts +147 -1
- package/src/storages/pluggable/UniqueKeysCachePluggable.ts +67 -0
- package/src/storages/pluggable/inMemoryWrapper.ts +6 -6
- package/src/storages/pluggable/index.ts +56 -20
- package/src/storages/types.ts +53 -70
- package/src/storages/utils.ts +78 -0
- package/src/sync/submitters/submitter.ts +2 -2
- package/src/sync/submitters/submitterManager.ts +1 -1
- package/src/sync/submitters/telemetrySubmitter.ts +9 -39
- package/src/sync/submitters/types.ts +33 -17
- package/src/sync/submitters/uniqueKeysSubmitter.ts +6 -5
- package/src/trackers/impressionObserver/utils.ts +1 -16
- package/src/trackers/impressionsTracker.ts +2 -2
- package/src/trackers/strategy/strategyDebug.ts +4 -4
- package/src/trackers/strategy/strategyNone.ts +9 -9
- package/src/trackers/strategy/strategyOptimized.ts +9 -9
- package/src/trackers/uniqueKeysTracker.ts +6 -6
- package/src/types.ts +0 -2
- package/src/utils/lang/maps.ts +20 -8
- package/src/utils/redis/RedisMock.ts +33 -0
- package/src/utils/settingsValidation/index.ts +5 -5
- package/types/services/types.d.ts +2 -2
- package/types/storages/AbstractSplitsCacheAsync.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheSync.d.ts +1 -1
- package/types/storages/KeyBuilderSS.d.ts +5 -2
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +0 -1
- package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +23 -9
- package/types/storages/inMemory/uniqueKeysCacheInMemory.d.ts +9 -9
- package/types/storages/inMemory/uniqueKeysCacheInMemoryCS.d.ts +2 -4
- package/types/storages/inRedis/EventsCacheInRedis.d.ts +1 -1
- package/types/storages/inRedis/ImpressionCountsCacheInRedis.d.ts +3 -1
- package/types/storages/inRedis/ImpressionsCacheInRedis.d.ts +0 -1
- package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +16 -1
- package/types/storages/inRedis/uniqueKeysCacheInRedis.d.ts +8 -2
- package/types/storages/pluggable/ImpressionCountsCachePluggable.d.ts +16 -0
- package/types/storages/pluggable/ImpressionsCachePluggable.d.ts +1 -2
- package/types/storages/pluggable/TelemetryCachePluggable.d.ts +17 -1
- package/types/storages/pluggable/UniqueKeysCachePluggable.d.ts +20 -0
- package/types/storages/types.d.ts +42 -49
- package/types/storages/utils.d.ts +8 -0
- package/types/sync/submitters/submitter.d.ts +2 -2
- package/types/sync/submitters/telemetrySubmitter.d.ts +2 -10
- package/types/sync/submitters/types.d.ts +27 -18
- package/types/trackers/impressionObserver/utils.d.ts +0 -8
- package/types/trackers/strategy/strategyNone.d.ts +2 -2
- package/types/trackers/strategy/strategyOptimized.d.ts +2 -2
- package/types/trackers/uniqueKeysTracker.d.ts +1 -1
- package/types/types.d.ts +0 -2
- package/types/utils/lang/maps.d.ts +6 -2
- package/types/utils/redis/RedisMock.d.ts +4 -0
- package/types/utils/settingsValidation/index.d.ts +0 -1
- package/cjs/storages/metadataBuilder.js +0 -12
- package/esm/storages/metadataBuilder.js +0 -8
- package/src/storages/metadataBuilder.ts +0 -11
- 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/inRedis/CountsCacheInRedis.d.ts +0 -9
- package/types/storages/inRedis/LatenciesCacheInRedis.d.ts +0 -9
- 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/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/utils/timeTracker/index.d.ts +0 -70
|
@@ -7,10 +7,10 @@ export class AttributesCacheInMemory {
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Create or update the value for the given attribute
|
|
10
|
-
*
|
|
10
|
+
*
|
|
11
11
|
* @param {string} attributeName attribute name
|
|
12
12
|
* @param {Object} attributeValue attribute value
|
|
13
|
-
* @returns {boolean} the attribute was stored
|
|
13
|
+
* @returns {boolean} the attribute was stored
|
|
14
14
|
*/
|
|
15
15
|
setAttribute(attributeName: string, attributeValue: Object): boolean {
|
|
16
16
|
this.attributesCache[attributeName] = attributeValue;
|
|
@@ -19,7 +19,7 @@ export class AttributesCacheInMemory {
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Retrieves the value of a given attribute
|
|
22
|
-
*
|
|
22
|
+
*
|
|
23
23
|
* @param {string} attributeName attribute name
|
|
24
24
|
* @returns {Object?} stored attribute value
|
|
25
25
|
*/
|
|
@@ -29,7 +29,7 @@ export class AttributesCacheInMemory {
|
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Create or update all the given attributes
|
|
32
|
-
*
|
|
32
|
+
*
|
|
33
33
|
* @param {[string, Object]} attributes attributes to create or update
|
|
34
34
|
* @returns {boolean} attributes were stored
|
|
35
35
|
*/
|
|
@@ -40,7 +40,7 @@ export class AttributesCacheInMemory {
|
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Retrieve the full attributes map
|
|
43
|
-
*
|
|
43
|
+
*
|
|
44
44
|
* @returns {Map<string, Object>} stored attributes
|
|
45
45
|
*/
|
|
46
46
|
getAll(): Record<string, Object> {
|
|
@@ -49,7 +49,7 @@ export class AttributesCacheInMemory {
|
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
51
|
* Removes a given attribute from the map
|
|
52
|
-
*
|
|
52
|
+
*
|
|
53
53
|
* @param {string} attributeName attribute to remove
|
|
54
54
|
* @returns {boolean} attribute removed
|
|
55
55
|
*/
|
|
@@ -63,7 +63,7 @@ export class AttributesCacheInMemory {
|
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Clears all attributes stored in the SDK
|
|
66
|
-
*
|
|
66
|
+
*
|
|
67
67
|
*/
|
|
68
68
|
clear() {
|
|
69
69
|
this.attributesCache = {};
|
|
@@ -7,8 +7,8 @@ export class ImpressionCountsCacheInMemory implements IImpressionCountsCacheSync
|
|
|
7
7
|
private readonly maxStorage: number;
|
|
8
8
|
protected onFullQueue?: () => void;
|
|
9
9
|
private cacheSize = 0;
|
|
10
|
-
|
|
11
|
-
constructor(impressionCountsCacheSize
|
|
10
|
+
|
|
11
|
+
constructor(impressionCountsCacheSize = DEFAULT_CACHE_SIZE) {
|
|
12
12
|
this.maxStorage = impressionCountsCacheSize;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -4,9 +4,9 @@ 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 { DEBUG,
|
|
8
|
-
import { TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
-
import { UniqueKeysCacheInMemory } from './
|
|
7
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
|
+
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
+
import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* InMemory storage factory for standalone server-side SplitFactory
|
|
@@ -14,15 +14,19 @@ import { UniqueKeysCacheInMemory } from './uniqueKeysCacheInMemory';
|
|
|
14
14
|
* @param params parameters required by EventsCacheSync
|
|
15
15
|
*/
|
|
16
16
|
export function InMemoryStorageFactory(params: IStorageFactoryParams): IStorageSync {
|
|
17
|
+
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode } } } = params;
|
|
18
|
+
|
|
19
|
+
const splits = new SplitsCacheInMemory();
|
|
20
|
+
const segments = new SegmentsCacheInMemory();
|
|
17
21
|
|
|
18
22
|
return {
|
|
19
|
-
splits
|
|
20
|
-
segments
|
|
21
|
-
impressions: new ImpressionsCacheInMemory(
|
|
22
|
-
impressionCounts:
|
|
23
|
-
events: new EventsCacheInMemory(
|
|
24
|
-
telemetry: params
|
|
25
|
-
uniqueKeys:
|
|
23
|
+
splits,
|
|
24
|
+
segments,
|
|
25
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
26
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
27
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
28
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
29
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
|
|
26
30
|
|
|
27
31
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
28
32
|
destroy() {
|
|
@@ -4,9 +4,9 @@ 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 { DEBUG,
|
|
7
|
+
import { DEBUG, NONE, STORAGE_MEMORY } from '../../utils/constants';
|
|
8
8
|
import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
|
|
9
|
-
import { UniqueKeysCacheInMemoryCS } from './
|
|
9
|
+
import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* InMemory storage factory for standalone client-side SplitFactory
|
|
@@ -14,16 +14,19 @@ import { UniqueKeysCacheInMemoryCS } from './uniqueKeysCacheInMemoryCS';
|
|
|
14
14
|
* @param params parameters required by EventsCacheSync
|
|
15
15
|
*/
|
|
16
16
|
export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync {
|
|
17
|
+
const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode } } } = params;
|
|
18
|
+
|
|
19
|
+
const splits = new SplitsCacheInMemory();
|
|
20
|
+
const segments = new MySegmentsCacheInMemory();
|
|
17
21
|
|
|
18
22
|
return {
|
|
19
|
-
splits
|
|
20
|
-
segments
|
|
21
|
-
impressions: new ImpressionsCacheInMemory(
|
|
22
|
-
impressionCounts:
|
|
23
|
-
events: new EventsCacheInMemory(
|
|
24
|
-
telemetry:
|
|
25
|
-
uniqueKeys:
|
|
26
|
-
|
|
23
|
+
splits,
|
|
24
|
+
segments,
|
|
25
|
+
impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
|
|
26
|
+
impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
|
|
27
|
+
events: new EventsCacheInMemory(eventsQueueSize),
|
|
28
|
+
telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
|
|
29
|
+
uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
|
|
27
30
|
|
|
28
31
|
// When using MEMORY we should clean all the caches to leave them empty
|
|
29
32
|
destroy() {
|
|
@@ -1,26 +1,66 @@
|
|
|
1
|
-
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies } from '../../sync/submitters/types';
|
|
1
|
+
import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies, TelemetryUsageStatsPayload } from '../../sync/submitters/types';
|
|
2
|
+
import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
|
|
2
3
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
3
|
-
import { ITelemetryCacheSync } from '../types';
|
|
4
|
+
import { ISegmentsCacheSync, ISplitsCacheSync, 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
|
-
// MAX_LATENCY_BUCKET_COUNT (length) is 23
|
|
10
|
+
export function newBuckets() {
|
|
11
|
+
// MAX_LATENCY_BUCKET_COUNT (length) is 23
|
|
12
|
+
// Not using Array.fill for old browsers compatibility
|
|
10
13
|
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
const ACCEPTANCE_RANGE = 0.001;
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
|
-
*
|
|
19
|
+
* Record telemetry if mode is not localhost.
|
|
20
|
+
* All factory instances track telemetry on server-side, and 0.1% on client-side.
|
|
17
21
|
*/
|
|
18
|
-
export function shouldRecordTelemetry() {
|
|
19
|
-
return Math.random() <= ACCEPTANCE_RANGE;
|
|
22
|
+
export function shouldRecordTelemetry({ settings }: IStorageFactoryParams) {
|
|
23
|
+
return settings.mode !== LOCALHOST_MODE && (settings.core.key === undefined || Math.random() <= ACCEPTANCE_RANGE);
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
23
27
|
|
|
28
|
+
constructor(private splits?: ISplitsCacheSync, private segments?: ISegmentsCacheSync) { }
|
|
29
|
+
|
|
30
|
+
// isEmpty flag
|
|
31
|
+
private e = true;
|
|
32
|
+
|
|
33
|
+
isEmpty() { return this.e; }
|
|
34
|
+
|
|
35
|
+
clear() { /* no-op */ }
|
|
36
|
+
|
|
37
|
+
pop(): TelemetryUsageStatsPayload {
|
|
38
|
+
this.e = true;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
lS: this.getLastSynchronization(),
|
|
42
|
+
mL: this.popLatencies(),
|
|
43
|
+
mE: this.popExceptions(),
|
|
44
|
+
hE: this.popHttpErrors(),
|
|
45
|
+
hL: this.popHttpLatencies(),
|
|
46
|
+
tR: this.popTokenRefreshes(),
|
|
47
|
+
aR: this.popAuthRejections(),
|
|
48
|
+
iQ: this.getImpressionStats(QUEUED),
|
|
49
|
+
iDe: this.getImpressionStats(DEDUPED),
|
|
50
|
+
iDr: this.getImpressionStats(DROPPED),
|
|
51
|
+
spC: this.splits && this.splits.getSplitNames().length,
|
|
52
|
+
seC: this.segments && this.segments.getRegisteredSegments().length,
|
|
53
|
+
skC: this.segments && this.segments.getKeysCount(),
|
|
54
|
+
sL: this.getSessionLength(),
|
|
55
|
+
eQ: this.getEventStats(QUEUED),
|
|
56
|
+
eD: this.getEventStats(DROPPED),
|
|
57
|
+
sE: this.popStreamingEvents(),
|
|
58
|
+
t: this.popTags(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Config stats */
|
|
63
|
+
|
|
24
64
|
private timeUntilReady?: number;
|
|
25
65
|
|
|
26
66
|
getTimeUntilReady() {
|
|
@@ -51,6 +91,8 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
51
91
|
this.notReadyUsage++;
|
|
52
92
|
}
|
|
53
93
|
|
|
94
|
+
/** Usage stats */
|
|
95
|
+
|
|
54
96
|
private impressionStats = [0, 0, 0];
|
|
55
97
|
|
|
56
98
|
getImpressionStats(type: ImpressionDataType) {
|
|
@@ -59,6 +101,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
59
101
|
|
|
60
102
|
recordImpressionStats(type: ImpressionDataType, count: number) {
|
|
61
103
|
this.impressionStats[type] += count;
|
|
104
|
+
this.e = false;
|
|
62
105
|
}
|
|
63
106
|
|
|
64
107
|
private eventStats = [0, 0];
|
|
@@ -69,9 +112,9 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
69
112
|
|
|
70
113
|
recordEventStats(type: EventDataType, count: number) {
|
|
71
114
|
this.eventStats[type] += count;
|
|
115
|
+
this.e = false;
|
|
72
116
|
}
|
|
73
117
|
|
|
74
|
-
// @ts-expect-error
|
|
75
118
|
private lastSync: LastSync = {};
|
|
76
119
|
|
|
77
120
|
getLastSynchronization() {
|
|
@@ -80,40 +123,35 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
80
123
|
|
|
81
124
|
recordSuccessfulSync(resource: OperationType, timeMs: number) {
|
|
82
125
|
this.lastSync[resource] = timeMs;
|
|
126
|
+
this.e = false;
|
|
83
127
|
}
|
|
84
128
|
|
|
85
|
-
// @ts-expect-error
|
|
86
129
|
private httpErrors: HttpErrors = {};
|
|
87
130
|
|
|
88
131
|
popHttpErrors() {
|
|
89
|
-
const result = this.httpErrors;
|
|
132
|
+
const result = this.httpErrors;
|
|
90
133
|
this.httpErrors = {};
|
|
91
134
|
return result;
|
|
92
135
|
}
|
|
93
136
|
|
|
94
137
|
recordHttpError(resource: OperationType, status: number) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
} else {
|
|
99
|
-
this.httpErrors[resource][status]++;
|
|
100
|
-
}
|
|
138
|
+
const statusErrors = (this.httpErrors[resource] = this.httpErrors[resource] || {});
|
|
139
|
+
statusErrors[status] = (statusErrors[status] || 0) + 1;
|
|
140
|
+
this.e = false;
|
|
101
141
|
}
|
|
102
142
|
|
|
103
|
-
// @ts-expect-error
|
|
104
143
|
private httpLatencies: HttpLatencies = {};
|
|
105
144
|
|
|
106
145
|
popHttpLatencies() {
|
|
107
|
-
const result = this.httpLatencies;
|
|
146
|
+
const result = this.httpLatencies;
|
|
108
147
|
this.httpLatencies = {};
|
|
109
148
|
return result;
|
|
110
149
|
}
|
|
111
150
|
|
|
112
151
|
recordHttpLatency(resource: OperationType, latencyMs: number) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
this.httpLatencies[resource][findLatencyIndex(latencyMs)]++;
|
|
152
|
+
const latencyBuckets = (this.httpLatencies[resource] = this.httpLatencies[resource] || newBuckets());
|
|
153
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
154
|
+
this.e = false;
|
|
117
155
|
}
|
|
118
156
|
|
|
119
157
|
private authRejections = 0;
|
|
@@ -126,6 +164,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
126
164
|
|
|
127
165
|
recordAuthRejections() {
|
|
128
166
|
this.authRejections++;
|
|
167
|
+
this.e = false;
|
|
129
168
|
}
|
|
130
169
|
|
|
131
170
|
private tokenRefreshes = 0;
|
|
@@ -138,6 +177,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
138
177
|
|
|
139
178
|
recordTokenRefreshes() {
|
|
140
179
|
this.tokenRefreshes++;
|
|
180
|
+
this.e = false;
|
|
141
181
|
}
|
|
142
182
|
|
|
143
183
|
private streamingEvents: StreamingEvent[] = []
|
|
@@ -150,6 +190,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
150
190
|
if (this.streamingEvents.length < MAX_STREAMING_EVENTS) {
|
|
151
191
|
this.streamingEvents.push(streamingEvent);
|
|
152
192
|
}
|
|
193
|
+
this.e = false;
|
|
153
194
|
}
|
|
154
195
|
|
|
155
196
|
private tags: string[] = [];
|
|
@@ -162,6 +203,7 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
162
203
|
if (this.tags.length < MAX_TAGS) {
|
|
163
204
|
this.tags.push(tag);
|
|
164
205
|
}
|
|
206
|
+
this.e = false;
|
|
165
207
|
}
|
|
166
208
|
|
|
167
209
|
private sessionLength?: number;
|
|
@@ -172,39 +214,34 @@ export class TelemetryCacheInMemory implements ITelemetryCacheSync {
|
|
|
172
214
|
|
|
173
215
|
recordSessionLength(ms: number) {
|
|
174
216
|
this.sessionLength = ms;
|
|
217
|
+
this.e = false;
|
|
175
218
|
}
|
|
176
219
|
|
|
177
|
-
// @ts-expect-error
|
|
178
220
|
private exceptions: MethodExceptions = {};
|
|
179
221
|
|
|
180
222
|
popExceptions() {
|
|
181
|
-
const result = this.exceptions;
|
|
223
|
+
const result = this.exceptions;
|
|
182
224
|
this.exceptions = {};
|
|
183
225
|
return result;
|
|
184
226
|
}
|
|
185
227
|
|
|
186
228
|
recordException(method: Method) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
} else {
|
|
190
|
-
this.exceptions[method]++;
|
|
191
|
-
}
|
|
229
|
+
this.exceptions[method] = (this.exceptions[method] || 0) + 1;
|
|
230
|
+
this.e = false;
|
|
192
231
|
}
|
|
193
232
|
|
|
194
|
-
// @ts-expect-error
|
|
195
233
|
private latencies: MethodLatencies = {};
|
|
196
234
|
|
|
197
235
|
popLatencies() {
|
|
198
|
-
const result = this.latencies;
|
|
236
|
+
const result = this.latencies;
|
|
199
237
|
this.latencies = {};
|
|
200
238
|
return result;
|
|
201
239
|
}
|
|
202
240
|
|
|
203
241
|
recordLatency(method: Method, latencyMs: number) {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
this.latencies[method][findLatencyIndex(latencyMs)]++;
|
|
242
|
+
const latencyBuckets = (this.latencies[method] = this.latencies[method] || newBuckets());
|
|
243
|
+
latencyBuckets[findLatencyIndex(latencyMs)]++;
|
|
244
|
+
this.e = false;
|
|
208
245
|
}
|
|
209
246
|
|
|
210
247
|
}
|
|
@@ -3,14 +3,33 @@ import { ISet, setToArray, _Set } from '../../utils/lang/sets';
|
|
|
3
3
|
import { UniqueKeysPayloadSs } from '../../sync/submitters/types';
|
|
4
4
|
import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
8
|
+
*/
|
|
9
|
+
export function fromUniqueKeysCollector(uniqueKeys: { [featureName: string]: ISet<string> }): UniqueKeysPayloadSs {
|
|
10
|
+
const payload = [];
|
|
11
|
+
const featureNames = Object.keys(uniqueKeys);
|
|
12
|
+
for (let i = 0; i < featureNames.length; i++) {
|
|
13
|
+
const featureName = featureNames[i];
|
|
14
|
+
const userKeys = setToArray(uniqueKeys[featureName]);
|
|
15
|
+
const uniqueKeysPayload = {
|
|
16
|
+
f: featureName,
|
|
17
|
+
ks: userKeys
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
payload.push(uniqueKeysPayload);
|
|
21
|
+
}
|
|
22
|
+
return { keys: payload };
|
|
23
|
+
}
|
|
24
|
+
|
|
6
25
|
export class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
7
26
|
|
|
8
27
|
protected onFullQueue?: () => void;
|
|
9
28
|
private readonly maxStorage: number;
|
|
10
29
|
private uniqueTrackerSize = 0;
|
|
11
|
-
protected uniqueKeysTracker: { [
|
|
30
|
+
protected uniqueKeysTracker: { [featureName: string]: ISet<string> };
|
|
12
31
|
|
|
13
|
-
constructor(uniqueKeysQueueSize
|
|
32
|
+
constructor(uniqueKeysQueueSize = DEFAULT_CACHE_SIZE) {
|
|
14
33
|
this.maxStorage = uniqueKeysQueueSize;
|
|
15
34
|
this.uniqueKeysTracker = {};
|
|
16
35
|
}
|
|
@@ -20,15 +39,13 @@ export class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
/**
|
|
23
|
-
* Store unique keys
|
|
24
|
-
* key: string = feature name.
|
|
25
|
-
* value: Set<string> = set of unique keys.
|
|
42
|
+
* Store unique keys per feature.
|
|
26
43
|
*/
|
|
27
|
-
track(
|
|
44
|
+
track(userKey: string, featureName: string) {
|
|
28
45
|
if (!this.uniqueKeysTracker[featureName]) this.uniqueKeysTracker[featureName] = new _Set();
|
|
29
46
|
const tracker = this.uniqueKeysTracker[featureName];
|
|
30
|
-
if (!tracker.has(
|
|
31
|
-
tracker.add(
|
|
47
|
+
if (!tracker.has(userKey)) {
|
|
48
|
+
tracker.add(userKey);
|
|
32
49
|
this.uniqueTrackerSize++;
|
|
33
50
|
}
|
|
34
51
|
if (this.uniqueTrackerSize >= this.maxStorage && this.onFullQueue) {
|
|
@@ -50,7 +67,7 @@ export class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
|
50
67
|
pop() {
|
|
51
68
|
const data = this.uniqueKeysTracker;
|
|
52
69
|
this.uniqueKeysTracker = {};
|
|
53
|
-
return
|
|
70
|
+
return fromUniqueKeysCollector(data);
|
|
54
71
|
}
|
|
55
72
|
|
|
56
73
|
/**
|
|
@@ -59,24 +76,5 @@ export class UniqueKeysCacheInMemory implements IUniqueKeysCacheBase {
|
|
|
59
76
|
isEmpty() {
|
|
60
77
|
return Object.keys(this.uniqueKeysTracker).length === 0;
|
|
61
78
|
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Converts `uniqueKeys` data from cache into request payload for SS.
|
|
65
|
-
*/
|
|
66
|
-
private fromUniqueKeysCollector(uniqueKeys: { [featureName: string]: ISet<string> }): UniqueKeysPayloadSs {
|
|
67
|
-
const payload = [];
|
|
68
|
-
const featureNames = Object.keys(uniqueKeys);
|
|
69
|
-
for (let i = 0; i < featureNames.length; i++) {
|
|
70
|
-
const featureName = featureNames[i];
|
|
71
|
-
const featureKeys = setToArray(uniqueKeys[featureName]);
|
|
72
|
-
const uniqueKeysPayload = {
|
|
73
|
-
f: featureName,
|
|
74
|
-
ks: featureKeys
|
|
75
|
-
};
|
|
76
79
|
|
|
77
|
-
payload.push(uniqueKeysPayload);
|
|
78
|
-
}
|
|
79
|
-
return { keys: payload };
|
|
80
|
-
}
|
|
81
|
-
|
|
82
80
|
}
|
|
@@ -8,14 +8,14 @@ export class UniqueKeysCacheInMemoryCS implements IUniqueKeysCacheBase {
|
|
|
8
8
|
private onFullQueue?: () => void;
|
|
9
9
|
private readonly maxStorage: number;
|
|
10
10
|
private uniqueTrackerSize = 0;
|
|
11
|
-
private uniqueKeysTracker: { [
|
|
11
|
+
private uniqueKeysTracker: { [userKey: string]: ISet<string> };
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
15
|
* @param impressionsQueueSize number of queued impressions to call onFullQueueCb.
|
|
16
16
|
* Default value is 0, that means no maximum value, in case we want to avoid this being triggered.
|
|
17
17
|
*/
|
|
18
|
-
constructor(uniqueKeysQueueSize
|
|
18
|
+
constructor(uniqueKeysQueueSize = DEFAULT_CACHE_SIZE) {
|
|
19
19
|
this.maxStorage = uniqueKeysQueueSize;
|
|
20
20
|
this.uniqueKeysTracker = {};
|
|
21
21
|
}
|
|
@@ -25,14 +25,12 @@ export class UniqueKeysCacheInMemoryCS implements IUniqueKeysCacheBase {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* Store unique keys
|
|
29
|
-
* key: string = key.
|
|
30
|
-
* value: HashSet<string> = set of split names.
|
|
28
|
+
* Store unique keys per feature.
|
|
31
29
|
*/
|
|
32
|
-
track(
|
|
33
|
-
|
|
34
|
-
if (!this.uniqueKeysTracker[
|
|
35
|
-
const tracker = this.uniqueKeysTracker[
|
|
30
|
+
track(userKey: string, featureName: string) {
|
|
31
|
+
|
|
32
|
+
if (!this.uniqueKeysTracker[userKey]) this.uniqueKeysTracker[userKey] = new _Set();
|
|
33
|
+
const tracker = this.uniqueKeysTracker[userKey];
|
|
36
34
|
if (!tracker.has(featureName)) {
|
|
37
35
|
tracker.add(featureName);
|
|
38
36
|
this.uniqueTrackerSize++;
|
|
@@ -65,18 +63,18 @@ export class UniqueKeysCacheInMemoryCS implements IUniqueKeysCacheBase {
|
|
|
65
63
|
isEmpty() {
|
|
66
64
|
return Object.keys(this.uniqueKeysTracker).length === 0;
|
|
67
65
|
}
|
|
68
|
-
|
|
66
|
+
|
|
69
67
|
/**
|
|
70
68
|
* Converts `uniqueKeys` data from cache into request payload.
|
|
71
69
|
*/
|
|
72
|
-
private fromUniqueKeysCollector(uniqueKeys: { [
|
|
70
|
+
private fromUniqueKeysCollector(uniqueKeys: { [userKey: string]: ISet<string> }): UniqueKeysPayloadCs {
|
|
73
71
|
const payload = [];
|
|
74
|
-
const
|
|
75
|
-
for (let k = 0; k <
|
|
76
|
-
const
|
|
77
|
-
const featureNames = setToArray(uniqueKeys[
|
|
72
|
+
const userKeys = Object.keys(uniqueKeys);
|
|
73
|
+
for (let k = 0; k < userKeys.length; k++) {
|
|
74
|
+
const userKey = userKeys[k];
|
|
75
|
+
const featureNames = setToArray(uniqueKeys[userKey]);
|
|
78
76
|
const uniqueKeysPayload = {
|
|
79
|
-
k:
|
|
77
|
+
k: userKey,
|
|
80
78
|
fs: featureNames
|
|
81
79
|
};
|
|
82
80
|
|
|
@@ -84,5 +82,5 @@ export class UniqueKeysCacheInMemoryCS implements IUniqueKeysCacheBase {
|
|
|
84
82
|
}
|
|
85
83
|
return { keys: payload };
|
|
86
84
|
}
|
|
87
|
-
|
|
85
|
+
|
|
88
86
|
}
|
|
@@ -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,5 +1,7 @@
|
|
|
1
1
|
import { Redis } from 'ioredis';
|
|
2
2
|
import { ILogger } from '../../logger/types';
|
|
3
|
+
import { ImpressionCountsPayload } from '../../sync/submitters/types';
|
|
4
|
+
import { forOwn } from '../../utils/lang';
|
|
3
5
|
import { ImpressionCountsCacheInMemory } from '../inMemory/ImpressionCountsCacheInMemory';
|
|
4
6
|
import { LOG_PREFIX, REFRESH_RATE, TTL_REFRESH } from './constants';
|
|
5
7
|
|
|
@@ -10,8 +12,8 @@ export class ImpressionCountsCacheInRedis extends ImpressionCountsCacheInMemory
|
|
|
10
12
|
private readonly redis: Redis;
|
|
11
13
|
private readonly refreshRate: number;
|
|
12
14
|
private intervalId: any;
|
|
13
|
-
|
|
14
|
-
constructor(log: ILogger, key: string, redis: Redis, impressionCountsCacheSize?: number, refreshRate
|
|
15
|
+
|
|
16
|
+
constructor(log: ILogger, key: string, redis: Redis, impressionCountsCacheSize?: number, refreshRate = REFRESH_RATE) {
|
|
15
17
|
super(impressionCountsCacheSize);
|
|
16
18
|
this.log = log;
|
|
17
19
|
this.key = key;
|
|
@@ -19,11 +21,12 @@ export class ImpressionCountsCacheInRedis extends ImpressionCountsCacheInMemory
|
|
|
19
21
|
this.refreshRate = refreshRate;
|
|
20
22
|
this.onFullQueue = () => { this.postImpressionCountsInRedis(); };
|
|
21
23
|
}
|
|
22
|
-
|
|
23
|
-
postImpressionCountsInRedis(){
|
|
24
|
+
|
|
25
|
+
private postImpressionCountsInRedis() {
|
|
24
26
|
const counts = this.pop();
|
|
25
27
|
const keys = Object.keys(counts);
|
|
26
|
-
if (!keys) return Promise.resolve(false);
|
|
28
|
+
if (!keys.length) return Promise.resolve(false);
|
|
29
|
+
|
|
27
30
|
const pipeline = this.redis.pipeline();
|
|
28
31
|
keys.forEach(key => {
|
|
29
32
|
pipeline.hincrby(this.key, key, counts[key]);
|
|
@@ -37,16 +40,56 @@ export class ImpressionCountsCacheInRedis extends ImpressionCountsCacheInMemory
|
|
|
37
40
|
})
|
|
38
41
|
.catch(err => {
|
|
39
42
|
this.log.error(`${LOG_PREFIX}Error in impression counts pipeline: ${err}.`);
|
|
40
|
-
return
|
|
43
|
+
return false;
|
|
41
44
|
});
|
|
42
45
|
}
|
|
43
|
-
|
|
46
|
+
|
|
44
47
|
start() {
|
|
45
48
|
this.intervalId = setInterval(this.postImpressionCountsInRedis.bind(this), this.refreshRate);
|
|
46
49
|
}
|
|
47
|
-
|
|
50
|
+
|
|
48
51
|
stop() {
|
|
49
52
|
clearInterval(this.intervalId);
|
|
50
53
|
return this.postImpressionCountsInRedis();
|
|
51
54
|
}
|
|
55
|
+
|
|
56
|
+
// Async consumer API, used by synchronizer
|
|
57
|
+
getImpressionsCount(): Promise<ImpressionCountsPayload | undefined> {
|
|
58
|
+
return this.redis.hgetall(this.key)
|
|
59
|
+
.then(counts => {
|
|
60
|
+
if (!Object.keys(counts).length) return undefined;
|
|
61
|
+
|
|
62
|
+
this.redis.del(this.key).catch(() => { /* no-op */ });
|
|
63
|
+
|
|
64
|
+
const pf: ImpressionCountsPayload['pf'] = [];
|
|
65
|
+
|
|
66
|
+
forOwn(counts, (count, key) => {
|
|
67
|
+
const nameAndTime = key.split('::');
|
|
68
|
+
if (nameAndTime.length !== 2) {
|
|
69
|
+
this.log.error(`${LOG_PREFIX}Error spliting key ${key}`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const timeFrame = parseInt(nameAndTime[1]);
|
|
74
|
+
if (isNaN(timeFrame)) {
|
|
75
|
+
this.log.error(`${LOG_PREFIX}Error parsing time frame ${nameAndTime[1]}`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const rawCount = parseInt(count);
|
|
80
|
+
if (isNaN(rawCount)) {
|
|
81
|
+
this.log.error(`${LOG_PREFIX}Error parsing raw count ${count}`);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
pf.push({
|
|
86
|
+
f: nameAndTime[0],
|
|
87
|
+
m: timeFrame,
|
|
88
|
+
rc: rawCount,
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return { pf };
|
|
93
|
+
});
|
|
94
|
+
}
|
|
52
95
|
}
|