You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@skywalking.apache.org by ha...@apache.org on 2018/04/27 03:28:36 UTC
[incubator-skywalking-ui] branch 5.0.0/beta updated: Fix #149
Support Topology links Application, Trace and Alarm
This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch 5.0.0/beta
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git
The following commit(s) were added to refs/heads/5.0.0/beta by this push:
new e40c7b4 Fix #149 Support Topology links Application,Trace and Alarm
e40c7b4 is described below
commit e40c7b40003827e2f718b356fbbcbacf0d5e79b6
Author: hanahmily <ha...@gmail.com>
AuthorDate: Fri Apr 27 11:23:29 2018 +0800
Fix #149 Support Topology links Application,Trace and Alarm
---
src/components/ApplicationLitePanel/index.js | 39 ++++++++++++++
src/components/Topology/AppTopology.js | 10 ++++
src/components/Topology/Base.js | 3 ++
src/models/topology.js | 4 +-
src/models/trace.js | 19 +++++++
src/routes/Topology/Topology.js | 79 ++++++++++++++++++++++++----
6 files changed, 142 insertions(+), 12 deletions(-)
diff --git a/src/components/ApplicationLitePanel/index.js b/src/components/ApplicationLitePanel/index.js
new file mode 100644
index 0000000..1620a10
--- /dev/null
+++ b/src/components/ApplicationLitePanel/index.js
@@ -0,0 +1,39 @@
+/**
+ * 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 { Avatar } from 'antd';
+import DescriptionList from '../../components/DescriptionList';
+
+const { Description } = DescriptionList;
+
+export default class ApplicationLitePanel extends PureComponent {
+ render() {
+ const { appInfo } = this.props;
+ return (
+ <div>
+ {appInfo.isAlarm ? <Avatar style={{ backgroundColor: '#F04864', marginBottom: 10 }} icon="bell" /> : null}
+ <DescriptionList col={1} layout="vertical" >
+ <Description term="SLA">{appInfo.sla}%</Description>
+ <Description term="Calls Per Minute">{appInfo.cpm}</Description>
+ <Description term="Avg Response Time">{appInfo.avgResponseTime} ms</Description>
+ <Description term="Server Alarm">{appInfo.numOfServerAlarm} / {appInfo.numOfServer}</Description>
+ </DescriptionList>
+ </div>
+ );
+ }
+}
diff --git a/src/components/Topology/AppTopology.js b/src/components/Topology/AppTopology.js
index cf8af5f..23e41da 100644
--- a/src/components/Topology/AppTopology.js
+++ b/src/components/Topology/AppTopology.js
@@ -47,6 +47,16 @@ export default class AppTopology extends Base {
}),
};
}
+ bindEvent = (cy) => {
+ const { onSelectedApplication } = this.props;
+ cy.on('select', 'node[sla]', (evt) => {
+ const node = evt.target;
+ onSelectedApplication(node.data());
+ });
+ cy.on('unselect', 'node[sla]', () => {
+ onSelectedApplication();
+ });
+ }
getStyle = () => {
return cytoscape.stylesheet()
.selector('node[sla]')
diff --git a/src/components/Topology/Base.js b/src/components/Topology/Base.js
index e9b29ab..4f3a676 100644
--- a/src/components/Topology/Base.js
+++ b/src/components/Topology/Base.js
@@ -51,6 +51,9 @@ export default class Base extends Component {
elements: nextElements,
style: this.getStyle(),
});
+ if (this.bindEvent) {
+ this.bindEvent(this.cy);
+ }
}
componentWillReceiveProps(nextProps) {
if (nextProps.elements === this.elements) {
diff --git a/src/models/topology.js b/src/models/topology.js
index 489317d..86e0436 100644
--- a/src/models/topology.js
+++ b/src/models/topology.js
@@ -35,7 +35,7 @@ export default generateModal({
type
... on ApplicationNode {
sla
- callsPerSec
+ cpm
avgResponseTime
apdex
isAlarm
@@ -49,7 +49,7 @@ export default generateModal({
target
isAlert
callType
- callsPerSec
+ cpm
avgResponseTime
}
}
diff --git a/src/models/trace.js b/src/models/trace.js
index 64a879a..48184e9 100644
--- a/src/models/trace.js
+++ b/src/models/trace.js
@@ -134,4 +134,23 @@ export default generateModal({
};
},
},
+ subscriptions: {
+ setup({ history, dispatch }) {
+ return history.listen(({ pathname, state }) => {
+ if (pathname === '/trace' && state) {
+ dispatch({
+ type: 'saveVariables',
+ payload: {
+ values: {
+ applicationId: state.key,
+ },
+ labels: {
+ applicationId: state.label,
+ },
+ },
+ });
+ }
+ });
+ },
+ },
});
diff --git a/src/routes/Topology/Topology.js b/src/routes/Topology/Topology.js
index 64103e4..d0b2866 100644
--- a/src/routes/Topology/Topology.js
+++ b/src/routes/Topology/Topology.js
@@ -18,10 +18,24 @@
import React, { PureComponent } from 'react';
import { connect } from 'dva';
+import { Row, Col, Card, Icon } from 'antd';
import { ChartCard } from '../../components/Charts';
import { AppTopology } from '../../components/Topology';
import { Panel } from '../../components/Page';
+import ApplicationLitePanel from '../../components/ApplicationLitePanel';
+import DescriptionList from '../../components/DescriptionList';
+import { redirect } from '../../utils/utils';
+const { Description } = DescriptionList;
+
+const colResponsiveProps = {
+ xs: 24,
+ sm: 24,
+ md: 24,
+ lg: 12,
+ xl: 12,
+ style: { marginTop: 8 },
+};
@connect(state => ({
topology: state.topology,
duration: state.global.duration,
@@ -37,20 +51,65 @@ export default class Topology extends PureComponent {
payload: { variables },
});
}
+ handleSelectedApplication = (appInfo) => {
+ if (appInfo) {
+ this.props.dispatch({
+ type: 'topology/saveData',
+ payload: { appInfo },
+ });
+ } else {
+ this.props.dispatch({
+ type: 'topology/saveData',
+ payload: { appInfo: null },
+ });
+ }
+ }
+ renderActions = () => {
+ const { data: { appInfo } } = this.props.topology;
+ return [
+ <Icon type="appstore" onClick={() => redirect(this.props.history, '/application', { key: appInfo.id, label: appInfo.name })} />,
+ <Icon type="exception" onClick={() => redirect(this.props.history, '/trace', { key: appInfo.id, label: appInfo.name })} />,
+ appInfo.isAlarm ? <Icon type="bell" onClick={() => redirect(this.props.history, '/alarm')} /> : null,
+ ];
+ }
render() {
const { data } = this.props.topology;
return (
<Panel globalVariables={this.props.globalVariables} onChange={this.handleChange}>
- <ChartCard
- title="Topology Map"
- >
- {data.getClusterTopology.nodes.length > 0 ? (
- <AppTopology
- height={this.props.graphHeight}
- elements={data.getClusterTopology}
- />
- ) : null}
- </ChartCard>
+ <Row gutter={8}>
+ <Col {...{ ...colResponsiveProps, xl: 18, lg: 16 }}>
+ <ChartCard
+ title="Topology Map"
+ >
+ {data.getClusterTopology.nodes.length > 0 ? (
+ <AppTopology
+ height={this.props.graphHeight}
+ elements={data.getClusterTopology}
+ onSelectedApplication={this.handleSelectedApplication}
+ />
+ ) : null}
+ </ChartCard>
+ </Col>
+ <Col {...{ ...colResponsiveProps, xl: 6, lg: 8 }}>
+ {data.appInfo ? (
+ <Card
+ title={data.appInfo.name}
+ bodyStyle={{ height: 558 }}
+ actions={this.renderActions()}
+ >
+ <ApplicationLitePanel appInfo={data.appInfo} />
+ </Card>
+ )
+ : (
+ <Card title="Overview" style={{ height: 662 }}>
+ <DescriptionList col={1} layout="vertical" >
+ <Description term="Total Application">{data.getClusterTopology.nodes.filter(_ => _.sla).length}</Description>
+ <Description term="Application Alarm">{data.getClusterTopology.nodes.filter(_ => _.isAlarm).length}</Description>
+ </DescriptionList>
+ </Card>
+ )}
+ </Col>
+ </Row>
</Panel>
);
}
--
To stop receiving notification emails like this one, please contact
hanahmily@apache.org.