Current File : //lib/node_modules/pm2/node_modules/@pm2/io/build/main/src/features/metrics.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const meter_1 = require("../utils/metrics/meter");
const counter_1 = require("../utils/metrics/counter");
const histogram_1 = require("../utils/metrics/histogram");
const serviceManager_1 = require("../serviceManager");
const constants_1 = require("../constants");
const metrics_1 = require("../services/metrics");
class MetricsFeature {
    constructor() {
        this._var = new Map();
        this.defaultAggregation = 'avg';
        this._started = false;
        this._alreadySentData = [];
        this.AVAILABLE_MEASUREMENTS = [
            'min',
            'max',
            'sum',
            'count',
            'variance',
            'mean',
            'stddev',
            'median',
            'p75',
            'p95',
            'p99',
            'p999'
        ];
        this._var = serviceManager_1.ServiceManager.get('metricsMap');
        serviceManager_1.ServiceManager.set('metricService', new metrics_1.default(this));
        this.metricService = serviceManager_1.ServiceManager.get('metricService');
    }
    init(config, force) {
        if (this._started === false) {
            this._started = true;
            const self = this;
            this.timer = setInterval(function () {
                const data = self._cookData(self._getVar());
                // don't send empty data
                if (Object.keys(data).length !== 0 && serviceManager_1.ServiceManager.get('transport')) {
                    serviceManager_1.ServiceManager.get('transport').setMetrics(data);
                }
            }, constants_1.default.METRIC_INTERVAL);
            this.timer.unref();
        }
        this.metricService.init(config, force);
        return {
            histogram: this.histogram,
            meter: this.meter,
            counter: this.counter,
            metric: this.metric
        };
    }
    transpose(variableName, reporter) {
        if (typeof variableName === 'object') {
            reporter = variableName.data;
            variableName = variableName.name;
        }
        if (typeof reporter !== 'function') {
            console.error('[PM2 IO][Transpose] reporter is not a function');
            return undefined;
        }
        this._var.set(variableName, {
            value: reporter
        });
    }
    meter(opts) {
        if (!opts.name) {
            console.error('[PM2 IO][Meter] Name not defined');
            return undefined;
        }
        opts.unit = opts.unit || '';
        const meter = new meter_1.default(opts);
        this._var.set(opts.name, {
            value: function () {
                return meter.val() + `${opts.unit}`;
            },
            type: opts.type || opts.name,
            historic: this._historicEnabled(opts.historic),
            agg_type: opts.agg_type || this.defaultAggregation,
            unit: opts.unit
        });
        return meter;
    }
    counter(opts) {
        if (!opts.name) {
            console.error('[PM2 IO][Counter] Name not defined');
            return undefined;
        }
        const counter = new counter_1.default(opts);
        this._var.set(opts.name, {
            value: function () { return counter.val(); },
            type: opts.type || opts.name,
            historic: this._historicEnabled(opts.historic),
            agg_type: opts.agg_type || this.defaultAggregation,
            unit: opts.unit
        });
        return counter;
    }
    histogram(opts) {
        if (!opts.name) {
            console.error('[PM2 IO][Histogram] Name not defined');
            return undefined;
        }
        opts.measurement = opts.measurement || 'mean';
        opts.unit = opts.unit || '';
        if (this.AVAILABLE_MEASUREMENTS.indexOf(opts.measurement) === -1) {
            console.error('[PM2 IO][Histogram] Measure type %s does not exists', opts.measurement);
            return undefined;
        }
        const histogram = new histogram_1.default(opts);
        this._var.set(opts.name, {
            value: function () {
                return (Math.round(histogram.val() * 100) / 100) + `${opts.unit}`;
            },
            type: opts.type || opts.name,
            historic: this._historicEnabled(opts.historic),
            agg_type: opts.agg_type || this.defaultAggregation,
            unit: opts.unit
        });
        return histogram;
    }
    metric(opts) {
        if (!opts.name) {
            console.error('[PM2 IO][Metric] Name not defined');
            return undefined;
        }
        this._var.set(opts.name, {
            value: opts.value || 0,
            type: opts.type || opts.name,
            historic: this._historicEnabled(opts.historic),
            agg_type: opts.agg_type || this.defaultAggregation,
            unit: opts.unit
        });
        const self = this;
        return {
            val: function () {
                let value = self._var.get(opts.name).value;
                if (typeof (value) === 'function') {
                    value = value();
                }
                return value;
            },
            set: function (dt) {
                if (self._var.get(opts.name))
                    self._var.get(opts.name).value = dt;
            }
        };
    }
    deleteMetric(name) {
        this._var.delete(name);
        this._alreadySentData.splice(this._alreadySentData.indexOf(name), 1);
    }
    destroy() {
        clearInterval(this.timer);
        this._getVar().clear();
        this._started = false;
        this.metricService.destroyAll();
    }
    /** -----------------------------------------
     * Private Methods
     * ------------------------------------------
     */
    /**
     * Check if metric is historic or not
     *
     * @param historic
     * @returns {boolean}
     * @private
     */
    _historicEnabled(historic) {
        if (historic === false) {
            return false;
        }
        if (typeof (historic) === 'undefined') {
            return true;
        }
        return true;
    }
    /**
     * Only for tests
     *
     * @returns {Object}
     */
    _getVar() {
        return this._var;
    }
    /**
     * Data that will be sent to Keymetrics
     */
    _cookData(data) {
        const cookedData = {};
        const self = this;
        data.forEach(function (probe, probeName) {
            if (typeof (data.get(probeName).value) === 'undefined') {
                return false;
            }
            const value = self._getValue(data.get(probeName).value);
            // do not send data if this is always equal to 0
            // probably an initialized metric which is not "active"
            if ((self._alreadySentData.indexOf(probeName) === -1 && value !== 0) ||
                self._alreadySentData.indexOf(probeName) > -1) {
                if (self._alreadySentData.indexOf(probeName) === -1) {
                    self._alreadySentData.push(probeName);
                }
                cookedData[probeName] = {
                    value: value
                };
                /**
                 * Attach aggregation mode
                 */
                if (data.get(probeName).agg_type &&
                    data.get(probeName).agg_type !== 'none') {
                    cookedData[probeName].agg_type = data.get(probeName).agg_type;
                }
                cookedData[probeName].historic = data.get(probeName).historic;
                cookedData[probeName].type = data.get(probeName).type;
                cookedData[probeName].unit = data.get(probeName).unit;
            }
        });
        return cookedData;
    }
    _getValue(value) {
        if (typeof (value) === 'function') {
            return value();
        }
        return value;
    }
}
exports.default = MetricsFeature;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9mZWF0dXJlcy9tZXRyaWNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0Esa0RBQTBDO0FBQzFDLHNEQUE4QztBQUM5QywwREFBa0Q7QUFDbEQsc0RBQWtEO0FBQ2xELDRDQUFvQztBQUNwQyxpREFBZ0Q7QUFFaEQ7SUF1QkU7UUF0QlEsU0FBSSxHQUFxQixJQUFJLEdBQUcsRUFBRSxDQUFBO1FBQ2xDLHVCQUFrQixHQUFXLEtBQUssQ0FBQTtRQUNsQyxhQUFRLEdBQVksS0FBSyxDQUFBO1FBQ3pCLHFCQUFnQixHQUFrQixFQUFFLENBQUE7UUFJcEMsMkJBQXNCLEdBQWtCO1lBQzlDLEtBQUs7WUFDTCxLQUFLO1lBQ0wsS0FBSztZQUNMLE9BQU87WUFDUCxVQUFVO1lBQ1YsTUFBTTtZQUNOLFFBQVE7WUFDUixRQUFRO1lBQ1IsS0FBSztZQUNMLEtBQUs7WUFDTCxLQUFLO1lBQ0wsTUFBTTtTQUNQLENBQUE7UUFHQyxJQUFJLENBQUMsSUFBSSxHQUFHLCtCQUFjLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFBO1FBQzVDLCtCQUFjLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxJQUFJLGlCQUFjLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUM3RCxJQUFJLENBQUMsYUFBYSxHQUFHLCtCQUFjLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0lBQzFELENBQUM7SUFFRCxJQUFJLENBQUUsTUFBTyxFQUFFLEtBQU07UUFDbkIsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLEtBQUssRUFBRTtZQUMzQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQTtZQUNwQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUE7WUFFakIsSUFBSSxDQUFDLEtBQUssR0FBRyxXQUFXLENBQUM7Z0JBQ3ZCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7Z0JBRTNDLHdCQUF3QjtnQkFDeEIsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksK0JBQWMsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQ3JFLCtCQUFjLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQTtpQkFDakQ7WUFDSCxDQUFDLEVBQUUsbUJBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQTtZQUU3QixJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFBO1NBQ25CO1FBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBRXRDLE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1lBQ2pCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTztZQUNyQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQTtJQUNILENBQUM7SUFFRCxTQUFTLENBQUUsWUFBWSxFQUFFLFFBQVM7UUFDaEMsSUFBSSxPQUFPLFlBQVksS0FBSyxRQUFRLEVBQUU7WUFDcEMsUUFBUSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUE7WUFDNUIsWUFBWSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUE7U0FDakM7UUFFRCxJQUFJLE9BQU8sUUFBUSxLQUFLLFVBQVUsRUFBRTtZQUNsQyxPQUFPLENBQUMsS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUE7WUFDL0QsT0FBTyxTQUFTLENBQUE7U0FDakI7UUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUU7WUFDMUIsS0FBSyxFQUFFLFFBQVE7U0FDaEIsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBRSxJQUFTO1FBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxDQUFDLENBQUE7WUFDakQsT0FBTyxTQUFTLENBQUE7U0FDakI7UUFFRCxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFBO1FBRTNCLE1BQU0sS0FBSyxHQUFHLElBQUksZUFBSyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRTdCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDdkIsS0FBSyxFQUFFO2dCQUNMLE9BQU8sS0FBSyxDQUFDLEdBQUcsRUFBRSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFBO1lBQ3JDLENBQUM7WUFDRCxJQUFJLEVBQU0sSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSTtZQUNoQyxRQUFRLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDOUMsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLGtCQUFrQjtZQUNsRCxJQUFJLEVBQUcsSUFBSSxDQUFDLElBQUk7U0FDakIsQ0FBQyxDQUFBO1FBRUYsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO0lBRUQsT0FBTyxDQUFFLElBQVU7UUFDakIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDZCxPQUFPLENBQUMsS0FBSyxDQUFDLG9DQUFvQyxDQUFDLENBQUE7WUFDbkQsT0FBTyxTQUFTLENBQUE7U0FDakI7UUFFRCxNQUFNLE9BQU8sR0FBRyxJQUFJLGlCQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFakMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUN2QixLQUFLLEVBQUUsY0FBYyxPQUFPLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQSxDQUFDLENBQUM7WUFDM0MsSUFBSSxFQUFNLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUk7WUFDaEMsUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQzlDLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxrQkFBa0I7WUFDbEQsSUFBSSxFQUFHLElBQUksQ0FBQyxJQUFJO1NBQ2pCLENBQUMsQ0FBQTtRQUVGLE9BQU8sT0FBTyxDQUFBO0lBQ2hCLENBQUM7SUFFRCxTQUFTLENBQUUsSUFBVTtRQUNuQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUNkLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0NBQXNDLENBQUMsQ0FBQTtZQUNyRCxPQUFPLFNBQVMsQ0FBQTtTQUNqQjtRQUVELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsSUFBSSxNQUFNLENBQUE7UUFDN0MsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQTtRQUUzQixJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ2hFLE9BQU8sQ0FBQyxLQUFLLENBQUMscURBQXFELEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBQ3RGLE9BQU8sU0FBUyxDQUFBO1NBQ2pCO1FBRUQsTUFBTSxTQUFTLEdBQUcsSUFBSSxtQkFBUyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRXJDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDdkIsS0FBSyxFQUFFO2dCQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQTtZQUNuRSxDQUFDO1lBQ0QsSUFBSSxFQUFNLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUk7WUFDaEMsUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO1lBQzlDLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxrQkFBa0I7WUFDbEQsSUFBSSxFQUFHLElBQUksQ0FBQyxJQUFJO1NBQ2pCLENBQUMsQ0FBQTtRQUVGLE9BQU8sU0FBUyxDQUFBO0lBQ2xCLENBQUM7SUFFRCxNQUFNLENBQUUsSUFBSTtRQUNWLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQ2QsT0FBTyxDQUFDLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFBO1lBQ2xELE9BQU8sU0FBUyxDQUFBO1NBQ2pCO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUN2QixLQUFLLEVBQUssSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDO1lBQ3pCLElBQUksRUFBTSxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJO1lBQ2hDLFFBQVEsRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztZQUM5QyxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsa0JBQWtCO1lBQ2xELElBQUksRUFBRyxJQUFJLENBQUMsSUFBSTtTQUNqQixDQUFDLENBQUE7UUFFRixNQUFNLElBQUksR0FBRyxJQUFJLENBQUE7UUFFakIsT0FBTztZQUNMLEdBQUcsRUFBRztnQkFDSixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFBO2dCQUUxQyxJQUFJLE9BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxVQUFVLEVBQUU7b0JBQ2hDLEtBQUssR0FBRyxLQUFLLEVBQUUsQ0FBQTtpQkFDaEI7Z0JBRUQsT0FBTyxLQUFLLENBQUE7WUFDZCxDQUFDO1lBQ0QsR0FBRyxFQUFHLFVBQVUsRUFBRTtnQkFDaEIsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO29CQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFBO1lBQ25FLENBQUM7U0FDRixDQUFBO0lBQ0gsQ0FBQztJQUVELFlBQVksQ0FBRSxJQUFZO1FBQ3hCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3RCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUN0RSxDQUFDO0lBRUQsT0FBTztRQUNMLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDekIsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFBO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFBO1FBRXJCLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxFQUFFLENBQUE7SUFDakMsQ0FBQztJQUNEOzs7T0FHRztJQUVIOzs7Ozs7T0FNRztJQUNILGdCQUFnQixDQUFFLFFBQVE7UUFDeEIsSUFBSSxRQUFRLEtBQUssS0FBSyxFQUFFO1lBQ3RCLE9BQU8sS0FBSyxDQUFBO1NBQ2I7UUFDRCxJQUFJLE9BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxXQUFXLEVBQUU7WUFDcEMsT0FBTyxJQUFJLENBQUE7U0FDWjtRQUNELE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFBO0lBQ2xCLENBQUM7SUFFRDs7T0FFRztJQUNILFNBQVMsQ0FBRSxJQUFJO1FBQ2IsTUFBTSxVQUFVLEdBQUcsRUFBRSxDQUFBO1FBQ3JCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQTtRQUVqQixJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsS0FBSyxFQUFFLFNBQVM7WUFFckMsSUFBSSxPQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxXQUFXLEVBQUU7Z0JBQ3JELE9BQU8sS0FBSyxDQUFBO2FBQ2I7WUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUE7WUFFdkQsZ0RBQWdEO1lBQ2hELHVEQUF1RDtZQUN2RCxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDO2dCQUNsRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFO2dCQUMvQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUU7b0JBQ25ELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7aUJBQ3RDO2dCQUVELFVBQVUsQ0FBQyxTQUFTLENBQUMsR0FBRztvQkFDdEIsS0FBSyxFQUFFLEtBQUs7aUJBQ2IsQ0FBQTtnQkFFRDs7bUJBRUc7Z0JBQ0gsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVE7b0JBQzlCLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsUUFBUSxLQUFLLE1BQU0sRUFBRTtvQkFDekMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtpQkFDOUQ7Z0JBRUQsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLFFBQVEsQ0FBQTtnQkFDN0QsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQTtnQkFFckQsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQTthQUN0RDtRQUNILENBQUMsQ0FBQyxDQUFBO1FBQ0YsT0FBTyxVQUFVLENBQUE7SUFDbkIsQ0FBQztJQUVELFNBQVMsQ0FBRSxLQUFLO1FBQ2QsSUFBSSxPQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssVUFBVSxFQUFFO1lBQ2hDLE9BQU8sS0FBSyxFQUFFLENBQUE7U0FDZjtRQUNELE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQztDQUNGO0FBNVFELGlDQTRRQyJ9