135 lines
4.6 KiB
TypeScript
135 lines
4.6 KiB
TypeScript
import {
|
|
buildInstanceTypeRecordFromMiB,
|
|
renderInstanceType
|
|
} from '@/pages/gpu-service/instances/utils/render-instance-type';
|
|
import { useIntl } from '@umijs/max';
|
|
import { useMemo } from 'react';
|
|
import { ResourceBreakdownItem } from '../../apis/resource';
|
|
import { instanceTypeLabel } from '../../utils/format-instance-type';
|
|
import { parseRollup } from '../../utils/time-buckets';
|
|
|
|
type GroupKey = 'gpu_type' | 'instance' | 'user';
|
|
|
|
/**
|
|
* Column factory for the GPU-instances breakdown tables, shared by the in-tab
|
|
* table and the export preview. Columns adapt to the active grouping. Sort
|
|
* indicators are uncontrolled (antd manages the header arrows); the table
|
|
* reports changes through its `onChange`.
|
|
*/
|
|
const useInstancesColumns = (groupKey: GroupKey) => {
|
|
const intl = useIntl();
|
|
|
|
return useMemo(() => {
|
|
const baseValueCols = [
|
|
{
|
|
title: intl.formatMessage({ id: 'usage.metric.gpuHours' }),
|
|
dataIndex: 'gpu_hours',
|
|
key: 'gpu_hours',
|
|
sorter: true,
|
|
render: (v: number) => (v ?? 0).toFixed(2)
|
|
},
|
|
{
|
|
title: intl.formatMessage({ id: 'usage.metric.instanceHours' }),
|
|
dataIndex: 'instance_hours',
|
|
key: 'instance_hours',
|
|
sorter: true,
|
|
render: (v: number) => (v ?? 0).toFixed(2)
|
|
}
|
|
];
|
|
// Instance Types breakdown: the pretty product name (or flavor slug for
|
|
// older rows; "CPU Only" when no GPU cards) plus a CPU + RAM spec popover —
|
|
// rendered through the canonical renderer so the formatting matches the GPU
|
|
// Instances list, but limited to the CPU/RAM categories.
|
|
const instanceTypeColType = {
|
|
title: intl.formatMessage({ id: 'usage.table.instanceType' }),
|
|
dataIndex: 'gpu_type',
|
|
key: 'gpu_type',
|
|
render: (_v: string, row: ResourceBreakdownItem) =>
|
|
renderInstanceType(
|
|
buildInstanceTypeRecordFromMiB({
|
|
name: row.instance_name,
|
|
product: row.product || row.gpu_type,
|
|
gpuCount: row.gpu_count,
|
|
unitCpuMilli: row.unit_cpu_milli,
|
|
unitMemoryMib: row.unit_memory_mib,
|
|
vramMib: row.vram_mib
|
|
}),
|
|
{
|
|
intl,
|
|
categories: ['cpu', 'ram'],
|
|
title:
|
|
(row.gpu_count ?? 0) > 0 ? instanceTypeLabel(row) : 'CPU Only'
|
|
}
|
|
)
|
|
};
|
|
// Instances breakdown: render through the canonical GPU Instances list
|
|
// renderer so the label + spec popover are identical. The breakdown row
|
|
// carries flat MiB fields, so adapt it into the ListItem shape first.
|
|
const instanceTypeColInstance = {
|
|
title: intl.formatMessage({ id: 'usage.table.instanceType' }),
|
|
dataIndex: 'gpu_type',
|
|
key: 'gpu_type',
|
|
render: (_v: string, row: ResourceBreakdownItem) =>
|
|
renderInstanceType(
|
|
buildInstanceTypeRecordFromMiB({
|
|
name: row.instance_name,
|
|
product: row.product || row.gpu_type,
|
|
gpuCount: row.gpu_count,
|
|
unitCpuMilli: row.unit_cpu_milli,
|
|
unitMemoryMib: row.unit_memory_mib,
|
|
vramMib: row.vram_mib,
|
|
localStorageMib: row.local_storage_mib,
|
|
ephemeralMib: row.ephemeral_mib,
|
|
persistentMib: row.persistent_mib
|
|
}),
|
|
{ intl }
|
|
)
|
|
};
|
|
// Last Active = the last active day. The backend sends a rollup-tz instant
|
|
// with its offset; parseRollup keeps that wall clock (no browser-tz convert),
|
|
// consistent with the trend chart buckets. Shown date-only.
|
|
const lastActiveCol = {
|
|
title: intl.formatMessage({ id: 'usage.table.lastActive' }),
|
|
dataIndex: 'last_active',
|
|
key: 'last_active',
|
|
render: (v?: string) => (v ? parseRollup(v).format('YYYY-MM-DD') : '-')
|
|
};
|
|
if (groupKey === 'gpu_type') {
|
|
return [
|
|
instanceTypeColType,
|
|
...baseValueCols,
|
|
{
|
|
title: intl.formatMessage({ id: 'usage.metric.activeInstances' }),
|
|
dataIndex: 'active_instances',
|
|
key: 'active_instances'
|
|
},
|
|
lastActiveCol
|
|
];
|
|
}
|
|
if (groupKey === 'instance') {
|
|
return [
|
|
{
|
|
title: intl.formatMessage({ id: 'usage.table.instance' }),
|
|
dataIndex: 'instance_name',
|
|
key: 'instance_name'
|
|
},
|
|
instanceTypeColInstance,
|
|
...baseValueCols,
|
|
lastActiveCol
|
|
];
|
|
}
|
|
// user tab
|
|
return [
|
|
{
|
|
title: intl.formatMessage({ id: 'usage.table.user' }),
|
|
dataIndex: 'user_name',
|
|
key: 'user_name'
|
|
},
|
|
...baseValueCols,
|
|
lastActiveCol
|
|
];
|
|
}, [groupKey, intl]);
|
|
};
|
|
|
|
export default useInstancesColumns;
|