You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@inlong.apache.org by do...@apache.org on 2022/11/11 08:58:10 UTC
[inlong] branch master updated: [INLONG-6504][Dashboard] Support stream to view execution log and execute workflow (#6509)
This is an automated email from the ASF dual-hosted git repository.
dockerzhang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/inlong.git
The following commit(s) were added to refs/heads/master by this push:
new cd23f5caf [INLONG-6504][Dashboard] Support stream to view execution log and execute workflow (#6509)
cd23f5caf is described below
commit cd23f5cafb9e13ada37b2db7727bdeea0be27952
Author: Lizhen <88...@users.noreply.github.com>
AuthorDate: Fri Nov 11 16:58:04 2022 +0800
[INLONG-6504][Dashboard] Support stream to view execution log and execute workflow (#6509)
---
inlong-dashboard/src/locales/cn.json | 3 +
inlong-dashboard/src/locales/en.json | 3 +
.../GroupDetail/DataStream/ExecutionLogModal.tsx | 219 +++++++++++++++++++++
.../src/pages/GroupDetail/DataStream/index.tsx | 50 +++++
4 files changed, 275 insertions(+)
diff --git a/inlong-dashboard/src/locales/cn.json b/inlong-dashboard/src/locales/cn.json
index 60f5a5af0..7be671dba 100644
--- a/inlong-dashboard/src/locales/cn.json
+++ b/inlong-dashboard/src/locales/cn.json
@@ -302,6 +302,9 @@
"meta.Stream.Status.Pending": "配置中",
"meta.Stream.Status.Error": "配置失败",
"meta.Stream.Status.Success": "配置成功",
+ "meta.Stream.ExecuteWorkflow": "执行工作流",
+ "meta.Stream.ExecuteConfirm": "确认执行工作流吗?",
+ "meta.Stream.ExecuteSuccess": "执行成功",
"meta.Consume.ConsumerGroupName": "消费组名称",
"meta.Consume.ConsumerGroupNameRules": "只能包含小写字母、数字、中划线、下划线",
"meta.Consume.TopicName": "Topic名称",
diff --git a/inlong-dashboard/src/locales/en.json b/inlong-dashboard/src/locales/en.json
index fffa3bb68..cc17fd9f9 100644
--- a/inlong-dashboard/src/locales/en.json
+++ b/inlong-dashboard/src/locales/en.json
@@ -302,6 +302,9 @@
"meta.Stream.Status.Pending": "Pending",
"meta.Stream.Status.Error": "Error",
"meta.Stream.Status.Success": "Success",
+ "meta.Stream.ExecuteWorkflow": "ExecuteWorkflow",
+ "meta.Stream.ExecuteConfirm": "Are you sure to execute the workflow?",
+ "meta.Stream.ExecuteSuccess": "Execution Success",
"meta.Consume.ConsumerGroupName": "Consumer Group Name",
"meta.Consume.TopicName": "Topic Name",
"meta.Consume.MQType": "MQ Type",
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/ExecutionLogModal.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStream/ExecutionLogModal.tsx
new file mode 100644
index 000000000..6445135c8
--- /dev/null
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStream/ExecutionLogModal.tsx
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useCallback, useState } from 'react';
+import { Modal, message, Button, Collapse, Popover, Timeline, Pagination, Empty } from 'antd';
+import { ModalProps } from 'antd/es/modal';
+import HighTable from '@/components/HighTable';
+import request from '@/utils/request';
+import { useTranslation } from 'react-i18next';
+import { useRequest, useUpdateEffect } from '@/hooks';
+import { timestampFormat } from '@/utils';
+import StatusTag from '@/components/StatusTag';
+
+const { Panel } = Collapse;
+
+export interface Props extends ModalProps {
+ inlongGroupId?: string;
+ inlongStreamId: string;
+}
+
+const Comp: React.FC<Props> = ({ inlongGroupId, inlongStreamId, ...modalProps }) => {
+ const { t } = useTranslation();
+
+ const [options, setOptions] = useState({
+ pageNum: 1,
+ pageSize: 5,
+ });
+
+ const { run: getData, data } = useRequest(
+ {
+ url: '/workflow/listTaskLogs',
+ params: {
+ ...options,
+ inlongGroupId: inlongGroupId,
+ inlongStreamId: inlongStreamId,
+ processNames: 'CREATE_GROUP_RESOURCE,CREATE_STREAM_RESOURCE',
+ taskType: 'ServiceTask',
+ },
+ },
+ {
+ manual: true,
+ },
+ );
+
+ const onChange = useCallback((pageNum, pageSize) => {
+ setOptions(prev => ({
+ ...prev,
+ pageNum,
+ pageSize,
+ }));
+ }, []);
+
+ const reRun = useCallback(
+ ({ taskId }) => {
+ Modal.confirm({
+ title: t('pages.GroupDashboard.ExecutionLogModal.ConfirmThatItIsRe-executed'),
+ onOk: async () => {
+ await request({
+ url: `/workflow/complete/` + taskId,
+ method: 'POST',
+ data: {
+ remark: '',
+ },
+ });
+ await getData(inlongGroupId);
+ message.success(t('pages.GroupDashboard.ExecutionLogModal.Re-executingSuccess'));
+ },
+ });
+ },
+ [getData, inlongGroupId, t],
+ );
+
+ useUpdateEffect(() => {
+ if (modalProps.visible) {
+ getData();
+ }
+ }, [options]);
+
+ useUpdateEffect(() => {
+ if (modalProps.visible) {
+ getData();
+ } else {
+ setOptions(prev => ({
+ ...prev,
+ pageNum: 1,
+ }));
+ }
+ }, [modalProps.visible]);
+
+ const columns = [
+ {
+ title: t('pages.GroupDashboard.ExecutionLogModal.TaskType'),
+ dataIndex: 'taskDisplayName',
+ },
+ {
+ title: t('pages.GroupDashboard.ExecutionLogModal.RunResults'),
+ dataIndex: 'status',
+ render: (text, record) => (
+ <>
+ <div>
+ {record.status === 'COMPLETED' ? (
+ <StatusTag
+ type={'success'}
+ title={t('pages.GroupDashboard.ExecutionLogModal.Success')}
+ />
+ ) : record.status === 'FAILED' ? (
+ <StatusTag type={'error'} title={t('pages.GroupDashboard.ExecutionLogModal.Fail')} />
+ ) : record.status === 'SKIPPED' ? (
+ <StatusTag
+ type={'primary'}
+ title={t('pages.GroupDashboard.ExecutionLogModal.Skip')}
+ />
+ ) : (
+ <StatusTag
+ type={'warning'}
+ title={t('pages.GroupDashboard.ExecutionLogModal.Processing')}
+ />
+ )}
+ </div>
+ </>
+ ),
+ },
+ {
+ title: t('pages.GroupDashboard.ExecutionLogModal.ExecuteLog'),
+ dataIndex: 'listenerExecuteLogs',
+ width: 400,
+ render: text =>
+ text?.length ? (
+ <Popover
+ content={
+ <Timeline mode={'left'} style={{ marginBottom: -20 }}>
+ {text.map(item => (
+ <Timeline.Item key={item.id} color={item.state === -1 ? 'red' : 'blue'}>
+ {item.description}
+ </Timeline.Item>
+ ))}
+ </Timeline>
+ }
+ overlayStyle={{ maxWidth: 750, maxHeight: 300, overflow: 'auto' }}
+ >
+ <div style={{ height: 45, overflow: 'hidden' }}>{text[0]?.description}</div>
+ </Popover>
+ ) : null,
+ },
+ {
+ title: t('pages.GroupDashboard.ExecutionLogModal.EndTime'),
+ dataIndex: 'endTime',
+ render: (text, record) => record.endTime && timestampFormat(record.endTime),
+ },
+ {
+ title: t('basic.Operating'),
+ dataIndex: 'actions',
+ render: (text, record) => (
+ <>
+ {record?.status && record.status === 'FAILED' && (
+ <Button type="link" onClick={() => reRun(record)}>
+ {t('pages.GroupDashboard.ExecutionLogModal.CarriedOut')}
+ </Button>
+ )}
+ </>
+ ),
+ },
+ ];
+ return (
+ <Modal
+ {...modalProps}
+ title={t('pages.GroupDashboard.ExecutionLogModal.ExecuteLog')}
+ width={1024}
+ footer={null}
+ >
+ {data?.list?.length ? (
+ <>
+ <Collapse accordion defaultActiveKey={[data.list[0]?.processId]}>
+ {data.list.map(item => (
+ <Panel header={item.processDisplayName} key={item.processId}>
+ <HighTable
+ table={{
+ columns,
+ rowKey: 'taskId',
+ size: 'small',
+ dataSource: item.taskExecuteLogs,
+ }}
+ />
+ </Panel>
+ ))}
+ </Collapse>
+ <Pagination
+ size="small"
+ pageSize={options.pageSize}
+ current={options.pageNum}
+ total={data.total}
+ onChange={onChange}
+ style={{ textAlign: 'right', marginTop: 10 }}
+ />
+ </>
+ ) : (
+ <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+ )}
+ </Modal>
+ );
+};
+
+export default Comp;
diff --git a/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx b/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
index 634127bd9..065710d64 100644
--- a/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
+++ b/inlong-dashboard/src/pages/GroupDetail/DataStream/index.tsx
@@ -28,6 +28,7 @@ import { useLoadMeta, useDefaultMeta, StreamMetaType } from '@/metas';
import { CommonInterface } from '../common';
import StreamItemModal from './StreamItemModal';
import { getFilterFormContent } from './config';
+import ExecutionLogModal from './ExecutionLogModal';
type Props = CommonInterface;
@@ -47,6 +48,12 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
inlongGroupId,
});
+ const [executionLogModal, setExecutionLogModal] = useState({
+ visible: false,
+ inlongGroupId,
+ inlongStreamId: '',
+ });
+
const {
data,
loading,
@@ -85,6 +92,14 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
setStreamItemModal(prev => ({ ...prev, visible: true, inlongStreamId: record.inlongStreamId }));
};
+ const openModal = record => {
+ setExecutionLogModal({
+ visible: true,
+ inlongGroupId: inlongGroupId,
+ inlongStreamId: record.inlongStreamId,
+ });
+ };
+
const onDelete = record => {
Modal.confirm({
title: t('basic.DeleteConfirm'),
@@ -103,6 +118,23 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
});
};
+ const onWorkflow = record => {
+ Modal.confirm({
+ title: t('meta.Stream.ExecuteConfirm'),
+ onOk: async () => {
+ await request({
+ url: `/stream/startProcess/${inlongGroupId}/${record?.inlongStreamId}`,
+ method: 'POST',
+ params: {
+ sync: false,
+ },
+ });
+ await getList();
+ message.success(t('meta.Stream.ExecuteSuccess'));
+ },
+ });
+ };
+
const onChange = ({ current: pageNum, pageSize }) => {
setOptions(prev => ({
...prev,
@@ -146,6 +178,16 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
<Button type="link" onClick={() => onDelete(record)}>
{t('basic.Delete')}
</Button>
+ {record?.status && (record?.status === 120 || record?.status === 130) && (
+ <Button type="link" onClick={() => onWorkflow(record)}>
+ {t('meta.Stream.ExecuteWorkflow')}
+ </Button>
+ )}
+ {record?.status && (record?.status === 120 || record?.status === 130) && (
+ <Button type="link" onClick={() => openModal(record)}>
+ {t('pages.GroupDashboard.config.ExecuteLog')}
+ </Button>
+ )}
</>
),
},
@@ -184,6 +226,14 @@ const Comp = ({ inlongGroupId, readonly, mqType }: Props, ref) => {
}}
onCancel={() => setStreamItemModal(prev => ({ ...prev, visible: false }))}
/>
+
+ <ExecutionLogModal
+ {...executionLogModal}
+ onOk={() => setExecutionLogModal({ visible: false, inlongGroupId: '', inlongStreamId: '' })}
+ onCancel={() =>
+ setExecutionLogModal({ visible: false, inlongGroupId: '', inlongStreamId: '' })
+ }
+ />
</>
);
};