@rolloutctrl/js-sdk 0.0.8 → 0.0.9
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/dist/index.d.mts +17 -9
- package/dist/index.d.ts +17 -9
- package/dist/index.js +41 -37
- package/dist/index.mjs +40 -36
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -32,6 +32,14 @@ interface MetricEvent {
|
|
|
32
32
|
strategyId?: string;
|
|
33
33
|
variantId?: string;
|
|
34
34
|
}
|
|
35
|
+
interface AggregatedMetric {
|
|
36
|
+
type: MetricType;
|
|
37
|
+
featureFlagEnvironmentId: string;
|
|
38
|
+
featureFlagId?: string;
|
|
39
|
+
strategyId?: string;
|
|
40
|
+
variantId?: string;
|
|
41
|
+
count: number;
|
|
42
|
+
}
|
|
35
43
|
interface RolloutCtrlOptions {
|
|
36
44
|
sdkKey: string;
|
|
37
45
|
environment: string;
|
|
@@ -54,10 +62,9 @@ declare class RolloutCtrlClient {
|
|
|
54
62
|
private readonly repository;
|
|
55
63
|
private readonly evaluatorManager;
|
|
56
64
|
private readonly updateProvider;
|
|
57
|
-
private readonly
|
|
65
|
+
private readonly metricAggregator;
|
|
58
66
|
private readonly subscribers;
|
|
59
67
|
private isInitialized;
|
|
60
|
-
private readonly trackedEvaluations;
|
|
61
68
|
private readonly readyPromise;
|
|
62
69
|
private resolveReady;
|
|
63
70
|
private rejectReady;
|
|
@@ -144,19 +151,20 @@ declare class LocalStorageAdapter implements StorageAdapter {
|
|
|
144
151
|
clear(): Promise<void>;
|
|
145
152
|
}
|
|
146
153
|
|
|
147
|
-
|
|
154
|
+
type TrackInput = Omit<AggregatedMetric, 'count'>;
|
|
155
|
+
declare class MetricAggregator {
|
|
148
156
|
private readonly apiUrl;
|
|
149
157
|
private readonly sdkKey;
|
|
150
158
|
private readonly requestTimeout;
|
|
151
|
-
private
|
|
159
|
+
private readonly metrics;
|
|
152
160
|
private flushTimer;
|
|
153
|
-
|
|
161
|
+
private readonly maxMetricKeys;
|
|
162
|
+
constructor(apiUrl: string, sdkKey: string, requestTimeout: number, maxMetricKeys?: number);
|
|
154
163
|
start(): void;
|
|
155
164
|
stop(): void;
|
|
156
|
-
|
|
165
|
+
track(metric: TrackInput): void;
|
|
157
166
|
flush(): Promise<void>;
|
|
158
|
-
private
|
|
159
|
-
private sendBatch;
|
|
167
|
+
private send;
|
|
160
168
|
}
|
|
161
169
|
|
|
162
|
-
export { type Configuration, type ConfigurationRepository, type Evaluator, EvaluatorManager, type FlagConfig, HttpConfigurationRepository, LocalStorageAdapter, type MetricEvent, type MetricType,
|
|
170
|
+
export { type AggregatedMetric, type Configuration, type ConfigurationRepository, type Evaluator, EvaluatorManager, type FlagConfig, HttpConfigurationRepository, LocalStorageAdapter, MetricAggregator, type MetricEvent, type MetricType, PollingUpdateProvider, RolloutCtrlClient, type RolloutCtrlOptions, SseUpdateProvider, type StorageAdapter, type UpdateProvider, type VariantResult, createEvaluator };
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,14 @@ interface MetricEvent {
|
|
|
32
32
|
strategyId?: string;
|
|
33
33
|
variantId?: string;
|
|
34
34
|
}
|
|
35
|
+
interface AggregatedMetric {
|
|
36
|
+
type: MetricType;
|
|
37
|
+
featureFlagEnvironmentId: string;
|
|
38
|
+
featureFlagId?: string;
|
|
39
|
+
strategyId?: string;
|
|
40
|
+
variantId?: string;
|
|
41
|
+
count: number;
|
|
42
|
+
}
|
|
35
43
|
interface RolloutCtrlOptions {
|
|
36
44
|
sdkKey: string;
|
|
37
45
|
environment: string;
|
|
@@ -54,10 +62,9 @@ declare class RolloutCtrlClient {
|
|
|
54
62
|
private readonly repository;
|
|
55
63
|
private readonly evaluatorManager;
|
|
56
64
|
private readonly updateProvider;
|
|
57
|
-
private readonly
|
|
65
|
+
private readonly metricAggregator;
|
|
58
66
|
private readonly subscribers;
|
|
59
67
|
private isInitialized;
|
|
60
|
-
private readonly trackedEvaluations;
|
|
61
68
|
private readonly readyPromise;
|
|
62
69
|
private resolveReady;
|
|
63
70
|
private rejectReady;
|
|
@@ -144,19 +151,20 @@ declare class LocalStorageAdapter implements StorageAdapter {
|
|
|
144
151
|
clear(): Promise<void>;
|
|
145
152
|
}
|
|
146
153
|
|
|
147
|
-
|
|
154
|
+
type TrackInput = Omit<AggregatedMetric, 'count'>;
|
|
155
|
+
declare class MetricAggregator {
|
|
148
156
|
private readonly apiUrl;
|
|
149
157
|
private readonly sdkKey;
|
|
150
158
|
private readonly requestTimeout;
|
|
151
|
-
private
|
|
159
|
+
private readonly metrics;
|
|
152
160
|
private flushTimer;
|
|
153
|
-
|
|
161
|
+
private readonly maxMetricKeys;
|
|
162
|
+
constructor(apiUrl: string, sdkKey: string, requestTimeout: number, maxMetricKeys?: number);
|
|
154
163
|
start(): void;
|
|
155
164
|
stop(): void;
|
|
156
|
-
|
|
165
|
+
track(metric: TrackInput): void;
|
|
157
166
|
flush(): Promise<void>;
|
|
158
|
-
private
|
|
159
|
-
private sendBatch;
|
|
167
|
+
private send;
|
|
160
168
|
}
|
|
161
169
|
|
|
162
|
-
export { type Configuration, type ConfigurationRepository, type Evaluator, EvaluatorManager, type FlagConfig, HttpConfigurationRepository, LocalStorageAdapter, type MetricEvent, type MetricType,
|
|
170
|
+
export { type AggregatedMetric, type Configuration, type ConfigurationRepository, type Evaluator, EvaluatorManager, type FlagConfig, HttpConfigurationRepository, LocalStorageAdapter, MetricAggregator, type MetricEvent, type MetricType, PollingUpdateProvider, RolloutCtrlClient, type RolloutCtrlOptions, SseUpdateProvider, type StorageAdapter, type UpdateProvider, type VariantResult, createEvaluator };
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
EvaluatorManager: () => EvaluatorManager,
|
|
24
24
|
HttpConfigurationRepository: () => HttpConfigurationRepository,
|
|
25
25
|
LocalStorageAdapter: () => LocalStorageAdapter,
|
|
26
|
-
|
|
26
|
+
MetricAggregator: () => MetricAggregator,
|
|
27
27
|
PollingUpdateProvider: () => PollingUpdateProvider,
|
|
28
28
|
RolloutCtrlClient: () => RolloutCtrlClient,
|
|
29
29
|
SseUpdateProvider: () => SseUpdateProvider,
|
|
@@ -259,15 +259,15 @@ var SseUpdateProvider = class {
|
|
|
259
259
|
|
|
260
260
|
// src/metrics.ts
|
|
261
261
|
var FLUSH_INTERVAL_MS = 3e4;
|
|
262
|
-
var
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
constructor(apiUrl, sdkKey, requestTimeout) {
|
|
262
|
+
var DEFAULT_MAX_METRIC_KEYS = 1e3;
|
|
263
|
+
var MetricAggregator = class {
|
|
264
|
+
constructor(apiUrl, sdkKey, requestTimeout, maxMetricKeys = DEFAULT_MAX_METRIC_KEYS) {
|
|
266
265
|
this.apiUrl = apiUrl;
|
|
267
266
|
this.sdkKey = sdkKey;
|
|
268
267
|
this.requestTimeout = requestTimeout;
|
|
269
|
-
this.
|
|
268
|
+
this.metrics = /* @__PURE__ */ new Map();
|
|
270
269
|
this.flushTimer = null;
|
|
270
|
+
this.maxMetricKeys = maxMetricKeys;
|
|
271
271
|
}
|
|
272
272
|
start() {
|
|
273
273
|
this.flushTimer = setInterval(() => {
|
|
@@ -281,29 +281,38 @@ var MetricsQueue = class {
|
|
|
281
281
|
this.flushTimer = null;
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
track(metric) {
|
|
285
|
+
const key = `${metric.type}:${metric.featureFlagEnvironmentId}:${metric.featureFlagId ?? ""}:${metric.strategyId ?? ""}:${metric.variantId ?? ""}`;
|
|
286
|
+
const existing = this.metrics.get(key);
|
|
287
|
+
if (existing) {
|
|
288
|
+
existing.count++;
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (this.metrics.size >= this.maxMetricKeys) return;
|
|
292
|
+
this.metrics.set(key, { ...metric, count: 1 });
|
|
293
|
+
if (this.metrics.size >= this.maxMetricKeys) {
|
|
287
294
|
this.flush().catch(() => {
|
|
288
295
|
});
|
|
289
296
|
}
|
|
290
297
|
}
|
|
291
298
|
async flush() {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (this.queue.length === 0) return;
|
|
296
|
-
const batch = this.queue.splice(0, this.queue.length);
|
|
299
|
+
if (this.metrics.size === 0) return;
|
|
300
|
+
const snapshot = new Map(this.metrics);
|
|
301
|
+
this.metrics.clear();
|
|
297
302
|
try {
|
|
298
|
-
await this.
|
|
303
|
+
await this.send([...snapshot.values()]);
|
|
299
304
|
} catch {
|
|
300
|
-
|
|
301
|
-
this.
|
|
302
|
-
|
|
305
|
+
for (const [key, metric] of snapshot) {
|
|
306
|
+
const current = this.metrics.get(key);
|
|
307
|
+
if (current) {
|
|
308
|
+
current.count += metric.count;
|
|
309
|
+
} else {
|
|
310
|
+
this.metrics.set(key, { ...metric });
|
|
311
|
+
}
|
|
303
312
|
}
|
|
304
313
|
}
|
|
305
314
|
}
|
|
306
|
-
async
|
|
315
|
+
async send(metrics) {
|
|
307
316
|
const controller = new AbortController();
|
|
308
317
|
const timeout = setTimeout(() => controller.abort(), this.requestTimeout);
|
|
309
318
|
try {
|
|
@@ -313,7 +322,7 @@ var MetricsQueue = class {
|
|
|
313
322
|
"x-api-key": this.sdkKey,
|
|
314
323
|
"Content-Type": "application/json"
|
|
315
324
|
},
|
|
316
|
-
body: JSON.stringify({
|
|
325
|
+
body: JSON.stringify({ metrics }),
|
|
317
326
|
signal: controller.signal
|
|
318
327
|
});
|
|
319
328
|
if (!response.ok) {
|
|
@@ -334,17 +343,15 @@ var RolloutCtrlClient = class {
|
|
|
334
343
|
this.emitter = new TinyEmitter();
|
|
335
344
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
336
345
|
this.isInitialized = false;
|
|
337
|
-
this.trackedEvaluations = /* @__PURE__ */ new Map();
|
|
338
346
|
const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
|
|
339
347
|
const refreshInterval = options.refreshInterval ?? DEFAULT_REFRESH_INTERVAL;
|
|
340
348
|
const requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
|
|
341
349
|
this.repository = new HttpConfigurationRepository(apiUrl, options.sdkKey, options.environment, requestTimeout);
|
|
342
350
|
this.evaluatorManager = new EvaluatorManager();
|
|
343
351
|
this.updateProvider = new PollingUpdateProvider(refreshInterval);
|
|
344
|
-
this.
|
|
352
|
+
this.metricAggregator = options.enableMetrics ?? true ? new MetricAggregator(apiUrl, options.sdkKey, requestTimeout) : null;
|
|
345
353
|
this.repository.subscribe((configuration) => {
|
|
346
354
|
this.evaluatorManager.update(configuration);
|
|
347
|
-
this.trackedEvaluations.clear();
|
|
348
355
|
options.storage?.set(configuration).catch(() => {
|
|
349
356
|
});
|
|
350
357
|
if (this.isInitialized) {
|
|
@@ -379,7 +386,7 @@ var RolloutCtrlClient = class {
|
|
|
379
386
|
this.updateProvider.start(() => {
|
|
380
387
|
void this.repository.refresh();
|
|
381
388
|
});
|
|
382
|
-
this.
|
|
389
|
+
this.metricAggregator?.start();
|
|
383
390
|
this.emitter.emit("ready");
|
|
384
391
|
this.resolveReady();
|
|
385
392
|
} catch (error) {
|
|
@@ -401,9 +408,9 @@ var RolloutCtrlClient = class {
|
|
|
401
408
|
}
|
|
402
409
|
async close() {
|
|
403
410
|
this.updateProvider.stop();
|
|
404
|
-
if (this.
|
|
405
|
-
this.
|
|
406
|
-
await this.
|
|
411
|
+
if (this.metricAggregator) {
|
|
412
|
+
this.metricAggregator.stop();
|
|
413
|
+
await this.metricAggregator.flush();
|
|
407
414
|
}
|
|
408
415
|
this.subscribers.clear();
|
|
409
416
|
this.emitter.emit("shutdown");
|
|
@@ -436,29 +443,26 @@ var RolloutCtrlClient = class {
|
|
|
436
443
|
return this.evaluate(flagKey, context).variant;
|
|
437
444
|
}
|
|
438
445
|
trackEvaluation(flagKey, result) {
|
|
439
|
-
if (!this.
|
|
446
|
+
if (!this.metricAggregator || !this.isInitialized) return;
|
|
440
447
|
try {
|
|
441
448
|
const config = this.repository.getConfiguration();
|
|
442
449
|
const flag = config.flags.find((f) => f.key === flagKey);
|
|
443
450
|
if (!flag) return;
|
|
444
|
-
const fingerprint = `${result.enabled ? 1 : 0}:${result.strategy?.id ?? ""}:${result.variant?.id ?? ""}`;
|
|
445
|
-
if (this.trackedEvaluations.get(flagKey) === fingerprint) return;
|
|
446
|
-
this.trackedEvaluations.set(flagKey, fingerprint);
|
|
447
451
|
const base = {
|
|
448
452
|
featureFlagId: flag.id,
|
|
449
453
|
featureFlagEnvironmentId: flag.featureFlagEnvironmentId
|
|
450
454
|
};
|
|
451
|
-
this.
|
|
455
|
+
this.metricAggregator.track({ ...base, type: "FLAG_EVALUATION" });
|
|
452
456
|
if (result.enabled) {
|
|
453
|
-
this.
|
|
457
|
+
this.metricAggregator.track({ ...base, type: "FLAG_ENABLED" });
|
|
454
458
|
if (result.strategy?.id) {
|
|
455
|
-
this.
|
|
459
|
+
this.metricAggregator.track({ ...base, type: "STRATEGY_MATCH", strategyId: result.strategy.id });
|
|
456
460
|
}
|
|
457
461
|
if (result.variant?.id) {
|
|
458
|
-
this.
|
|
462
|
+
this.metricAggregator.track({ ...base, type: "VARIANT_EXPOSURE", variantId: result.variant.id });
|
|
459
463
|
}
|
|
460
464
|
} else {
|
|
461
|
-
this.
|
|
465
|
+
this.metricAggregator.track({ ...base, type: "FLAG_DISABLED" });
|
|
462
466
|
}
|
|
463
467
|
} catch {
|
|
464
468
|
}
|
|
@@ -501,7 +505,7 @@ var LocalStorageAdapter = class {
|
|
|
501
505
|
EvaluatorManager,
|
|
502
506
|
HttpConfigurationRepository,
|
|
503
507
|
LocalStorageAdapter,
|
|
504
|
-
|
|
508
|
+
MetricAggregator,
|
|
505
509
|
PollingUpdateProvider,
|
|
506
510
|
RolloutCtrlClient,
|
|
507
511
|
SseUpdateProvider,
|
package/dist/index.mjs
CHANGED
|
@@ -230,15 +230,15 @@ var SseUpdateProvider = class {
|
|
|
230
230
|
|
|
231
231
|
// src/metrics.ts
|
|
232
232
|
var FLUSH_INTERVAL_MS = 3e4;
|
|
233
|
-
var
|
|
234
|
-
var
|
|
235
|
-
|
|
236
|
-
constructor(apiUrl, sdkKey, requestTimeout) {
|
|
233
|
+
var DEFAULT_MAX_METRIC_KEYS = 1e3;
|
|
234
|
+
var MetricAggregator = class {
|
|
235
|
+
constructor(apiUrl, sdkKey, requestTimeout, maxMetricKeys = DEFAULT_MAX_METRIC_KEYS) {
|
|
237
236
|
this.apiUrl = apiUrl;
|
|
238
237
|
this.sdkKey = sdkKey;
|
|
239
238
|
this.requestTimeout = requestTimeout;
|
|
240
|
-
this.
|
|
239
|
+
this.metrics = /* @__PURE__ */ new Map();
|
|
241
240
|
this.flushTimer = null;
|
|
241
|
+
this.maxMetricKeys = maxMetricKeys;
|
|
242
242
|
}
|
|
243
243
|
start() {
|
|
244
244
|
this.flushTimer = setInterval(() => {
|
|
@@ -252,29 +252,38 @@ var MetricsQueue = class {
|
|
|
252
252
|
this.flushTimer = null;
|
|
253
253
|
}
|
|
254
254
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
255
|
+
track(metric) {
|
|
256
|
+
const key = `${metric.type}:${metric.featureFlagEnvironmentId}:${metric.featureFlagId ?? ""}:${metric.strategyId ?? ""}:${metric.variantId ?? ""}`;
|
|
257
|
+
const existing = this.metrics.get(key);
|
|
258
|
+
if (existing) {
|
|
259
|
+
existing.count++;
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
if (this.metrics.size >= this.maxMetricKeys) return;
|
|
263
|
+
this.metrics.set(key, { ...metric, count: 1 });
|
|
264
|
+
if (this.metrics.size >= this.maxMetricKeys) {
|
|
258
265
|
this.flush().catch(() => {
|
|
259
266
|
});
|
|
260
267
|
}
|
|
261
268
|
}
|
|
262
269
|
async flush() {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (this.queue.length === 0) return;
|
|
267
|
-
const batch = this.queue.splice(0, this.queue.length);
|
|
270
|
+
if (this.metrics.size === 0) return;
|
|
271
|
+
const snapshot = new Map(this.metrics);
|
|
272
|
+
this.metrics.clear();
|
|
268
273
|
try {
|
|
269
|
-
await this.
|
|
274
|
+
await this.send([...snapshot.values()]);
|
|
270
275
|
} catch {
|
|
271
|
-
|
|
272
|
-
this.
|
|
273
|
-
|
|
276
|
+
for (const [key, metric] of snapshot) {
|
|
277
|
+
const current = this.metrics.get(key);
|
|
278
|
+
if (current) {
|
|
279
|
+
current.count += metric.count;
|
|
280
|
+
} else {
|
|
281
|
+
this.metrics.set(key, { ...metric });
|
|
282
|
+
}
|
|
274
283
|
}
|
|
275
284
|
}
|
|
276
285
|
}
|
|
277
|
-
async
|
|
286
|
+
async send(metrics) {
|
|
278
287
|
const controller = new AbortController();
|
|
279
288
|
const timeout = setTimeout(() => controller.abort(), this.requestTimeout);
|
|
280
289
|
try {
|
|
@@ -284,7 +293,7 @@ var MetricsQueue = class {
|
|
|
284
293
|
"x-api-key": this.sdkKey,
|
|
285
294
|
"Content-Type": "application/json"
|
|
286
295
|
},
|
|
287
|
-
body: JSON.stringify({
|
|
296
|
+
body: JSON.stringify({ metrics }),
|
|
288
297
|
signal: controller.signal
|
|
289
298
|
});
|
|
290
299
|
if (!response.ok) {
|
|
@@ -305,17 +314,15 @@ var RolloutCtrlClient = class {
|
|
|
305
314
|
this.emitter = new TinyEmitter();
|
|
306
315
|
this.subscribers = /* @__PURE__ */ new Set();
|
|
307
316
|
this.isInitialized = false;
|
|
308
|
-
this.trackedEvaluations = /* @__PURE__ */ new Map();
|
|
309
317
|
const apiUrl = options.apiUrl ?? DEFAULT_API_URL;
|
|
310
318
|
const refreshInterval = options.refreshInterval ?? DEFAULT_REFRESH_INTERVAL;
|
|
311
319
|
const requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT;
|
|
312
320
|
this.repository = new HttpConfigurationRepository(apiUrl, options.sdkKey, options.environment, requestTimeout);
|
|
313
321
|
this.evaluatorManager = new EvaluatorManager();
|
|
314
322
|
this.updateProvider = new PollingUpdateProvider(refreshInterval);
|
|
315
|
-
this.
|
|
323
|
+
this.metricAggregator = options.enableMetrics ?? true ? new MetricAggregator(apiUrl, options.sdkKey, requestTimeout) : null;
|
|
316
324
|
this.repository.subscribe((configuration) => {
|
|
317
325
|
this.evaluatorManager.update(configuration);
|
|
318
|
-
this.trackedEvaluations.clear();
|
|
319
326
|
options.storage?.set(configuration).catch(() => {
|
|
320
327
|
});
|
|
321
328
|
if (this.isInitialized) {
|
|
@@ -350,7 +357,7 @@ var RolloutCtrlClient = class {
|
|
|
350
357
|
this.updateProvider.start(() => {
|
|
351
358
|
void this.repository.refresh();
|
|
352
359
|
});
|
|
353
|
-
this.
|
|
360
|
+
this.metricAggregator?.start();
|
|
354
361
|
this.emitter.emit("ready");
|
|
355
362
|
this.resolveReady();
|
|
356
363
|
} catch (error) {
|
|
@@ -372,9 +379,9 @@ var RolloutCtrlClient = class {
|
|
|
372
379
|
}
|
|
373
380
|
async close() {
|
|
374
381
|
this.updateProvider.stop();
|
|
375
|
-
if (this.
|
|
376
|
-
this.
|
|
377
|
-
await this.
|
|
382
|
+
if (this.metricAggregator) {
|
|
383
|
+
this.metricAggregator.stop();
|
|
384
|
+
await this.metricAggregator.flush();
|
|
378
385
|
}
|
|
379
386
|
this.subscribers.clear();
|
|
380
387
|
this.emitter.emit("shutdown");
|
|
@@ -407,29 +414,26 @@ var RolloutCtrlClient = class {
|
|
|
407
414
|
return this.evaluate(flagKey, context).variant;
|
|
408
415
|
}
|
|
409
416
|
trackEvaluation(flagKey, result) {
|
|
410
|
-
if (!this.
|
|
417
|
+
if (!this.metricAggregator || !this.isInitialized) return;
|
|
411
418
|
try {
|
|
412
419
|
const config = this.repository.getConfiguration();
|
|
413
420
|
const flag = config.flags.find((f) => f.key === flagKey);
|
|
414
421
|
if (!flag) return;
|
|
415
|
-
const fingerprint = `${result.enabled ? 1 : 0}:${result.strategy?.id ?? ""}:${result.variant?.id ?? ""}`;
|
|
416
|
-
if (this.trackedEvaluations.get(flagKey) === fingerprint) return;
|
|
417
|
-
this.trackedEvaluations.set(flagKey, fingerprint);
|
|
418
422
|
const base = {
|
|
419
423
|
featureFlagId: flag.id,
|
|
420
424
|
featureFlagEnvironmentId: flag.featureFlagEnvironmentId
|
|
421
425
|
};
|
|
422
|
-
this.
|
|
426
|
+
this.metricAggregator.track({ ...base, type: "FLAG_EVALUATION" });
|
|
423
427
|
if (result.enabled) {
|
|
424
|
-
this.
|
|
428
|
+
this.metricAggregator.track({ ...base, type: "FLAG_ENABLED" });
|
|
425
429
|
if (result.strategy?.id) {
|
|
426
|
-
this.
|
|
430
|
+
this.metricAggregator.track({ ...base, type: "STRATEGY_MATCH", strategyId: result.strategy.id });
|
|
427
431
|
}
|
|
428
432
|
if (result.variant?.id) {
|
|
429
|
-
this.
|
|
433
|
+
this.metricAggregator.track({ ...base, type: "VARIANT_EXPOSURE", variantId: result.variant.id });
|
|
430
434
|
}
|
|
431
435
|
} else {
|
|
432
|
-
this.
|
|
436
|
+
this.metricAggregator.track({ ...base, type: "FLAG_DISABLED" });
|
|
433
437
|
}
|
|
434
438
|
} catch {
|
|
435
439
|
}
|
|
@@ -471,7 +475,7 @@ export {
|
|
|
471
475
|
EvaluatorManager,
|
|
472
476
|
HttpConfigurationRepository,
|
|
473
477
|
LocalStorageAdapter,
|
|
474
|
-
|
|
478
|
+
MetricAggregator,
|
|
475
479
|
PollingUpdateProvider,
|
|
476
480
|
RolloutCtrlClient,
|
|
477
481
|
SseUpdateProvider,
|