feat: monitor button
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Space } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
export interface WorkerRightActionsProps {
|
||||
handleDeleteByBatch: () => void;
|
||||
handleClickPrimary?: () => void;
|
||||
MonitorButton?: React.ReactNode;
|
||||
rowSelection: {
|
||||
selectedRowKeys: React.Key[];
|
||||
};
|
||||
}
|
||||
|
||||
const WorkerRightActions: React.FC<WorkerRightActionsProps> = ({
|
||||
handleDeleteByBatch,
|
||||
handleClickPrimary,
|
||||
rowSelection,
|
||||
MonitorButton
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<Space size={16}>
|
||||
{MonitorButton}
|
||||
<Button
|
||||
icon={<PlusOutlined />}
|
||||
type="primary"
|
||||
onClick={handleClickPrimary}
|
||||
>
|
||||
{intl.formatMessage({ id: 'resources.button.create' })}
|
||||
</Button>
|
||||
<Button
|
||||
icon={<DeleteOutlined />}
|
||||
danger
|
||||
onClick={handleDeleteByBatch}
|
||||
disabled={!rowSelection?.selectedRowKeys?.length}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'common.button.delete' })}
|
||||
{rowSelection?.selectedRowKeys?.length > 0 && (
|
||||
<span>({rowSelection?.selectedRowKeys?.length})</span>
|
||||
)}
|
||||
</span>
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
};
|
||||
|
||||
export default WorkerRightActions;
|
||||
@@ -25,6 +25,7 @@ import useWorkerColumns from '../hooks/use-worker-columns';
|
||||
import useWorkerMaintenance from '../hooks/use-worker-maintenance';
|
||||
import UpdateLabels from './update-labels';
|
||||
import WorkerDetailModal from './worker-detail-modal';
|
||||
import WorkerRightActions from './worker-right-actions';
|
||||
|
||||
const Workers: React.FC<{
|
||||
clusterId?: string | number | null;
|
||||
@@ -65,7 +66,10 @@ const Workers: React.FC<{
|
||||
cluster_id: clusterId
|
||||
}
|
||||
});
|
||||
const { goToGrafana } = useGranfanaLink({ type: 'worker' });
|
||||
const { goToGrafana, ActionButton } = useGranfanaLink({
|
||||
type: 'worker',
|
||||
dataList: dataSource.dataList || []
|
||||
});
|
||||
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
|
||||
useWorkerMaintenance({ fetchData: handleSearch });
|
||||
|
||||
@@ -268,11 +272,19 @@ const Workers: React.FC<{
|
||||
handleDeleteByBatch={handleDeleteBatch}
|
||||
handleSearch={handleSearch}
|
||||
handleSelectChange={handleClusterChange}
|
||||
handleClickPrimary={showAddButton ? handleOnAddWorker : undefined}
|
||||
handleClickPrimary={handleOnAddWorker}
|
||||
handleInputChange={handleNameChange}
|
||||
rowSelection={rowSelection}
|
||||
selectOptions={clusterData.list}
|
||||
widths={widths}
|
||||
right={
|
||||
<WorkerRightActions
|
||||
handleDeleteByBatch={handleDeleteBatch}
|
||||
handleClickPrimary={handleOnAddWorker}
|
||||
rowSelection={rowSelection}
|
||||
MonitorButton={ActionButton()}
|
||||
></WorkerRightActions>
|
||||
}
|
||||
></FilterBar>
|
||||
<ConfigProvider renderEmpty={renderEmpty}>
|
||||
<Table
|
||||
|
||||
@@ -223,8 +223,7 @@ const setWorkerIPArg = (params: any) => {
|
||||
|
||||
const setImageArgs = (params: any) => {
|
||||
return `${params.image} \\
|
||||
--server-url ${params.server} \\
|
||||
${generateExtraArgs(params)}`;
|
||||
--server-url ${params.server} \\`;
|
||||
};
|
||||
|
||||
// avaliable for NVIDIA、MThreads
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import { GPUSTACK_API_BASE_URL } from '@/config/settings';
|
||||
|
||||
// 1. /grafana/d/gpustack-model/gpustack-model
|
||||
// 2. /grafana/d/gpustack-worker/gpustack-worker
|
||||
const useGranfanaLink = (options: {
|
||||
type: 'model' | 'worker' | 'instance';
|
||||
}) => {
|
||||
const goToModelGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/models/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToWorkerGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/workers/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToInstanceGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/model-instances/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToGrafana = (row: { id: number }) => {
|
||||
if (options.type === 'model') {
|
||||
goToModelGrafana(row);
|
||||
} else if (options.type === 'worker') {
|
||||
goToWorkerGrafana(row);
|
||||
} else if (options.type === 'instance') {
|
||||
goToInstanceGrafana(row);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
goToGrafana
|
||||
};
|
||||
};
|
||||
|
||||
export default useGranfanaLink;
|
||||
@@ -0,0 +1,81 @@
|
||||
import { systemConfigAtom } from '@/atoms/system';
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { GPUSTACK_API_BASE_URL } from '@/config/settings';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button } from 'antd';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
||||
const useGranfanaLink = (options: {
|
||||
type: 'model' | 'worker' | 'instance' | 'cluster';
|
||||
dataList: any[];
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const systemConfig = useAtomValue(systemConfigAtom);
|
||||
|
||||
const goToModelGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/models/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToWorkerGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/workers/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToInstanceGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/model-instances/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToClusterGrafana = (row: { id: number }) => {
|
||||
window.open(
|
||||
`/${GPUSTACK_API_BASE_URL}/clusters/${row.id}/dashboard`,
|
||||
'_blank'
|
||||
);
|
||||
};
|
||||
|
||||
const goToGrafana = (row: { id: number }) => {
|
||||
if (options.type === 'model') {
|
||||
goToModelGrafana(row);
|
||||
} else if (options.type === 'worker') {
|
||||
goToWorkerGrafana(row);
|
||||
} else if (options.type === 'instance') {
|
||||
goToInstanceGrafana(row);
|
||||
} else if (options.type === 'cluster') {
|
||||
goToClusterGrafana(row);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
if (options.dataList?.length > 0) {
|
||||
goToGrafana(options.dataList?.[0]);
|
||||
}
|
||||
};
|
||||
|
||||
const ActionButton = () => {
|
||||
if (systemConfig?.showMonitoring) {
|
||||
return (
|
||||
<Button
|
||||
onClick={handleClick}
|
||||
icon={<IconFont type="icon-metrics" style={{ fontSize: 16 }} />}
|
||||
>
|
||||
{intl.formatMessage({ id: 'resources.metrics.details' })}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return {
|
||||
goToGrafana,
|
||||
ActionButton
|
||||
};
|
||||
};
|
||||
|
||||
export default useGranfanaLink;
|
||||
@@ -1,3 +1,4 @@
|
||||
import { systemConfigAtom } from '@/atoms/system';
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import DropdownButtons from '@/components/drop-down-buttons';
|
||||
import IconFont from '@/components/icon-font';
|
||||
@@ -18,6 +19,7 @@ import {
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Tooltip } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import _ from 'lodash';
|
||||
import { useMemo } from 'react';
|
||||
import styled from 'styled-components';
|
||||
@@ -83,21 +85,6 @@ const ActionList = [
|
||||
}
|
||||
];
|
||||
|
||||
const setActions = (row: ListItem) => {
|
||||
return ActionList.filter((action) => {
|
||||
if (action.key === 'download_ssh_key') {
|
||||
return !!row.ssh_key_id;
|
||||
}
|
||||
if (action.key === 'star_maintenance') {
|
||||
return !row.maintenance?.enabled;
|
||||
}
|
||||
if (action.key === 'stop_maintenance') {
|
||||
return row.maintenance?.enabled;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
const fieldList = [
|
||||
{
|
||||
label: 'resources.table.total',
|
||||
@@ -252,6 +239,7 @@ const useWorkerColumns = ({
|
||||
handleSelect: (action: string, record: ListItem) => void;
|
||||
}): ColumnsType<ListItem> => {
|
||||
const intl = useIntl();
|
||||
const systemConfig = useAtomValue(systemConfigAtom);
|
||||
|
||||
const renderIP = (text: string, record: ListItem) => {
|
||||
if (record.advertise_address === record.ip) {
|
||||
@@ -277,6 +265,25 @@ const useWorkerColumns = ({
|
||||
return record.ip || record.advertise_address || '';
|
||||
};
|
||||
|
||||
const setActions = (row: ListItem) => {
|
||||
return ActionList.filter((action) => {
|
||||
if (action.key === 'download_ssh_key') {
|
||||
return !!row.ssh_key_id;
|
||||
}
|
||||
if (action.key === 'star_maintenance') {
|
||||
return !row.maintenance?.enabled;
|
||||
}
|
||||
if (action.key === 'stop_maintenance') {
|
||||
return row.maintenance?.enabled;
|
||||
}
|
||||
|
||||
if (action.key === 'metrics') {
|
||||
return systemConfig.showMonitoring;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
return useMemo<ColumnsType<ListItem>>(
|
||||
() => [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user