UNPKG

unleash-server

Version:

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

102 lines 3.96 kB
export class CustomMetricsStore { constructor(config) { this.customMetricsStore = new Map(); this.logger = config.getLogger('custom-metrics-store'); } roundToMinute(date) { const rounded = new Date(date); rounded.setSeconds(0); rounded.setMilliseconds(0); return rounded; } getMetricKey(metric, timestamp) { const roundedTimestamp = this.roundToMinute(timestamp); const timeKey = roundedTimestamp.toISOString(); let key = `${metric.name}:${timeKey}`; if (metric.labels && Object.keys(metric.labels).length > 0) { const labelEntries = Object.entries(metric.labels).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)); const labelString = labelEntries .map(([key, value]) => `${key}=${value}`) .join(','); key += `:${labelString}`; } return key; } addMetric(metric) { const now = new Date(); const roundedTimestamp = this.roundToMinute(now); const metricKey = this.getMetricKey(metric, now); const storedMetric = { ...metric, timestamp: roundedTimestamp, }; this.customMetricsStore.set(metricKey, storedMetric); } addMetrics(metrics) { let storedCount = 0; metrics.forEach((metric) => { this.addMetric(metric); storedCount++; }); this.logger.debug(`Stored ${storedCount} custom metrics`); } getMetrics() { return Array.from(this.customMetricsStore.values()); } getMetricsByName(name) { return Array.from(this.customMetricsStore.values()).filter((metric) => metric.name === name); } getMetricNames() { const names = new Set(); for (const metric of this.customMetricsStore.values()) { names.add(metric.name); } return Array.from(names); } getPrometheusMetrics() { let output = ''; const metricsByName = new Map(); for (const metric of this.customMetricsStore.values()) { if (!metricsByName.has(metric.name)) { metricsByName.set(metric.name, new Map()); } let labelKey = ''; if (metric.labels && Object.keys(metric.labels).length > 0) { const labelEntries = Object.entries(metric.labels).sort(([keyA], [keyB]) => keyA.localeCompare(keyB)); labelKey = labelEntries .map(([key, value]) => `${key}=${value}`) .join(','); } const metricsForName = metricsByName.get(metric.name); if (!metricsForName.has(labelKey) || metricsForName.get(labelKey).timestamp < metric.timestamp) { metricsForName.set(labelKey, metric); } } for (const [metricName, metricsMap] of metricsByName.entries()) { if (metricsMap.size === 0) continue; output += `# HELP ${metricName} Custom metric reported to Unleash\n`; output += `# TYPE ${metricName} counter\n`; for (const metric of metricsMap.values()) { let labelStr = ''; if (metric.labels && Object.keys(metric.labels).length > 0) { const labelParts = Object.entries(metric.labels) .map(([key, value]) => `${key}="${this.escapePrometheusString(value)}"`) .join(','); labelStr = `{${labelParts}}`; } output += `${metricName}${labelStr} ${metric.value}\n`; } output += '\n'; } return output; } escapePrometheusString(str) { return str .replace(/\\/g, '\\\\') .replace(/"/g, '\\"') .replace(/\n/g, '\\n'); } } //# sourceMappingURL=custom-metrics-store.js.map