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:53 UTC

[incubator-skywalking-ui] branch 6.0.0/dev updated (d2af186 -> a204416)

This is an automated email from the ASF dual-hosted git repository.

hanahmily pushed a change to branch 6.0.0/dev
in repository https://gitbox.apache.org/repos/asf/incubator-skywalking-ui.git.


    from d2af186  Refactor alarm page for v6 protocol
     new 2fab03f  Refactor endpoint page with v6 protocol
     new a204416  Refactor topology page with v6

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .roadhogrc.mock.js                                 |  16 +--
 mock/metadata.js                                   |  10 +-
 mock/metric.js                                     |   8 ++
 mock/service.js                                    | 134 --------------------
 mock/topology.js                                   | 138 +++++++++++++++++++++
 src/common/menu.js                                 |   4 +-
 src/common/router.js                               |   4 +-
 src/components/Topology/AppTopology.js             |  50 +++-----
 src/models/{service.js => endpoint.js}             | 100 +++++++--------
 src/models/topology.js                             |  21 +---
 .../{Service/Service.js => Endpoint/Endpoint.js}   | 128 +++++++++----------
 src/routes/Topology/Topology.js                    |  12 +-
 src/utils/time.js                                  |   5 +
 src/utils/utils.js                                 |   7 ++
 14 files changed, 316 insertions(+), 321 deletions(-)
 delete mode 100644 mock/service.js
 rename src/models/{service.js => endpoint.js} (64%)
 rename src/routes/{Service/Service.js => Endpoint/Endpoint.js} (67%)


[incubator-skywalking-ui] 02/02: Refactor topology page with v6

Posted by ha...@apache.org.
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">


[incubator-skywalking-ui] 01/02: Refactor endpoint page with v6 protocol

Posted by ha...@apache.org.
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 2fab03fff22ec23f78994ca16ade1cf6c827d875
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Mon Sep 10 14:18:06 2018 +0800

    Refactor endpoint page with v6 protocol
---
 .roadhogrc.mock.js                                 |  10 +-
 mock/metadata.js                                   |  10 +-
 mock/metric.js                                     |   8 ++
 mock/topology.js                                   |  49 ++++++++
 src/common/menu.js                                 |   4 +-
 src/common/router.js                               |   4 +-
 src/models/{service.js => endpoint.js}             | 100 ++++++++--------
 .../{Service/Service.js => Endpoint/Endpoint.js}   | 128 ++++++++++-----------
 src/utils/time.js                                  |   5 +
 src/utils/utils.js                                 |   7 ++
 10 files changed, 199 insertions(+), 126 deletions(-)

diff --git a/.roadhogrc.mock.js b/.roadhogrc.mock.js
index 9fa1e25..1021e7f 100644
--- a/.roadhogrc.mock.js
+++ b/.roadhogrc.mock.js
@@ -1,7 +1,7 @@
 import mockjs from 'mockjs';
 import fs from 'fs';
 import { delay } from 'roadhog-api-doc';
-import { getTopology } from './mock/topology';
+import { getTopology, getServiceTopology } from './mock/topology';
 import { getAllApplication, getApplication } from './mock/application';
 import { searchServer, getServer } from './mock/server';
 import { searchService, getService } from './mock/service';
@@ -9,8 +9,8 @@ import { Alarms, getNoticeAlarm, AlarmTrend } from './mock/alarm';
 import { TraceBrief, Trace } from './mock/trace'
 import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
 import { graphql } from 'graphql';
-import { ClusterBrief, getAllServices } from './mock/metadata';
-import { Thermodynamic } from './mock/metric';
+import { ClusterBrief, getAllServices, searchEndpoint } from './mock/metadata';
+import { IntValues, Thermodynamic } from './mock/metric';
 import { getTopN } from './mock/aggregation';
 
 const noMock = process.env.NO_MOCK === 'true';
@@ -19,6 +19,8 @@ const resolvers = {
   Query: {
     getTopN,
     getAllServices,
+    getServiceTopology,
+    searchEndpoint,
   }
 }
 
@@ -30,6 +32,7 @@ const schema = makeExecutableSchema({ typeDefs: [
   fs.readFileSync('query-protocol/metric.graphqls', 'utf8'),
   fs.readFileSync('query-protocol/aggregation.graphqls', 'utf8'),
   fs.readFileSync('query-protocol/trace.graphqls', 'utf8'),
+  fs.readFileSync('query-protocol/topology.graphqls', 'utf8'),
 ], resolvers });
 
 addMockFunctionsToSchema({
@@ -42,6 +45,7 @@ addMockFunctionsToSchema({
     Alarms,
     TraceBrief,
     Trace,
+    IntValues,
   },
   preserveResolvers: true 
 });
diff --git a/mock/metadata.js b/mock/metadata.js
index 351f7f6..12fe2c3 100644
--- a/mock/metadata.js
+++ b/mock/metadata.js
@@ -28,8 +28,14 @@ export default {
   ,
   getAllServices: () => {
     const data = mockjs.mock({
-      'serviceId|20-50': [{ 'id|+1': 3, name: function() { return `app-${this.id}`; } }], // eslint-disable-line
+      'serviceId|20-50': [{ 'id|+1': 3, name: function() { return `service-${this.id}`; } }], // eslint-disable-line
     });
     return data.serviceId;
-  }
+  },
+  searchEndpoint: () => {
+    const data = mockjs.mock({
+      'endpointId|20-50': [{ 'id|+1': 3, name: function() { return `endpoint-${this.id}`; } }], // eslint-disable-line
+    });
+    return data.endpointId;
+  },
 };
diff --git a/mock/metric.js b/mock/metric.js
index 673cc63..410d006 100644
--- a/mock/metric.js
+++ b/mock/metric.js
@@ -30,4 +30,12 @@ export default {
     },
     responseTimeStep: 50,
   }),
+  IntValues: () => (mockjs.mock(
+    {
+      'values|60': [{
+        'id|+1': 1,
+        value: '@natural(0, 1000)',
+      }],
+    }
+  )),
 };
diff --git a/mock/topology.js b/mock/topology.js
index e0b816b..5480589 100644
--- a/mock/topology.js
+++ b/mock/topology.js
@@ -19,6 +19,55 @@
 import mockjs from 'mockjs';
 
 export default {
+  getServiceTopology: () => {
+    const upNodes = mockjs.mock({
+      'nodes|1-5': [
+        {
+          'id|+1': 100,
+          name: '@url',
+          'type|1': ['DUBBO', 'USER', 'SPRINGMVC'],
+        },
+      ],
+    });
+    const centerNodes = mockjs.mock({
+      nodes: [
+        {
+          'id|+1': 1,
+          name: '@url',
+          'type|1': ['DUBBO', 'tomcat', 'SPRINGMVC'],
+        },
+      ],
+    });
+    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,
+    }))).concat(downNodes.nodes.map(node => (mockjs.mock({
+      source: 1,
+      target: node.id,
+      'isAlert|1': true,
+      'callType|1': ['rpc', 'http', 'dubbo'],
+      'cpm|0-2000': 1,
+    }))));
+    calls.push({ source: '-175', target: 1, isAlert: false, callType: 'GRPC', cpm: 0, avgResponseTime: 52 });
+    return {
+      nodes,
+      calls,
+    };
+  },
   getTopology(req, res) {
     res.json(mockjs.mock(
       {
diff --git a/src/common/menu.js b/src/common/menu.js
index cbf1815..bc98328 100644
--- a/src/common/menu.js
+++ b/src/common/menu.js
@@ -34,8 +34,8 @@ const menuData = [{
       name: 'Application',
       path: 'application',
     }, {
-      name: 'Service',
-      path: 'service',
+      name: 'Endpoint',
+      path: 'endpoint',
     }, {
       name: 'Alarm',
       path: 'alarm',
diff --git a/src/common/router.js b/src/common/router.js
index 00e3934..db30edd 100644
--- a/src/common/router.js
+++ b/src/common/router.js
@@ -100,8 +100,8 @@ export const getRouterData = (app) => {
     '/monitor/application': {
       component: dynamicWrapper(app, ['application'], () => import('../routes/Application/Application')),
     },
-    '/monitor/service': {
-      component: dynamicWrapper(app, ['service'], () => import('../routes/Service/Service')),
+    '/monitor/endpoint': {
+      component: dynamicWrapper(app, ['endpoint'], () => import('../routes/Endpoint/Endpoint')),
     },
     '/trace': {
       component: dynamicWrapper(app, ['trace'], () => import('../routes/Trace/Trace')),
diff --git a/src/models/service.js b/src/models/endpoint.js
similarity index 64%
rename from src/models/service.js
rename to src/models/endpoint.js
index bd873ec..662546a 100644
--- a/src/models/service.js
+++ b/src/models/endpoint.js
@@ -16,12 +16,12 @@
  */
 
 
-import { generateModal, saveOptionsInState } from '../utils/models';
-import { query } from '../services/graphql';
+import { base, saveOptionsInState } from '../utils/models';
+import { exec } from '../services/graphql';
 
 const optionsQuery = `
-  query ApplicationOption($duration: Duration!) {
-    applicationId: getAllApplication(duration: $duration) {
+  query ServiceOption($duration: Duration!) {
+    serviceId: getAllServices(duration: $duration) {
       key: id
       label: name
     }
@@ -29,15 +29,30 @@ const optionsQuery = `
 `;
 
 const dataQuery = `
-  query Service($serviceId: ID!, $duration: Duration!, $traceCondition: TraceQueryCondition!) {
-    getServiceResponseTimeTrend(serviceId: $serviceId, duration: $duration) {
-      trendList
+  query Endpoint($endpointId: ID!, $duration: Duration!, $traceCondition: TraceQueryCondition!) {
+    getEndpointResponseTimeTrend: getLinearIntValues(metric: {
+      name: "endpointResponseTimeTrend"
+      id: $endpointId
+    }, duration: $duration) {
+      values {
+        value
+      }
     }
-    getServiceThroughputTrend(serviceId: $serviceId, duration: $duration) {
-      trendList
+    getEndpointThroughputTrend: getLinearIntValues(metric: {
+      name: "endpointResponseTimeTrend"
+      id: $endpointId
+    }, duration: $duration) {
+      values {
+        value
+      }
     }
-    getServiceSLATrend(serviceId: $serviceId, duration: $duration) {
-      trendList
+    getEndpointSLATrend: getLinearIntValues(metric: {
+      name: "endpointResponseTimeTrend"
+      id: $endpointId
+    }, duration: $duration) {
+      values {
+        value
+      }
     }
     queryBasicTraces(condition: $traceCondition) {
       traces {
@@ -50,26 +65,6 @@ const dataQuery = `
       }
       total
     }
-    getServiceTopology(serviceId: $serviceId, duration: $duration) {
-      nodes {
-        id
-        name
-        type
-        ... on ServiceNode {
-          sla
-          calls
-          numOfServiceAlarm
-        }
-      }
-      calls {
-        source
-        target
-        isAlert
-        callType
-        cpm
-        avgResponseTime
-      }
-    }
   }
 `;
 
@@ -111,19 +106,19 @@ const spanQuery = `query Spans($traceId: ID!) {
   }
 }`;
 
-export default generateModal({
-  namespace: 'service',
+export default base({
+  namespace: 'endpoint',
   state: {
-    getServiceResponseTimeTrend: {
-      trendList: [],
+    getEndpointResponseTimeTrend: {
+      values: [],
     },
-    getServiceThroughputTrend: {
-      trendList: [],
+    getEndpointThroughputTrend: {
+      values: [],
     },
-    getServiceSLATrend: {
-      trendList: [],
+    getEndpointSLATrend: {
+      values: [],
     },
-    getServiceTopology: {
+    getEndpointTopology: {
       nodes: [],
       calls: [],
     },
@@ -136,7 +131,7 @@ export default generateModal({
   optionsQuery,
   effects: {
     *fetchSpans({ payload }, { call, put }) {
-      const response = yield call(query, 'spans', { query: spanQuery, variables: payload.variables });
+      const response = yield call(exec, { query: spanQuery, variables: payload.variables });
       yield put({
         type: 'saveSpans',
         payload: response,
@@ -157,21 +152,21 @@ export default generateModal({
         },
       };
     },
-    saveAppInfo(preState, { payload: allOptions }) {
+    saveServiceInfo(preState, { payload: allOptions }) {
       const rawState = saveOptionsInState(null, preState, { payload: allOptions });
       const { data } = rawState;
-      if (data.appInfo) {
+      if (data.serviceInfo) {
         return rawState;
       }
       const { variables: { values } } = rawState;
-      if (!values.applicationId) {
+      if (!values.serviceId) {
         return rawState;
       }
       return {
         ...rawState,
         data: {
           ...data,
-          appInfo: { applicationId: values.applicationId },
+          serviceInfo: { serviceId: values.serviceId },
         },
       };
     },
@@ -189,26 +184,25 @@ export default generateModal({
   subscriptions: {
     setup({ history, dispatch }) {
       return history.listen(({ pathname, state }) => {
-        if (pathname === '/monitor/service' && state) {
-          console.info(state);
+        if (pathname === '/monitor/endpoint' && state) {
           dispatch({
             type: 'saveVariables',
             payload: {
               values: {
-                serviceId: state.key,
-                applicationId: state.applicationId,
+                endpointId: state.key,
+                serviceId: state.serviceId,
               },
               labels: {
-                serviceId: state.label,
-                applicationId: state.applicationName,
+                endpointId: state.label,
+                serviceId: state.serviceName,
               },
             },
           });
           dispatch({
             type: 'saveData',
             payload: {
-              appInfo: { applicationId: state.applicationId },
-              serviceInfo: { key: state.key, label: state.label },
+              serviceInfo: { serviceId: state.serviceId },
+              endpointInfo: { key: state.key, label: state.label },
             },
           });
         }
diff --git a/src/routes/Service/Service.js b/src/routes/Endpoint/Endpoint.js
similarity index 67%
rename from src/routes/Service/Service.js
rename to src/routes/Endpoint/Endpoint.js
index 62e467f..d6add80 100644
--- a/src/routes/Service/Service.js
+++ b/src/routes/Endpoint/Endpoint.js
@@ -21,9 +21,9 @@ import { connect } from 'dva';
 import { Row, Col, Form, Button, Icon, Select } from 'antd';
 import {
   ChartCard, MiniArea, MiniBar, Sankey,
-} from '../../components/Charts';
-import { axis } from '../../utils/time';
-import { avgTimeSeries } from '../../utils/utils';
+} from 'components/Charts';
+import { axisY } from '../../utils/time';
+import { avgTS } from '../../utils/utils';
 import { Panel, Search } from '../../components/Page';
 import TraceList from '../../components/Trace/TraceList';
 import TraceTimeline from '../Trace/TraceTimeline';
@@ -32,29 +32,29 @@ const { Item: FormItem } = Form;
 const { Option } = Select;
 
 @connect(state => ({
-  service: state.service,
+  endpoint: state.endpoint,
   duration: state.global.duration,
   globalVariables: state.global.globalVariables,
-  loading: state.loading.models.service,
+  loading: state.loading.models.endpoint,
 }))
 @Form.create({
   mapPropsToFields(props) {
-    const { variables: { values, labels } } = props.service;
+    const { variables: { values, labels } } = props.endpoint;
     return {
-      applicationId: Form.createFormField({
-        value: { key: values.applicationId ? values.applicationId : '', label: labels.applicationId ? labels.applicationId : '' },
-      }),
       serviceId: Form.createFormField({
         value: { key: values.serviceId ? values.serviceId : '', label: labels.serviceId ? labels.serviceId : '' },
       }),
+      endpointId: Form.createFormField({
+        value: { key: values.endpointId ? values.endpointId : '', label: labels.endpointId ? labels.endpointId : '' },
+      }),
     };
   },
 })
-export default class Service extends PureComponent {
+export default class Endpoint extends PureComponent {
   componentDidMount() {
     this.props.dispatch({
-      type: 'service/initOptions',
-      payload: { variables: this.props.globalVariables, reducer: 'saveAppInfo' },
+      type: 'endpoint/initOptions',
+      payload: { variables: this.props.globalVariables, reducer: 'saveServiceInfo' },
     });
   }
 
@@ -63,21 +63,21 @@ export default class Service extends PureComponent {
       return;
     }
     this.props.dispatch({
-      type: 'service/initOptions',
-      payload: { variables: nextProps.globalVariables, reducer: 'saveAppInfo' },
+      type: 'endpoint/initOptions',
+      payload: { variables: nextProps.globalVariables, reducer: 'saveServiceInfo' },
     });
   }
 
-  handleAppSelect = (selected) => {
+  handleServiceSelect = (selected) => {
     this.props.dispatch({
-      type: 'service/save',
+      type: 'endpoint/save',
       payload: {
         variables: {
-          values: { applicationId: selected.key, serviceId: null },
-          labels: { applicationId: selected.label, serviceId: null },
+          values: { serviceId: selected.key, endpointId: null },
+          labels: { serviceId: selected.label, endpointId: null },
         },
         data: {
-          appInfo: { applicationId: selected.key },
+          serviceInfo: { serviceId: selected.key },
         },
       },
     });
@@ -85,36 +85,36 @@ export default class Service extends PureComponent {
 
   handleSelect = (selected) => {
     this.props.dispatch({
-      type: 'service/save',
+      type: 'endpoint/save',
       payload: {
         variables: {
-          values: { serviceId: selected.key },
-          labels: { serviceId: selected.label },
+          values: { endpointId: selected.key },
+          labels: { endpointId: selected.label },
         },
         data: {
-          serviceInfo: selected,
+          endpointInfo: selected,
         },
       },
     });
   }
 
   handleChange = (variables) => {
-    const { variables: { values } } = this.props.service;
-    if (!values.applicationId) {
+    const { variables: { values } } = this.props.endpoint;
+    if (!values.serviceId) {
       return;
     }
-    const { key: serviceId, label: serviceName, duration } = variables;
-    if (!serviceId) {
+    const { key: endpointId, label: endpointName, duration } = variables;
+    if (!endpointId) {
       return;
     }
     this.props.dispatch({
-      type: 'service/fetchData',
+      type: 'endpoint/fetchData',
       payload: { variables: {
-        serviceId,
+        endpointId,
         duration,
         traceCondition: {
-          applicationId: values.applicationId,
-          operationName: serviceName,
+          endpointId: parseInt(values.endpointId, 10),
+          operationName: endpointName,
           queryDuration: duration,
           traceState: 'ALL',
           queryOrder: 'BY_DURATION',
@@ -131,30 +131,30 @@ export default class Service extends PureComponent {
   handleShowTrace = (traceId) => {
     const { dispatch } = this.props;
     dispatch({
-      type: 'service/fetchSpans',
+      type: 'endpoint/fetchSpans',
       payload: { variables: { traceId } },
     });
   }
 
   handleGoBack = () => {
     this.props.dispatch({
-      type: 'service/hideTimeline',
+      type: 'endpoint/hideTimeline',
     });
   }
 
-  edgeWith = edge => edge.cpm * edge.avgResponseTime;
+  edgeWith = edge => edge.cpm;
 
   renderPanel = () => {
-    const { service, duration } = this.props;
-    const { variables: { values }, data } = service;
-    const { getServiceResponseTimeTrend, getServiceThroughputTrend,
-      getServiceSLATrend, getServiceTopology, queryBasicTraces } = data;
-    if (!values.serviceId) {
+    const { endpoint, duration } = this.props;
+    const { variables: { values }, data } = endpoint;
+    const { getEndpointResponseTimeTrend, getEndpointThroughputTrend,
+      getEndpointSLATrend, getEndpointTopology, queryBasicTraces } = data;
+    if (!values.endpointId) {
       return null;
     }
     return (
       <Panel
-        variables={data.serviceInfo}
+        variables={data.endpointInfo}
         globalVariables={this.props.globalVariables}
         onChange={this.handleChange}
       >
@@ -162,35 +162,35 @@ export default class Service extends PureComponent {
           <Col xs={24} sm={24} md={24} lg={8} xl={8} style={{ marginTop: 8 }}>
             <ChartCard
               title="Avg Throughput"
-              total={`${avgTimeSeries(getServiceThroughputTrend.trendList)} cpm`}
+              total={`${avgTS(getEndpointThroughputTrend.values)} cpm`}
               contentHeight={46}
             >
               <MiniArea
                 color="#975FE4"
-                data={axis(duration, getServiceThroughputTrend.trendList)}
+                data={axisY(duration, getEndpointThroughputTrend.values)}
               />
             </ChartCard>
           </Col>
           <Col xs={24} sm={24} md={24} lg={8} xl={8} style={{ marginTop: 8 }}>
             <ChartCard
               title="Avg Response Time"
-              total={`${avgTimeSeries(getServiceResponseTimeTrend.trendList)} ms`}
+              total={`${avgTS(getEndpointResponseTimeTrend.values)} ms`}
               contentHeight={46}
             >
               <MiniArea
-                data={axis(duration, getServiceResponseTimeTrend.trendList)}
+                data={axisY(duration, getEndpointResponseTimeTrend.values)}
               />
             </ChartCard>
           </Col>
           <Col xs={24} sm={24} md={24} lg={8} xl={8} style={{ marginTop: 8 }}>
             <ChartCard
               title="Avg SLA"
-              total={`${(avgTimeSeries(getServiceSLATrend.trendList) / 100).toFixed(2)} %`}
+              total={`${(avgTS(getEndpointSLATrend.values) / 100).toFixed(2)} %`}
             >
               <MiniBar
                 animate={false}
                 height={46}
-                data={axis(duration, getServiceSLATrend.trendList,
+                data={axisY(duration, getEndpointSLATrend.values,
                   ({ x, y }) => ({ x, y: y / 100 }))}
               />
             </ChartCard>
@@ -209,7 +209,7 @@ export default class Service extends PureComponent {
             </ChartCard>
           </Col>
         </Row>
-        {this.renderSankey(getServiceTopology)}
+        {this.renderSankey(getEndpointTopology)}
       </Panel>
     );
   }
@@ -238,13 +238,13 @@ export default class Service extends PureComponent {
           >
             <Sankey
               data={nData}
-              edgeTooltip={['target*source*cpm*avgResponseTime*isAlert', (target, source, cpm, avgResponseTime) => {
+              edgeTooltip={['target*source*cpm', (target, source, cpm) => {
                 return {
                   name: `${source.name} to ${target.name} </span>`,
-                  value: `${cpm < 1 ? '<1' : cpm} cpm ${avgResponseTime}ms`,
+                  value: `${cpm} cpm`,
                 };
               }]}
-              edgeColor={['isAlert', isAlert => (isAlert ? '#DC143C' : '#bbb')]}
+              edgeColor="#bbb"
             />
           </ChartCard>
         </Col>
@@ -252,9 +252,9 @@ export default class Service extends PureComponent {
   }
 
   render() {
-    const { form, service } = this.props;
+    const { form, endpoint } = this.props;
     const { getFieldDecorator } = form;
-    const { variables: { options }, data } = service;
+    const { variables: { options }, data } = endpoint;
     const { showTimeline, queryTrace, currentTraceId } = data;
     return (
       <div>
@@ -271,31 +271,31 @@ export default class Service extends PureComponent {
           <Col span={showTimeline ? 0 : 24}>
             <Form layout="inline">
               <FormItem>
-                {getFieldDecorator('applicationId')(
+                {getFieldDecorator('serviceId')(
                   <Select
                     showSearch
                     optionFilterProp="children"
                     style={{ width: 200 }}
-                    placeholder="Select a application"
+                    placeholder="Select a service"
                     labelInValue
-                    onSelect={this.handleAppSelect.bind(this)}
+                    onSelect={this.handleServiceSelect.bind(this)}
                   >
-                    {options.applicationId && options.applicationId.map(app =>
-                      <Option key={app.key} value={app.key}>{app.label}</Option>)}
+                    {options.serviceId && options.serviceId.map(service =>
+                      <Option key={service.key} value={service.key}>{service.label}</Option>)}
                   </Select>
                 )}
               </FormItem>
-              {data.appInfo ? (
+              {data.serviceInfo ? (
                 <FormItem>
-                  {getFieldDecorator('serviceId')(
+                  {getFieldDecorator('endpointId')(
                     <Search
-                      placeholder="Search a service"
+                      placeholder="Search a endpoint"
                       onSelect={this.handleSelect.bind(this)}
-                      url="/service/search"
-                      variables={data.appInfo}
+                      url="/graphql"
+                      variables={data.serviceInfo}
                       query={`
-                        query SearchService($applicationId: ID!, $keyword: String!) {
-                          searchService(applicationId: $applicationId, keyword: $keyword, topN: 10) {
+                        query SearchEndpoint($serviceId: ID!, $keyword: String!) {
+                          searchEndpoint(serviceId: $serviceId, keyword: $keyword, limit: 10) {
                             key: id
                             label: name
                           }
diff --git a/src/utils/time.js b/src/utils/time.js
index e2476ca..b4e7301 100644
--- a/src/utils/time.js
+++ b/src/utils/time.js
@@ -22,6 +22,11 @@ export function axis({ display }, data, tranformFunc) {
     (tranformFunc ? tranformFunc({ x: v, y: data[i] }) : { x: v, y: data[i] }));
 }
 
+export function axisY({ display }, data, tranformFunc) {
+  return display.range.map((v, i) =>
+    (tranformFunc ? tranformFunc({ x: v, y: data[i] ? data[i].value : null }) : { x: v, y: data[i] ? data[i].value : null }));
+}
+
 export function generateDuration({ from, to }) {
   const start = from();
   const end = to();
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 2969ebf..d6c4e3b 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -27,6 +27,13 @@ export function avgTimeSeries(list) {
       (acc, curr) => acc + curr) / filteredList.length).toFixed(2)) : 0;
 }
 
+export function avgTS(list) {
+  const filteredList = list.map(_ => _.value).filter(_ => _ > 0);
+  return filteredList.length > 0 ?
+    parseFloat((filteredList.reduce(
+      (acc, curr) => acc + curr) / filteredList.length).toFixed(2)) : 0;
+}
+
 export function getPlainNode(nodeList, parentPath = '') {
   const arr = [];
   nodeList.forEach((node) => {