"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Profiler = void 0;
const tslib_1 = require("tslib");
const node_perf_hooks_1 = require("node:perf_hooks");
const crypto_1 = tslib_1.__importDefault(require("crypto"));
const defaultMeta = { datadog: true };
class Profiler {
    marks;
    at;
    detail;
    logger;
    constructor({ logger, at, logLevel, ...detail }) {
        this.marks = new Map();
        this.logger = logger;
        this.at = at;
        this.detail = detail;
    }
    warn(data) {
        this.logger.warn({
            at: this.at,
            ...data,
        });
    }
    logMeasure(data) {
        this.logger.debug({
            at: this.at,
            ...defaultMeta,
            ...data,
        });
    }
    start(task, detail) {
        const start = crypto_1.default.randomUUID();
        const startTime = this.mark(start, detail);
        return {
            startTime,
            stop: (_detail) => this.measure(task, { from: start, ...(detail ?? {}), ...(_detail ?? {}) }),
        };
    }
    mark(label, detail) {
        const currentTime = node_perf_hooks_1.performance.now();
        this.detail = { ...(this.detail ?? {}), ...(detail ?? {}) };
        this.marks.set(label, { time: currentTime, detail });
        return currentTime;
    }
    measure(task, params) {
        const { from, to, ...detail } = params;
        const startMark = this.marks.get(from);
        const endMark = to ? this.marks.get(to) : undefined;
        if (!startMark) {
            this.warn({
                message: `Cannot find start mark for label "${from}".`,
                ...this.detail,
            });
            return;
        }
        const endTime = endMark?.time ?? node_perf_hooks_1.performance.now();
        const duration = endTime - startMark.time;
        const { message, ...combinedDetail } = { ...(this.detail ?? {}), ...(detail ?? {}) };
        const defaultMessage = `Profiler Log: ${task}`;
        this.logMeasure({
            task,
            duration,
            message: message ?? defaultMessage,
            data: combinedDetail,
        });
        return duration;
    }
    async measureAsync(pr, task, detail) {
        const startTime = node_perf_hooks_1.performance.now();
        try {
            const result = await pr;
            return result;
        }
        finally {
            const endTime = node_perf_hooks_1.performance.now();
            const duration = endTime - startTime;
            const { message, ...combinedDetail } = { ...detail };
            const defaultMessage = `Profiler Log: ${task}`;
            this.logMeasure({
                task,
                duration,
                message: message ?? defaultMessage,
                data: combinedDetail,
            });
        }
    }
    measureSync(fn, task, detail) {
        const startTime = node_perf_hooks_1.performance.now();
        try {
            const result = fn();
            return result;
        }
        finally {
            const endTime = node_perf_hooks_1.performance.now();
            const duration = endTime - startTime;
            const { message, ...combinedDetail } = { ...detail };
            const defaultMessage = `Profiler Log: ${task}`;
            this.logMeasure({
                task,
                duration,
                message: message ?? defaultMessage,
                data: combinedDetail,
            });
        }
    }
}
exports.Profiler = Profiler;
//# sourceMappingURL=Profiler.js.map