UNPKG

unleash-server

Version:

Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.

113 lines 4.11 kB
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