Skip to content

Commit

Permalink
[Optimization][metrics]fix_metrics_web_page (#3561)
Browse files Browse the repository at this point in the history
Signed-off-by: Zzm0809 <934230207@qq.com>
Co-authored-by: zackyoungh <zackyoungh@users.noreply.github.com>
Co-authored-by: Zzm0809 <934230207@qq.com>
Co-authored-by: Zzm0809 <Zzm0809@users.noreply.github.com>
  • Loading branch information
4 people authored Jun 5, 2024
1 parent 34eacc2 commit 9a81a38
Show file tree
Hide file tree
Showing 25 changed files with 589 additions and 217 deletions.
7 changes: 6 additions & 1 deletion dinky-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@
],
"dependencies": {
"@andrewray/react-multi-split-pane": "^0.3.5",
"@ant-design/charts": "^1.4.3",
"@ant-design/charts": "^2.1.1",
"@ant-design/icons": "^5.3.7",
"@ant-design/pro-components": "^2.6.43",
"@ant-design/pro-layout": "^7.17.16",
"@ant-design/pro-table": "^3.13.11",
"@ant-design/use-emotion-css": "^1.0.4",
"@antv/layout": "^0.3.25",
"@antv/x6": "^2.15.6",
"@antv/x6-plugin-selection": "^2.2.1",
"@antv/x6-react-shape": "^2.2.2",
Expand All @@ -65,9 +66,11 @@
"react-countup": "^6.5.0",
"react-dom": "^18.0.0",
"react-helmet-async": "^2.0.1",
"react-infinite-scroll-component": "^6.1.0",
"react-lineage-dag": "^2.0.36",
"react-markdown": "^9.0.1",
"react-spring": "^9.7.3",
"react-fast-marquee": "^1.6.4",
"react-use-cookie": "^1.4.0",
"redux-persist": "^6.0.0",
"remark-gfm": "^4.0.0",
Expand All @@ -82,6 +85,7 @@
"@types/classnames": "^2.3.1",
"@types/express": "^4.17.21",
"@types/history": "^5.0.0",
"@types/js-cookie": "^3.0.6",
"@types/lodash": "^4.14.199",
"@types/react": "^18.2.39",
"@types/react-dom": "^18.2.17",
Expand All @@ -95,6 +99,7 @@
"lint-staged": "^13",
"prettier": "^2",
"react-dev-inspector": "^2.0.0",
"react-fast-marquee": "^1.6.4",
"react-inspector": "^6.0.2",
"sql-formatter": "^13.0.1",
"swagger-ui-dist": "^5.10.3",
Expand Down
32 changes: 21 additions & 11 deletions dinky-web/src/components/Flink/FlinkChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
*/

import { ChartData } from '@/pages/Metrics/JobMetricsList/data';
import { differenceDays } from '@/utils/function';
import { Line } from '@ant-design/charts';
import { THEME } from '@/types/Public/data';
import { differenceDays, getChartThemeColor } from '@/utils/function';
import { Line, LineConfig } from '@ant-design/charts';
import { ExpandOutlined } from '@ant-design/icons';
import { ProCard, StatisticCard } from '@ant-design/pro-components';
import { Col, Modal, Radio, Segmented, Space } from 'antd';
import Paragraph from 'antd/es/typography/Paragraph';
import { useState } from 'react';
import { useEffect, useState } from 'react';

type FlinkChartProps = {
title: string;
Expand All @@ -51,6 +52,7 @@ const FlinkChart = (props: FlinkChartProps) => {
titleWidth: '60%'
});

const [themeColor, setThemeColor] = useState<string>(THEME.CHART_THEME_LIGHT);
const [showExtra, setShowExtra] = useState<boolean>(false);

const getLineTimeMask = (charData: ChartData[]) => {
Expand All @@ -69,16 +71,23 @@ const FlinkChart = (props: FlinkChartProps) => {
}
};

const config = {
animation: false,
useEffect(() => {
setThemeColor(getChartThemeColor());
}, [getChartThemeColor()]);

const config: LineConfig = {
animation: true,
autoFit: true,
data: data,
smooth: true,
xField: 'time',
theme: themeColor,
yField: 'value',
xAxis: {
type: 'time',
mask: getLineTimeMask(data),
tickCount: 40
xField: (d: ChartData) => new Date(d.time),
axis: {
x: {
tickCount: 10,
mask: getLineTimeMask(data)
}
},
...chartOptions
};
Expand Down Expand Up @@ -163,7 +172,8 @@ const FlinkChart = (props: FlinkChartProps) => {
) : (
<StatisticCard.Group
style={{
minHeight: '100%',
marginTop: '5%',
minHeight: '95%',
minWidth: '100%',
display: 'flex',
justifyContent: 'center',
Expand Down
78 changes: 78 additions & 0 deletions dinky-web/src/components/Flink/ListPagination/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
*
* 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 { Pagination, Row } from 'antd';
import React, { useEffect, useState } from 'react';

type ListPaginationProps<T, F> = {
data: T[];
defaultPageSize: number;
layout: (data: T[]) => React.ReactNode;
filter?: FilterProp<T, F>;
};

type FilterProp<T, F> = {
content: (data: T[], setFilter: React.Dispatch<F>) => React.ReactNode;
filter: (data: T, filter: F) => boolean;
};

const ListPagination = <T, F>(props: ListPaginationProps<T, F>) => {
const [data, setData] = useState<T[]>(props.data);
const [currentData, setCurrentData] = useState<T[]>([]);
const [currentPage, setCurrentPage] = useState<number>(1);
const [currentPageSize, setCurrentPageSize] = useState<number>(props.defaultPageSize);
const [filter, setFilter] = useState<F>({} as F);

useEffect(() => {
const newData = props.data.filter((item) => {
if (props.filter) {
return props.filter.filter(item, filter);
}
return true;
});
setCurrentData(
newData.slice((currentPage - 1) * currentPageSize, currentPage * currentPageSize)
);
setData(newData);
}, [currentPage, currentPageSize, filter, data]);

return (
<>
{props.filter && props.filter.content(props.data, setFilter)}
<Row gutter={[8, 16]}>{props.layout(currentData)}</Row>
<Pagination
style={{ textAlign: 'center', marginTop: '16px' }}
showTitle
total={data.length}
hideOnSinglePage
showTotal={(total, range) => `${range[0]}-${range[1]} of ${total} Items`}
defaultPageSize={props.defaultPageSize}
responsive
showLessItems
defaultCurrent={currentPage}
onChange={(page, pageSize) => {
setCurrentPage(page);
setCurrentPageSize(pageSize);
}}
/>
</>
);
};

export default ListPagination;
33 changes: 33 additions & 0 deletions dinky-web/src/components/MarqueeAlert/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {Alert, Result} from "antd";
import Marquee from "react-fast-marquee";
import React from "react";


interface MetricsProps {
tips: string | React.ReactNode
type: 'success' | 'info' | 'warning' | 'error';
showIcon?: boolean;
banner?: boolean;
play?: boolean;
}


/**
* The scrolling message prompt component is only used for long text, but its width may exceed the width of the container, so scrolling display is required
* @param props
*/
export default (props: MetricsProps) => {

const {tips, type, banner = false, showIcon = true, play = true} = props;

const renderMarquee = () => {
return <>
<Marquee style={{alignContent: 'center'}} play={play} speed={50} gradient={false} gradientWidth={0}>
{tips}
</Marquee>
</>
}


return <><Alert style={{width: '50vw'}} message={renderMarquee()} type={type} banner={banner} showIcon={showIcon}/></>
};
4 changes: 3 additions & 1 deletion dinky-web/src/locales/en-US/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ export default {
'devops.jobinfo.job.keyConfirm': '{key} this Job?',
'devops.jobinfo.metrics.configMetrics': 'Metrics Config',
'devops.jobinfo.metrics.metricsItems': 'Metrics Items',
'devops.jobinfo.metrics.vertices': 'Vertices',
'devops.jobinfo.metrics.name': 'Metrics Name',
'devops.jobinfo.metrics.selected': 'Selected',
'devops.jobinfo.offline': 'Offline',
'devops.jobinfo.recently.job.status': 'View recently saved job status information',
Expand Down Expand Up @@ -359,7 +361,7 @@ export default {
'metrics.flink.subTask.placeholder': 'Please select a SubTask Name',
'metrics.flink.taskId': 'Dinky Job ID',
'metrics.dinky.not.open':
'Dinky Server monitoring is not enabled, please go to the Setting Center -> Global Settings -> Metrics Configuration -> Dinky JVM Monitor switch to open',
'The monitoring function is not enabled, and the Dinky Server and Flink task monitoring functions cannot be used. \nPlease go to the Configuration Center -> Global Configuration -> Metrics Configuration -> Dinky JVM Monitor switch to enable it',
'metrics.flink.deleteConfirm':
'Are you sure to delete the monitoring data under this task? \nAttention: This operation will synchronously affect the monitoring data of the operation and maintenance center for this task!! \nPlease operate with caution, this operation is irreversible!',

Expand Down
4 changes: 3 additions & 1 deletion dinky-web/src/locales/zh-CN/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ export default {
'devops.jobinfo.job.keyConfirm': '确定 {key} 该作业吗?',
'devops.jobinfo.metrics.configMetrics': '任务监控配置',
'devops.jobinfo.metrics.metricsItems': '监控项列表',
'devops.jobinfo.metrics.vertices': '顶点',
'devops.jobinfo.metrics.name': '监控项名称',
'devops.jobinfo.metrics.selected': '已选择',
'devops.jobinfo.offline': '下线',
'devops.jobinfo.recently.job.status': '查看最近保存的作业状态信息',
Expand Down Expand Up @@ -346,7 +348,7 @@ export default {
'metrics.flink.subTask.placeholder': '请选择子任务名称',
'metrics.flink.taskId': 'Dinky 任务ID',
'metrics.dinky.not.open':
'暂未开启 Dinky Server 监控, 请前往 配置中心 -> 全局配置 -> Metrics 配置 -> Dinky JVM Monitor 开关 进行开启',
'未开启监控功能,Dinky Server 和 Flink 任务监控功能无法使用. \n请前往 配置中心 -> 全局配置 -> Metrics 配置 -> Dinky JVM Monitor 开关 进行开启',
'metrics.flink.deleteConfirm':
'确认删除该任务下的监控数据吗? \n注意:该操作会同步影响运维中心该任务的监控数据!!\n请谨慎操作,该操作不可撤消!',
/**
Expand Down
17 changes: 10 additions & 7 deletions dinky-web/src/pages/DataStudio/FooterContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,16 @@ const FooterContainer: React.FC<FooterContainerProps & StateType> = (props) => {
useEffect(() => {
const eventSource = getSseData(API_CONSTANTS.BASE_URL + API_CONSTANTS.GET_JVM_INFO);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data).data;
setMemDetailInfo(
Number(data['heapUsed'] / 1024 / 1024).toFixed(0) +
'/' +
Number(data['max'] / 1024 / 1024).toFixed(0) +
'M'
);
const respData = JSON.parse(event.data);
const data = respData.data;
if (respData['topic'] != 'HEART_BEAT') {
setMemDetailInfo(
Number(data['heapUsed'] / 1024 / 1024).toFixed(0) +
'/' +
Number(data['max'] / 1024 / 1024).toFixed(0) +
'M'
);
}
};
return () => {
eventSource.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@
*/

import FlinkChart from '@/components/Flink/FlinkChart';
import ListPagination from '@/components/Flink/ListPagination';
import useHookRequest from '@/hooks/useHookRequest';
import { SseData } from '@/models/Sse';
import { SSE_TOPIC } from '@/pages/DevOps/constants';
import { JobMetricsItem, MetricsTimeFilter } from '@/pages/DevOps/JobDetail/data';
import { getMetricsData } from '@/pages/DevOps/JobDetail/srvice';
import { getMetricsData } from '@/pages/DevOps/JobDetail/service';
import { Filter, isBlank } from '@/pages/Metrics/JobMetricsList';
import { ChartData } from '@/pages/Metrics/JobMetricsList/data';
import { MetricsDataType } from '@/pages/Metrics/Server/data';
import { Jobs } from '@/types/DevOps/data';
import { Empty, Row, Spin } from 'antd';
import { l } from '@/utils/intl';
import { ProFormSelect, ProFormText, QueryFilter } from '@ant-design/pro-components';
import { Empty, Spin } from 'antd';
import { useEffect, useState } from 'react';
import { useModel } from 'umi';

Expand All @@ -44,7 +48,7 @@ const JobChart = (props: JobChartProps) => {
subscribeTopic: model.subscribeTopic
}));

const { loading } = useHookRequest(getMetricsData, {
const { loading, refresh: refreshMetricsData } = useHookRequest(getMetricsData, {
defaultParams: [timeRange, jobDetail.instance.jid],
refreshDeps: [timeRange, metricsList],
onSuccess: (result) => {
Expand Down Expand Up @@ -102,7 +106,62 @@ const JobChart = (props: JobChartProps) => {
};
return (
<Spin spinning={loading} delay={500}>
<Row gutter={[8, 16]}>{renderMetricsCardList(metricsList ?? {}, chartDatas)}</Row>
{metricsList && (
<ListPagination<JobMetricsItem, Filter>
data={metricsList}
layout={(data) => renderMetricsCardList(data, chartDatas)}
defaultPageSize={12}
filter={{
content: (data: JobMetricsItem[], setFilter) => {
return (
<QueryFilter<Filter>
labelWidth={'auto'}
span={8}
defaultCollapsed
split
onFinish={async (values) => setFilter(values)}
onReset={async () => {
// 清空筛选条件
setFilter({
vertices: '',
metrics: ''
});
await refreshMetricsData();
}}
>
<ProFormSelect
name='vertices'
colProps={{ md: 12, xl: 8 }}
label={l('devops.jobinfo.metrics.vertices')}
valueEnum={[...new Set(data.map((item) => item.vertices))].reduce(
(accumulator, item) => {
accumulator[item] = item;
return accumulator;
},
{} as Record<string, string>
)}
/>
<ProFormText
colProps={{ md: 12, xl: 8 }}
name='metrics'
label={l('devops.jobinfo.metrics.name')}
/>
</QueryFilter>
);
},
filter: (item: JobMetricsItem, filter: Filter) => {
let rule = true;
if (!isBlank(filter.vertices)) {
rule = rule && item.vertices.includes(filter.vertices);
}
if (!isBlank(filter.metrics)) {
rule = rule && item.metrics.includes(filter.metrics);
}
return rule;
}
}}
/>
)}
</Spin>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import useHookRequest from '@/hooks/useHookRequest';
import { JobMetricsItem } from '@/pages/DevOps/JobDetail/data';
import { getFLinkVertices } from '@/pages/DevOps/JobDetail/srvice';
import { getFLinkVertices } from '@/pages/DevOps/JobDetail/service';
import { Jobs } from '@/types/DevOps/data';
import { l } from '@/utils/intl';
import { Transfer } from 'antd';
Expand Down
Loading

0 comments on commit 9a81a38

Please sign in to comment.