add gateway monitor page

This commit is contained in:
shiyang 2020-11-21 00:37:05 +08:00
parent b4622b3e83
commit b7a876aaf4
7 changed files with 437 additions and 6 deletions

3
.gitignore vendored
View File

@ -28,4 +28,5 @@ appveyor.yml
/vendor /vendor
/bin /bin
*.exe *.exe
web/.github/ web/.github/
web/report*

View File

@ -18,7 +18,7 @@ export default [
authority: ['admin', 'user'], authority: ['admin', 'user'],
routes: [ routes: [
// dashboard // dashboard
{ path: '/', redirect: '/platform/gateway' }, { path: '/', redirect: '/platform/cluster' },
{ {
path: '/platform', path: '/platform',
name: 'platform', name: 'platform',
@ -28,7 +28,7 @@ export default [
{ {
path: '/platform/gateway', path: '/platform/gateway',
name: 'gateway', name: 'gateway',
component: './Dashboard/Analysis', component: './Dashboard/GatewayMonitor',
}, { }, {
path: '/platform/cluster', path: '/platform/cluster',
name: 'cluster', name: 'cluster',
@ -40,7 +40,7 @@ export default [
}, { }, {
path: '/platform/search', path: '/platform/search',
name: 'search', name: 'search',
component: './Dashboard/Search', component: './Dashboard/SearchMonitor',
}, },
] ]
}, },

View File

@ -0,0 +1,48 @@
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi/locale';
import { Row, Col, Card, Tooltip } from 'antd';
import numeral from 'numeral';
import { Pie, WaterWave, Gauge, TagCloud } from '@/components/Charts';
import NumberInfo from '@/components/NumberInfo';
import CountDown from '@/components/CountDown';
import ActiveChart from '@/components/ActiveChart';
import GridContent from '@/components/PageHeaderWrapper/GridContent';
import Authorized from '@/utils/Authorized';
import styles from './Monitor.less';
const { Secured } = Authorized;
const targetTime = new Date().getTime() + 3900000;
// use permission as a parameter
const havePermissionAsync = new Promise(resolve => {
// Call resolve on behalf of passed
setTimeout(() => resolve(), 300);
});
@Secured(havePermissionAsync)
@connect(({ monitor, loading }) => ({
monitor,
loading: loading.models.monitor,
}))
class ClusterMonitor extends PureComponent {
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: 'monitor/fetchTags',
});
}
render() {
const { monitor, loading } = this.props;
const { tags } = monitor;
return (
<h1>cluster monitor</h1>
);
}
}
export default ClusterMonitor;

View File

@ -0,0 +1,156 @@
import React, { PureComponent } from 'react';
import GridContent from '@/components/PageHeaderWrapper/GridContent';
import {
Row,
Col,
Icon,
Card,
Tabs,
Table,
Radio,
DatePicker,
Menu,
Dropdown,
} from 'antd';
import { Chart, Geom, Axis, Tooltip, Legend, Coord } from 'bizcharts';
import DataSet from '@antv/data-set';
import Slider from 'bizcharts-plugin-slider';
import stylesGateway from "./GatewayMonitor.less";
const styles ={
...stylesGateway,
mainTitle:{
fontSize:20,
color:"black",
textAlign:"center"
},
subTitle:{
fontSize:16,
color:"gray",
textAlign:"center"
}
}
class GatewayMonitor extends PureComponent {
//时间戳转换方法 date:时间戳数字
formatDate(timestamp) {
var date = new Date(timestamp);
var YY = date.getFullYear();
var MM = '-' + (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1);
var DD = '-' + (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate());
var hh = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours());
var mm = ':' + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes());
var ss = ':' + (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
// return YY + MM + DD +" "+hh + mm + ss;
return hh + mm;
}
render() {
// 数据源
const chartDataIndex = [];
const chartDataQuery = [];
for (let i = 0; i < 24; i += 1) {
chartDataIndex.push({
x_time: this.formatDate(new Date().getTime() + (1000 * 60 * 60 * (i-24))),
y_value: Math.floor(Math.random() * 100) * 100,
});
chartDataQuery.push({
x_time: this.formatDate(new Date().getTime() + (1000 * 60 * 60 * (i-24))),
y_value: Math.floor(Math.random() * 100) * 500,
});
}
// 定义度量
const cols = {
y_value: {
min: 0,
alias: '次数'
},
x_time: {
range: [0, 1],
alias: '时间'
}
};
return (
<GridContent>
<Row gutter={24}>
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
<Card
loading={false}
className={styles.offlineCard}
bordered={false}
bodyStyle={{ padding: '30px 0 10px' }}
style={{ marginTop: 32 }}
>
<Chart height={400} data={chartDataIndex} scale={cols} forceFit>
<h3 className='main-title' style={styles.mainTitle}>
索引QPS
</h3>
<Axis name="year" title/>
<Axis name="value" title/>
<Tooltip
crosshairs={{
type: "y"
}}
/>
<Geom type="line" position="x_time*y_value" size={2} />
<Geom
type="point"
position="x_time*y_value"
size={4}
shape={"circle"}
style={{
stroke: "#fff",
lineWidth: 1
}}
/>
</Chart>
</Card>
</Col>
<Col xl={12} lg={24} md={24} sm={24} xs={24}>
<Card
loading={false}
className={styles.offlineCard}
bordered={false}
bodyStyle={{ padding: '30px 0 10px' }}
style={{ marginTop: 32 }}
>
<div style={{ padding: '0 24px' }}>
<Chart height={400} data={chartDataQuery} scale={cols} forceFit>
<h3 className='main-title' style={styles.mainTitle}>
查询QPS
</h3>
<Axis name="year" />
<Axis name="value" />
<Tooltip
crosshairs={{
type: "y"
}}
/>
<Geom type="line" position="x_time*y_value" size={2} />
<Geom
type="point"
position="x_time*y_value"
size={4}
shape={"circle"}
style={{
stroke: "#fff",
lineWidth: 1
}}
/>
</Chart>
</div>
</Card>
</Col>
</Row>
</GridContent>
)
}
}
export default GatewayMonitor;

View File

@ -0,0 +1,178 @@
@import '~antd/lib/style/themes/default.less';
@import '~@/utils/utils.less';
.iconGroup {
i {
transition: color 0.32s;
color: @text-color-secondary;
cursor: pointer;
margin-left: 16px;
&:hover {
color: @text-color;
}
}
}
.rankingList {
margin: 25px 0 0;
padding: 0;
list-style: none;
li {
.clearfix();
margin-top: 16px;
display: flex;
align-items: center;
span {
color: @text-color;
font-size: 14px;
line-height: 22px;
}
.rankingItemNumber {
background-color: @background-color-base;
border-radius: 20px;
display: inline-block;
font-size: 12px;
font-weight: 600;
margin-right: 16px;
height: 20px;
line-height: 20px;
width: 20px;
text-align: center;
margin-top: 1.5px;
&.active {
background-color: #314659;
color: #fff;
}
}
.rankingItemTitle {
flex: 1;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin-right: 8px;
}
}
}
.salesExtra {
display: inline-block;
margin-right: 24px;
a {
color: @text-color;
margin-left: 24px;
&:hover {
color: @primary-color;
}
&.currentDate {
color: @primary-color;
}
}
}
.salesCard {
.salesBar {
padding: 0 0 32px 32px;
}
.salesRank {
padding: 0 32px 32px 72px;
}
:global {
.ant-tabs-bar {
padding-left: 16px;
.ant-tabs-nav .ant-tabs-tab {
padding-top: 16px;
padding-bottom: 14px;
line-height: 24px;
}
}
.ant-tabs-extra-content {
padding-right: 24px;
line-height: 55px;
}
.ant-card-head {
position: relative;
}
.ant-card-head-title {
align-items: normal;
}
}
}
.salesCardExtra {
height: 68px;
}
.salesTypeRadio {
position: absolute;
left: 24px;
bottom: 15px;
}
.offlineCard {
:global {
.ant-tabs-ink-bar {
bottom: auto;
}
.ant-tabs-bar {
border-bottom: none;
}
.ant-tabs-nav-container-scrolling {
padding-left: 40px;
padding-right: 40px;
}
.ant-tabs-tab-prev-icon:before {
position: relative;
left: 6px;
}
.ant-tabs-tab-next-icon:before {
position: relative;
right: 6px;
}
.ant-tabs-tab-active h4 {
color: @primary-color;
}
}
}
.trendText {
margin-left: 8px;
color: @heading-color;
}
@media screen and (max-width: @screen-lg) {
.salesExtra {
display: none;
}
.rankingList {
li {
span:first-child {
margin-right: 8px;
}
}
}
}
@media screen and (max-width: @screen-md) {
.rankingTitle {
margin-top: 16px;
}
.salesCard .salesBar {
padding: 16px;
}
}
@media screen and (max-width: @screen-sm) {
.salesExtraWrap {
display: none;
}
.salesCard {
:global {
.ant-tabs-content {
padding-top: 30px;
}
}
}
}

View File

@ -27,7 +27,7 @@ const havePermissionAsync = new Promise(resolve => {
monitor, monitor,
loading: loading.models.monitor, loading: loading.models.monitor,
})) }))
class Search extends PureComponent { class SearchMonitor extends PureComponent {
componentDidMount() { componentDidMount() {
const { dispatch } = this.props; const { dispatch } = this.props;
dispatch({ dispatch({
@ -45,4 +45,4 @@ class Search extends PureComponent {
} }
} }
export default Search; export default SearchMonitor;

View File

@ -0,0 +1,48 @@
import React, { PureComponent } from 'react';
import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi/locale';
import { Row, Col, Card, Tooltip } from 'antd';
import numeral from 'numeral';
import { Pie, WaterWave, Gauge, TagCloud } from '@/components/Charts';
import NumberInfo from '@/components/NumberInfo';
import CountDown from '@/components/CountDown';
import ActiveChart from '@/components/ActiveChart';
import GridContent from '@/components/PageHeaderWrapper/GridContent';
import Authorized from '@/utils/Authorized';
import styles from './Monitor.less';
const { Secured } = Authorized;
const targetTime = new Date().getTime() + 3900000;
// use permission as a parameter
const havePermissionAsync = new Promise(resolve => {
// Call resolve on behalf of passed
setTimeout(() => resolve(), 300);
});
@Secured(havePermissionAsync)
@connect(({ monitor, loading }) => ({
monitor,
loading: loading.models.monitor,
}))
class TaskMonitor extends PureComponent {
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: 'monitor/fetchTags',
});
}
render() {
const { monitor, loading } = this.props;
const { tags } = monitor;
return (
<h1>task monitor</h1>
);
}
}
export default TaskMonitor;