feat: logs history
This commit is contained in:
@@ -152,6 +152,11 @@ export async function queryModelInstanceLogs(id: number) {
|
||||
method: 'GET'
|
||||
});
|
||||
}
|
||||
export async function queryModelInstanceRestartCount(id: number) {
|
||||
return request(`${MODEL_INSTANCE_API}/${id}/log-options`, {
|
||||
method: 'GET'
|
||||
});
|
||||
}
|
||||
|
||||
// ===================== Model Instances end =====================
|
||||
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
||||
import { LogsViewer } from '@gpustack/core-ui';
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import { BaseSelect, LogsViewer } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Modal } from 'antd';
|
||||
import { Button, Modal } from 'antd';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { MODELS_API } from '../apis';
|
||||
|
||||
import { InstanceRealtimeLogStatus, InstanceStatusMap } from '../config';
|
||||
import useQueryModelInstanceRestartCount from '../services/use-query-instance-restart-count';
|
||||
|
||||
type ViewModalProps = {
|
||||
open: boolean;
|
||||
url: string;
|
||||
id?: number | string;
|
||||
id?: number;
|
||||
modelId?: number | string;
|
||||
tail?: number;
|
||||
status?: string;
|
||||
@@ -24,7 +27,12 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
|
||||
const [isDownloading, setIsDownloading] = useState<boolean>(
|
||||
status === InstanceStatusMap.Downloading
|
||||
);
|
||||
const [params, setParams] = useState<any>({
|
||||
follow: true
|
||||
});
|
||||
const logsViewerRef = React.useRef<any>(null);
|
||||
const { countOptions, fetchData, cancelRequest } =
|
||||
useQueryModelInstanceRestartCount();
|
||||
const requestRef = React.useRef<any>(null);
|
||||
const contentRef = React.useRef<any>(null);
|
||||
|
||||
@@ -68,6 +76,82 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
const cancelOnClose = () => {
|
||||
logsViewerRef.current?.abort();
|
||||
requestRef.current?.current?.cancel?.();
|
||||
cancelRequest();
|
||||
};
|
||||
|
||||
const handleOnChange = (value: number, option: any) => {
|
||||
if (!option) {
|
||||
setParams({
|
||||
follow: true
|
||||
});
|
||||
} else {
|
||||
setParams({
|
||||
follow: true,
|
||||
watch: false,
|
||||
restart_count: option.value,
|
||||
worker_id: option.worker_id
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const renderTitle = () => {
|
||||
return (
|
||||
<span className="flex-between flex-center gap-16">
|
||||
<span style={{ fontWeight: 'var(--font-weight-bold)' }}>
|
||||
{intl.formatMessage({ id: 'common.button.viewlog' })}
|
||||
</span>
|
||||
<span>
|
||||
<BaseSelect
|
||||
allowClear
|
||||
onChange={handleOnChange}
|
||||
prefix={
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 400,
|
||||
fontSize: 13,
|
||||
marginRight: 8,
|
||||
paddingRight: 8,
|
||||
color: 'var(--ant-color-text-secondary)',
|
||||
borderRight: '1px solid var(--ant-color-split)'
|
||||
}}
|
||||
>
|
||||
{intl.formatMessage({ id: 'models.instance.startHistory' })} (
|
||||
{countOptions.length})
|
||||
</span>
|
||||
}
|
||||
options={countOptions}
|
||||
labelRender={(option) => {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 500,
|
||||
fontSize: 13
|
||||
}}
|
||||
>
|
||||
{option?.label}
|
||||
</span>
|
||||
);
|
||||
}}
|
||||
style={{
|
||||
width: 400,
|
||||
marginRight: 16
|
||||
}}
|
||||
></BaseSelect>
|
||||
<Button
|
||||
type="text"
|
||||
color="default"
|
||||
icon={<CloseOutlined />}
|
||||
onClick={handleCancel}
|
||||
size="middle"
|
||||
></Button>
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (open && props.id) {
|
||||
requestRef.current?.current?.cancel?.();
|
||||
@@ -75,32 +159,24 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
|
||||
url: `${MODELS_API}/${props.modelId}/instances`,
|
||||
handler: updateHandler
|
||||
});
|
||||
fetchData(props.id);
|
||||
} else {
|
||||
logsViewerRef.current?.abort();
|
||||
requestRef.current?.current?.cancel?.();
|
||||
cancelOnClose();
|
||||
}
|
||||
|
||||
return () => {
|
||||
logsViewerRef.current?.abort();
|
||||
requestRef.current?.current?.cancel?.();
|
||||
cancelOnClose();
|
||||
};
|
||||
}, [props.id, open]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={
|
||||
<span className="flex flex-center">
|
||||
<span style={{ fontWeight: 'var(--font-weight-bold)' }}>
|
||||
{' '}
|
||||
{intl.formatMessage({ id: 'common.button.viewlog' })}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
title={renderTitle()}
|
||||
open={open}
|
||||
centered={true}
|
||||
onCancel={handleCancel}
|
||||
destroyOnHidden={true}
|
||||
closeIcon={true}
|
||||
closeIcon={false}
|
||||
mask={{
|
||||
closable: false
|
||||
}}
|
||||
@@ -116,14 +192,12 @@ const ViewLogsModal: React.FC<ViewModalProps> = (props) => {
|
||||
<div className="viewer-wrapper" ref={contentRef}>
|
||||
<LogsViewer
|
||||
ref={logsViewerRef}
|
||||
diffHeight={78}
|
||||
diffHeight={95}
|
||||
url={url}
|
||||
tail={tail}
|
||||
enableScorllLoad={enableScorllLoad}
|
||||
isDownloading={isDownloading}
|
||||
params={{
|
||||
follow: true
|
||||
}}
|
||||
params={params}
|
||||
></LogsViewer>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
@@ -375,3 +375,8 @@ export interface DraftModelItem {
|
||||
name: string;
|
||||
algorithm: string;
|
||||
}
|
||||
|
||||
export interface InstanceRestartCount {
|
||||
restart_counts: number[];
|
||||
workers: { id: number; name: string }[];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { useQueryData } from '@/hooks/use-query-data-list';
|
||||
import { formatOrdinal } from '@/utils';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { useState } from 'react';
|
||||
import { queryModelInstanceRestartCount } from '../apis';
|
||||
import { InstanceRestartCount } from '../config/types';
|
||||
|
||||
export default function useQueryModelInstanceRestartCount() {
|
||||
const { detailData, loading, cancelRequest, fetchData } =
|
||||
useQueryData<InstanceRestartCount>({
|
||||
fetchDetail: queryModelInstanceRestartCount,
|
||||
key: 'modelInstanceRestartCount'
|
||||
});
|
||||
const intl = useIntl();
|
||||
|
||||
const [dataList, setDataList] = useState<
|
||||
{ value: number; label: number | string; worker_id: number }[]
|
||||
>([]);
|
||||
|
||||
const fetchRestartCount = async (instance_id: number) => {
|
||||
const res = await fetchData(instance_id);
|
||||
const workerId = res?.workers?.[0]?.id || 0;
|
||||
const dataList =
|
||||
res?.restart_counts?.map((count, index) => {
|
||||
return {
|
||||
value: count,
|
||||
label:
|
||||
count === 0
|
||||
? intl.formatMessage({ id: 'models.instance.firstStart' })
|
||||
: formatOrdinal(count),
|
||||
worker_id: workerId
|
||||
};
|
||||
}) || [];
|
||||
setDataList(dataList);
|
||||
};
|
||||
return {
|
||||
countOptions: dataList,
|
||||
loading,
|
||||
cancelRequest,
|
||||
fetchData: fetchRestartCount
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user