const mapcap = require('mapcap');
/**
* Simple registry that stores Metrics by name and dimensions.
*/
class DimensionAwareMetricsRegistry {
/**
* @param {DimensionAwareMetricsRegistryOptions} [options] Configurable options for the Dimension Aware Metrics Registry
*/
constructor(options) {
options = options || {};
let metrics = new Map();
if (options.metricLimit) {
metrics = mapcap(metrics, options.metricLimit, options.lru);
}
this._metrics = metrics;
}
/**
* Checks to see if a metric with the given name and dimensions is present.
*
* @param {string} name The metric name
* @param {Dimensions} dimensions The dimensions for the metric
* @returns {boolean} true if the metric with given dimensions is present
*/
hasMetric(name, dimensions) {
const key = this._generateStorageKey(name, dimensions);
return this._metrics.has(key);
}
/**
* Retrieves a metric with a given name and dimensions is present.
*
* @param {string} name The metric name
* @param {Dimensions} dimensions The dimensions for the metric
* @returns {Metric} a wrapper object around name, dimension and {@link Metric}
*/
getMetric(name, dimensions) {
const key = this._generateStorageKey(name, dimensions);
return this._metrics.get(key).metricImpl;
}
/**
* Retrieves a metric by the calculated key (name / dimension combo).
*
* @param {string} key The registered key for the given registered {@link MetricWrapper}
* @returns {MetricWrapper} a wrapper object around name, dimension and {@link Metric}
*/
getMetricWrapperByKey(key) {
return this._metrics.get(key);
}
/**
* Upserts a {@link Metric} in the internal storage map for a given name, dimension combo
*
* @param {string} name The metric name
* @param {Metric} metric The {@link Metric} impl
* @param {Dimensions} dimensions The dimensions for the metric
* @return {string} The registry key for the metric, dimension combo
*/
putMetric(name, metric, dimensions) {
const key = this._generateStorageKey(name, dimensions);
this._metrics.set(key, {
name: name,
metricImpl: metric,
dimensions: dimensions || {}
});
return key;
}
/**
* Returns an array of all keys of metrics stored in this registry.
* @return {string[]} all keys of metrics stored in this registry.
*/
allKeys() {
return Array.from(this._metrics.keys());
}
/**
* Generates a unique key off of the metric name and custom dimensions for internal use in the registry maps.
*
* @param {string} name The metric name
* @param {Dimensions} dimensions The dimensions for the metric
* @return {string} a unique key based off of the metric nae and dimensions
* @private
*/
_generateStorageKey(name, dimensions) {
let key = name;
if (dimensions) {
Object.keys(dimensions)
.sort()
.forEach(dimensionKey => {
key = `${key}-${dimensions[dimensionKey]}`;
});
}
return key;
}
}
module.exports = DimensionAwareMetricsRegistry;
/**
* Configurable options for the Dimension Aware Metrics Registry
*
* @interface DimensionAwareMetricsRegistryOptions
* @typedef DimensionAwareMetricsRegistryOptions
* @property {Number} metricLimit the maximum number of metrics the registry may hold before dropping metrics
* @property {Boolean} lru switch dropping strategy from "least recently added" to "least recently used"
*/