@splitsoftware/splitio-commons 1.3.2-rc.0 → 1.3.2-rc.3

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.
Files changed (43) hide show
  1. package/cjs/readiness/sdkReadinessManager.js +7 -7
  2. package/cjs/sdkFactory/index.js +1 -1
  3. package/cjs/services/splitApi.js +2 -2
  4. package/cjs/sync/polling/pollingManagerCS.js +1 -1
  5. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +2 -2
  6. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -2
  7. package/cjs/sync/submitters/submitter.js +5 -4
  8. package/cjs/sync/submitters/telemetrySubmitter.js +2 -1
  9. package/cjs/trackers/telemetryTracker.js +4 -2
  10. package/cjs/utils/settingsValidation/index.js +16 -6
  11. package/cjs/utils/settingsValidation/url.js +1 -1
  12. package/esm/readiness/sdkReadinessManager.js +7 -7
  13. package/esm/sdkFactory/index.js +1 -1
  14. package/esm/services/splitApi.js +2 -2
  15. package/esm/sync/polling/pollingManagerCS.js +1 -1
  16. package/esm/sync/polling/syncTasks/splitsSyncTask.js +2 -2
  17. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -2
  18. package/esm/sync/submitters/submitter.js +5 -4
  19. package/esm/sync/submitters/telemetrySubmitter.js +2 -1
  20. package/esm/trackers/telemetryTracker.js +4 -2
  21. package/esm/utils/settingsValidation/index.js +17 -7
  22. package/esm/utils/settingsValidation/url.js +1 -1
  23. package/package.json +1 -1
  24. package/src/readiness/sdkReadinessManager.ts +7 -5
  25. package/src/readiness/types.ts +7 -1
  26. package/src/sdkFactory/index.ts +1 -1
  27. package/src/sdkFactory/types.ts +1 -1
  28. package/src/services/splitApi.ts +2 -2
  29. package/src/sync/polling/pollingManagerCS.ts +1 -1
  30. package/src/sync/polling/syncTasks/splitsSyncTask.ts +2 -0
  31. package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -1
  32. package/src/sync/submitters/submitter.ts +4 -4
  33. package/src/sync/submitters/telemetrySubmitter.ts +2 -1
  34. package/src/trackers/telemetryTracker.ts +3 -3
  35. package/src/types.ts +1 -1
  36. package/src/utils/settingsValidation/index.ts +18 -8
  37. package/src/utils/settingsValidation/url.ts +1 -1
  38. package/types/readiness/sdkReadinessManager.d.ts +1 -3
  39. package/types/readiness/types.d.ts +6 -1
  40. package/types/sdkFactory/types.d.ts +1 -1
  41. package/types/sync/polling/syncTasks/splitsSyncTask.d.ts +1 -1
  42. package/types/sync/polling/updaters/splitChangesUpdater.d.ts +1 -1
  43. package/types/types.d.ts +1 -1
@@ -13,15 +13,13 @@ var REMOVE_LISTENER_EVENT = 'removeListener';
13
13
  * It also updates logs related warnings and errors.
14
14
  *
15
15
  * @param readyTimeout time in millis to emit SDK_READY_TIME_OUT event
16
- * @param internalReadyCbCount offset value of SDK_READY listeners that are added/removed internally
17
- * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
18
16
  * @param readinessManager optional readinessManager to use. only used internally for `shared` method
19
17
  */
20
- function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager) {
18
+ function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, readinessManager) {
21
19
  if (readyTimeout === void 0) { readyTimeout = 0; }
22
- if (internalReadyCbCount === void 0) { internalReadyCbCount = 0; }
23
20
  if (readinessManager === void 0) { readinessManager = (0, readinessManager_1.readinessManagerFactory)(EventEmitter, readyTimeout); }
24
21
  /** Ready callback warning */
22
+ var internalReadyCbCount = 0;
25
23
  var readyCbCount = 0;
26
24
  readinessManager.gate.on(REMOVE_LISTENER_EVENT, function (event) {
27
25
  if (event === constants_1.SDK_READY)
@@ -62,10 +60,12 @@ function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalRea
62
60
  }
63
61
  return {
64
62
  readinessManager: readinessManager,
65
- shared: function (readyTimeout, internalReadyCbCount) {
63
+ shared: function (readyTimeout) {
66
64
  if (readyTimeout === void 0) { readyTimeout = 0; }
67
- if (internalReadyCbCount === void 0) { internalReadyCbCount = 0; }
68
- return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout));
65
+ return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, readinessManager.shared(readyTimeout));
66
+ },
67
+ incInternalReadyCbCount: function () {
68
+ internalReadyCbCount++;
69
69
  },
70
70
  sdkStatus: (0, objectAssign_1.objectAssign)(
71
71
  // Expose Event Emitter functionality
@@ -55,7 +55,7 @@ function sdkFactory(params) {
55
55
  var eventTracker = (0, eventTracker_1.eventTrackerFactory)(settings, storage.events, integrationsManager, storage.telemetry);
56
56
  var telemetryTracker = (0, telemetryTracker_1.telemetryTrackerFactory)(storage.telemetry, platform.now);
57
57
  // splitApi is used by SyncManager and Browser signal listener
58
- var splitApi = splitApiFactory && splitApiFactory(settings, platform);
58
+ var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
59
59
  var ctx = { splitApi: splitApi, eventTracker: eventTracker, impressionsTracker: impressionsTracker, telemetryTracker: telemetryTracker, sdkReadinessManager: sdkReadinessManager, readiness: readiness, settings: settings, storage: storage, platform: platform };
60
60
  var syncManager = syncManagerFactory && syncManagerFactory(ctx);
61
61
  ctx.syncManager = syncManager;
@@ -91,11 +91,11 @@ function splitApiFactory(settings, platform, telemetryTracker) {
91
91
  return splitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.IMPRESSIONS_COUNT));
92
92
  },
93
93
  postMetricsConfig: function (body) {
94
- var url = urls.telemetry + "/metrics/config";
94
+ var url = urls.telemetry + "/v1/metrics/config";
95
95
  return splitHttpClient(url, { method: 'POST', body: body }, telemetryTracker.trackHttp(constants_1.TELEMETRY), true);
96
96
  },
97
97
  postMetricsUsage: function (body) {
98
- var url = urls.telemetry + "/metrics/usage";
98
+ var url = urls.telemetry + "/v1/metrics/usage";
99
99
  return splitHttpClient(url, { method: 'POST', body: body }, telemetryTracker.trackHttp(constants_1.TELEMETRY), true);
100
100
  }
101
101
  };
@@ -14,7 +14,7 @@ var constants_2 = require("../../logger/constants");
14
14
  function pollingManagerCSFactory(params) {
15
15
  var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
16
16
  var log = settings.log;
17
- var splitsSyncTask = (0, splitsSyncTask_1.splitsSyncTaskFactory)(splitApi.fetchSplitChanges, storage, readiness, settings);
17
+ var splitsSyncTask = (0, splitsSyncTask_1.splitsSyncTaskFactory)(splitApi.fetchSplitChanges, storage, readiness, settings, true);
18
18
  // Map of matching keys to their corresponding MySegmentsSyncTask.
19
19
  var mySegmentsSyncTasks = {};
20
20
  var matchingKey = (0, key_1.getMatching)(settings.core.key);
@@ -7,7 +7,7 @@ var splitChangesUpdater_1 = require("../updaters/splitChangesUpdater");
7
7
  /**
8
8
  * Creates a sync task that periodically executes a `splitChangesUpdater` task
9
9
  */
10
- function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings) {
11
- return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
10
+ function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
11
+ return (0, syncTask_1.syncTaskFactory)(settings.log, (0, splitChangesUpdater_1.splitChangesUpdaterFactory)(settings.log, (0, splitChangesFetcher_1.splitChangesFetcherFactory)(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
12
12
  }
13
13
  exports.splitsSyncTaskFactory = splitsSyncTaskFactory;
@@ -69,7 +69,7 @@ exports.computeSplitsMutation = computeSplitsMutation;
69
69
  * @param requestTimeoutBeforeReady How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
70
70
  * @param retriesOnFailureBeforeReady How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
71
71
  */
72
- function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady) {
72
+ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
73
73
  if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
74
74
  if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
75
75
  var startingUp = true;
@@ -111,7 +111,7 @@ function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments,
111
111
  ]).then(function () {
112
112
  if (splitsEventEmitter) {
113
113
  // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
114
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && checkAllSegmentsExist(segments)))
114
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && (isClientSide || checkAllSegmentsExist(segments))))
115
115
  .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
116
116
  .then(function (emitSplitsArrivedEvent) {
117
117
  // emit SDK events
@@ -6,7 +6,8 @@ var constants_1 = require("../../logger/constants");
6
6
  /**
7
7
  * Base function to create submitters, such as ImpressionsSubmitter and EventsSubmitter
8
8
  */
9
- function submitterFactory(log, postClient, sourceCache, postRate, dataName, fromCacheToPayload, maxRetries, debugLogs) {
9
+ function submitterFactory(log, postClient, sourceCache, postRate, dataName, fromCacheToPayload, maxRetries, debugLogs // true for telemetry submitters
10
+ ) {
10
11
  if (maxRetries === void 0) { maxRetries = 0; }
11
12
  var retries = 0;
12
13
  function postData() {
@@ -24,16 +25,16 @@ function submitterFactory(log, postClient, sourceCache, postRate, dataName, from
24
25
  sourceCache.clear(); // we clear the queue if request successes.
25
26
  }).catch(function (err) {
26
27
  if (!maxRetries) {
27
- log.warn(constants_1.SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
28
+ log[debugLogs ? 'debug' : 'warn'](constants_1.SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
28
29
  }
29
30
  else if (retries === maxRetries) {
30
31
  retries = 0;
31
32
  sourceCache.clear(); // we clear the queue if request fails after retries.
32
- log.warn(constants_1.SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
33
+ log[debugLogs ? 'debug' : 'warn'](constants_1.SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
33
34
  }
34
35
  else {
35
36
  retries++;
36
- log.warn(constants_1.SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
37
+ log[debugLogs ? 'debug' : 'warn'](constants_1.SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
37
38
  }
38
39
  });
39
40
  }
@@ -109,12 +109,13 @@ function telemetrySubmitterFactory(params) {
109
109
  var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry;
110
110
  if (!telemetry)
111
111
  return; // No submitter created if telemetry cache is not defined
112
- var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, now = params.platform.now, readiness = params.readiness;
112
+ var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, now = params.platform.now, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
113
113
  var startTime = (0, timer_1.timer)(now || Date.now);
114
114
  var submitter = (0, submitter_1.firstPushWindowDecorator)((0, submitter_1.submitterFactory)(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
115
115
  readiness.gate.once(constants_2.SDK_READY_FROM_CACHE, function () {
116
116
  telemetry.recordTimeUntilReadyFromCache(startTime());
117
117
  });
118
+ sdkReadinessManager.incInternalReadyCbCount();
118
119
  readiness.gate.once(constants_2.SDK_READY, function () {
119
120
  telemetry.recordTimeUntilReady(startTime());
120
121
  // Post config data when the SDK is ready and if the telemetry submitter was started
@@ -16,7 +16,8 @@ function telemetryTrackerFactory(telemetryCache, now) {
16
16
  telemetryCache.recordException(method);
17
17
  return; // Don't track latency on exceptions
18
18
  case labels_1.SDK_NOT_READY: // @ts-ignore ITelemetryCacheAsync doesn't implement the method
19
- telemetryCache === null || telemetryCache === void 0 ? void 0 : telemetryCache.recordNonReadyUsage();
19
+ if (telemetryCache.recordNonReadyUsage)
20
+ telemetryCache.recordNonReadyUsage();
20
21
  }
21
22
  telemetryCache.recordLatency(method, evalTime());
22
23
  };
@@ -32,7 +33,8 @@ function telemetryTrackerFactory(telemetryCache, now) {
32
33
  };
33
34
  },
34
35
  sessionLength: function () {
35
- telemetryCache.recordSessionLength(startTime_1());
36
+ if (telemetryCache.recordSessionLength)
37
+ telemetryCache.recordSessionLength(startTime_1());
36
38
  },
37
39
  streamingEvent: function (e, d) {
38
40
  if (e === constants_1.AUTH_REJECTION) {
@@ -32,8 +32,8 @@ exports.base = {
32
32
  segmentsRefreshRate: 60,
33
33
  // publish telemetry stats each 3600 secs (1 hour)
34
34
  telemetryRefreshRate: 3600,
35
- // publish evaluations each 60 sec
36
- impressionsRefreshRate: 60,
35
+ // publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
36
+ impressionsRefreshRate: 300,
37
37
  // fetch offline changes each 15 sec
38
38
  offlineRefreshRate: 15,
39
39
  // publish events every 60 seconds after the first flush
@@ -55,7 +55,7 @@ exports.base = {
55
55
  // Streaming Server
56
56
  streaming: 'https://streaming.split.io',
57
57
  // Telemetry Server
58
- telemetry: 'https://telemetry.split.io',
58
+ telemetry: 'https://telemetry.split.io/api',
59
59
  },
60
60
  // Defines which kind of storage we should instanciate.
61
61
  storage: undefined,
@@ -96,6 +96,8 @@ function settingsValidation(config, validationParams) {
96
96
  // First thing to validate, since other validators might use the logger.
97
97
  var log = logger(withDefaults); // @ts-ignore, modify readonly prop
98
98
  withDefaults.log = log;
99
+ // ensure a valid impressionsMode
100
+ withDefaults.sync.impressionsMode = (0, impressionsMode_1.validImpressionsMode)(log, withDefaults.sync.impressionsMode);
99
101
  function validateMinValue(paramName, actualValue, minValue) {
100
102
  if (actualValue >= minValue)
101
103
  return actualValue;
@@ -107,10 +109,20 @@ function settingsValidation(config, validationParams) {
107
109
  var scheduler = withDefaults.scheduler, startup = withDefaults.startup;
108
110
  scheduler.featuresRefreshRate = fromSecondsToMillis(scheduler.featuresRefreshRate);
109
111
  scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
110
- scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
111
112
  scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
112
113
  scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
113
114
  scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
115
+ if (scheduler.impressionsRefreshRate !== exports.base.scheduler.impressionsRefreshRate) {
116
+ // Validate impressionsRefreshRate defined by user
117
+ scheduler.impressionsRefreshRate = validateMinValue('impressionsRefreshRate', scheduler.impressionsRefreshRate, withDefaults.sync.impressionsMode === constants_1.DEBUG ? 1 : 60 // Min is 1 sec for DEBUG and 60 secs for OPTIMIZED
118
+ );
119
+ }
120
+ else {
121
+ // Default impressionsRefreshRate for DEBUG mode is 60 secs
122
+ if (withDefaults.sync.impressionsMode === constants_1.DEBUG)
123
+ scheduler.impressionsRefreshRate = 60;
124
+ }
125
+ scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
114
126
  // Log deprecation for old telemetry param
115
127
  if (scheduler.metricsRefreshRate)
116
128
  log.warn('`metricsRefreshRate` will be deprecated soon. For configuring telemetry rates, update `telemetryRefreshRate` value in configs');
@@ -166,8 +178,6 @@ function settingsValidation(config, validationParams) {
166
178
  var splitFiltersValidation = (0, splitFilters_1.validateSplitFilters)(log, withDefaults.sync.splitFilters, withDefaults.mode);
167
179
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
168
180
  withDefaults.sync.__splitFiltersValidation = splitFiltersValidation;
169
- // ensure a valid impressionsMode
170
- withDefaults.sync.impressionsMode = (0, impressionsMode_1.validImpressionsMode)(log, withDefaults.sync.impressionsMode);
171
181
  // ensure a valid user consent value
172
182
  // @ts-ignore, modify readonly prop
173
183
  withDefaults.userConsent = consent(withDefaults);
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.url = void 0;
4
- var telemetryEndpointMatcher = /^\/metrics\/(config|usage)/;
4
+ var telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/;
5
5
  var eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
6
6
  var authEndpointMatcher = /^\/v2\/auth/;
7
7
  var streamingEndpointMatcher = /^\/(sse|event-stream)/;
@@ -10,15 +10,13 @@ var REMOVE_LISTENER_EVENT = 'removeListener';
10
10
  * It also updates logs related warnings and errors.
11
11
  *
12
12
  * @param readyTimeout time in millis to emit SDK_READY_TIME_OUT event
13
- * @param internalReadyCbCount offset value of SDK_READY listeners that are added/removed internally
14
- * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
15
13
  * @param readinessManager optional readinessManager to use. only used internally for `shared` method
16
14
  */
17
- export function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager) {
15
+ export function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, readinessManager) {
18
16
  if (readyTimeout === void 0) { readyTimeout = 0; }
19
- if (internalReadyCbCount === void 0) { internalReadyCbCount = 0; }
20
17
  if (readinessManager === void 0) { readinessManager = readinessManagerFactory(EventEmitter, readyTimeout); }
21
18
  /** Ready callback warning */
19
+ var internalReadyCbCount = 0;
22
20
  var readyCbCount = 0;
23
21
  readinessManager.gate.on(REMOVE_LISTENER_EVENT, function (event) {
24
22
  if (event === SDK_READY)
@@ -59,10 +57,12 @@ export function sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, inte
59
57
  }
60
58
  return {
61
59
  readinessManager: readinessManager,
62
- shared: function (readyTimeout, internalReadyCbCount) {
60
+ shared: function (readyTimeout) {
63
61
  if (readyTimeout === void 0) { readyTimeout = 0; }
64
- if (internalReadyCbCount === void 0) { internalReadyCbCount = 0; }
65
- return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout));
62
+ return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, readinessManager.shared(readyTimeout));
63
+ },
64
+ incInternalReadyCbCount: function () {
65
+ internalReadyCbCount++;
66
66
  },
67
67
  sdkStatus: objectAssign(
68
68
  // Expose Event Emitter functionality
@@ -52,7 +52,7 @@ export function sdkFactory(params) {
52
52
  var eventTracker = eventTrackerFactory(settings, storage.events, integrationsManager, storage.telemetry);
53
53
  var telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
54
54
  // splitApi is used by SyncManager and Browser signal listener
55
- var splitApi = splitApiFactory && splitApiFactory(settings, platform);
55
+ var splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
56
56
  var ctx = { splitApi: splitApi, eventTracker: eventTracker, impressionsTracker: impressionsTracker, telemetryTracker: telemetryTracker, sdkReadinessManager: sdkReadinessManager, readiness: readiness, settings: settings, storage: storage, platform: platform };
57
57
  var syncManager = syncManagerFactory && syncManagerFactory(ctx);
58
58
  ctx.syncManager = syncManager;
@@ -88,11 +88,11 @@ export function splitApiFactory(settings, platform, telemetryTracker) {
88
88
  return splitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT));
89
89
  },
90
90
  postMetricsConfig: function (body) {
91
- var url = urls.telemetry + "/metrics/config";
91
+ var url = urls.telemetry + "/v1/metrics/config";
92
92
  return splitHttpClient(url, { method: 'POST', body: body }, telemetryTracker.trackHttp(TELEMETRY), true);
93
93
  },
94
94
  postMetricsUsage: function (body) {
95
- var url = urls.telemetry + "/metrics/usage";
95
+ var url = urls.telemetry + "/v1/metrics/usage";
96
96
  return splitHttpClient(url, { method: 'POST', body: body }, telemetryTracker.trackHttp(TELEMETRY), true);
97
97
  }
98
98
  };
@@ -11,7 +11,7 @@ import { POLLING_SMART_PAUSING, POLLING_START, POLLING_STOP } from '../../logger
11
11
  export function pollingManagerCSFactory(params) {
12
12
  var splitApi = params.splitApi, storage = params.storage, readiness = params.readiness, settings = params.settings;
13
13
  var log = settings.log;
14
- var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings);
14
+ var splitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
15
15
  // Map of matching keys to their corresponding MySegmentsSyncTask.
16
16
  var mySegmentsSyncTasks = {};
17
17
  var matchingKey = getMatching(settings.core.key);
@@ -4,6 +4,6 @@ import { splitChangesUpdaterFactory } from '../updaters/splitChangesUpdater';
4
4
  /**
5
5
  * Creates a sync task that periodically executes a `splitChangesUpdater` task
6
6
  */
7
- export function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings) {
8
- return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
7
+ export function splitsSyncTaskFactory(fetchSplitChanges, storage, readiness, settings, isClientSide) {
8
+ return syncTaskFactory(settings.log, splitChangesUpdaterFactory(settings.log, splitChangesFetcherFactory(fetchSplitChanges), storage.splits, storage.segments, readiness.splits, settings.startup.requestTimeoutBeforeReady, settings.startup.retriesOnFailureBeforeReady, isClientSide), settings.scheduler.featuresRefreshRate, 'splitChangesUpdater');
9
9
  }
@@ -64,7 +64,7 @@ export function computeSplitsMutation(entries) {
64
64
  * @param requestTimeoutBeforeReady How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
65
65
  * @param retriesOnFailureBeforeReady How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
66
66
  */
67
- export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady) {
67
+ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, segments, splitsEventEmitter, requestTimeoutBeforeReady, retriesOnFailureBeforeReady, isClientSide) {
68
68
  if (requestTimeoutBeforeReady === void 0) { requestTimeoutBeforeReady = 0; }
69
69
  if (retriesOnFailureBeforeReady === void 0) { retriesOnFailureBeforeReady = 0; }
70
70
  var startingUp = true;
@@ -106,7 +106,7 @@ export function splitChangesUpdaterFactory(log, splitChangesFetcher, splits, seg
106
106
  ]).then(function () {
107
107
  if (splitsEventEmitter) {
108
108
  // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
109
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && checkAllSegmentsExist(segments)))
109
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && (isClientSide || checkAllSegmentsExist(segments))))
110
110
  .catch(function () { return false; } /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
111
111
  .then(function (emitSplitsArrivedEvent) {
112
112
  // emit SDK events
@@ -3,7 +3,8 @@ import { SUBMITTERS_PUSH, SUBMITTERS_PUSH_FAILS, SUBMITTERS_PUSH_RETRY } from '.
3
3
  /**
4
4
  * Base function to create submitters, such as ImpressionsSubmitter and EventsSubmitter
5
5
  */
6
- export function submitterFactory(log, postClient, sourceCache, postRate, dataName, fromCacheToPayload, maxRetries, debugLogs) {
6
+ export function submitterFactory(log, postClient, sourceCache, postRate, dataName, fromCacheToPayload, maxRetries, debugLogs // true for telemetry submitters
7
+ ) {
7
8
  if (maxRetries === void 0) { maxRetries = 0; }
8
9
  var retries = 0;
9
10
  function postData() {
@@ -21,16 +22,16 @@ export function submitterFactory(log, postClient, sourceCache, postRate, dataNam
21
22
  sourceCache.clear(); // we clear the queue if request successes.
22
23
  }).catch(function (err) {
23
24
  if (!maxRetries) {
24
- log.warn(SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
25
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
25
26
  }
26
27
  else if (retries === maxRetries) {
27
28
  retries = 0;
28
29
  sourceCache.clear(); // we clear the queue if request fails after retries.
29
- log.warn(SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
30
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
30
31
  }
31
32
  else {
32
33
  retries++;
33
- log.warn(SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
34
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
34
35
  }
35
36
  });
36
37
  }
@@ -104,12 +104,13 @@ export function telemetrySubmitterFactory(params) {
104
104
  var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry;
105
105
  if (!telemetry)
106
106
  return; // No submitter created if telemetry cache is not defined
107
- var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, now = params.platform.now, readiness = params.readiness;
107
+ var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, now = params.platform.now, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
108
108
  var startTime = timer(now || Date.now);
109
109
  var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
110
110
  readiness.gate.once(SDK_READY_FROM_CACHE, function () {
111
111
  telemetry.recordTimeUntilReadyFromCache(startTime());
112
112
  });
113
+ sdkReadinessManager.incInternalReadyCbCount();
113
114
  readiness.gate.once(SDK_READY, function () {
114
115
  telemetry.recordTimeUntilReady(startTime());
115
116
  // Post config data when the SDK is ready and if the telemetry submitter was started
@@ -13,7 +13,8 @@ export function telemetryTrackerFactory(telemetryCache, now) {
13
13
  telemetryCache.recordException(method);
14
14
  return; // Don't track latency on exceptions
15
15
  case SDK_NOT_READY: // @ts-ignore ITelemetryCacheAsync doesn't implement the method
16
- telemetryCache === null || telemetryCache === void 0 ? void 0 : telemetryCache.recordNonReadyUsage();
16
+ if (telemetryCache.recordNonReadyUsage)
17
+ telemetryCache.recordNonReadyUsage();
17
18
  }
18
19
  telemetryCache.recordLatency(method, evalTime());
19
20
  };
@@ -29,7 +30,8 @@ export function telemetryTrackerFactory(telemetryCache, now) {
29
30
  };
30
31
  },
31
32
  sessionLength: function () {
32
- telemetryCache.recordSessionLength(startTime_1());
33
+ if (telemetryCache.recordSessionLength)
34
+ telemetryCache.recordSessionLength(startTime_1());
33
35
  },
34
36
  streamingEvent: function (e, d) {
35
37
  if (e === AUTH_REJECTION) {
@@ -1,7 +1,7 @@
1
1
  import { merge } from '../lang';
2
2
  import { mode } from './mode';
3
3
  import { validateSplitFilters } from './splitFilters';
4
- import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants';
4
+ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE, DEBUG } from '../constants';
5
5
  import { validImpressionsMode } from './impressionsMode';
6
6
  import { validateKey } from '../inputValidation/key';
7
7
  import { validateTrafficType } from '../inputValidation/trafficType';
@@ -29,8 +29,8 @@ export var base = {
29
29
  segmentsRefreshRate: 60,
30
30
  // publish telemetry stats each 3600 secs (1 hour)
31
31
  telemetryRefreshRate: 3600,
32
- // publish evaluations each 60 sec
33
- impressionsRefreshRate: 60,
32
+ // publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
33
+ impressionsRefreshRate: 300,
34
34
  // fetch offline changes each 15 sec
35
35
  offlineRefreshRate: 15,
36
36
  // publish events every 60 seconds after the first flush
@@ -52,7 +52,7 @@ export var base = {
52
52
  // Streaming Server
53
53
  streaming: 'https://streaming.split.io',
54
54
  // Telemetry Server
55
- telemetry: 'https://telemetry.split.io',
55
+ telemetry: 'https://telemetry.split.io/api',
56
56
  },
57
57
  // Defines which kind of storage we should instanciate.
58
58
  storage: undefined,
@@ -93,6 +93,8 @@ export function settingsValidation(config, validationParams) {
93
93
  // First thing to validate, since other validators might use the logger.
94
94
  var log = logger(withDefaults); // @ts-ignore, modify readonly prop
95
95
  withDefaults.log = log;
96
+ // ensure a valid impressionsMode
97
+ withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode);
96
98
  function validateMinValue(paramName, actualValue, minValue) {
97
99
  if (actualValue >= minValue)
98
100
  return actualValue;
@@ -104,10 +106,20 @@ export function settingsValidation(config, validationParams) {
104
106
  var scheduler = withDefaults.scheduler, startup = withDefaults.startup;
105
107
  scheduler.featuresRefreshRate = fromSecondsToMillis(scheduler.featuresRefreshRate);
106
108
  scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
107
- scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
108
109
  scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
109
110
  scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
110
111
  scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
112
+ if (scheduler.impressionsRefreshRate !== base.scheduler.impressionsRefreshRate) {
113
+ // Validate impressionsRefreshRate defined by user
114
+ scheduler.impressionsRefreshRate = validateMinValue('impressionsRefreshRate', scheduler.impressionsRefreshRate, withDefaults.sync.impressionsMode === DEBUG ? 1 : 60 // Min is 1 sec for DEBUG and 60 secs for OPTIMIZED
115
+ );
116
+ }
117
+ else {
118
+ // Default impressionsRefreshRate for DEBUG mode is 60 secs
119
+ if (withDefaults.sync.impressionsMode === DEBUG)
120
+ scheduler.impressionsRefreshRate = 60;
121
+ }
122
+ scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
111
123
  // Log deprecation for old telemetry param
112
124
  if (scheduler.metricsRefreshRate)
113
125
  log.warn('`metricsRefreshRate` will be deprecated soon. For configuring telemetry rates, update `telemetryRefreshRate` value in configs');
@@ -163,8 +175,6 @@ export function settingsValidation(config, validationParams) {
163
175
  var splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
164
176
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
165
177
  withDefaults.sync.__splitFiltersValidation = splitFiltersValidation;
166
- // ensure a valid impressionsMode
167
- withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode);
168
178
  // ensure a valid user consent value
169
179
  // @ts-ignore, modify readonly prop
170
180
  withDefaults.userConsent = consent(withDefaults);
@@ -1,4 +1,4 @@
1
- var telemetryEndpointMatcher = /^\/metrics\/(config|usage)/;
1
+ var telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/;
2
2
  var eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
3
3
  var authEndpointMatcher = /^\/v2\/auth/;
4
4
  var streamingEndpointMatcher = /^\/(sse|event-stream)/;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.3.2-rc.0",
3
+ "version": "1.3.2-rc.3",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -15,18 +15,16 @@ const REMOVE_LISTENER_EVENT = 'removeListener';
15
15
  * It also updates logs related warnings and errors.
16
16
  *
17
17
  * @param readyTimeout time in millis to emit SDK_READY_TIME_OUT event
18
- * @param internalReadyCbCount offset value of SDK_READY listeners that are added/removed internally
19
- * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
20
18
  * @param readinessManager optional readinessManager to use. only used internally for `shared` method
21
19
  */
22
20
  export function sdkReadinessManagerFactory(
23
21
  log: ILogger,
24
22
  EventEmitter: new () => IEventEmitter,
25
23
  readyTimeout = 0,
26
- internalReadyCbCount = 0,
27
24
  readinessManager = readinessManagerFactory(EventEmitter, readyTimeout)): ISdkReadinessManager {
28
25
 
29
26
  /** Ready callback warning */
27
+ let internalReadyCbCount = 0;
30
28
  let readyCbCount = 0;
31
29
  readinessManager.gate.on(REMOVE_LISTENER_EVENT, (event: any) => {
32
30
  if (event === SDK_READY) readyCbCount--;
@@ -74,8 +72,12 @@ export function sdkReadinessManagerFactory(
74
72
  return {
75
73
  readinessManager,
76
74
 
77
- shared(readyTimeout = 0, internalReadyCbCount = 0) {
78
- return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, internalReadyCbCount, readinessManager.shared(readyTimeout));
75
+ shared(readyTimeout = 0) {
76
+ return sdkReadinessManagerFactory(log, EventEmitter, readyTimeout, readinessManager.shared(readyTimeout));
77
+ },
78
+
79
+ incInternalReadyCbCount() {
80
+ internalReadyCbCount++;
79
81
  },
80
82
 
81
83
  sdkStatus: objectAssign(
@@ -66,6 +66,12 @@ export interface ISdkReadinessManager {
66
66
  readinessManager: IReadinessManager
67
67
  sdkStatus: IStatusInterface
68
68
 
69
+ /**
70
+ * Increment internalReadyCbCount, an offset value of SDK_READY listeners that are added/removed internally
71
+ * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
72
+ */
73
+ incInternalReadyCbCount(): void
74
+
69
75
  /** for client-side */
70
- shared(readyTimeout?: number, internalReadyCbCount?: number): ISdkReadinessManager
76
+ shared(readyTimeout?: number): ISdkReadinessManager
71
77
  }
@@ -69,7 +69,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
69
69
  const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
70
70
 
71
71
  // splitApi is used by SyncManager and Browser signal listener
72
- const splitApi = splitApiFactory && splitApiFactory(settings, platform);
72
+ const splitApi = splitApiFactory && splitApiFactory(settings, platform, telemetryTracker);
73
73
 
74
74
  const ctx: ISdkFactoryContext = { splitApi, eventTracker, impressionsTracker, telemetryTracker, sdkReadinessManager, readiness, settings, storage, platform };
75
75
 
@@ -64,7 +64,7 @@ export interface ISdkFactoryParams {
64
64
 
65
65
  // Factory of Split Api (HTTP Client Service).
66
66
  // It is not required when providing an asynchronous storage or offline SyncManager
67
- splitApiFactory?: (settings: ISettings, platform: IPlatform) => ISplitApi,
67
+ splitApiFactory?: (settings: ISettings, platform: IPlatform, telemetryTracker: ITelemetryTracker) => ISplitApi,
68
68
 
69
69
  // SyncManager factory.
70
70
  // Not required when providing an asynchronous storage (consumer mode), but required in standalone mode to avoid SDK timeout.
@@ -108,12 +108,12 @@ export function splitApiFactory(
108
108
  },
109
109
 
110
110
  postMetricsConfig(body: string) {
111
- const url = `${urls.telemetry}/metrics/config`;
111
+ const url = `${urls.telemetry}/v1/metrics/config`;
112
112
  return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
113
113
  },
114
114
 
115
115
  postMetricsUsage(body: string) {
116
- const url = `${urls.telemetry}/metrics/usage`;
116
+ const url = `${urls.telemetry}/v1/metrics/usage`;
117
117
  return splitHttpClient(url, { method: 'POST', body }, telemetryTracker.trackHttp(TELEMETRY), true);
118
118
  }
119
119
  };
@@ -20,7 +20,7 @@ export function pollingManagerCSFactory(
20
20
  const { splitApi, storage, readiness, settings } = params;
21
21
  const log = settings.log;
22
22
 
23
- const splitsSyncTask: ISplitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings);
23
+ const splitsSyncTask: ISplitsSyncTask = splitsSyncTaskFactory(splitApi.fetchSplitChanges, storage, readiness, settings, true);
24
24
 
25
25
  // Map of matching keys to their corresponding MySegmentsSyncTask.
26
26
  const mySegmentsSyncTasks: Record<string, ISegmentsSyncTask> = {};
@@ -15,6 +15,7 @@ export function splitsSyncTaskFactory(
15
15
  storage: IStorageSync,
16
16
  readiness: IReadinessManager,
17
17
  settings: ISettings,
18
+ isClientSide?: boolean
18
19
  ): ISplitsSyncTask {
19
20
  return syncTaskFactory(
20
21
  settings.log,
@@ -26,6 +27,7 @@ export function splitsSyncTaskFactory(
26
27
  readiness.splits,
27
28
  settings.startup.requestTimeoutBeforeReady,
28
29
  settings.startup.retriesOnFailureBeforeReady,
30
+ isClientSide
29
31
  ),
30
32
  settings.scheduler.featuresRefreshRate,
31
33
  'splitChangesUpdater',
@@ -93,6 +93,7 @@ export function splitChangesUpdaterFactory(
93
93
  splitsEventEmitter?: ISplitsEventEmitter,
94
94
  requestTimeoutBeforeReady: number = 0,
95
95
  retriesOnFailureBeforeReady: number = 0,
96
+ isClientSide?: boolean
96
97
  ): ISplitChangesUpdater {
97
98
 
98
99
  let startingUp = true;
@@ -140,7 +141,7 @@ export function splitChangesUpdaterFactory(
140
141
 
141
142
  if (splitsEventEmitter) {
142
143
  // To emit SDK_SPLITS_ARRIVED for server-side SDK, we must check that all registered segments have been fetched
143
- return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && checkAllSegmentsExist(segments)))
144
+ return Promise.resolve(!splitsEventEmitter.splitsArrived || (since !== splitChanges.till && (isClientSide || checkAllSegmentsExist(segments))))
144
145
  .catch(() => false /** noop. just to handle a possible `checkAllSegmentsExist` rejection, before emitting SDK event */)
145
146
  .then(emitSplitsArrivedEvent => {
146
147
  // emit SDK events
@@ -16,7 +16,7 @@ export function submitterFactory<TState>(
16
16
  dataName: string,
17
17
  fromCacheToPayload?: (cacheData: TState) => any,
18
18
  maxRetries: number = 0,
19
- debugLogs?: boolean
19
+ debugLogs?: boolean // true for telemetry submitters
20
20
  ): ISyncTask<[], void> {
21
21
 
22
22
  let retries = 0;
@@ -37,14 +37,14 @@ export function submitterFactory<TState>(
37
37
  sourceCache.clear(); // we clear the queue if request successes.
38
38
  }).catch(err => {
39
39
  if (!maxRetries) {
40
- log.warn(SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
40
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
41
41
  } else if (retries === maxRetries) {
42
42
  retries = 0;
43
43
  sourceCache.clear(); // we clear the queue if request fails after retries.
44
- log.warn(SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
44
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_FAILS, [dataCountMessage, err]);
45
45
  } else {
46
46
  retries++;
47
- log.warn(SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
47
+ log[debugLogs ? 'debug' : 'warn'](SUBMITTERS_PUSH_RETRY, [dataCountMessage, err]);
48
48
  }
49
49
  });
50
50
  }
@@ -117,7 +117,7 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
117
117
  const { storage: { splits, segments, telemetry } } = params;
118
118
  if (!telemetry) return; // No submitter created if telemetry cache is not defined
119
119
 
120
- const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, platform: { now }, readiness } = params;
120
+ const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, platform: { now }, readiness, sdkReadinessManager } = params;
121
121
  const startTime = timer(now || Date.now);
122
122
 
123
123
  const submitter = firstPushWindowDecorator(
@@ -129,6 +129,7 @@ export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
129
129
  telemetry.recordTimeUntilReadyFromCache(startTime());
130
130
  });
131
131
 
132
+ sdkReadinessManager.incInternalReadyCbCount();
132
133
  readiness.gate.once(SDK_READY, () => {
133
134
  telemetry.recordTimeUntilReady(startTime());
134
135
 
@@ -22,7 +22,7 @@ export function telemetryTrackerFactory(
22
22
  telemetryCache.recordException(method);
23
23
  return; // Don't track latency on exceptions
24
24
  case SDK_NOT_READY: // @ts-ignore ITelemetryCacheAsync doesn't implement the method
25
- telemetryCache?.recordNonReadyUsage();
25
+ if (telemetryCache.recordNonReadyUsage) telemetryCache.recordNonReadyUsage();
26
26
  }
27
27
  telemetryCache.recordLatency(method, evalTime());
28
28
  };
@@ -36,8 +36,8 @@ export function telemetryTrackerFactory(
36
36
  else (telemetryCache as ITelemetryCacheSync).recordSuccessfulSync(operation, now());
37
37
  };
38
38
  },
39
- sessionLength() {
40
- (telemetryCache as ITelemetryCacheSync).recordSessionLength(startTime());
39
+ sessionLength() { // @ts-ignore ITelemetryCacheAsync doesn't implement the method
40
+ if (telemetryCache.recordSessionLength) telemetryCache.recordSessionLength(startTime());
41
41
  },
42
42
  streamingEvent(e, d) {
43
43
  if (e === AUTH_REJECTION) {
package/src/types.ts CHANGED
@@ -684,7 +684,7 @@ export namespace SplitIO {
684
684
  /**
685
685
  * String property to override the base URL where the SDK will post telemetry data.
686
686
  * @property {string} telemetry
687
- * @default 'https://telemetry.split.io'
687
+ * @default 'https://telemetry.split.io/api'
688
688
  */
689
689
  telemetry?: string
690
690
  };
@@ -1,7 +1,7 @@
1
1
  import { merge } from '../lang';
2
2
  import { mode } from './mode';
3
3
  import { validateSplitFilters } from './splitFilters';
4
- import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants';
4
+ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE, DEBUG } from '../constants';
5
5
  import { validImpressionsMode } from './impressionsMode';
6
6
  import { ISettingsValidationParams } from './types';
7
7
  import { ISettings } from '../../types';
@@ -34,8 +34,8 @@ export const base = {
34
34
  segmentsRefreshRate: 60,
35
35
  // publish telemetry stats each 3600 secs (1 hour)
36
36
  telemetryRefreshRate: 3600,
37
- // publish evaluations each 60 sec
38
- impressionsRefreshRate: 60,
37
+ // publish evaluations each 300 sec (default value for OPTIMIZED impressions mode)
38
+ impressionsRefreshRate: 300,
39
39
  // fetch offline changes each 15 sec
40
40
  offlineRefreshRate: 15,
41
41
  // publish events every 60 seconds after the first flush
@@ -58,7 +58,7 @@ export const base = {
58
58
  // Streaming Server
59
59
  streaming: 'https://streaming.split.io',
60
60
  // Telemetry Server
61
- telemetry: 'https://telemetry.split.io',
61
+ telemetry: 'https://telemetry.split.io/api',
62
62
  },
63
63
 
64
64
  // Defines which kind of storage we should instanciate.
@@ -113,6 +113,9 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
113
113
  const log = logger(withDefaults); // @ts-ignore, modify readonly prop
114
114
  withDefaults.log = log;
115
115
 
116
+ // ensure a valid impressionsMode
117
+ withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode);
118
+
116
119
  function validateMinValue(paramName: string, actualValue: number, minValue: number) {
117
120
  if (actualValue >= minValue) return actualValue;
118
121
  // actualValue is not a number or is lower than minValue
@@ -124,11 +127,21 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
124
127
  const { scheduler, startup } = withDefaults;
125
128
  scheduler.featuresRefreshRate = fromSecondsToMillis(scheduler.featuresRefreshRate);
126
129
  scheduler.segmentsRefreshRate = fromSecondsToMillis(scheduler.segmentsRefreshRate);
127
- scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
128
130
  scheduler.offlineRefreshRate = fromSecondsToMillis(scheduler.offlineRefreshRate);
129
131
  scheduler.eventsPushRate = fromSecondsToMillis(scheduler.eventsPushRate);
130
132
  scheduler.telemetryRefreshRate = fromSecondsToMillis(validateMinValue('telemetryRefreshRate', scheduler.telemetryRefreshRate, 60));
131
133
 
134
+ if (scheduler.impressionsRefreshRate !== base.scheduler.impressionsRefreshRate) {
135
+ // Validate impressionsRefreshRate defined by user
136
+ scheduler.impressionsRefreshRate = validateMinValue('impressionsRefreshRate', scheduler.impressionsRefreshRate,
137
+ withDefaults.sync.impressionsMode === DEBUG ? 1 : 60 // Min is 1 sec for DEBUG and 60 secs for OPTIMIZED
138
+ );
139
+ } else {
140
+ // Default impressionsRefreshRate for DEBUG mode is 60 secs
141
+ if (withDefaults.sync.impressionsMode === DEBUG) scheduler.impressionsRefreshRate = 60;
142
+ }
143
+ scheduler.impressionsRefreshRate = fromSecondsToMillis(scheduler.impressionsRefreshRate);
144
+
132
145
  // Log deprecation for old telemetry param
133
146
  if (scheduler.metricsRefreshRate) log.warn('`metricsRefreshRate` will be deprecated soon. For configuring telemetry rates, update `telemetryRefreshRate` value in configs');
134
147
 
@@ -190,9 +203,6 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
190
203
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
191
204
  withDefaults.sync.__splitFiltersValidation = splitFiltersValidation;
192
205
 
193
- // ensure a valid impressionsMode
194
- withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode);
195
-
196
206
  // ensure a valid user consent value
197
207
  // @ts-ignore, modify readonly prop
198
208
  withDefaults.userConsent = consent(withDefaults);
@@ -1,6 +1,6 @@
1
1
  import { ISettings } from '../../types';
2
2
 
3
- const telemetryEndpointMatcher = /^\/metrics\/(config|usage)/;
3
+ const telemetryEndpointMatcher = /^\/v1\/metrics\/(config|usage)/;
4
4
  const eventsEndpointMatcher = /^\/(testImpressions|metrics|events)/;
5
5
  const authEndpointMatcher = /^\/v2\/auth/;
6
6
  const streamingEndpointMatcher = /^\/(sse|event-stream)/;
@@ -6,8 +6,6 @@ import { ILogger } from '../logger/types';
6
6
  * It also updates logs related warnings and errors.
7
7
  *
8
8
  * @param readyTimeout time in millis to emit SDK_READY_TIME_OUT event
9
- * @param internalReadyCbCount offset value of SDK_READY listeners that are added/removed internally
10
- * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
11
9
  * @param readinessManager optional readinessManager to use. only used internally for `shared` method
12
10
  */
13
- export declare function sdkReadinessManagerFactory(log: ILogger, EventEmitter: new () => IEventEmitter, readyTimeout?: number, internalReadyCbCount?: number, readinessManager?: import("./types").IReadinessManager): ISdkReadinessManager;
11
+ export declare function sdkReadinessManagerFactory(log: ILogger, EventEmitter: new () => IEventEmitter, readyTimeout?: number, readinessManager?: import("./types").IReadinessManager): ISdkReadinessManager;
@@ -49,7 +49,12 @@ export interface IReadinessManager {
49
49
  export interface ISdkReadinessManager {
50
50
  readinessManager: IReadinessManager;
51
51
  sdkStatus: IStatusInterface;
52
+ /**
53
+ * Increment internalReadyCbCount, an offset value of SDK_READY listeners that are added/removed internally
54
+ * by the SDK. It is required to properly log the warning 'No listeners for SDK Readiness detected'
55
+ */
56
+ incInternalReadyCbCount(): void;
52
57
  /** for client-side */
53
- shared(readyTimeout?: number, internalReadyCbCount?: number): ISdkReadinessManager;
58
+ shared(readyTimeout?: number): ISdkReadinessManager;
54
59
  }
55
60
  export {};
@@ -49,7 +49,7 @@ export interface ISdkFactoryParams {
49
49
  settings: ISettings;
50
50
  platform: IPlatform;
51
51
  storageFactory: (params: IStorageFactoryParams) => IStorageSync | IStorageAsync;
52
- splitApiFactory?: (settings: ISettings, platform: IPlatform) => ISplitApi;
52
+ splitApiFactory?: (settings: ISettings, platform: IPlatform, telemetryTracker: ITelemetryTracker) => ISplitApi;
53
53
  syncManagerFactory?: (params: ISdkFactoryContextSync) => ISyncManager;
54
54
  sdkManagerFactory: (log: ILogger, splits: ISplitsCacheSync | ISplitsCacheAsync, sdkReadinessManager: ISdkReadinessManager) => SplitIO.IManager | SplitIO.IAsyncManager;
55
55
  sdkClientMethodFactory: (params: ISdkFactoryContext) => ({
@@ -6,4 +6,4 @@ import { ISettings } from '../../../types';
6
6
  /**
7
7
  * Creates a sync task that periodically executes a `splitChangesUpdater` task
8
8
  */
9
- export declare function splitsSyncTaskFactory(fetchSplitChanges: IFetchSplitChanges, storage: IStorageSync, readiness: IReadinessManager, settings: ISettings): ISplitsSyncTask;
9
+ export declare function splitsSyncTaskFactory(fetchSplitChanges: IFetchSplitChanges, storage: IStorageSync, readiness: IReadinessManager, settings: ISettings, isClientSide?: boolean): ISplitsSyncTask;
@@ -35,5 +35,5 @@ export declare function computeSplitsMutation(entries: ISplit[]): ISplitMutation
35
35
  * @param requestTimeoutBeforeReady How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
36
36
  * @param retriesOnFailureBeforeReady How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
37
37
  */
38
- export declare function splitChangesUpdaterFactory(log: ILogger, splitChangesFetcher: ISplitChangesFetcher, splits: ISplitsCacheBase, segments: ISegmentsCacheBase, splitsEventEmitter?: ISplitsEventEmitter, requestTimeoutBeforeReady?: number, retriesOnFailureBeforeReady?: number): ISplitChangesUpdater;
38
+ export declare function splitChangesUpdaterFactory(log: ILogger, splitChangesFetcher: ISplitChangesFetcher, splits: ISplitsCacheBase, segments: ISegmentsCacheBase, splitsEventEmitter?: ISplitsEventEmitter, requestTimeoutBeforeReady?: number, retriesOnFailureBeforeReady?: number, isClientSide?: boolean): ISplitChangesUpdater;
39
39
  export {};
package/types/types.d.ts CHANGED
@@ -681,7 +681,7 @@ export declare namespace SplitIO {
681
681
  /**
682
682
  * String property to override the base URL where the SDK will post telemetry data.
683
683
  * @property {string} telemetry
684
- * @default 'https://telemetry.split.io'
684
+ * @default 'https://telemetry.split.io/api'
685
685
  */
686
686
  telemetry?: string;
687
687
  };