"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const promBundle = require("express-prom-bundle");
const Prom = require("prom-client");
const settings_1 = require("./settings");
var AGGREGATOR;
(function (AGGREGATOR) {
    AGGREGATOR[AGGREGATOR["MIN"] = 1] = "MIN";
    AGGREGATOR[AGGREGATOR["AVERAGE"] = 2] = "AVERAGE";
    AGGREGATOR[AGGREGATOR["MAX"] = 4] = "MAX";
})(AGGREGATOR = exports.AGGREGATOR || (exports.AGGREGATOR = {}));
class Max {
    constructor() {
        this.max = Number.MIN_VALUE;
    }
    set(value) {
        if (value > this.max) {
            this.max = value;
        }
    }
    get() {
        if (this.max != Number.MIN_VALUE)
            return this.max;
        return 0;
    }
    reset() {
        this.max = Number.MIN_VALUE;
    }
    type() {
        return "max";
    }
}
class Avg {
    constructor() {
        this.sum = 0;
        this.count = 0;
    }
    set(value) {
        this.sum += value;
        this.count++;
    }
    get() {
        return this.count == 0 ? 0 : (this.sum / this.count);
    }
    reset() {
        this.sum = 0;
        this.count = 0;
    }
    type() {
        return "avg";
    }
}
class Min {
    constructor() {
        this.min = Number.MAX_VALUE;
    }
    set(value) {
        if (this.min > value) {
            this.min = value;
        }
    }
    get() {
        if (this.min != Number.MAX_VALUE)
            return this.min;
        return 0;
    }
    reset() {
        this.min = Number.MAX_VALUE;
    }
    type() {
        return "min";
    }
}
class GaugeWraper extends Prom.Gauge {
    constructor(name, help, labels, aggregator) {
        let aggr = [];
        let label = labels != undefined ? labels : [];
        if (aggregator != undefined && aggregator > 0) {
            if (aggregator & AGGREGATOR.MAX) {
                aggr.push(new Max());
            }
            if (aggregator & AGGREGATOR.AVERAGE) {
                aggr.push(new Avg());
            }
            if (aggregator & AGGREGATOR.MIN) {
                aggr.push(new Min());
            }
            label.push("aggregator");
        }
        super({
            name: name,
            help: help,
            labelNames: label
        });
        this.aggregators = aggr;
    }
    set(labels, value, timestamp) {
        let _labels = value != undefined ? labels : {};
        let _value = value != undefined ? value : labels;
        if (value == undefined) {
            super.set(_value, timestamp);
        }
        else {
            super.set(JSON.parse(JSON.stringify(labels)), _value, timestamp);
        }
        this.aggregators.forEach(aggregator => {
            aggregator.set(_value);
            _labels["aggregator"] = aggregator.type();
            super.set(JSON.parse(JSON.stringify(_labels)), aggregator.get());
        });
    }
    reset() {
        super.reset();
        if (this.aggregators != null) {
            this.aggregators.forEach(aggregator => {
                aggregator.reset();
            });
        }
    }
}
class Registry {
    constructor(token) {
        this.counters = {};
        this.gauges = {};
        this.histograms = {};
        this.options = settings_1.default.Instance.getMetrics(token);
        let name = this.options != undefined ? this.options.name : undefined;
        if (name == undefined || name == "global") {
            this.registy = promBundle.promClient.register;
        }
        else {
            this.registy = new promBundle.promClient.Registry();
        }
    }
    counter(name) {
        return this.counters[name];
    }
    gauge(name) {
        return this.gauges[name];
    }
    histogram(name) {
        return this.histograms[name];
    }
    newCounter(name, help, labels) {
        let counter = this.counters[name];
        if (counter != null) {
            this.registy.removeSingleMetric(name);
        }
        counter = new promBundle.promClient.Counter({
            name: name,
            help: help,
            labelNames: labels
        });
        this.counters[name] = counter;
        this.registy.registerMetric(counter);
        return counter;
    }
    newGauge(name, help, labels, aggregator) {
        let gauge = this.gauges[name];
        if (gauge != null) {
            this.registy.removeSingleMetric(name);
        }
        gauge = new GaugeWraper(name, help, labels, aggregator);
        this.gauges[name] = gauge;
        this.registy.registerMetric(gauge);
        return gauge;
    }
    newHistogram(name, help, labels, buckets) {
        let histogram = this.histograms[name];
        if (histogram != null) {
            this.registy.removeSingleMetric(name);
        }
        var settings = {
            name: name,
            help: help,
            labelNames: labels ? labels : []
        };
        if (buckets != null) {
            settings.buckets = buckets;
        }
        histogram = new Prom.Histogram(settings);
        this.histograms[name] = histogram;
        this.registy.registerMetric(histogram);
        return histogram;
    }
    deleteCounter(name) {
        if (this.counters[name] != null) {
            this.registy.removeSingleMetric(name);
            delete this.counters[name];
        }
    }
    deleteGauge(name) {
        if (this.gauges[name] != null) {
            this.registy.removeSingleMetric(name);
            delete this.gauges[name];
        }
    }
    deleteHistogram(name) {
        if (this.histograms[name] != null) {
            this.registy.removeSingleMetric(name);
            delete this.histograms[name];
        }
    }
    getRegistry() {
        return this.registy;
    }
    destroy() {
        this.registy.clear();
        this.counters = {};
        this.gauges = {};
        this.histograms = {};
    }
    getStatus() {
        return "";
    }
    isFunctional() {
        return true;
    }
    /**
     * Get string representation for all metrics
     */
    metrics(opts) {
        return this.registy.metrics(opts);
    }
    /**
     * Reset all metrics in the registry
     */
    resetMetrics() {
        this.registy.resetMetrics();
    }
    /**
     * Get all metrics as objects
     */
    getMetricsAsJSON() {
        return this.registy.getMetricsAsJSON();
    }
    /**
     * Set static labels to every metric emitted by this registry
     * @param labels of name/value pairs:
     * { defaultLabel: "value", anotherLabel: "value 2" }
     */
    setDefaultLabels(labels) {
        this.registy.setDefaultLabels(labels);
    }
    get contentType() {
        return this.registy.contentType;
    }
}
Registry.AGGREGATOR = AGGREGATOR;
exports.default = Registry;
//# sourceMappingURL=metrics.js.map