@splitsoftware/splitio-commons 1.3.2-rc.5 → 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 CHANGED
@@ -1,4 +1,4 @@
1
- 1.4.0 (May XX, 2022)
1
+ 1.4.0 (May 20, 2022)
2
2
  - Added `scheduler.telemetryRefreshRate` property to SDK configuration, and deprecated `scheduler.metricsRefreshRate` property.
3
3
  - Updated SDK telemetry storage, metrics and updater to be more effective and send less often.
4
4
  - Bugfixing - Updated default values for `scheduler.impressionsRefreshRate` config parameter: 300s for OPTIMIZED impression mode and 60s for DEBUG impression mode.
@@ -82,11 +82,13 @@ function telemetryCacheConfigAdapter(telemetry, settings) {
82
82
  clear: function () { },
83
83
  state: function () {
84
84
  var urls = settings.urls, scheduler = settings.scheduler;
85
+ var isClientSide = settings.core.key !== undefined;
85
86
  return (0, objectAssign_1.objectAssign)(getTelemetryConfigStats(settings.mode, settings.storage.type), {
86
87
  sE: settings.streamingEnabled,
87
88
  rR: {
88
89
  sp: scheduler.featuresRefreshRate / 1000,
89
- se: scheduler.segmentsRefreshRate / 1000,
90
+ se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
91
+ ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
90
92
  im: scheduler.impressionsRefreshRate / 1000,
91
93
  ev: scheduler.eventsPushRate / 1000,
92
94
  te: scheduler.telemetryRefreshRate / 1000,
@@ -118,11 +120,11 @@ exports.telemetryCacheConfigAdapter = telemetryCacheConfigAdapter;
118
120
  * Submitter that periodically posts telemetry data
119
121
  */
120
122
  function telemetrySubmitterFactory(params) {
121
- var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry;
122
- if (!telemetry)
123
+ var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry, now = params.platform.now;
124
+ if (!telemetry || !now)
123
125
  return; // No submitter created if telemetry cache is not defined
124
- 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;
125
- var startTime = (0, timer_1.timer)(now || Date.now);
126
+ var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
127
+ var startTime = (0, timer_1.timer)(now);
126
128
  var submitter = (0, submitter_1.firstPushWindowDecorator)((0, submitter_1.submitterFactory)(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
127
129
  readiness.gate.once(constants_2.SDK_READY_FROM_CACHE, function () {
128
130
  telemetry.recordTimeUntilReadyFromCache(startTime());
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.now = void 0;
4
- // @TODO migrate to Browser SDK package eventually
4
+ // Can be used on any runtime, since it fallbacks to `Date.now` if `performance.now` is not available
5
5
  function nowFactory() {
6
6
  // eslint-disable-next-line
7
7
  if (typeof performance === 'object' && typeof performance.now === 'function') {
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.now = void 0;
4
- // @TODO migrate to Node SDK package eventually
5
4
  function now() {
6
5
  // eslint-disable-next-line no-undef
7
6
  var time = process.hrtime();
@@ -77,11 +77,13 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
77
77
  clear: function () { },
78
78
  state: function () {
79
79
  var urls = settings.urls, scheduler = settings.scheduler;
80
+ var isClientSide = settings.core.key !== undefined;
80
81
  return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
81
82
  sE: settings.streamingEnabled,
82
83
  rR: {
83
84
  sp: scheduler.featuresRefreshRate / 1000,
84
- se: scheduler.segmentsRefreshRate / 1000,
85
+ se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
86
+ ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
85
87
  im: scheduler.impressionsRefreshRate / 1000,
86
88
  ev: scheduler.eventsPushRate / 1000,
87
89
  te: scheduler.telemetryRefreshRate / 1000,
@@ -112,11 +114,11 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
112
114
  * Submitter that periodically posts telemetry data
113
115
  */
114
116
  export function telemetrySubmitterFactory(params) {
115
- var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry;
116
- if (!telemetry)
117
+ var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry, now = params.platform.now;
118
+ if (!telemetry || !now)
117
119
  return; // No submitter created if telemetry cache is not defined
118
- 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;
119
- var startTime = timer(now || Date.now);
120
+ var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
121
+ var startTime = timer(now);
120
122
  var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage, telemetryCacheStatsAdapter(telemetry, splits, segments), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
121
123
  readiness.gate.once(SDK_READY_FROM_CACHE, function () {
122
124
  telemetry.recordTimeUntilReadyFromCache(startTime());
@@ -1,4 +1,4 @@
1
- // @TODO migrate to Browser SDK package eventually
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,4 +1,3 @@
1
- // @TODO migrate to Node SDK package eventually
2
1
  export function now() {
3
2
  // eslint-disable-next-line no-undef
4
3
  var time = process.hrtime();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.3.2-rc.5",
3
+ "version": "1.3.2-rc.6",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -11,13 +11,27 @@ import { SplitIO, ISettings, IEventEmitter } from '../types';
11
11
 
12
12
  /**
13
13
  * Environment related dependencies.
14
- * These getters are called a fixed number of times per factory instantiation.
15
14
  */
16
15
  export interface IPlatform {
17
- getOptions?: () => object
16
+ /**
17
+ * If provided, it is used to retrieve the Fetch API for HTTP requests. Otherwise, the global fetch is used.
18
+ */
18
19
  getFetch?: () => (IFetch | undefined)
20
+ /**
21
+ * If provided, it is used to pass additional options to fetch calls.
22
+ */
23
+ getOptions?: () => object
24
+ /**
25
+ * If provided, it is used to retrieve the EventSource constructor for streaming support.
26
+ */
19
27
  getEventSource?: () => (IEventSourceConstructor | undefined)
28
+ /**
29
+ * EventEmitter constructor, like NodeJS.EventEmitter or a polyfill.
30
+ */
20
31
  EventEmitter: new () => IEventEmitter,
32
+ /**
33
+ * Function used to track latencies for telemetry.
34
+ */
21
35
  now?: () => number
22
36
  }
23
37
 
@@ -90,12 +90,14 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
90
90
 
91
91
  state(): TelemetryConfigStatsPayload {
92
92
  const { urls, scheduler } = settings;
93
+ const isClientSide = settings.core.key !== undefined;
93
94
 
94
95
  return objectAssign(getTelemetryConfigStats(settings.mode, settings.storage.type), {
95
96
  sE: settings.streamingEnabled,
96
97
  rR: {
97
98
  sp: scheduler.featuresRefreshRate / 1000,
98
- se: scheduler.segmentsRefreshRate / 1000,
99
+ se: isClientSide ? undefined : scheduler.segmentsRefreshRate / 1000,
100
+ ms: isClientSide ? scheduler.segmentsRefreshRate / 1000 : undefined,
99
101
  im: scheduler.impressionsRefreshRate / 1000,
100
102
  ev: scheduler.eventsPushRate / 1000,
101
103
  te: scheduler.telemetryRefreshRate / 1000,
@@ -127,11 +129,11 @@ export function telemetryCacheConfigAdapter(telemetry: ITelemetryCacheSync, sett
127
129
  * Submitter that periodically posts telemetry data
128
130
  */
129
131
  export function telemetrySubmitterFactory(params: ISdkFactoryContextSync) {
130
- const { storage: { splits, segments, telemetry } } = params;
131
- 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
132
134
 
133
- const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, platform: { now }, readiness, sdkReadinessManager } = params;
134
- const startTime = timer(now || Date.now);
135
+ const { settings, settings: { log, scheduler: { telemetryRefreshRate } }, splitApi, readiness, sdkReadinessManager } = params;
136
+ const startTime = timer(now);
135
137
 
136
138
  const submitter = firstPushWindowDecorator(
137
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: number, // mySegments
154
+ se?: number, // segments
155
+ ms?: number, // mySegments
155
156
  im: number, // impressions
156
157
  ev: number, // events
157
158
  te: number, // telemetry
@@ -1,4 +1,4 @@
1
- // @TODO migrate to Browser SDK package eventually
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,4 +1,3 @@
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();
@@ -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
- getOptions?: () => object;
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 {
@@ -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: number;
137
+ se?: number;
138
+ ms?: number;
138
139
  im: number;
139
140
  ev: number;
140
141
  te: number;
@@ -1,70 +1 @@
1
- import { ILogger } from '../../logger/types';
2
- import { IResponse } from '../../services/types';
3
- interface MetricsCollector {
4
- countException(): void;
5
- count(status: number): void;
6
- latency(ms: number): void;
7
- ready(ms: number): void;
8
- getTreatment(ms: number): void;
9
- getTreatments(ms: number): void;
10
- getTreatmentWithConfig(ms: number): void;
11
- getTreatmentsWithConfig(ms: number): void;
12
- [method: string]: (ms: number) => void;
13
- }
14
- export declare const TrackerAPI: {
15
- /**
16
- * "Private" method, used to attach count/countException and stop callbacks to a promise.
17
- *
18
- * @param {ILogger} log - Logger.
19
- * @param {Promise} promise - The promise we want to attach the callbacks.
20
- * @param {string} task - The name of the task.
21
- * @param {number | string} modifier - (optional) The modifier for the task, if any.
22
- */
23
- __attachToPromise(log: ILogger, promise: Promise<IResponse>, task: string, collector: false | MetricsCollector, modifier?: string | number | undefined): Promise<IResponse>;
24
- /**
25
- * Starts tracking the time for a given task. All tasks tracked are considered "unique" because
26
- * there may be multiple SDK instances tracking a "generic" task, making any task non-generic.
27
- *
28
- * @param {ILogger} log - Logger.
29
- * @param {string} task - The task we are starting.
30
- * @param {Object} collectors - The collectors map.
31
- * @param {Promise} promise - (optional) The promise we are tracking.
32
- * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered.
33
- */
34
- start(log: ILogger, task: string, collectors?: Record<string, MetricsCollector> | undefined, promise?: Promise<IResponse> | undefined, now?: () => number): 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;
@@ -1,197 +0,0 @@
1
- "use strict";
2
- var _a;
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.TrackerAPI = void 0;
5
- var lang_1 = require("../lang");
6
- var timer_1 = require("./timer");
7
- var thenable_1 = require("../promise/thenable");
8
- // Map we will use for storing timers data
9
- var timers = {};
10
- // Tasks constants
11
- var CONSTANTS = {
12
- SDK_READY: 'Getting ready - Split SDK',
13
- SDK_GET_TREATMENT: 'SDK - Get Treatment',
14
- SDK_GET_TREATMENTS: 'SDK - Get Treatments',
15
- SDK_GET_TREATMENT_WITH_CONFIG: 'SDK - Get Treatment with config',
16
- SDK_GET_TREATMENTS_WITH_CONFIG: 'SDK - Get Treatments with config',
17
- SPLITS_READY: 'Getting ready - Splits',
18
- SEGMENTS_READY: 'Getting ready - Segments',
19
- METRICS_PUSH: 'Pushing - Metrics',
20
- IMPRESSIONS_PUSH: 'Pushing - Impressions',
21
- EVENTS_PUSH: 'Pushing - Events',
22
- MY_SEGMENTS_FETCH: 'Fetching - My Segments',
23
- SEGMENTS_FETCH: 'Fetching - Segments',
24
- SPLITS_FETCH: 'Fetching - Splits'
25
- };
26
- // Tasks callbacks, if any
27
- var CALLBACKS = (_a = {},
28
- _a[CONSTANTS.SDK_READY] = {
29
- collector: 'client',
30
- method: 'ready'
31
- },
32
- _a[CONSTANTS.SDK_GET_TREATMENT] = {
33
- collector: 'client',
34
- method: 'getTreatment'
35
- },
36
- _a[CONSTANTS.SDK_GET_TREATMENTS] = {
37
- collector: 'client',
38
- method: 'getTreatments'
39
- },
40
- _a[CONSTANTS.SDK_GET_TREATMENT_WITH_CONFIG] = {
41
- collector: 'client',
42
- method: 'getTreatmentWithConfig'
43
- },
44
- _a[CONSTANTS.SDK_GET_TREATMENTS_WITH_CONFIG] = {
45
- collector: 'client',
46
- method: 'getTreatmentsWithConfig'
47
- },
48
- _a[CONSTANTS.MY_SEGMENTS_FETCH] = {
49
- collector: 'mySegments',
50
- method: 'latency'
51
- },
52
- _a[CONSTANTS.SEGMENTS_FETCH] = {
53
- collector: 'segmentChanges',
54
- method: 'latency'
55
- },
56
- _a[CONSTANTS.SPLITS_FETCH] = {
57
- collector: 'splitChanges',
58
- method: 'latency'
59
- },
60
- _a);
61
- /**
62
- * Generates the timer keys using the task name and a modifier, if any.
63
- * @param {string} task - The task name
64
- * @param {number | string} modifier - (optional) The modifier, if any.
65
- * @return {string} The generated timer key
66
- */
67
- function generateTimerKey(task, modifier) { return modifier ? task + modifier : task; }
68
- /**
69
- * Given the collectors map, it returns the specific collector for a given task.
70
- *
71
- * @param {string} task - The task name
72
- * @param {Object} collectors - The collectors map
73
- */
74
- function getCollectorForTask(task, collectors) {
75
- var callbackData = CALLBACKS[task];
76
- if (callbackData && collectors)
77
- return collectors[callbackData.collector];
78
- return false;
79
- }
80
- /**
81
- * Given a collector and a task, returns the callback function that should be called when we stop the timer.
82
- *
83
- * @param {string} task - The task name
84
- * @param {Object} collector - The collector object for the task
85
- */
86
- function getCallbackForTask(task, collector) {
87
- var callbackData = CALLBACKS[task];
88
- if (callbackData && collector)
89
- return collector[callbackData.method];
90
- return false;
91
- }
92
- // Our "time tracker" API
93
- exports.TrackerAPI = {
94
- /**
95
- * "Private" method, used to attach count/countException and stop callbacks to a promise.
96
- *
97
- * @param {ILogger} log - Logger.
98
- * @param {Promise} promise - The promise we want to attach the callbacks.
99
- * @param {string} task - The name of the task.
100
- * @param {number | string} modifier - (optional) The modifier for the task, if any.
101
- */
102
- __attachToPromise: function (log, promise, task, collector, modifier) {
103
- var _this = this;
104
- return promise.then(function (resp) {
105
- _this.stop(log, task, modifier);
106
- if (collector && collector.count)
107
- collector.count(resp.status);
108
- return resp;
109
- })
110
- .catch(function (err) {
111
- _this.stop(log, task, modifier);
112
- if (collector && collector.countException)
113
- collector.countException();
114
- throw err;
115
- });
116
- },
117
- /**
118
- * Starts tracking the time for a given task. All tasks tracked are considered "unique" because
119
- * there may be multiple SDK instances tracking a "generic" task, making any task non-generic.
120
- *
121
- * @param {ILogger} log - Logger.
122
- * @param {string} task - The task we are starting.
123
- * @param {Object} collectors - The collectors map.
124
- * @param {Promise} promise - (optional) The promise we are tracking.
125
- * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered.
126
- */
127
- start: function (log, task, collectors, promise, now) {
128
- if (now === void 0) { now = Date.now; }
129
- var taskUniqueId = (0, lang_1.uniqueId)();
130
- var taskCollector = getCollectorForTask(task, collectors);
131
- var result;
132
- // If we are registering a promise with this task, we should count the status and the exceptions as well
133
- // as stopping the task when the promise resolves. Then return the promise
134
- if ((0, thenable_1.thenable)(promise)) {
135
- result = this.__attachToPromise(log, promise, task, taskCollector, taskUniqueId);
136
- }
137
- else {
138
- // If not, we return the stop function, as it will be stopped manually.
139
- result = this.stop.bind(this, log, task, taskUniqueId);
140
- if (CALLBACKS[task] && !taskCollector) {
141
- // and provide a way for a defered setup of the collector, if needed.
142
- // @ts-expect-error
143
- result.setCollectorForTask = this.setCollectorForTask.bind(this, task, taskUniqueId);
144
- }
145
- }
146
- // We start the timer, with an uniqueId attached to it's name, and save tracking info for this task.
147
- var trackingKey = generateTimerKey(task, taskUniqueId);
148
- var cb = getCallbackForTask(task, taskCollector);
149
- timers[trackingKey] = {
150
- cb: cb,
151
- timer: (0, timer_1.timer)(now)
152
- };
153
- return result;
154
- },
155
- /**
156
- * Setup the collector for a task that reports metrics.
157
- *
158
- * @param {string} task - The task name
159
- * @param {number | string} taskUniqueId - The unique identifier for this task
160
- * @param {Object} collectors - The collectors map.
161
- */
162
- setCollectorForTask: function (task, taskUniqueId, collectors) {
163
- var taskCollector = getCollectorForTask(task, collectors);
164
- if (taskCollector) {
165
- var trackingKey = generateTimerKey(task, taskUniqueId);
166
- timers[trackingKey].cb = getCallbackForTask(task, taskCollector);
167
- }
168
- },
169
- /**
170
- * Stops the tracking of a given task.
171
- *
172
- * @param {ILogger} log - Logger.
173
- * @param {string} task - The task we are starting.
174
- * @param {number | string} modifier - (optional) The modifier for that specific task.
175
- */
176
- stop: function (log, task, modifier) {
177
- var timerName = generateTimerKey(task, modifier);
178
- var timerData = timers[timerName];
179
- if (timerData) {
180
- // Stop the timer and round result for readability.
181
- var et = timerData.timer();
182
- log.debug("[TIME TRACKER]: [" + task + "] took " + et + "ms to finish.");
183
- // Check if we have a tracker callback.
184
- if (timerData.cb) {
185
- // If we have a callback, we call it with the elapsed time of the task and then delete the reference.
186
- timerData.cb(et);
187
- }
188
- // Remove the task tracking reference.
189
- delete timers[timerName];
190
- return et;
191
- }
192
- },
193
- /**
194
- * The constants shortcut for the task names.
195
- */
196
- TaskNames: CONSTANTS
197
- };
@@ -1,194 +0,0 @@
1
- var _a;
2
- import { uniqueId } from '../lang';
3
- import { timer } from './timer';
4
- import { thenable } from '../promise/thenable';
5
- // Map we will use for storing timers data
6
- var timers = {};
7
- // Tasks constants
8
- var CONSTANTS = {
9
- SDK_READY: 'Getting ready - Split SDK',
10
- SDK_GET_TREATMENT: 'SDK - Get Treatment',
11
- SDK_GET_TREATMENTS: 'SDK - Get Treatments',
12
- SDK_GET_TREATMENT_WITH_CONFIG: 'SDK - Get Treatment with config',
13
- SDK_GET_TREATMENTS_WITH_CONFIG: 'SDK - Get Treatments with config',
14
- SPLITS_READY: 'Getting ready - Splits',
15
- SEGMENTS_READY: 'Getting ready - Segments',
16
- METRICS_PUSH: 'Pushing - Metrics',
17
- IMPRESSIONS_PUSH: 'Pushing - Impressions',
18
- EVENTS_PUSH: 'Pushing - Events',
19
- MY_SEGMENTS_FETCH: 'Fetching - My Segments',
20
- SEGMENTS_FETCH: 'Fetching - Segments',
21
- SPLITS_FETCH: 'Fetching - Splits'
22
- };
23
- // Tasks callbacks, if any
24
- var CALLBACKS = (_a = {},
25
- _a[CONSTANTS.SDK_READY] = {
26
- collector: 'client',
27
- method: 'ready'
28
- },
29
- _a[CONSTANTS.SDK_GET_TREATMENT] = {
30
- collector: 'client',
31
- method: 'getTreatment'
32
- },
33
- _a[CONSTANTS.SDK_GET_TREATMENTS] = {
34
- collector: 'client',
35
- method: 'getTreatments'
36
- },
37
- _a[CONSTANTS.SDK_GET_TREATMENT_WITH_CONFIG] = {
38
- collector: 'client',
39
- method: 'getTreatmentWithConfig'
40
- },
41
- _a[CONSTANTS.SDK_GET_TREATMENTS_WITH_CONFIG] = {
42
- collector: 'client',
43
- method: 'getTreatmentsWithConfig'
44
- },
45
- _a[CONSTANTS.MY_SEGMENTS_FETCH] = {
46
- collector: 'mySegments',
47
- method: 'latency'
48
- },
49
- _a[CONSTANTS.SEGMENTS_FETCH] = {
50
- collector: 'segmentChanges',
51
- method: 'latency'
52
- },
53
- _a[CONSTANTS.SPLITS_FETCH] = {
54
- collector: 'splitChanges',
55
- method: 'latency'
56
- },
57
- _a);
58
- /**
59
- * Generates the timer keys using the task name and a modifier, if any.
60
- * @param {string} task - The task name
61
- * @param {number | string} modifier - (optional) The modifier, if any.
62
- * @return {string} The generated timer key
63
- */
64
- function generateTimerKey(task, modifier) { return modifier ? task + modifier : task; }
65
- /**
66
- * Given the collectors map, it returns the specific collector for a given task.
67
- *
68
- * @param {string} task - The task name
69
- * @param {Object} collectors - The collectors map
70
- */
71
- function getCollectorForTask(task, collectors) {
72
- var callbackData = CALLBACKS[task];
73
- if (callbackData && collectors)
74
- return collectors[callbackData.collector];
75
- return false;
76
- }
77
- /**
78
- * Given a collector and a task, returns the callback function that should be called when we stop the timer.
79
- *
80
- * @param {string} task - The task name
81
- * @param {Object} collector - The collector object for the task
82
- */
83
- function getCallbackForTask(task, collector) {
84
- var callbackData = CALLBACKS[task];
85
- if (callbackData && collector)
86
- return collector[callbackData.method];
87
- return false;
88
- }
89
- // Our "time tracker" API
90
- export var TrackerAPI = {
91
- /**
92
- * "Private" method, used to attach count/countException and stop callbacks to a promise.
93
- *
94
- * @param {ILogger} log - Logger.
95
- * @param {Promise} promise - The promise we want to attach the callbacks.
96
- * @param {string} task - The name of the task.
97
- * @param {number | string} modifier - (optional) The modifier for the task, if any.
98
- */
99
- __attachToPromise: function (log, promise, task, collector, modifier) {
100
- var _this = this;
101
- return promise.then(function (resp) {
102
- _this.stop(log, task, modifier);
103
- if (collector && collector.count)
104
- collector.count(resp.status);
105
- return resp;
106
- })
107
- .catch(function (err) {
108
- _this.stop(log, task, modifier);
109
- if (collector && collector.countException)
110
- collector.countException();
111
- throw err;
112
- });
113
- },
114
- /**
115
- * Starts tracking the time for a given task. All tasks tracked are considered "unique" because
116
- * there may be multiple SDK instances tracking a "generic" task, making any task non-generic.
117
- *
118
- * @param {ILogger} log - Logger.
119
- * @param {string} task - The task we are starting.
120
- * @param {Object} collectors - The collectors map.
121
- * @param {Promise} promise - (optional) The promise we are tracking.
122
- * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered.
123
- */
124
- start: function (log, task, collectors, promise, now) {
125
- if (now === void 0) { now = Date.now; }
126
- var taskUniqueId = uniqueId();
127
- var taskCollector = getCollectorForTask(task, collectors);
128
- var result;
129
- // If we are registering a promise with this task, we should count the status and the exceptions as well
130
- // as stopping the task when the promise resolves. Then return the promise
131
- if (thenable(promise)) {
132
- result = this.__attachToPromise(log, promise, task, taskCollector, taskUniqueId);
133
- }
134
- else {
135
- // If not, we return the stop function, as it will be stopped manually.
136
- result = this.stop.bind(this, log, task, taskUniqueId);
137
- if (CALLBACKS[task] && !taskCollector) {
138
- // and provide a way for a defered setup of the collector, if needed.
139
- // @ts-expect-error
140
- result.setCollectorForTask = this.setCollectorForTask.bind(this, task, taskUniqueId);
141
- }
142
- }
143
- // We start the timer, with an uniqueId attached to it's name, and save tracking info for this task.
144
- var trackingKey = generateTimerKey(task, taskUniqueId);
145
- var cb = getCallbackForTask(task, taskCollector);
146
- timers[trackingKey] = {
147
- cb: cb,
148
- timer: timer(now)
149
- };
150
- return result;
151
- },
152
- /**
153
- * Setup the collector for a task that reports metrics.
154
- *
155
- * @param {string} task - The task name
156
- * @param {number | string} taskUniqueId - The unique identifier for this task
157
- * @param {Object} collectors - The collectors map.
158
- */
159
- setCollectorForTask: function (task, taskUniqueId, collectors) {
160
- var taskCollector = getCollectorForTask(task, collectors);
161
- if (taskCollector) {
162
- var trackingKey = generateTimerKey(task, taskUniqueId);
163
- timers[trackingKey].cb = getCallbackForTask(task, taskCollector);
164
- }
165
- },
166
- /**
167
- * Stops the tracking of a given task.
168
- *
169
- * @param {ILogger} log - Logger.
170
- * @param {string} task - The task we are starting.
171
- * @param {number | string} modifier - (optional) The modifier for that specific task.
172
- */
173
- stop: function (log, task, modifier) {
174
- var timerName = generateTimerKey(task, modifier);
175
- var timerData = timers[timerName];
176
- if (timerData) {
177
- // Stop the timer and round result for readability.
178
- var et = timerData.timer();
179
- log.debug("[TIME TRACKER]: [" + task + "] took " + et + "ms to finish.");
180
- // Check if we have a tracker callback.
181
- if (timerData.cb) {
182
- // If we have a callback, we call it with the elapsed time of the task and then delete the reference.
183
- timerData.cb(et);
184
- }
185
- // Remove the task tracking reference.
186
- delete timers[timerName];
187
- return et;
188
- }
189
- },
190
- /**
191
- * The constants shortcut for the task names.
192
- */
193
- TaskNames: CONSTANTS
194
- };
@@ -1,226 +0,0 @@
1
- import { uniqueId } from '../lang';
2
- import { timer } from './timer';
3
- import { thenable } from '../promise/thenable';
4
- import { ILogger } from '../../logger/types';
5
- import { IResponse } from '../../services/types';
6
-
7
- // Based on ProducerMetricsCollector and ClientCollector classes
8
- interface MetricsCollector {
9
- // ProducerMetricsCollector API
10
- countException(): void,
11
- count(status: number): void,
12
- latency(ms: number): void,
13
-
14
- // ClientCollector API
15
- ready(ms: number): void,
16
- getTreatment(ms: number): void,
17
- getTreatments(ms: number): void,
18
- getTreatmentWithConfig(ms: number): void,
19
- getTreatmentsWithConfig(ms: number): void,
20
-
21
- [method: string]: (ms: number) => void,
22
- }
23
-
24
- // Map we will use for storing timers data
25
- const timers: Record<string, {
26
- cb: false | ((et: number) => void),
27
- timer: () => number
28
- }> = {};
29
-
30
- // Tasks constants
31
- const CONSTANTS = {
32
- SDK_READY: 'Getting ready - Split SDK',
33
- SDK_GET_TREATMENT: 'SDK - Get Treatment',
34
- SDK_GET_TREATMENTS: 'SDK - Get Treatments',
35
- SDK_GET_TREATMENT_WITH_CONFIG: 'SDK - Get Treatment with config',
36
- SDK_GET_TREATMENTS_WITH_CONFIG: 'SDK - Get Treatments with config',
37
- SPLITS_READY: 'Getting ready - Splits',
38
- SEGMENTS_READY: 'Getting ready - Segments',
39
- METRICS_PUSH: 'Pushing - Metrics',
40
- IMPRESSIONS_PUSH: 'Pushing - Impressions',
41
- EVENTS_PUSH: 'Pushing - Events',
42
- MY_SEGMENTS_FETCH: 'Fetching - My Segments',
43
- SEGMENTS_FETCH: 'Fetching - Segments',
44
- SPLITS_FETCH: 'Fetching - Splits'
45
- };
46
- // Tasks callbacks, if any
47
- const CALLBACKS = {
48
- [CONSTANTS.SDK_READY]: {
49
- collector: 'client',
50
- method: 'ready'
51
- },
52
- [CONSTANTS.SDK_GET_TREATMENT]: {
53
- collector: 'client',
54
- method: 'getTreatment'
55
- },
56
- [CONSTANTS.SDK_GET_TREATMENTS]: {
57
- collector: 'client',
58
- method: 'getTreatments'
59
- },
60
- [CONSTANTS.SDK_GET_TREATMENT_WITH_CONFIG]: {
61
- collector: 'client',
62
- method: 'getTreatmentWithConfig'
63
- },
64
- [CONSTANTS.SDK_GET_TREATMENTS_WITH_CONFIG]: {
65
- collector: 'client',
66
- method: 'getTreatmentsWithConfig'
67
- },
68
- [CONSTANTS.MY_SEGMENTS_FETCH]: {
69
- collector: 'mySegments',
70
- method: 'latency'
71
- },
72
- [CONSTANTS.SEGMENTS_FETCH]: {
73
- collector: 'segmentChanges',
74
- method: 'latency'
75
- },
76
- [CONSTANTS.SPLITS_FETCH]: {
77
- collector: 'splitChanges',
78
- method: 'latency'
79
- }
80
- };
81
- /**
82
- * Generates the timer keys using the task name and a modifier, if any.
83
- * @param {string} task - The task name
84
- * @param {number | string} modifier - (optional) The modifier, if any.
85
- * @return {string} The generated timer key
86
- */
87
- function generateTimerKey(task: string, modifier?: number | string) { return modifier ? task + modifier : task; }
88
- /**
89
- * Given the collectors map, it returns the specific collector for a given task.
90
- *
91
- * @param {string} task - The task name
92
- * @param {Object} collectors - The collectors map
93
- */
94
- function getCollectorForTask(task: string, collectors?: Record<string, MetricsCollector>): false | MetricsCollector {
95
- const callbackData = CALLBACKS[task];
96
-
97
- if (callbackData && collectors) return collectors[callbackData.collector];
98
-
99
- return false;
100
- }
101
- /**
102
- * Given a collector and a task, returns the callback function that should be called when we stop the timer.
103
- *
104
- * @param {string} task - The task name
105
- * @param {Object} collector - The collector object for the task
106
- */
107
- function getCallbackForTask(task: string, collector: MetricsCollector | false): ((ms: number) => void) | false {
108
- const callbackData = CALLBACKS[task];
109
-
110
- if (callbackData && collector) return collector[callbackData.method];
111
-
112
- return false;
113
- }
114
-
115
- // Our "time tracker" API
116
- export const TrackerAPI = {
117
- /**
118
- * "Private" method, used to attach count/countException and stop callbacks to a promise.
119
- *
120
- * @param {ILogger} log - Logger.
121
- * @param {Promise} promise - The promise we want to attach the callbacks.
122
- * @param {string} task - The name of the task.
123
- * @param {number | string} modifier - (optional) The modifier for the task, if any.
124
- */
125
- __attachToPromise(log: ILogger, promise: Promise<IResponse>, task: string, collector: false | MetricsCollector, modifier?: number | string) {
126
- return promise.then(resp => {
127
- this.stop(log, task, modifier);
128
-
129
- if (collector && collector.count) collector.count(resp.status);
130
-
131
- return resp;
132
- })
133
- .catch(err => {
134
- this.stop(log, task, modifier);
135
-
136
- if (collector && collector.countException) collector.countException();
137
-
138
- throw err;
139
- });
140
- },
141
- /**
142
- * Starts tracking the time for a given task. All tasks tracked are considered "unique" because
143
- * there may be multiple SDK instances tracking a "generic" task, making any task non-generic.
144
- *
145
- * @param {ILogger} log - Logger.
146
- * @param {string} task - The task we are starting.
147
- * @param {Object} collectors - The collectors map.
148
- * @param {Promise} promise - (optional) The promise we are tracking.
149
- * @return {Function | Promise} The stop function for this specific task or the promise received with the callbacks registered.
150
- */
151
- start(log: ILogger, task: string, collectors?: Record<string, MetricsCollector>, promise?: Promise<IResponse>, now: () => number = Date.now): Promise<IResponse> | (() => number) {
152
- const taskUniqueId = uniqueId();
153
- const taskCollector = getCollectorForTask(task, collectors);
154
- let result;
155
-
156
- // If we are registering a promise with this task, we should count the status and the exceptions as well
157
- // as stopping the task when the promise resolves. Then return the promise
158
- if (thenable(promise)) {
159
- result = this.__attachToPromise(log, promise, task, taskCollector, taskUniqueId);
160
- } else {
161
- // If not, we return the stop function, as it will be stopped manually.
162
- result = this.stop.bind(this, log, task, taskUniqueId);
163
- if (CALLBACKS[task] && !taskCollector) {
164
- // and provide a way for a defered setup of the collector, if needed.
165
- // @ts-expect-error
166
- result.setCollectorForTask = this.setCollectorForTask.bind(this, task, taskUniqueId);
167
- }
168
- }
169
-
170
- // We start the timer, with an uniqueId attached to it's name, and save tracking info for this task.
171
- const trackingKey = generateTimerKey(task, taskUniqueId);
172
- const cb = getCallbackForTask(task, taskCollector);
173
- timers[trackingKey] = {
174
- cb,
175
- timer: timer(now)
176
- };
177
-
178
- return result as () => number;
179
- },
180
- /**
181
- * Setup the collector for a task that reports metrics.
182
- *
183
- * @param {string} task - The task name
184
- * @param {number | string} taskUniqueId - The unique identifier for this task
185
- * @param {Object} collectors - The collectors map.
186
- */
187
- setCollectorForTask(task: string, taskUniqueId: number | string, collectors: Record<string, MetricsCollector>) {
188
- const taskCollector = getCollectorForTask(task, collectors);
189
-
190
- if (taskCollector) {
191
- const trackingKey = generateTimerKey(task, taskUniqueId);
192
- timers[trackingKey].cb = getCallbackForTask(task, taskCollector);
193
- }
194
- },
195
- /**
196
- * Stops the tracking of a given task.
197
- *
198
- * @param {ILogger} log - Logger.
199
- * @param {string} task - The task we are starting.
200
- * @param {number | string} modifier - (optional) The modifier for that specific task.
201
- */
202
- stop(log: ILogger, task: string, modifier?: number | string) {
203
- const timerName = generateTimerKey(task, modifier);
204
- const timerData = timers[timerName];
205
- if (timerData) {
206
- // Stop the timer and round result for readability.
207
- const et = timerData.timer();
208
- log.debug(`[TIME TRACKER]: [${task}] took ${et}ms to finish.`);
209
-
210
- // Check if we have a tracker callback.
211
- if (timerData.cb) {
212
- // If we have a callback, we call it with the elapsed time of the task and then delete the reference.
213
- timerData.cb(et);
214
- }
215
-
216
- // Remove the task tracking reference.
217
- delete timers[timerName];
218
-
219
- return et;
220
- }
221
- },
222
- /**
223
- * The constants shortcut for the task names.
224
- */
225
- TaskNames: CONSTANTS
226
- };