Commit e9be4cb1 authored by wenmo's avatar wenmo

作业实例详情

parent 92ba0fdf
......@@ -51,7 +51,7 @@ public class JobInstance implements Serializable {
private Long duration;
private Integer failed_restart_count;
private Integer failedRestartCount;
@TableField(exist = false)
private String type;
......
......@@ -25,8 +25,6 @@ import java.util.Map;
**/
public class FlinkAPI {
private String address;
private String jarsId;
private String jobId;
public FlinkAPI(String address) {
this.address = address;
......
......@@ -367,4 +367,18 @@ create table dlink_alert_history
)
comment 'Alert历史';
DROP TABLE IF EXISTS `dlink_job_history`;
create table dlink_job_history
(
id int comment '实例主键'
primary key,
job json null comment 'Job信息',
exceptions json null comment '异常日志',
checkpoints json null comment '保存点',
checkpoints_config json null comment '保存点配置',
config json null comment '配置',
update_time datetime null comment '更新时间'
)
comment 'Job历史详情';
SET FOREIGN_KEY_CHECKS = 1;
......@@ -597,4 +597,21 @@ ALTER TABLE `dlink_job_instance` MODIFY COLUMN name varchar(255) NULL COMMENT '
ALTER TABLE `dlink_job_instance`
ADD COLUMN `duration` BIGINT NULL COMMENT '耗时' AFTER `finish_time`;
-- ----------------------------
-- 0.6.0-SNAPSHOT 2022-03-01
-- ----------------------------
DROP TABLE IF EXISTS `dlink_job_history`;
create table dlink_job_history
(
id int comment '实例主键'
primary key,
job json null comment 'Job信息',
exceptions json null comment '异常日志',
checkpoints json null comment '保存点',
checkpoints_config json null comment '保存点配置',
config json null comment '配置',
update_time datetime null comment '更新时间'
)
comment 'Job历史详情';
SET FOREIGN_KEY_CHECKS = 1;
import {Tag} from 'antd';
import {
CheckCircleOutlined,
ClockCircleOutlined,
CloseCircleOutlined,
MinusCircleOutlined,
SyncOutlined,
QuestionCircleOutlined
} from "@ant-design/icons";
export type JobStatusFormProps = {
status: string|undefined;
};
const JobStatus = (props: JobStatusFormProps) => {
const {status} = props;
return (<>
{ (status === 'FINISHED') ?
(<Tag icon={<CheckCircleOutlined/>} color="success">
FINISHED
</Tag>) : (status === 'RUNNING') ?
(<Tag icon={<SyncOutlined spin/>} color="processing">
RUNNING
</Tag>) : (status === 'FAILED') ?
(<Tag icon={<CloseCircleOutlined/>} color="error">
FAILED
</Tag>) : (status === 'CANCELED') ?
(<Tag icon={<MinusCircleOutlined/>} color="default">
CANCELED
</Tag>) : (status === 'INITIALIZING') ?
(<Tag icon={<ClockCircleOutlined/>} color="default">
INITIALIZING
</Tag>) : (status === 'RESTARTING') ?
(<Tag icon={<ClockCircleOutlined/>} color="default">
RESTARTING
</Tag>) :
(<Tag icon={<QuestionCircleOutlined />} color="default">
UNKNOWEN
</Tag>)
}
</>)
};
export default JobStatus;
import {Tag, Tooltip} from 'antd';
export type StatusCountsType = {
CREATED: number;
INITIALIZING: number;
DEPLOYING: number;
RUNNING: number;
FAILED: number;
FINISHED: number;
RECONCILING: number;
SCHEDULED: number;
CANCELING: number;
CANCELED: number;
};
export type StatusCountsFormProps = {
statusCounts: StatusCountsType;
};
const StatusCounts = (props: StatusCountsFormProps) => {
const {statusCounts} = props;
return (<>
{statusCounts?.CREATED > 0 ? (
<Tooltip title="CREATED"><Tag color="#666">{statusCounts.CREATED}</Tag></Tooltip>) : undefined}
{statusCounts?.INITIALIZING > 0 ? (
<Tooltip title="INITIALIZING"><Tag color="#666">{statusCounts.INITIALIZING}</Tag></Tooltip>) : undefined}
{statusCounts?.DEPLOYING > 0 ? (
<Tooltip title="DEPLOYING"><Tag color="#666">{statusCounts.DEPLOYING}</Tag></Tooltip>) : undefined}
{statusCounts?.RUNNING > 0 ? (
<Tooltip title="RUNNING"><Tag color="#44b549">{statusCounts.RUNNING}</Tag></Tooltip>) : undefined}
{statusCounts?.FAILED > 0 ? (
<Tooltip title="FAILED"><Tag color="#ff4d4f">{statusCounts.FAILED}</Tag></Tooltip>) : undefined}
{statusCounts?.FINISHED > 0 ? (
<Tooltip title="FINISHED"><Tag color="#108ee9">{statusCounts.FINISHED}</Tag></Tooltip>) : undefined}
{statusCounts?.RECONCILING > 0 ? (
<Tooltip title="RECONCILING"><Tag color="#666">{statusCounts.RECONCILING}</Tag></Tooltip>) : undefined}
{statusCounts?.SCHEDULED > 0 ? (
<Tooltip title="SCHEDULED"><Tag color="#666">{statusCounts.SCHEDULED}</Tag></Tooltip>) : undefined}
{statusCounts?.CANCELING > 0 ? (
<Tooltip title="CANCELING"><Tag color="#feb72b">{statusCounts.CANCELING}</Tag></Tooltip>) : undefined}
{statusCounts?.CANCELED > 0 ? (
<Tooltip title="CANCELED"><Tag color="#db970f">{statusCounts.CANCELED}</Tag></Tooltip>) : undefined}
</>)
};
export default StatusCounts;
......@@ -7,6 +7,7 @@ import ProTable from '@ant-design/pro-table';
import {cancelJob, savepointJob, showFlinkJobs} from "../../StudioEvent/DDL";
import {ClusterTableListItem} from "@/pages/Cluster/data";
import React from "react";
import JobStatus from "@/components/Common/JobStatus";
const {Option} = Select;
......@@ -70,36 +71,7 @@ const StudioProcess = (props: any) => {
dataIndex: "state",
sorter: true,
render: (_, row) => {
return (
<>
{(row.state == 'FINISHED') ?
(<Tag icon={<CheckCircleOutlined />} color="success">
FINISHED
</Tag>) :
(row.state == 'RUNNING') ?
(<Tag icon={<SyncOutlined spin />} color="processing">
RUNNING
</Tag>) :
(row.state == 'FAILED') ?
(<Tag icon={<CloseCircleOutlined />} color="error">
FAILED
</Tag>) :
(row.state == 'CANCELED') ?
(<Tag icon={<MinusCircleOutlined />} color="default">
CANCELED
</Tag>) :
(row.state == 'INITIALIZE') ?
(<Tag icon={<ClockCircleOutlined />} color="default">
INITIALIZE
</Tag>) :(row.state == 'RESTARTING') ?
(<Tag icon={<ClockCircleOutlined />} color="default">
RESTARTING
</Tag>) :
(<Tag color="default">
UNKNOWEN
</Tag>)
}</>)
;
return (<JobStatus status={row.state}/>);
}
}, {
title: "开始时间",
......
import { Descriptions, Badge } from 'antd';
import {Descriptions} from 'antd';
import StatusCounts from "@/components/Common/StatusCounts";
const BaseInfo = (props: any) => {
const {job} = props;
return (<Descriptions bordered>
<Descriptions.Item label="实例状态">{job?.instance.status}</Descriptions.Item>
<Descriptions.Item label="重启次数">{job?.instance.schema}</Descriptions.Item>
<Descriptions.Item label="作业状态"><StatusCounts statusCounts={job?.instance.statusCounts}/></Descriptions.Item>
<Descriptions.Item label="重启次数">{job?.instance.failedRestartCount}</Descriptions.Item>
<Descriptions.Item label="耗时">{job?.instance.duration}</Descriptions.Item>
<Descriptions.Item label="启动时间">{job?.instance.createTime}</Descriptions.Item>
<Descriptions.Item label="更新时间">{job?.instance.updateTime}</Descriptions.Item>
<Descriptions.Item label="完成时间">{job?.instance.finishTime}</Descriptions.Item>
<Descriptions.Item label="Task" span={3}>
{}
</Descriptions.Item>
<Descriptions.Item >{}</Descriptions.Item>
<Descriptions.Item span={3}>{}</Descriptions.Item>
</Descriptions>)
};
......
import React, {useEffect, useState} from 'react';
import { history, useLocation } from 'umi';
import { EllipsisOutlined, CheckCircleOutlined,SyncOutlined,CloseCircleOutlined,MinusCircleOutlined,ClockCircleOutlined,
FireOutlined,ClusterOutlined,RocketOutlined} from '@ant-design/icons';
import { Button, Dropdown, Menu, Tag, Space } from 'antd';
import { PageContainer } from '@ant-design/pro-layout';
import {history, useLocation} from 'umi';
import {
EllipsisOutlined, RedoOutlined,
FireOutlined, ClusterOutlined, RocketOutlined
} from '@ant-design/icons';
import {Button, Dropdown, Menu, Tag, Space, Typography} from 'antd';
import {PageContainer} from '@ant-design/pro-layout';
import ProCard from '@ant-design/pro-card';
import {JobInfoDetail, StatusCount} from "@/pages/DevOps/data";
import {getJobInfoDetail, getStatusCount} from "@/pages/DevOps/service";
import {JobInfoDetail} from "@/pages/DevOps/data";
import {getJobInfoDetail} from "@/pages/DevOps/service";
import moment from "moment";
import BaseInfo from "@/pages/DevOps/JobInfo/BaseInfo";
import JobStatus from "@/components/Common/JobStatus";
const JobInfo = (props:any) => {
const {Link} = Typography;
const JobInfo = (props: any) => {
const params = useLocation();
const { } = props;
const {} = props;
const id = params.query.id;
const [job, setJob] = useState<JobInfoDetail>();
const [time, setTime] = useState(() => Date.now());
const [tabKey, setTabKey] = useState<string>('base');
const refreshJobInfoDetail = () => {
const res = getJobInfoDetail(id);
res.then((result)=>{
res.then((result) => {
setJob(result.datas);
setTime(Date.now());
});
......@@ -27,7 +34,7 @@ const JobInfo = (props:any) => {
useEffect(() => {
refreshJobInfoDetail();
let dataPolling = setInterval(refreshJobInfoDetail,3000);
let dataPolling = setInterval(refreshJobInfoDetail, 3000);
return () => {
clearInterval(dataPolling);
};
......@@ -44,7 +51,11 @@ const JobInfo = (props:any) => {
ghost: true,
extra: [
<Button key="back" type="dashed" onClick={handleBack}>返回</Button>,
<Button key="flinkwebui">FlinkWebUI</Button>,
<Button key="refresh" icon={<RedoOutlined/>}/>,
<Button key="flinkwebui">
<Link href={`http://${job?.history.jobManagerAddress}`} target="_blank">
FlinkWebUI
</Link></Button>,
<Button key="autorestart" type="primary">智能重启</Button>,
<Button key="autostop" type="primary" danger>智能停止</Button>,
<Dropdown
......@@ -58,57 +69,31 @@ const JobInfo = (props:any) => {
</Menu>
}
>
<Button key="4" style={{ padding: '0 8px' }}>
<EllipsisOutlined />
<Button key="4" style={{padding: '0 8px'}}>
<EllipsisOutlined/>
</Button>
</Dropdown>,
],
}}
content={<>
<Space size={0}>
{job?.instance.jid?(
{job?.instance.jid ? (
<Tag color="blue" key={job?.instance.jid}>
<FireOutlined /> {job?.instance.jid}
<FireOutlined/> {job?.instance.jid}
</Tag>
):undefined}
{(job?.instance.status == 'FINISHED') ?
(<Tag icon={<CheckCircleOutlined />} color="success">
FINISHED
</Tag>) :
(job?.instance.status == 'RUNNING') ?
(<Tag icon={<SyncOutlined spin />} color="processing">
RUNNING
</Tag>) :
(job?.instance.status == 'FAILED') ?
(<Tag icon={<CloseCircleOutlined />} color="error">
FAILED
</Tag>) :
(job?.instance.status == 'CANCELED') ?
(<Tag icon={<MinusCircleOutlined />} color="default">
CANCELED
</Tag>) :
(job?.instance.status == 'INITIALIZING') ?
(<Tag icon={<ClockCircleOutlined />} color="default">
INITIALIZING
</Tag>) :(job?.instance.status == 'RESTARTING') ?
(<Tag icon={<ClockCircleOutlined />} color="default">
RESTARTING
</Tag>) :
(<Tag color="default">
UNKNOWEN
</Tag>)
}
{job?.history.type?(
) : undefined}
<JobStatus status={job?.instance.status}/>
{job?.history.type ? (
<Tag color="blue" key={job?.history.type}>
<RocketOutlined /> {job?.history.type}
<RocketOutlined/> {job?.history.type}
</Tag>
):undefined}
{job?.cluster.alias?(
) : undefined}
{job?.cluster.alias ? (
<Tag color="green" key={job?.cluster.alias}>
<ClusterOutlined /> {job?.cluster.alias}
<ClusterOutlined/> {job?.cluster.alias}
</Tag>
):(<Tag color="green" key='local'>
<ClusterOutlined /> 本地环境
) : (<Tag color="green" key='local'>
<ClusterOutlined/> 本地环境
</Tag>)}
</Space>
</>}
......@@ -145,13 +130,12 @@ const JobInfo = (props:any) => {
closable: false,
},
]}
onTabChange={(key) => {
setTabKey(key);
}}
>
<ProCard direction="column" ghost gutter={[0, 16]}>
<ProCard style={{ height: 200 }} />
<ProCard gutter={16} ghost style={{ height: 200 }}>
<ProCard colSpan={16} />
<ProCard colSpan={8} />
</ProCard>
<ProCard>
{tabKey === 'base' ? <BaseInfo job={job}/> : undefined}
</ProCard>
</PageContainer>
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment