Problem
With METRICS_RETENTION_DAYS set (e.g. 14 on the free Grafana Cloud plan), the largest window that reports an honest summary figure is 7d. 30d and 1y correctly render — because their labels would overstate the data behind them.
The gap: the plan actually retains ~14 days, but there is no window that summarizes the 8–14 day slice. The per-window uptime/response numbers jump straight from 7d to —, so roughly the second week of retained data is never shown as a headline figure anywhere (overview list, per-site uptime grid, or the window selector).
Note this is specifically about the summary numbers. The per-site charts are not affected — fetchSiteHistory already clamps the bars, response line, and min/avg/max to retentionSec(), so selecting 30d/1y on a detail page plots the full ~14 retained days. The retained data is fetched and drawn; it just isn't quantified as a labeled percentage.
Proposed solution
Add a 14d entry to the window set so the full free-plan retention has an honest, properly-labeled summary figure.
- Extend
WindowKey and WINDOWS in lib/types.ts with { key: "14d", label: "14 days", seconds: 1_209_600 }, ordered between 7d and 30d.
- Add a
BAR_COUNT["14d"] in lib/buckets.ts (e.g. 84 → clean 4h buckets, since 84 × 14400 = 1_209_600), keeping the "count × step == span" invariant.
- Everything else is window-generic:
coveredWindows(), windowWithinRetention(), the query fan-out, mock data, and the coverage clamp all iterate WINDOWS, so 14d flows through with no special-casing.
- Under
METRICS_RETENTION_DAYS=14, 14d becomes the largest covered window, so defaultWindow() naturally opens the overview on it — the page defaults to the max data the plan retains.
Scope / things to get right
- Layout: the per-site grid is
grid-cols-2 sm:grid-cols-4 and would now hold five cells — needs a responsive tweak (e.g. sm:grid-cols-5).
- Tests: window-map assertions in
lib/synthetics.test.ts, the per-window step/count case in lib/buckets.test.ts, and the retention default in components/Overview.test.tsx hardcode the current four keys.
- Docs: mention
14d in docs/configuration.md alongside the retention section.
Alternatives considered
- Dynamically relabeled "13d/14d" figure over whatever's retained — most truthful, but the label churns with config and the moving edge of history and complicates every label render site.
- Show the clamped 14-day figure on the
30d card with a footnote — reintroduces the "30 days" showing 14 mislabeling the retention work removed.
- Leave as-is — data is still visible in charts, just not summarized; leaves a week of real data unquantified.
Additional context
Builds on the METRICS_RETENTION_DAYS work (#13); the clamping that makes 14d show real data already exists in fetchSiteHistory and the maxSpanSec param in lib/buckets.ts.
Problem
With
METRICS_RETENTION_DAYSset (e.g.14on the free Grafana Cloud plan), the largest window that reports an honest summary figure is7d.30dand1ycorrectly render—because their labels would overstate the data behind them.The gap: the plan actually retains ~14 days, but there is no window that summarizes the 8–14 day slice. The per-window uptime/response numbers jump straight from
7dto—, so roughly the second week of retained data is never shown as a headline figure anywhere (overview list, per-site uptime grid, or the window selector).Note this is specifically about the summary numbers. The per-site charts are not affected —
fetchSiteHistoryalready clamps the bars, response line, and min/avg/max toretentionSec(), so selecting30d/1yon a detail page plots the full ~14 retained days. The retained data is fetched and drawn; it just isn't quantified as a labeled percentage.Proposed solution
Add a
14dentry to the window set so the full free-plan retention has an honest, properly-labeled summary figure.WindowKeyandWINDOWSinlib/types.tswith{ key: "14d", label: "14 days", seconds: 1_209_600 }, ordered between7dand30d.BAR_COUNT["14d"]inlib/buckets.ts(e.g.84→ clean 4h buckets, since84 × 14400 = 1_209_600), keeping the "count × step == span" invariant.coveredWindows(),windowWithinRetention(), the query fan-out, mock data, and the coverage clamp all iterateWINDOWS, so14dflows through with no special-casing.METRICS_RETENTION_DAYS=14,14dbecomes the largest covered window, sodefaultWindow()naturally opens the overview on it — the page defaults to the max data the plan retains.Scope / things to get right
grid-cols-2 sm:grid-cols-4and would now hold five cells — needs a responsive tweak (e.g.sm:grid-cols-5).lib/synthetics.test.ts, the per-window step/count case inlib/buckets.test.ts, and the retention default incomponents/Overview.test.tsxhardcode the current four keys.14dindocs/configuration.mdalongside the retention section.Alternatives considered
30dcard with a footnote — reintroduces the "30 days" showing 14 mislabeling the retention work removed.Additional context
Builds on the
METRICS_RETENTION_DAYSwork (#13); the clamping that makes14dshow real data already exists infetchSiteHistoryand themaxSpanSecparam inlib/buckets.ts.