Functional Weave
Code in Python

monitor.rollup@1.0.0

impl/typescript.ts

1,640 bytes · the TypeScript implementation · view raw

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;
}