feat(history): answer long windows from the union and take a range key - #92
Closed
Fl0p wants to merge 2 commits into
Closed
feat(history): answer long windows from the union and take a range key#92Fl0p wants to merge 2 commits into
Fl0p wants to merge 2 commits into
Conversation
/history was the last read endpoint outside the range contract: it took from/to and read raw spans only, so on year or all it charted a visibly shorter window than the Costs panel beside it, and the Overview papered over that by borrowing the sessions list's coverage note. It now takes range, defaulting to month — the window from/to already defaulted to, so an existing caller sees exactly what it saw before — with explicit from/to still winning and echoing a null range, the precedence /costs sets. At day, week and month granularity buckets and by_model resolve over the existing usageCTE union at the raw-floor split, so a long window keeps charting after retention has deleted the raw spans. hour stays raw-only and says so in covered_since: daily_usage consumes whole UTC days and cannot produce a sub-day bucket, so the alternative is day-shaped data under an hour label. Both heatmaps resolve hour of day at every granularity and get the same treatment under heatmap_covered_since, rather than drawing empty cells for days that were merely rolled up. The Overview's History block reads that coverage for its own series instead of the sessions list's, so the note is gone on every range the union covers. RANGE_DAYS goes with it — the page no longer derives from/to from the range key at all. Co-Authored-By: Wayland <wayland@agents.flopbut.local> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The hourly series reports covered_since, but only the Overview read it — and the Overview asks for hour granularity solely on its Day range, where a 24h window is always inside raw retention. So the one place the clamp is reachable, the History page's 1y window at Hour granularity, said nothing: the charts silently showed the last raw days while the KPI header totalled a year. Both notes now come from one component keyed by which series it describes: covered_since above the activity charts, and heatmap_covered_since under each heatmap. Co-Authored-By: Wayland <wayland@agents.flopbut.local> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Contributor
Author
|
Squash-merged to |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
/historywas the last read endpoint outside therangecontract: it tookfrom/toand read raw spans only, so onyearorallit charted a visibly shorter window than the Costs panel beside it. The Overview papered over that by borrowing the sessions list'scovered_sinceand printing a note. This removes the need for that note wherever the union can genuinely cover the window.Acceptance criteria
rangeviaparseRangeDefault, echoing the resolved key — default ismonth. That is the windowparseDateRangealready applied when a caller passed neitherfromnorto, so a bareGET /historyanswers exactly what it answered before. (allwould have silently widened every existing caller;/sessionsand/modelstookallfor the mirror-image reason — they had no filter before.)from/towin — sameexplicitDateRangeprecedence/costssets; the response then echoes"range": null.dayresolves over the union —historyUnionSeriesreuses the existingusageCTE/newUsageFilterat the raw-floor split. No second union was written.hourstays raw-only and reportscovered_sinceviarawCoveredSince.HistorySectionreads the history response's owncovered_sinceinstead of the sessions list's, so it is gone on every range the union covers and remains only where coverage is genuinely short.internal/api/history_range_test.go, followingoverview_range_test.goand seeding off the sameseedRangeFixture.docs/operations/api-reference.mdgains aGET /historysection; the "not part of this contract" line is replaced, the endpoint added to the contract paragraph and the defaults table.CHANGELOG.md+ aREADME.mdclause.Also in scope:
RANGE_DAYSandHISTORY_EPOCHare gone fromOverview.tsx— the page no longer derivesfrom/tofrom the range key at all, so its copy of the window lengths cannot drift from the server's. (The ticket flagged a leap-year skew betweenRANGE_DAYS.year = 365and a serverAddDate(-1, 0, 0);rangeSinceonmainactually usesAddDate(0, 0, -365), so there was no live skew — deleting the frontend copy removes the class of bug regardless.)Beyond the criteria — one addition worth a look
heatmap_covered_since. Both heatmaps resolve hour of day, whichdaily_usagedoes not keep, so they stay raw-only at every granularity. Now that the charts above them reach back a year, the calendar draws ~11 months of empty cells that read as "no activity" rather than "rolled up". SamerawCoveredSincecall, one note per heatmap. Easy to drop if you consider it out of scope.The second commit exists for the same reason:
covered_sincehad no consumer where it was actually reachable. The Overview only asks forhouron itsDayrange, where a 24 h window is always inside raw retention — so the History page at 1y + Hour showed a raw-only chart under a year-long KPI header and said nothing. It now shows the note.Verified
go test ./...green,go vet ./...clean (Dockergolang:1.23-bookworm; no native Go toolchain on this box).npm run buildclean (tsc+ vite).daily_usagerows, retention run so aggregates cover 90 days and the raw floor sits at 2026-07-27):/history?granularity=day&range=all/costs?range=all/history?granularity=hour&range=allcovered_since2026-07-27T08:00:00Z/history?range=all&from=2026-08-01"range": null, clamped to 20 buckets/history?granularity=day&range=monthcovered_sincenull,heatmap_covered_sincesetCoverage notes rendered, per page and range:
All/Year/Month/Day→ no History note at any range; only the Sessions note remains, which is correct.30d→ heatmap notes only.1y+Hour→ hourly-series note and heatmap notes.One caveat on the screenshots: Recharts area/line marks do not rasterise in this headless Chromium at Overview's chart size — the untouched Costs chart is blank in exactly the same way. I checked the DOM instead: the Overview History area is a real 179-segment path 1098 px wide spanning all 90 days.
Scrutinize
monthdefault (criterion 1) — it is the behaviour-preserving choice, but it is the one call that changes what a bare request means if I readparseDateRangewrong.heatmap_covered_sinceis welcome or scope creep.🤖 Generated with Claude Code