This is an automated email from the ASF dual-hosted git repository. hanahmily pushed a commit to branch feature/5.0.0 in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git
The following commit(s) were added to refs/heads/feature/5.0.0 by this push: new 35a2bae Add application topology 35a2bae is described below commit 35a2bae1584729bc009919b40de92657f0a9fe60 Author: gaohongtao <hanahm...@gmail.com> AuthorDate: Thu Jan 11 19:51:31 2018 +0800 Add application topology --- src/main/frontend/mock/dashboard.js | 85 +++++++++++++++++++++ src/main/frontend/public/alert.png | Bin 0 -> 4326 bytes src/main/frontend/public/app.jpg | Bin 0 -> 8847 bytes src/main/frontend/public/data.png | Bin 0 -> 7245 bytes src/main/frontend/public/img/node/DUBBO.png | Bin 0 -> 3537 bytes .../frontend/public/img/node/FeignDefaultHttp.png | Bin 0 -> 3892 bytes src/main/frontend/public/img/node/H2.png | Bin 0 -> 2681 bytes src/main/frontend/public/img/node/HPROSE.png | Bin 0 -> 2158 bytes src/main/frontend/public/img/node/HTTPCLIENT.png | Bin 0 -> 10718 bytes src/main/frontend/public/img/node/JETTY.png | Bin 0 -> 2838 bytes src/main/frontend/public/img/node/JETTYSERVER.png | Bin 0 -> 9889 bytes src/main/frontend/public/img/node/MONGODB.png | Bin 0 -> 4161 bytes src/main/frontend/public/img/node/MOTAN.png | Bin 0 -> 17288 bytes src/main/frontend/public/img/node/MYSQL.png | Bin 0 -> 4980 bytes src/main/frontend/public/img/node/NutzHttp.png | Bin 0 -> 12509 bytes src/main/frontend/public/img/node/NutzMvc.png | Bin 0 -> 14196 bytes src/main/frontend/public/img/node/OKHTTP.png | Bin 0 -> 4070 bytes src/main/frontend/public/img/node/Oracle.png | Bin 0 -> 4312 bytes src/main/frontend/public/img/node/REDIS.png | Bin 0 -> 5178 bytes src/main/frontend/public/img/node/RESIN.png | Bin 0 -> 15092 bytes src/main/frontend/public/img/node/SPRINGMVC.png | Bin 0 -> 11226 bytes src/main/frontend/public/img/node/STRUTS2.png | Bin 0 -> 11643 bytes src/main/frontend/public/img/node/UNDEFINED.png | Bin 0 -> 2918 bytes src/main/frontend/public/img/node/USER.png | Bin 0 -> 2444 bytes src/main/frontend/public/img/node/tomcat.png | Bin 0 -> 4302 bytes .../src/components/Topology/AppTopology.js | 78 +++++++++++++++++++ src/main/frontend/src/components/Topology/Base.js | 42 ++++++++++ .../frontend/src/components/Topology/Topology.js | 37 --------- src/main/frontend/src/components/Topology/conf.js | 5 ++ src/main/frontend/src/components/Topology/index.js | 5 ++ .../frontend/src/components/Topology/index.less | 17 +++++ src/main/frontend/src/models/dashboard.js | 4 + .../frontend/src/routes/Dashboard/Dashboard.js | 3 +- 33 files changed, 238 insertions(+), 38 deletions(-) diff --git a/src/main/frontend/mock/dashboard.js b/src/main/frontend/mock/dashboard.js index c97c655..37f2e79 100644 --- a/src/main/frontend/mock/dashboard.js +++ b/src/main/frontend/mock/dashboard.js @@ -20,6 +20,91 @@ export default { }, 'getTopNSlowService|10': [{ 'key|+1': 1, name: '@name', 'avgResponseTime|200-1000': 1 }], 'getTopNServerThroughput|10': [{ 'key|+1': 1, name: '@name', 'tps|100-10000': 1 }], + getClusterTopology: () => { + const application = mockjs.mock({ + 'nodes|5-20': [ + { + data: { + 'id|+1': 1, + name: '@name', + 'type|1': ['DUBBO', 'tomcat', 'SPRINGMVC'], + 'calls|1000-2000': 1, + 'sla|1-100.1-2': 1, + 'apdex|0.2': 1, + 'numOfServer|1-100': 1, + 'numOfServerAlarm|1-100': 1, + 'numOfServiceAlarm|1-100': 1, + 'isIncomingNode|1': true, + }, + }, + ], + }); + const users = mockjs.mock({ + 'nodes|1-3': [ + { + data: { + 'id|+1': 100, + name: 'User', + type: 'USER', + }, + }, + ], + }); + const resources = mockjs.mock({ + 'nodes|2-5': [ + { + data: { + 'id|+1': 200, + name: '@name', + 'type|1': ['Oracle', 'MYSQL', 'REDIS'], + }, + }, + ], + }); + const nodes = application.nodes.concat(users.nodes, resources.nodes); + const userConnectApplication = mockjs.mock({ + 'calls|1-3': [{ + data: { + 'source|+1': 100, + 'target|+1': 1, + 'isAlarm|1': true, + 'callType|1': ['rpc', 'http', 'dubbo'], + 'callsPerSec|100-2000': 1, + 'responseTimePerSec: 500-5000': 1, + }, + }], + }); + const applicationConnectApplication = mockjs.mock({ + 'calls|1-3': [{ + data: { + 'source|+1': 1, + 'target|+1': 1, + 'isAlarm|1': true, + 'callType|1': ['rpc', 'http', 'dubbo'], + 'callsPerSec|100-2000': 1, + 'responseTimePerSec: 500-5000': 1, + }, + }], + }); + const applicationConnectResources = mockjs.mock({ + 'calls|1-3': [{ + data: { + 'source|+1': 1, + 'target|+1': 200, + 'isAlarm|1': true, + 'callType|1': ['rpc', 'http', 'dubbo'], + 'callsPerSec|100-2000': 1, + 'responseTimePerSec: 500-5000': 1, + }, + }], + }); + const calls = userConnectApplication.calls + .concat(applicationConnectApplication.calls, applicationConnectResources.calls); + return { + nodes, + calls, + }; + }, }, } )); diff --git a/src/main/frontend/public/alert.png b/src/main/frontend/public/alert.png new file mode 100755 index 0000000..e24e202 Binary files /dev/null and b/src/main/frontend/public/alert.png differ diff --git a/src/main/frontend/public/app.jpg b/src/main/frontend/public/app.jpg new file mode 100755 index 0000000..8d8166d Binary files /dev/null and b/src/main/frontend/public/app.jpg differ diff --git a/src/main/frontend/public/data.png b/src/main/frontend/public/data.png new file mode 100755 index 0000000..7c15d62 Binary files /dev/null and b/src/main/frontend/public/data.png differ diff --git a/src/main/frontend/public/img/node/DUBBO.png b/src/main/frontend/public/img/node/DUBBO.png new file mode 100644 index 0000000..c388222 Binary files /dev/null and b/src/main/frontend/public/img/node/DUBBO.png differ diff --git a/src/main/frontend/public/img/node/FeignDefaultHttp.png b/src/main/frontend/public/img/node/FeignDefaultHttp.png new file mode 100644 index 0000000..b727c0f Binary files /dev/null and b/src/main/frontend/public/img/node/FeignDefaultHttp.png differ diff --git a/src/main/frontend/public/img/node/H2.png b/src/main/frontend/public/img/node/H2.png new file mode 100644 index 0000000..29e78b1 Binary files /dev/null and b/src/main/frontend/public/img/node/H2.png differ diff --git a/src/main/frontend/public/img/node/HPROSE.png b/src/main/frontend/public/img/node/HPROSE.png new file mode 100644 index 0000000..a90bd98 Binary files /dev/null and b/src/main/frontend/public/img/node/HPROSE.png differ diff --git a/src/main/frontend/public/img/node/HTTPCLIENT.png b/src/main/frontend/public/img/node/HTTPCLIENT.png new file mode 100644 index 0000000..00f158f Binary files /dev/null and b/src/main/frontend/public/img/node/HTTPCLIENT.png differ diff --git a/src/main/frontend/public/img/node/JETTY.png b/src/main/frontend/public/img/node/JETTY.png new file mode 100644 index 0000000..85d8167 Binary files /dev/null and b/src/main/frontend/public/img/node/JETTY.png differ diff --git a/src/main/frontend/public/img/node/JETTYSERVER.png b/src/main/frontend/public/img/node/JETTYSERVER.png new file mode 100644 index 0000000..31cafa8 Binary files /dev/null and b/src/main/frontend/public/img/node/JETTYSERVER.png differ diff --git a/src/main/frontend/public/img/node/MONGODB.png b/src/main/frontend/public/img/node/MONGODB.png new file mode 100644 index 0000000..93d9a01 Binary files /dev/null and b/src/main/frontend/public/img/node/MONGODB.png differ diff --git a/src/main/frontend/public/img/node/MOTAN.png b/src/main/frontend/public/img/node/MOTAN.png new file mode 100644 index 0000000..ff57bf9 Binary files /dev/null and b/src/main/frontend/public/img/node/MOTAN.png differ diff --git a/src/main/frontend/public/img/node/MYSQL.png b/src/main/frontend/public/img/node/MYSQL.png new file mode 100644 index 0000000..34530b4 Binary files /dev/null and b/src/main/frontend/public/img/node/MYSQL.png differ diff --git a/src/main/frontend/public/img/node/NutzHttp.png b/src/main/frontend/public/img/node/NutzHttp.png new file mode 100644 index 0000000..506cfad Binary files /dev/null and b/src/main/frontend/public/img/node/NutzHttp.png differ diff --git a/src/main/frontend/public/img/node/NutzMvc.png b/src/main/frontend/public/img/node/NutzMvc.png new file mode 100644 index 0000000..dce0725 Binary files /dev/null and b/src/main/frontend/public/img/node/NutzMvc.png differ diff --git a/src/main/frontend/public/img/node/OKHTTP.png b/src/main/frontend/public/img/node/OKHTTP.png new file mode 100644 index 0000000..c4c19a9 Binary files /dev/null and b/src/main/frontend/public/img/node/OKHTTP.png differ diff --git a/src/main/frontend/public/img/node/Oracle.png b/src/main/frontend/public/img/node/Oracle.png new file mode 100644 index 0000000..7b1cd56 Binary files /dev/null and b/src/main/frontend/public/img/node/Oracle.png differ diff --git a/src/main/frontend/public/img/node/REDIS.png b/src/main/frontend/public/img/node/REDIS.png new file mode 100644 index 0000000..5c6a5a4 Binary files /dev/null and b/src/main/frontend/public/img/node/REDIS.png differ diff --git a/src/main/frontend/public/img/node/RESIN.png b/src/main/frontend/public/img/node/RESIN.png new file mode 100644 index 0000000..aa0eed3 Binary files /dev/null and b/src/main/frontend/public/img/node/RESIN.png differ diff --git a/src/main/frontend/public/img/node/SPRINGMVC.png b/src/main/frontend/public/img/node/SPRINGMVC.png new file mode 100644 index 0000000..626f832 Binary files /dev/null and b/src/main/frontend/public/img/node/SPRINGMVC.png differ diff --git a/src/main/frontend/public/img/node/STRUTS2.png b/src/main/frontend/public/img/node/STRUTS2.png new file mode 100644 index 0000000..5f1d499 Binary files /dev/null and b/src/main/frontend/public/img/node/STRUTS2.png differ diff --git a/src/main/frontend/public/img/node/UNDEFINED.png b/src/main/frontend/public/img/node/UNDEFINED.png new file mode 100644 index 0000000..3e1d681 Binary files /dev/null and b/src/main/frontend/public/img/node/UNDEFINED.png differ diff --git a/src/main/frontend/public/img/node/USER.png b/src/main/frontend/public/img/node/USER.png new file mode 100644 index 0000000..a195d8f Binary files /dev/null and b/src/main/frontend/public/img/node/USER.png differ diff --git a/src/main/frontend/public/img/node/tomcat.png b/src/main/frontend/public/img/node/tomcat.png new file mode 100644 index 0000000..5c4a1a3 Binary files /dev/null and b/src/main/frontend/public/img/node/tomcat.png differ diff --git a/src/main/frontend/src/components/Topology/AppTopology.js b/src/main/frontend/src/components/Topology/AppTopology.js new file mode 100644 index 0000000..0d7e59f --- /dev/null +++ b/src/main/frontend/src/components/Topology/AppTopology.js @@ -0,0 +1,78 @@ +import styles from './index.less'; +import Base from './Base'; + +export default class AppTopology extends Base { + getStyle = () => { + return [ + { + selector: 'node[calls]', + style: { + width: 120, + height: 120, + 'text-valign': 'bottom', + 'text-halign': 'center', + 'background-color': '#fff', + 'border-width': 3, + 'border-color': ele => (ele.data('isAlarm') ? 'red' : 'rgb(99, 160, 167)'), + 'font-family': 'Microsoft YaHei', + label: 'data(name)', + }, + }, + { + selector: 'node[!calls]', + style: { + width: 60, + height: 60, + 'text-valign': 'bottom', + 'text-halign': 'center', + 'background-color': '#fff', + 'background-image': ele => `img/node/${ele.data('type') ? ele.data('type') : 'UNDEFINED'}.png`, + 'background-width': '60%', + 'background-height': '60%', + 'border-width': 1, + 'font-family': 'Microsoft YaHei', + label: 'data(name)', + }, + }, + { + selector: 'edge', + style: { + 'curve-style': 'unbundled-bezier', + 'target-arrow-shape': 'triangle', + 'target-arrow-color': ele => (ele.data('isAlarm') ? 'red' : 'rgb(147, 198, 174)'), + 'line-color': ele => (ele.data('isAlarm') ? 'red' : 'rgb(147, 198, 174)'), + width: 2, + label: ele => `${ele.data('callType')} \n ${ele.data('callsPerSec')} tps / ${ele.data('responseTimePerSec')} ms`, + 'text-wrap': 'wrap', + color: 'rgb(110, 112, 116)', + 'text-rotation': 'autorotate', + }, + }, + ]; + } + getNodeLabel = () => { + return [ + { + query: 'node[calls]', + halign: 'center', + valign: 'center', + halignBox: 'center', + valignBox: 'center', + cssClass: `${styles.node}`, + tpl(data) { + return ` + <div class="${styles.circle}"> + <div class="node-percentage">${data.sla}%</div> + <div>${data.calls} calls/s</div> + <div> + <img src="data.png" class="${styles.logo}"/>${data.numOfServer} + <img src="alert.png" class="${styles.logo}"/> + <span class="${styles.alert}">${data.numOfServerAlarm}</span> + </div> + <div>${data.apdex} Apdex</div> + </div>`; + }, + }, + ]; + } +} diff --git a/src/main/frontend/src/components/Topology/Base.js b/src/main/frontend/src/components/Topology/Base.js new file mode 100644 index 0000000..b934a02 --- /dev/null +++ b/src/main/frontend/src/components/Topology/Base.js @@ -0,0 +1,42 @@ +import React, { Component } from 'react'; +import cytoscape from 'cytoscape'; +import coseBilkent from 'cytoscape-cose-bilkent'; +import nodeHtmlLabel from 'cytoscape-node-html-label'; +import conf from './conf'; + +cytoscape.use(coseBilkent); +cytoscape.use(nodeHtmlLabel); + +const cyStyle = { + height: '400px', + display: 'block', +}; + +export default class Base extends Component { + componentDidMount() { + this.elements = this.props.elements; + const { nodes, calls } = this.props.elements; + this.cy = cytoscape({ ...conf, elements: { nodes, edges: calls }, style: this.getStyle() }); + this.cy.nodeHtmlLabel(this.getNodeLabel()); + } + componentWillReceiveProps(nextProps) { + if (nextProps.elements === this.elements) { + return; + } + this.elements = nextProps.elements; + const { nodes, calls } = this.elements; + this.cy.json({ elements: { nodes, edges: calls }, style: this.getStyle() }); + } + shouldComponentUpdate() { + return false; + } + componentWillUnmount() { + this.cy.destroy(); + } + getCy() { + return this.cy; + } + render() { + return (<div style={cyStyle} ref={(el) => { conf.container = el; }} />); + } +} diff --git a/src/main/frontend/src/components/Topology/Topology.js b/src/main/frontend/src/components/Topology/Topology.js deleted file mode 100644 index 475603e..0000000 --- a/src/main/frontend/src/components/Topology/Topology.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Component } from 'react'; -import cytoscape from 'cytoscape'; -import coseBilkent from 'cytoscape-cose-bilkent'; -import nodeHtmlLabel from 'cytoscape-node-html-label'; -import conf from './conf'; - -cytoscape.use(coseBilkent); -cytoscape.use(nodeHtmlLabel); - -const cyStyle = { - height: '400px', - display: 'block', -}; - -class Topology extends Component { - componentDidMount() { - this.cy = cytoscape(conf); - this.cy.json({ elements: this.props.elements }); - } - componentWillReceiveProps(nextProps) { - this.cy.json(nextProps); - } - shouldComponentUpdate() { - return false; - } - componentWillUnmount() { - this.cy.destroy(); - } - getCy() { - return this.cy; - } - render() { - return <div style={cyStyle} ref={(rel) => { conf.container = rel; }} />; - } -} - -export default Topology; diff --git a/src/main/frontend/src/components/Topology/conf.js b/src/main/frontend/src/components/Topology/conf.js index 70893f1..abc6614 100644 --- a/src/main/frontend/src/components/Topology/conf.js +++ b/src/main/frontend/src/components/Topology/conf.js @@ -1,6 +1,11 @@ const conf = { boxSelectionEnabled: true, autounselectify: true, + layout: { + name: 'cose-bilkent', + animate: true, + idealEdgeLength: 100, + }, }; export default conf; diff --git a/src/main/frontend/src/components/Topology/index.js b/src/main/frontend/src/components/Topology/index.js new file mode 100644 index 0000000..554f2d5 --- /dev/null +++ b/src/main/frontend/src/components/Topology/index.js @@ -0,0 +1,5 @@ +import AppTopology from './AppTopology'; + +export default { + AppTopology, +}; diff --git a/src/main/frontend/src/components/Topology/index.less b/src/main/frontend/src/components/Topology/index.less new file mode 100644 index 0000000..4dca934 --- /dev/null +++ b/src/main/frontend/src/components/Topology/index.less @@ -0,0 +1,17 @@ +.node { + text-align: center; +} + +.logo { + height: 15px; + vertical-align: middle; + margin: -3px 2px 0px 0px; +} + +.circle { + font-size: 16px; +} + +.alert { + color: red; +} diff --git a/src/main/frontend/src/models/dashboard.js b/src/main/frontend/src/models/dashboard.js index 0796d23..f5ba419 100644 --- a/src/main/frontend/src/models/dashboard.js +++ b/src/main/frontend/src/models/dashboard.js @@ -18,6 +18,10 @@ export default { }, getTopNSlowService: [], getTopNServerThroughput: [], + getClusterTopology: { + nodes: [], + calls: [], + }, }, effects: { *fetch({ payload }, { call, put }) { diff --git a/src/main/frontend/src/routes/Dashboard/Dashboard.js b/src/main/frontend/src/routes/Dashboard/Dashboard.js index 3400e24..888d8e8 100644 --- a/src/main/frontend/src/routes/Dashboard/Dashboard.js +++ b/src/main/frontend/src/routes/Dashboard/Dashboard.js @@ -5,6 +5,7 @@ import { ChartCard, Pie, MiniArea, Field, } from '../../components/Charts'; import { timeRange } from '../../utils/utils'; +import { AppTopology } from '../../components/Topology'; @connect(state => ({ dashboard: state.dashboard, @@ -96,7 +97,7 @@ export default class Dashboard extends Component { bordered={false} bodyStyle={{ padding: 0, marginTop: 24 }} > - <div style={{ height: 480 }}>Topoloy</div> + <AppTopology elements={this.props.dashboard.getClusterTopology} /> </Card> <Row gutter={24}> <Col xs={24} sm={24} md={24} lg={12} xl={12} style={{ marginTop: 24 }}> -- To stop receiving notification emails like this one, please contact ['"commits@skywalking.apache.org" <commits@skywalking.apache.org>'].