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">