Skip to content

Add per-pane usage averages and custom date ranges - #606

Open
parsakhaz wants to merge 1 commit into
mainfrom
rough-leaderboard-metrics-of-tokens-per-task
Open

Add per-pane usage averages and custom date ranges#606
parsakhaz wants to merge 1 commit into
mainfrom
rough-leaderboard-metrics-of-tokens-per-task

Conversation

@parsakhaz

@parsakhaz parsakhaz commented Sep 12, 2026

Copy link
Copy Markdown
Member

Usage & Limits now shows tokens, estimated API cost, and recorded messages per pane for the selected period and provider. The default average can be switched to a mean that removes the highest and lowest 10% of values independently for each metric, with sample counts and definitions visible.

A calendar button adds custom inclusive local dates alongside 24h/7d/30d/90d presets. Both features reuse the existing report; no additional summary queries, transcript rescans, dependencies, or schema changes are needed. Leaderboard changes are deferred.

Tokens per pane excludes cache reads. Empty panes and unattributed usage are excluded; archived panes with recorded usage are included. Missing model pricing makes the cost summary unavailable. Custom ranges cover available indexed history, subject to the existing 180-day retention window. Trim selection survives filter changes, and late responses/rescan completions cannot replace the current-filter report.

Validation:

  • pnpm lint and pnpm typecheck passed.
  • pnpm --filter frontend build and pnpm build:main passed.
  • Seven Usage & Limits Playwright tests passed: calculations, independent trimming, empty/missing-price samples, provider/preset changes, custom-date validation/cancel, 23/25-hour DST dates, and stale request/rescan handling.
  • Wide/narrow browser screenshots inspected; fresh implementation review completed with no remaining blockers.

Screenshots (fixture data):

Per-pane usage

Custom date range

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T00:09:11.203410Z 43c68b2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown

React Doctor found 1 new issue in 1 file · 1 warning · score 90 / 100 (Great) · 0 fixed · vs main

1 warning

src/components/usage/UsageView.tsx

  • ⚠️ L193 Loading flag reset outside finally no-loading-flag-reset-outside-finally

Reviewed by React Doctor for commit 43c68b2. See inline comments for fixes.

setRefreshing(false);
if (id === requestId.current) {
setLoading(false);
setRefreshing(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

React Doctor · react-doctor/no-loading-flag-reset-outside-finally (warning)

This resets a loading/busy flag only on the success path: if the awaited call rejects the reset never runs and the flag stays stuck truthy (a spinner that never stops, a button disabled forever). Move the reset into a finally block, or mirror it on every catch, so it clears on rejection too.

Fix → A trailing setLoading(false) after an await never runs if the awaited call rejects, so the flag stays stuck truthy; reset it in a finally block (or mirror the reset on every catch) so it clears on both paths.

Docs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 43c68b2075

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +10 to +14
export function usageDateBounds(range: UsageDateRange) {
const start = new Date(`${range.start}T00:00:00`);
const end = new Date(`${range.end}T00:00:00`);
end.setDate(end.getDate() + 1);
return { fromMs: start.getTime(), toMs: end.getTime() - 1 };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Align daily buckets with the custom range timezone

When a custom interval longer than two days is selected outside UTC, these local-midnight bounds are passed into a report whose automatic daily series still floors timestamps to UTC-day boundaries (main/src/services/usage/usageAggregator.ts:323,360), while the renderer formats those boundaries as local dates (UsageView.tsx:294). For example, March 8–10 in America/Los_Angeles can produce buckets labeled March 7–10 and split a selected local day between bars, so the time chart does not represent the requested calendar days. The custom-range path needs timezone-aligned bucketing or local regrouping of hourly data.

Useful? React with 👍 / 👎.

Comment on lines +549 to +551
initialRange={customRange ?? {
start: localDateString(new Date(Date.now() - rangeDays * DAY_MS)),
end: localDateString(new Date()),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Seed inclusive ranges with one fewer calendar day

When no custom range exists, opening the dialog after selecting 30d seeds today - 30 days through today, which is 31 inclusive calendar dates; after 24h it similarly expands to two full dates. Applying the untouched defaults therefore requests more history than the selected preset suggests. Calculate the start as rangeDays - 1 calendar days before today (using calendar arithmetic so DST does not shift the date).

Useful? React with 👍 / 👎.

Comment on lines +222 to +224
const rangeLabel = customRange
? `${customRange.start} to ${customRange.end}`
: RANGE_OPTIONS.find(o => o.days === rangeDays)?.label ?? `${rangeDays}d`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Announce the custom interval in the chart label

When a custom range is active, rangeDays retains the previous preset, and the AreaChart at line 658 still announces Token usage over the last ${rangeDays} days. A screen-reader user selecting a custom historical interval therefore hears a false range even though this new rangeLabel contains the correct dates. Use the custom label in the chart's accessible name when customRange is set.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant