diff --git a/src/components/icon-font/icons.ts b/src/components/icon-font/icons.ts
index 9f84e967..d1678570 100644
--- a/src/components/icon-font/icons.ts
+++ b/src/components/icon-font/icons.ts
@@ -64,7 +64,8 @@ const icons = {
StarOutlined: React.createElement(StarOutlined),
Charger: React.createElement(IconFont, { type: 'icon-charger' }),
Disabled: React.createElement(IconFont, { type: 'icon-disabled' }),
- CopyOutlined: React.createElement(CopyOutlined)
+ CopyOutlined: React.createElement(CopyOutlined),
+ Metrics: React.createElement(IconFont, { type: 'icon-metrics' })
};
export default icons;
diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx
index fb4f8e9e..5b93627b 100644
--- a/src/components/icon-font/index.tsx
+++ b/src/components/icon-font/index.tsx
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
// import './iconfont/iconfont.js';
const IconFont = createFromIconfontCN({
- scriptUrl: '//at.alicdn.com/t/c/font_4613488_lqs6kytf9t8.js'
+ scriptUrl: '//at.alicdn.com/t/c/font_4613488_n2otiiv2h4s.js'
});
export default IconFont;
diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts
index 2eb633e7..26c023b7 100644
--- a/src/locales/en-US/resources.ts
+++ b/src/locales/en-US/resources.ts
@@ -106,5 +106,6 @@ export default {
'resources.worker.maintenance.tips':
'When enter the maintenance mode, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
- 'No available clusters. Please create a cluster before adding a node.'
+ 'No available clusters. Please create a cluster before adding a node.',
+ 'resources.metrics.details': 'Metrics Details'
};
diff --git a/src/locales/ja-JP/resources.ts b/src/locales/ja-JP/resources.ts
index 3020e30c..5a9b3b52 100644
--- a/src/locales/ja-JP/resources.ts
+++ b/src/locales/ja-JP/resources.ts
@@ -107,7 +107,8 @@ export default {
'resources.worker.maintenance.tips':
'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
- 'No available clusters. Please create a cluster before adding a node.'
+ 'No available clusters. Please create a cluster before adding a node.',
+ 'resources.metrics.details': 'Metrics Details'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
diff --git a/src/locales/ru-RU/resources.ts b/src/locales/ru-RU/resources.ts
index 2a10de85..ff8f2294 100644
--- a/src/locales/ru-RU/resources.ts
+++ b/src/locales/ru-RU/resources.ts
@@ -105,7 +105,8 @@ export default {
'resources.worker.maintenance.tips':
'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
'resources.worker.noCluster.tips':
- 'No available clusters. Please create a cluster before adding a node.'
+ 'No available clusters. Please create a cluster before adding a node.',
+ 'resources.metrics.details': 'Metrics Details'
};
// ========== To-Do: Translate Keys (Remove After Translation) ==========
@@ -115,5 +116,6 @@ export default {
// 5. 'resources.worker.maintenance.remark': 'Remark',
// 6. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks',
// 7. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.',
-// 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.'
+// 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.',
+// 9. 'resources.metrics.details': 'Metrics Details'
// ========== End of To-Do List ==========
diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts
index 59425b90..44a0469a 100644
--- a/src/locales/zh-CN/resources.ts
+++ b/src/locales/zh-CN/resources.ts
@@ -102,5 +102,6 @@ export default {
'resources.worker.maintenance.remark.rules': '请输入维护备注',
'resources.worker.maintenance.tips':
'进入维护模式后,节点将停止调度新的模型实例部署任务,正在运行的实例不会受到影响。',
- 'resources.worker.noCluster.tips': '当前无可用集群,请先创建集群再添加节点。'
+ 'resources.worker.noCluster.tips': '当前无可用集群,请先创建集群再添加节点。',
+ 'resources.metrics.details': '监控详情'
};
diff --git a/src/pages/llmodels/components/instance-item.tsx b/src/pages/llmodels/components/instance-item.tsx
index 15fdc65b..5592903d 100644
--- a/src/pages/llmodels/components/instance-item.tsx
+++ b/src/pages/llmodels/components/instance-item.tsx
@@ -11,6 +11,7 @@ import { HandlerOptions } from '@/hooks/use-chunk-fetch';
import useDownloadStream from '@/hooks/use-download-stream';
import { useBenchmarkTargetInstance } from '@/pages/llmodels/hooks/use-run-benchmark';
import { ListItem as WorkerListItem } from '@/pages/resources/config/types';
+import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
import { convertFileSize } from '@/utils';
import {
DeleteOutlined,
@@ -327,6 +328,12 @@ const childActionList = [
],
icon:
},
+ {
+ label: 'resources.metrics.details',
+ key: 'metrics',
+ status: [InstanceStatusMap.Running],
+ icon:
+ },
{
label: 'common.button.downloadLog',
key: 'download',
@@ -428,6 +435,7 @@ const InstanceItem: React.FC = ({
defaultOpenId,
handleChildSelect
}) => {
+ const { goToGrafana } = useGranfanaLink({ type: 'instance' });
const { runBenchmarkOnInstance } = useBenchmarkTargetInstance();
const [api, contextHolder] = notification.useNotification({
stack: { threshold: 1 }
@@ -689,6 +697,8 @@ const InstanceItem: React.FC = ({
filename: createFileName(instanceData.name),
downloadNotification
});
+ } else if (val === 'metrics') {
+ goToGrafana(instanceData);
} else {
handleChildSelect(val, instanceData);
}
diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx
index cab036dc..a7319b87 100644
--- a/src/pages/llmodels/components/table-list.tsx
+++ b/src/pages/llmodels/components/table-list.tsx
@@ -9,7 +9,6 @@ import SealTable from '@/components/seal-table';
import { TableOrder } from '@/components/seal-table/types';
import { PageAction } from '@/config';
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
-import { PageActionType } from '@/config/types';
import useBodyScroll from '@/hooks/use-body-scroll';
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
import useTableRowSelection from '@/hooks/use-table-row-selection';
@@ -18,6 +17,7 @@ import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
import { TargetStatusValueMap } from '@/pages/model-routes/config';
import useOpenPlayground from '@/pages/model-routes/hooks/use-open-playground';
import useQueryTargets from '@/pages/model-routes/services/use-query-targets';
+import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
import { handleBatchRequest } from '@/utils';
import { DownOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons';
import { useIntl, useNavigate, useSearchParams } from '@umijs/max';
@@ -170,6 +170,9 @@ const Models: React.FC = ({
useEffect(() => {
fetchTargets({});
}, []);
+ const { goToGrafana } = useGranfanaLink({
+ type: 'model'
+ });
const [openLogModal, setOpenLogModal] = useState(false);
const [openDeployModal, setOpenDeployModal] = useState<{
@@ -451,6 +454,9 @@ const Models: React.FC = ({
name: targetRoute?.route_name || ''
});
}
+ if (val === 'metrics') {
+ goToGrafana(row);
+ }
} catch (error) {
// ignore
}
diff --git a/src/pages/llmodels/config/button-actions.ts b/src/pages/llmodels/config/button-actions.ts
index c3685c45..ba4a170e 100644
--- a/src/pages/llmodels/config/button-actions.ts
+++ b/src/pages/llmodels/config/button-actions.ts
@@ -39,6 +39,11 @@ export const ActionList: ActionItem[] = [
key: 'edit',
icon: icons.EditOutlined
},
+ {
+ label: 'resources.metrics.details',
+ key: 'metrics',
+ icon: icons.Metrics
+ },
{
label: 'models.openinplayground',
key: 'chat',
diff --git a/src/pages/llmodels/index.tsx b/src/pages/llmodels/index.tsx
index 4f3e5a9b..aaedc70a 100644
--- a/src/pages/llmodels/index.tsx
+++ b/src/pages/llmodels/index.tsx
@@ -35,7 +35,6 @@ const Models: React.FC<{ clusterId?: number }> = ({ clusterId }) => {
loadend: false,
total: 0
});
-
const chunkRequedtRef = useRef();
const chunkInstanceRequedtRef = useRef();
const isPageHidden = useRef(false);
diff --git a/src/pages/resources/components/workers.tsx b/src/pages/resources/components/workers.tsx
index 0d0d1b5e..33c07524 100644
--- a/src/pages/resources/components/workers.tsx
+++ b/src/pages/resources/components/workers.tsx
@@ -8,6 +8,7 @@ import { DockerStepsFromWorker } from '@/pages/cluster-management/components/add
import { ClusterListItem } from '@/pages/cluster-management/config/types';
import useAddWorker from '@/pages/cluster-management/hooks/use-add-worker';
import useNoResourceResult from '@/pages/llmodels/hooks/use-no-resource-result';
+import useGranfanaLink from '@/pages/resources/hooks/use-grafana-link';
import { useIntl } from '@umijs/max';
import { useMemoizedFn } from 'ahooks';
import { ConfigProvider, Table, message } from 'antd';
@@ -20,7 +21,6 @@ import {
updateWorker
} from '../apis';
import { ListItem } from '../config/types';
-import useTerminalTabs from '../hooks/use-terminal-tabs';
import useWorkerColumns from '../hooks/use-worker-columns';
import useWorkerMaintenance from '../hooks/use-worker-maintenance';
import UpdateLabels from './update-labels';
@@ -65,7 +65,7 @@ const Workers: React.FC<{
cluster_id: clusterId
}
});
- const { TerminalPanel, terminals, handleAddTerminal } = useTerminalTabs();
+ const { goToGrafana } = useGranfanaLink({ type: 'worker' });
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
useWorkerMaintenance({ fetchData: handleSearch });
@@ -199,9 +199,8 @@ const Workers: React.FC<{
if (val === 'stop_maintenance') {
handleStopMaintenance(record);
}
-
- if (val === 'terminal') {
- handleAddTerminal(record);
+ if (val === 'metrics') {
+ goToGrafana(record);
}
});
diff --git a/src/pages/resources/hooks/use-grafana-link.ts b/src/pages/resources/hooks/use-grafana-link.ts
new file mode 100644
index 00000000..21eacf70
--- /dev/null
+++ b/src/pages/resources/hooks/use-grafana-link.ts
@@ -0,0 +1,42 @@
+import { GPUSTACK_API_BASE_URL } from '@/config/settings';
+
+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;
diff --git a/src/pages/resources/hooks/use-worker-columns.tsx b/src/pages/resources/hooks/use-worker-columns.tsx
index 32b43745..28068958 100644
--- a/src/pages/resources/hooks/use-worker-columns.tsx
+++ b/src/pages/resources/hooks/use-worker-columns.tsx
@@ -1,5 +1,6 @@
import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons';
+import IconFont from '@/components/icon-font';
import LabelsCell from '@/components/label-cell';
import ProgressBar from '@/components/progress-bar';
import InfoColumn from '@/components/simple-table/info-column';
@@ -42,6 +43,11 @@ const IPWrapper = styled.span`
const ActionList = [
{ label: 'common.button.edit', key: 'edit', icon: },
+ {
+ label: 'resources.metrics.details',
+ key: 'metrics',
+ icon:
+ },
// {
// label: 'common.button.detail',
// key: 'details',