feat(dashboard): add admin channel analytics report - #5921
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe change adds conservative channel ID backfill scripts, records additional prompt, completion, and cache token metrics, and exposes an admin-authenticated channel quota report endpoint with aggregation and channel metadata enrichment. ChangesChannel quota analytics
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant AdminClient
participant API Router
participant GetChannelQuotaReportData
participant QuotaDataStore
participant ChannelStore
AdminClient->>API Router: GET /api/data/channels
API Router->>GetChannelQuotaReportData: authorize and invoke handler
GetChannelQuotaReportData->>QuotaDataStore: aggregate quota data by channel and model
GetChannelQuotaReportData->>ChannelStore: fetch channel metadata
ChannelStore-->>GetChannelQuotaReportData: channel names and status
GetChannelQuotaReportData-->>AdminClient: JSON report data
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
model/usedata_channel.go (1)
21-34: 🚀 Performance & Scalability | 🔵 TrivialConsider a composite index for this reporting query.
The aggregation filters/groups by
channel_idandcreated_attogether, butQuotaDataonly has separate single-column indexes on each. A composite index (e.g.,channel_id, created_at) would better support this grouping pattern as data volume grows.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@model/usedata_channel.go` around lines 21 - 34, Add a composite index to support the reporting query in GetChannelQuotaReportData, since it filters and groups on channel_id and created_at together and the current single-column indexes are not enough. Update the QuotaData model/index definitions to include a combined channel_id, created_at index (or equivalent migration/tag), and keep the query in GetChannelQuotaReportData using those same fields so the database can use the new index efficiently.model/usedata_channel_test.go (1)
90-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse
assertfor independent, non-fatal value checks.Lines 90-95 check independent row fields after the length/order is already validated; using
assert(rather thanrequire) here lets all mismatches surface in a single run instead of stopping at the first failure.As per coding guidelines, "New or substantially rewritten Go backend tests must use `github.com/stretchr/testify/require` for setup and fatal assertions, and `github.com/stretchr/testify/assert` for non-fatal value checks."♻️ Suggested change
+ "github.com/stretchr/testify/assert" ... - require.Equal(t, "gpt-b", rows[1].ModelName) - require.Equal(t, 75, rows[1].Quota) - require.Equal(t, "west", rows[2].ChannelName) - require.Equal(t, 2, rows[2].Status) - require.Equal(t, 99, rows[3].ChannelID) - require.Equal(t, "channel-99", rows[3].ChannelName) + assert.Equal(t, "gpt-b", rows[1].ModelName) + assert.Equal(t, 75, rows[1].Quota) + assert.Equal(t, "west", rows[2].ChannelName) + assert.Equal(t, 2, rows[2].Status) + assert.Equal(t, 99, rows[3].ChannelID) + assert.Equal(t, "channel-99", rows[3].ChannelName)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@model/usedata_channel_test.go` around lines 90 - 95, Switch the independent row field checks in the usedata channel test from fatal assertions to non-fatal ones. In the test that validates rows after length/order has already been confirmed, keep `require` for setup and structural checks, but replace the `require.Equal` calls on `rows[1]`, `rows[2]`, and `rows[3]` with `assert.Equal` so all value mismatches are reported in one run.Source: Coding guidelines
web/default/src/features/dashboard/components/channels/channel-analytics.tsx (2)
1350-1362: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExpose selected state of the trend/bar toggle to assistive tech.
These buttons act as a toggle group but only convey the active state visually. Add
aria-pressed(or arole="tab"/aria-selectedpattern) so screen-reader users can perceive the current selection.♿ Proposed fix
<button key={item.value} type='button' + aria-pressed={activeTrendView === item.value} onClick={() => setActiveTrendView(item.value)}As per path instructions: "ensure keyboard operability ... add ARIA attributes when needed".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/dashboard/components/channels/channel-analytics.tsx` around lines 1350 - 1362, The trend/bar toggle buttons in channel-analytics currently expose selection only through styling, so assistive tech cannot tell which view is active. Update the button rendered in the item map around setActiveTrendView/activeTrendView to include an accessible selected-state pattern, preferably aria-pressed on the existing button or a tab/tablist aria-selected pattern if you switch semantics. Keep the current click behavior and ensure the active item is announced consistently for screen-reader users.Source: Path instructions
792-797: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMark decorative icons with
aria-hidden="true".These icons are purely decorative (each is paired with a text label), so they should be hidden from assistive tech. This applies to the other decorative icons in this file as well (
ChartPanelheader icon at Line 830,Channel Healthicon at Line 1370, and the summary card icons).♿ Example fix for SummaryCard
- <Icon className='size-4' /> + <Icon className='size-4' aria-hidden='true' />As per path instructions: "hide decorative icons with
aria-hidden="true"".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/dashboard/components/channels/channel-analytics.tsx` around lines 792 - 797, Mark the decorative icons used in `SummaryCard`, the `ChartPanel` header, the `Channel Health` section, and the summary card icons with `aria-hidden="true"` since each icon already has a nearby text label and should be hidden from assistive tech. Update the icon elements in `channel-analytics.tsx` to include this attribute consistently wherever the icon is purely decorative, using the existing component names and JSX blocks as the targets.Source: Path instructions
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/i18n/locales/ja.json`:
- Line 740: The ja.json translation for Channel Tokens still mixes English and
Japanese, so update the localized value in the locale entry to a fully Japanese
phrasing for consistency with nearby keys like Channel Requests and Channel
Spend. Locate the Channel Tokens string in the Japanese locale file and change
the translation from the mixed-language form to the appropriate Japanese term
suggested by the review.
In `@web/default/src/i18n/locales/ru.json`:
- Line 5000: The Russian locale entry for Zoom is still left in English, so
update the corresponding key in the ru.json localization data to a proper
Russian translation. Locate the "Zoom" string in the locale dictionary and
replace the value with a localized term consistent with other translations in
this file, such as "Масштаб", to match the intended Russian UI text.
---
Nitpick comments:
In `@model/usedata_channel_test.go`:
- Around line 90-95: Switch the independent row field checks in the usedata
channel test from fatal assertions to non-fatal ones. In the test that validates
rows after length/order has already been confirmed, keep `require` for setup and
structural checks, but replace the `require.Equal` calls on `rows[1]`,
`rows[2]`, and `rows[3]` with `assert.Equal` so all value mismatches are
reported in one run.
In `@model/usedata_channel.go`:
- Around line 21-34: Add a composite index to support the reporting query in
GetChannelQuotaReportData, since it filters and groups on channel_id and
created_at together and the current single-column indexes are not enough. Update
the QuotaData model/index definitions to include a combined channel_id,
created_at index (or equivalent migration/tag), and keep the query in
GetChannelQuotaReportData using those same fields so the database can use the
new index efficiently.
In
`@web/default/src/features/dashboard/components/channels/channel-analytics.tsx`:
- Around line 1350-1362: The trend/bar toggle buttons in channel-analytics
currently expose selection only through styling, so assistive tech cannot tell
which view is active. Update the button rendered in the item map around
setActiveTrendView/activeTrendView to include an accessible selected-state
pattern, preferably aria-pressed on the existing button or a tab/tablist
aria-selected pattern if you switch semantics. Keep the current click behavior
and ensure the active item is announced consistently for screen-reader users.
- Around line 792-797: Mark the decorative icons used in `SummaryCard`, the
`ChartPanel` header, the `Channel Health` section, and the summary card icons
with `aria-hidden="true"` since each icon already has a nearby text label and
should be hidden from assistive tech. Update the icon elements in
`channel-analytics.tsx` to include this attribute consistently wherever the icon
is purely decorative, using the existing component names and JSX blocks as the
targets.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 292ae0fe-772d-46b3-bbcc-6c25ac6ec1fe
📒 Files selected for processing (23)
bin/backfill_quota_data_channel_id.mysql.sqlbin/backfill_quota_data_channel_id.sqlite_postgres.sqlcontroller/usedata.gomodel/log.gomodel/usedata.gomodel/usedata_channel.gomodel/usedata_channel_test.gomodel/usedata_flow_test.gorouter/api-router.goweb/classic/rsbuild.config.tsweb/default/src/features/dashboard/api.tsweb/default/src/features/dashboard/components/channels/channel-analytics.tsxweb/default/src/features/dashboard/index.tsxweb/default/src/features/dashboard/section-registry.tsxweb/default/src/features/dashboard/types.tsweb/default/src/hooks/use-sidebar-config.tsweb/default/src/hooks/use-sidebar-data.tsweb/default/src/i18n/locales/en.jsonweb/default/src/i18n/locales/fr.jsonweb/default/src/i18n/locales/ja.jsonweb/default/src/i18n/locales/ru.jsonweb/default/src/i18n/locales/vi.jsonweb/default/src/i18n/locales/zh.json
Add an admin-only channel analytics dashboard with channel/model filters, metric switching, token breakdowns, trend/bar chart views, health summaries, and accurate spend details. Persist prompt/completion/cache token splits into quota_data and expose an admin channel report API backed by aggregated quota data. Add conservative channel_id backfill SQL scripts for legacy quota_data rows and fix classic frontend date-fns alias resolution for Bun/Docker builds.
94c6330 to
6254881
Compare
51fdfc5 to
2b6f1df
Compare
Important
📝 变更描述 / Description
新增管理员可见的渠道统计报表,用于从渠道维度查看金额、请求数、总 Token、输入/输出 Token、cache read/write Token、模型使用分布、消费趋势与渠道健康度。后端基于
quota_data聚合渠道、模型和时间维度,接口通过管理员鉴权暴露;前端把渠道统计放在管理员的渠道区域,同时保留 dashboard 内部 tab 体验。为保证后续数据准确,消费日志写入数据看板时同步记录 prompt/completion/cache token 明细和 channel_id;旧数据不做自动迁移,提供按数据库方言区分的一次性保守回填 SQL,只处理能和消费日志唯一匹配且总量一致的历史
channel_id = 0聚合行,避免总金额重复或误拆分。另外修复 classic 前端在 Bun/Docker 构建时
date-fnsalias 写死路径的问题,改为按实际安装布局探测存在的路径。🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
go test ./...go test ./modelcd web/default && bunx oxlint src/features/dashboard/components/channels/channel-analytics.tsx src/features/dashboard/index.tsx src/hooks/use-sidebar-data.ts src/hooks/use-sidebar-config.tscd web/default && bun run typecheckcd web/default && bun run buildcd web/classic && bun run buildt(...)key 在 en/zh/fr/ru/ja/vi 中均已覆盖,且 locale JSON 无根层级漏写 key。Summary by CodeRabbit
New Features
Bug Fixes