@splitsoftware/splitio-commons
Version:
Split JavaScript SDK common components
139 lines (138 loc) • 7.19 kB
JavaScript
import { findLatencyIndex } from '../findLatencyIndex';
import { getTelemetryConfigStats } from '../../sync/submitters/telemetrySubmitter';
import { CONSUMER_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
import { isString, isNaNNumber } from '../../utils/lang';
import { MAX_LATENCY_BUCKET_COUNT, newBuckets } from '../inMemory/TelemetryCacheInMemory';
import { parseLatencyField, parseExceptionField, parseMetadata } from '../utils';
var TelemetryCachePluggable = /** @class */ (function () {
/**
* Create a Telemetry cache that uses a storage wrapper.
* @param log - Logger instance.
* @param keys - Key builder.
* @param wrapper - Adapted wrapper storage.
*/
function TelemetryCachePluggable(log, keys, wrapper) {
this.log = log;
this.keys = keys;
this.wrapper = wrapper;
}
TelemetryCachePluggable.prototype.recordLatency = function (method, latencyMs) {
return this.wrapper.incr(this.keys.buildLatencyKey(method, findLatencyIndex(latencyMs)))
.catch(function () { });
};
TelemetryCachePluggable.prototype.recordException = function (method) {
return this.wrapper.incr(this.keys.buildExceptionKey(method))
.catch(function () { });
};
TelemetryCachePluggable.prototype.recordConfig = function () {
var value = JSON.stringify(getTelemetryConfigStats(CONSUMER_MODE, STORAGE_PLUGGABLE));
return this.wrapper.set(this.keys.buildInitKey(), value).catch(function () { });
};
/**
* Pop telemetry latencies.
* The returned promise rejects if wrapper operations fail.
*/
TelemetryCachePluggable.prototype.popLatencies = function () {
var _this = this;
return this.wrapper.getKeysByPrefix(this.keys.latencyPrefix).then(function (latencyKeys) {
return latencyKeys.length ?
_this.wrapper.getMany(latencyKeys).then(function (latencies) {
var result = new Map();
for (var i = 0; i < latencyKeys.length; i++) {
var field = latencyKeys[i].split('::')[1];
var parsedField = parseLatencyField(field);
if (isString(parsedField)) {
_this.log.error("Ignoring invalid latency field: ".concat(field, ": ").concat(parsedField));
continue;
}
// @ts-ignore
var count = parseInt(latencies[i]);
if (isNaNNumber(count)) {
_this.log.error("Ignoring latency with invalid count: ".concat(latencies[i]));
continue;
}
var metadata = parsedField[0], method = parsedField[1], bucket = parsedField[2];
if (bucket >= MAX_LATENCY_BUCKET_COUNT) {
_this.log.error("Ignoring latency with invalid bucket: ".concat(bucket));
continue;
}
var methodLatencies = result.get(metadata) || {};
methodLatencies[method] = methodLatencies[method] || newBuckets();
methodLatencies[method][bucket] = count;
result.set(metadata, methodLatencies);
}
return Promise.all(latencyKeys.map(function (latencyKey) { return _this.wrapper.del(latencyKey); })).then(function () { return result; });
}) :
// If latencyKeys is empty, return an empty map.
new Map();
});
};
/**
* Pop telemetry exceptions.
* The returned promise rejects if wrapper operations fail.
*/
TelemetryCachePluggable.prototype.popExceptions = function () {
var _this = this;
return this.wrapper.getKeysByPrefix(this.keys.exceptionPrefix).then(function (exceptionKeys) {
return exceptionKeys.length ?
_this.wrapper.getMany(exceptionKeys).then(function (exceptions) {
var result = new Map();
for (var i = 0; i < exceptionKeys.length; i++) {
var field = exceptionKeys[i].split('::')[1];
var parsedField = parseExceptionField(field);
if (isString(parsedField)) {
_this.log.error("Ignoring invalid exception field: ".concat(field, ": ").concat(parsedField));
continue;
}
// @ts-ignore
var count = parseInt(exceptions[i]);
if (isNaNNumber(count)) {
_this.log.error("Ignoring exception with invalid count: ".concat(exceptions[i]));
continue;
}
var metadata = parsedField[0], method = parsedField[1];
if (!result.has(metadata))
result.set(metadata, {});
result.get(metadata)[method] = count;
}
return Promise.all(exceptionKeys.map(function (exceptionKey) { return _this.wrapper.del(exceptionKey); })).then(function () { return result; });
}) :
// If exceptionKeys is empty, return an empty map.
new Map();
});
};
/**
* Pop telemetry configs.
* The returned promise rejects if wrapper operations fail.
*/
TelemetryCachePluggable.prototype.popConfigs = function () {
var _this = this;
return this.wrapper.getKeysByPrefix(this.keys.initPrefix).then(function (configKeys) {
return configKeys.length ?
_this.wrapper.getMany(configKeys).then(function (configs) {
var result = new Map();
for (var i = 0; i < configKeys.length; i++) {
var field = configKeys[i].split('::')[1];
var parsedField = parseMetadata(field);
if (isString(parsedField)) {
_this.log.error("Ignoring invalid config field: ".concat(field, ": ").concat(parsedField));
continue;
}
var metadata = parsedField[0];
try { // @ts-ignore
var config = JSON.parse(configs[i]);
result.set(metadata, config);
}
catch (e) {
_this.log.error("Ignoring invalid config: ".concat(configs[i]));
}
}
return Promise.all(configKeys.map(function (configKey) { return _this.wrapper.del(configKey); })).then(function () { return result; });
}) :
// If configKeys is empty, return an empty map.
new Map();
});
};
return TelemetryCachePluggable;
}());
export { TelemetryCachePluggable };