Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { roundDiv } from "./math_round_div.ts"; ← from math.round-div ^1.0.0 · built alongside by fune
import { seriesWindow, type MetricSample } from "./monitor_series_window.ts"; ← from monitor.series-window ^1.0.0 · built alongside by fune
import { type Bucket } from "./monitor_rollup_types.ts";
const MAX_BUCKETS = 10000;
/**
* One row per bucket from `from` to `to`, empty buckets included so a chart
* shows gaps as gaps. Buckets are aligned to `from`; the last is clipped to `to`.
*/
export function rollup(samples: readonly MetricSample[], from: number, to: number, bucketSeconds: number): readonly Bucket[] {
if (!Number.isInteger(bucketSeconds)) throw new RangeError("bucketSeconds must be a whole number of seconds");
if (bucketSeconds < 1) throw new RangeError(`bucketSeconds must be at least 1, received ${bucketSeconds}`);
const inside = seriesWindow(samples, from, to);
const n = Math.ceil((to - from) / bucketSeconds);
if (n > MAX_BUCKETS) throw new RangeError(`too many buckets: ${n}, at most ${MAX_BUCKETS}`);
const out: Bucket[] = [];
let j = 0;
for (let i = 0; i < n; i++) {
const start = from + i * bucketSeconds;
const end = Math.min(start + bucketSeconds, to);
let count = 0;
let sum = 0;
let min: number | null = null;
let max: number | null = null;
let last: number | null = null;
while (j < inside.length && inside[j].at < end) {
const v = inside[j].value;
count += 1;
sum += v;
min = min === null || v < min ? v : min;
max = max === null || v > max ? v : max;
last = v;
j++;
}
const avg = count === 0 ? null : roundDiv(sum, count, "half-up");
out.push({ start, end, count, min, max, avg, sum, last });
}
return out;
}