@splitsoftware/splitio-commons 1.3.2-rc.3 → 1.3.2-rc.6
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 +5 -0
- package/cjs/listeners/browser.js +6 -1
- package/cjs/storages/KeyBuilderSS.js +9 -5
- package/cjs/storages/inRedis/RedisAdapter.js +1 -1
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +7 -0
- package/cjs/storages/inRedis/index.js +4 -1
- package/cjs/storages/pluggable/index.js +2 -1
- package/cjs/sync/submitters/telemetrySubmitter.js +31 -17
- package/cjs/trackers/telemetryTracker.js +2 -2
- package/cjs/utils/timeTracker/now/browser.js +1 -1
- package/cjs/utils/timeTracker/now/node.js +1 -2
- package/esm/listeners/browser.js +6 -1
- package/esm/storages/KeyBuilderSS.js +9 -5
- package/esm/storages/inRedis/RedisAdapter.js +1 -1
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +7 -0
- package/esm/storages/inRedis/index.js +4 -1
- package/esm/storages/pluggable/index.js +2 -1
- package/esm/sync/submitters/telemetrySubmitter.js +30 -17
- package/esm/trackers/telemetryTracker.js +2 -2
- package/esm/utils/timeTracker/now/browser.js +1 -1
- package/esm/utils/timeTracker/now/node.js +1 -2
- package/package.json +1 -1
- package/src/listeners/browser.ts +6 -1
- package/src/sdkFactory/types.ts +16 -2
- package/src/storages/KeyBuilderSS.ts +12 -6
- package/src/storages/inRedis/RedisAdapter.ts +1 -1
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +7 -0
- package/src/storages/inRedis/index.ts +5 -1
- package/src/storages/pluggable/index.ts +2 -1
- package/src/sync/submitters/telemetrySubmitter.ts +33 -18
- package/src/sync/submitters/types.ts +13 -7
- package/src/trackers/telemetryTracker.ts +2 -2
- package/src/utils/murmur3/utfx.ts +1 -2
- package/src/utils/timeTracker/now/browser.ts +1 -1
- package/src/utils/timeTracker/now/node.ts +1 -2
- package/types/sdkFactory/types.d.ts +16 -2
- package/types/storages/KeyBuilderSS.d.ts +3 -2
- package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +1 -0
- package/types/sync/submitters/telemetrySubmitter.d.ts +3 -2
- package/types/sync/submitters/types.d.ts +10 -6
- package/types/utils/timeTracker/index.d.ts +1 -70
- package/cjs/utils/timeTracker/index.js +0 -197
- package/esm/utils/timeTracker/index.js +0 -194
- package/src/utils/timeTracker/index.ts +0 -226
|
@@ -23,10 +23,6 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
23
23
|
return `${this.prefix}.segments.registered`;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
private buildVersionablePrefix() {
|
|
27
|
-
return `${this.metadata.s}/${this.metadata.n}/${this.metadata.i}`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
26
|
buildImpressionsKey() {
|
|
31
27
|
return `${this.prefix}.impressions`;
|
|
32
28
|
}
|
|
@@ -35,6 +31,12 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
35
31
|
return `${this.prefix}.events`;
|
|
36
32
|
}
|
|
37
33
|
|
|
34
|
+
searchPatternForSplitKeys() {
|
|
35
|
+
return `${this.buildSplitKeyPrefix()}*`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Telemetry keys */
|
|
39
|
+
|
|
38
40
|
buildLatencyKey(method: Method, bucket: number) {
|
|
39
41
|
return `${this.prefix}.telemetry.latencies::${this.buildVersionablePrefix()}/${methodNames[method]}/${bucket}`;
|
|
40
42
|
}
|
|
@@ -43,8 +45,12 @@ export class KeyBuilderSS extends KeyBuilder {
|
|
|
43
45
|
return `${this.prefix}.telemetry.exceptions::${this.buildVersionablePrefix()}/${methodNames[method]}`;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
return `${this.
|
|
48
|
+
buildInitKey() {
|
|
49
|
+
return `${this.prefix}.telemetry.init::${this.buildVersionablePrefix()}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private buildVersionablePrefix() {
|
|
53
|
+
return `${this.metadata.s}/${this.metadata.n}/${this.metadata.i}`;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
}
|
|
@@ -8,7 +8,7 @@ import { timeout } from '../../utils/promise/timeout';
|
|
|
8
8
|
const LOG_PREFIX = 'storage:redis-adapter: ';
|
|
9
9
|
|
|
10
10
|
// If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis.
|
|
11
|
-
const METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'pipeline', 'expire', 'mget', 'lrange', 'ltrim'];
|
|
11
|
+
const METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'pipeline', 'expire', 'mget', 'lrange', 'ltrim', 'hset'];
|
|
12
12
|
|
|
13
13
|
// Not part of the settings since it'll vary on each storage. We should be removing storage specific logic from elsewhere.
|
|
14
14
|
const DEFAULT_OPTIONS = {
|
|
@@ -4,6 +4,8 @@ import { KeyBuilderSS } from '../KeyBuilderSS';
|
|
|
4
4
|
import { ITelemetryCacheAsync } from '../types';
|
|
5
5
|
import { findLatencyIndex } from '../findLatencyIndex';
|
|
6
6
|
import { Redis } from 'ioredis';
|
|
7
|
+
import { getTelemetryConfigStats } from '../../sync/submitters/telemetrySubmitter';
|
|
8
|
+
import { CONSUMER_MODE, STORAGE_REDIS } from '../../utils/constants';
|
|
7
9
|
|
|
8
10
|
export class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
9
11
|
|
|
@@ -26,4 +28,9 @@ export class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
|
26
28
|
.catch(() => { /* Handle rejections for telemetry */ });
|
|
27
29
|
}
|
|
28
30
|
|
|
31
|
+
recordConfig() {
|
|
32
|
+
const [key, field] = this.keys.buildInitKey().split('::');
|
|
33
|
+
const value = JSON.stringify(getTelemetryConfigStats(CONSUMER_MODE, STORAGE_REDIS));
|
|
34
|
+
return this.redis.hset(key, field, value).catch(() => { /* Handle rejections for telemetry */ });
|
|
35
|
+
}
|
|
29
36
|
}
|
|
@@ -26,10 +26,14 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
|
|
|
26
26
|
|
|
27
27
|
const keys = new KeyBuilderSS(prefix, metadata);
|
|
28
28
|
const redisClient = new RedisAdapter(log, options.options || {});
|
|
29
|
+
const telemetry = new TelemetryCacheInRedis(log, keys, redisClient);
|
|
29
30
|
|
|
30
31
|
// subscription to Redis connect event in order to emit SDK_READY event on consumer mode
|
|
31
32
|
redisClient.on('connect', () => {
|
|
32
33
|
onReadyCb();
|
|
34
|
+
|
|
35
|
+
// Synchronize config
|
|
36
|
+
telemetry.recordConfig();
|
|
33
37
|
});
|
|
34
38
|
|
|
35
39
|
return {
|
|
@@ -37,7 +41,7 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
|
|
|
37
41
|
segments: new SegmentsCacheInRedis(log, keys, redisClient),
|
|
38
42
|
impressions: new ImpressionsCacheInRedis(log, keys.buildImpressionsKey(), redisClient, metadata),
|
|
39
43
|
events: new EventsCacheInRedis(log, keys.buildEventsKey(), redisClient, metadata),
|
|
40
|
-
telemetry
|
|
44
|
+
telemetry,
|
|
41
45
|
|
|
42
46
|
// When using REDIS we should:
|
|
43
47
|
// 1- Disconnect from the storage
|
|
@@ -39,6 +39,7 @@ function validatePluggableStorageOptions(options: any) {
|
|
|
39
39
|
function wrapperConnect(wrapper: IPluggableStorageWrapper, onReadyCb: (error?: any) => void) {
|
|
40
40
|
wrapper.connect().then(() => {
|
|
41
41
|
onReadyCb();
|
|
42
|
+
// At the moment, we don't synchronize config with pluggable storage
|
|
42
43
|
}).catch((e) => {
|
|
43
44
|
onReadyCb(e || new Error('Error connecting wrapper'));
|
|
44
45
|
});
|
|
@@ -77,7 +78,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
|
|
|
77
78
|
impressions: isPartialConsumer ? new ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
|
|
78
79
|
impressionCounts: optimize ? new ImpressionCountsCacheInMemory() : undefined,
|
|
79
80
|
events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
|
|
80
|
-
// @TODO Not using TelemetryCachePluggable yet
|
|
81
|
+
// @TODO Not using TelemetryCachePluggable yet because it's not supported by the Split Synchronizer, and needs to drop or queue operations while the wrapper is not ready
|
|
81
82
|
// telemetry: isPartialConsumer ? new TelemetryCacheInMemory() : new TelemetryCachePluggable(log, keys, wrapper),
|
|
82
83
|
|
|
83
84
|
// Disconnect the underlying storage
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { ISegmentsCacheSync, ISplitsCacheSync, ITelemetryCacheSync } from '../../storages/types';
|
|
2
2
|
import { submitterFactory, firstPushWindowDecorator } from './submitter';
|
|
3
|
-
import { TelemetryUsageStatsPayload, TelemetryConfigStatsPayload } 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 } from '../../utils/constants';
|
|
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';
|
|
5
5
|
import { SDK_READY, SDK_READY_FROM_CACHE } from '../../readiness/constants';
|
|
6
|
-
import { ISettings } from '../../types';
|
|
6
|
+
import { ConsentStatus, ISettings, SDKMode } from '../../types';
|
|
7
7
|
import { base } from '../../utils/settingsValidation';
|
|
8
8
|
import { usedKeysMap } from '../../utils/inputValidation/apiKey';
|
|
9
9
|
import { timer } from '../../utils/timeTracker/timer';
|
|
10
10
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
11
|
+
import { objectAssign } from '../../utils/lang/objectAssign';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Converts data from telemetry cache into /metrics/usage request payload.
|
|
@@ -54,6 +55,12 @@ const IMPRESSIONS_MODE_MAP = {
|
|
|
54
55
|
[DEBUG]: DEBUG_ENUM
|
|
55
56
|
} as Record<ISettings['sync']['impressionsMode'], (0 | 1)>;
|
|
56
57
|
|
|
58
|
+
const USER_CONSENT_MAP = {
|
|
59
|
+
[CONSENT_UNKNOWN]: 1,
|
|
60
|
+
[CONSENT_GRANTED]: 2,
|
|
61
|
+
[CONSENT_DECLINED]: 3
|
|
62
|
+
} as Record<ConsentStatus, number>;
|
|
63
|
+
|
|
57
64
|
function getActiveFactories() {
|
|
58
65
|
return Object.keys(usedKeysMap).length;
|
|
59
66
|
}
|
|
@@ -64,6 +71,15 @@ function getRedundantActiveFactories() {
|
|
|
64
71
|
}, 0);
|
|
65
72
|
}
|
|
66
73
|
|
|
74
|
+
export function getTelemetryConfigStats(mode: SDKMode, storageType: string): TelemetryConfigStats {
|
|
75
|
+
return {
|
|
76
|
+
oM: OPERATION_MODE_MAP[mode], // @ts-ignore lower case of storage type
|
|
77
|
+
st: storageType.toLowerCase(),
|
|
78
|
+
aF: getActiveFactories(),
|
|
79
|
+
rF: getRedundantActiveFactories(),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
67
83
|
/**
|
|
68
84
|
* Converts data from telemetry cache and settings into /metrics/config request payload.
|
|
69
85
|
*/
|
|
@@ -74,17 +90,17 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
|
|
|
74
90
|
|
|
75
91
|
state(): TelemetryConfigStatsPayload {
|
|
76
92
|
const { urls, scheduler } = settings;
|
|
93
|
+
const isClientSide = settings.core.key !== undefined;
|
|
77
94
|
|
|
78
|
-
return {
|
|
79
|
-
oM: OPERATION_MODE_MAP[settings.mode], // @ts-ignore lower case of storage type
|
|
80
|
-
st: settings.storage.type.toLowerCase(),
|
|
95
|
+
return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
|
|
81
96
|
sE: settings.streamingEnabled,
|
|
82
97
|
rR: {
|
|
83
|
-
sp: scheduler.featuresRefreshRate,
|
|
84
|
-
se: scheduler.segmentsRefreshRate,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
sp: scheduler.featuresRefreshRate / 1000,
|
|
99
|
+
se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
|
|
100
|
+
ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
|
|
101
|
+
im: scheduler.impressionsRefreshRate / 1000,
|
|
102
|
+
ev: scheduler.eventsPushRate / 1000,
|
|
103
|
+
te: scheduler.telemetryRefreshRate / 1000,
|
|
88
104
|
}, // refreshRates
|
|
89
105
|
uO: {
|
|
90
106
|
s: urls.sdk !== base.urls.sdk,
|
|
@@ -98,14 +114,13 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
|
|
|
98
114
|
iM: IMPRESSIONS_MODE_MAP[settings.sync.impressionsMode],
|
|
99
115
|
iL: settings.impressionListener ? true : false,
|
|
100
116
|
hP: false, // @TODO proxy not supported
|
|
101
|
-
aF: getActiveFactories(),
|
|
102
|
-
rF: getRedundantActiveFactories(),
|
|
103
117
|
tR: telemetry.getTimeUntilReady() as number,
|
|
104
118
|
tC: telemetry.getTimeUntilReadyFromCache(),
|
|
105
119
|
nR: telemetry.getNonReadyUsage(),
|
|
106
120
|
t: telemetry.popTags(),
|
|
107
121
|
i: settings.integrations && settings.integrations.map(int => int.type),
|
|
108
|
-
|
|
122
|
+
uC: settings.userConsent ? USER_CONSENT_MAP[settings.userConsent] : 0
|
|
123
|
+
});
|
|
109
124
|
}
|
|
110
125
|
};
|
|
111
126
|
}
|
|
@@ -114,11 +129,11 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
|
|
|
114
129
|
* Submitter that periodically posts telemetry data
|
|
115
130
|
*/
|
|
116
131
|
export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
|
|
117
|
-
const { storage: { splits, segments, telemetry } } = params;
|
|
118
|
-
if (!telemetry) return; // No submitter created if telemetry cache is not defined
|
|
132
|
+
const { storage: { splits, segments, telemetry }, platform: { now } } = params;
|
|
133
|
+
if (!telemetry || !now) return; // No submitter created if telemetry cache is not defined
|
|
119
134
|
|
|
120
|
-
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi,
|
|
121
|
-
const startTime = timer(now
|
|
135
|
+
const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness, sdkReadinessManager } = params;
|
|
136
|
+
const startTime = timer(now);
|
|
122
137
|
|
|
123
138
|
const submitter = firstPushWindowDecorator(
|
|
124
139
|
submitterFactory(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true),
|
|
@@ -151,7 +151,8 @@ export type ImpressionsMode = OPTIMIZED_ENUM | DEBUG_ENUM;
|
|
|
151
151
|
|
|
152
152
|
export type RefreshRates = {
|
|
153
153
|
sp: number, // splits
|
|
154
|
-
se
|
|
154
|
+
se?: number, // segments
|
|
155
|
+
ms?: number, // mySegments
|
|
155
156
|
im: number, // impressions
|
|
156
157
|
ev: number, // events
|
|
157
158
|
te: number, // telemetry
|
|
@@ -165,10 +166,17 @@ export type UrlOverrides = {
|
|
|
165
166
|
t: boolean, // telemetry
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
// '
|
|
169
|
-
export type
|
|
170
|
-
oM
|
|
169
|
+
// 'telemetry.init' Redis/Pluggable key
|
|
170
|
+
export type TelemetryConfigStats = {
|
|
171
|
+
oM: OperationMode, // operationMode
|
|
171
172
|
st: 'memory' | 'redis' | 'pluggable' | 'localstorage', // storage
|
|
173
|
+
aF: number, // activeFactories
|
|
174
|
+
rF: number, // redundantActiveFactories
|
|
175
|
+
t?: Array<string>, // tags
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// 'metrics/config' JSON request body
|
|
179
|
+
export type TelemetryConfigStatsPayload = TelemetryConfigStats & {
|
|
172
180
|
sE: boolean, // streamingEnabled
|
|
173
181
|
rR: RefreshRates, // refreshRates
|
|
174
182
|
uO: UrlOverrides, // urlOverrides
|
|
@@ -177,11 +185,9 @@ export type TelemetryConfigStatsPayload = {
|
|
|
177
185
|
iM: ImpressionsMode, // impressionsMode
|
|
178
186
|
iL: boolean, // impressionsListenerEnabled
|
|
179
187
|
hP: boolean, // httpProxyDetected
|
|
180
|
-
aF: number, // activeFactories
|
|
181
|
-
rF: number, // redundantActiveFactories
|
|
182
188
|
tR: number, // timeUntilSDKReady
|
|
183
189
|
tC?: number, // timeUntilSDKReadyFromCache
|
|
184
190
|
nR: number, // SDKNotReadyUsage
|
|
185
|
-
t?: Array<string>, // tags
|
|
186
191
|
i?: Array<string>, // integrations
|
|
192
|
+
uC: number, // userConsent
|
|
187
193
|
}
|
|
@@ -33,7 +33,7 @@ export function telemetryTrackerFactory(
|
|
|
33
33
|
return (error) => {
|
|
34
34
|
(telemetryCache as ITelemetryCacheSync).recordHttpLatency(operation, httpTime());
|
|
35
35
|
if (error && error.statusCode) (telemetryCache as ITelemetryCacheSync).recordHttpError(operation, error.statusCode);
|
|
36
|
-
else (telemetryCache as ITelemetryCacheSync).recordSuccessfulSync(operation, now());
|
|
36
|
+
else (telemetryCache as ITelemetryCacheSync).recordSuccessfulSync(operation, Date.now());
|
|
37
37
|
};
|
|
38
38
|
},
|
|
39
39
|
sessionLength() { // @ts-ignore ITelemetryCacheAsync doesn't implement the method
|
|
@@ -44,7 +44,7 @@ export function telemetryTrackerFactory(
|
|
|
44
44
|
(telemetryCache as ITelemetryCacheSync).recordAuthRejections();
|
|
45
45
|
} else {
|
|
46
46
|
(telemetryCache as ITelemetryCacheSync).recordStreamingEvents({
|
|
47
|
-
e, d, t: now()
|
|
47
|
+
e, d, t: Date.now()
|
|
48
48
|
});
|
|
49
49
|
if (e === TOKEN_REFRESH) (telemetryCache as ITelemetryCacheSync).recordTokenRefreshes();
|
|
50
50
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
//
|
|
1
|
+
// Can be used on any runtime, since it fallbacks to `Date.now` if `performance.now` is not available
|
|
2
2
|
function nowFactory() {
|
|
3
3
|
// eslint-disable-next-line
|
|
4
4
|
if (typeof performance === 'object' && typeof performance.now === 'function') {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
// @TODO migrate to Node SDK package eventually
|
|
2
1
|
export function now() {
|
|
3
2
|
// eslint-disable-next-line no-undef
|
|
4
3
|
let time = process.hrtime();
|
|
5
4
|
|
|
6
|
-
return time[0] * 1e3 + time[1] * 1e-6; // convert it to
|
|
5
|
+
return time[0] * 1e3 + time[1] * 1e-6; // convert it to millis
|
|
7
6
|
}
|
|
@@ -10,13 +10,27 @@ import { IImpressionsTracker, IEventTracker, ITelemetryTracker } from '../tracke
|
|
|
10
10
|
import { SplitIO, ISettings, IEventEmitter } from '../types';
|
|
11
11
|
/**
|
|
12
12
|
* Environment related dependencies.
|
|
13
|
-
* These getters are called a fixed number of times per factory instantiation.
|
|
14
13
|
*/
|
|
15
14
|
export interface IPlatform {
|
|
16
|
-
|
|
15
|
+
/**
|
|
16
|
+
* If provided, it is used to retrieve the Fetch API for HTTP requests. Otherwise, the global fetch is used.
|
|
17
|
+
*/
|
|
17
18
|
getFetch?: () => (IFetch | undefined);
|
|
19
|
+
/**
|
|
20
|
+
* If provided, it is used to pass additional options to fetch calls.
|
|
21
|
+
*/
|
|
22
|
+
getOptions?: () => object;
|
|
23
|
+
/**
|
|
24
|
+
* If provided, it is used to retrieve the EventSource constructor for streaming support.
|
|
25
|
+
*/
|
|
18
26
|
getEventSource?: () => (IEventSourceConstructor | undefined);
|
|
27
|
+
/**
|
|
28
|
+
* EventEmitter constructor, like NodeJS.EventEmitter or a polyfill.
|
|
29
|
+
*/
|
|
19
30
|
EventEmitter: new () => IEventEmitter;
|
|
31
|
+
/**
|
|
32
|
+
* Function used to track latencies for telemetry.
|
|
33
|
+
*/
|
|
20
34
|
now?: () => number;
|
|
21
35
|
}
|
|
22
36
|
export interface ISdkFactoryContext {
|
|
@@ -5,10 +5,11 @@ export declare class KeyBuilderSS extends KeyBuilder {
|
|
|
5
5
|
protected readonly metadata: IMetadata;
|
|
6
6
|
constructor(prefix: string, metadata: IMetadata);
|
|
7
7
|
buildRegisteredSegmentsKey(): string;
|
|
8
|
-
private buildVersionablePrefix;
|
|
9
8
|
buildImpressionsKey(): string;
|
|
10
9
|
buildEventsKey(): string;
|
|
10
|
+
searchPatternForSplitKeys(): string;
|
|
11
11
|
buildLatencyKey(method: Method, bucket: number): string;
|
|
12
12
|
buildExceptionKey(method: Method): string;
|
|
13
|
-
|
|
13
|
+
buildInitKey(): string;
|
|
14
|
+
private buildVersionablePrefix;
|
|
14
15
|
}
|
|
@@ -16,4 +16,5 @@ export declare class TelemetryCacheInRedis implements ITelemetryCacheAsync {
|
|
|
16
16
|
constructor(log: ILogger, keys: KeyBuilderSS, redis: Redis);
|
|
17
17
|
recordLatency(method: Method, latencyMs: number): Promise<number | void>;
|
|
18
18
|
recordException(method: Method): Promise<number | void>;
|
|
19
|
+
recordConfig(): Promise<number | void>;
|
|
19
20
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ISegmentsCacheSync, ISplitsCacheSync, ITelemetryCacheSync } from '../../storages/types';
|
|
2
|
-
import { TelemetryUsageStatsPayload, TelemetryConfigStatsPayload } from './types';
|
|
3
|
-
import { ISettings } from '../../types';
|
|
2
|
+
import { TelemetryUsageStatsPayload, TelemetryConfigStatsPayload, TelemetryConfigStats } from './types';
|
|
3
|
+
import { ISettings, SDKMode } from '../../types';
|
|
4
4
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
5
5
|
/**
|
|
6
6
|
* Converts data from telemetry cache into /metrics/usage request payload.
|
|
@@ -10,6 +10,7 @@ export declare function telemetryCacheStatsAdapter(telemetry: ITelemetryCacheSyn
|
|
|
10
10
|
clear(): void;
|
|
11
11
|
state(): TelemetryUsageStatsPayload;
|
|
12
12
|
};
|
|
13
|
+
export declare function getTelemetryConfigStats(mode: SDKMode, storageType: string): TelemetryConfigStats;
|
|
13
14
|
/**
|
|
14
15
|
* Converts data from telemetry cache and settings into /metrics/config request payload.
|
|
15
16
|
*/
|
|
@@ -134,7 +134,8 @@ export declare type DEBUG_ENUM = 1;
|
|
|
134
134
|
export declare type ImpressionsMode = OPTIMIZED_ENUM | DEBUG_ENUM;
|
|
135
135
|
export declare type RefreshRates = {
|
|
136
136
|
sp: number;
|
|
137
|
-
se
|
|
137
|
+
se?: number;
|
|
138
|
+
ms?: number;
|
|
138
139
|
im: number;
|
|
139
140
|
ev: number;
|
|
140
141
|
te: number;
|
|
@@ -146,9 +147,14 @@ export declare type UrlOverrides = {
|
|
|
146
147
|
st: boolean;
|
|
147
148
|
t: boolean;
|
|
148
149
|
};
|
|
149
|
-
export declare type
|
|
150
|
-
oM
|
|
150
|
+
export declare type TelemetryConfigStats = {
|
|
151
|
+
oM: OperationMode;
|
|
151
152
|
st: 'memory' | 'redis' | 'pluggable' | 'localstorage';
|
|
153
|
+
aF: number;
|
|
154
|
+
rF: number;
|
|
155
|
+
t?: Array<string>;
|
|
156
|
+
};
|
|
157
|
+
export declare type TelemetryConfigStatsPayload = TelemetryConfigStats & {
|
|
152
158
|
sE: boolean;
|
|
153
159
|
rR: RefreshRates;
|
|
154
160
|
uO: UrlOverrides;
|
|
@@ -157,11 +163,9 @@ export declare type TelemetryConfigStatsPayload = {
|
|
|
157
163
|
iM: ImpressionsMode;
|
|
158
164
|
iL: boolean;
|
|
159
165
|
hP: boolean;
|
|
160
|
-
aF: number;
|
|
161
|
-
rF: number;
|
|
162
166
|
tR: number;
|
|
163
167
|
tC?: number;
|
|
164
168
|
nR: number;
|
|
165
|
-
t?: Array<string>;
|
|
166
169
|
i?: Array<string>;
|
|
170
|
+
uC: number;
|
|
167
171
|
};
|
|
@@ -1,70 +1 @@
|
|
|
1
|
-
|
|
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): 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
|
+
export declare function timeTracker(now: () => number): () => () => number;
|