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/04 08:24:13 UTC
[incubator-skywalking-ui] branch 6.0.0/dev updated: Refactor
Dashboard page
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
The following commit(s) were added to refs/heads/6.0.0/dev by this push:
new ab179d4 Refactor Dashboard page
ab179d4 is described below
commit ab179d44b065e2344cb2f5cc60c49f55d1766b2c
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Tue Sep 4 16:23:33 2018 +0800
Refactor Dashboard page
---
.gitmodules | 3 +
.roadhogrc.mock.js | 32 +++++-
src/services/graphql.js => mock/aggregation.js | 20 ++--
mock/alarm.js | 3 +
mock/dashboard.js | 57 -----------
mock/metadata.js | 52 ++--------
src/services/graphql.js => mock/metric.js | 23 +++--
package-lock.json | 76 +++++++++++++-
package.json | 4 +-
query-protocol | 1 +
src/models/dashboard.js | 56 ++++++-----
src/routes/Dashboard/Dashboard.js | 49 +++++----
src/services/graphql.js | 7 ++
src/utils/models.js | 132 ++++++++++++++++++++++++-
14 files changed, 341 insertions(+), 174 deletions(-)
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..aa82721
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "query-protocol"]
+ path = query-protocol
+ url = https://github.com/apache/incubator-skywalking-query-protocol.git
diff --git a/.roadhogrc.mock.js b/.roadhogrc.mock.js
index c2455e7..52159cb 100644
--- a/.roadhogrc.mock.js
+++ b/.roadhogrc.mock.js
@@ -1,17 +1,43 @@
import mockjs from 'mockjs';
+import fs from 'fs';
import { delay } from 'roadhog-api-doc';
-import { getDashboard } from './mock/dashboard';
import { getTopology } from './mock/topology';
import { getAllApplication, getApplication } from './mock/application';
import { searchServer, getServer } from './mock/server';
import { searchService, getService } from './mock/service';
-import { getAlarm, getNoticeAlarm } from './mock/alarm';
+import { getAlarm, getNoticeAlarm, AlarmTrend } from './mock/alarm';
import { getAllApplication as getAllApplicationForTrace, getTrace, getSpans } from './mock/trace'
+import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools';
+import { graphql } from 'graphql';
+import { ClusterBrief } from './mock/metadata';
+import { Thermodynamic } from './mock/metric';
+import { getTopN } from './mock/aggregation';
const noMock = process.env.NO_MOCK === 'true';
+const resolvers = {
+ Query: {
+ getTopN
+ }
+}
+
+const schema = makeExecutableSchema({ typeDefs: [
+ fs.readFileSync('query-protocol/common.graphqls', 'utf8'),
+ fs.readFileSync('query-protocol/metadata.graphqls', 'utf8'),
+ fs.readFileSync('query-protocol/alarm.graphqls', 'utf8'),
+ fs.readFileSync('query-protocol/metric.graphqls', 'utf8'),
+ fs.readFileSync('query-protocol/aggregation.graphqls', 'utf8'),
+], resolvers });
+
+addMockFunctionsToSchema({ schema, mocks: {
+ ClusterBrief, Thermodynamic, AlarmTrend
+}, preserveResolvers: true });
+
const proxy = {
- 'POST /api/dashboard': getDashboard,
+ 'POST /api/graphql': (req, res) => {
+ const { query: source, variables: variableValues } = req.body;
+ graphql({ schema, source, variableValues }).then((result) => res.send(result));
+ },
'POST /api/topology': getTopology,
'POST /api/application/options': getAllApplication,
'POST /api/application': getApplication,
diff --git a/src/services/graphql.js b/mock/aggregation.js
similarity index 64%
copy from src/services/graphql.js
copy to mock/aggregation.js
index 1f081a2..e03c16a 100644
--- a/src/services/graphql.js
+++ b/mock/aggregation.js
@@ -15,12 +15,16 @@
* limitations under the License.
*/
+import mockjs from 'mockjs';
-import request from '../utils/request';
-
-export async function query(namespace, playload) {
- return request(`/api/${namespace}`, {
- method: 'POST',
- body: playload,
- });
-}
+export default {
+ getTopN: (obj, args, context, info) => {
+ let array = null;
+ if (args.condition.filterScope === 'ENDPOINT') {
+ array = mockjs.mock({ 'array|10': [{ 'id|+1': 1, name: '@url', 'value|200-1000': 1 }]});
+ } else if (args.condition.filterScope === 'SERVICE') {
+ array = mockjs.mock({ 'array|10': [{ 'id|+1': 1, name: '@name', 'value|100-10000': 1 }]});
+ }
+ return array.array;
+ },
+};
diff --git a/mock/alarm.js b/mock/alarm.js
index 150b7cb..2358bfe 100644
--- a/mock/alarm.js
+++ b/mock/alarm.js
@@ -19,6 +19,9 @@
import mockjs from 'mockjs';
export default {
+ AlarmTrend: () => mockjs.mock({
+ 'numOfAlarm|60': ['@natural(0, 9999)'],
+ }),
getNoticeAlarm(req, res) {
return res.json(mockjs.mock(
{
diff --git a/mock/dashboard.js b/mock/dashboard.js
deleted file mode 100644
index 0d58909..0000000
--- a/mock/dashboard.js
+++ /dev/null
@@ -1,57 +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 {
- getDashboard(req, res) {
- res.json(mockjs.mock(
- {
- data: {
- getClusterBrief: {
- 'numOfApplication|1-100': 1,
- 'numOfService|1-100': 1,
- 'numOfDatabase|1-100': 1,
- 'numOfCache|1-100': 1,
- 'numOfMQ|1-100': 1,
- },
- getAlarmTrend: {
- 'numOfAlarmRate|60': ['@natural(0, 9999)'],
- },
- getConjecturalApps: {
- 'apps|3-5': [{ 'name|1': ['Oracle', 'MySQL', 'ActiveMQ', 'Redis', 'Memcache', 'SQLServer'], num: '@natural(1, 20)' }],
- },
- getThermodynamic: {
- nodes: () => {
- const result = [];
- for (let i = 0; i < 61; i += 1) {
- for (let j = 0; j < 41; j += 1) {
- result.push([i, j, mockjs.Random.natural(0, 999)]);
- }
- }
- return result;
- },
- responseTimeStep: 50,
- },
- 'getTopNSlowService|10': [{ service: { 'key|+1': 1, label: '@url', 'applicationId|+1': 1, applicationName: '@name' }, 'value|200-1000': 1 }],
- 'getTopNApplicationThroughput|10': [{ 'key|+1': 1, label: '@name', 'value|100-10000': 1 }],
- },
- }
- ));
- },
-};
diff --git a/mock/metadata.js b/mock/metadata.js
index a16b833..cd1630d 100644
--- a/mock/metadata.js
+++ b/mock/metadata.js
@@ -18,48 +18,12 @@
import mockjs from 'mockjs';
export default {
- getDashboard(req, res) {
- res.json(
- mockjs.mock({
- data: {
- getGlobalBrief: {
- 'numOfService|1-100': 1,
- 'numOfEndpoint|1-100': 1,
- 'numOfDatabase|1-100': 1,
- 'numOfCache|1-100': 1,
- 'numOfMQ|1-100': 1,
- },
- getAlarmTrend: {
- 'numOfAlarm|60': ['@natural(0, 9999)'],
- },
- getThermodynamic: {
- nodes: () => {
- const result = [];
- for (let i = 0; i < 61; i += 1) {
- for (let j = 0; j < 41; j += 1) {
- result.push([i, j, mockjs.Random.natural(0, 999)]);
- }
- }
- return result;
- },
- axisYStep: 50,
- },
- 'getTopNSlowService|10': [
- {
- service: {
- 'key|+1': 1,
- label: '@url',
- 'applicationId|+1': 1,
- applicationName: '@name',
- },
- 'value|200-1000': 1,
- },
- ],
- 'getTopNApplicationThroughput|10': [
- { 'key|+1': 1, label: '@name', 'value|100-10000': 1 },
- ],
- },
- })
- );
- },
+ ClusterBrief: () => mockjs.mock({
+ 'numOfService|1-100': 1,
+ 'numOfEndpoint|1-100': 1,
+ 'numOfDatabase|1-100': 1,
+ 'numOfCache|1-100': 1,
+ 'numOfMQ|1-100': 1,
+ })
+ ,
};
diff --git a/src/services/graphql.js b/mock/metric.js
similarity index 70%
copy from src/services/graphql.js
copy to mock/metric.js
index 1f081a2..673cc63 100644
--- a/src/services/graphql.js
+++ b/mock/metric.js
@@ -15,12 +15,19 @@
* limitations under the License.
*/
+import mockjs from 'mockjs';
-import request from '../utils/request';
-
-export async function query(namespace, playload) {
- return request(`/api/${namespace}`, {
- method: 'POST',
- body: playload,
- });
-}
+export default {
+ Thermodynamic: () => ({
+ nodes: () => {
+ const result = [];
+ for (let i = 0; i < 61; i += 1) {
+ for (let j = 0; j < 41; j += 1) {
+ result.push([i, j, mockjs.Random.natural(0, 999)]);
+ }
+ }
+ return result;
+ },
+ responseTimeStep: 50,
+ }),
+};
diff --git a/package-lock.json b/package-lock.json
index 381f6a4..3219e08 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3325,6 +3325,11 @@
"any-observable": "^0.3.0"
}
},
+ "@types/graphql": {
+ "version": "0.12.6",
+ "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.12.6.tgz",
+ "integrity": "sha512-wXAVyLfkG1UMkKOdMijVWFky39+OD/41KftzqfX1Oejd0Gm6dOIKjCihSVECg6X7PHjftxXmfOKA/d1H79ZfvQ=="
+ },
"@types/history": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.0.tgz",
@@ -4098,6 +4103,24 @@
}
}
},
+ "apollo-link": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.2.tgz",
+ "integrity": "sha512-Uk/BC09dm61DZRDSu52nGq0nFhq7mcBPTjy5EEH1eunJndtCaNXQhQz/BjkI2NdrfGI+B+i5he6YSoRBhYizdw==",
+ "requires": {
+ "@types/graphql": "0.12.6",
+ "apollo-utilities": "^1.0.0",
+ "zen-observable-ts": "^0.8.9"
+ }
+ },
+ "apollo-utilities": {
+ "version": "1.0.20",
+ "resolved": "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.0.20.tgz",
+ "integrity": "sha512-2M4BJCyX/9UXGJFoV4sTnVTZ4Q29aM18Z1avDrwvlCGGwoRTz50sGBAfTiWnUnnNQyPIIJEYElScw46DgIu0Rg==",
+ "requires": {
+ "fast-json-stable-stringify": "^2.0.0"
+ }
+ },
"append-transform": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
@@ -7443,6 +7466,11 @@
"integrity": "sha512-b5dDNQYdy2vW9WXUD8+RQlfoxvqztLLhDE+T7Gd37I5E8My7nJkKu6FmhdDeRWJ8B+yjZKuwjCta8pgi8kgSqA==",
"dev": true
},
+ "deprecated-decorator": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz",
+ "integrity": "sha1-AJZjF7ehL+kvPMgx91g68ym4bDc="
+ },
"des.js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
@@ -9058,8 +9086,7 @@
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
- "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
- "dev": true
+ "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"fast-levenshtein": {
"version": "2.0.6",
@@ -10426,6 +10453,33 @@
"lodash": "^4.11.1"
}
},
+ "graphql": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.0.0.tgz",
+ "integrity": "sha512-HGVcnO6B25YZcSt6ZsH6/N+XkYuPA7yMqJmlJ4JWxWlS4Tr8SHI56R1Ocs8Eor7V7joEZPRXPDH8RRdll1w44Q==",
+ "requires": {
+ "iterall": "^1.2.2"
+ }
+ },
+ "graphql-tools": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/graphql-tools/-/graphql-tools-3.1.1.tgz",
+ "integrity": "sha512-yHvPkweUB0+Q/GWH5wIG60bpt8CTwBklCSzQdEHmRUgAdEQKxw+9B7zB3dG7wB3Ym7M7lfrS4Ej+jtDZfA2UXg==",
+ "requires": {
+ "apollo-link": "^1.2.2",
+ "apollo-utilities": "^1.0.1",
+ "deprecated-decorator": "^0.1.6",
+ "iterall": "^1.1.3",
+ "uuid": "^3.1.0"
+ },
+ "dependencies": {
+ "uuid": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+ "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
+ }
+ }
+ },
"growly": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
@@ -11986,6 +12040,11 @@
"handlebars": "^4.0.11"
}
},
+ "iterall": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz",
+ "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA=="
+ },
"jest-changed-files": {
"version": "22.4.3",
"resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-22.4.3.tgz",
@@ -24100,6 +24159,19 @@
"requires": {
"fd-slicer": "~1.0.1"
}
+ },
+ "zen-observable": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.9.tgz",
+ "integrity": "sha512-Y9kPzjGvIZ5jchSlqlCpBW3I82zBBL4z+ulXDRVA1NwsKzjt5kwAi+gOYIy0htNkfuehGZZtP5mRXHRV6TjDWw=="
+ },
+ "zen-observable-ts": {
+ "version": "0.8.9",
+ "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz",
+ "integrity": "sha512-KJz2O8FxbAdAU5CSc8qZ1K2WYEJb1HxS6XDRF+hOJ1rOYcg6eTMmS9xYHCXzqZZzKw6BbXWyF4UpwSsBQnHJeA==",
+ "requires": {
+ "zen-observable": "^0.8.0"
+ }
}
}
}
diff --git a/package.json b/package.json
index 7cd61eb..43a00f0 100755
--- a/package.json
+++ b/package.json
@@ -33,8 +33,8 @@
"dependencies": {
"@antv/data-set": "^0.8.0",
"@babel/polyfill": "^7.0.0-beta.36",
- "antd": "^3.8.0",
"ant-design-pro": "^1.4.4",
+ "antd": "^3.8.0",
"bizcharts": "^3.1.10",
"bizcharts-plugin-slider": "^2.0.1",
"classnames": "^2.2.5",
@@ -45,6 +45,8 @@
"dva": "^2.2.3",
"dva-loading": "^2.0.3",
"enquire-js": "^0.2.1",
+ "graphql": "^14.0.0",
+ "graphql-tools": "^3.1.1",
"lodash": "^4.17.10",
"lodash-decorators": "^6.0.0",
"moment": "^2.19.3",
diff --git a/query-protocol b/query-protocol
new file mode 160000
index 0000000..ebbeb72
--- /dev/null
+++ b/query-protocol
@@ -0,0 +1 @@
+Subproject commit ebbeb721d95bba8ee63bc2e706e877ee3a56433e
diff --git a/src/models/dashboard.js b/src/models/dashboard.js
index b5d14ee..01f2771 100644
--- a/src/models/dashboard.js
+++ b/src/models/dashboard.js
@@ -16,57 +16,65 @@
*/
-import { generateModal } from '../utils/models';
+import { base } from '../utils/models';
-export default generateModal({
+export default base({
namespace: 'dashboard',
state: {
- getClusterBrief: {
- numOfApplication: 0,
+ getGlobalBrief: {
numOfService: 0,
+ numOfEndpoint: 0,
numOfDatabase: 0,
numOfCache: 0,
numOfMQ: 0,
},
getAlarmTrend: {
- numOfAlarmRate: [],
+ numOfAlarm: [],
},
getThermodynamic: {
nodes: [],
responseTimeStep: 0,
},
- getTopNSlowService: [],
- getTopNApplicationThroughput: [],
+ getTopNSlowEndpoint: [],
+ getTopNServiceThroughput: [],
},
dataQuery: `
query Dashboard($duration: Duration!) {
- getClusterBrief(duration: $duration) {
- numOfApplication
+ getGlobalBrief(duration: $duration) {
numOfService
+ numOfEndpoint
numOfDatabase
numOfCache
numOfMQ
}
getAlarmTrend(duration: $duration) {
- numOfAlarmRate
+ numOfAlarm
}
- getThermodynamic(duration: $duration, type: ALL) {
+ getThermodynamic(duration: $duration, metric: {
+ name: "Endpoint_avg"
+ }) {
nodes
- responseTimeStep
+ responseTimeStep: axisYStep
}
- getTopNSlowService(duration: $duration, topN: 10) {
- service {
- key: id
- label: name
- applicationId
- applicationName
- }
- value: avgResponseTime
+ getTopNSlowEndpoint: getTopN(duration: $duration, condition: {
+ name: "slowEndpoint",
+ topN: 10,
+ order: DES,
+ filterScope: ENDPOINT
+ }) {
+ key: id
+ label: name
+ value
}
- getTopNApplicationThroughput(duration: $duration, topN: 10) {
- key: applicationId
- label: applicationCode
- value: cpm
+ getTopNServiceThroughput: getTopN(duration: $duration, condition: {
+ name: "serviceThroughput",
+ topN: 10,
+ order: DES,
+ filterScope: SERVICE
+ }) {
+ key: id
+ label: name
+ value
}
}
`,
diff --git a/src/routes/Dashboard/Dashboard.js b/src/routes/Dashboard/Dashboard.js
index 1032431..57e3ee0 100644
--- a/src/routes/Dashboard/Dashboard.js
+++ b/src/routes/Dashboard/Dashboard.js
@@ -50,50 +50,50 @@ export default class Dashboard extends PureComponent {
render() {
const { data } = this.props.dashboard;
- const { numOfAlarmRate } = data.getAlarmTrend;
+ const { numOfAlarm } = data.getAlarmTrend;
const accuracy = 100;
let visitData = [];
let avg = 0;
let max = 0;
let min = 0;
- if (numOfAlarmRate && numOfAlarmRate.length > 0) {
- visitData = axis(this.props.duration, numOfAlarmRate, ({ x, y }) => ({ x, y: y / accuracy }));
- avg = avgTimeSeries(numOfAlarmRate) / accuracy;
- max = numOfAlarmRate.reduce((acc, curr) => { return acc < curr ? curr : acc; }) / accuracy;
- min = numOfAlarmRate.reduce((acc, curr) => { return acc > curr ? curr : acc; }) / accuracy;
+ if (numOfAlarm && numOfAlarm.length > 0) {
+ visitData = axis(this.props.duration, numOfAlarm, ({ x, y }) => ({ x, y: y / accuracy }));
+ avg = avgTimeSeries(numOfAlarm) / accuracy;
+ max = numOfAlarm.reduce((acc, curr) => { return acc < curr ? curr : acc; }) / accuracy;
+ min = numOfAlarm.reduce((acc, curr) => { return acc > curr ? curr : acc; }) / accuracy;
}
return (
<Panel globalVariables={this.props.globalVariables} onChange={this.handleDurationChange}>
<Row gutter={8}>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
- title="App"
- action={this.renderAction('Show application details', '/monitor/application')}
- avatar={<img style={{ width: 56, height: 56 }} src="img/icon/app.png" alt="app" />}
- total={data.getClusterBrief.numOfApplication}
+ title="Service"
+ action={this.renderAction('Show service details', '/monitor/service')}
+ avatar={<img style={{ width: 56, height: 56 }} src="img/icon/app.png" alt="service" />}
+ total={data.getGlobalBrief.numOfService}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
- title="Service"
- action={this.renderAction('Show service details', '/monitor/service')}
- avatar={<img style={{ width: 56, height: 56 }} src="img/icon/service.png" alt="service" />}
- total={data.getClusterBrief.numOfService}
+ title="Endpoint"
+ action={this.renderAction('Show endpoint details', '/monitor/endpoint')}
+ avatar={<img style={{ width: 56, height: 56 }} src="img/icon/service.png" alt="endpoint" />}
+ total={data.getGlobalBrief.numOfEndpoint}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="DB & Cache"
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/database.png" alt="database" />}
- total={data.getClusterBrief.numOfDatabase
- + data.getClusterBrief.numOfCache}
+ total={data.getGlobalBrief.numOfDatabase
+ + data.getGlobalBrief.numOfCache}
/>
</Col>
<Col xs={24} sm={24} md={12} lg={6} xl={6}>
<ChartCard
title="MQ"
avatar={<img style={{ width: 56, height: 56 }} src="img/icon/mq.png" alt="mq" />}
- total={data.getClusterBrief.numOfMQ}
+ total={data.getGlobalBrief.numOfMQ}
/>
</Col>
</Row>
@@ -147,31 +147,28 @@ export default class Dashboard extends PureComponent {
<Row gutter={8}>
<Col xs={24} sm={24} md={24} lg={16} xl={16} style={{ marginTop: 8 }}>
<Card
- title="Slow Service"
+ title="Slow Endpoint"
bordered={false}
bodyStyle={{ padding: '0px 10px' }}
>
<RankList
- data={data.getTopNSlowService.map(_ => ({ ..._.service, value: _.value }))}
+ data={data.getTopNSlowEndpoint}
renderValue={_ => `${_.value} ms`}
- onClick={(key, item) => redirect(this.props.history, '/monitor/service', { key,
- label: item.label,
- applicationId: item.applicationId,
- applicationName: item.applicationName })}
+ onClick={(key, item) => redirect(this.props.history, '/monitor/endpoint', { key })}
/>
</Card>
</Col>
<Col xs={24} sm={24} md={24} lg={8} xl={8} style={{ marginTop: 8 }}>
<Card
- title="Application Throughput"
+ title="Service Throughput"
bordered={false}
bodyStyle={{ padding: '0px 10px' }}
>
<RankList
- data={data.getTopNApplicationThroughput}
+ data={data.getTopNServiceThroughput}
renderValue={_ => `${_.value} cpm`}
color="#965fe466"
- onClick={(key, item) => redirect(this.props.history, '/monitor/application', { key, label: item.label })}
+ onClick={(key, item) => redirect(this.props.history, '/monitor/service', { key })}
/>
</Card>
</Col>
diff --git a/src/services/graphql.js b/src/services/graphql.js
index 1f081a2..663b296 100644
--- a/src/services/graphql.js
+++ b/src/services/graphql.js
@@ -24,3 +24,10 @@ export async function query(namespace, playload) {
body: playload,
});
}
+
+export async function exec(playload) {
+ return request(`/api/graphql`, {
+ method: 'POST',
+ body: playload,
+ });
+}
diff --git a/src/utils/models.js b/src/utils/models.js
index 16a32c6..e88a90b 100644
--- a/src/utils/models.js
+++ b/src/utils/models.js
@@ -16,7 +16,7 @@
*/
-import { query as queryService } from '../services/graphql';
+import { query as queryService, exec } from '../services/graphql';
export function saveOptionsInState(defaultOption, preState, { payload: allOptions }) {
if (!allOptions) {
@@ -202,3 +202,133 @@ export function generateModal({ namespace, dataQuery, optionsQuery, defaultOptio
},
};
}
+
+export function base({ namespace, dataQuery, optionsQuery, defaultOption, state = {},
+ varState = {}, effects = {}, reducers = {}, subscriptions = {} }) {
+ return {
+ namespace,
+ state: {
+ variables: {
+ values: {},
+ labels: {},
+ options: {},
+ ...varState,
+ },
+ data: state,
+ },
+ effects: {
+ *initOptions({ payload }, { call, put }) {
+ const { variables, reducer = undefined } = payload;
+ const response = yield call(exec, { variables, query: optionsQuery });
+ if (reducer) {
+ yield put({
+ type: reducer,
+ payload: response.data,
+ });
+ } else {
+ yield put({
+ type: 'saveOptions',
+ payload: response.data,
+ });
+ }
+ },
+ *fetchData({ payload }, { call, put }) {
+ const { variables, reducer = undefined } = payload;
+ const response = yield call(exec, { variables, query: dataQuery });
+ if (!response.data) {
+ return;
+ }
+ if (reducer) {
+ yield put({
+ type: reducer,
+ payload: response.data,
+ });
+ } else {
+ yield put({
+ type: 'saveData',
+ payload: response.data,
+ });
+ }
+ },
+ ...effects,
+ },
+ reducers: {
+ saveOptions(preState, action) {
+ const raw = saveOptionsInState(defaultOption, preState, action);
+ return raw;
+ },
+ save(preState, { payload: { variables: { values = {}, options = {}, labels = {} },
+ data = {} } }) {
+ const { variables: { values: preValues, options: preOptions, labels: preLabels },
+ data: preData } = preState;
+ return {
+ variables: {
+ values: {
+ ...preValues,
+ ...values,
+ },
+ options: {
+ ...preOptions,
+ ...options,
+ },
+ labels: {
+ ...preLabels,
+ ...labels,
+ },
+ },
+ data: {
+ ...preData,
+ ...data,
+ },
+ };
+ },
+ saveData(preState, { payload }) {
+ const { data } = preState;
+ return {
+ ...preState,
+ data: {
+ ...data,
+ ...payload,
+ },
+ };
+ },
+ saveVariables(preState, { payload: { values: variableValues, labels = {} } }) {
+ const { variables: preVariables } = preState;
+ const { values: preValues, lables: preLabels } = preVariables;
+ return {
+ ...preState,
+ variables: {
+ ...preVariables,
+ values: {
+ ...preValues,
+ ...variableValues,
+ },
+ labels: {
+ ...preLabels,
+ ...labels,
+ },
+ },
+ };
+ },
+ initVariables(preState, { payload: { values: variableValues, labels = {} } }) {
+ const { variables: preVariables } = preState;
+ return {
+ ...preState,
+ variables: {
+ ...preVariables,
+ values: {
+ ...variableValues,
+ },
+ labels: {
+ ...labels,
+ },
+ },
+ };
+ },
+ ...reducers,
+ },
+ subscriptions: {
+ ...subscriptions,
+ },
+ };
+}