Skip to content

fix: correct dashboard numbers that misrepresent backend values - #8830

Draft
yomybaby wants to merge 2 commits into
mainfrom
claude/dashboard-numbers-validation-f7g6il
Draft

fix: correct dashboard numbers that misrepresent backend values#8830
yomybaby wants to merge 2 commits into
mainfrom
claude/dashboard-numbers-validation-f7g6il

Conversation

@yomybaby

@yomybaby yomybaby commented Aug 17, 2026

Copy link
Copy Markdown
Member

This PR is the outcome of a systematic audit of every number shown on the dashboard against the backend logic that produces it (REST /resource/check-presets, GraphQL compute_session_nodes / agent_nodes / agent_summary_list, legacy /folders, quota-scope and resource-policy fields). Each fix below addresses a case where the displayed number was objectively wrong relative to what the backend value means.

Fixes

1. "My Sessions" counted other users' sessions for admin/monitor roles

SessionCountDashboardItem queried compute_session_nodes with only a project scope. For UserRole.ADMIN/MONITOR, the backend RBAC grants project-wide read (session/row.py maps them to PredefinedRole.ADMIN), so a domain admin with zero sessions of their own saw other members' sessions under a "My Sessions" title — disagreeing with the session list page, which already applies user_id == <uuid> for exactly this reason (ComputeSessionListPage.tsx:170-172). The counts now merge the same user filter for every non-superadmin role; superadmin keeps the project-wide "Active Sessions" behavior, and AdminDashboardPage is unchanged via fragment-argument defaults.

2. "Project Folders" counted group folders of all projects

The legacy GET /folders list returns group folders of every project the user can see regardless of the group_id param (backend applies it only for RBAC scoping, not filtering). The numerator therefore aggregated across projects while the "/ limit" denominator was per-project. The count is now filtered by item.group === currentProject.id, matching the scoping already documented in this file's TODO(FR-2691 v2-migration) note.

3. Project folder limit looked up by project name instead of the group's policy

project_resource_policy(name: currentProject.name) assumed a policy shares the project's name. In stock deployments projects bind to the "default" policy, so the lookup returned null and the "/ limit" silently disappeared even though max_vfolder_count is enforced; a coincidentally same-named policy would show an unrelated limit. The limit is now resolved via group(id).resource_policyproject_resource_policy(name:).

4. "My Folders N / max" excluded delete-ongoing folders that the enforced limit counts

Backend count_vfolders_by_user excludes only HARD_DELETED_VFOLDER_STATUSES (delete-complete, delete-error); the UI additionally excluded delete-ongoing, so a user at "9 / 10" could get quota-exceeded on creation. Exclusion sets now match.

5. Total Resources panel silently truncated at 100 agents (superadmin)

agent_nodes(first: 100) summed only the first 100 ALIVE schedulable agents while the label claims the whole resource group; raised to 1000 to match the non-admin agent_summary_list(limit: 1000) path.

6. Total Resources "Free" could render negative

Occupied can exceed available when an agent re-registers with shrunken capacity while its kernels keep running; Free (available − occupied) now clamps at 0 for CPU/memory/accelerators.

7. Active Agents card pager was disconnected from the data

AgentList spread {...tableProps} after its own pagination, so ActiveAgents' {pageSize: 3} override wholesale replaced total/current/onChange: all 10 fetched rows rendered, the pager read "1–3 of 10" (rows.length, not agent_nodes.count), and page clicks changed nothing. Pagination is now merged (caller overrides display options; server-paging keys survive) and the override's pageSize seeds the query page size.

8. Accelerator utilization label showed the multi-GPU sum as a percent

The backend node-level *_util value is the sum of per-device utilizations (0..N×100). The bar divided by capacity (correct), but the text label divided by 100 — a fully-loaded 4-GPU agent showed "400 %" next to a full bar. Label now uses the same current/capacity quotient.

9. Net Rx/Tx displayed bytes/sec with a bits/sec unit

Agent net_rx/net_tx rates come from psutil byte counters (MovingStatistics.rate = bytes/sec), but the UI appended "(K|M|G)bps" — an 8× misrepresentation. Label is now "B/s".

10. Quota panel project column truncated small usage to "0 GB"

Fixed 'g' unit conversion turned any nonzero usage under ~5 MB into "0 GB" (the adjacent user column already used 'auto' and showed "4 MB"). Both columns now use 'auto'.

11. "My Total Resource Usage" total now honors the domain limit (with lablup/backend.ai#13788)

The panel tooltip promises the most restrictive of keypair/project/domain limits, but /resource/check-presets carried no domain limits, so the total was min(keypair_limits, group_limits) only — while the free/remaining side does include the domain clamp (final_remaining). The paired manager PR adds domain_limits to the response; this PR merges it into the limit calculation when present, falling back gracefully on older managers.

Verification

  • bash scripts/verify.sh=== ALL PASS === (Relay, Lint, Format, TypeScript, Vite warmup, StyleX, Astryx theme build, Terminology)
  • pnpm --filter backend.ai-ui test → 613 passed, 1 skipped
  • pnpm --filter backend-ai-webui-react test → 1405 passed

Checklist: (if applicable)

  • Documentation
  • Minium required manager version — item 11 requires the paired manager PR (fix(manager): correct check-presets per-sgroup remaining and expose domain limits backend.ai#13788) for the domain-limit total; all other fixes work with any manager. The frontend degrades gracefully (field absent → previous behavior).
  • Specific setting for review (eg., KB link, endpoint or how to setup)
  • Minimum requirements to check during review — semantics of each fix are documented above with the backend evidence.
  • Test case(s) to demonstrate the difference of before/after — covered by existing suites (all green); each fix lists a concrete before/after scenario above.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BEBfA8mPRdhNvLS5pUoHRt

Validated every number shown on the dashboard against the backend logic
that produces it, and fixed the panels whose displayed values were
objectively wrong:

- SessionCountDashboardItem: scope the "My Sessions" counts to the
  requesting user for non-superadmin roles. Domain admins/monitors hold
  project-wide session read permission, so the previous unfiltered counts
  showed every member's sessions under a "My Sessions" title, disagreeing
  with the per-type counters on the session list page (which already
  applies a user_id filter).
- StorageStatusPanelCard: (1) count only the selected project's group
  folders — the legacy /folders list returns group folders of every
  visible project, so "Project Folders" aggregated across projects while
  its "/ limit" denominator was per-project; (2) resolve the project
  vfolder limit through group.resource_policy instead of assuming the
  policy shares the project's name (stock deployments bind projects to
  the "default" policy, so the limit silently never rendered); (3) count
  delete-ongoing folders like the backend's enforced max_vfolder_count
  does (only delete-complete/delete-error are excluded server-side).
- TotalResourceWithinResourceGroup: raise the superadmin agent_nodes page
  cap from 100 to 1000 (matching the non-admin agent_summary_list) so
  groups with >100 agents are no longer silently under-summed, and clamp
  the Free values at 0 — occupied can exceed available when an agent
  re-registers with shrunken capacity while kernels keep running.
- AgentList/ActiveAgents: merge caller pagination overrides instead of
  letting the tableProps spread clobber total/current/onChange. The
  dashboard's Active Agents card rendered all fetched rows while its
  pager showed "1-3 of 10", page clicks did nothing, and the real agent
  count (agent_nodes.count) was never shown.
- BAIAgentTable: divide accelerator utilization labels by capacity
  (device_count x 100) instead of 100 — the backend value is the SUM of
  per-device utilizations, so multi-GPU agents showed e.g. "400 %" next
  to a correctly-scaled bar.
- BAIAgentTable/AgentResources: label Net Rx/Tx as B/s. The backend rate
  is bytes/sec from psutil byte counters; the old "bps" label understated
  traffic 8x.
- QuotaPerStorageVolumePanelCard: use auto unit selection for the project
  quota column like the user column — the fixed "g" unit truncated any
  usage under ~5 MB to "0 GB".
- useResourceLimitAndRemaining/MyResource: include the new domain_limits
  field from /resource/check-presets (when the manager provides it) in
  the merged limit, so the "My Total Resource Usage" total honors the
  domain quota as its own tooltip claims. Falls back gracefully on older
  managers.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEBfA8mPRdhNvLS5pUoHRt
@cla-assistant

cla-assistant Bot commented Aug 17, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

1 similar comment
@cla-assistant

cla-assistant Bot commented Aug 17, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for backend-ai-ui-coverage (./packages/backend.ai-ui)

Status Category Percentage Covered / Total
🔵 Lines 37.55% 3128 / 8330
🔵 Statements 32.04% 3506 / 10942
🔵 Functions 35.12% 628 / 1788
🔵 Branches 23.62% 2450 / 10369
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/backend.ai-ui/src/components/fragments/BAIAgentTable.tsx 4.48% 0% 5% 6.84% 62, 67-72, 93-104, 240-493, 496-506, 527-532, 596-783
Generated in workflow #4020 for commit 577c3c3 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 14.5% 4859 / 33502
🔵 Statements 12.24% 5900 / 48184
🔵 Functions 11.7% 724 / 6186
🔵 Branches 9.09% 4183 / 46002
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/AgentList.tsx 0% 0% 0% 0% 54-305
react/src/components/QuotaPerStorageVolumePanelCard.tsx 0% 0% 0% 0% 53-245
react/src/components/SessionCountDashboardItem.tsx 0% 0% 0% 0% 26-111
react/src/components/StorageStatusPanelCard.tsx 0% 0% 0% 0% 33-213
react/src/components/TotalResourceWithinResourceGroup.tsx 3.84% 0% 0% 4% 52-60, 66-353
react/src/components/AgentNodeItems/AgentResources.tsx 0% 0% 0% 0% 33-406
react/src/hooks/useResourceLimitAndRemaining.tsx 68.96% 51.28% 55.55% 71.42% 31, 179, 185, 232-255, 282, 354-385, 402-415, 459-464
react/src/pages/DashboardPage.tsx 0% 0% 0% 0% 42-401
Generated in workflow #4020 for commit 577c3c3 by the Vitest Coverage Report Action

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

Labels

size:XL 500~ LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants