Fix usage day-boundary timezone handling and add configurable usage ranges with smoother UI updates#96
Conversation
|
Thanks for reviewing this PR. This one is pretty focused. The main thing I wanted to fix is a trust issue on the Usage page: the dashboard already has a configurable So the goals here were basically:
A few quick notes in case they help while reviewing:
If there’s one thing I’d love sanity-checked most, it’s whether 感谢看这个 PR。 这次改动我其实收得比较紧,主要就是想修一个 Usage 页面的“可信度问题”:项目已经有可配置的 所以这次的目标其实很直接:
补几个 reviewer 可能会关心的点:
如果 reviewer 想先抓主线,我觉得最值得先确认的一点就是:在这个项目里, |
TianyiDataScience
left a comment
There was a problem hiding this comment.
Thanks for the detailed write-up here. The core direction makes sense to me: using the configured UI_TIMEZONE for day-boundary math and expanding the Usage view beyond today / cumulative is a reasonable improvement for operators.
I’m requesting a trim before I can take this one as-is, because the PR currently bundles in a couple of unrelated behavior/config changes:
- it flips the repo default
UI_TIMEZONEfromUTCtoAmerica/New_York - it adds deployment-specific notes/config for
opendashboard.ecomstack.net/ Cloudflare / nginx / PM2
Those pieces are much more environment-specific than the underlying usage fix, and the default-timezone change would also alter behavior for installs that never set UI_TIMEZONE explicitly.
If you keep the timezone-aware usage aggregation + richer range selection in this PR, and drop the default-timezone flip plus the deployment-specific notes/config, I’m happy to re-check quickly. The main thing I want to preserve is that this lands as a focused product/runtime fix rather than mixing in one team’s deployment defaults.
|
Sorry about that. We initially made the change while deploying and testing locally, so some local environment-specific config ended up in the PR. We have now trimmed those parts out:
We also fixed the Usage range interaction so it now stays on the current page and updates via partial refresh, instead of falling through to a full page reload. The PR is now focused on the timezone-aware usage aggregation and the richer usage range support only. I also merged the latest upstream/main into this branch and resolved the test/usage-cost.test.ts conflict by keeping both the new upstream coverage and the timezone/range coverage in this PR. Verification run locally before updating the PR:
|
31265a2 to
87e26de
Compare
TianyiDataScience
left a comment
There was a problem hiding this comment.
Thanks for the quick follow-up. I re-checked the updated PR metadata and patch against the previous requested changes:
- the branch is now mergeable against
main - the changed-file set is back to the usage/runtime/UI/test scope only
- the repo default timezone is covered by the new
test/config-defaults.test.tsand remainsUTC - I do not see the earlier deployment-specific Cloudflare/nginx/PM2 material in the current changed files
So the trim I asked for looks addressed from the diff. The remaining blocker is just verification on the exact branch: this automation workspace cannot fetch the PR head right now (FETCH_HEAD is sandbox-blocked in the worktree, and an isolated /tmp fetch cannot resolve github.com), and GitHub is not reporting status checks for 87e26dee407ac48abbb046c90b4fc0f57aecf3de.
Next step on my side is a local/CI test pass on the exact head commit before approving or merging. Thanks again for narrowing the PR back to the core usage-timezone change.
PR Title
Fix usage day-boundary timezone handling and add configurable usage ranges with smoother UI updates
English PR Description
Summary
This PR fixes a long-standing mismatch between the configured UI timezone and the actual day-boundary logic used by Usage & Cost reporting.
Before this change, several usage-related calculations still implicitly followed UTC-style date slicing, which caused "today", token usage, and estimated cost to drift away from the dashboard's configured timezone. In deployments using
UI_TIMEZONE=America/New_York(or any non-UTC timezone), this could make the Usage page show misleading numbers around day rollover.This PR also expands the Usage page from a binary
Today / Cumulativeview into a more practical operator workflow with:TodayYesterdayThis weekLast weekLast 7 daysLast 30 daysCumulativeIn addition, the usage range controls now update the Usage page without a full page reload, while preserving the existing server-rendered architecture and visual language.
Why this change matters
From an operator perspective, this was not just a presentation issue.
The dashboard already exposes a configurable
UI_TIMEZONE, and absolute timestamps in the UI respect it. However, several usage and cost rollups still derived day buckets withtoISOString().slice(0, 10)or equivalent UTC-oriented logic. That created a trust gap:For teams using the dashboard to monitor real spend, token burn, and subscription windows, this made the Usage page harder to trust during the most sensitive time: around daily rollover and reporting cutoffs.
This PR aligns the reporting logic with the configured timezone and makes the page much more useful for real operational review.
What changed
1. Use configured timezone for usage day boundaries
The following usage-related paths now derive calendar days from
UI_TIMEZONErather than UTC date slicing:A shared timezone-aware date formatter was added so the logic stays centralized and consistent.
2. Add configurable usage range selection
The Usage page now supports richer range selection through both UI state and backend aggregation:
todayyesterdaythis_weeklast_weeklast_7dlast_30dcumulativecustomwithusage_start/usage_endThe backend now returns a selected range summary and a selected-range breakdown so the page no longer has to fake this behavior on the frontend.
3. Keep the page responsive without full reloads
Range selection now updates the Usage section via lightweight fetch-based partial replacement instead of a full page refresh.
This keeps the current architecture intact:
4. Improve the custom range UI without introducing a new library
The new date-range controls were styled using the existing design system and CSS patterns already present in the repo.
The result is intentionally incremental rather than disruptive:
5. Keep English and Chinese copy aligned
All newly introduced range controls and usage descriptions were wired through the existing bilingual copy helpers, so the feature works cleanly in both English and Chinese.
Files changed
Runtime / data logic
src/runtime/ui-timezone.tssrc/runtime/usage-cost.tssrc/runtime/commander-digest.tsUI / interaction
src/ui/server.tsTests
test/ui-timezone.test.tstest/usage-cost.test.tstest/ui-render-smoke.test.tsImplementation notes
Timezone handling
This PR intentionally does not hardcode a specific business timezone in usage logic.
Instead, all relevant day-boundary calculations now flow from the existing configured
UI_TIMEZONEvalue, which keeps behavior consistent with the rest of the dashboard and with deployment-specific expectations.Range model
The backend now exposes selected-range data separately from the fixed reference windows (
today,7d,30d), allowing the UI to:This avoids overloading the original period cards with too many responsibilities.
Progressive enhancement
The partial update behavior for usage ranges is implemented as a small client-side enhancement layered on top of the existing server-rendered page. If JavaScript behavior changes in the future, the page still has a clear server-side URL model underneath.
Backward compatibility
This PR is designed to be low-risk for existing deployments:
UI_TIMEZONEconfig continues to workcumulativeremains available as beforeValidation
Typecheck
npx tsc -p tsconfig.json --noEmitFocused tests
npm test -- --test test/ui-timezone.test.ts test/usage-cost.test.ts test/ui-render-smoke.test.tsAdditional checks performed
Test coverage added
This PR adds or updates coverage for:
yesterdaylast_weekRisks / tradeoffs
The largest behavioral change here is intentional: any deployment that previously looked like it was using one timezone while actually grouping usage by UTC will now report according to the configured timezone. That is the desired outcome, but it may cause some numbers near day boundaries to shift compared with previous behavior.
I believe that is the correct fix, because it aligns the dashboard with its stated configuration and improves operator trust.
What I did not change
To keep this PR reviewable and merge-friendly, I did not:
Suggested reviewer focus
The most important review points are:
UI_TIMEZONEis the right source of truth for usage day boundariesOperator impact
After this PR:
Screenshots / demo
Recommended to capture during review:
TodayYesterdayAmerica/New_YorkClosing note
This change is meant to improve one of the most trust-sensitive surfaces in the dashboard: usage and cost reporting. I tried to keep the implementation faithful to the current architecture, low-risk to deploy, and practical for real operators instead of adding surface-level UI only.
中文 PR 描述
概述
这个 PR 修复了 Usage & Cost 报表中一个长期存在的问题:界面已经支持配置
UI_TIMEZONE,但部分“按天统计”的用量与费用逻辑仍然隐式按 UTC 边界在算,导致“今天”的 token 用量、费用和真实团队时区不一致。在使用
UI_TIMEZONE=America/New_York或其他非 UTC 时区的部署中,这会让 Usage 页面在跨日附近显示出误导性的数字,影响运营判断。在修复时区边界问题的同时,这个 PR 也把 Usage 页面从原本只有
Today / Cumulative两种口径,扩展成更贴近真实运营场景的范围查看方式:TodayYesterdayThis weekLast weekLast 7 daysLast 30 daysCumulative此外,时间范围切换现在支持局部刷新,不再每次都整页重载,同时保持现有服务端渲染架构和视觉风格不变。
为什么这个改动重要
这不只是一个展示层的小问题,而是一个“数据可信度”问题。
当前控制台已经有
UI_TIMEZONE配置,UI 中绝对时间显示也是按这个配置来的;但如果“今天”的用量与费用仍然按 UTC 切日,用户看到的会是:对依赖这个面板看 token 消耗、成本走势和订阅窗口的团队来说,这会直接削弱 Usage 页面的可信度,尤其是在每天切日和预算观察最敏感的时刻。
这个 PR 的核心目标,就是让报表逻辑和配置的时区真正一致,并把 Usage 页做成更适合日常运营使用的形态。
改动内容
1. 让 Usage 的“按天边界”真正跟随配置时区
以下 Usage 相关逻辑现在都改为基于
UI_TIMEZONE推导自然日,而不再直接用 UTC 风格的日期截取:同时新增了统一的时区日期格式化工具,避免各处重复实现和逻辑漂移。
2. 扩展 Usage 范围选择
Usage 页面现在支持以下范围:
todayyesterdaythis_weeklast_weeklast_7dlast_30dcumulativecustom,通过usage_start/usage_end指定自定义范围后端也同步增加了“选中范围”的 summary 和 breakdown,因此这不是纯前端切换,而是真正的数据聚合能力扩展。
3. 范围切换改为局部刷新,不再整页 reload
现在点击 Usage 范围按钮或提交自定义时间范围时,会通过 fetch 拉取页面片段并替换 Usage 区块,而不是整页刷新。
这样做的好处是:
4. 优化自定义时间选择 UI,不引入新库
这次没有引入新的日期选择库,而是直接复用当前项目已有的样式体系进行增强。
结果是一个比较克制的增量优化:
5. 保持中英文文案一致
所有新增加的时间范围标签、说明文案和使用提示都接入了现有双语文案体系,确保英文和中文界面都能正常工作,不会出现一边完整、一边像临时文案的情况。
涉及文件
运行时 / 数据逻辑
src/runtime/ui-timezone.tssrc/runtime/usage-cost.tssrc/runtime/commander-digest.tsUI / 交互
src/ui/server.ts测试
test/ui-timezone.test.tstest/usage-cost.test.tstest/ui-render-smoke.test.ts实现说明
时区处理
这个 PR 没有把某个具体业务时区硬编码到 Usage 逻辑里。
相反,所有相关的“按天边界”计算都统一从已有配置
UI_TIMEZONE取值,这样逻辑上与整个控制台保持一致,也能适应不同部署环境。范围模型
后端现在把“选中范围数据”和原有固定参考窗口(
today/7d/30d)拆开返回,使 UI 可以:这样既增强了灵活性,也避免把原始 period 卡片塞入过多职责。
渐进增强
局部刷新的实现是一个很轻量的客户端增强层,叠加在现有服务端页面之上。如果将来客户端逻辑调整,底层仍然保留完整、可直达的服务端 URL 模型。
兼容性
这个 PR 设计上尽量保持低风险:
UI_TIMEZONE配置继续生效cumulative视图仍然保留验证方式
类型检查
npx tsc -p tsconfig.json --noEmit聚焦测试
npm test -- --test test/ui-timezone.test.ts test/usage-cost.test.ts test/ui-render-smoke.test.ts额外验证
新增 / 更新测试覆盖
本 PR 补充或更新了以下覆盖:
yesterdaylast_week风险与取舍
这次最大的行为变化是有意为之:如果某个部署此前“看起来像是在某个时区展示”,但实际统计却按 UTC 切日,那么这个 PR 会让数字改为真正跟随配置时区。
这可能会让跨日附近的数字与旧行为不一样,但我认为这是正确修复,因为它让系统行为终于和它宣称的配置保持一致,也提升了运营层面对数据的信任。
我刻意没有做的事情
为了让这个 PR 更容易审查和合并,我没有做以下扩展:
建议审查关注点
建议 reviewer 重点关注:
UI_TIMEZONE是否应该成为 Usage“按天边界”的唯一可信来源对运营侧的影响
合并后:
截图 / 演示建议
建议在 review 时附上:
Today视图Yesterday视图America/New_York)下的效果确认结语
这个改动主要针对控制台里最需要“被信任”的页面之一:Usage 与 Cost 报表。我尽量把实现控制在现有架构之内,保持低风险、易部署,并让它真正对运营者有用,而不是只做表层 UI 改动。
Reviewer Note
Primary intent: make usage/cost reporting truly respect the configured timezone and improve operator trust around day rollovers, while keeping the implementation low-risk and aligned with the existing server-rendered architecture.
Testing Checklist
npx tsc -p tsconfig.json --noEmitnpm test -- --test test/ui-timezone.test.ts test/usage-cost.test.ts test/ui-render-smoke.test.tsonline