"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const worker_threads_1 = require("worker_threads");
const http_1 = require("http");
const prom_client_1 = require("prom-client");
const logging_1 = __importDefault(require("../logging"));
const METRICS_DUMP_TIMEOUT_MS = 20000;
function writeLog(level, msg) {
    return worker_threads_1.parentPort === null || worker_threads_1.parentPort === void 0 ? void 0 : worker_threads_1.parentPort.postMessage(`log:${level}:${msg}`);
}
function workerThread() {
    let lastDumpTs = Date.now();
    const registry = new prom_client_1.Registry();
    const intervalCounter = new prom_client_1.Gauge({
        name: "metrics_worker_interval",
        help: "Interval time for metrics being reported to the metrics worker process",
        registers: [registry]
    });
    if (!worker_threads_1.parentPort) {
        throw Error("Missing parentPort");
    }
    http_1.createServer((req, res) => {
        res.setHeader("Content-Type", "text/plain");
        if (!req.url || req.url !== "/metrics" || req.method !== "GET") {
            res.statusCode = 404;
            res.write('Path or method not known');
            res.end();
            return;
        }
        writeLog("debug", "Request for /metrics");
        const timeout = setTimeout(() => {
            intervalCounter.inc(METRICS_DUMP_TIMEOUT_MS);
            res.statusCode = 200;
            res.write(`${registry.metrics()}`);
            res.end();
        }, METRICS_DUMP_TIMEOUT_MS);
        // We've checked for the existence of parentPort above.
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        worker_threads_1.parentPort.once("message", (msg) => {
            clearTimeout(timeout);
            const time = Date.now();
            intervalCounter.set(time - lastDumpTs);
            lastDumpTs = time;
            const dump = msg.substr('metricsdump:'.length);
            res.statusCode = 200;
            res.write(`${dump}\n${registry.metrics()}`);
            res.end();
        });
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        worker_threads_1.parentPort.postMessage("metricsdump");
    }).listen(worker_threads_1.workerData.port, worker_threads_1.workerData.hostname, 1);
}
function spawnMetricsWorker(port, hostname = "127.0.0.1", onMetricsRequested) {
    const worker = new worker_threads_1.Worker(__filename, { workerData: { port, hostname } });
    const workerLogger = logging_1.default("MetricsWorker");
    worker.on("message", (msg) => {
        if (msg === "metricsdump") {
            worker.postMessage("metricsdump:" + onMetricsRequested());
        }
        else if (msg.startsWith("log")) {
            const [, logLevel, logMsg] = msg.split(":");
            workerLogger.log(logLevel, logMsg, { loggerName: "MetricsWorker" });
        }
    });
    return worker;
}
exports.spawnMetricsWorker = spawnMetricsWorker;
if (!worker_threads_1.isMainThread) {
    workerThread();
}
//# sourceMappingURL=MetricsWorker.js.map