Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { type Incident } from "./monitor_incidents_types.ts";
import { roundDiv } from "./math_round_div.ts"; ← from math.round-div ^1.0.0 · built alongside by fune
import { type ReliabilityStats } from "./monitor_mttr_types.ts";
/**
* Reliability figures for the window from <= t < to. An incident counts when
* it overlaps the window; downtime is clipped to it, but MTTR and the
* longest incident use full durations, because an outage that began last
* month still took as long as it took to fix.
*/
export function reliabilityStats(incidents: readonly Incident[], from: number, to: number): ReliabilityStats {
if (!Number.isSafeInteger(from) || !Number.isSafeInteger(to)) throw new RangeError("from and to must be whole seconds");
if (from > to) throw new RangeError(`from must not be after to: ${from} > ${to}`);
let prevEnd: number | null = null;
let count = 0;
let resolved = 0;
let downtime = 0;
let repairTotal = 0;
let longest = 0;
for (const x of incidents) {
if (x.durationSeconds < 0) throw new RangeError(`durationSeconds must not be negative, received ${x.durationSeconds}`);
if (x.end !== null && x.end !== undefined) {
if (x.end < x.start) throw new RangeError(`incident end must not be before its start: ${x.end} < ${x.start}`);
if (x.durationSeconds !== x.end - x.start) {
throw new RangeError(`durationSeconds must equal end - start: ${x.durationSeconds} != ${x.end - x.start}`);
}
}
// An ongoing incident ends, for now, where its duration says.
const end = x.start + x.durationSeconds;
if (prevEnd !== null && x.start < prevEnd) {
throw new RangeError(`incidents must be in time order and must not overlap: ${x.start} is before ${prevEnd}`);
}
prevEnd = end;
if (!(x.start < to && (x.start >= from || end > from))) continue;
count++;
downtime += Math.max(0, Math.min(end, to) - Math.max(x.start, from));
if (x.end !== null && x.end !== undefined) {
resolved++;
repairTotal += x.durationSeconds;
}
if (x.durationSeconds > longest) longest = x.durationSeconds;
}
return {
incidents: count,
resolved,
downtimeSeconds: downtime,
mttrSeconds: resolved > 0 ? roundDiv(repairTotal, resolved, "half-up") : null,
mtbfSeconds: count > 0 ? roundDiv(to - from - downtime, count, "half-up") : null,
longestSeconds: longest,
};
}