export class Diagnostics {
    maxHistory;
    metrics = new Map();
    activeTimers = new Map();
    constructor(maxHistory = 120) {
        this.maxHistory = maxHistory;
    }
    increment(name, amount = 1) {
        const metric = this.ensure(name, "counter");
        metric.value += amount;
        this.recordSample(metric, metric.value);
    }
    gauge(name, value) {
        const metric = this.ensure(name, "gauge");
        metric.value = value;
        this.recordSample(metric, value);
    }
    begin(name) {
        if (this.activeTimers.has(name))
            throw new Error(`Timer ${name} already started.`);
        this.activeTimers.set(name, performance.now());
    }
    end(name) {
        const start = this.activeTimers.get(name);
        if (start === undefined)
            throw new Error(`Timer ${name} was not started.`);
        this.activeTimers.delete(name);
        const duration = performance.now() - start;
        const metric = this.ensure(name, "timing");
        metric.value = duration;
        this.recordSample(metric, duration);
        return duration;
    }
    snapshot() {
        const metrics = [...this.metrics.entries()].map(([name, metric]) => Object.freeze({
            kind: metric.kind,
            name,
            value: metric.value,
            samples: Object.freeze([...metric.samples])
        }));
        return Object.freeze({ metrics: Object.freeze(metrics), timestamp: Date.now() });
    }
    ensure(name, kind) {
        const existing = this.metrics.get(name);
        if (existing) {
            if (existing.kind !== kind)
                throw new Error(`Metric ${name} already exists as ${existing.kind}.`);
            return existing;
        }
        const metric = { kind, value: 0, samples: [] };
        this.metrics.set(name, metric);
        return metric;
    }
    recordSample(metric, value) {
        metric.samples.push(value);
        if (metric.samples.length > this.maxHistory)
            metric.samples.shift();
    }
}
//# sourceMappingURL=Diagnostics.js.map