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.