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 a1bd2ff Service Topology
a1bd2ff is described below
commit a1bd2ffeda4c8fdf487db145f4d1dd77482c2b88
Author: hanahmily <[email protected]>
AuthorDate: Fri Jan 12 15:58:24 2018 +0800
Service Topology
---
src/main/frontend/mock/service.js | 57 ++++++++++++++++
src/main/frontend/src/components/Topology/Base.js | 21 ++++--
.../src/components/Topology/ServiceTopology.js | 77 ++++++++++++++++++++++
src/main/frontend/src/components/Topology/conf.js | 2 +
src/main/frontend/src/components/Topology/index.js | 2 +
src/main/frontend/src/routes/Service/Service.js | 3 +-
6 files changed, 155 insertions(+), 7 deletions(-)
diff --git a/src/main/frontend/mock/service.js
b/src/main/frontend/mock/service.js
index d8997fb..1f0cf0a 100644
--- a/src/main/frontend/mock/service.js
+++ b/src/main/frontend/mock/service.js
@@ -15,6 +15,63 @@ export default {
getServiceSLATrend: {
'trendList|15': ['@natural(80, 100)'],
},
+ getServiceTopology: () => {
+ const upNodes = mockjs.mock({
+ 'nodes|1-5': [
+ {
+ 'id|+1': 100,
+ name: '@name',
+ 'type|1': ['DUBBO', 'USER', 'SPRINGMVC'],
+ 'calls|1000-2000': 1,
+ 'sla|1-100.1-2': 1,
+ 'apdex|0.2': 1,
+ 'numOfServiceAlarm|1-100': 1,
+ },
+ ],
+ });
+ const centerNodes = mockjs.mock({
+ nodes: [
+ {
+ 'id|+1': 1,
+ name: '@name',
+ 'type|1': ['DUBBO', 'tomcat', 'SPRINGMVC'],
+ 'calls|1000-2000': 1,
+ 'sla|1-100.1-2': 1,
+ 'apdex|0.2': 1,
+ 'numOfServiceAlarm|1-100': 1,
+ },
+ ],
+ });
+ const downNodes = mockjs.mock({
+ 'nodes|2-5': [
+ {
+ 'id|+1': 200,
+ name: '@name',
+ 'type|1': ['Oracle', 'MYSQL', 'REDIS'],
+ },
+ ],
+ });
+ const nodes = upNodes.nodes.concat(centerNodes.nodes,
downNodes.nodes);
+ const calls = upNodes.nodes.map(node => (mockjs.mock({
+ source: node.id,
+ target: 1,
+ 'isAlarm|1': true,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'callsPerSec|100-2000': 1,
+ 'responseTimePerSec|500-5000': 1,
+ }))).concat(downNodes.nodes.map(node => (mockjs.mock({
+ source: 1,
+ target: node.id,
+ 'isAlarm|1': true,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'callsPerSec|100-2000': 1,
+ 'responseTimePerSec|500-5000': 1,
+ }))));
+ return {
+ nodes,
+ calls,
+ };
+ },
},
}
));
diff --git a/src/main/frontend/src/components/Topology/Base.js
b/src/main/frontend/src/components/Topology/Base.js
index 99f279f..6eeb0cd 100644
--- a/src/main/frontend/src/components/Topology/Base.js
+++ b/src/main/frontend/src/components/Topology/Base.js
@@ -26,10 +26,16 @@ export default class Base extends Component {
return;
}
this.cy.json({ elements: this.transform(nextProps.elements), style:
this.getStyle() });
- this.cy.layout({
- name: 'cose',
- animate: true,
- }).run();
+ const layout = this.cy.layout({
+ name: 'cose-bilkent',
+ animate: 'end',
+ dealEdgeLength: 200,
+ padding: 10,
+ });
+ layout.pon('layoutstop').then(() => {
+ this.cy.minZoom(this.cy.zoom());
+ });
+ layout.run();
}
shouldComponentUpdate() {
return false;
@@ -41,12 +47,15 @@ export default class Base extends Component {
return this.cy;
}
transform(elements) {
+ if (!elements) {
+ return [];
+ }
this.elements = elements;
const { nodes, calls } = elements;
return {
nodes: nodes.map(node => ({ data: node })),
- edges: calls.filter(call => (nodes.findIndex(node => node.id ===
call.source)
- && nodes.findIndex(node => node.id === call.target)))
+ edges: calls.filter(call => (nodes.findIndex(node => node.id ===
call.source) > -1
+ && nodes.findIndex(node => node.id === call.target) > -1))
.map(call => ({ data: { ...call, id: `${call.source}-${call.target}` }
})),
};
}
diff --git a/src/main/frontend/src/components/Topology/ServiceTopology.js
b/src/main/frontend/src/components/Topology/ServiceTopology.js
new file mode 100644
index 0000000..bb80c34
--- /dev/null
+++ b/src/main/frontend/src/components/Topology/ServiceTopology.js
@@ -0,0 +1,77 @@
+import styles from './index.less';
+import Base from './Base';
+
+export default class ServiceTopology 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('numOfServiceAlarm') > 0 ? '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': 'bezier',
+ 'control-point-step-size': 100,
+ '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="alert.png" class="${styles.logo}"/>
+ <span class="${styles.alert}">${data.numOfServiceAlarm}</span>
+ </div>
+ </div>`;
+ },
+ },
+ ];
+ }
+}
diff --git a/src/main/frontend/src/components/Topology/conf.js
b/src/main/frontend/src/components/Topology/conf.js
index abc6614..685b68d 100644
--- a/src/main/frontend/src/components/Topology/conf.js
+++ b/src/main/frontend/src/components/Topology/conf.js
@@ -1,4 +1,6 @@
const conf = {
+ zoom: 1,
+ maxZoom: 1,
boxSelectionEnabled: true,
autounselectify: true,
layout: {
diff --git a/src/main/frontend/src/components/Topology/index.js
b/src/main/frontend/src/components/Topology/index.js
index 554f2d5..96bb101 100644
--- a/src/main/frontend/src/components/Topology/index.js
+++ b/src/main/frontend/src/components/Topology/index.js
@@ -1,5 +1,7 @@
import AppTopology from './AppTopology';
+import ServiceTopology from './ServiceTopology';
export default {
AppTopology,
+ ServiceTopology,
};
diff --git a/src/main/frontend/src/routes/Service/Service.js
b/src/main/frontend/src/routes/Service/Service.js
index 4e4fdc5..4cfac85 100644
--- a/src/main/frontend/src/routes/Service/Service.js
+++ b/src/main/frontend/src/routes/Service/Service.js
@@ -5,6 +5,7 @@ import {
ChartCard, MiniArea, MiniBar,
} from '../../components/Charts';
import { timeRange } from '../../utils/utils';
+import { ServiceTopology } from '../../components/Topology';
const { Option } = Select;
@@ -95,7 +96,7 @@ export default class Service extends Component {
bordered={false}
bodyStyle={{ padding: 0 }}
>
- <div style={{ height: 430 }}>The toplogy of service
dependencies</div>
+ <ServiceTopology
elements={this.props.service.getServiceTopology} />
</Card>
</Col>
</Row>
--
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].