Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -621,5 +621,17 @@
"External Access Domain": "External Access Domain",
"Failed to load task logs": "Failed to load task logs",
"Retry loading logs": "Retry loading logs",
"WorkLoad": "WorkLoad"
"WorkLoad": "WorkLoad",
"Log read failed; current content is preserved": "Log read failed; current content is preserved",
"Operation read failed": "Operation read failed",
"Task read failed; current content is preserved": "Task read failed; current content is preserved",
"Execution logs": "Execution logs",
"No log output yet": "No log output yet",
"Execution failed": "Execution failed",
"Task message": "Task message",
"Succeeded": "Succeeded",
"Running": "Running",
"Pending": "Pending",
"TimedOut": "TimedOut",
"Canceled": "Canceled"
}
14 changes: 13 additions & 1 deletion src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -621,5 +621,17 @@
"External Access Domain": "外部访问域名",
"Failed to load task logs": "任务日志加载失败",
"Retry loading logs": "重新加载日志",
"WorkLoad": "工作负载"
"WorkLoad": "工作负载",
"Log read failed; current content is preserved": "日志读取失败,已保留当前内容",
"Operation read failed": "操作信息读取失败",
"Task read failed; current content is preserved": "任务状态读取失败,已保留当前内容",
"Execution logs": "执行日志",
"No log output yet": "暂无日志输出",
"Execution failed": "执行失败",
"Task message": "任务消息",
"Succeeded": "成功",
"Running": "执行中",
"Pending": "等待执行",
"TimedOut": "已超时",
"Canceled": "已取消"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,58 +22,54 @@ import {
CheckCircleFilled,
CloseCircleFilled,
} from '@ant-design/icons';
import { Alert, Button, Spin } from 'antd';
import { Spin, Button } from 'antd';
import { observer } from 'mobx-react';
import styles from './index.less';
import { useRootStore } from 'stores';
import LogStore from 'stores/log';
import { formatSeconds } from 'utils';
import { useInterval } from 'hooks';

function LogItemContent(props) {
const { isExpand, isLoading, logdata, logError, onRetry } = props;
if (isExpand) {
if (isLoading) {
return <Spin className={styles['spin-center']} />;
} else {
return (
<div className={styles['log-item-content']}>
{logdata && <pre>{logdata}</pre>}
{logError && (
<Alert
type="error"
showIcon
message={t('Failed to load task logs')}
description={logError}
action={
<Button size="small" onClick={onRetry}>
{t('Retry loading logs')}
</Button>
}
/>
)}
</div>
);
}
}
return '';
function LogItemContent({ isExpand, isLoading, logdata }) {
if (!isExpand) return null;
return (
<div className={styles['log-output']}>
<div className={styles['log-output-title']}>{t('Execution logs')}</div>
{isLoading && !logdata ? (
<Spin className={styles['spin-center']} />
) : (
<pre className={styles['log-item-content']}>
{logdata || t('No log output yet')}
</pre>
)}
</div>
);
}

const LogItem = observer((props) => {
const { nodeStatus, taskName, logStore, runtime, nodes, index } = props;
const inputEl = useRef();
const {
nodeStatus,
taskName,
logStore,
runtime,
nodes,
index,
message,
reason,
} = props;
const initiallyExpanded = useRef(index === 0);

const taskFinished = ['Succeeded', 'Failed', 'TimedOut', 'Canceled'].includes(
nodeStatus
);
logStore.isStepFinished = taskFinished;
const {
logdata,
logError,
isExpand,
isLoading,
cumulativeSize,
isStepFinished,
error,
} = logStore;

const stateIcons = (errIgnore, status) => {
Expand All @@ -91,21 +87,27 @@ const LogItem = observer((props) => {
};

useEffect(() => {
if (index === 0 && taskName) {
if (initiallyExpanded.current) logStore.isExpand = true;
return () => logStore.logReset();
}, [taskName, logStore]);

useEffect(() => {
if (logStore.isExpand && taskName) {
const fn = async () => {
await logStore.fetchStepLog(params);
inputEl.current?.scrollIntoView({ block: 'end' });
await logStore.fetchStepLog({
taskName,
offset: logStore.cumulativeSize,
});
};

fn();
}
}, [taskName]);
}, [taskName, nodeStatus, index, logStore]);

useInterval(
() => {
const fn = async () => {
await logStore.fetchStepLog(params);
inputEl.current?.scrollIntoView({ block: 'end' });
};
fn();
},
Expand All @@ -115,30 +117,73 @@ const LogItem = observer((props) => {
const toggleExpand = async () => {
if (!taskName) return;

logStore.isExpand = !isExpand;
if (!isExpand) {
logStore.isExpand = true;
await logStore.getStepLog(params);
logStore.getStepLog(params);
} else {
logStore.logReset();
logStore.isExpand = false;
}
};

const failed = ['Failed', 'TimedOut', 'Canceled'].includes(nodeStatus);
const statusClass = failed
? 'status-failed'
: nodeStatus === 'Succeeded'
? 'status-succeeded'
: 'status-running';

return (
<div className={styles.LogItem} ref={inputEl}>
<div className={classNames(styles.LogItem__title)} onClick={toggleExpand}>
{isExpand ? <CaretDownOutlined /> : <CaretRightOutlined />}
{nodes.ipv4 ? `${nodes.id}(${nodes.ipv4})` : nodes.id}
<div className={styles.LogItem}>
<button
type="button"
className={styles.LogItem__title}
onClick={toggleExpand}
aria-expanded={isExpand}
>
<span className={styles['node-heading']}>
{isExpand ? <CaretDownOutlined /> : <CaretRightOutlined />}
<strong>{nodes.ipv4 || nodes.id}</strong>
{nodes.ipv4 && (
<span className={styles['node-id']} title={nodes.id}>
{nodes.id}
</span>
)}
</span>
<span className={styles.logitem_status}>
<span>{runtime || ''}</span>
{stateIcons(false, nodeStatus)}
<span
className={classNames(styles['status-badge'], styles[statusClass])}
>
{stateIcons(false, nodeStatus)} {t(nodeStatus)}
</span>
{runtime && <span className={styles.runtime}>{runtime}</span>}
</span>
</div>
</button>
{(message || reason) && (
<div role="alert" className={styles['log-item-error']}>
<div className={styles['error-heading']}>
<CloseCircleFilled />{' '}
{t(failed ? 'Execution failed' : 'Task message')}
</div>
<pre>{message || reason}</pre>
</div>
)}
{error && (
<div role="alert" className={styles['log-read-error']}>
<span>
{t('Log read failed; current content is preserved')}: {error}
</span>
<Button
type="link"
size="small"
onClick={() => logStore.getStepLog(params)}
>
{t('Retry loading logs')}
</Button>
</div>
)}
<LogItemContent
isExpand={isExpand}
logdata={logdata}
logError={logError}
onRetry={() => logStore.getStepLog(params)}
isLoading={isLoading}
/>
</div>
Expand Down Expand Up @@ -169,6 +214,8 @@ function RightLogContent() {
key={index}
logStore={logStores.current.get(storeKey)}
nodeStatus={taskStatus.status || 'Pending'}
message={taskStatus.message}
reason={taskStatus.reason}
taskName={taskName}
runtime={
taskStatus.startAt
Expand Down
Loading
Loading