buildTrendSeries overwrote a (label, bucket) value on collision. Should two
backend groups ever map to the same display label, their values must add up
rather than letting the last write win. Accumulate instead.
Instance Types are grouped by actual shape now, so each row/series is one
concrete type. Label them accordingly via a shared instanceTypeSeriesLabel,
used by both the table column and the trend legend so they read identically:
GPU shows "<product> x <cards>", CPU shows "CPU Only · N vCPU · M GB" (the
instance's real size, not the bare "CPU Only" + hover tooltip). The Instances
tab also uses the per-instance cpu/mem totals, so a 3c6g instance of a 1c2g
flavor reads 3c6g instead of 1c2g. flatten carries cpu_milli/memory_mib/
gpu_count from the breakdown dimensions.
flattenItem receives the unmapped frontend dimension; the instance-type
grouping is 'gpu_type' (mapped to backend 'instance_type' via GROUP_BY_MAP),
so the previous 'instance_type' check never matched and the trend legend kept
showing the raw flavor slug. Check 'gpu_type'. (PR #1240 review)
The grouped-trend legend used the raw group key, which for instance_type is
the flavor slug (e.g. gpustack--generic-ln-x64-40c-160g--nvidia-a100-80g-4d).
Prefer the enriched product name so the chart legend matches the GPU Instances
list (#5700); falls back to the slug for legacy rows without dimension data.
Trend charts and breakdown exports need the complete date series. The old
perPage=10000 workaround (and the missing page param on the token trend,
which fell back to perPage=20) dropped low-traffic — often most recent —
buckets, leaving gaps in the charts (#5690).
Send page=-1 (the backend's no-pagination sentinel) for the token trend,
the storage/instances trend charts and table exports, the resource export
dialog, and the summary-tab date trends.
The Last Active column had no renderer, so it dumped the raw ISO timestamp
(gpustack/gpustack#5523). It's a UTC instant (max bucket hour), so format it
to the user's local time with dayjs — matching the Resource Events time
column and the rest of the product. (Token Last Active is a daily date, not
an instant, so it stays a plain date with no timezone shift.)
The legend renders at the chart bottom (bottom: 0); with the default grid
(bottom: 8) it overlapped the date labels once a group-by split the trend
into multiple series. Reserve grid bottom space (matching the Tokens trend)
whenever a legend is shown.
Mirror the Tokens trend: add a clearable "Group by" select to the
MetricChartCard so the GPU Instances chart can split by instance type /
instance / user, and Storage by storage / user. When grouped, the chart
fetches group_by=["date", "<dim>"] (the same list style as the token usage
API) and pivots into one stacked series per group (shared buildTrendSeries
util), with a legend; ungrouped stays a single series. group_by is now a
list across the resource breakdown client; group-by options reuse the
bottom-table dimensions (Users only when org-wide).
- Event type: trim the dropdown to the four types that are actually emitted
(Created / Started / Stopped / Deleted) — updated/attached/detached were
never recorded — and actually send the selection (event_types) to the API,
which previously dropped it so the filter did nothing.
- Add a resource-name text filter (debounced, case-insensitive substring).
- Remove the "filter by user" select: the events list has no User column.
Scope still applies (members see only their own events).
Add the Usage page with Summary / Tokens / GPU Instances / Storage / Resource
Events tabs over the new metering endpoints: per-resource breakdowns with
date / scope / user / resource filters, trend charts, server-side sortable
tables (GPU-Hours, Instance-Hours, GB-Days, GB-Hours), Excel export with an
in-dialog preview, and KPI cards with help tooltips explaining each metric.
MaaS-only users (no Kubernetes cluster and no resource events) get a
tokens-only view with the tab bar dropped; GPU Service / the full page unlock
for admins, cluster owners, or anyone who has run a resource. Instance-type
rows reuse the GPU Instances list styling, and deleted users / instances /
volumes are flagged in breakdowns and filters.
Replace the raw flavor slug in the GPU Instances list with the product name
("<product> x <count>") plus an info-icon popover that breaks the spec down by
category (GPU / CPU / Memory / Disk): per-card VRAM, whole-instance CPU/RAM,
system / ephemeral / persistent disks (persistent size resolved from the
referenced PV). Extract the cell into a shared InstanceTypeCell and centralize
memory formatting in formatMemoryDisplay so the GPU Instances list and the
Usage tab render identical sizes.
`${values.spec?.resources?.cpu}` turned an unset cpu into the literal
string "undefined", which fails k8s quantity validation. Omit cpu when
it has no value instead.
- bar-chart: barMinWidth so hour-granularity bars stay visible with gaps.
- pie-chart: single legend-beside-pie layout, value (percent%) tooltip,
2-decimal rounding for the Summary donut.
The data layer the resource tabs build on:
- apis/resource.ts: adapter over the unified metered_usage read API
(resource/gpu-instances/storage/summary/events breakdowns), flattening
the server's generic shape into the per-tab item shape.
- hooks/use-resource-meta.ts: loads creators/instances/volumes filter
options for the current scope.
- utils/time-buckets.ts: day/week/month/hour bucket keys + range fill.
- utils/export-breakdown.ts: derive Excel columns from antd table specs.