blob: 3c24d76f94169ad2b22e93efed79db88a8077ef4 [file] [log] [blame]
/**
* 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, { PureComponent } from 'react';
import { connect } from 'dva';
import { Row, Col, Card, Tooltip, Icon } from 'antd';
import {
ChartCard, MiniArea, Field, HeatMap, Line,
} from '../../components/Charts';
import { axis, generateDuration, axisMY } from '../../utils/time';
import { avgTimeSeries, redirect } from '../../utils/utils';
import { Panel } from '../../components/Page';
import RankList from '../../components/RankList';
@connect(state => ({
dashboard: state.dashboard,
duration: state.global.duration,
globalVariables: state.global.globalVariables,
}))
export default class Dashboard extends PureComponent {
handleDurationChange = (variables) => {
this.props.dispatch({
type: 'dashboard/fetchData',
payload: { variables },
});
}
renderAction = (prompt, path) => {
return (
<Tooltip title={prompt}>
<Icon type="info-circle-o" onClick={() => redirect(this.props.history, path)} />
</Tooltip>
);
}
render() {
const { data } = this.props.dashboard;
const { numOfAlarm } = data.getAlarmTrend;
const accuracy = 100;
let visitData = [];
let avg = 0;
let max = 0;
let min = 0;
if (numOfAlarm && numOfAlarm.length > 0) {
visitData = axis(this.props.duration, numOfAlarm, ({ x, y }) => ({ x, y: y / accuracy }));
avg = avgTimeSeries(numOfAlarm) / accuracy;
max = numOfAlarm.reduce((acc, curr) => { return acc < curr ? curr : acc; }) / accuracy;
min = numOfAlarm.reduce((acc, curr) => { return acc > curr ? curr : acc; }) / accuracy;
}
return (
<Panel globalVariables={this.props.globalVariables} onChange={this.handleDurationChange}>
<Row gutter={8}>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="Service"
action={this.renderAction('Show service details', '/monitor/service')}
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/app.png" alt="service" />}
total={data.getGlobalBrief.numOfService}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="Endpoint"
action={this.renderAction('Show endpoint details', '/monitor/endpoint')}
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/service.png" alt="endpoint" />}
total={data.getGlobalBrief.numOfEndpoint}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="DB & Cache"
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/database.png" alt="database" />}
total={data.getGlobalBrief.numOfDatabase
+ data.getGlobalBrief.numOfCache}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="MQ"
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/mq.png" alt="mq" />}
total={data.getGlobalBrief.numOfMQ}
/>
</Col>
</Row>
<Row gutter={8}>
<Col xs={24} sm={24} md={24} lg={12} xl={12} style={{ marginTop: 8 }}>
<ChartCard
title="Calls HeatMap"
contentHeight={200}
>
<HeatMap
data={data.getThermodynamic}
duration={this.props.duration}
height={200}
onClick={(duration, responseTimeRange) => redirect(this.props.history, '/trace', { values: { duration: generateDuration({
from() {
return duration.start;
},
to() {
return duration.end;
},
}),
minTraceDuration: responseTimeRange.min,
maxTraceDuration: responseTimeRange.max,
} })}
/>
</ChartCard>
</Col>
<Col xs={24} sm={24} md={24} lg={12} xl={12} style={{ marginTop: 8 }}>
<ChartCard
title="Avg Application Alarm"
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/alert.png" alt="app" />}
total={`${avg.toFixed(2)}%`}
footer={<div><Field label="Max" value={`${max}%`} /> <Field label="Min" value={`${min}%`} /></div>}
contentHeight={100}
>
<MiniArea
animate={false}
color="#D87093"
borderColor="#B22222"
line="true"
data={visitData}
yAxis={{
formatter(val) {
return `${val} %`;
},
}}
/>
</ChartCard>
</Col>
</Row>
<Row>
<Col xs={24} sm={24} md={24} lg={24} xl={24} style={{ marginTop: 8 }}>
<Card
title="Response Time"
bordered={false}
bodyStyle={{ padding: 5, height: 150}}
>
<Line
data={axisMY(this.props.duration, [{ title: 'p99', value: data.getP99}, { title: 'p95', value: data.getP95}
, { title: 'p90', value: data.getP90}, { title: 'p75', value: data.getP75}, { title: 'p50', value: data.getP50}])}
/>
</Card>
</Col>
</Row>
<Row gutter={8}>
<Col xs={24} sm={24} md={24} lg={16} xl={16} style={{ marginTop: 8 }}>
<Card
title="Slow Endpoint"
bordered={false}
bodyStyle={{ padding: '0px 10px' }}
>
<RankList
data={data.getTopNSlowEndpoint}
renderValue={_ => `${_.value} ms`}
onClick={(key, item) => redirect(this.props.history, '/monitor/endpoint', { key })}
/>
</Card>
</Col>
<Col xs={24} sm={24} md={24} lg={8} xl={8} style={{ marginTop: 8 }}>
<Card
title="Service Throughput"
bordered={false}
bodyStyle={{ padding: '0px 10px' }}
>
<RankList
data={data.getTopNServiceThroughput}
renderValue={_ => `${_.value} cpm`}
color="#965fe466"
onClick={(key, item) => redirect(this.props.history, '/monitor/service', { key })}
/>
</Card>
</Col>
</Row>
</Panel>
);
}
}