import { Segmented } from "@/components/ui/segmented" /** * A window of history, and everything a query needs to ask for it. * * `bucketS` keeps the number of points a chart draws roughly constant: a week * of minute buckets is ten thousand readings nobody can see and a megabyte of * JSON every refresh, so the longer windows are folded coarser server-side. */ export type Range = { label: string; hours: number; bucketS: number } /** * The windows on offer. * * Bounded by what the collector keeps: it prunes buckets, failures and runs at * `OBS_RETENTION_DAYS` (30 by default), so a week is behind the last preset * rather than an empty chart. */ export const RANGES: Range[] = [ { label: "1h", hours: 1, bucketS: 60 }, { label: "6h", hours: 6, bucketS: 60 }, { label: "24h", hours: 24, bucketS: 60 }, { label: "7d", hours: 168, bucketS: 900 }, ] /** A day: long enough to hold a night's worth of trouble, short enough to read. */ export const DEFAULT_RANGE = RANGES[2] /** * Where the window starts, as the stamp the history endpoints take. * * Read at fetch time rather than when the options are built, so the window * slides with the clock instead of freezing where the screen opened. */ export const rangeStart = (range: Range) => new Date(Date.now() - range.hours * 3600_000).toISOString() /** The window a screen is showing, as presets. */ export function RangePicker({ value, onChange, }: { value: Range onChange: (range: Range) => void }) { return ( [String(range.hours), range.label] as const, )} onChange={(hours) => onChange( RANGES.find((range) => String(range.hours) === hours) ?? DEFAULT_RANGE, ) } /> ) }