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/09/10 08:40:55 UTC
[incubator-skywalking-ui] 02/02: Refactor topology page with v6
This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch 6.0.0/dev
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git
commit a204416a08164833b09257cee33c5575f62ceaf5
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Mon Sep 10 16:40:22 2018 +0800
Refactor topology page with v6
---
.roadhogrc.mock.js | 8 +-
mock/service.js | 134 ---------------------------------
mock/topology.js | 89 ++++++++++++++++++++++
src/components/Topology/AppTopology.js | 50 ++++--------
src/models/topology.js | 21 ++----
src/routes/Topology/Topology.js | 12 +--
6 files changed, 118 insertions(+), 196 deletions(-)
diff --git a/.roadhogrc.mock.js b/.roadhogrc.mock.js
index 1021e7f..28819b2 100644
--- a/.roadhogrc.mock.js
+++ b/.roadhogrc.mock.js
@@ -1,10 +1,8 @@
-import mockjs from 'mockjs';
import fs from 'fs';
import { delay } from 'roadhog-api-doc';
-import { getTopology, getServiceTopology } from './mock/topology';
+import { getTopology, getGlobalTopology, getServiceTopology } from './mock/topology';
import { getAllApplication, getApplication } from './mock/application';
import { searchServer, getServer } from './mock/server';
-import { searchService, getService } from './mock/service';
import { Alarms, getNoticeAlarm, AlarmTrend } from './mock/alarm';
import { TraceBrief, Trace } from './mock/trace'
import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
@@ -19,6 +17,7 @@ const resolvers = {
Query: {
getTopN,
getAllServices,
+ getGlobalTopology,
getServiceTopology,
searchEndpoint,
}
@@ -60,9 +59,6 @@ const proxy = {
'POST /api/application': getApplication,
'POST /api/server/search': searchServer,
'POST /api/server': getServer,
- 'POST /api/service/search': searchService,
- 'POST /api/service': getService,
- 'POST /api/service/options': getAllApplication,
'POST /api/notice': getNoticeAlarm,
'POST /api/login/account': (req, res) => {
const { password, userName } = req.body;
diff --git a/mock/service.js b/mock/service.js
deleted file mode 100644
index a3a21f4..0000000
--- a/mock/service.js
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * 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 mockjs from 'mockjs';
-
-export default {
- searchService(req, res) {
- res.json(mockjs.mock(
- {
- data: {
- 'searchService|5': [
- {
- 'key|+1': 3,
- label: function() { return `service-${this.key}`; }, // eslint-disable-line
- },
- ],
- },
- }
- ));
- },
- getService(req, res) {
- res.json(mockjs.mock(
- {
- data: {
- queryBasicTraces: () => {
- let offset = 0;
- let duration = 2500;
- return mockjs.mock(
- {
- 'traces|20': [{
- key: '@id',
- operationNames: ['200://wgmb.ev/jcknolzq'],
- duration: () => {
- duration -= 100;
- return duration;
- },
- start: function() { // eslint-disable-line
- offset = offset + 3600000; // eslint-disable-line
- const now = new Date().getTime(); // eslint-disable-line
- return `${now + offset}`;
- },// eslint-disable-line
- 'isError|1': true,
- 'traceIds|1-3': ['@guid'],
- }],
- total: '@natural(20, 1000)',
- },
- );
- },
- getServiceResponseTimeTrend: {
- 'trendList|60': ['@natural(100, 1000)'],
- },
- getServiceThroughputTrend: {
- 'trendList|60': ['@natural(500, 10000)'],
- },
- getServiceSLATrend: {
- 'trendList|60': ['@natural(8000, 10000)'],
- },
- getServiceTopology: () => {
- const upNodes = mockjs.mock({
- 'nodes|1-5': [
- {
- 'id|+1': 100,
- name: '@url',
- 'type|1': ['DUBBO', 'USER', 'SPRINGMVC'],
- 'calls|1000-2000': 1,
- 'sla|1-100.1-2': 1,
- 'numOfServiceAlarm|1-100': 1,
- },
- ],
- });
- const centerNodes = mockjs.mock({
- nodes: [
- {
- 'id|+1': 1,
- name: '@url',
- 'type|1': ['DUBBO', 'tomcat', 'SPRINGMVC'],
- 'calls|1000-2000': 1,
- 'sla|1-100.1-2': 1,
- 'numOfServiceAlarm|1-100': 1,
- },
- ],
- });
- const downNodes = mockjs.mock({
- 'nodes|2-5': [
- {
- 'id|+1': 200,
- name: '@url',
- 'type|1': ['Oracle', 'MYSQL', 'REDIS'],
- },
- ],
- });
- downNodes.nodes.push({ id: -111 });
- const nodes = upNodes.nodes.concat(centerNodes.nodes, downNodes.nodes);
- const calls = upNodes.nodes.map(node => (mockjs.mock({
- source: node.id,
- target: 1,
- 'isAlert|1': true,
- 'callType|1': ['rpc', 'http', 'dubbo'],
- 'cpm|0-1000': 1,
- 'avgResponseTime|500-5000': 0,
- }))).concat(downNodes.nodes.map(node => (mockjs.mock({
- source: 1,
- target: node.id,
- 'isAlert|1': true,
- 'callType|1': ['rpc', 'http', 'dubbo'],
- 'cpm|0-2000': 1,
- 'avgResponseTime|500-5000': 1,
- }))));
- calls.push({ source: '-175', target: 1, isAlert: false, callType: 'GRPC', cpm: 0, avgResponseTime: 52 });
- return {
- nodes,
- calls,
- };
- },
- },
- }
- ));
- },
-};
diff --git a/mock/topology.js b/mock/topology.js
index 5480589..fd1fe86 100644
--- a/mock/topology.js
+++ b/mock/topology.js
@@ -68,6 +68,95 @@ export default {
calls,
};
},
+ getGlobalTopology: () => {
+ const application = mockjs.mock({
+ 'nodes|2-3': [
+ {
+ 'id|+1': 2,
+ name: '@name',
+ 'type|1': ['DUBBO', 'tomcat', 'SPRINGMVC'],
+ isReal: true,
+ },
+ ],
+ });
+ const users = mockjs.mock({
+ nodes: [
+ {
+ id: 1,
+ name: 'User',
+ type: 'USER',
+ isReal: false,
+ },
+ ],
+ });
+ const resources = mockjs.mock({
+ 'nodes|5': [
+ {
+ 'id|+1': 200,
+ name: '@name',
+ 'type|1': ['Oracle', 'MYSQL', 'REDIS'],
+ isReal: false,
+ },
+ ],
+ });
+ const nodes = users.nodes.concat(application.nodes, resources.nodes);
+ const userConnectApplication = mockjs.mock({
+ calls: [
+ {
+ source: 1,
+ target: 2,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 2,
+ target: 3,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 3,
+ target: 2,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 2,
+ target: 200,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 2,
+ target: 201,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 3,
+ target: 202,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 3,
+ target: 203,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ {
+ source: 3,
+ target: 204,
+ 'callType|1': ['rpc', 'http', 'dubbo'],
+ 'cpm|100-2000': 1,
+ },
+ ],
+ });
+ return {
+ nodes,
+ calls: userConnectApplication.calls,
+ };
+ },
getTopology(req, res) {
res.json(mockjs.mock(
{
diff --git a/src/components/Topology/AppTopology.js b/src/components/Topology/AppTopology.js
index a0f5332..4f51d64 100644
--- a/src/components/Topology/AppTopology.js
+++ b/src/components/Topology/AppTopology.js
@@ -28,23 +28,10 @@ const conf = {
export default class AppTopology extends Base {
setUp = (elements) => {
const { nodes } = elements;
- const cpmArray = nodes.filter(_ => _.data && _.data.cpm).map(_ => _.data.cpm);
- const minCPM = Math.min(...cpmArray);
- const maxCPM = Math.max(...cpmArray);
- const { nodeSize: { min, max } } = conf;
- const scale = maxCPM > minCPM ? (max - min) / (maxCPM - minCPM) : 0;
const eleWithNewUsers = this.supplyUserNode(elements.edges);
return {
edges: eleWithNewUsers.edges,
- nodes: nodes.filter(_ => !_.data || _.data.id !== '1').map((_) => {
- return {
- ..._,
- data: {
- ..._.data,
- size: (_.data && _.data.cpm && scale > 0) ? (scale * (_.data.cpm - minCPM)) + min : min,
- },
- };
- }).concat(eleWithNewUsers.nodes),
+ nodes: nodes.filter(_ => !_.data || _.data.id !== '1').concat(eleWithNewUsers.nodes),
};
}
@@ -81,11 +68,11 @@ export default class AppTopology extends Base {
bindEvent = (cy) => {
const { onSelectedApplication } = this.props;
if (onSelectedApplication) {
- cy.on('select', 'node[sla]', (evt) => {
+ cy.on('select', 'node[?isReal]', (evt) => {
const node = evt.target;
onSelectedApplication(node.data());
});
- cy.on('unselect', 'node[sla]', () => {
+ cy.on('unselect', 'node[?isReal]', () => {
onSelectedApplication();
});
}
@@ -93,37 +80,32 @@ export default class AppTopology extends Base {
getStyle = () => {
return cytoscape.stylesheet()
- .selector('node[sla]')
+ .selector('node[?isReal]')
.css({
- width: 'data(size)',
- height: 'data(size)',
+ width: 60,
+ height: 60,
'text-valign': 'bottom',
'text-halign': 'center',
'font-family': 'Microsoft YaHei',
content: 'data(name)',
'text-margin-y': 10,
- 'border-width': ele => (ele.data('isAlarm') ? 10 : 0),
+ 'border-width': 0,
'border-color': '#A8071A',
- 'pie-1-background-color': '#2FC25B',
- 'pie-1-background-size': 'data(sla)',
- 'pie-1-background-opacity': 0.8,
- 'pie-2-background-color': '#F04864',
- 'pie-2-background-size': '100 - data(sla)',
- 'pie-2-background-opacity': 0.8,
+ 'background-image': ele => `img/node/${ele.data('type') ? ele.data('type').toUpperCase() : 'UNDEFINED'}.png`,
+ 'background-width': '60%',
+ 'background-height': '60%',
+ 'background-color': '#fff',
})
.selector(':selected')
.css({
- 'pie-size': '80%',
- 'background-color': ele => (ele.data('isAlarm') ? '#A8071A' : '#1890FF'),
- 'pie-1-background-opacity': 1,
- 'pie-2-background-opacity': 1,
+ 'border-width': 4,
})
.selector('.faded')
.css({
opacity: 0.25,
'text-opacity': 0,
})
- .selector('node[!sla]')
+ .selector('node[!isReal]')
.css({
width: 60,
height: 60,
@@ -144,10 +126,10 @@ export default class AppTopology extends Base {
'control-point-step-size': 100,
'target-arrow-shape': 'triangle',
'arrow-scale': 1.7,
- 'target-arrow-color': ele => (ele.data('isAlert') ? 'rgb(204, 0, 51)' : 'rgb(147, 198, 174)'),
- 'line-color': ele => (ele.data('isAlert') ? 'rgb(204, 0, 51)' : 'rgb(147, 198, 174)'),
+ 'target-arrow-color': 'rgb(147, 198, 174)',
+ 'line-color': 'rgb(147, 198, 174)',
width: 3,
- label: ele => `${ele.data('callType')} \n ${ele.data('cpm')} cpm / ${ele.data('avgResponseTime')} ms`,
+ label: ele => `${ele.data('callType')} \n ${ele.data('cpm')} cpm`,
'text-wrap': 'wrap',
color: 'rgb(110, 112, 116)',
'text-rotation': 'autorotate',
diff --git a/src/models/topology.js b/src/models/topology.js
index 9ae1643..760f1fa 100644
--- a/src/models/topology.js
+++ b/src/models/topology.js
@@ -16,41 +16,30 @@
*/
-import { generateModal } from '../utils/models';
+import { base } from '../utils/models';
-export default generateModal({
+export default base({
namespace: 'topology',
state: {
- getClusterTopology: {
+ getGlobalTopology: {
nodes: [],
calls: [],
},
},
dataQuery: `
query Topology($duration: Duration!) {
- getClusterTopology(duration: $duration) {
+ getGlobalTopology(duration: $duration) {
nodes {
id
name
type
- ... on ApplicationNode {
- sla
- cpm
- avgResponseTime
- apdex
- isAlarm
- numOfServer
- numOfServerAlarm
- numOfServiceAlarm
- }
+ isReal
}
calls {
source
target
- isAlert
callType
cpm
- avgResponseTime
}
}
}
diff --git a/src/routes/Topology/Topology.js b/src/routes/Topology/Topology.js
index bcd6a26..ff56a81 100644
--- a/src/routes/Topology/Topology.js
+++ b/src/routes/Topology/Topology.js
@@ -109,16 +109,16 @@ export default class Topology extends PureComponent {
}
filter = () => {
- const { topology: { variables: { appRegExps }, data: { getClusterTopology } } } = this.props;
+ const { topology: { variables: { appRegExps }, data: { getGlobalTopology } } } = this.props;
if (!appRegExps) {
- return getClusterTopology;
+ return getGlobalTopology;
}
- const nn = getClusterTopology.nodes.filter(_ => appRegExps
+ const nn = getGlobalTopology.nodes.filter(_ => appRegExps
.findIndex(r => _.name.match(r)) > -1);
- const cc = getClusterTopology.calls.filter(_ => nn
+ const cc = getGlobalTopology.calls.filter(_ => nn
.findIndex(n => n.id === _.source || n.id === _.target) > -1);
return {
- nodes: getClusterTopology.nodes.filter(_ => cc
+ nodes: getGlobalTopology.nodes.filter(_ => cc
.findIndex(c => c.source === _.id || c.target === _.id) > -1),
calls: cc,
};
@@ -206,7 +206,7 @@ export default class Topology extends PureComponent {
tokenSeparators={[',']}
value={appFilters}
>
- {data.getClusterTopology.nodes.filter(_ => _.sla)
+ {data.getGlobalTopology.nodes.filter(_ => _.sla)
.map(_ => <Option key={_.name}>{_.name}</Option>)}
</Select>
<DescriptionList layout="vertical">