/** Time ranges offered above CloudWatch charts. */ export const RANGES = [{label: '1 hour', minutes: 60}, {label: '3 hours', minutes: 180}, {label: '24 hours', minutes: 1440}, {label: '7 days', minutes: 10080}] /** About five round ticks covering [min, max], always including zero when the range does. */ export function niceTicks(min: number, max: number, count = 5): number[] { const span = max - min const raw = span / (count - 1) const magnitude = 10 ** Math.floor(Math.log10(raw)) const step = [1, 2, 2.5, 5, 10].map((factor) => factor * magnitude).find((candidate) => candidate >= raw) ?? 10 * magnitude const start = Math.floor(min / step) * step const end = Math.ceil(max / step) * step const ticks: number[] = [] for (let value = start; value <= end + step / 2; value += step) ticks.push(Number(value.toPrecision(12))) return ticks } export function timeTicks(start: number, end: number, count: number): number[] { if (end <= start) return [start] const step = (end - start) / count return Array.from({length: count + 1}, (_, index) => start + index * step) } export function formatValue(value: number): string { const abs = Math.abs(value) if (abs >= 1e9) return `${trim(value / 1e9)}B` if (abs >= 1e6) return `${trim(value / 1e6)}M` if (abs >= 1e3) return `${trim(value / 1e3)}K` return trim(value) } function trim(value: number): string { return Number.isInteger(value) ? String(value) : value.toFixed(Math.abs(value) < 10 ? 2 : 1).replace(/\.?0+$/, '') }