unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
113 lines • 4.11 kB
JavaScript
import { Counter, Gauge } from 'prom-client';
export class MetricsTranslator {
constructor(registry) {
this.registry = registry;
}
sanitizeName(name) {
const regex = /[^a-zA-Z0-9_]/g;
const sanitized = name.replace(regex, '_');
return sanitized;
}
hasNewLabels(existingMetric, newLabelNames) {
const existingLabelNames = existingMetric.labelNames || [];
return newLabelNames.some((label) => !existingLabelNames.includes(label));
}
transformLabels(labels) {
return Object.fromEntries(Object.entries(labels).map(([labelKey, value]) => [
`unleash_${this.sanitizeName(labelKey)}`,
value,
]));
}
addOriginLabel(sample) {
return {
...(sample.labels || {}),
origin: (sample.labels && sample.labels.origin) || 'sdk',
};
}
translateMetric(metric) {
const sanitizedName = this.sanitizeName(metric.name);
const prefixedName = `unleash_${metric.type}_${sanitizedName}`;
const existingMetric = this.registry.getSingleMetric(prefixedName);
const allLabelNames = new Set();
allLabelNames.add('unleash_origin');
for (const sample of metric.samples) {
if (sample.labels) {
Object.keys(sample.labels).forEach((label) => allLabelNames.add(`unleash_${label}`));
}
}
const labelNames = Array.from(allLabelNames).map((labelName) => this.sanitizeName(labelName));
if (metric.type === 'counter') {
let counter;
if (existingMetric && existingMetric instanceof Counter) {
if (this.hasNewLabels(existingMetric, labelNames)) {
this.registry.removeSingleMetric(prefixedName);
counter = new Counter({
name: prefixedName,
help: metric.help,
registers: [this.registry],
labelNames,
});
}
else {
counter = existingMetric;
}
}
else {
counter = new Counter({
name: prefixedName,
help: metric.help,
registers: [this.registry],
labelNames,
});
}
for (const sample of metric.samples) {
counter.inc(this.transformLabels(this.addOriginLabel(sample)), sample.value);
}
return counter;
}
else if (metric.type === 'gauge') {
let gauge;
if (existingMetric && existingMetric instanceof Gauge) {
if (this.hasNewLabels(existingMetric, labelNames)) {
this.registry.removeSingleMetric(prefixedName);
gauge = new Gauge({
name: prefixedName,
help: metric.help,
registers: [this.registry],
labelNames,
});
}
else {
gauge = existingMetric;
}
}
else {
gauge = new Gauge({
name: prefixedName,
help: metric.help,
registers: [this.registry],
labelNames,
});
}
for (const sample of metric.samples) {
gauge.set(this.transformLabels(this.addOriginLabel(sample)), sample.value);
}
return gauge;
}
return null;
}
translateMetrics(metrics) {
for (const metric of metrics) {
this.translateMetric(metric);
}
return this.registry;
}
serializeMetrics() {
return this.registry.metrics();
}
translateAndSerializeMetrics(metrics) {
this.translateMetrics(metrics);
return this.serializeMetrics();
}
}
//# sourceMappingURL=metrics-translator.js.map