alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
1,487 lines (1,486 loc) • 152 kB
JavaScript
import { createRequire } from "node:module";
import { $hook, $inject, $module, Alepha } from "alepha";
import { $route, AlephaServer } from "alepha/server";
//#region \0rolldown/runtime.js
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __esmMin = (fn, res, err) => () => {
if (err) throw err[0];
try {
return fn && (res = fn(fn = 0)), res;
} catch (e) {
throw err = [e], e;
}
};
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __exportAll = (all, no_symbols) => {
let target = {};
for (var name in all) __defProp(target, name, {
get: all[name],
enumerable: true
});
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
return target;
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
//#endregion
//#region ../../../../node_modules/prom-client/lib/util.js
var require_util = /* @__PURE__ */ __commonJSMin(((exports) => {
exports.getValueAsString = function getValueString(value) {
if (Number.isNaN(value)) return "Nan";
else if (!Number.isFinite(value)) if (value < 0) return "-Inf";
else return "+Inf";
else return `${value}`;
};
exports.removeLabels = function removeLabels(hashMap, labels, sortedLabelNames) {
const hash = hashObject(labels, sortedLabelNames);
delete hashMap[hash];
};
exports.setValue = function setValue(hashMap, value, labels) {
const hash = hashObject(labels);
hashMap[hash] = {
value: typeof value === "number" ? value : 0,
labels: labels || {}
};
return hashMap;
};
exports.setValueDelta = function setValueDelta(hashMap, deltaValue, labels, hash = "") {
const value = typeof deltaValue === "number" ? deltaValue : 0;
if (hashMap[hash]) hashMap[hash].value += value;
else hashMap[hash] = {
value,
labels
};
return hashMap;
};
exports.getLabels = function(labelNames, args) {
if (typeof args[0] === "object") return args[0];
if (labelNames.length !== args.length) throw new Error(`Invalid number of arguments (${args.length}): "${args.join(", ")}" for label names (${labelNames.length}): "${labelNames.join(", ")}".`);
const acc = {};
for (let i = 0; i < labelNames.length; i++) acc[labelNames[i]] = args[i];
return acc;
};
function fastHashObject(keys, labels) {
if (keys.length === 0) return "";
let hash = "";
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = labels[key];
if (value === void 0) continue;
hash += `${key}:${value},`;
}
return hash;
}
function hashObject(labels, labelNames) {
if (labelNames) return fastHashObject(labelNames, labels);
const keys = Object.keys(labels);
if (keys.length > 1) keys.sort();
return fastHashObject(keys, labels);
}
exports.hashObject = hashObject;
exports.isObject = function isObject(obj) {
return obj !== null && typeof obj === "object";
};
exports.nowTimestamp = function nowTimestamp() {
return Date.now() / 1e3;
};
var Grouper = class extends Map {
/**
* Adds the `value` to the `key`'s array of values.
* @param {*} key Key to set.
* @param {*} value Value to add to `key`'s array.
* @returns {undefined} undefined.
*/
add(key, value) {
if (this.has(key)) this.get(key).push(value);
else this.set(key, [value]);
}
};
exports.Grouper = Grouper;
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/registry.js
var require_registry = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { getValueAsString } = require_util();
var Registry = class Registry {
static get PROMETHEUS_CONTENT_TYPE() {
return "text/plain; version=0.0.4; charset=utf-8";
}
static get OPENMETRICS_CONTENT_TYPE() {
return "application/openmetrics-text; version=1.0.0; charset=utf-8";
}
constructor(regContentType = Registry.PROMETHEUS_CONTENT_TYPE) {
this._metrics = {};
this._collectors = [];
this._defaultLabels = {};
if (regContentType !== Registry.PROMETHEUS_CONTENT_TYPE && regContentType !== Registry.OPENMETRICS_CONTENT_TYPE) throw new TypeError(`Content type ${regContentType} is unsupported`);
this._contentType = regContentType;
}
getMetricsAsArray() {
return Object.values(this._metrics);
}
async getMetricsAsString(metrics) {
const metric = typeof metrics.getForPromString === "function" ? await metrics.getForPromString() : await metrics.get();
const name = escapeString(metric.name);
const values = [`# HELP ${name} ${escapeString(metric.help)}`, `# TYPE ${name} ${metric.type}`];
const defaultLabels = Object.keys(this._defaultLabels).length > 0 ? this._defaultLabels : null;
const isOpenMetrics = this.contentType === Registry.OPENMETRICS_CONTENT_TYPE;
for (const val of metric.values || []) {
let { metricName = name, labels = {} } = val;
const { sharedLabels = {} } = val;
if (isOpenMetrics && metric.type === "counter") metricName = `${metricName}_total`;
if (defaultLabels) labels = {
...labels,
...defaultLabels,
...labels
};
const formattedLabels = formatLabels(labels, sharedLabels);
const flattenedShared = flattenSharedLabels(sharedLabels);
const labelParts = [...formattedLabels, flattenedShared].filter(Boolean);
const labelsString = labelParts.length ? `{${labelParts.join(",")}}` : "";
let fullMetricLine = `${metricName}${labelsString} ${getValueAsString(val.value)}`;
const { exemplar } = val;
if (exemplar && isOpenMetrics) {
const formattedExemplars = formatLabels(exemplar.labelSet);
fullMetricLine += ` # {${formattedExemplars.join(",")}} ${getValueAsString(exemplar.value)} ${exemplar.timestamp}`;
}
values.push(fullMetricLine);
}
return values.join("\n");
}
async metrics() {
const isOpenMetrics = this.contentType === Registry.OPENMETRICS_CONTENT_TYPE;
const promises = this.getMetricsAsArray().map((metric) => {
if (isOpenMetrics && metric.type === "counter") metric.name = standardizeCounterName(metric.name);
return this.getMetricsAsString(metric);
});
const resolves = await Promise.all(promises);
return isOpenMetrics ? `${resolves.join("\n")}\n# EOF\n` : `${resolves.join("\n\n")}\n`;
}
registerMetric(metric) {
if (this._metrics[metric.name] && this._metrics[metric.name] !== metric) throw new Error(`A metric with the name ${metric.name} has already been registered.`);
this._metrics[metric.name] = metric;
}
clear() {
this._metrics = {};
this._defaultLabels = {};
}
async getMetricsAsJSON() {
const metrics = [];
const defaultLabelNames = Object.keys(this._defaultLabels);
const promises = [];
for (const metric of this.getMetricsAsArray()) promises.push(metric.get());
const resolves = await Promise.all(promises);
for (const item of resolves) {
if (item.values && defaultLabelNames.length > 0) for (const val of item.values) {
val.labels = Object.assign({}, val.labels);
for (const labelName of defaultLabelNames) val.labels[labelName] = val.labels[labelName] || this._defaultLabels[labelName];
}
metrics.push(item);
}
return metrics;
}
removeSingleMetric(name) {
delete this._metrics[name];
}
getSingleMetricAsString(name) {
return this.getMetricsAsString(this._metrics[name]);
}
getSingleMetric(name) {
return this._metrics[name];
}
setDefaultLabels(labels) {
this._defaultLabels = labels;
}
resetMetrics() {
for (const metric in this._metrics) this._metrics[metric].reset();
}
get contentType() {
return this._contentType;
}
setContentType(metricsContentType) {
if (metricsContentType === Registry.OPENMETRICS_CONTENT_TYPE || metricsContentType === Registry.PROMETHEUS_CONTENT_TYPE) this._contentType = metricsContentType;
else throw new Error(`Content type ${metricsContentType} is unsupported`);
}
static merge(registers) {
const regType = registers[0].contentType;
for (const reg of registers) if (reg.contentType !== regType) throw new Error("Registers can only be merged if they have the same content type");
const mergedRegistry = new Registry(regType);
registers.reduce((acc, reg) => acc.concat(reg.getMetricsAsArray()), []).forEach(mergedRegistry.registerMetric, mergedRegistry);
return mergedRegistry;
}
};
function formatLabels(labels, exclude) {
const { hasOwnProperty } = Object.prototype;
const formatted = [];
for (const [name, value] of Object.entries(labels)) if (!exclude || !hasOwnProperty.call(exclude, name)) formatted.push(`${name}="${escapeLabelValue(value)}"`);
return formatted;
}
const sharedLabelCache = /* @__PURE__ */ new WeakMap();
function flattenSharedLabels(labels) {
const cached = sharedLabelCache.get(labels);
if (cached) return cached;
const flattened = formatLabels(labels).join(",");
sharedLabelCache.set(labels, flattened);
return flattened;
}
function escapeLabelValue(str) {
if (typeof str !== "string") return str;
return escapeString(str).replace(/"/g, "\\\"");
}
function escapeString(str) {
return str.replace(/\\/g, "\\\\").replace(/\n/g, "\\n");
}
function standardizeCounterName(name) {
return name.replace(/_total$/, "");
}
module.exports = Registry;
module.exports.globalRegistry = new Registry();
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/validation.js
var require_validation = /* @__PURE__ */ __commonJSMin(((exports) => {
const util$4 = __require("util");
const metricRegexp = /^[a-zA-Z_:][a-zA-Z0-9_:]*$/;
const labelRegexp = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
exports.validateMetricName = function(name) {
return metricRegexp.test(name);
};
exports.validateLabelName = function(names = []) {
return names.every((name) => labelRegexp.test(name));
};
exports.validateLabel = function validateLabel(savedLabels, labels) {
for (const label in labels) if (!savedLabels.includes(label)) throw new Error(`Added label "${label}" is not included in initial labelset: ${util$4.inspect(savedLabels)}`);
};
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/metric.js
var require_metric = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const Registry = require_registry();
const { isObject } = require_util();
const { validateMetricName, validateLabelName } = require_validation();
/**
* @abstract
*/
var Metric = class {
constructor(config, defaults = {}) {
if (!isObject(config)) throw new TypeError("constructor expected a config object");
Object.assign(this, {
labelNames: [],
registers: [Registry.globalRegistry],
aggregator: "sum",
enableExemplars: false
}, defaults, config);
if (!this.registers) this.registers = [Registry.globalRegistry];
if (!this.help) throw new Error("Missing mandatory help parameter");
if (!this.name) throw new Error("Missing mandatory name parameter");
if (!validateMetricName(this.name)) throw new Error("Invalid metric name");
if (!validateLabelName(this.labelNames)) throw new Error("Invalid label name");
if (this.collect && typeof this.collect !== "function") throw new Error("Optional \"collect\" parameter must be a function");
if (this.labelNames) this.sortedLabelNames = [...this.labelNames].sort();
else this.sortedLabelNames = [];
this.reset();
for (const register of this.registers) {
if (this.enableExemplars && register.contentType === Registry.PROMETHEUS_CONTENT_TYPE) throw new TypeError("Exemplars are supported only on OpenMetrics registries");
register.registerMetric(this);
}
}
reset() {}
};
module.exports = { Metric };
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/exemplar.js
var require_exemplar = /* @__PURE__ */ __commonJSMin(((exports, module) => {
/**
* Class representing an OpenMetrics exemplar.
*
* @property {object} labelSet
* @property {number} value
* @property {number} [timestamp]
* */
var Exemplar = class {
constructor(labelSet = {}, value = null) {
this.labelSet = labelSet;
this.value = value;
}
/**
* Validation for the label set format.
* https://github.com/OpenObservability/OpenMetrics/blob/d99b705f611b75fec8f450b05e344e02eea6921d/specification/OpenMetrics.md#exemplars
*
* @param {object} labelSet - Exemplar labels.
* @throws {RangeError}
* @return {void}
*/
validateExemplarLabelSet(labelSet) {
let res = "";
for (const [labelName, labelValue] of Object.entries(labelSet)) res += `${labelName}${labelValue}`;
if (res.length > 128) throw new RangeError("Label set size must be smaller than 128 UTF-8 chars");
}
};
module.exports = Exemplar;
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/counter.js
/**
* Counter metric
*/
var require_counter = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const util$3 = __require("util");
const { hashObject, isObject, getLabels, removeLabels, nowTimestamp } = require_util();
const { validateLabel } = require_validation();
const { Metric } = require_metric();
const Exemplar = require_exemplar();
var Counter = class extends Metric {
constructor(config) {
super(config);
this.type = "counter";
this.defaultLabels = {};
this.defaultValue = 1;
this.defaultExemplarLabelSet = {};
if (config.enableExemplars) {
this.enableExemplars = true;
this.inc = this.incWithExemplar;
} else this.inc = this.incWithoutExemplar;
}
/**
* Increment counter
* @param {object} labels - What label you want to be incremented
* @param {Number} value - Value to increment, if omitted increment with 1
* @returns {object} results - object with information about the inc operation
* @returns {string} results.labelHash - hash representation of the labels
*/
incWithoutExemplar(labels, value) {
let hash = "";
if (isObject(labels)) {
hash = hashObject(labels, this.sortedLabelNames);
validateLabel(this.labelNames, labels);
} else {
value = labels;
labels = {};
}
if (value && !Number.isFinite(value)) throw new TypeError(`Value is not a valid number: ${util$3.format(value)}`);
if (value < 0) throw new Error("It is not possible to decrease a counter");
if (value === null || value === void 0) value = 1;
setValue(this.hashMap, value, labels, hash);
return { labelHash: hash };
}
/**
* Increment counter with exemplar, same as inc but accepts labels for an
* exemplar.
* If no label is provided the current exemplar labels are kept unchanged
* (defaults to empty set).
*
* @param {object} incOpts - Object with options about what metric to increase
* @param {object} incOpts.labels - What label you want to be incremented,
* defaults to null (metric with no labels)
* @param {Number} incOpts.value - Value to increment, defaults to 1
* @param {object} incOpts.exemplarLabels - Key-value labels for the
* exemplar, defaults to empty set {}
* @returns {void}
*/
incWithExemplar({ labels = this.defaultLabels, value = this.defaultValue, exemplarLabels = this.defaultExemplarLabelSet } = {}) {
const res = this.incWithoutExemplar(labels, value);
this.updateExemplar(exemplarLabels, value, res.labelHash);
}
updateExemplar(exemplarLabels, value, hash) {
if (exemplarLabels === this.defaultExemplarLabelSet) return;
if (!isObject(this.hashMap[hash].exemplar)) this.hashMap[hash].exemplar = new Exemplar();
this.hashMap[hash].exemplar.validateExemplarLabelSet(exemplarLabels);
this.hashMap[hash].exemplar.labelSet = exemplarLabels;
this.hashMap[hash].exemplar.value = value ? value : 1;
this.hashMap[hash].exemplar.timestamp = nowTimestamp();
}
/**
* Reset counter
* @returns {void}
*/
reset() {
this.hashMap = {};
if (this.labelNames.length === 0) setValue(this.hashMap, 0);
}
async get() {
if (this.collect) {
const v = this.collect();
if (v instanceof Promise) await v;
}
return {
help: this.help,
name: this.name,
type: this.type,
values: Object.values(this.hashMap),
aggregator: this.aggregator
};
}
labels(...args) {
const labels = getLabels(this.labelNames, args) || {};
return { inc: this.inc.bind(this, labels) };
}
remove(...args) {
const labels = getLabels(this.labelNames, args) || {};
validateLabel(this.labelNames, labels);
return removeLabels.call(this, this.hashMap, labels, this.sortedLabelNames);
}
};
function setValue(hashMap, value, labels = {}, hash = "") {
if (hashMap[hash]) hashMap[hash].value += value;
else hashMap[hash] = {
value,
labels
};
return hashMap;
}
module.exports = Counter;
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/gauge.js
/**
* Gauge metric
*/
var require_gauge = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const util$2 = __require("util");
const { setValue, setValueDelta, getLabels, hashObject, isObject, removeLabels } = require_util();
const { validateLabel } = require_validation();
const { Metric } = require_metric();
var Gauge = class extends Metric {
constructor(config) {
super(config);
this.type = "gauge";
}
/**
* Set a gauge to a value
* @param {object} labels - Object with labels and their values
* @param {Number} value - Value to set the gauge to, must be positive
* @returns {void}
*/
set(labels, value) {
value = getValueArg(labels, value);
labels = getLabelArg(labels);
set(this, labels, value);
}
/**
* Reset gauge
* @returns {void}
*/
reset() {
this.hashMap = {};
if (this.labelNames.length === 0) setValue(this.hashMap, 0, {});
}
/**
* Increment a gauge value
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @param {Number} value - Value to increment - if omitted, increment with 1
* @returns {void}
*/
inc(labels, value) {
value = getValueArg(labels, value);
labels = getLabelArg(labels);
if (value === void 0) value = 1;
setDelta(this, labels, value);
}
/**
* Decrement a gauge value
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @param {Number} value - Value to decrement - if omitted, decrement with 1
* @returns {void}
*/
dec(labels, value) {
value = getValueArg(labels, value);
labels = getLabelArg(labels);
if (value === void 0) value = 1;
setDelta(this, labels, -value);
}
/**
* Set the gauge to current unix epoch
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @returns {void}
*/
setToCurrentTime(labels) {
const now = Date.now() / 1e3;
if (labels === void 0) this.set(now);
else this.set(labels, now);
}
/**
* Start a timer
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @returns {function} - Invoke this function to set the duration in seconds since you started the timer.
* @example
* var done = gauge.startTimer();
* makeXHRRequest(function(err, response) {
* done(); //Duration of the request will be saved
* });
*/
startTimer(labels) {
const start = process.hrtime();
return (endLabels) => {
const delta = process.hrtime(start);
const value = delta[0] + delta[1] / 1e9;
this.set(Object.assign({}, labels, endLabels), value);
return value;
};
}
async get() {
if (this.collect) {
const v = this.collect();
if (v instanceof Promise) await v;
}
return {
help: this.help,
name: this.name,
type: this.type,
values: Object.values(this.hashMap),
aggregator: this.aggregator
};
}
_getValue(labels) {
const hash = hashObject(labels || {}, this.sortedLabelNames);
return this.hashMap[hash] ? this.hashMap[hash].value : 0;
}
labels(...args) {
const labels = getLabels(this.labelNames, args);
validateLabel(this.labelNames, labels);
return {
inc: this.inc.bind(this, labels),
dec: this.dec.bind(this, labels),
set: this.set.bind(this, labels),
setToCurrentTime: this.setToCurrentTime.bind(this, labels),
startTimer: this.startTimer.bind(this, labels)
};
}
remove(...args) {
const labels = getLabels(this.labelNames, args);
validateLabel(this.labelNames, labels);
removeLabels.call(this, this.hashMap, labels, this.sortedLabelNames);
}
};
function set(gauge, labels, value) {
if (typeof value !== "number") throw new TypeError(`Value is not a valid number: ${util$2.format(value)}`);
validateLabel(gauge.labelNames, labels);
setValue(gauge.hashMap, value, labels);
}
function setDelta(gauge, labels, delta) {
if (typeof delta !== "number") throw new TypeError(`Delta is not a valid number: ${util$2.format(delta)}`);
validateLabel(gauge.labelNames, labels);
const hash = hashObject(labels, gauge.sortedLabelNames);
setValueDelta(gauge.hashMap, delta, labels, hash);
}
function getLabelArg(labels) {
return isObject(labels) ? labels : {};
}
function getValueArg(labels, value) {
return isObject(labels) ? value : labels;
}
module.exports = Gauge;
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/histogram.js
/**
* Histogram
*/
var require_histogram = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const util$1 = __require("util");
const { getLabels, hashObject, isObject, removeLabels, nowTimestamp } = require_util();
const { validateLabel } = require_validation();
const { Metric } = require_metric();
const Exemplar = require_exemplar();
var Histogram = class extends Metric {
constructor(config) {
super(config, { buckets: [
.005,
.01,
.025,
.05,
.1,
.25,
.5,
1,
2.5,
5,
10
] });
this.type = "histogram";
this.defaultLabels = {};
this.defaultExemplarLabelSet = {};
this.enableExemplars = false;
for (const label of this.labelNames) if (label === "le") throw new Error("le is a reserved label keyword");
this.upperBounds = this.buckets;
this.bucketValues = this.upperBounds.reduce((acc, upperBound) => {
acc[upperBound] = 0;
return acc;
}, {});
if (config.enableExemplars) {
this.enableExemplars = true;
this.bucketExemplars = this.upperBounds.reduce((acc, upperBound) => {
acc[upperBound] = null;
return acc;
}, {});
Object.freeze(this.bucketExemplars);
this.observe = this.observeWithExemplar;
} else this.observe = this.observeWithoutExemplar;
Object.freeze(this.bucketValues);
Object.freeze(this.upperBounds);
if (this.labelNames.length === 0) this.hashMap = { [hashObject({})]: createBaseValues({}, this.bucketValues, this.bucketExemplars) };
}
/**
* Observe a value in histogram
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @param {Number} value - Value to observe in the histogram
* @returns {void}
*/
observeWithoutExemplar(labels, value) {
observe.call(this, labels === 0 ? 0 : labels || {})(value);
}
observeWithExemplar({ labels = this.defaultLabels, value, exemplarLabels = this.defaultExemplarLabelSet } = {}) {
observe.call(this, labels === 0 ? 0 : labels || {})(value);
this.updateExemplar(labels, value, exemplarLabels);
}
updateExemplar(labels, value, exemplarLabels) {
if (Object.keys(exemplarLabels).length === 0) return;
const hash = hashObject(labels, this.sortedLabelNames);
const bound = findBound(this.upperBounds, value);
const { bucketExemplars } = this.hashMap[hash];
let exemplar = bucketExemplars[bound];
if (!isObject(exemplar)) {
exemplar = new Exemplar();
bucketExemplars[bound] = exemplar;
}
exemplar.validateExemplarLabelSet(exemplarLabels);
exemplar.labelSet = exemplarLabels;
exemplar.value = value;
exemplar.timestamp = nowTimestamp();
}
async get() {
const data = await this.getForPromString();
data.values = data.values.map(splayLabels);
return data;
}
async getForPromString() {
if (this.collect) {
const v = this.collect();
if (v instanceof Promise) await v;
}
const values = Object.values(this.hashMap).map(extractBucketValuesForExport(this)).reduce(addSumAndCountForExport(this), []);
return {
name: this.name,
help: this.help,
type: this.type,
values,
aggregator: this.aggregator
};
}
reset() {
this.hashMap = {};
}
/**
* Initialize the metrics for the given combination of labels to zero
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @returns {void}
*/
zero(labels) {
const hash = hashObject(labels, this.sortedLabelNames);
this.hashMap[hash] = createBaseValues(labels, this.bucketValues, this.bucketExemplars);
}
/**
* Start a timer that could be used to logging durations
* @param {object} labels - Object with labels where key is the label key and value is label value. Can only be one level deep
* @param {object} exemplarLabels - Object with labels for exemplar where key is the label key and value is label value. Can only be one level deep
* @returns {function} - Function to invoke when you want to stop the timer and observe the duration in seconds
* @example
* var end = histogram.startTimer();
* makeExpensiveXHRRequest(function(err, res) {
* const duration = end(); //Observe the duration of expensiveXHRRequest and returns duration in seconds
* console.log('Duration', duration);
* });
*/
startTimer(labels, exemplarLabels) {
return this.enableExemplars ? startTimerWithExemplar.call(this, labels, exemplarLabels)() : startTimer.call(this, labels)();
}
labels(...args) {
const labels = getLabels(this.labelNames, args);
validateLabel(this.labelNames, labels);
return {
observe: observe.call(this, labels),
startTimer: startTimer.call(this, labels)
};
}
remove(...args) {
const labels = getLabels(this.labelNames, args);
validateLabel(this.labelNames, labels);
removeLabels.call(this, this.hashMap, labels, this.sortedLabelNames);
}
};
function startTimer(startLabels) {
return () => {
const start = process.hrtime();
return (endLabels) => {
const delta = process.hrtime(start);
const value = delta[0] + delta[1] / 1e9;
this.observe(Object.assign({}, startLabels, endLabels), value);
return value;
};
};
}
function startTimerWithExemplar(startLabels, startExemplarLabels) {
return () => {
const start = process.hrtime();
return (endLabels, endExemplarLabels) => {
const delta = process.hrtime(start);
const value = delta[0] + delta[1] / 1e9;
this.observe({
labels: Object.assign({}, startLabels, endLabels),
value,
exemplarLabels: Object.assign({}, startExemplarLabels, endExemplarLabels)
});
return value;
};
};
}
function setValuePair(labels, value, metricName, exemplar, sharedLabels = {}) {
return {
labels,
sharedLabels,
value,
metricName,
exemplar
};
}
function findBound(upperBounds, value) {
for (let i = 0; i < upperBounds.length; i++) {
const bound = upperBounds[i];
if (value <= bound) return bound;
}
return -1;
}
function observe(labels) {
return (value) => {
const labelValuePair = convertLabelsAndValues(labels, value);
validateLabel(this.labelNames, labelValuePair.labels);
if (!Number.isFinite(labelValuePair.value)) throw new TypeError(`Value is not a valid number: ${util$1.format(labelValuePair.value)}`);
const hash = hashObject(labelValuePair.labels, this.sortedLabelNames);
let valueFromMap = this.hashMap[hash];
if (!valueFromMap) valueFromMap = createBaseValues(labelValuePair.labels, this.bucketValues, this.bucketExemplars);
const b = findBound(this.upperBounds, labelValuePair.value);
valueFromMap.sum += labelValuePair.value;
valueFromMap.count += 1;
if (Object.prototype.hasOwnProperty.call(valueFromMap.bucketValues, b)) valueFromMap.bucketValues[b] += 1;
this.hashMap[hash] = valueFromMap;
};
}
function createBaseValues(labels, bucketValues, bucketExemplars) {
const result = {
labels,
bucketValues: { ...bucketValues },
sum: 0,
count: 0
};
if (bucketExemplars) result.bucketExemplars = { ...bucketExemplars };
return result;
}
function convertLabelsAndValues(labels, value) {
return isObject(labels) ? {
labels,
value
} : {
value: labels,
labels: {}
};
}
function extractBucketValuesForExport(histogram) {
const name = `${histogram.name}_bucket`;
return (bucketData) => {
let acc = 0;
return {
buckets: histogram.upperBounds.map((upperBound) => {
acc += bucketData.bucketValues[upperBound];
return setValuePair({ le: upperBound }, acc, name, bucketData.bucketExemplars ? bucketData.bucketExemplars[upperBound] : null, bucketData.labels);
}),
data: bucketData
};
};
}
function addSumAndCountForExport(histogram) {
return (acc, d) => {
acc.push(...d.buckets);
acc.push(setValuePair({ le: "+Inf" }, d.data.count, `${histogram.name}_bucket`, d.data.bucketExemplars ? d.data.bucketExemplars["-1"] : null, d.data.labels), setValuePair({}, d.data.sum, `${histogram.name}_sum`, void 0, d.data.labels), setValuePair({}, d.data.count, `${histogram.name}_count`, void 0, d.data.labels));
return acc;
};
}
function splayLabels(bucket) {
const { sharedLabels, labels, ...newBucket } = bucket;
for (const label of Object.keys(sharedLabels)) labels[label] = sharedLabels[label];
newBucket.labels = labels;
return newBucket;
}
module.exports = Histogram;
}));
//#endregion
//#region ../../../../node_modules/bintrees/lib/treebase.js
var require_treebase = /* @__PURE__ */ __commonJSMin(((exports, module) => {
function TreeBase() {}
TreeBase.prototype.clear = function() {
this._root = null;
this.size = 0;
};
TreeBase.prototype.find = function(data) {
var res = this._root;
while (res !== null) {
var c = this._comparator(data, res.data);
if (c === 0) return res.data;
else res = res.get_child(c > 0);
}
return null;
};
TreeBase.prototype.findIter = function(data) {
var res = this._root;
var iter = this.iterator();
while (res !== null) {
var c = this._comparator(data, res.data);
if (c === 0) {
iter._cursor = res;
return iter;
} else {
iter._ancestors.push(res);
res = res.get_child(c > 0);
}
}
return null;
};
TreeBase.prototype.lowerBound = function(item) {
var cur = this._root;
var iter = this.iterator();
var cmp = this._comparator;
while (cur !== null) {
var c = cmp(item, cur.data);
if (c === 0) {
iter._cursor = cur;
return iter;
}
iter._ancestors.push(cur);
cur = cur.get_child(c > 0);
}
for (var i = iter._ancestors.length - 1; i >= 0; --i) {
cur = iter._ancestors[i];
if (cmp(item, cur.data) < 0) {
iter._cursor = cur;
iter._ancestors.length = i;
return iter;
}
}
iter._ancestors.length = 0;
return iter;
};
TreeBase.prototype.upperBound = function(item) {
var iter = this.lowerBound(item);
var cmp = this._comparator;
while (iter.data() !== null && cmp(iter.data(), item) === 0) iter.next();
return iter;
};
TreeBase.prototype.min = function() {
var res = this._root;
if (res === null) return null;
while (res.left !== null) res = res.left;
return res.data;
};
TreeBase.prototype.max = function() {
var res = this._root;
if (res === null) return null;
while (res.right !== null) res = res.right;
return res.data;
};
TreeBase.prototype.iterator = function() {
return new Iterator(this);
};
TreeBase.prototype.each = function(cb) {
var it = this.iterator(), data;
while ((data = it.next()) !== null) if (cb(data) === false) return;
};
TreeBase.prototype.reach = function(cb) {
var it = this.iterator(), data;
while ((data = it.prev()) !== null) if (cb(data) === false) return;
};
function Iterator(tree) {
this._tree = tree;
this._ancestors = [];
this._cursor = null;
}
Iterator.prototype.data = function() {
return this._cursor !== null ? this._cursor.data : null;
};
Iterator.prototype.next = function() {
if (this._cursor === null) {
var root = this._tree._root;
if (root !== null) this._minNode(root);
} else if (this._cursor.right === null) {
var save;
do {
save = this._cursor;
if (this._ancestors.length) this._cursor = this._ancestors.pop();
else {
this._cursor = null;
break;
}
} while (this._cursor.right === save);
} else {
this._ancestors.push(this._cursor);
this._minNode(this._cursor.right);
}
return this._cursor !== null ? this._cursor.data : null;
};
Iterator.prototype.prev = function() {
if (this._cursor === null) {
var root = this._tree._root;
if (root !== null) this._maxNode(root);
} else if (this._cursor.left === null) {
var save;
do {
save = this._cursor;
if (this._ancestors.length) this._cursor = this._ancestors.pop();
else {
this._cursor = null;
break;
}
} while (this._cursor.left === save);
} else {
this._ancestors.push(this._cursor);
this._maxNode(this._cursor.left);
}
return this._cursor !== null ? this._cursor.data : null;
};
Iterator.prototype._minNode = function(start) {
while (start.left !== null) {
this._ancestors.push(start);
start = start.left;
}
this._cursor = start;
};
Iterator.prototype._maxNode = function(start) {
while (start.right !== null) {
this._ancestors.push(start);
start = start.right;
}
this._cursor = start;
};
module.exports = TreeBase;
}));
//#endregion
//#region ../../../../node_modules/bintrees/lib/rbtree.js
var require_rbtree = /* @__PURE__ */ __commonJSMin(((exports, module) => {
var TreeBase = require_treebase();
function Node(data) {
this.data = data;
this.left = null;
this.right = null;
this.red = true;
}
Node.prototype.get_child = function(dir) {
return dir ? this.right : this.left;
};
Node.prototype.set_child = function(dir, val) {
if (dir) this.right = val;
else this.left = val;
};
function RBTree(comparator) {
this._root = null;
this._comparator = comparator;
this.size = 0;
}
RBTree.prototype = new TreeBase();
RBTree.prototype.insert = function(data) {
var ret = false;
if (this._root === null) {
this._root = new Node(data);
ret = true;
this.size++;
} else {
var head = new Node(void 0);
var dir = 0;
var last = 0;
var gp = null;
var ggp = head;
var p = null;
var node = this._root;
ggp.right = this._root;
while (true) {
if (node === null) {
node = new Node(data);
p.set_child(dir, node);
ret = true;
this.size++;
} else if (is_red(node.left) && is_red(node.right)) {
node.red = true;
node.left.red = false;
node.right.red = false;
}
if (is_red(node) && is_red(p)) {
var dir2 = ggp.right === gp;
if (node === p.get_child(last)) ggp.set_child(dir2, single_rotate(gp, !last));
else ggp.set_child(dir2, double_rotate(gp, !last));
}
var cmp = this._comparator(node.data, data);
if (cmp === 0) break;
last = dir;
dir = cmp < 0;
if (gp !== null) ggp = gp;
gp = p;
p = node;
node = node.get_child(dir);
}
this._root = head.right;
}
this._root.red = false;
return ret;
};
RBTree.prototype.remove = function(data) {
if (this._root === null) return false;
var head = new Node(void 0);
var node = head;
node.right = this._root;
var p = null;
var gp = null;
var found = null;
var dir = 1;
while (node.get_child(dir) !== null) {
var last = dir;
gp = p;
p = node;
node = node.get_child(dir);
var cmp = this._comparator(data, node.data);
dir = cmp > 0;
if (cmp === 0) found = node;
if (!is_red(node) && !is_red(node.get_child(dir))) {
if (is_red(node.get_child(!dir))) {
var sr = single_rotate(node, dir);
p.set_child(last, sr);
p = sr;
} else if (!is_red(node.get_child(!dir))) {
var sibling = p.get_child(!last);
if (sibling !== null) if (!is_red(sibling.get_child(!last)) && !is_red(sibling.get_child(last))) {
p.red = false;
sibling.red = true;
node.red = true;
} else {
var dir2 = gp.right === p;
if (is_red(sibling.get_child(last))) gp.set_child(dir2, double_rotate(p, last));
else if (is_red(sibling.get_child(!last))) gp.set_child(dir2, single_rotate(p, last));
var gpc = gp.get_child(dir2);
gpc.red = true;
node.red = true;
gpc.left.red = false;
gpc.right.red = false;
}
}
}
}
if (found !== null) {
found.data = node.data;
p.set_child(p.right === node, node.get_child(node.left === null));
this.size--;
}
this._root = head.right;
if (this._root !== null) this._root.red = false;
return found !== null;
};
function is_red(node) {
return node !== null && node.red;
}
function single_rotate(root, dir) {
var save = root.get_child(!dir);
root.set_child(!dir, save.get_child(dir));
save.set_child(dir, root);
root.red = true;
save.red = false;
return save;
}
function double_rotate(root, dir) {
root.set_child(!dir, single_rotate(root.get_child(!dir), !dir));
return single_rotate(root, dir);
}
module.exports = RBTree;
}));
//#endregion
//#region ../../../../node_modules/bintrees/lib/bintree.js
var require_bintree = /* @__PURE__ */ __commonJSMin(((exports, module) => {
var TreeBase = require_treebase();
function Node(data) {
this.data = data;
this.left = null;
this.right = null;
}
Node.prototype.get_child = function(dir) {
return dir ? this.right : this.left;
};
Node.prototype.set_child = function(dir, val) {
if (dir) this.right = val;
else this.left = val;
};
function BinTree(comparator) {
this._root = null;
this._comparator = comparator;
this.size = 0;
}
BinTree.prototype = new TreeBase();
BinTree.prototype.insert = function(data) {
if (this._root === null) {
this._root = new Node(data);
this.size++;
return true;
}
var dir = 0;
var p = null;
var node = this._root;
while (true) {
if (node === null) {
node = new Node(data);
p.set_child(dir, node);
ret = true;
this.size++;
return true;
}
if (this._comparator(node.data, data) === 0) return false;
dir = this._comparator(node.data, data) < 0;
p = node;
node = node.get_child(dir);
}
};
BinTree.prototype.remove = function(data) {
if (this._root === null) return false;
var head = new Node(void 0);
var node = head;
node.right = this._root;
var p = null;
var found = null;
var dir = 1;
while (node.get_child(dir) !== null) {
p = node;
node = node.get_child(dir);
var cmp = this._comparator(data, node.data);
dir = cmp > 0;
if (cmp === 0) found = node;
}
if (found !== null) {
found.data = node.data;
p.set_child(p.right === node, node.get_child(node.left === null));
this._root = head.right;
this.size--;
return true;
} else return false;
};
module.exports = BinTree;
}));
//#endregion
//#region ../../../../node_modules/bintrees/index.js
var require_bintrees = /* @__PURE__ */ __commonJSMin(((exports, module) => {
module.exports = {
RBTree: require_rbtree(),
BinTree: require_bintree()
};
}));
//#endregion
//#region ../../../../node_modules/tdigest/tdigest.js
var require_tdigest = /* @__PURE__ */ __commonJSMin(((exports, module) => {
var RBTree = require_bintrees().RBTree;
function TDigest(delta, K, CX) {
this.discrete = delta === false;
this.delta = delta || .01;
this.K = K === void 0 ? 25 : K;
this.CX = CX === void 0 ? 1.1 : CX;
this.centroids = new RBTree(compare_centroid_means);
this.nreset = 0;
this.reset();
}
TDigest.prototype.reset = function() {
this.centroids.clear();
this.n = 0;
this.nreset += 1;
this.last_cumulate = 0;
};
TDigest.prototype.size = function() {
return this.centroids.size;
};
TDigest.prototype.toArray = function(everything) {
var result = [];
if (everything) {
this._cumulate(true);
this.centroids.each(function(c) {
result.push(c);
});
} else this.centroids.each(function(c) {
result.push({
mean: c.mean,
n: c.n
});
});
return result;
};
TDigest.prototype.summary = function() {
return [
(this.discrete ? "exact " : "approximating ") + this.n + " samples using " + this.size() + " centroids",
"min = " + this.percentile(0),
"Q1 = " + this.percentile(.25),
"Q2 = " + this.percentile(.5),
"Q3 = " + this.percentile(.75),
"max = " + this.percentile(1)
].join("\n");
};
function compare_centroid_means(a, b) {
return a.mean > b.mean ? 1 : a.mean < b.mean ? -1 : 0;
}
function compare_centroid_mean_cumns(a, b) {
return a.mean_cumn - b.mean_cumn;
}
TDigest.prototype.push = function(x, n) {
n = n || 1;
x = Array.isArray(x) ? x : [x];
for (var i = 0; i < x.length; i++) this._digest(x[i], n);
};
TDigest.prototype.push_centroid = function(c) {
c = Array.isArray(c) ? c : [c];
for (var i = 0; i < c.length; i++) this._digest(c[i].mean, c[i].n);
};
TDigest.prototype._cumulate = function(exact) {
if (this.n === this.last_cumulate || !exact && this.CX && this.CX > this.n / this.last_cumulate) return;
var cumn = 0;
this.centroids.each(function(c) {
c.mean_cumn = cumn + c.n / 2;
cumn = c.cumn = cumn + c.n;
});
this.n = this.last_cumulate = cumn;
};
TDigest.prototype.find_nearest = function(x) {
if (this.size() === 0) return null;
var iter = this.centroids.lowerBound({ mean: x });
var c = iter.data() === null ? iter.prev() : iter.data();
if (c.mean === x || this.discrete) return c;
var prev = iter.prev();
if (prev && Math.abs(prev.mean - x) < Math.abs(c.mean - x)) return prev;
else return c;
};
TDigest.prototype._new_centroid = function(x, n, cumn) {
var c = {
mean: x,
n,
cumn
};
this.centroids.insert(c);
this.n += n;
return c;
};
TDigest.prototype._addweight = function(nearest, x, n) {
if (x !== nearest.mean) nearest.mean += n * (x - nearest.mean) / (nearest.n + n);
nearest.cumn += n;
nearest.mean_cumn += n / 2;
nearest.n += n;
this.n += n;
};
TDigest.prototype._digest = function(x, n) {
var min = this.centroids.min();
var max = this.centroids.max();
var nearest = this.find_nearest(x);
if (nearest && nearest.mean === x) this._addweight(nearest, x, n);
else if (nearest === min) this._new_centroid(x, n, 0);
else if (nearest === max) this._new_centroid(x, n, this.n);
else if (this.discrete) this._new_centroid(x, n, nearest.cumn);
else {
var p = nearest.mean_cumn / this.n;
if (Math.floor(4 * this.n * this.delta * p * (1 - p)) - nearest.n >= n) this._addweight(nearest, x, n);
else this._new_centroid(x, n, nearest.cumn);
}
this._cumulate(false);
if (!this.discrete && this.K && this.size() > this.K / this.delta) this.compress();
};
TDigest.prototype.bound_mean = function(x) {
var iter = this.centroids.upperBound({ mean: x });
var lower = iter.prev();
return [lower, lower.mean === x ? lower : iter.next()];
};
TDigest.prototype.p_rank = function(x_or_xlist) {
var ps = (Array.isArray(x_or_xlist) ? x_or_xlist : [x_or_xlist]).map(this._p_rank, this);
return Array.isArray(x_or_xlist) ? ps : ps[0];
};
TDigest.prototype._p_rank = function(x) {
if (this.size() === 0) return;
else if (x < this.centroids.min().mean) return 0;
else if (x > this.centroids.max().mean) return 1;
this._cumulate(true);
var bound = this.bound_mean(x);
var lower = bound[0], upper = bound[1];
if (this.discrete) return lower.cumn / this.n;
else {
var cumn = lower.mean_cumn;
if (lower !== upper) cumn += (x - lower.mean) * (upper.mean_cumn - lower.mean_cumn) / (upper.mean - lower.mean);
return cumn / this.n;
}
};
TDigest.prototype.bound_mean_cumn = function(cumn) {
this.centroids._comparator = compare_centroid_mean_cumns;
var iter = this.centroids.upperBound({ mean_cumn: cumn });
this.centroids._comparator = compare_centroid_means;
var lower = iter.prev();
return [lower, lower && lower.mean_cumn === cumn ? lower : iter.next()];
};
TDigest.prototype.percentile = function(p_or_plist) {
var qs = (Array.isArray(p_or_plist) ? p_or_plist : [p_or_plist]).map(this._percentile, this);
return Array.isArray(p_or_plist) ? qs : qs[0];
};
TDigest.prototype._percentile = function(p) {
if (this.size() === 0) return;
this._cumulate(true);
var h = this.n * p;
var bound = this.bound_mean_cumn(h);
var lower = bound[0], upper = bound[1];
if (upper === lower || lower === null || upper === null) return (lower || upper).mean;
else if (!this.discrete) return lower.mean + (h - lower.mean_cumn) * (upper.mean - lower.mean) / (upper.mean_cumn - lower.mean_cumn);
else if (h <= lower.cumn) return lower.mean;
else return upper.mean;
};
function pop_random(choices) {
var idx = Math.floor(Math.random() * choices.length);
return choices.splice(idx, 1)[0];
}
TDigest.prototype.compress = function() {
if (this.compressing) return;
var points = this.toArray();
this.reset();
this.compressing = true;
while (points.length > 0) this.push_centroid(pop_random(points));
this._cumulate(true);
this.compressing = false;
};
function Digest(config) {
this.config = config || {};
this.mode = this.config.mode || "auto";
TDigest.call(this, this.mode === "cont" ? config.delta : false);
this.digest_ratio = this.config.ratio || .9;
this.digest_thresh = this.config.thresh || 1e3;
this.n_unique = 0;
}
Digest.prototype = Object.create(TDigest.prototype);
Digest.prototype.constructor = Digest;
Digest.prototype.push = function(x_or_xlist) {
TDigest.prototype.push.call(this, x_or_xlist);
this.check_continuous();
};
Digest.prototype._new_centroid = function(x, n, cumn) {
this.n_unique += 1;
TDigest.prototype._new_centroid.call(this, x, n, cumn);
};
Digest.prototype._addweight = function(nearest, x, n) {
if (nearest.n === 1) this.n_unique -= 1;
TDigest.prototype._addweight.call(this, nearest, x, n);
};
Digest.prototype.check_continuous = function() {
if (this.mode !== "auto" || this.size() < this.digest_thresh) return false;
if (this.n_unique / this.size() > this.digest_ratio) {
this.mode = "cont";
this.discrete = false;
this.delta = this.config.delta || .01;
this.compress();
return true;
}
return false;
};
module.exports = {
"TDigest": TDigest,
"Digest": Digest
};
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/timeWindowQuantiles.js
var require_timeWindowQuantiles = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const { TDigest } = require_tdigest();
var TimeWindowQuantiles = class {
constructor(maxAgeSeconds, ageBuckets) {
this.maxAgeSeconds = maxAgeSeconds || 0;
this.ageBuckets = ageBuckets || 0;
this.shouldRotate = maxAgeSeconds && ageBuckets;
this.ringBuffer = Array(ageBuckets).fill(new TDigest());
this.currentBuffer = 0;
this.lastRotateTimestampMillis = Date.now();
this.durationBetweenRotatesMillis = maxAgeSeconds * 1e3 / ageBuckets || Infinity;
}
size() {
return rotate.call(this).size();
}
percentile(quantile) {
return rotate.call(this).percentile(quantile);
}
push(value) {
rotate.call(this);
this.ringBuffer.forEach((bucket) => {
bucket.push(value);
});
}
reset() {
this.ringBuffer.forEach((bucket) => {
bucket.reset();
});
}
compress() {
this.ringBuffer.forEach((bucket) => {
bucket.compress();
});
}
};
function rotate() {
let timeSinceLastRotateMillis = Date.now() - this.lastRotateTimestampMillis;
while (timeSinceLastRotateMillis > this.durationBetweenRotatesMillis && this.shouldRotate) {
this.ringBuffer[this.currentBuffer] = new TDigest();
if (++this.currentBuffer >= this.ringBuffer.length) this.currentBuffer = 0;
timeSinceLastRotateMillis -= this.durationBetweenRotatesMillis;
this.lastRotateTimestampMillis += this.durationBetweenRotatesMillis;
}
return this.ringBuffer[this.currentBuffer];
}
module.exports = TimeWindowQuantiles;
}));
//#endregion
//#region ../../../../node_modules/prom-client/lib/summary.js
/**
* Summary
*/
var require_summary = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const util = __require("util");
const { getLabels, hashObject, removeLabels } = require_util();
const { validateLabel } = require_validation();
const { Metric } = require_metric();
const timeWindowQuantiles = require_timeWindowQuantiles();
const DEFAULT_COMPRESS_COUNT = 1e3;
var Summary = class extends Metric {
constructor(config) {
super(config, {
percentiles: [
.01,
.05,
.5,
.9,
.95,
.99,
.999
],
compressCount: DEFAULT_COMPRESS_COUNT,
hashMap: {}
});
this.type = "summary";
for (const label of this.labelNames) if (label === "quantile") throw new Error("quantile is a reserved label keyword");
if (this.labelNames.length === 0) this.hashMap = { [hashObject({})]: {
labels: {},
td: new timeWindowQuantiles(this.maxAgeSeconds, this.ageBuckets),
count: 0,
sum: 0
} };
}
/**
* Observe a value