You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/06/02 12:26:52 UTC
[skywalking-rocketbot-ui] branch master updated: Feat: Implement
metrics templates in the topology (#495)
This is an automated email from the ASF dual-hosted git repository.
kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking-rocketbot-ui.git
The following commit(s) were added to refs/heads/master by this push:
new 8ab2da2 Feat: Implement metrics templates in the topology (#495)
8ab2da2 is described below
commit 8ab2da2bf10719df857bf07809034d9fe522c23e
Author: Qiuxia Fan <fi...@outlook.com>
AuthorDate: Wed Jun 2 20:26:46 2021 +0800
Feat: Implement metrics templates in the topology (#495)
---
src/assets/lang/en.ts | 2 +
src/assets/lang/zh.ts | 2 +
src/assets/styles/lib.scss | 3 +
src/assets/styles/reset.scss | 4 +-
src/assets/styles/style.scss | 16 -
src/components/rk-select.vue | 49 +-
src/constants/constant.ts | 13 +-
src/graph/fragments/topology.ts | 254 --------
src/graph/query/topology.ts | 25 +-
.../modules/dashboard/dashboard-data-query.ts | 120 +++-
src/store/modules/dashboard/mutation-types.ts | 3 +
src/store/modules/global/selectors.ts | 37 +-
src/store/modules/topology/index.ts | 697 +++++++++++++--------
src/store/modules/trace/index.ts | 4 +-
src/store/mutation-types.ts | 28 +-
src/types/topo.d.ts | 94 +--
.../components/dashboard/charts/chart-bar.vue | 4 +
.../components/dashboard/charts/chart-edit.vue | 127 ++--
.../components/dashboard/charts/chart-heap.vue | 4 +
.../components/dashboard/charts/chart-line.vue | 4 +
.../components/dashboard/charts/chart-num.vue | 7 +-
.../components/dashboard/charts/chart-table.vue | 14 +-
src/views/components/dashboard/charts/constant.ts | 3 +
src/views/components/dashboard/dashboard-item.vue | 131 +++-
.../dashboard/tool-bar/tool-bar-btns.vue | 2 +-
.../components/dashboard/tool-bar/tool-bar.vue | 4 +
src/views/components/topology/chart-line.vue | 98 ---
.../topology/{ => chart}/dependency-sankey.vue | 5 -
.../components/topology/{ => chart}/radial.vue | 0
src/views/components/topology/chart/topo.vue | 10 +-
.../dependency/topo-endpoint-dependency.vue | 314 ++++++++++
.../dependency/topo-instance-dependency.vue | 342 ++++++++++
.../dependency/topo-service-dependency.vue | 143 +++++
.../components/topology/styles/common.scss} | 37 +-
src/views/components/topology/topo-aside.vue | 83 +--
src/views/components/topology/topo-chart.vue | 94 ---
.../components/topology/topo-detect-point.vue | 343 +++++++---
.../topology/topo-endpoint-dependency.vue | 126 ----
.../topology/topo-instance-dependency.vue | 148 -----
.../components/topology/topo-service-metrics.vue | 129 ++++
src/views/containers/dashboard.vue | 20 +-
.../topology/endpoint-dependency/index.vue | 6 +-
.../topology/endpoint/endpoints-survey.vue | 92 ++-
src/views/containers/topology/endpoint/index.vue | 119 +++-
src/views/containers/topology/instance/index.vue | 121 +++-
.../topology/instance/instances-survey.vue | 90 ++-
src/views/containers/topology/topology.vue | 165 +++--
47 files changed, 2598 insertions(+), 1538 deletions(-)
diff --git a/src/assets/lang/en.ts b/src/assets/lang/en.ts
index 33a931a..4f6c801 100644
--- a/src/assets/lang/en.ts
+++ b/src/assets/lang/en.ts
@@ -226,6 +226,8 @@ const m = {
tooltipsContent: 'Tooltip Content',
alarmDetail: 'Alarm Detail',
scope: 'Scope',
+ destService: 'Destination Service',
+ destServiceInstance: 'Destination Service Instance',
};
export default m;
diff --git a/src/assets/lang/zh.ts b/src/assets/lang/zh.ts
index 972d197..5ed9f6d 100644
--- a/src/assets/lang/zh.ts
+++ b/src/assets/lang/zh.ts
@@ -224,6 +224,8 @@ const m = {
tooltipsContent: '提示内容',
alarmDetail: '警告详情',
scope: '范围',
+ destService: '终点服务',
+ destServiceInstance: '终点实例',
};
export default m;
diff --git a/src/assets/styles/lib.scss b/src/assets/styles/lib.scss
index f18b456..94232c9 100644
--- a/src/assets/styles/lib.scss
+++ b/src/assets/styles/lib.scss
@@ -175,6 +175,9 @@
.pt-5 {
padding-top: 5px;
}
+.pl-10 {
+ padding-left: 10px;
+}
.pt-10 {
padding-top: 10px;
}
diff --git a/src/assets/styles/reset.scss b/src/assets/styles/reset.scss
index 44b7d50..754c350 100644
--- a/src/assets/styles/reset.scss
+++ b/src/assets/styles/reset.scss
@@ -165,7 +165,7 @@ pre {
overflow: auto;
}
.scroll_bar_style::-webkit-scrollbar {
- width: 10px;
+ width: 9px;
height: 6px;
}
.scroll_bar_style::-webkit-scrollbar-track {
@@ -173,5 +173,5 @@ pre {
}
.scroll_bar_style::-webkit-scrollbar-thumb {
border-radius: 5px;
- background: #777;
+ background: rgba(196, 200, 225, .2);
}
diff --git a/src/assets/styles/style.scss b/src/assets/styles/style.scss
index 2cb9595..a805edd 100644
--- a/src/assets/styles/style.scss
+++ b/src/assets/styles/style.scss
@@ -68,19 +68,3 @@
.oa:hover {
overflow: auto;
}
-
-.dashboard-container {
- overflow: auto;
- padding: 20px 15px;
- height: 100%;
- flex-grow: 1;
- .rk-add-dashboard-item {
- height: 342px;
- text-align: center;
- line-height: 250px;
- border: 1px dashed rgba(196, 200, 225, 0.5);
- cursor: pointer;
- display: inline-block;
- font-size: 16px;
- }
-}
diff --git a/src/components/rk-select.vue b/src/components/rk-select.vue
index 528c05a..7e20251 100644
--- a/src/components/rk-select.vue
+++ b/src/components/rk-select.vue
@@ -21,15 +21,15 @@ limitations under the License. -->
search = '';
}
"
- :class="{ active: visible }"
+ :class="{ active: visible, dark: theme === 'dark' }"
>
- <div class="rk-bar-i flex-h" @click="visible = !visible">
+ <div class="rk-bar-i flex-h" @click="visible = !visible" :class="{ dark: theme === 'dark' }">
<div class="mr-15 rk-bar-i-text">
- <div v-if="Array.isArray(current)">
- <span class="selected" v-for="item in current" :key="item.key">
+ <div v-if="Array.isArray(current)" class="flex-h">
+ <div class="selected" v-for="item in current" :key="item.key">
<span>{{ item.label }}</span>
<span class="remove-icon" v-if="current.length !== 1" @click="removeSelected(item)">×</span>
- </span>
+ </div>
</div>
<div class="ell" v-else v-tooltip:right.ellipsis="current.label || ''">
{{ current.label }}
@@ -39,9 +39,9 @@ limitations under the License. -->
<use xlink:href="#arrow-down"></use>
</svg>
</div>
- <div class="rk-sel" v-show="visible">
+ <div class="rk-sel" v-show="visible" :class="{ dark: theme === 'dark' }">
<div>
- <input type="text" class="rk-sel-search" v-model="search" />
+ <input type="text" class="rk-sel-search" v-model="search" :class="{ dark: theme === 'dark' }" />
<svg class="icon sm close" @click="search = ''" v-if="search">
<use xlink:href="#clear"></use>
</svg>
@@ -50,7 +50,7 @@ limitations under the License. -->
<div
class="rk-opt ell"
@click="handleSelect(i)"
- :class="{ 'select-disabled': selectedOpt.includes(i.key) }"
+ :class="{ 'select-disabled': selectedOpt.includes(i.key), dark: theme === 'dark' }"
v-for="i in filterData"
:key="i.key"
>
@@ -69,6 +69,8 @@ limitations under the License. -->
@Prop() private mode: any;
@Prop() private data!: any;
@Prop() private current!: any;
+ @Prop({ default: 'light' }) private theme!: string;
+
private search: string = '';
private visible: boolean = false;
@@ -116,18 +118,17 @@ limitations under the License. -->
flex-shrink: 0;
}
.selected {
- display: inline-block;
- padding: 5px;
+ padding: 0 3px;
border-radius: 3px;
margin: 3px;
- overflow: hidden;
color: rgba(0, 0, 0, 0.65);
background-color: #fafafa;
border: 1px solid #e8e8e8;
+ text-align: center;
}
.remove-icon {
display: inline-block;
- margin-left: 5px;
+ padding: 0 6px;
cursor: pointer;
}
}
@@ -137,7 +138,7 @@ limitations under the License. -->
.rk-bar-i {
height: 100%;
width: 100%;
- padding: 5px 10px;
+ padding: 2px 10px;
overflow: auto;
}
.rk-sel {
@@ -185,4 +186,26 @@ limitations under the License. -->
max-height: 200px;
padding-bottom: 2px;
}
+ .rk-sel-search.dark {
+ border-bottom: 1px solid #333;
+ border-top: 1px solid #333;
+ }
+ .dark {
+ border: none;
+ background: #3d444f;
+ color: #eee;
+ &:hover {
+ background-color: #333;
+ }
+ &.select-disabled {
+ color: #eee;
+ cursor: not-allowed;
+ }
+ }
+ .selected-ell {
+ display: table-cell;
+ vertical-align: middle;
+ text-align: center;
+ height: 100%;
+ }
</style>
diff --git a/src/constants/constant.ts b/src/constants/constant.ts
index f67961e..f1c77cd 100644
--- a/src/constants/constant.ts
+++ b/src/constants/constant.ts
@@ -18,12 +18,10 @@
export enum TopologyType {
TOPOLOGY_ENDPOINT = 'TOPOLOGY_ENDPOINT',
TOPOLOGY_INSTANCE = 'TOPOLOGY_INSTANCE',
-}
-
-export enum ObjectsType {
- UPDATE_INSTANCES = 'UPDATE_INSTANCES',
- UPDATE_ENDPOINTS = 'UPDATE_ENDPOINTS',
- UPDATE_DASHBOARD = 'UPDATE_DASHBOARD',
+ TOPOLOGY_SERVICE = 'TOPOLOGY_SERVICE',
+ TOPOLOGY_SERVICE_DEPENDENCY = 'TOPOLOGY_SERVICE_RELATION',
+ TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY = 'TOPOLOGY_SERVICE_INSTANCE_RELATION',
+ TOPOLOGY_ENDPOINT_DEPENDENCY = 'TOPOLOGY_ENDPOINT_RELATION',
}
export enum TimeType {
@@ -36,8 +34,11 @@ export enum PageEventsType {
DASHBOARD_EVENTS = 'dashboardEvents',
TOPO_ENDPOINT_EVENTS = 'topoEndpointEvents',
TOPO_INSTANCE_EVENTS = 'topoInstanceEvents',
+ TOPO_SERVICE_EVENTS = 'topoInstanceEvents',
}
export enum PageTypes {
DASHBOARD = 'Dashboard',
LOG = 'Log',
+ TOPOLOGY = 'Topology',
}
+export const DEFAULT = 'default';
diff --git a/src/graph/fragments/topology.ts b/src/graph/fragments/topology.ts
index 18288f9..c540d9b 100644
--- a/src/graph/fragments/topology.ts
+++ b/src/graph/fragments/topology.ts
@@ -15,142 +15,6 @@
* limitations under the License.
*/
-export const TopoServiceInfo = {
- variable: '$duration: Duration!, $id: ID!',
- query: `
- getResponseTimeTrend: getLinearIntValues(metric: {
- name: "service_relation_server_resp_time"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getThroughputTrend: getLinearIntValues(metric: {
- name: "service_relation_server_cpm"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getSLATrend: getLinearIntValues(metric: {
- name: "service_relation_server_call_sla"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getPercentile: getMultipleLinearIntValues(metric: {
- name: "service_relation_server_percentile",
- id: $id
- }, numOfLinear: 5, duration: $duration) { values { value } }
-`,
-};
-
-export const TopoClientInfo = {
- variable: '$duration: Duration!, $id: ID!',
- query: `
- getResponseTimeTrend: getLinearIntValues(metric: {
- name: "service_relation_client_resp_time"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getThroughputTrend: getLinearIntValues(metric: {
- name: "service_relation_client_cpm"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getSLATrend: getLinearIntValues(metric: {
- name: "service_relation_client_call_sla"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getPercentile: getMultipleLinearIntValues(metric: {
- name: "service_relation_client_percentile",
- id: $id
- }, numOfLinear: 5, duration: $duration) { values { value } }
-`,
-};
-
-export const TopoInstanceClientInfo = {
- variable: '$duration: Duration!, $id: ID!',
- query: `
- getResponseTimeTrend: getLinearIntValues(metric: {
- name: "service_instance_relation_client_resp_time"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getThroughputTrend: getLinearIntValues(metric: {
- name: "service_instance_relation_client_cpm"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getSLATrend: getLinearIntValues(metric: {
- name: "service_instance_relation_client_call_sla"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getPercentile: getMultipleLinearIntValues(metric: {
- name: "service_instance_relation_client_percentile",
- id: $id
- }, numOfLinear: 5, duration: $duration) { values { value } }
-`,
-};
-
-export const TopoInstanceServerInfo = {
- variable: '$duration: Duration!, $id: ID!',
- query: `
- getResponseTimeTrend: getLinearIntValues(metric: {
- name: "service_instance_relation_server_resp_time"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getThroughputTrend: getLinearIntValues(metric: {
- name: "service_instance_relation_server_cpm"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getSLATrend: getLinearIntValues(metric: {
- name: "service_instance_relation_server_call_sla"
- id: $id
- }, duration: $duration) {
- values {
- value
- }
- }
- getPercentile: getMultipleLinearIntValues(metric: {
- name: "service_instance_relation_client_percentile",
- id: $id
- }, numOfLinear: 5, duration: $duration) { values { value } }
-`,
-};
-
export const TopoInstanceDependency = {
variable: '$clientServiceId: ID!, $serverServiceId: ID!, $duration: Duration!',
query: `
@@ -352,121 +216,3 @@ export const DependencyInstanceClientMetric = {
}
}`,
};
-export const TopoServiceDetail = {
- variable: ['$serviceId: ID!', '$duration: Duration!'],
- query: `
- servicePercentile: getMultipleLinearIntValues(metric: {
- name: "service_percentile"
- id: $serviceId
- }, numOfLinear: 5, duration: $duration) {
- values { value }
- }
- serviceSLA: getLinearIntValues(metric: {
- name: "service_sla"
- id: $serviceId
- }, duration: $duration) {
- values {
- value
- }
- }
- serviceThroughput: getLinearIntValues(metric: {
- name: "service_cpm"
- id: $serviceId
- }, duration: $duration) {
- values {
- value
- }
- }
- serviceResponseTime: getLinearIntValues(metric: {
- name: "service_resp_time"
- id: $serviceId
- }, duration: $duration) {
- values {value}
- }
- serviceApdexScore: getLinearIntValues(metric: {
- name: "service_apdex"
- id: $serviceId
- }, duration: $duration) {
- values {value}
- }
-`,
-};
-export const TopoEndpointDependencyMetrics = {
- variable: [
- '$serviceName: String',
- '$endpointName: String',
- '$destServiceName: String',
- '$destEndpointName: String',
- '$duration: Duration!',
- ],
- query: `
- endpointRelationPercentile: readLabeledMetricsValues(condition: {
- name: "endpoint_relation_percentile"
- entity: {
- scope: EndpointRelation
- serviceName: $serviceName
- normal: true
- endpointName: $endpointName
- destNormal: true
- destServiceName: $destServiceName
- destEndpointName: $destEndpointName
- }
- }, labels: ["0", "1", "2", "3", "4"], duration: $duration) {
- label
- values {
- values {value}
- }
- }
- endpointRelationCpm: readMetricsValues(condition: {
- name: "endpoint_relation_cpm"
- entity: {
- scope: EndpointRelation
- serviceName: $serviceName
- normal: true
- endpointName: $endpointName
- destNormal: true
- destServiceName: $destServiceName
- destEndpointName: $destEndpointName
- }
- }, duration: $duration) {
- label
- values {
- values {value}
- }
- }
- endpointRelationRespTime: readMetricsValues(condition: {
- name: "endpoint_relation_resp_time"
- entity: {
- scope: EndpointRelation
- serviceName: $serviceName
- normal: true
- endpointName: $endpointName
- destNormal: true
- destServiceName: $destServiceName
- destEndpointName: $destEndpointName
- }
- }, duration: $duration) {
- label
- values {
- values {value}
- }
- }
- endpointRelationSla: readMetricsValues(condition: {
- name: "endpoint_relation_sla"
- entity: {
- scope: EndpointRelation
- serviceName: $serviceName
- normal: true
- endpointName: $endpointName
- destNormal: true
- destServiceName: $destServiceName
- destEndpointName: $destEndpointName
- }
- }, duration: $duration) {
- label
- values {
- values {value}
- }
- }
-`,
-};
diff --git a/src/graph/query/topology.ts b/src/graph/query/topology.ts
index e4d8ec3..8b8a4ac 100644
--- a/src/graph/query/topology.ts
+++ b/src/graph/query/topology.ts
@@ -21,17 +21,11 @@ import {
ServicesTopo,
TopoMetric,
TopoInstanceDependency,
- TopoInstanceClientInfo,
- TopoInstanceServerInfo,
TopoServiceMetric,
TopoClientMetric,
- TopoServiceInfo,
- TopoClientInfo,
DependencyInstanceServerMetric,
DependencyInstanceClientMetric,
- TopoServiceDetail,
endpointTopology,
- TopoEndpointDependencyMetrics,
} from '../fragments/topology';
export const queryTopo = `query queryTopo(${Topo.variable}) {${Topo.query}}`;
@@ -51,32 +45,17 @@ export const queryTopoInfo = `query queryTopoInfo(
${TopoClientMetric.query}
}`;
-export const queryTopoServiceInfo = `query queryTopoServiceInfo(
- ${TopoServiceInfo.variable}) {${TopoServiceInfo.query}}`;
-
-export const queryTopoClientInfo = `query queryTopoClientInfo(
- ${TopoClientInfo.variable}) {${TopoClientInfo.query}}`;
-
export const queryTopoInstanceDependency = `query queryTopoInstanceDependency(
${TopoInstanceDependency.variable}) {${TopoInstanceDependency.query}}`;
-export const queryTopoInstanceServerInfo = `query queryTopoInstanceServerInfo(
- ${TopoInstanceServerInfo.variable}) {${TopoInstanceServerInfo.query}}`;
-
-export const queryTopoInstanceClientInfo = `query queryTopoInstanceClientInfo(
- ${TopoInstanceClientInfo.variable}) {${TopoInstanceClientInfo.query}}`;
-
export const queryDependencyInstanceServerMetric = `query queryDependencyInstanceServerMetric(
${DependencyInstanceServerMetric.variable}) {${DependencyInstanceServerMetric.query}}`;
export const queryDependencyInstanceClientMetric = `query queryDependencyInstanceClientMetric(
${DependencyInstanceClientMetric.variable}) {${DependencyInstanceClientMetric.query}}`;
-export const queryTopoServiceDetail = `query queryTopoServiceDetail(
- ${TopoServiceDetail.variable}) {${TopoServiceDetail.query}}`;
+// export const queryTopoServiceDetail = `query queryTopoServiceDetail(
+// ${TopoServiceDetail.variable}) {${TopoServiceDetail.query}}`;
export const queryEndpointTopology = `query queryEndpointTopology(${endpointTopology.variable}) {
${endpointTopology.query}}`;
-
-export const queryTopoEndpointDependencyMetrics = `query queryTopoEndpointDependencyMetrics(
- ${TopoEndpointDependencyMetrics.variable}) {${TopoEndpointDependencyMetrics.query}}`;
diff --git a/src/store/modules/dashboard/dashboard-data-query.ts b/src/store/modules/dashboard/dashboard-data-query.ts
index 5394335..7318cce 100644
--- a/src/store/modules/dashboard/dashboard-data-query.ts
+++ b/src/store/modules/dashboard/dashboard-data-query.ts
@@ -19,11 +19,7 @@ import { Commit, ActionTree, Dispatch } from 'vuex';
import { AxiosResponse } from 'axios';
import { State } from './dashboard-data';
import graph from '@/graph';
-
-export enum TopologyType {
- TOPOLOGY_ENDPOINT = 'TOPOLOGY_ENDPOINT',
- TOPOLOGY_INSTANCE = 'TOPOLOGY_INSTANCE',
-}
+import { TopologyType } from '@/constants/constant';
// actions
const actions: ActionTree<State, any> = {
@@ -34,31 +30,104 @@ const actions: ActionTree<State, any> = {
duration: any;
type: string;
rocketOption: any;
+ templateType: string;
+ templateMode: string;
},
) {
- const { currentDatabase, currentEndpoint, currentInstance, currentService } = params.rocketOption;
+ const {
+ currentDatabase,
+ currentEndpoint,
+ currentInstance,
+ currentService,
+ destService,
+ destInstance,
+ destEndpoint,
+ } = params.rocketOption;
const dashboard: string = `${window.localStorage.getItem('dashboard')}`;
const tree = dashboard ? JSON.parse(dashboard) : context.state.tree;
const normal = params.type ? true : tree[context.state.group].type === 'database' ? false : true;
- let config = {} as any;
+ let config = null as any;
const names = ['readSampledRecords', 'sortMetrics'];
if (params.type === TopologyType.TOPOLOGY_ENDPOINT) {
- const endpointComps: string = `${window.localStorage.getItem('topologyEndpoints')}`;
- const topoEndpoint = endpointComps ? JSON.parse(endpointComps) : [];
- config = topoEndpoint[params.index];
+ const endpointCompStr: string = `${window.localStorage.getItem('topologyEndpoints')}`;
+ const topoEndpoint = endpointCompStr ? JSON.parse(endpointCompStr) : {};
+ let endpointComps: any = [];
+ for (const type of params.templateType) {
+ const t: any = type;
+
+ endpointComps = [...endpointComps, ...topoEndpoint[t]];
+ }
+ config = endpointComps[params.index];
+ if (!config) {
+ return new Promise((resolve) => resolve({}));
+ }
} else if (params.type === TopologyType.TOPOLOGY_INSTANCE) {
- const instanceComps: string = `${window.localStorage.getItem('topologyInstances')}`;
- const topoInstance = instanceComps ? JSON.parse(instanceComps) : [];
- config = topoInstance[params.index];
+ const instanceCompStr: string = `${localStorage.getItem('topologyInstances')}`;
+ const topoInstance = instanceCompStr ? JSON.parse(instanceCompStr) : {};
+ let instanceComps: any[] = [];
+ for (const type of params.templateType) {
+ const t: any = type;
+
+ instanceComps = [...instanceComps, ...topoInstance[t]];
+ }
+ config = instanceComps[params.index];
+ if (!config) {
+ return new Promise((resolve) => resolve({}));
+ }
+ } else if (params.type === TopologyType.TOPOLOGY_SERVICE) {
+ const serviceCompsStr: string = `${window.localStorage.getItem('topologyServices')}`;
+ const topoService = serviceCompsStr ? JSON.parse(serviceCompsStr) : {};
+ let serviceComps: any[] = [];
+
+ for (const type of params.templateType) {
+ serviceComps = [...serviceComps, ...topoService[type]];
+ }
+ config = serviceComps[params.index];
+ if (!config) {
+ return new Promise((resolve) => resolve({}));
+ }
+ } else if (params.type === TopologyType.TOPOLOGY_SERVICE_DEPENDENCY) {
+ const serviceDependencyCompStr: string = `${window.localStorage.getItem('topologyServicesDependency')}`;
+ const topoServiceDependency = serviceDependencyCompStr ? JSON.parse(serviceDependencyCompStr) : {};
+ let serviceDependencyComps: any[] = [];
+
+ for (const type of params.templateType) {
+ serviceDependencyComps = [...serviceDependencyComps, ...topoServiceDependency[type][params.templateMode]];
+ }
+ config = serviceDependencyComps[params.index];
+ } else if (params.type === TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY) {
+ const serviceInstanceDependencyComps: string = `${localStorage.getItem('topologyServicesInstanceDependency')}`;
+ const topoServiceInstanceDependency = serviceInstanceDependencyComps
+ ? JSON.parse(serviceInstanceDependencyComps)
+ : {};
+ let instanceDependencyComps: any[] = [];
+
+ for (const type of params.templateType) {
+ instanceDependencyComps = [
+ ...instanceDependencyComps,
+ ...topoServiceInstanceDependency[type][params.templateMode],
+ ];
+ }
+ config = instanceDependencyComps[params.index];
+ } else if (params.type === TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY) {
+ const endpointDependencyCompStr: string = `${localStorage.getItem('topologyEndpointDependency')}`;
+ const topoEndpointDependency = JSON.parse(endpointDependencyCompStr || JSON.stringify({}));
+ let endpointDependencyComps: any[] = [];
+
+ for (const type of params.templateType) {
+ endpointDependencyComps = [...endpointDependencyComps, ...topoEndpointDependency[type]];
+ }
+ config = endpointDependencyComps[params.index];
} else {
config = tree[context.state.group].children[context.state.current].children[params.index];
}
+
if (!config) {
- return;
+ return new Promise((resolve) => resolve([]));
}
if (!config.metricName) {
- return;
+ return new Promise((resolve) => resolve([{ config }]));
}
// remove the space at the beginning and end of the string
const metricNames = config.metricName.split(',').map((item: string) => item.replace(/^\s*|\s*$/g, ''));
@@ -68,6 +137,7 @@ const actions: ActionTree<State, any> = {
const currentEndpointId = config.independentSelector ? config.currentEndpoint : currentEndpoint.label;
const currentDatabaseId = config.independentSelector ? config.currentDatabase : currentDatabase.label;
const labels = config.metricType === 'LABELED_VALUE' ? labelsIndex : undefined;
+ const isRelation = ['ServiceRelation', 'ServiceInstanceRelation', 'EndpointRelation'].includes(config.entityType);
const variablesList = metricNames.map((name: string) => {
let variables = {} as any;
@@ -131,13 +201,21 @@ const actions: ActionTree<State, any> = {
entity: {
scope: normal ? config.entityType : 'Service',
serviceName,
- serviceInstanceName: config.entityType === 'ServiceInstance' ? currentInstanceId : undefined,
- endpointName: config.entityType === 'Endpoint' ? currentEndpointId : undefined,
+ serviceInstanceName: config.entityType.includes('ServiceInstance') ? currentInstanceId : undefined,
+ endpointName: config.entityType.includes('Endpoint') ? currentEndpointId : undefined,
normal,
- // destNormal: normal,
- // destServiceName: '',
- // destServiceInstanceName: '',
- // destEndpointName: '',
+ destNormal: isRelation ? normal : undefined,
+ destServiceName: isRelation ? destService.label : undefined,
+ destServiceInstanceName: isRelation
+ ? config.entityType === 'ServiceInstanceRelation'
+ ? destInstance.label
+ : undefined
+ : undefined,
+ destEndpointName: isRelation
+ ? config.entityType === 'EndpointRelation'
+ ? destEndpoint.label
+ : undefined
+ : undefined,
},
},
labels,
diff --git a/src/store/modules/dashboard/mutation-types.ts b/src/store/modules/dashboard/mutation-types.ts
index eef9b1c..a526130 100644
--- a/src/store/modules/dashboard/mutation-types.ts
+++ b/src/store/modules/dashboard/mutation-types.ts
@@ -42,6 +42,9 @@ export const SET_ALL_INSTANCE_EVENTS = 'SET_ALL_INSTANCE_EVENTS';
export const SET_EVENTS_PAGE_TYPE = 'SET_EVENTS_PAGE_TYPE';
export const SET_CURRENT_SERIES_TYPE = 'SET_CURRENT_SERIES_TYPE';
export const SET_CLEAR_SELECTED_EVENTS = 'SET_CLEAR_SELECTED_EVENTS';
+export const SET_SERVICE_DEPENDENCY = 'SET_SERVICE_DEPENDENCY';
+export const SET_SERVICE_INSTANCE_DEPENDENCY = 'SET_SERVICE_INSTANCE_DEPENDENCY';
+export const SET_ENDPOINT_DEPENDENCY = 'SET_ENDPOINT_DEPENDENCY';
// comp
export const SET_CURRENT_GROUP = 'SET_CURRENT_GROUP';
diff --git a/src/store/modules/global/selectors.ts b/src/store/modules/global/selectors.ts
index 72832f2..605317f 100644
--- a/src/store/modules/global/selectors.ts
+++ b/src/store/modules/global/selectors.ts
@@ -20,7 +20,7 @@ import * as types from '../dashboard/mutation-types';
import { AxiosResponse } from 'axios';
import graph from '@/graph';
import { Duration, DurationTime, Option } from '@/types/global';
-import { PageTypes } from '@/constants/constant';
+import { PageTypes, TopologyType } from '@/constants/constant';
const EntityType = ['Service', 'ServiceInstance', 'Endpoint'];
export interface State {
@@ -34,10 +34,11 @@ export interface State {
currentInstance: Option;
updateDashboard: { key: string; label?: string | undefined };
pageType: string;
+ destService: Option;
+ destInstance: Option;
+ destEndpoint: Option;
}
-const LOG = 'Log';
-
const initState: State = {
services: [],
currentService: { key: '', label: '' },
@@ -49,17 +50,20 @@ const initState: State = {
currentDatabase: { key: '', label: '' },
updateDashboard: { key: '' },
pageType: '',
+ destService: { key: '', label: '' },
+ destInstance: { key: '', label: '' },
+ destEndpoint: { key: '', label: '' },
};
// mutations
const mutations: MutationTree<State> = {
[types.SET_SERVICES](state: State, data: Option[]) {
- state.services = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
+ state.services = state.pageType === PageTypes.LOG ? [{ label: 'All', key: '' }, ...data] : data;
state.currentService = state.services[0] || {};
},
[types.SET_CURRENT_SERVICE](state: State, service: Option) {
state.currentService = service;
- if (state.pageType !== PageTypes.DASHBOARD) {
+ if (state.pageType === PageTypes.LOG) {
state.updateDashboard = service;
}
},
@@ -69,7 +73,7 @@ const mutations: MutationTree<State> = {
},
[types.SET_ENDPOINTS](state: State, data: Option[]) {
- state.endpoints = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
+ state.endpoints = state.pageType === PageTypes.LOG ? [{ label: 'All', key: '' }, ...data] : data;
if (!state.endpoints.length) {
state.currentEndpoint = { key: '', label: '' };
return;
@@ -81,7 +85,7 @@ const mutations: MutationTree<State> = {
state.updateDashboard = endpoint;
},
[types.SET_INSTANCES](state: State, data: Option[]) {
- state.instances = state.pageType === LOG ? [{ label: 'All', key: '' }, ...data] : data;
+ state.instances = state.pageType === PageTypes.LOG ? [{ label: 'All', key: '' }, ...data] : data;
if (!state.instances.length) {
state.currentInstance = { key: '', label: '' };
return;
@@ -107,6 +111,25 @@ const mutations: MutationTree<State> = {
[types.SET_PAGE_TYPE](state: State, type: string) {
state.pageType = type;
},
+ [types.SET_SERVICE_DEPENDENCY](state: State, call: any) {
+ state.currentService = { key: call.source.id, label: call.source.name };
+ state.destService = { key: call.target.id, label: call.target.name };
+ state.updateDashboard = { key: TopologyType.TOPOLOGY_SERVICE_DEPENDENCY + call.id };
+ },
+ [types.SET_SERVICE_INSTANCE_DEPENDENCY](state: State, call: any) {
+ state.currentService = { key: call.sourceObj.serviceId, label: call.sourceObj.serviceName };
+ state.currentInstance = { key: call.sourceObj.id, label: call.sourceObj.name };
+ state.destService = { key: call.targetObj.serviceId, label: call.targetObj.serviceName };
+ state.destInstance = { key: call.targetObj.id, label: call.targetObj.name };
+ state.updateDashboard = { key: TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY + call.id };
+ },
+ [types.SET_ENDPOINT_DEPENDENCY](state: State, call: any) {
+ state.currentService = { key: call.serviceId, label: call.serviceName };
+ state.currentEndpoint = { key: call.endpointId, label: call.endpointName };
+ state.destService = { key: call.destServiceId, label: call.destServiceName };
+ state.destEndpoint = { key: call.destEndpointId, label: call.destEndpointName };
+ state.updateDashboard = { key: TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY + call.id };
+ },
};
// actions
diff --git a/src/store/modules/topology/index.ts b/src/store/modules/topology/index.ts
index 5de64af..2288f39 100644
--- a/src/store/modules/topology/index.ts
+++ b/src/store/modules/topology/index.ts
@@ -20,47 +20,10 @@ import graph from '@/graph';
import * as types from '../../mutation-types';
import axios, { AxiosPromise, AxiosResponse } from 'axios';
import { cancelToken } from '@/utils/cancelToken';
-
-interface Option {
- key: string;
- label: string;
-}
-export interface Duration {
- start: string;
- end: string;
- step: string;
-}
-export interface Call {
- avgResponseTime: number;
- cpm: number;
- isAlert: boolean;
- source: string | any;
- target: string | any;
- id: string;
- detectPoints: string[];
-}
-interface Node {
- apdex: number;
- avgResponseTime: number;
- cpm: number;
- id: string;
- isAlarm: boolean;
- name: string;
- numOfServer: number;
- numOfServerAlarm: number;
- numOfServiceAlarm: number;
- sla: number;
- type: string;
-}
-
-export interface EndpointDependencyConidition {
- serviceName: string;
- endpointName: string;
- destServiceName: string;
- destEndpointName: string;
- duration: Duration;
-}
-
+import { Call, Node, EndpointDependencyConidition } from '@/types/topo';
+import { Duration, Option } from '@/types/global';
+import { DEFAULT, TopologyType } from '@/constants/constant';
+import { uuid } from '@/utils/uuid';
export interface State {
callback: any;
calls: Call[];
@@ -71,10 +34,6 @@ export interface State {
currentLink: any;
current: Option;
mode: boolean;
- getResponseTimeTrend: number[];
- getSLATrend: number[];
- getThroughputTrend: number[];
- responsePercentile: { [key: string]: number[] };
instanceDependency: {
calls: Call[];
nodes: Node[];
@@ -84,20 +43,26 @@ export interface State {
nodes: Node[];
};
selectedInstanceCall: Call | null;
- instanceDependencyMetrics: { [key: string]: any };
+ selectedEndpointCall: Call | null;
endpointDependencyMetrics: { [key: string]: any };
currentEndpointDepth: { key: number; label: string };
- queryInstanceMetricsType: string;
- serviceThroughput: { Throughput: number[] };
- serviceSLA: { SLA: number[] };
- serviceResponseTime: { ResponseTime: number[] };
- servicePercentile: { [key: string]: number[] };
- serviceApdexScore: { ApdexScore: number[] };
- topoEndpoints: any[];
- topoInstances: any[];
+ topoEndpoints: { [key: string]: any[] };
+ topoInstances: { [key: string]: any[] };
+ topoServices: { [key: string]: any[] };
+ topoServicesDependency: { [key: string]: any[] };
+ topoServicesInstanceDependency: { [key: string]: any[] };
+ topoEndpointDependency: { [key: string]: any[] };
+ instanceDependencyMode: string;
+ editDependencyMetrics: boolean;
+ topoTemplatesType: { [key: string]: any };
}
-const PercentileItem: string[] = ['p50', 'p75', 'p90', 'p95', 'p99'];
+const DefaultConfig = {
+ width: 12,
+ title: 'Title',
+ height: 250,
+ metricType: 'UNKNOWN',
+};
const initState: State = {
callback: '',
@@ -112,10 +77,6 @@ const initState: State = {
key: 'default',
label: 'default',
},
- getResponseTimeTrend: [],
- getSLATrend: [],
- getThroughputTrend: [],
- responsePercentile: {},
instanceDependency: {
calls: [],
nodes: [],
@@ -125,23 +86,18 @@ const initState: State = {
nodes: [],
},
selectedInstanceCall: null,
- instanceDependencyMetrics: {},
+ selectedEndpointCall: null,
endpointDependencyMetrics: {},
currentEndpointDepth: { key: 2, label: '2' },
- queryInstanceMetricsType: '',
- serviceThroughput: { Throughput: [] },
- serviceSLA: { SLA: [] },
- serviceResponseTime: { ResponseTime: [] },
- servicePercentile: {
- p50: [],
- p75: [],
- p90: [],
- p95: [],
- p99: [],
- },
- serviceApdexScore: { ApdexScore: [] },
- topoEndpoints: [],
- topoInstances: [],
+ topoEndpoints: {},
+ topoInstances: {},
+ topoServices: {},
+ topoServicesDependency: {},
+ topoServicesInstanceDependency: {},
+ instanceDependencyMode: '',
+ editDependencyMetrics: false,
+ topoEndpointDependency: {},
+ topoTemplatesType: JSON.parse(localStorage.getItem('topoTemplateTypes') || JSON.stringify({})),
};
// getters
@@ -149,9 +105,6 @@ const getters = {};
// mutations
const mutations = {
- [types.SET_CALLBACK](state: State, data: any) {
- state.callback = data;
- },
[types.SET_MODE](state: State, data: string[]) {
state.detectPoints = data;
const temp = state.mode ? 'SERVER' : 'CLIENT';
@@ -162,151 +115,443 @@ const mutations = {
[types.SET_MODE_STATUS](state: State, data: boolean) {
state.mode = data;
},
- [types.SET_NODE](state: State, data: any) {
+ [types.SET_INSTANCE_DEPENDENCY_MODE_STATUS](state: State, data: string) {
+ state.instanceDependencyMode = data;
+ },
+ [types.SET_NODE](state: State, data: Node) {
state.currentNode = data;
},
- [types.SET_LINK](state: State, data: any) {
+ [types.SET_LINK](state: State, data: Call) {
state.currentLink = data;
},
- [types.SET_TOPO](state: State, data: any) {
+ [types.SET_TOPO](state: State, data: { nodes: Node[]; calls: Call[] }) {
state.calls = data.calls;
state.nodes = data.nodes;
},
[types.SET_SELECTED_CALL](state: State, data: any) {
state.selectedServiceCall = data;
},
- [types.SET_TOPO_RELATION](state: State, data: any) {
- state.getResponseTimeTrend = data.getResponseTimeTrend
- ? data.getResponseTimeTrend.values.map((i: any) => i.value)
- : [];
- state.getSLATrend = data.getSLATrend ? data.getSLATrend.values.map((i: any) => i.value) : [];
- state.getThroughputTrend = data.getThroughputTrend ? data.getThroughputTrend.values.map((i: any) => i.value) : [];
-
- if (!data.getPercentile) {
- state.responsePercentile = {};
- return;
- }
- data.getPercentile.forEach((item: any, index: number) => {
- state.responsePercentile[PercentileItem[index]] = item.values.map((i: any) => i.value);
- });
- },
[types.SET_INSTANCE_DEPENDENCY](state: State, data: any) {
state.instanceDependency = data;
},
[types.SET_SELECTED_INSTANCE_CALL](state: State, data: Call) {
state.selectedInstanceCall = data;
},
- [types.SET_INSTANCE_DEPEDENCE_METRICS](state: State, data: any) {
- state.instanceDependencyMetrics.getResponseTimeTrend = data.getResponseTimeTrend
- ? data.getResponseTimeTrend.values.map((i: any) => i.value)
- : [];
- state.instanceDependencyMetrics.getSLATrend = data.getSLATrend
- ? data.getSLATrend.values.map((i: any) => i.value)
- : [];
- state.instanceDependencyMetrics.getThroughputTrend = data.getThroughputTrend
- ? data.getThroughputTrend.values.map((i: any) => i.value)
- : [];
- state.instanceDependencyMetrics.percentResponse = {};
- if (!data.getPercentile) {
- return;
+ [types.SET_SELECTED_ENDPOINT_CALL](state: State, data: Call) {
+ state.selectedEndpointCall = data;
+ },
+ [types.SET_TOPO_ENDPOINT](state: State, data: { [key: string]: unknown[] }) {
+ state.topoEndpoints = data;
+ window.localStorage.setItem('topologyEndpoints', JSON.stringify(data));
+ },
+ [types.SET_TOPO_INSTANCE](state: State, data: { [key: string]: unknown[] }) {
+ state.topoInstances = data;
+ window.localStorage.setItem('topologyInstances', JSON.stringify(data));
+ },
+ [types.SET_TOPO_SERVICE_DEPENDENCY](state: State, data: any) {
+ state.topoServicesDependency = data;
+ localStorage.setItem('topologyServicesDependency', JSON.stringify(data));
+ },
+ [types.SET_TOPO_SERVICE_INSTANCE_DEPENDENCY](state: State, data: any) {
+ state.topoServicesInstanceDependency = data;
+ localStorage.setItem('topologyServicesInstanceDependency', JSON.stringify(data));
+ },
+ [types.SET_TOPO_ENDPOINT_DEPENDENCY](state: State, data: any) {
+ state.topoEndpointDependency = data;
+ localStorage.setItem('topologyEndpointDependency', JSON.stringify(data));
+ },
+ [types.DELETE_TOPO_ENDPOINT](state: State, id: string) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT] || {};
+ const temps = serviceTemplateType[state.currentNode.type || DEFAULT] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoEndpoints[type.key].findIndex((d) => d.uuid === id);
+ if (index > -1) {
+ state.topoEndpoints[type.key].splice(index, 1);
+ localStorage.setItem('topologyEndpoints', JSON.stringify(state.topoEndpoints));
+ }
+ }
+ },
+ [types.DELETE_TOPO_INSTANCE](state: State, id: string) {
+ const instanceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_INSTANCE] || {};
+ const temps = instanceTemplateType[state.currentNode.type || DEFAULT] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoInstances[type.key].findIndex((d) => d.uuid === id);
+ if (index > -1) {
+ state.topoInstances[type.key].splice(index, 1);
+ window.localStorage.setItem('topologyInstances', JSON.stringify(state.topoInstances));
+ }
}
- data.getPercentile.forEach((item: any, index: number) => {
- state.instanceDependencyMetrics.percentResponse[PercentileItem[index]] = item.values.map((i: any) => i.value);
- });
},
- [types.SET_ENDPOINT_DEPENDENCY_METRICS](state: State, data: { [key: string]: any }) {
- state.endpointDependencyMetrics.cpm = data.endpointRelationCpm
- ? data.endpointRelationCpm.values.values.map((i: any) => i.value)
- : [];
- state.endpointDependencyMetrics.respTime = data.endpointRelationRespTime
- ? data.endpointRelationRespTime.values.values.map((i: any) => i.value)
- : [];
- state.endpointDependencyMetrics.sla = data.endpointRelationSla
- ? data.endpointRelationSla.values.values.map((i: any) => i.value)
- : [];
- state.endpointDependencyMetrics.percentile = {};
- if (!data.endpointRelationPercentile) {
+ [types.DELETE_TOPO_SERVICE](state: State, id: string) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE] || {};
+ const temps = serviceTemplateType[state.currentNode.type || DEFAULT] || [{ key: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServices[type.key].findIndex((d) => d.uuid === id);
+ if (index > -1) {
+ state.topoServices[type.key].splice(index, 1);
+ localStorage.setItem('topologyServices', JSON.stringify(state.topoServices));
+ }
+ }
+ },
+ [types.DELETE_TOPO_SERVICE_DEPENDENCY](state: State, id: string) {
+ if (!state.selectedServiceCall) {
return;
}
- for (const item of data.endpointRelationPercentile) {
- state.endpointDependencyMetrics.percentile[PercentileItem[Number(item.label)]] = item.values.values.map(
- (i: any) => i.value,
- );
+ const typeCall = state.selectedServiceCall.source.type || DEFAULT;
+ const serviceDependencyTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY] || {};
+ const temps =
+ serviceDependencyTemplateType[typeCall] ||
+ serviceDependencyTemplateType[DEFAULT] || [{ key: DEFAULT, label: DEFAULT }] ||
+ [];
+ const mode: any = state.mode ? 'server' : 'client';
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServicesDependency[type.key][mode].findIndex((d: any) => d.uuid === id);
+ if (index > -1) {
+ state.topoServicesDependency[type.key][mode].splice(index, 1);
+ localStorage.setItem('topologyServicesDependency', JSON.stringify(state.topoServicesDependency));
+ }
}
},
- [types.SET_INSTANCE_DEPEDENCE_TYPE](state: State, data: string) {
- state.queryInstanceMetricsType = data;
- },
- [types.SET_SERVICE_DETAIL](state: State, data: any) {
- state.serviceApdexScore = data.serviceApdexScore
- ? data.serviceApdexScore.values.map((i: any) => Number((i.value / 10000).toFixed(2)))
- : [];
- state.serviceResponseTime = data.serviceResponseTime
- ? data.serviceResponseTime.values.map((i: any) => i.value)
- : [];
- state.serviceThroughput = data.serviceThroughput ? data.serviceThroughput.values.map((i: any) => i.value) : [];
- state.serviceSLA = data.serviceSLA ? data.serviceSLA.values.map((i: any) => i.value / 100) : [];
- if (!data.servicePercentile) {
+ [types.DELETE_TOPO_ENDPOINT_DEPENDENCY](state: State, id: string) {
+ if (!state.selectedEndpointCall) {
return;
}
- data.servicePercentile.forEach((item: any, index: number) => {
- state.servicePercentile[PercentileItem[index]] = item.values.map((i: any) => i.value);
- });
+ const typeCall = state.selectedEndpointCall.type || DEFAULT;
+ const serviceDependencyTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY] || {};
+ const temps = serviceDependencyTemplateType[typeCall] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoEndpointDependency[type.key].findIndex((d) => d.uuid === id);
+ if (index > -1) {
+ state.topoEndpointDependency[type.key].splice(index, 1);
+ localStorage.setItem('topologyEndpointDependency', JSON.stringify(state.topoEndpointDependency));
+ }
+ }
},
- [types.SET_TOPO_ENDPOINT](state: State, data: any[]) {
- state.topoEndpoints = data;
- window.localStorage.setItem('topologyEndpoints', JSON.stringify(data));
+ [types.DELETE_TOPO_INSTANCE_DEPENDENCY](state: State, id: string) {
+ const { sourceObj } = state.selectedInstanceCall || ({} as any);
+ const typeCall = sourceObj.type || DEFAULT;
+ const mode: any = state.instanceDependencyMode;
+ const serviceDependencyTemplateType =
+ state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY] || {};
+ const temps = serviceDependencyTemplateType[typeCall] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServicesInstanceDependency[type.key][mode].findIndex((d: any) => d.uuid === id);
+ if (index > -1) {
+ state.topoServicesInstanceDependency[type.key][mode].splice(index, 1);
+ localStorage.setItem(
+ 'topologyServicesInstanceDependency',
+ JSON.stringify(state.topoServicesInstanceDependency),
+ );
+ }
+ }
},
- [types.SET_TOPO_INSTANCE](state: State, data: any[]) {
- state.topoInstances = data;
- window.localStorage.setItem('topologyInstances', JSON.stringify(data));
+ [types.EDIT_TOPO_INSTANCE_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ const templateType = state.topoTemplatesType[TopologyType.TOPOLOGY_INSTANCE] || {};
+ const temps = templateType[state.currentNode.type] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoInstances[type.key].findIndex((d) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoInstances[type.key][params.index] = {
+ ...state.topoInstances[type.key][params.index],
+ ...params.values,
+ };
+ localStorage.setItem('topologyInstances', JSON.stringify(state.topoInstances));
+ }
+ }
},
- [types.EDIT_TOPO_INSTANCE_CONFIG](state: State, params: { values: any; index: number }) {
- state.topoInstances[params.index] = { ...state.topoInstances[params.index], ...params.values };
- window.localStorage.setItem('topologyInstances', JSON.stringify(state.topoInstances));
+ [types.EDIT_TOPO_ENDPOINT_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ const templateType = state.topoTemplatesType[TopologyType.TOPOLOGY_INSTANCE] || {};
+ const temps = templateType[state.currentNode.type] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoEndpoints[type.key].findIndex((d) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoEndpoints[type.key][params.index] = {
+ ...state.topoEndpoints[type.key][params.index],
+ ...params.values,
+ };
+ localStorage.setItem('topologyEndpoints', JSON.stringify(state.topoEndpoints));
+ }
+ }
},
- [types.EDIT_TOPO_ENDPOINT_CONFIG](state: State, params: { values: any; index: number }) {
- state.topoEndpoints[params.index] = { ...state.topoEndpoints[params.index], ...params.values };
- window.localStorage.setItem('topologyEndpoints', JSON.stringify(state.topoEndpoints));
+ [types.EDIT_TOPO_SERVICE_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE] || {};
+ const temps = serviceTemplateType[state.currentNode.type] || [{ key: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServices[type.key].findIndex((d) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoServices[type.key][params.index] = {
+ ...state.topoServices[type.key][params.index],
+ ...params.values,
+ };
+ window.localStorage.setItem('topologyServices', JSON.stringify(state.topoServices));
+ }
+ }
},
- [types.DELETE_TOPO_ENDPOINT](state: State, index: number) {
- state.topoEndpoints.splice(index, 1);
- window.localStorage.setItem('topologyEndpoints', JSON.stringify(state.topoEndpoints));
+ [types.EDIT_ENDPOINT_DEPENDENCY_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ if (!state.selectedEndpointCall) {
+ return;
+ }
+ const endpointTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY] || {};
+ const temps = endpointTemplateType[state.selectedEndpointCall.type || DEFAULT] || [
+ { key: DEFAULT, label: DEFAULT },
+ ];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoEndpointDependency[type.key].findIndex((d) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoEndpointDependency[type.key][index] = {
+ ...state.topoEndpointDependency[type.key][index],
+ ...params.values,
+ };
+ localStorage.setItem('topologyEndpointDependency', JSON.stringify(state.topoEndpointDependency));
+ }
+ }
},
- [types.DELETE_TOPO_INSTANCE](state: State, index: number) {
- state.topoInstances.splice(index, 1);
- window.localStorage.setItem('topologyInstances', JSON.stringify(state.topoInstances));
+ [types.EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ const { source } = state.currentLink;
+ const mode: any = state.mode ? 'server' : 'client';
+ const serviceEndpointTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY] || {};
+ const temps = serviceEndpointTemplateType[source.type || DEFAULT] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServicesDependency[type.key][mode].findIndex((d: any) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoServicesDependency[type.key][mode][params.index] = {
+ ...state.topoServicesDependency[type.key][mode][params.index],
+ ...params.values,
+ };
+ localStorage.setItem('topologyServicesDependency', JSON.stringify(state.topoServicesDependency));
+ }
+ }
+ },
+ [types.EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG](state: State, params: { values: any; index: number; uuid: string }) {
+ const { sourceObj } = state.selectedInstanceCall || ({} as any);
+ const typeCall = sourceObj.type || DEFAULT;
+ const mode: any = state.instanceDependencyMode;
+
+ if (!(state.topoServicesInstanceDependency[typeCall] && state.topoServicesInstanceDependency[typeCall][mode])) {
+ return;
+ }
+ const endpointTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY] || {};
+ const temps = endpointTemplateType[typeCall] || [{ key: DEFAULT, label: DEFAULT }];
+ let index = -1;
+
+ for (const type of temps) {
+ index = state.topoServicesInstanceDependency[type.key][mode].findIndex((d: any) => d.uuid === params.uuid);
+ if (index > -1) {
+ state.topoServicesInstanceDependency[type.key][mode][params.index] = {
+ ...state.topoServicesInstanceDependency[type.key][mode][params.index],
+ ...params.values,
+ };
+ localStorage.setItem(
+ 'topologyServicesInstanceDependency',
+ JSON.stringify(state.topoServicesInstanceDependency),
+ );
+ }
+ }
},
[types.ADD_TOPO_INSTANCE_COMP](state: State) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE] || {};
+ const temps = serviceTemplateType[state.currentNode.type] || [{ key: DEFAULT }];
+ const type = temps[temps.length - 1 || 0].key;
const comp = {
+ ...DefaultConfig,
width: 3,
- title: 'Title',
- height: 350,
+ uuid: uuid(),
entityType: 'ServiceInstance',
- independentSelector: false,
- metricType: 'UNKNOWN',
};
- state.topoInstances.push(comp);
+
+ state.topoInstances[type].push(comp);
window.localStorage.setItem('topologyInstances', JSON.stringify(state.topoInstances));
},
[types.ADD_TOPO_ENDPOINT_COMP](state: State) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE] || {};
+ const temps = serviceTemplateType[state.currentNode.type] || [{ key: DEFAULT }];
+ const type = temps[temps.length - 1 || 0].key;
const comp = {
+ ...DefaultConfig,
width: 3,
- title: 'Title',
- height: 350,
+ uuid: uuid(),
entityType: 'Endpoint',
- independentSelector: false,
- metricType: 'UNKNOWN',
};
- state.topoEndpoints.push(comp);
+
+ state.topoEndpoints[type].push(comp);
window.localStorage.setItem('topologyEndpoints', JSON.stringify(state.topoEndpoints));
},
+ [types.ADD_TOPO_SERVICE_COMP](state: State) {
+ const serviceTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE] || {};
+ const temps = serviceTemplateType[state.currentNode.type] || [{ key: DEFAULT }];
+ const type = temps[temps.length - 1 || 0].key;
+ const comp = {
+ ...DefaultConfig,
+ entityType: 'Service',
+ uuid: uuid(),
+ };
+ state.topoServices[type].push(comp);
+ window.localStorage.setItem('topologyServices', JSON.stringify(state.topoServices));
+ },
+ [types.ADD_TOPO_ENDPOINT_DEPENDENCY_COMP](state: State) {
+ if (!state.selectedEndpointCall) {
+ return;
+ }
+ const callType = state.selectedEndpointCall.type || DEFAULT;
+ const endpointDependencyTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY] || {};
+ const temps = endpointDependencyTemplateType[callType] || [{ key: DEFAULT, label: DEFAULT }];
+ const type = temps[temps.length - 1 || 0].key;
+ const comp = {
+ ...DefaultConfig,
+ height: 200,
+ width: 3,
+ uuid: uuid(),
+ entityType: 'EndpointRelation',
+ };
+
+ state.topoEndpointDependency[type].push(comp);
+ localStorage.setItem('topologyEndpointDependency', JSON.stringify(state.topoEndpointDependency));
+ },
+ [types.ADD_TOPO_SERVICE_DEPENDENCY_COMP](state: State) {
+ if (!state.selectedServiceCall) {
+ return;
+ }
+ const sourceType = state.selectedServiceCall.source.type || DEFAULT;
+ const serviceDependencyTemplateType = state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY] || {};
+ const temps = serviceDependencyTemplateType[sourceType] || serviceDependencyTemplateType[DEFAULT] || [];
+ const type = temps[temps.length - 1 || 0] ? temps[temps.length - 1 || 0].key : [DEFAULT];
+ const mode: any = state.mode ? 'server' : 'client';
+
+ if (!(state.topoServicesDependency[type] && state.topoServicesDependency[type][mode])) {
+ return;
+ }
+ const comp = {
+ ...DefaultConfig,
+ uuid: uuid(),
+ entityType: 'ServiceRelation',
+ };
+ state.topoServicesDependency[type][mode].push(comp);
+ window.localStorage.setItem('topologyServicesDependency', JSON.stringify(state.topoServicesDependency));
+ },
+ [types.ADD_TOPO_INSTANCE_DEPENDENCY_COMP](state: State) {
+ if (!state.selectedInstanceCall) {
+ return;
+ }
+ const sourceType = state.selectedInstanceCall.sourceObj.type || DEFAULT;
+ const serviceDependencyTemplateType =
+ state.topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY] || {};
+ const temps = serviceDependencyTemplateType[sourceType] || [{ key: DEFAULT, label: DEFAULT }];
+ const type = temps[temps.length - 1 || 0].key;
+ const mode: any = state.instanceDependencyMode;
+
+ if (!(state.topoServicesInstanceDependency[type] && state.topoServicesInstanceDependency[type][mode])) {
+ return;
+ }
+ const comp = {
+ ...DefaultConfig,
+ uuid: uuid(),
+ entityType: 'ServiceInstanceRelation',
+ };
+ state.topoServicesInstanceDependency[type][mode].push(comp);
+ localStorage.setItem('topologyServicesInstanceDependency', JSON.stringify(state.topoServicesInstanceDependency));
+ },
[types.SET_ENDPOINT_DEPENDENCY](state: State, data: { calls: Call[]; nodes: Node[] }) {
state.endpointDependency = data;
+ state.selectedEndpointCall = null;
},
[types.SET_ENDPOINT_DEPTH](state: State, data: { key: number; label: string }) {
state.currentEndpointDepth = data;
},
+ [types.SET_TOPO_SERVICE](state: State, data: any) {
+ state.topoServices = data;
+ localStorage.setItem('topologyServices', JSON.stringify(data));
+ },
+ [types.EDIT_DEPENDENCY_METRICS](state: State, isEdit: boolean) {
+ state.editDependencyMetrics = isEdit;
+ },
+ [types.IMPORT_TREE_SERVICE](state: State, data: any) {
+ const keys = Object.keys(data);
+
+ for (const key of keys) {
+ if (state.topoServices[key]) {
+ state.topoServices[key].push(...data[key]);
+ } else {
+ state.topoServices[key] = data[key];
+ }
+ }
+ localStorage.setItem('topologyServices', JSON.stringify(state.topoServices));
+ },
+ [types.IMPORT_TREE_SERVICE_DEPENDENCY](state: State, data: any) {
+ const keys = Object.keys(data);
+ const modes: any = ['server', 'client'];
+
+ for (const key of keys) {
+ if (state.topoServicesDependency[key]) {
+ for (const mode of modes) {
+ if (state.topoServicesDependency[key][mode]) {
+ state.topoServicesDependency[key][mode].push(...data[key][mode]);
+ } else {
+ state.topoServicesDependency[key][mode] = data[key][mode];
+ }
+ }
+ } else {
+ state.topoServicesDependency[key] = data[key];
+ }
+ }
+ localStorage.setItem('topologyServicesDependency', JSON.stringify(state.topoServicesDependency));
+ },
+ [types.IMPORT_TREE_ENDPOINT_DEPENDENCY](state: State, data: any) {
+ const keys = Object.keys(data);
+
+ for (const key of keys) {
+ if (state.topoEndpointDependency[key]) {
+ state.topoEndpointDependency[key].push(...data[key]);
+ } else {
+ state.topoEndpointDependency[key] = data[key];
+ }
+ }
+ localStorage.setItem('topologyEndpointDependency', JSON.stringify(state.topoEndpointDependency));
+ },
+ [types.IMPORT_TREE_INSTANCE_DEPENDENCY](state: State, data: any) {
+ const keys = Object.keys(data);
+ const modes: any = ['server', 'client'];
+
+ for (const key of keys) {
+ if (state.topoServicesInstanceDependency[key]) {
+ for (const mode of modes) {
+ if (state.topoServicesInstanceDependency[key][mode]) {
+ state.topoServicesInstanceDependency[key][mode].push(...data[key][mode]);
+ } else {
+ state.topoServicesInstanceDependency[key][mode] = data[key][mode];
+ }
+ }
+ } else {
+ state.topoServicesInstanceDependency[key] = data[key];
+ }
+ }
+ localStorage.setItem('topologyServicesInstanceDependency', JSON.stringify(state.topoServicesInstanceDependency));
+ },
+ [types.UPDATE_TOPO_TEMPLATE_TYPES](state: State, data: any) {
+ state.topoTemplatesType = data;
+ localStorage.setItem('topoTemplateTypes', JSON.stringify(data));
+ },
};
// actions
@@ -340,69 +585,8 @@ const actions: ActionTree<State, any> = {
context.commit(types.SET_TOPO, { calls: [], nodes: [] });
},
CLEAR_TOPO_INFO(context: { commit: Commit; state: State }) {
- context.commit(types.SET_TOPO_RELATION, {});
context.commit(types.SET_SELECTED_CALL, null);
},
- GET_INSTANCE_DEPENDENCY_METRICS(
- context: { commit: Commit; state: State; dispatch: Dispatch; getters: any },
- params: any,
- ) {
- if (params.mode === 'SERVER') {
- params.queryType = 'queryTopoInstanceServerInfo';
- context.dispatch('INSTANCE_RELATION_INFO', params);
- }
- if (params.mode === 'CLIENT') {
- params.queryType = 'queryTopoInstanceClientInfo';
- context.dispatch('INSTANCE_RELATION_INFO', params);
- }
- },
- GET_TOPO_SERVICE_INFO(context: { commit: Commit; state: State }, params: { id: string; duration: Duration }) {
- if (!params.id) {
- return;
- }
- return graph
- .query('queryTopoServiceInfo')
- .params({
- id: params.id,
- duration: params.duration,
- })
- .then((res: AxiosResponse) => {
- if (!res.data.data) {
- return;
- }
- context.commit('SET_TOPO_RELATION', res.data.data);
- context.commit(types.SET_SELECTED_CALL, params);
- });
- },
- GET_TOPO_CLIENT_INFO(context: { commit: Commit; state: State }, params: any) {
- return graph
- .query('queryTopoClientInfo')
- .params(params)
- .then((res: AxiosResponse) => {
- if (!res.data.data) {
- return;
- }
- context.commit('SET_TOPO_RELATION', res.data.data);
- context.commit(types.SET_SELECTED_CALL, params);
- });
- },
- GET_TOPO_SERVICE_DETAIL(
- context: { commit: Commit; state: State },
- params: { serviceId: string; duration: Duration },
- ) {
- return graph
- .query('queryTopoServiceDetail')
- .params({
- serviceId: params.serviceId,
- duration: params.duration,
- })
- .then((res: AxiosResponse) => {
- if (!res.data.data) {
- return;
- }
- context.commit('SET_SERVICE_DETAIL', res.data.data);
- });
- },
GET_TOPO(context: { commit: Commit; state: State }, params: any) {
let query = 'queryTopo';
if (params.serviceId) {
@@ -422,8 +606,8 @@ const actions: ActionTree<State, any> = {
const calls = res.data.data.topo.calls;
const nodes = res.data.data.topo.nodes;
const ids = nodes.map((i: any) => i.id);
- const idsC = calls.filter((i: any) => i.detectPoints.indexOf('CLIENT') !== -1).map((b: any) => b.id);
- const idsS = calls.filter((i: any) => i.detectPoints.indexOf('CLIENT') === -1).map((b: any) => b.id);
+ const idsC = calls.filter((i: any) => i.detectPoints.includes('CLIENT')).map((b: any) => b.id);
+ const idsS = calls.filter((i: any) => i.detectPoints.includes('CLIENT')).map((b: any) => b.id);
return graph
.query('queryTopoInfo')
.params({ ...params, ids, idsC, idsS })
@@ -580,11 +764,16 @@ const actions: ActionTree<State, any> = {
source = node;
call.serviceName = node.serviceName;
call.endpointName = node.name;
+ call.serviceId = node.serviceId;
+ call.endpointId = node.id;
+ call.type = node.type;
}
if (node.id === call.target) {
target = node;
call.destServiceName = node.serviceName;
+ call.destServiceId = node.serviceId;
call.destEndpointName = node.name;
+ call.destEndpointId = node.id;
}
}
return `cpm_${index}: readMetricsValue(condition: {
@@ -702,40 +891,20 @@ const actions: ActionTree<State, any> = {
nodes: res.data.data.topo.nodes,
calls: [...values[0], ...values[1]],
};
+ for (const call of instanceDependency.calls) {
+ for (const node of instanceDependency.nodes) {
+ if (call.source === node.id) {
+ call.sourceObj = node;
+ }
+ if (call.target === node.id) {
+ call.targetObj = node;
+ }
+ }
+ }
context.commit(types.SET_INSTANCE_DEPENDENCY, instanceDependency);
});
});
},
- INSTANCE_RELATION_INFO(
- context: { commit: Commit; state: State },
- params: Call & { mode: string; queryType: string; durationTime: Duration },
- ) {
- graph
- .query(params.queryType)
- .params({
- id: params.id,
- duration: params.durationTime,
- })
- .then((res: AxiosResponse) => {
- if (!(res.data && res.data.data)) {
- return;
- }
- context.commit(types.SET_SELECTED_INSTANCE_CALL, params);
- context.commit(types.SET_INSTANCE_DEPEDENCE_TYPE, params.mode);
- context.commit(types.SET_INSTANCE_DEPEDENCE_METRICS, res.data.data);
- });
- },
- GET_ENDPOINT_DEPENDENCY_METRICS(context: { commit: Commit; state: State }, params: EndpointDependencyConidition) {
- return graph
- .query('queryTopoEndpointDependencyMetrics')
- .params(params)
- .then((res: AxiosResponse) => {
- if (!(res.data && res.data.data)) {
- return;
- }
- context.commit(types.SET_ENDPOINT_DEPENDENCY_METRICS, res.data.data);
- });
- },
};
export default {
diff --git a/src/store/modules/trace/index.ts b/src/store/modules/trace/index.ts
index 4e9a009..2fbdd3d 100644
--- a/src/store/modules/trace/index.ts
+++ b/src/store/modules/trace/index.ts
@@ -18,7 +18,7 @@
import graph from '@/graph';
import * as types from '@/store/mutation-types';
import { Option } from '@/types/global';
-import { Span, Trace } from '@/types/topo';
+import { Span, Trace } from '@/types/trace';
import { AxiosResponse } from 'axios';
import { ActionTree, Commit, Dispatch, MutationTree } from 'vuex';
@@ -100,7 +100,7 @@ const mutations: MutationTree<State> = {
[types.SET_TRACE_SPANS](state: State, data: Span[]): void {
state.traceSpans = data;
},
- [types.SET_CURRENT_TRACE](state: State, data: Span): void {
+ [types.SET_CURRENT_TRACE](state: State, data: any): void {
state.currentTrace = data;
},
[types.SET_DEFAULT_EMPTY_TRACE](state: State): void {
diff --git a/src/store/mutation-types.ts b/src/store/mutation-types.ts
index d94ad6d..c23f013 100644
--- a/src/store/mutation-types.ts
+++ b/src/store/mutation-types.ts
@@ -78,7 +78,6 @@ export const SET_TOPO = 'SET_TOPO';
export const SET_NODE = 'SET_NODE';
export const SET_MODE = 'SET_MODE';
export const SET_TOPO_RELATION = 'SET_TOPO_RELATION';
-export const SET_CALLBACK = 'SET_CALLBACK';
export const SET_MODE_STATUS = 'SET_MODE_STATUS';
export const SET_HONEYCOMB_NODE = 'SET_HONEYCOMB_NODE';
export const SET_SHOW_DIALOG = 'SET_SHOW_DIALOG';
@@ -87,8 +86,6 @@ export const SET_LINK = 'SET_LINK';
export const SET_SERVICE_DETAIL = 'SET_SERVICE_DETAIL';
export const SET_SERVICE_TOPOLOGY = 'GET_SERVICE_TOPOLOGY';
export const SET_SELECTED_INSTANCE_CALL = 'SET_SELECTED_INSTANCE_CALL';
-export const SET_INSTANCE_DEPEDENCE_METRICS = 'SET_INSTANCE_DEPEDENCE_METRICS';
-export const SET_INSTANCE_DEPEDENCE_TYPE = 'SET_INSTANCE_DEPEDENCE_TYPE';
export const SET_SELECTED_CALL = 'SET_SELECTED_CALL';
export const SET_TOPO_ENDPOINT = 'SET_TOPO_ENDPOINT';
export const SET_TOPO_INSTANCE = 'SET_TOPO_INSTANCE';
@@ -99,8 +96,31 @@ export const DELETE_TOPO_ENDPOINT = 'DELETE_TOPO_ENDPOINT';
export const ADD_TOPO_INSTANCE_COMP = 'ADD_TOPO_INSTANCE_COMP';
export const ADD_TOPO_ENDPOINT_COMP = 'ADD_TOPO_ENDPOINT_COMP';
export const SET_ENDPOINT_DEPENDENCY = 'SET_ENDPOINT_DEPENDENCY';
-export const SET_ENDPOINT_DEPENDENCY_METRICS = 'SET_ENDPOINT_DEPENDENCY_METRICS';
export const SET_ENDPOINT_DEPTH = 'SET_ENDPOINT_DEPTH';
+export const SET_TOPO_SERVICE = 'SET_TOPO_SERVICE';
+export const ADD_TOPO_SERVICE_COMP = 'ADD_TOPO_SERVICE_COMP';
+export const DELETE_TOPO_SERVICE = 'DELETE_TOPO_SERVICE';
+export const EDIT_TOPO_SERVICE_CONFIG = 'EDIT_TOPO_SERVICE_CONFIG';
+export const IMPORT_TREE_SERVICE = 'IMPORT_TREE_SERVICE';
+export const SET_TOPO_SERVICE_DEPENDENCY = 'SET_TOPO_SERVICE_DEPENDENCY';
+export const EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG = 'EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG';
+export const DELETE_TOPO_SERVICE_DEPENDENCY = 'DELETE_TOPO_SERVICE_DEPENDENCY';
+export const ADD_TOPO_SERVICE_DEPENDENCY_COMP = 'ADD_TOPO_SERVICE_DEPENDENCY_COMP';
+export const IMPORT_TREE_SERVICE_DEPENDENCY = 'IMPORT_TREE_SERVICE_DEPENDENCY';
+export const SET_TOPO_SERVICE_INSTANCE_DEPENDENCY = 'SET_TOPO_SERVICE_INSTANCE_DEPENDENCY';
+export const SET_INSTANCE_DEPENDENCY_MODE_STATUS = 'SET_INSTANCE_DEPENDENCY_MODE_STATUS';
+export const EDIT_DEPENDENCY_METRICS = 'EDIT_DEPENDENCY_METRICS';
+export const EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG = 'EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG';
+export const ADD_TOPO_INSTANCE_DEPENDENCY_COMP = 'ADD_TOPO_INSTANCE_DEPENDENCY_COMP';
+export const DELETE_TOPO_INSTANCE_DEPENDENCY = 'DELETE_TOPO_INSTANCE_DEPENDENCY';
+export const IMPORT_TREE_INSTANCE_DEPENDENCY = 'IMPORT_TREE_INSTANCE_DEPENDENCY';
+export const SET_TOPO_ENDPOINT_DEPENDENCY = 'SET_TOPO_ENDPOINT_DEPENDENCY';
+export const SET_SELECTED_ENDPOINT_CALL = 'SET_SELECTED_ENDPOINT_CALL';
+export const IMPORT_TREE_ENDPOINT_DEPENDENCY = 'IMPORT_TREE_ENDPOINT_DEPENDENCY';
+export const ADD_TOPO_ENDPOINT_DEPENDENCY_COMP = 'ADD_TOPO_ENDPOINT_DEPENDENCY_COMP';
+export const EDIT_ENDPOINT_DEPENDENCY_CONFIG = 'EDIT_ENDPOINT_DEPENDENCY_CONFIG';
+export const DELETE_TOPO_ENDPOINT_DEPENDENCY = 'DELETE_TOPO_ENDPOINT_DEPENDENCY';
+export const UPDATE_TOPO_TEMPLATE_TYPES = 'UPDATE_TOPO_TEMPLATE_TYPES';
// profile
export const SET_TASK_OPTIONS = 'SET_TASK_OPTIONS';
diff --git a/src/types/topo.d.ts b/src/types/topo.d.ts
index 2932ef5..863455c 100644
--- a/src/types/topo.d.ts
+++ b/src/types/topo.d.ts
@@ -14,72 +14,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-export interface CompsContainer {
- service: CompsItem[];
- database: CompsItem[];
- proxy: CompsItem[];
-}
-
-export interface CompsItem {
- o: string;
- comp: string;
- n: string;
- t: string;
+import { Duration } from './global';
+export interface Call {
+ avgResponseTime: number;
+ cpm: number;
+ isAlert: boolean;
+ source: string | any;
+ target: string | any;
+ id: string;
+ detectPoints: string[];
type?: string;
- w: number;
-}
-
-export interface CompsGroup {
+ sourceObj?: any;
+}
+export interface Node {
+ apdex: number;
+ avgResponseTime: number;
+ cpm: number;
+ id: string;
+ isAlarm: boolean;
name: string;
- children: CompsItem[];
-}
-
-export interface CompQuery {
- service: Option;
- database: Option;
- endpoint: Option;
- instance: Option;
-}
-
-export interface CompsTree {
- name?: string;
+ numOfServer: number;
+ numOfServerAlarm: number;
+ numOfServiceAlarm: number;
+ sla: number;
type: string;
- query: CompQuery;
- children: CompsGroup[];
-}
-
-export interface Option {
- key: string;
- label: string;
-}
-
-export interface Duration {
- start: Date;
- end: Date;
- step: string;
-}
-
-export interface DurationTime {
- start: string;
- end: string;
- step: string;
-}
-
-export interface Trace {
- duration: number;
- isError: boolean;
- key: string;
- operationNames: string[];
- start: string;
- traceIds: string[];
}
-export interface Span {
- duration: number;
- isError: boolean;
- key: string;
- operationNames: string[];
- start: string;
- traceIds: string[];
+export interface EndpointDependencyConidition {
+ serviceName: string;
+ serviceId: string;
+ endpointName: string;
+ endpointId: string;
+ destServiceName: string;
+ destEndpointName: string;
+ destServiceId: string;
+ destEndpointId: string;
+ duration: Duration;
}
diff --git a/src/views/components/dashboard/charts/chart-bar.vue b/src/views/components/dashboard/charts/chart-bar.vue
index 16dbb49..826b591 100644
--- a/src/views/components/dashboard/charts/chart-bar.vue
+++ b/src/views/components/dashboard/charts/chart-bar.vue
@@ -24,6 +24,7 @@ limitations under the License. -->
export default class ChartBar extends Vue {
@Prop() private data!: any;
@Prop() private intervalTime!: any;
+ @Prop() private theme!: string;
@Prop() private itemEvents!: Event[];
public resize() {
const chart: any = this.$refs.chart;
@@ -131,6 +132,9 @@ limitations under the License. -->
top: 0,
left: 0,
itemWidth: 12,
+ textStyle: {
+ color: this.theme === 'dark' ? '#fff' : '#333',
+ },
},
grid: {
top: keys.length === 1 ? 15 : 40,
diff --git a/src/views/components/dashboard/charts/chart-edit.vue b/src/views/components/dashboard/charts/chart-edit.vue
index f900c8e..2515b3f 100755
--- a/src/views/components/dashboard/charts/chart-edit.vue
+++ b/src/views/components/dashboard/charts/chart-edit.vue
@@ -43,7 +43,7 @@ limitations under the License. -->
</option>
</select>
</div>
- <div class="flex-h mb-5" v-show="isChartType">
+ <div class="flex-h mb-5" v-show="hasChartType">
<div class="title grey sm">{{ $t('chartType') }}:</div>
<select
class="long"
@@ -73,7 +73,7 @@ limitations under the License. -->
@change="setItemConfig({ type: 'labelsIndex', value: $event.target.value })"
/>
</div>
- <div class="flex-h mb-5" v-show="!isDatabase && !pageTypes.includes(type)">
+ <div class="flex-h mb-5" v-show="!noEntity">
<div class="title grey sm">{{ $t('entityType') }}:</div>
<select
class="long"
@@ -164,7 +164,7 @@ limitations under the License. -->
</option>
</select>
</div>
- <div class="flex-h mb-5" v-show="!isIndependentSelector && !isBrowser">
+ <div class="flex-h mb-5" v-show="hasIndependentSelector">
<div class="title grey sm">{{ $t('independentSelector') }}:</div>
<select
class="long"
@@ -319,6 +319,10 @@ limitations under the License. -->
@Mutation('EDIT_COMP_CONFIG') private EDIT_COMP_CONFIG: any;
@Mutation('rocketTopo/EDIT_TOPO_INSTANCE_CONFIG') private EDIT_TOPO_INSTANCE_CONFIG: any;
@Mutation('rocketTopo/EDIT_TOPO_ENDPOINT_CONFIG') private EDIT_TOPO_ENDPOINT_CONFIG: any;
+ @Mutation('rocketTopo/EDIT_TOPO_SERVICE_CONFIG') private EDIT_TOPO_SERVICE_CONFIG: any;
+ @Mutation('rocketTopo/EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG') private EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG: any;
+ @Mutation('rocketTopo/EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG') private EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG: any;
+ @Mutation('rocketTopo/EDIT_ENDPOINT_DEPENDENCY_CONFIG') private EDIT_ENDPOINT_DEPENDENCY_CONFIG: any;
@Action('GET_ITEM_SERVICES') private GET_ITEM_SERVICES: any;
@Action('GET_ITEM_ENDPOINTS') private GET_ITEM_ENDPOINTS: any;
@Action('GET_ITEM_INSTANCES') private GET_ITEM_INSTANCES: any;
@@ -340,35 +344,37 @@ limitations under the License. -->
private isDatabase = false;
private isBrowser = false;
private isLabel = false;
- private isIndependentSelector = false;
+ private hasIndependentSelector = false;
private isChartSlow = false;
- private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as string[];
private isChartType = false;
private ChartTable = 'ChartTable';
+ private noEntity = false;
- private created() {
+ private beforeMount() {
this.itemConfig = this.item;
this.initConfig();
- if (!this.itemConfig.independentSelector || this.pageTypes.includes(this.type)) {
- return;
+ if (this.itemConfig.independentSelector) {
+ this.setItemServices();
}
- this.setItemServices();
}
private initConfig() {
- this.isDatabase = this.pageTypes.includes(this.type)
- ? false
- : this.rocketComps.tree[this.rocketComps.group].type === DASHBOARDTYPE.DATABASE
- ? true
- : false;
- this.isBrowser = this.rocketComps.tree[this.rocketComps.group].type === DASHBOARDTYPE.BROWSER;
+ const dashboardComps = this.rocketComps.tree[this.rocketComps.group] || {};
+ const topoPageTypes = [
+ TopologyType.TOPOLOGY_SERVICE,
+ TopologyType.TOPOLOGY_SERVICE_DEPENDENCY,
+ TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY,
+ ] as string[];
+
+ this.noEntity = topoPageTypes.includes(this.type);
+ this.isDatabase = dashboardComps.type === DASHBOARDTYPE.DATABASE;
+ this.isBrowser = dashboardComps.type === DASHBOARDTYPE.BROWSER;
if (this.isBrowser) {
this.EntityType = BrowserEntityType;
}
this.queryMetricTypesList = QueryMetricTypes[this.item.metricType] || [];
- this.isLabel = this.itemConfig.metricType === MetricsType.LABELED_VALUE ? true : false;
- this.isIndependentSelector =
- this.rocketComps.tree[this.rocketComps.group].type === 'metric' || this.pageTypes.includes(this.type);
+ this.isLabel = this.itemConfig.metricType === MetricsType.LABELED_VALUE;
+ this.hasIndependentSelector = dashboardComps.type === 'metric';
this.chartTypeOptions =
this.itemConfig.queryMetricType === 'readMetricsValue' ? ReadValueChartType : ChartTypeOptions;
this.isChartSlow = ['sortMetrics', 'readSampledRecords'].includes(this.itemConfig.queryMetricType);
@@ -377,6 +383,28 @@ limitations under the License. -->
}
}
+ private editComponentConfig(params: { index: number; values: unknown }) {
+ const data = {
+ ...params,
+ uuid: this.itemConfig.uuid,
+ };
+ if (this.type === TopologyType.TOPOLOGY_SERVICE) {
+ this.EDIT_TOPO_SERVICE_CONFIG(data);
+ } else if (this.type === TopologyType.TOPOLOGY_ENDPOINT) {
+ this.EDIT_TOPO_ENDPOINT_CONFIG(data);
+ } else if (this.type === TopologyType.TOPOLOGY_INSTANCE) {
+ this.EDIT_TOPO_INSTANCE_CONFIG(data);
+ } else if (this.type === TopologyType.TOPOLOGY_SERVICE_DEPENDENCY) {
+ this.EDIT_TOPO_SERVICE_DEPENDENCY_CONFIG(data);
+ } else if (this.type === TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY) {
+ this.EDIT_TOPO_INSTANCE_DEPENDENCY_CONFIG(data);
+ } else if (this.type === TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY) {
+ this.EDIT_ENDPOINT_DEPENDENCY_CONFIG(data);
+ } else {
+ this.EDIT_COMP_CONFIG(params);
+ }
+ }
+
private setItemConfig(params: { type: string; value: string }) {
this.itemConfig[params.type] = params.value;
const types = ['endpointsKey', 'instancesKey', 'currentService'];
@@ -411,18 +439,18 @@ limitations under the License. -->
}
if (params.type === 'independentSelector' || params.type === 'parentService') {
this.itemConfig[params.type] = params.value === 'true' ? true : false;
- if (this.type === this.pageTypes[0]) {
- this.EDIT_TOPO_ENDPOINT_CONFIG({
+ if (this.type === TopologyType.TOPOLOGY_ENDPOINT) {
+ this.editComponentConfig({
index: this.index,
values: { [params.type]: this.itemConfig[params.type] },
});
- } else if (this.type === this.pageTypes[1]) {
- this.EDIT_TOPO_INSTANCE_CONFIG({
+ } else if (this.type === TopologyType.TOPOLOGY_INSTANCE) {
+ this.editComponentConfig({
index: this.index,
values: { [params.type]: this.itemConfig[params.type] },
});
} else {
- this.EDIT_COMP_CONFIG({ index: this.index, values: { [params.type]: this.itemConfig[params.type] } });
+ this.editComponentConfig({ index: this.index, values: { [params.type]: this.itemConfig[params.type] } });
}
return;
}
@@ -430,18 +458,18 @@ limitations under the License. -->
this.updateAggregation(params);
return;
}
- if (this.type === this.pageTypes[0]) {
- this.EDIT_TOPO_ENDPOINT_CONFIG({
+ if (this.type === TopologyType.TOPOLOGY_ENDPOINT) {
+ this.editComponentConfig({
index: this.index,
values: { [params.type]: params.value },
});
- } else if (this.type === this.pageTypes[1]) {
- this.EDIT_TOPO_INSTANCE_CONFIG({
+ } else if (this.type === TopologyType.TOPOLOGY_INSTANCE) {
+ this.editComponentConfig({
index: this.index,
values: { [params.type]: params.value },
});
} else {
- this.EDIT_COMP_CONFIG({ index: this.index, values: { [params.type]: params.value } });
+ this.editComponentConfig({ index: this.index, values: { [params.type]: params.value } });
}
}
@@ -462,6 +490,7 @@ limitations under the License. -->
this.$emit('updateStatus', 'metricType', typeOfMetrics);
this.queryMetricTypesList = QueryMetricTypes[typeOfMetrics] || [];
this.itemConfig.queryMetricType = this.queryMetricTypesList[0] && this.queryMetricTypesList[0].value;
+ this.chartTypeOptions = ReadValueChartType;
this.hasChartType();
this.isLabel = typeOfMetrics === MetricsType.LABELED_VALUE ? true : false;
const values = {
@@ -470,18 +499,18 @@ limitations under the License. -->
chartType: MetricChartType[this.itemConfig.queryMetricType],
metricName: params.value,
};
- if (this.type === this.pageTypes[0]) {
- this.EDIT_TOPO_ENDPOINT_CONFIG({
+ if (this.type === TopologyType.TOPOLOGY_ENDPOINT) {
+ this.editComponentConfig({
index: this.index,
values,
});
- } else if (this.type === this.pageTypes[1]) {
- this.EDIT_TOPO_INSTANCE_CONFIG({
+ } else if (this.type === TopologyType.TOPOLOGY_INSTANCE) {
+ this.editComponentConfig({
index: this.index,
values,
});
} else {
- this.EDIT_COMP_CONFIG({
+ this.editComponentConfig({
index: this.index,
values,
});
@@ -502,7 +531,7 @@ limitations under the License. -->
...this.itemConfig,
...values,
};
- this.EDIT_COMP_CONFIG({
+ this.editComponentConfig({
index: this.index,
values,
});
@@ -513,22 +542,10 @@ limitations under the License. -->
chartType: MetricChartType[params.value],
[params.type]: params.value,
};
- if (this.type === this.pageTypes[0]) {
- this.EDIT_TOPO_ENDPOINT_CONFIG({
- index: this.index,
- values,
- });
- } else if (this.type === this.pageTypes[1]) {
- this.EDIT_TOPO_INSTANCE_CONFIG({
- index: this.index,
- values,
- });
- } else {
- this.EDIT_COMP_CONFIG({
- index: this.index,
- values,
- });
- }
+ this.editComponentConfig({
+ index: this.index,
+ values,
+ });
this.itemConfig = {
...this.itemConfig,
...values,
@@ -576,7 +593,10 @@ limitations under the License. -->
} else {
this.itemConfig.currentEndpoint = '';
}
- this.EDIT_COMP_CONFIG({ index: this.index, values: { currentEndpoint: this.itemConfig.currentEndpoint } });
+ this.editComponentConfig({
+ index: this.index,
+ values: { currentEndpoint: this.itemConfig.currentEndpoint },
+ });
}
});
} else if (this.itemConfig.entityType === EntityType[3].key) {
@@ -592,7 +612,10 @@ limitations under the License. -->
} else {
this.itemConfig.currentInstance = '';
}
- this.EDIT_COMP_CONFIG({ index: this.index, values: { currentInstance: this.itemConfig.currentInstance } });
+ this.editComponentConfig({
+ index: this.index,
+ values: { currentInstance: this.itemConfig.currentInstance },
+ });
}
});
}
diff --git a/src/views/components/dashboard/charts/chart-heap.vue b/src/views/components/dashboard/charts/chart-heap.vue
index a38025f..0258471 100644
--- a/src/views/components/dashboard/charts/chart-heap.vue
+++ b/src/views/components/dashboard/charts/chart-heap.vue
@@ -28,6 +28,7 @@ limitations under the License. -->
@Prop() private title!: string;
@Prop() private stateDashboard!: any;
@Prop() private intervalTime!: any;
+ @Prop() private theme!: string;
get responseConfig() {
return {
color: ['#3f96e3', '#3fbde3'],
@@ -44,6 +45,9 @@ limitations under the License. -->
top: 0,
left: 0,
itemWidth: 12,
+ textStyle: {
+ color: this.theme === 'dark' ? '#fff' : '#333',
+ },
},
grid: {
top: 10,
diff --git a/src/views/components/dashboard/charts/chart-line.vue b/src/views/components/dashboard/charts/chart-line.vue
index 1ba0622..d9f5739 100644
--- a/src/views/components/dashboard/charts/chart-line.vue
+++ b/src/views/components/dashboard/charts/chart-line.vue
@@ -25,6 +25,7 @@ limitations under the License. -->
@Prop() private data!: any;
@Prop() private type!: string;
@Prop() private intervalTime!: any;
+ @Prop() private theme!: string;
@Prop() private itemEvents!: Event[];
public resize() {
const chart: any = this.$refs.chart;
@@ -137,6 +138,9 @@ limitations under the License. -->
top: 0,
left: 0,
itemWidth: 12,
+ textStyle: {
+ color: this.theme === 'dark' ? '#fff' : '#333',
+ },
},
grid: {
top: keys.length === 1 ? 15 : 55,
diff --git a/src/views/components/dashboard/charts/chart-num.vue b/src/views/components/dashboard/charts/chart-num.vue
index 135a623..80e4893 100644
--- a/src/views/components/dashboard/charts/chart-num.vue
+++ b/src/views/components/dashboard/charts/chart-num.vue
@@ -16,7 +16,7 @@ limitations under the License. -->
<template>
<div class="rk-chart-num">
<div v-for="(item, index) in data" :key="index" class="rk-num-detail">
- <span class="b">{{
+ <span class="b" :style="`color: ${colors}`">{{
typeof item.avgNum === 'string' ? item.avgNum : isNaN(item.avgNum) ? null : item.avgNum.toFixed(2)
}}</span>
</div>
@@ -29,6 +29,11 @@ limitations under the License. -->
export default class ChartNum extends Vue {
@Prop() private data!: any;
@Prop() private item!: any;
+ @Prop() private theme!: string;
+
+ private get colors() {
+ return this.theme === 'dark' ? '#eee' : '#333';
+ }
}
</script>
<style lang="scss" scoped>
diff --git a/src/views/components/dashboard/charts/chart-table.vue b/src/views/components/dashboard/charts/chart-table.vue
index c03e24c..0b041ef 100644
--- a/src/views/components/dashboard/charts/chart-table.vue
+++ b/src/views/components/dashboard/charts/chart-table.vue
@@ -16,7 +16,7 @@ limitations under the License. -->
<template>
<div class="rk-chart-table">
<div ref="chartTable">
- <div class="row header flex-h" :style="`width: ${nameWidth + initWidth}px`">
+ <div class="row header flex-h" :style="`width: ${nameWidth + initWidth}px`" :class="{ dark: theme === 'dark' }">
<div class="name" :style="`width: ${nameWidth}px`">
{{ item.tableHeaderCol1 || $t('name') }}
<i class="r cp" ref="draggerName"><rk-icon icon="settings_ethernet"/></i>
@@ -25,7 +25,13 @@ limitations under the License. -->
{{ item.tableHeaderCol2 || $t('value') }}
</div>
</div>
- <div class="row flex-h" v-for="key in dataKeys" :key="key" :style="`width: ${nameWidth + initWidth}px`">
+ <div
+ class="row flex-h"
+ :class="{ dark: theme === 'dark' }"
+ v-for="key in dataKeys"
+ :key="key"
+ :style="`width: ${nameWidth + initWidth}px`"
+ >
<div :style="`width: ${nameWidth}px`">{{ key }}</div>
<div class="value-col" v-if="showTableValues">{{ data[key][dataLength(data[key])] }}</div>
</div>
@@ -41,6 +47,7 @@ limitations under the License. -->
export default class ChartTable extends Vue {
@Prop() private data!: any;
@Prop() private item: any;
+ @Prop() private theme!: string;
private nameWidth: number = 0;
private initWidth: number = 0;
@@ -106,6 +113,9 @@ limitations under the License. -->
border-bottom: 1px solid #ccc;
}
}
+ .dark {
+ color: #eee;
+ }
.row:first-child {
div {
border-top: 1px solid #ccc;
diff --git a/src/views/components/dashboard/charts/constant.ts b/src/views/components/dashboard/charts/constant.ts
index 7525211..5aa812f 100644
--- a/src/views/components/dashboard/charts/constant.ts
+++ b/src/views/components/dashboard/charts/constant.ts
@@ -20,6 +20,9 @@ export const EntityType = [
{ key: 'All', label: 'All' },
{ key: 'Endpoint', label: 'Service Endpoint' },
{ key: 'ServiceInstance', label: 'Service Instance' },
+ { key: 'ServiceRelation', label: 'Service Relation' },
+ { key: 'ServiceInstanceRelation', label: 'Service Instance Relation' },
+ { key: 'EndpointRelation', label: 'Endpoint Relation' },
];
export const BrowserEntityType = [
{ key: 'Service', label: 'Service' },
diff --git a/src/views/components/dashboard/dashboard-item.vue b/src/views/components/dashboard/dashboard-item.vue
index 137ad4b..27a9177 100644
--- a/src/views/components/dashboard/dashboard-item.vue
+++ b/src/views/components/dashboard/dashboard-item.vue
@@ -13,18 +13,24 @@ 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. -->
<template>
- <div class="rk-dashboard-item" :class="`g-sm-${width}`" :style="`height:${height}px;`">
+ <div class="rk-dashboard-item" :class="`g-sm-${width}`" :style="`height:${height}px;`" v-if="itemConfig.entityType">
<div class="rk-dashboard-item-title ell">
- <span v-show="rocketGlobal.edit" @click="deleteItem(index)">
+ <span v-show="rocketGlobal.edit || stateTopo.editDependencyMetrics" @click="deleteItem(index, itemConfig.uuid)">
<rk-icon class="r edit red" icon="file-deletion" />
</span>
<span>{{ title }}</span>
<span v-show="unit"> ( {{ unit }} ) </span>
<span v-show="status === 'UNKNOWN'" class="item-status">( {{ $t('unknownMetrics') }} )</span>
- <span v-show="!rocketGlobal.edit && !pageTypes.includes(type)" @click="editComponentConfig">
+ <span
+ v-show="!rocketGlobal.edit && !stateTopo.editDependencyMetrics && !noEditTypes.includes(type)"
+ @click="editComponentConfig"
+ >
<rk-icon class="r edit" icon="keyboard_control" v-tooltip:bottom="{ content: $t('editConfig') }" />
</span>
- <span v-show="!rocketGlobal.edit && itemConfig.chartType === 'ChartTable'" @click="copyTable">
+ <span
+ v-show="!rocketGlobal.edit && stateTopo.editDependencyMetrics && itemConfig.chartType === 'ChartTable'"
+ @click="copyTable"
+ >
<rk-icon class="r cp" icon="review-list" />
</span>
<rk-icon v-if="tips" class="r edit" icon="info_outline" v-tooltip:bottom="{ content: tips }" />
@@ -32,7 +38,7 @@ limitations under the License. -->
<div class="rk-dashboard-item-body" ref="chartBody">
<div style="height:100%;width:100%">
<component
- :is="rocketGlobal.edit ? 'ChartEdit' : itemConfig.chartType"
+ :is="rocketGlobal.edit || stateTopo.editDependencyMetrics ? 'ChartEdit' : itemConfig.chartType"
ref="chart"
:item="itemConfig"
:index="index"
@@ -40,6 +46,7 @@ limitations under the License. -->
:data="chartSource"
:type="type"
:itemEvents="itemEvents"
+ :theme="theme"
@updateStatus="(type, value) => setStatus(type, value)"
></component>
</div>
@@ -47,9 +54,10 @@ limitations under the License. -->
<rk-sidebox
width="70%"
:fixed="true"
+ :right="theme === 'dark'"
:title="$t('editConfig')"
:show.sync="dialogConfigVisible"
- @closeSideboxCallback="chartRender()"
+ @closeSideboxCallback="chartRender"
>
<div class="config-box">
<component
@@ -59,6 +67,8 @@ limitations under the License. -->
:index="index"
:intervalTime="intervalTime"
:data="chartSource"
+ :theme="theme"
+ :type="type"
></component>
</div>
</rk-sidebox>
@@ -71,7 +81,7 @@ limitations under the License. -->
import dayjs from 'dayjs';
import { QueryTypes, UpdateDashboardEvents } from './constant';
- import { TopologyType, ObjectsType } from '../../../constants/constant';
+ import { TopologyType } from '@/constants/constant';
import { CalculationType } from './charts/constant';
import { State as globalState } from '@/store/modules/global';
import { State as optionState } from '@/store/modules/global/selectors';
@@ -86,20 +96,26 @@ limitations under the License. -->
export default class DashboardItem extends Vue {
@State('rocketbot') private rocketGlobal!: globalState;
@State('rocketData') private rocketData!: rocketData;
- @Mutation('EDIT_COMP_CONFIG') private EDIT_COMP_CONFIG: any;
+ @State('rocketTopo') private stateTopo!: any;
@Mutation('DELETE_COMP') private DELETE_COMP: any;
@Mutation('rocketTopo/DELETE_TOPO_ENDPOINT') private DELETE_TOPO_ENDPOINT: any;
@Mutation('rocketTopo/DELETE_TOPO_INSTANCE') private DELETE_TOPO_INSTANCE: any;
+ @Mutation('rocketTopo/DELETE_TOPO_SERVICE') private DELETE_TOPO_SERVICE: any;
+ @Mutation('rocketTopo/DELETE_TOPO_SERVICE_DEPENDENCY') private DELETE_TOPO_SERVICE_DEPENDENCY: any;
+ @Mutation('rocketTopo/DELETE_TOPO_INSTANCE_DEPENDENCY') private DELETE_TOPO_INSTANCE_DEPENDENCY: any;
+ @Mutation('rocketTopo/DELETE_TOPO_ENDPOINT_DEPENDENCY') private DELETE_TOPO_ENDPOINT_DEPENDENCY: any;
@Action('GET_QUERY') private GET_QUERY: any;
@Getter('intervalTime') private intervalTime: any;
@Getter('durationTime') private durationTime: any;
@Prop() private item!: any;
@Prop() private index!: number;
@Prop() private type!: string;
- @Prop() private updateObjects!: string;
+ @Prop() private updateObjects!: boolean;
@Prop() private rocketOption!: optionState;
+ @Prop() private templateTypes!: string[];
+ @Prop() private templateMode!: string; // server client
- private pageTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as string[];
+ private noEditTypes = [TopologyType.TOPOLOGY_ENDPOINT, TopologyType.TOPOLOGY_INSTANCE] as string[];
private dialogConfigVisible = false;
private status = 'UNKNOWN';
private title = 'Title';
@@ -110,6 +126,13 @@ limitations under the License. -->
private chartSource: any = {};
private itemConfig: any = {};
private itemEvents: Event[] = [];
+ private theme: 'light' | 'dark' = 'light';
+ private darkThemeTypes = [
+ TopologyType.TOPOLOGY_SERVICE,
+ TopologyType.TOPOLOGY_SERVICE_DEPENDENCY,
+ TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY,
+ TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY,
+ ] as string[];
private created() {
this.status = this.item.metricType;
@@ -120,18 +143,13 @@ limitations under the License. -->
this.unit = this.item.unit;
this.itemConfig = this.item;
this.itemEvents = this.eventsFilter();
- const types = [
- ObjectsType.UPDATE_INSTANCES,
- ObjectsType.UPDATE_ENDPOINTS,
- ObjectsType.UPDATE_DASHBOARD,
- ] as string[];
+ this.theme = this.darkThemeTypes.includes(this.type) ? 'dark' : 'light';
- if (!types.includes(this.updateObjects)) {
- return;
+ if (this.updateObjects) {
+ setTimeout(() => {
+ this.chartRender();
+ }, 1000);
}
- setTimeout(() => {
- this.chartRender();
- }, 1000);
}
private chartRender() {
@@ -144,17 +162,22 @@ limitations under the License. -->
index: this.index,
type: this.type,
rocketOption: this.rocketOption,
+ templateType: this.templateTypes,
+ templateMode: this.templateMode,
}).then((params: Array<{ metricName: string; [key: string]: any; config: any }>) => {
if (!params) {
+ this.itemConfig = {};
return;
}
if (!params.length) {
+ this.itemConfig = {};
return;
}
this.itemConfig = params[0].config;
- const { queryMetricType, chartType } = this.itemConfig;
+
+ const { queryMetricType } = this.itemConfig;
let data = params;
- if (queryMetricType === QueryTypes.ReadMetricsValue /*&& chartType === 'ChartSlow'*/) {
+ if (queryMetricType === QueryTypes.ReadMetricsValue) {
const arr: any = [
{
config: this.itemConfig,
@@ -337,11 +360,25 @@ limitations under the License. -->
copy(JSON.stringify(data));
}
- private deleteItem(index: number) {
- if (this.type === this.pageTypes[0]) {
- this.DELETE_TOPO_ENDPOINT(index);
- } else if (this.type === this.pageTypes[1]) {
- this.DELETE_TOPO_INSTANCE(index);
+ private deleteItem(index: number, uuid: number) {
+ if (this.type === TopologyType.TOPOLOGY_ENDPOINT) {
+ this.DELETE_TOPO_ENDPOINT(uuid);
+ this.$emit('setTemplates');
+ } else if (this.type === TopologyType.TOPOLOGY_INSTANCE) {
+ this.DELETE_TOPO_INSTANCE(uuid);
+ this.$emit('setTemplates');
+ } else if (this.type === TopologyType.TOPOLOGY_SERVICE) {
+ this.DELETE_TOPO_SERVICE(uuid);
+ this.$emit('setTemplates');
+ } else if (this.type === TopologyType.TOPOLOGY_SERVICE_DEPENDENCY) {
+ this.DELETE_TOPO_SERVICE_DEPENDENCY(uuid);
+ this.$emit('setTemplates');
+ } else if (this.type === TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY) {
+ this.DELETE_TOPO_INSTANCE_DEPENDENCY(uuid);
+ this.$emit('setTemplates');
+ } else if (this.type === TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY) {
+ this.DELETE_TOPO_ENDPOINT_DEPENDENCY(uuid);
+ this.$emit('setTemplates');
} else {
this.DELETE_COMP(index);
}
@@ -384,15 +421,32 @@ limitations under the License. -->
}
// watch selectors and events
- @Watch('rocketOption.updateDashboard')
+ @Watch('rocketOption.updateDashboard.key')
private watchCurrentSelectors() {
+ if (!this.rocketOption.updateDashboard) {
+ return;
+ }
+ const key = this.rocketOption.updateDashboard.key || '';
+
this.itemEvents = this.eventsFilter();
+ if (key.includes(UpdateDashboardEvents)) {
+ return;
+ }
+ if (key.includes(TopologyType.TOPOLOGY_SERVICE) && this.itemConfig.entityType !== EntityType[0].key) {
+ return;
+ }
+ if (key.includes(TopologyType.TOPOLOGY_SERVICE_DEPENDENCY) && this.itemConfig.entityType !== EntityType[4].key) {
+ return;
+ }
if (
- this.rocketOption.updateDashboard.key &&
- this.rocketOption.updateDashboard.key.includes(UpdateDashboardEvents)
+ key.includes(TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY) &&
+ this.itemConfig.entityType !== EntityType[5].key
) {
return;
}
+ if (key.includes(TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY) && this.itemConfig.entityType !== EntityType[6].key) {
+ return;
+ }
setTimeout(() => {
this.chartRender();
}, 1000);
@@ -403,6 +457,20 @@ limitations under the License. -->
}
@Watch('rocketGlobal.edit')
private watchRerender() {
+ if (this.stateTopo.editDependencyMetrics) {
+ return;
+ }
+ this.chartRender();
+ }
+ @Watch('stateTopo.editDependencyMetrics')
+ private watchDependency() {
+ if (
+ (this.type !== TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY &&
+ this.type !== TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY) ||
+ this.stateTopo.editDependencyMetrics
+ ) {
+ return;
+ }
this.chartRender();
}
}
@@ -417,6 +485,9 @@ limitations under the License. -->
.edit {
cursor: pointer;
}
+ .rk-sidebox-title {
+ color: #333;
+ }
}
.dashboard-item-shadow {
background-color: #448dfe15;
diff --git a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
index 8d1f5ad..2a03715 100644
--- a/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
+++ b/src/views/components/dashboard/tool-bar/tool-bar-btns.vue
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. -->
<template>
- <div class="flex-h btn-box">
+ <div class="flex-h">
<div class="rk-dashboard-bar-btn" @click="handleSetEdit">
<rk-icon
class="lg"
diff --git a/src/views/components/dashboard/tool-bar/tool-bar.vue b/src/views/components/dashboard/tool-bar/tool-bar.vue
index 6708612..30a78a4 100644
--- a/src/views/components/dashboard/tool-bar/tool-bar.vue
+++ b/src/views/components/dashboard/tool-bar/tool-bar.vue
@@ -15,6 +15,7 @@ limitations under the License. -->
<template>
<div class="rk-dashboard-bar flex-h">
<ToolBarBtns
+ class="tool-btns"
:rocketGlobal="rocketGlobal"
:rocketComps="rocketComps"
:compType="compType"
@@ -228,6 +229,9 @@ limitations under the License. -->
</script>
<style lang="scss" scoped>
+ .tool-btns {
+ height: 58px;
+ }
.rk-dashboard-bar {
flex-shrink: 0;
color: #efefef;
diff --git a/src/views/components/topology/chart-line.vue b/src/views/components/topology/chart-line.vue
deleted file mode 100644
index 12111d6..0000000
--- a/src/views/components/topology/chart-line.vue
+++ /dev/null
@@ -1,98 +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. -->
-
-<template>
- <div>
- <div class="grey sm mb-5">{{ title }}</div>
- <RkEcharts height="120px" :option="option" />
- </div>
-</template>
-<script lang="ts">
- import { Vue, Component, Prop } from 'vue-property-decorator';
-
- @Component
- export default class ChartLine extends Vue {
- @Prop() private data!: any;
- @Prop() private title!: string;
- @Prop() private intervalTime!: any;
-
- get option() {
- const keys = Object.keys(this.data || {}).filter((i: any) => Array.isArray(this.data[i]) && this.data[i].length);
- const temp = keys.map((i: string, index: number) => {
- return {
- data: this.data[i].map((item: any, itemIndex: number) => [this.intervalTime[itemIndex], item]),
- name: i,
- type: 'line',
- symbol: 'none',
- barMaxWidth: 10,
- lineStyle: {
- width: 1.5,
- type: 'solid',
- },
- };
- });
- const color: string[] = [
- '#30A4EB',
- '#45BFC0',
- '#FFCC55',
- '#FF6A84',
- '#a0a7e6',
- '#6be6c1',
- '#626c91',
- '#96dee8',
- '#3f96e3',
- ];
-
- return {
- color,
- tooltip: {
- trigger: 'axis',
- backgroundColor: 'rgb(50,50,50)',
- textStyle: {
- fontSize: 13,
- },
- },
- legend: {
- show: false,
- },
- grid: {
- top: 5,
- left: 0,
- right: 18,
- bottom: 5,
- containLabel: true,
- },
- xAxis: {
- type: 'category',
- axisTick: {
- lineStyle: { color: '#c1c5ca41' },
- alignWithLabel: true,
- },
- splitLine: { show: false },
- axisLine: { lineStyle: { color: 'rgba(0,0,0,0)' } },
- axisLabel: { color: '#9da5b2', fontSize: '11' },
- },
- yAxis: {
- type: 'value',
- axisLine: { show: false },
- axisTick: { show: false },
- splitLine: { lineStyle: { color: '#c1c5ca41', type: 'dashed' } },
- axisLabel: { color: '#9da5b2', fontSize: '11' },
- },
- series: temp,
- };
- }
- }
-</script>
diff --git a/src/views/components/topology/dependency-sankey.vue b/src/views/components/topology/chart/dependency-sankey.vue
similarity index 87%
rename from src/views/components/topology/dependency-sankey.vue
rename to src/views/components/topology/chart/dependency-sankey.vue
index bb9ea6c..a0d6ad0 100644
--- a/src/views/components/topology/dependency-sankey.vue
+++ b/src/views/components/topology/chart/dependency-sankey.vue
@@ -20,15 +20,10 @@ limitations under the License. -->
<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
- import { State, Action, Getter, Mutation } from 'vuex-class';
- import * as echarts from 'echarts/lib/echarts';
@Component
export default class DependencySankey extends Vue {
@Prop() private data: any;
- @Getter('durationTime') private durationTime: any;
- @Action('rocketTopo/GET_INSTANCE_DEPENDENCY_METRICS')
- private GET_INSTANCE_DEPENDENCY_METRICS: any;
get optionConfigs() {
return {
diff --git a/src/views/components/topology/radial.vue b/src/views/components/topology/chart/radial.vue
similarity index 100%
rename from src/views/components/topology/radial.vue
rename to src/views/components/topology/chart/radial.vue
diff --git a/src/views/components/topology/chart/topo.vue b/src/views/components/topology/chart/topo.vue
index 802b7cc..96f3ec3 100644
--- a/src/views/components/topology/chart/topo.vue
+++ b/src/views/components/topology/chart/topo.vue
@@ -115,7 +115,7 @@ limitations under the License. -->
this.$emit('setDialog', 'endpoint_dependency');
},
handleNodeClick(d) {
- this.$emit('setCurrent', { key: d.id, label: d.name });
+ this.$emit('setCurrent', { key: d.id, label: d.name, isReal: d.isReal });
const {x, y, vx, vy, fx, fy, index, ...rest} = d;
this.$store.dispatch('rocketTopo/CLEAR_TOPO_INFO');
this.$store.commit('rocketTopo/SET_NODE', rest);
@@ -125,14 +125,10 @@ limitations under the License. -->
event.stopPropagation();
this.$store.commit('rocketTopo/SET_NODE', {});
this.$store.commit('rocketTopo/SET_LINK', d);
+ this.$store.commit('SET_SERVICE_DEPENDENCY', d);
this.$store.dispatch('rocketTopo/CLEAR_TOPO_INFO');
this.$store.commit('rocketTopo/SET_MODE', d.detectPoints);
- this.$store.dispatch(this.$store.state.rocketTopo.mode ? 'rocketTopo/GET_TOPO_SERVICE_INFO' :
- 'rocketTopo/GET_TOPO_CLIENT_INFO', { ...d, duration: this.$store.getters.durationTime });
- this.$store.commit('rocketTopo/SET_CALLBACK', () => {
- this.$store.dispatch(this.$store.state.rocketTopo.mode ? 'rocketTopo/GET_TOPO_SERVICE_INFO' :
- 'rocketTopo/GET_TOPO_CLIENT_INFO', { ...d, duration: this.$store.getters.durationTime });
- });
+ this.$store.commit('rocketTopo/SET_SELECTED_CALL', { ...d, duration: this.$store.getters.durationTime });
},
resize() {
this.svg.attr('height', this.$el.clientHeight);
diff --git a/src/views/components/topology/dependency/topo-endpoint-dependency.vue b/src/views/components/topology/dependency/topo-endpoint-dependency.vue
new file mode 100644
index 0000000..932bd02
--- /dev/null
+++ b/src/views/components/topology/dependency/topo-endpoint-dependency.vue
@@ -0,0 +1,314 @@
+<!-- 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. -->
+<template>
+ <div class="rk-endpoint-dependency" :style="`height: ${height}px`">
+ <div class="endpoint-dependency-chart">
+ <DependencySankey
+ v-if="stateTopo.endpointDependency.nodes.length"
+ :data="stateTopo.endpointDependency"
+ @showMetrics="showEndpointMetrics"
+ />
+ <div v-else class="endpoint-dependency-empty">
+ No Endpoint Dependency
+ </div>
+ </div>
+ <div class="mb-5 header" v-if="stateTopo.selectedEndpointCall">
+ <span class="topo-tool-btn" @click="handleSetEdit">
+ <rk-icon
+ class="lg rk-icon"
+ :style="`color:${stateTopo.editDependencyMetrics ? '#ffc107' : ''}`"
+ :icon="stateTopo.editDependencyMetrics ? 'lock-open' : 'lock'"
+ v-tooltip:bottom="{ content: stateTopo.editDependencyMetrics ? 'view' : 'edit' }"
+ />
+ </span>
+ <span class="topo-tool-btn" v-tooltip:bottom="{ content: 'import' }">
+ <input
+ id="endpoint-tool-bar-file"
+ type="file"
+ name="file"
+ title=""
+ accept=".json"
+ @change="importEndpointDependencyMetricsTemplate"
+ />
+ <label for="endpoint-tool-bar-file">
+ <rk-icon class="lg import" icon="folder_open" />
+ </label>
+ </span>
+ <span class="topo-tool-btn" @click="exportTopoEndpointDependencyMetrics">
+ <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" />
+ </span>
+ <span class="ml-5 pb-5 flex-h">
+ <div class="type grey">{{ $t('templateType') }}</div>
+ <RkSelect
+ class="content grey"
+ :mode="'multiple'"
+ :current="currentType"
+ :data="templateNameList"
+ :theme="'dark'"
+ @onChoose="(item) => changeTemplatesType(item)"
+ />
+ </span>
+ </div>
+ <div v-if="stateTopo.selectedEndpointCall" class="endpoint-dependency-metrics scroll_bar_style">
+ <DashboardItem
+ v-for="(i, index) in topoEndpointDependencyMetrics || []"
+ :key="i.uuid"
+ :rocketGlobal="rocketGlobal"
+ :item="i"
+ :index="index"
+ :type="type"
+ :updateObjects="true"
+ :rocketOption="stateDashboardOption"
+ :templateTypes="templateType"
+ @setTemplates="setMetricsTemplate"
+ />
+ <div v-show="stateTopo.editDependencyMetrics" class="rk-add-metric-item g-sm-3" @click="addMetrics">
+ + Add An Item
+ </div>
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { Vue, Component, Watch } from 'vue-property-decorator';
+ import { State, Getter, Mutation } from 'vuex-class';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import { State as topoState } from '@/store/modules/topology';
+ import DependencySankey from '../chart/dependency-sankey.vue';
+ import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { readFile } from '@/utils/readFile';
+ import { saveFile } from '@/utils/saveFile';
+ import { Duration } from '@/types/global';
+ import { EndpointDependencyConidition, Call } from '@/types/topo';
+ import { DEFAULT, TopologyType } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
+
+ @Component({
+ components: {
+ DependencySankey,
+ DashboardItem,
+ },
+ })
+ export default class TopoEndpointDependency extends Vue {
+ @Getter('durationTime') private durationTime!: Duration;
+ @Getter('intervalTime') private intervalTime: any;
+ @State('rocketTopo') private stateTopo!: topoState;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @Mutation('rocketTopo/SET_SELECTED_ENDPOINT_CALL') private SET_SELECTED_ENDPOINT_CALL: any;
+ @Mutation('SET_ENDPOINT_DEPENDENCY') private SET_ENDPOINT_DEPENDENCY: any;
+ @Mutation('rocketTopo/EDIT_DEPENDENCY_METRICS') private EDIT_DEPENDENCY_METRICS: any;
+ @Mutation('rocketTopo/IMPORT_TREE_ENDPOINT_DEPENDENCY') private IMPORT_TREE_ENDPOINT_DEPENDENCY: any;
+ @Mutation('rocketTopo/ADD_TOPO_ENDPOINT_DEPENDENCY_COMP') private ADD_TOPO_ENDPOINT_DEPENDENCY_COMP: any;
+ @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any;
+ @Mutation('rocketTopo/SET_TOPO_ENDPOINT_DEPENDENCY') private SET_TOPO_ENDPOINT_DEPENDENCY: any;
+
+ private templateType: string[] = [];
+ private topoEndpointDependencyMetrics: any = [];
+ private type = TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY;
+ private height = 500;
+ private templateNameList: Option[] = [];
+ private currentType: Option[] = [];
+
+ private beforeMount() {
+ this.height = document.body.clientHeight - 133;
+ }
+
+ private addMetrics() {
+ this.ADD_TOPO_ENDPOINT_DEPENDENCY_COMP();
+ this.setMetricsTemplate();
+ }
+
+ private changeTemplatesType(item: Option) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+
+ if (this.currentType.find((d) => d.key === item.key)) {
+ this.deleteTemplateTypes(item);
+ return;
+ }
+ this.currentType.push(item);
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]: this.currentType,
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ this.setTemplateTypes();
+ this.setMetricsTemplate();
+ }
+
+ private deleteTemplateTypes(item: any) {
+ let topoTemplateTypes = null;
+ const types = this.stateTopo.topoTemplatesType;
+ const index = this.currentType.findIndex((d) => item.key === d.key);
+
+ this.currentType.splice(index, 1);
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]: this.currentType,
+ };
+ this.setTemplateTypes();
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ this.setMetricsTemplate();
+ }
+
+ private showEndpointMetrics(data: EndpointDependencyConidition & Call) {
+ this.SET_SELECTED_ENDPOINT_CALL(data);
+ this.SET_ENDPOINT_DEPENDENCY(data);
+ this.setTemplateTypes();
+ this.templateNameList = Object.keys(this.stateTopo.topoEndpointDependency).map((item: string) => {
+ return { label: item, key: item };
+ });
+ this.setMetricsTemplate();
+ }
+
+ private setMetricsTemplate() {
+ this.topoEndpointDependencyMetrics = [];
+ let templates: any = {};
+
+ for (const type of Object.keys(this.stateTopo.topoEndpointDependency)) {
+ const metricsTemp = this.stateTopo.topoEndpointDependency[type].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: metricsTemp,
+ };
+ }
+ this.SET_TOPO_ENDPOINT_DEPENDENCY(templates);
+ for (const type of this.templateType) {
+ this.topoEndpointDependencyMetrics = [
+ ...this.topoEndpointDependencyMetrics,
+ ...this.stateTopo.topoEndpointDependency[type],
+ ];
+ }
+ }
+
+ private setTemplateTypes() {
+ if (!this.stateTopo.selectedEndpointCall) {
+ return;
+ }
+ const nodeType = this.stateTopo.selectedEndpointCall.type || DEFAULT;
+ const templates = this.stateTopo.topoTemplatesType || {};
+ let templateTypes = [];
+
+ if (templates[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY]) {
+ templateTypes = templates[TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY].map((item: Option) => item.key);
+ } else {
+ templateTypes = this.stateTopo.topoEndpointDependency[nodeType] ? [nodeType] : [DEFAULT];
+ }
+
+ this.templateType = templateTypes;
+ this.currentType = templateTypes.map((d: Option) => {
+ return { key: d, label: d };
+ });
+ }
+
+ private handleSetEdit() {
+ this.EDIT_DEPENDENCY_METRICS(!this.stateTopo.editDependencyMetrics);
+ }
+
+ private async importEndpointDependencyMetricsTemplate(event: Event) {
+ try {
+ const data: any = await readFile(event);
+ if (!Array.isArray(data)) {
+ throw new Error();
+ }
+ this.IMPORT_TREE_ENDPOINT_DEPENDENCY(data[0]);
+ this.setMetricsTemplate();
+ const el: any = document.getElementById('endpoint-tool-bar-file');
+ el!.value = '';
+ } catch (e) {
+ this.$modal.show('dialog', { text: 'ERROR' });
+ }
+ }
+
+ private exportTopoEndpointDependencyMetrics() {
+ const name = 'topo_endpoint_dependency_metrics.json';
+ let group: any = {};
+
+ for (const type of Object.keys(this.stateTopo.topoEndpointDependency)) {
+ const metricsTemp = this.stateTopo.topoEndpointDependency[type].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ group = {
+ ...group,
+ [type]: metricsTemp,
+ };
+ }
+
+ saveFile([group], name);
+ }
+
+ @Watch('stateTopo.endpointDependency.nodes')
+ private updateMetrics() {
+ this.topoEndpointDependencyMetrics = [];
+ }
+
+ private beforeDestroy() {
+ this.stateTopo.endpointDependency = {
+ calls: [],
+ nodes: [],
+ };
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ @import url('../styles/common.scss');
+ .rk-endpoint-dependency {
+ background: #333840;
+ display: flex;
+ flex-direction: column;
+ .endpoint-dependency-chart {
+ height: 75%;
+ min-height: 500px;
+ }
+ .endpoint-dependency-empty {
+ color: #fff;
+ text-align: center;
+ height: 500px;
+ line-height: 500px;
+ }
+ }
+ .endpoint-dependency-metrics {
+ background: #333840;
+ height: 25%;
+ overflow: auto;
+ min-height: 210px;
+ }
+ .header {
+ z-index: 1;
+ }
+ #endpoint-tool-bar-file {
+ display: none;
+ }
+ .topo-tool-btn {
+ cursor: pointer;
+ color: #fff;
+ margin-right: 5px;
+ }
+ .rk-add-metric-item {
+ color: #eee;
+ }
+ .type {
+ width: 100px;
+ }
+ .content {
+ width: 400px;
+ }
+</style>
diff --git a/src/views/components/topology/dependency/topo-instance-dependency.vue b/src/views/components/topology/dependency/topo-instance-dependency.vue
new file mode 100644
index 0000000..c5ddcfc
--- /dev/null
+++ b/src/views/components/topology/dependency/topo-instance-dependency.vue
@@ -0,0 +1,342 @@
+<!-- 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. -->
+<template>
+ <div class="rk-topo-instance-dependency">
+ <div class="rk-dependency-chart">
+ <DependencySankey :data="stateTopo.instanceDependency" @showMetrics="showDependencyMetrics" />
+ <div v-show="!stateTopo.instanceDependency.nodes.length">
+ No Instance Dependency
+ </div>
+ </div>
+ <div class="rk-instance-metric-box">
+ <div v-if="stateTopo.selectedInstanceCall" class="rk-instance-metric-content">
+ <div class="mb-5 clear header">
+ <span class="b dib mr-20 vm">{{ $t('detectPoint') }}</span>
+ <span
+ v-if="stateTopo.selectedInstanceCall.detectPoints.includes('CLIENT')"
+ class="link-topo-aside-box-btn tc r sm cp b"
+ :class="{ active: stateTopo.instanceDependencyMode === 'client' }"
+ @click="setMode('client')"
+ >
+ {{ $t('client') }}
+ </span>
+ <span
+ v-if="stateTopo.selectedInstanceCall.detectPoints.includes('SERVER')"
+ class="link-topo-aside-box-btn tc r sm cp b"
+ :class="{ active: stateTopo.instanceDependencyMode === 'server' }"
+ @click="setMode('server')"
+ >
+ {{ $t('server') }}
+ </span>
+ <span class="topo-tool-btn" @click="handleSetEdit">
+ <rk-icon
+ class="lg rk-icon"
+ :style="`color:${stateTopo.editDependencyMetrics ? '#ffc107' : ''}`"
+ :icon="stateTopo.editDependencyMetrics ? 'lock-open' : 'lock'"
+ v-tooltip:bottom="{ content: stateTopo.editDependencyMetrics ? 'view' : 'edit' }"
+ />
+ </span>
+ <span class="topo-tool-btn" v-tooltip:bottom="{ content: 'import' }">
+ <input
+ id="instance-tool-bar-file"
+ type="file"
+ name="file"
+ title=""
+ accept=".json"
+ @change="importInstanceDependencyMetricsTemplate"
+ />
+ <label for="instance-tool-bar-file">
+ <rk-icon class="lg import" icon="folder_open" />
+ </label>
+ </span>
+ <span class="topo-tool-btn" @click="exportTopoInstanceDependencyMetrics">
+ <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" />
+ </span>
+ </div>
+ <div class="pl-10 pb-5 flex-h">
+ <div class="type grey">{{ $t('templateType') }}</div>
+ <RkSelect
+ class="content grey"
+ :mode="'multiple'"
+ :current="currentType"
+ :data="templateNameList"
+ :theme="'dark'"
+ @onChoose="(item) => changeTemplatesType(item)"
+ />
+ </div>
+ <div
+ v-if="stateTopo.selectedInstanceCall"
+ class="rk-instance-dependency-metrics scroll_bar_style"
+ :style="`height: ${height}px`"
+ >
+ <DashboardItem
+ v-for="(i, index) in serviceInstanceDependencyComps || []"
+ :key="i.uuid"
+ :rocketGlobal="rocketGlobal"
+ :item="i"
+ :index="index"
+ :type="type"
+ :updateObjects="true"
+ :rocketOption="stateDashboardOption"
+ :templateTypes="templateType"
+ :templateMode="stateTopo.instanceDependencyMode"
+ @setTemplates="setMetircsTemplates"
+ />
+ <div
+ v-show="stateTopo.editDependencyMetrics"
+ class="rk-add-metric-item g-sm-3"
+ @click="addInstanceDependencyMetric"
+ >
+ + Add An Item
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { Vue, Component } from 'vue-property-decorator';
+ import { State, Getter, Mutation } from 'vuex-class';
+ import { State as topoState } from '@/store/modules/topology';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import DependencySankey from '../chart/dependency-sankey.vue';
+ import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { readFile } from '@/utils/readFile';
+ import { saveFile } from '@/utils/saveFile';
+ import { DEFAULT, TopologyType } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
+
+ @Component({
+ components: {
+ DependencySankey,
+ DashboardItem,
+ },
+ })
+ export default class TopoInstanceDependency extends Vue {
+ @Getter('intervalTime') private intervalTime: any;
+ @Getter('durationTime') private durationTime: any;
+ @State('rocketTopo') private stateTopo!: topoState;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @Mutation('rocketTopo/SET_INSTANCE_DEPENDENCY_MODE_STATUS') private SET_INSTANCE_DEPENDENCY_MODE_STATUS: any;
+ @Mutation('rocketTopo/SET_SELECTED_INSTANCE_CALL') private SET_SELECTED_INSTANCE_CALL: any;
+ @Mutation('SET_SERVICE_INSTANCE_DEPENDENCY') private SET_SERVICE_INSTANCE_DEPENDENCY: any;
+ @Mutation('rocketTopo/EDIT_DEPENDENCY_METRICS') private EDIT_DEPENDENCY_METRICS: any;
+ @Mutation('rocketTopo/ADD_TOPO_INSTANCE_DEPENDENCY_COMP') private ADD_TOPO_INSTANCE_DEPENDENCY_COMP: any;
+ @Mutation('rocketTopo/IMPORT_TREE_INSTANCE_DEPENDENCY') private IMPORT_TREE_INSTANCE_DEPENDENCY: any;
+ @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE_INSTANCE_DEPENDENCY') private SET_TOPO_SERVICE_INSTANCE_DEPENDENCY: any;
+
+ private showInfo: boolean = true;
+ private height: number = 500;
+ private serviceInstanceDependencyComps: any = [];
+ private mode: string = 'server';
+ private templateType: string[] = [];
+ private templateMode: string = '';
+ private type = TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY;
+ private currentType: Option[] = [];
+ private templateNameList: Option[] = [];
+
+ private beforeMount() {
+ this.height = document.body.clientHeight - 250;
+ }
+
+ private setMode(mode: any) {
+ this.SET_INSTANCE_DEPENDENCY_MODE_STATUS(mode);
+ const call: any = this.stateTopo.selectedInstanceCall || { sourceObj: {} };
+ this.templateTypes();
+ this.setMetircsTemplates();
+ }
+
+ private addInstanceDependencyMetric() {
+ this.ADD_TOPO_INSTANCE_DEPENDENCY_COMP();
+ this.setMetircsTemplates();
+ }
+ private showDependencyMetrics(data: any) {
+ this.SET_INSTANCE_DEPENDENCY_MODE_STATUS(data.detectPoints[0].toLowerCase());
+ this.SET_SELECTED_INSTANCE_CALL(data);
+ this.SET_SERVICE_INSTANCE_DEPENDENCY(data);
+ this.templateTypes();
+ this.templateNameList = Object.keys(this.stateTopo.topoServicesInstanceDependency).map((item: string) => {
+ return { label: item, key: item };
+ });
+ this.setMetircsTemplates();
+ }
+
+ private changeTemplatesType(item: Option) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+
+ if (this.currentType.find((d) => d.key === item.key)) {
+ this.deleteTemplateTypes(item);
+ return;
+ }
+ this.currentType.push(item);
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY]: this.currentType,
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ this.templateTypes();
+ this.setMetircsTemplates();
+ }
+
+ private deleteTemplateTypes(item: any) {
+ let topoTemplateTypes = null;
+ const types = this.stateTopo.topoTemplatesType;
+ const index = this.currentType.findIndex((d) => item.key === d.key);
+
+ this.currentType.splice(index, 1);
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY]: this.currentType,
+ };
+ this.templateTypes();
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ this.setMetircsTemplates();
+ }
+
+ private setMetircsTemplates() {
+ this.serviceInstanceDependencyComps = [];
+ const mode = this.stateTopo.instanceDependencyMode as any;
+ let templates: any = {};
+
+ for (const type of Object.keys(this.stateTopo.topoServicesInstanceDependency)) {
+ for (const detect of ['server', 'client']) {
+ const m: any = detect;
+ if (this.stateTopo.topoServicesInstanceDependency[type][m]) {
+ const metricsTemp = this.stateTopo.topoServicesInstanceDependency[type][m].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: {
+ ...templates[type],
+ [m]: metricsTemp,
+ },
+ };
+ }
+ }
+ }
+ this.SET_TOPO_SERVICE_INSTANCE_DEPENDENCY(templates);
+ for (const type of this.templateType) {
+ this.serviceInstanceDependencyComps = [
+ ...this.serviceInstanceDependencyComps,
+ ...this.stateTopo.topoServicesInstanceDependency[type][mode],
+ ];
+ }
+ }
+
+ private templateTypes() {
+ const nodeType = this.stateTopo.currentNode.type;
+ const templates = this.stateTopo.topoTemplatesType;
+ let templateTypes = [];
+
+ if (templates[TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY]) {
+ templateTypes = templates[TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY].map((item: Option) => item.key);
+ } else {
+ templateTypes = this.stateTopo.topoServicesInstanceDependency[nodeType] ? [nodeType] : [DEFAULT];
+ }
+
+ this.templateType = templateTypes;
+ this.currentType = templateTypes.map((d: Option) => {
+ return { key: d, label: d };
+ });
+ }
+
+ private handleSetEdit() {
+ this.EDIT_DEPENDENCY_METRICS(!this.stateTopo.editDependencyMetrics);
+ }
+ private async importInstanceDependencyMetricsTemplate(event: Event) {
+ try {
+ const data: any = await readFile(event);
+ if (!Array.isArray(data)) {
+ throw new Error();
+ }
+ this.IMPORT_TREE_INSTANCE_DEPENDENCY(data[0]);
+ this.setMetircsTemplates();
+ const el: any = document.getElementById('instance-tool-bar-file');
+ el!.value = '';
+ } catch (e) {
+ this.$modal.show('dialog', { text: 'ERROR' });
+ }
+ }
+ private exportTopoInstanceDependencyMetrics() {
+ let group: any = {};
+ const name = 'topo_service_instance_dependency_metrics.json';
+ for (const type of Object.keys(this.stateTopo.topoServicesInstanceDependency)) {
+ for (const mode of ['server', 'client']) {
+ const m: any = mode;
+ const metricsTemp = this.stateTopo.topoServicesInstanceDependency[type][m].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ group = {
+ ...group,
+ [type]: {
+ ...group[type],
+ [m]: metricsTemp,
+ },
+ };
+ }
+ }
+
+ saveFile([group], name);
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ @import url('../styles/common.scss');
+ .rk-topo-instance-dependency {
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ background: #2b3037;
+ .content {
+ width: 66%;
+ }
+ }
+ .rk-instance-metric-box {
+ display: flex;
+ flex-direction: column;
+ background: #252a2f;
+ }
+ .rk-instance-dependency-metrics {
+ width: 350px;
+ overflow: auto;
+ }
+ .rk-dependency-chart {
+ height: 100%;
+ width: calc(100% - 340px);
+ }
+ .header {
+ padding: 10px;
+ width: 100%;
+ overflow: hidden;
+ }
+ .rk-add-metric-item {
+ width: 325px;
+ }
+ .topo-tool-btn {
+ cursor: pointer;
+ }
+ #instance-tool-bar-file {
+ display: none;
+ }
+</style>
diff --git a/src/views/components/topology/dependency/topo-service-dependency.vue b/src/views/components/topology/dependency/topo-service-dependency.vue
new file mode 100644
index 0000000..162a63f
--- /dev/null
+++ b/src/views/components/topology/dependency/topo-service-dependency.vue
@@ -0,0 +1,143 @@
+<!-- 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. -->
+<template>
+ <div class="service-metrics scroll_bar_style" :style="`height: ${height}px`">
+ <DashboardItem
+ v-for="(i, index) in serviceDependencyComps || []"
+ :key="i.uuid"
+ :rocketGlobal="rocketGlobal"
+ :item="i"
+ :index="index"
+ :type="pageType"
+ :updateObjects="true"
+ :rocketOption="stateDashboardOption"
+ :templateTypes="templateType"
+ :templateMode="templateMode"
+ @setTemplates="setServiceDependencyTemplates"
+ />
+ <div v-show="rocketGlobal.edit" class="rk-add-metric-item g-sm-3" @click="addServiceDependencyMetric">
+ + Add An Item
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { State, Mutation } from 'vuex-class';
+ import { Component, Vue, Watch, Prop } from 'vue-property-decorator';
+ import { State as topoState } from '@/store/modules/topology';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { TopologyType, DEFAULT } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
+
+ @Component({
+ components: {
+ DashboardItem,
+ },
+ })
+ export default class TopoServiceDependency extends Vue {
+ @Prop() private currentType: any;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @State('rocketTopo') private stateTopo!: topoState;
+ @Mutation('rocketTopo/ADD_TOPO_SERVICE_DEPENDENCY_COMP') private ADD_TOPO_SERVICE_DEPENDENCY_COMP: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE_DEPENDENCY') private SET_TOPO_SERVICE_DEPENDENCY: any;
+
+ private serviceDependencyComps: any[] = [];
+ private height = 800;
+ private templateType: string[] = [DEFAULT];
+ private templateMode: any = 'server';
+ private pageType: string = TopologyType.TOPOLOGY_SERVICE_DEPENDENCY;
+
+ private beforeMount() {
+ this.templateMode = this.stateTopo.mode ? 'server' : 'client';
+ this.height = document.body.clientHeight - 280;
+ this.setServiceDependencyTemplates();
+ }
+
+ private addServiceDependencyMetric() {
+ this.ADD_TOPO_SERVICE_DEPENDENCY_COMP();
+ this.setServiceDependencyTemplates();
+ }
+
+ private templateTypes() {
+ let templateTypes = [];
+ if (!this.stateTopo.selectedServiceCall) {
+ return;
+ }
+ const callType = this.stateTopo.selectedServiceCall.source.type || DEFAULT;
+ const templates = this.stateTopo.topoTemplatesType;
+
+ if (
+ templates[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY] &&
+ templates[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY][callType]
+ ) {
+ templateTypes = templates[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY][callType].map((item: Option) => item.key);
+ } else {
+ templateTypes = this.stateTopo.topoServicesDependency[callType] ? [callType] : [DEFAULT];
+ }
+
+ this.templateType = templateTypes;
+ }
+
+ private setServiceDependencyTemplates() {
+ this.templateTypes();
+ this.templateMode = this.stateTopo.mode ? 'server' : 'client';
+ this.serviceDependencyComps = [];
+ let templates: any = {};
+
+ for (const type of Object.keys(this.stateTopo.topoServicesDependency)) {
+ for (const mode of ['server', 'client']) {
+ const m: any = mode;
+ const metricsTemp = this.stateTopo.topoServicesDependency[type][m].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: {
+ ...templates[type],
+ [m]: metricsTemp,
+ },
+ };
+ }
+ }
+ this.SET_TOPO_SERVICE_DEPENDENCY(templates);
+ for (const tep of this.templateType) {
+ this.serviceDependencyComps = [
+ ...this.serviceDependencyComps,
+ ...this.stateTopo.topoServicesDependency[tep][this.templateMode],
+ ];
+ }
+ }
+
+ @Watch('stateTopo.mode')
+ private updateServiceDependency() {
+ this.templateMode = this.stateTopo.mode ? 'server' : 'client';
+ this.setServiceDependencyTemplates();
+ }
+ @Watch('currentType')
+ private updateServiceMetrics() {
+ this.updateServiceDependency();
+ }
+ }
+</script>
+<style lang="scss" scoped>
+ @import url('../styles/common.scss');
+ .service-metrics {
+ overflow: auto;
+ }
+</style>
diff --git a/src/constants/constant.ts b/src/views/components/topology/styles/common.scss
similarity index 57%
copy from src/constants/constant.ts
copy to src/views/components/topology/styles/common.scss
index f67961e..dbfea22 100644
--- a/src/constants/constant.ts
+++ b/src/views/components/topology/styles/common.scss
@@ -14,30 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-export enum TopologyType {
- TOPOLOGY_ENDPOINT = 'TOPOLOGY_ENDPOINT',
- TOPOLOGY_INSTANCE = 'TOPOLOGY_INSTANCE',
-}
-
-export enum ObjectsType {
- UPDATE_INSTANCES = 'UPDATE_INSTANCES',
- UPDATE_ENDPOINTS = 'UPDATE_ENDPOINTS',
- UPDATE_DASHBOARD = 'UPDATE_DASHBOARD',
-}
-
-export enum TimeType {
- MINUTE_TIME = 'MINUTE',
- HOUR_TIME = 'HOUR',
- DAY_TIME = 'DAY',
-}
-
-export enum PageEventsType {
- DASHBOARD_EVENTS = 'dashboardEvents',
- TOPO_ENDPOINT_EVENTS = 'topoEndpointEvents',
- TOPO_INSTANCE_EVENTS = 'topoInstanceEvents',
-}
-export enum PageTypes {
- DASHBOARD = 'Dashboard',
- LOG = 'Log',
-}
+ .rk-add-metric-item {
+ height: 200px;
+ text-align: center;
+ line-height: 250px;
+ border: 1px dashed rgba(196, 200, 225, 0.5);
+ cursor: pointer;
+ font-size: 16px;
+ width: 340px;
+ margin-left: 5px;
+}
\ No newline at end of file
diff --git a/src/views/components/topology/topo-aside.vue b/src/views/components/topology/topo-aside.vue
index 7de491c..06be8ac 100644
--- a/src/views/components/topology/topo-aside.vue
+++ b/src/views/components/topology/topo-aside.vue
@@ -23,64 +23,21 @@ limitations under the License. -->
>
<use xlink:href="#issues" />
</svg>
- <svg
- v-if="showServerInfo"
- class="link-topo-aside-btn icon cp lg"
- @click="show = !show"
- :style="`position:absolute;left:290px;transform: rotate(${show ? 0 : 180}deg);top:45px;`"
- >
- <use xlink:href="#chevron-left" />
- </svg>
<TopoService />
- <div v-if="show">
- <div class="link-topo-aside-box" style="top:45px" v-if="!stateTopo.selectedServiceCall && showServerInfo">
- <div class="mb-20">
- <span class="b dib mr-20">{{ $t('serviceDetail') }}</span>
- </div>
- <div class="mb-10">
- <span class="label grey">{{ $t('name') }}</span>
- <span class="content">{{ stateTopo.currentNode.name }}</span>
- </div>
- <div class="mb-10">
- <span class="label grey">{{ $t('type') }}</span>
- <span class="content">{{ stateTopo.currentNode.type }}</span>
- </div>
- <div>
- <TopoChart
- v-if="stateTopo.serviceApdexScore.length"
- :data="stateTopo.serviceApdexScore"
- :intervalTime="intervalTime"
- title="Service ApdexScore"
- unit=""
- />
- <TopoChart
- v-if="stateTopo.serviceSLA.length"
- :data="stateTopo.serviceSLA"
- :intervalTime="intervalTime"
- :title="$t('avgSLA')"
- unit=""
- />
- </div>
- </div>
- <TopoDetectPoint />
- </div>
+ <TopoDetectPoint />
</aside>
</template>
<script lang="ts">
import { initState } from '@/store/modules/dashboard/dashboard-data-layout';
import { State as topoState } from '@/store/modules/topology';
- import { Component, Vue, Watch } from 'vue-property-decorator';
+ import { Component, Vue } from 'vue-property-decorator';
import { Action, Getter, Mutation, State } from 'vuex-class';
- import Radial from './radial.vue';
- import TopoChart from './topo-chart.vue';
+ import Radial from './chart/radial.vue';
import TopoService from './topo-services.vue';
import TopoDetectPoint from './topo-detect-point.vue';
- import { DurationTime } from '@/types/global';
- import compareObj from '@/utils/comparison';
@Component({
components: {
- TopoChart,
TopoService,
Radial,
TopoDetectPoint,
@@ -94,38 +51,18 @@ limitations under the License. -->
@Action('rocketTopo/CLEAR_TOPO_INFO') private CLEAR_TOPO_INFO: any;
@Mutation('SET_COMPS_TREE') private SET_COMPS_TREE: any;
@Mutation('rocketTopo/SET_MODE_STATUS') private SET_MODE_STATUS: any;
- private dialogTopoVisible = false;
- private drawerMainBodyHeight = '100%';
private initState = initState;
private radioStatus: boolean = false;
- private show: boolean = true;
private get showServerInfo() {
return this.stateTopo.currentNode.name && this.stateTopo.currentNode.isReal;
}
- private resize() {
- this.drawerMainBodyHeight = `${document.body.clientHeight - 50}px`;
- }
-
private created() {
this.SET_COMPS_TREE(this.initState.tree);
}
- private handleRefresh() {
- this.$store.dispatch(
- this.stateTopo.mode ? 'rocketTopo/GET_TOPO_SERVICE_INFO' : 'rocketTopo/GET_TOPO_CLIENT_INFO',
- { ...this.stateTopo.currentLink, duration: this.durationTime },
- );
- }
-
- private mounted() {
- this.resize();
- window.addEventListener('resize', this.resize);
- }
-
private beforeDestroy() {
- window.removeEventListener('resize', this.resize);
this.CLEAR_TOPO_INFO();
this.CLEAR_TOPO();
}
@@ -145,13 +82,6 @@ limitations under the License. -->
private showRadial() {
this.radioStatus = !this.radioStatus;
}
-
- @Watch('durationTime')
- private watchDurationTime(newValue: DurationTime, oldValue: DurationTime) {
- if (compareObj(newValue, oldValue)) {
- this.handleRefresh();
- }
- }
}
</script>
<style lang="scss" scoped>
@@ -167,6 +97,9 @@ limitations under the License. -->
border-top: 1px solid #d8d8d866;
}
}
+ .title {
+ padding: 10px;
+ }
.link-topo-aside-btn {
display: block;
@@ -185,7 +118,7 @@ limitations under the License. -->
z-index: 101;
color: #ddd;
background-color: #2b3037;
- padding: 15px 20px 10px;
+ // padding: 15px 20px 10px;
.label {
display: inline-block;
@@ -215,7 +148,7 @@ limitations under the License. -->
}
.link-topo-aside-box-min {
- width: 280px;
+ width: 360px;
animation: 0.5s linkTopoAsideBoxMin 1 running;
}
diff --git a/src/views/components/topology/topo-chart.vue b/src/views/components/topology/topo-chart.vue
deleted file mode 100644
index 8e017f8..0000000
--- a/src/views/components/topology/topo-chart.vue
+++ /dev/null
@@ -1,94 +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. -->
-<template>
- <div>
- <div class="grey sm mb-5">{{ title }}</div>
- <h5 class="grey mt-0 mb-0">{{ content.toFixed(2) }} {{ unit }}</h5>
- <RkEcharts height="100px" :option="responseConfig" />
- </div>
-</template>
-
-<script lang="ts">
- import Vue from 'vue';
- import { Component, Prop } from 'vue-property-decorator';
-
- @Component
- export default class TopoChart extends Vue {
- @Prop() private title!: string;
- @Prop() private data!: any;
- @Prop() private unit!: string;
- @Prop() private intervalTime!: number[];
- @Prop() private precent!: boolean;
- get content() {
- if (!this.data.length) {
- return 0;
- }
- const noZero = this.data.filter((i: any) => i);
- const sum = noZero.length
- ? noZero.reduce((preValue: number, curValue: number, index: number, array: number[]) => preValue + curValue) /
- noZero.length
- : 0;
- return this.precent ? sum / 100 : sum;
- }
- get responseConfig() {
- return {
- color: ['#3f96e3ee', '#6be6c1'],
- tooltip: {
- trigger: 'axis',
- backgroundColor: '#333844',
- textStyle: {
- fontSize: 13,
- },
- },
- grid: {
- top: 4,
- left: 0,
- right: 0,
- bottom: 7,
- containLabel: true,
- },
- xAxis: {
- type: 'category',
- axisTick: {
- lineStyle: { color: '#c1c5ca41' },
- alignWithLabel: true,
- },
- splitLine: { show: false },
- axisLine: { lineStyle: { color: 'rgba(0,0,0,0)' } },
- axisLabel: { color: '#9da5b2', fontSize: '11' },
- },
- yAxis: {
- type: 'value',
- axisLine: { show: false },
- axisTick: { show: false },
- splitLine: { lineStyle: { color: '#c1c5ca41', type: 'dashed' } },
- axisLabel: { color: '#9da5b2', fontSize: '11' },
- },
- series: [
- {
- data: this.data.map((i: any, index: number) => [this.intervalTime[index], this.precent ? i / 100 : i]),
- // type: this.precent ? 'bar' : 'line',
- type: 'line',
- symbol: 'none',
- barMaxWidth: 5,
- lineStyle: {
- width: 1,
- },
- },
- ],
- };
- }
- }
-</script>
diff --git a/src/views/components/topology/topo-detect-point.vue b/src/views/components/topology/topo-detect-point.vue
index 3697eb3..7365ff7 100644
--- a/src/views/components/topology/topo-detect-point.vue
+++ b/src/views/components/topology/topo-detect-point.vue
@@ -25,90 +25,80 @@ limitations under the License. -->
>
<use xlink:href="#chevron-left" />
</svg>
- <div class="mb-5 clear">
- <div v-if="stateTopo.selectedServiceCall">
+ <div class="mb-5 clear flex-h">
+ <span class="tool-title" v-if="stateTopo.selectedServiceCall">
<span class="b dib mr-20 vm">{{ $t('detectPoint') }}</span>
<span
v-if="stateTopo.detectPoints.indexOf('CLIENT') !== -1"
:class="{ active: !stateTopo.mode }"
class="link-topo-aside-box-btn tc r sm cp b"
@click="setMode(false)"
- >{{ $t('client') }}</span
>
+ {{ $t('client') }}
+ </span>
<span
v-if="stateTopo.detectPoints.indexOf('SERVER') !== -1"
:class="{ active: stateTopo.mode }"
class="link-topo-aside-box-btn tc r sm cp b"
@click="setMode(true)"
- >{{ $t('server') }}</span
>
+ {{ $t('server') }}
+ </span>
+ </span>
+ <span v-else-if="showServerInfo" class="b dib vm tool-title">{{ $t('serviceDetail') }}</span>
+ <div class="flex-h">
+ <div class="topo-tool-btn" @click="handleSetEdit">
+ <rk-icon
+ class="lg rk-icon"
+ :style="`color:${!rocketGlobal.edit ? '' : '#ffc107'}`"
+ :icon="!rocketGlobal.edit ? 'lock' : 'lock-open'"
+ v-tooltip:bottom="{ content: rocketGlobal.edit ? 'view' : 'edit' }"
+ />
+ </div>
+ <div class="topo-tool-btn" v-tooltip:bottom="{ content: 'import' }">
+ <input
+ id="tool-bar-file"
+ type="file"
+ name="file"
+ title=""
+ accept=".json"
+ @change="importServiceMetricsTemplate"
+ />
+ <label for="tool-bar-file">
+ <rk-icon class="lg import" icon="folder_open" />
+ </label>
+ </div>
+ <div class="topo-tool-btn" @click="exportTopoServiceMetrics">
+ <rk-icon class="lg" icon="save_alt" v-tooltip:bottom="{ content: 'export' }" />
+ </div>
</div>
- <span v-else-if="showServerInfo" class="b dib mr-20 vm">{{ $t('serviceDetail') }}</span>
</div>
<div v-if="showInfo">
- <div v-if="stateTopo.selectedServiceCall">
- <TopoChart
- v-if="stateTopo.getResponseTimeTrend.length"
- :data="stateTopo.getResponseTimeTrend"
- :intervalTime="intervalTime"
- :title="$t('avgResponseTime')"
- unit="ms"
- />
- <TopoChart
- v-if="stateTopo.getThroughputTrend.length"
- :data="stateTopo.getThroughputTrend"
- :intervalTime="intervalTime"
- :title="$t('avgThroughput')"
- unit="cpm"
- />
- <TopoChart
- v-if="stateTopo.getSLATrend.length"
- :data="stateTopo.getSLATrend"
- :intervalTime="intervalTime"
- :precent="true"
- :title="$t('avgSLA')"
- unit=""
- />
- <ChartLine
- v-if="stateTopo.responsePercentile.p50.length"
- :data="stateTopo.responsePercentile"
- :intervalTime="intervalTime"
- :title="$t('percentResponse')"
- />
- </div>
- <div v-else-if="showServerInfo">
- <TopoChart
- v-if="stateTopo.serviceResponseTime.length"
- :data="stateTopo.serviceResponseTime"
- :intervalTime="intervalTime"
- title="Service ResponseTime"
- unit="ms"
- />
- <TopoChart
- v-if="stateTopo.serviceThroughput.length"
- :data="stateTopo.serviceThroughput"
- :intervalTime="intervalTime"
- title="Service Throughput"
- unit="cpm"
- />
- <ChartLine
- v-if="stateTopo.servicePercentile.p50.length"
- :data="stateTopo.servicePercentile"
- :intervalTime="intervalTime"
- :title="$t('percentResponse')"
+ <div class="pl-10 pb-5 flex-h">
+ <div class="type grey">{{ $t('templateType') }}</div>
+ <RkSelect
+ class="content grey"
+ :mode="'multiple'"
+ :current="currentType"
+ :data="templateTypesList"
+ :theme="'dark'"
+ @onChoose="(item) => changeTemplatesType(item)"
/>
</div>
+ <TopoServiceDependency v-if="stateTopo.selectedServiceCall" :currentType="currentType" ref="serviceDependency" />
+ <TopoServiceMetrics v-else-if="showServerInfo" :currentType="currentType" ref="serviceTemplate" />
</div>
<div class="show-dependency" v-if="stateTopo.selectedServiceCall">
<a class="rk-btn lg" @click="openInstanceModal">{{ $t('ShowInstanceDependency') }}</a>
<rk-sidebox
class="instance-dependency"
- width="80%"
+ width="100%"
:fixed="false"
:title="
`${stateTopo.selectedServiceCall.source.name} -> ${stateTopo.selectedServiceCall.target.name} Instance Dependency`
"
:show.sync="dialogTopoVisible"
+ :closeSideboxCallback="clearInstance"
>
<TopoInstanceDependency />
</rk-sidebox>
@@ -119,25 +109,35 @@ limitations under the License. -->
import { State as topoState } from '@/store/modules/topology';
import { Component, Vue, Watch } from 'vue-property-decorator';
import { Action, Getter, Mutation, State } from 'vuex-class';
- import TopoChart from './topo-chart.vue';
- import TopoInstanceDependency from './topo-instance-dependency.vue';
- import ChartLine from './chart-line.vue';
- import { DurationTime } from '@/types/global';
+ import TopoInstanceDependency from './dependency/topo-instance-dependency.vue';
+ import { DurationTime, Option } from '@/types/global';
+ import TopoServiceMetrics from './topo-service-metrics.vue';
+ import ToolBarBtns from '../dashboard/tool-bar/tool-bar-btns.vue';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import { State as dataState } from '@/store/modules/dashboard/dashboard-data';
import compareObj from '@/utils/comparison';
+ import { readFile } from '@/utils/readFile';
+ import { saveFile } from '@/utils/saveFile';
+ import TopoServiceDependency from './dependency/topo-service-dependency.vue';
+ import { DEFAULT, TopologyType } from '@/constants/constant';
@Component({
components: {
+ TopoServiceMetrics,
TopoInstanceDependency,
- TopoChart,
- ChartLine,
+ TopoServiceDependency,
+ ToolBarBtns,
},
})
export default class TopoDetectPoint extends Vue {
+ @State('rocketData') private rocketComps!: dataState;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
@State('rocketTopo') private stateTopo!: topoState;
@Getter('intervalTime') private intervalTime: any;
- @Getter('durationTime') private durationTime: any;
+ @Getter('durationTime') private durationTime!: DurationTime;
@Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT')
private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any;
+ @Action('SET_EDIT') private SET_EDIT: any;
@Mutation('rocketTopo/SET_MODE_STATUS') private SET_MODE_STATUS: any;
@Mutation('rocketTopo/SET_SELECTED_INSTANCE_CALL')
private SET_SELECTED_INSTANCE_CALL: any;
@@ -146,17 +146,80 @@ limitations under the License. -->
@Action('rocketTopo/CLEAR_TOPO_INFO') private CLEAR_TOPO_INFO: any;
@Action('rocketTopo/GET_TOPO_INSTANCE_DEPENDENCY')
private GET_INSTANCE_DEPENDENCY: any;
- @Action('rocketTopo/GET_TOPO_SERVICE_DETAIL') private GET_TOPO_SERVICE_DETAIL: any;
+ @Mutation('rocketTopo/IMPORT_TREE_SERVICE') private IMPORT_TREE_SERVICE: any;
+ @Mutation('rocketTopo/IMPORT_TREE_SERVICE_DEPENDENCY') private IMPORT_TREE_SERVICE_DEPENDENCY: any;
+ @Mutation('UPDATE_DASHBOARD') private UPDATE_DASHBOARD: any;
+ @Mutation('rocketTopo/EDIT_DEPENDENCY_METRICS') private EDIT_DEPENDENCY_METRICS: any;
+ @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any;
private isMini: boolean = true;
private showInfoCount: number = 0;
private showInfo: boolean = false;
private dialogTopoVisible = false;
+ private templateTypesList: Option[] = [];
+ private currentType: Option[] = [{ key: '', label: '' }];
private get showServerInfo() {
return this.stateTopo.currentNode.name && this.stateTopo.currentNode.isReal;
}
+ private changeTemplatesType(item: any) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+
+ if (this.currentType.find((d) => d.key === item.key)) {
+ this.deleteTemplateTypes(item);
+ return;
+ }
+ this.currentType.push(item);
+ if (this.showServerInfo) {
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE]: { [nodeType]: this.currentType },
+ };
+ } else {
+ if (!(this.stateTopo.selectedServiceCall && this.stateTopo.selectedServiceCall.source)) {
+ return;
+ }
+ const callType = this.stateTopo.selectedServiceCall.source.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE_DEPENDENCY]: { [callType]: this.currentType },
+ };
+ }
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ }
+
+ private deleteTemplateTypes(item: any) {
+ let topoTemplateTypes = null;
+ const types = this.stateTopo.topoTemplatesType;
+ const index = this.currentType.findIndex((d) => item.key === d.key);
+
+ this.currentType.splice(index, 1);
+ if (this.showServerInfo) {
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE]: { [nodeType]: this.currentType },
+ };
+ } else {
+ if (!(this.stateTopo.selectedServiceCall && this.stateTopo.selectedServiceCall.source)) {
+ return;
+ }
+ const callType = this.stateTopo.selectedServiceCall.source.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_SERVICE_DEPENDENCY]: { [callType]: this.currentType },
+ };
+ }
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ }
+
private setShowInfo() {
this.showInfo = false;
this.showInfoCount = 1;
@@ -166,14 +229,18 @@ limitations under the License. -->
}, 550);
}
+ private handleSetEdit() {
+ this.SET_EDIT(!this.rocketGlobal.edit);
+ }
+
private setMode(mode: boolean) {
this.SET_MODE_STATUS(mode);
- this.stateTopo.callback();
}
private clearInstance() {
this.dialogTopoVisible = false;
this.SET_SELECTED_INSTANCE_CALL(null);
+ this.EDIT_DEPENDENCY_METRICS(false);
}
private openInstanceModal() {
@@ -189,15 +256,70 @@ limitations under the License. -->
});
}
+ private async importServiceMetricsTemplate(event: Event) {
+ try {
+ const data: any = await readFile(event);
+ if (!Array.isArray(data)) {
+ throw new Error();
+ }
+ if (this.showServerInfo) {
+ this.IMPORT_TREE_SERVICE(data[0]);
+ const service: any = this.$refs.serviceTemplate;
+ service.setServiceTemplates();
+ } else {
+ this.IMPORT_TREE_SERVICE_DEPENDENCY(data[0]);
+ const serviceDependency: any = this.$refs.serviceDependency;
+ serviceDependency.setServiceDependencyTemplates();
+ }
+ const el: any = document.getElementById('tool-bar-file');
+ el!.value = '';
+ } catch (e) {
+ this.$modal.show('dialog', { text: 'ERROR' });
+ }
+ }
+
+ private exportTopoServiceMetrics() {
+ let name = '';
+ let group: any = {};
+
+ if (this.showServerInfo) {
+ name = 'topo_service_metrics.json';
+ for (const type of Object.keys(this.stateTopo.topoServices)) {
+ const metricsTemp = this.stateTopo.topoServices[type].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ group = {
+ ...group,
+ [type]: metricsTemp,
+ };
+ }
+ } else {
+ name = 'topo_service_dependency_metrics.json';
+ for (const type of Object.keys(this.stateTopo.topoServicesDependency)) {
+ for (const mode of ['server', 'client']) {
+ const m: any = mode;
+ const metricsTemp = this.stateTopo.topoServicesDependency[type][m].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ group = {
+ ...group,
+ [type]: {
+ ...group[type],
+ [m]: metricsTemp,
+ },
+ };
+ }
+ }
+ }
+ saveFile([group], name);
+ }
+
@Watch('durationTime')
private watchDurationTime(newValue: DurationTime, oldValue: DurationTime) {
if (compareObj(newValue, oldValue)) {
- const service = this.stateTopo.currentNode;
-
- this.GET_TOPO_SERVICE_DETAIL({
- serviceId: service.id || '',
- duration: this.durationTime,
- });
+ this.UPDATE_DASHBOARD();
}
}
@@ -205,10 +327,27 @@ limitations under the License. -->
private watchDetectPointNodeId(newValue: string) {
if (newValue || this.stateTopo.currentNode.isReal) {
this.showInfo = true;
+ if (!(this.stateTopo.selectedServiceCall && this.stateTopo.selectedServiceCall.source)) {
+ return;
+ }
+ const callType = this.stateTopo.selectedServiceCall.source.type || DEFAULT;
+ const topoTemplatesType: any = this.stateTopo.topoTemplatesType;
+
+ this.templateTypesList = Object.keys(this.stateTopo.topoServicesDependency).map((item: string) => {
+ return { label: item, key: item };
+ });
+ if (topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY]) {
+ this.currentType = topoTemplatesType[TopologyType.TOPOLOGY_SERVICE_DEPENDENCY][callType] || [
+ { label: DEFAULT, key: DEFAULT },
+ ];
+ } else {
+ this.currentType = [{ label: DEFAULT, key: DEFAULT }];
+ }
} else {
this.showInfo = false;
this.showInfoCount = 0;
this.isMini = true;
+ this.SET_EDIT(false);
}
}
@@ -217,22 +356,43 @@ limitations under the License. -->
const service = this.stateTopo.currentNode;
if (this.stateTopo.currentNode.isReal) {
this.MIXHANDLE_CHANGE_GROUP_WITH_CURRENT({ index: 0, current: 1 });
- this.GET_TOPO_SERVICE_DETAIL({
- serviceId: service.id || '',
- duration: this.durationTime,
- });
+ this.UPDATE_DASHBOARD();
}
if (newValue || this.stateTopo.selectedServiceCall) {
this.showInfo = true;
+ const topoTemplatesType: any = this.stateTopo.topoTemplatesType;
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ this.templateTypesList = Object.keys(this.stateTopo.topoServices).map((item: string) => {
+ return { label: item, key: item };
+ });
+ if (topoTemplatesType[TopologyType.TOPOLOGY_SERVICE]) {
+ this.currentType = topoTemplatesType[TopologyType.TOPOLOGY_SERVICE][nodeType] || [
+ { label: DEFAULT, key: DEFAULT },
+ ];
+ } else {
+ this.currentType = [{ label: DEFAULT, key: DEFAULT }];
+ }
} else {
this.showInfo = false;
this.showInfoCount = 0;
this.isMini = true;
+ this.SET_EDIT(false);
}
}
}
</script>
<style lang="scss">
+ .tool-btns {
+ height: 30px;
+ }
+ #tool-bar-file {
+ display: none;
+ }
+ .topo-tool-btn {
+ margin: 0 3px;
+ cursor: pointer;
+ }
.link-topo-aside-box-btn {
color: #626977;
border: 1px solid;
@@ -244,6 +404,16 @@ limitations under the License. -->
color: #448dfe;
}
}
+ .instance-dependency {
+ .rk-sidebox {
+ background: #2b3037;
+ outline: none;
+ z-index: 200;
+ }
+ .rk-sidebox-inner {
+ height: 100%;
+ }
+ }
.show-dependency {
margin-top: 20px;
@@ -258,14 +428,9 @@ limitations under the License. -->
padding-left: 40px;
font-size: 16px;
}
- }
- .instance-dependency {
- .rk-sidebox {
- background: #2b3037;
- outline: none;
- }
- .rk-sidebox-inner {
- height: 100%;
+
+ .rk-sidebox-title {
+ color: #eee;
}
}
@@ -276,17 +441,25 @@ limitations under the License. -->
z-index: 101;
color: #ddd;
background-color: #2b3037;
- padding: 15px 20px 10px;
.label {
display: inline-block;
width: 40%;
}
+ .type {
+ display: inline-block;
+ width: 100px;
+ }
+
+ .tool-title {
+ padding: 10px;
+ }
+
.content {
vertical-align: top;
display: inline-block;
- width: 60%;
+ width: 67%;
}
.circle {
diff --git a/src/views/components/topology/topo-endpoint-dependency.vue b/src/views/components/topology/topo-endpoint-dependency.vue
deleted file mode 100644
index 8cfc6b9..0000000
--- a/src/views/components/topology/topo-endpoint-dependency.vue
+++ /dev/null
@@ -1,126 +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. -->
-<template>
- <div class="rk-endpoint-dependency">
- <div class="endpoint-dependency-chart">
- <DependencySankey
- v-if="stateTopo.endpointDependency.nodes.length"
- :data="stateTopo.endpointDependency"
- @showMetrics="showEndpointMetrics"
- />
- <div v-else class="endpoint-dependency-empty">
- No Endpoint Dependency
- </div>
- </div>
- <div class="endpoint-dependency-metrics">
- <div v-if="respTime.length">
- <TopoChart :data="respTime" :intervalTime="intervalTime" :title="$t('avgResponseTime')" unit="ms" />
- </div>
- <div v-if="cpm.length">
- <TopoChart :data="cpm" :intervalTime="intervalTime" :title="$t('avgThroughput')" unit="cpm" />
- </div>
- <div v-if="sla.length">
- <TopoChart :data="sla" :intervalTime="intervalTime" :precent="true" :title="$t('avgSLA')" unit="" />
- </div>
- <div v-if="percentile.p50">
- <ChartLine :data="percentile" :intervalTime="intervalTime" :title="$t('percentResponse')" />
- </div>
- </div>
- </div>
-</template>
-<script lang="ts">
- import { Vue, Component, Watch } from 'vue-property-decorator';
- import { State, Action, Getter } from 'vuex-class';
- import { State as topoState, EndpointDependencyConidition, Call, Duration } from '@/store/modules/topology';
- import TopoChart from './topo-chart.vue';
- import DependencySankey from './dependency-sankey.vue';
- import ChartLine from './chart-line.vue';
-
- @Component({
- components: {
- ChartLine,
- TopoChart,
- DependencySankey,
- },
- })
- export default class TopoEndpointDependency extends Vue {
- @Getter('durationTime') private durationTime!: Duration;
- @Getter('intervalTime') private intervalTime: any;
- @State('rocketTopo') private stateTopo!: topoState;
- @Action('rocketTopo/GET_ENDPOINT_DEPENDENCY_METRICS') private GET_ENDPOINT_DEPENDENCY_METRICS: any;
-
- private respTime: number[] = [];
- private cpm: number[] = [];
- private sla: number[] = [];
- private percentile: { [key: string]: number[] } = {};
-
- private showEndpointMetrics(data: EndpointDependencyConidition & Call) {
- this.GET_ENDPOINT_DEPENDENCY_METRICS({
- serviceName: data.serviceName,
- endpointName: data.endpointName,
- destServiceName: data.destServiceName,
- destEndpointName: data.destEndpointName,
- duration: this.durationTime,
- }).then(() => {
- this.updateMetrics();
- });
- }
-
- @Watch('stateTopo.endpointDependency.nodes')
- private updateMetrics() {
- this.respTime = this.stateTopo.endpointDependencyMetrics.respTime;
- this.cpm = this.stateTopo.endpointDependencyMetrics.cpm;
- this.sla = this.stateTopo.endpointDependencyMetrics.sla;
- this.percentile = this.stateTopo.endpointDependencyMetrics.percentile;
- }
-
- private beforeDestroy() {
- this.stateTopo.endpointDependency = {
- calls: [],
- nodes: [],
- };
- }
- }
-</script>
-<style lang="scss" scoped>
- .rk-endpoint-dependency {
- background: #333840;
- height: 100%;
- display: flex;
- flex-direction: column;
- overflow: auto;
- .endpoint-dependency-chart {
- height: 80%;
- min-height: 500px;
- }
- .endpoint-dependency-empty {
- color: #fff;
- text-align: center;
- height: 500px;
- line-height: 500px;
- }
- }
- .endpoint-dependency-metrics {
- height: 20%;
- min-height: 100px;
- display: flex;
- flex-direction: row;
- padding-left: 10px;
- > div {
- width: 25%;
- height: 100%;
- }
- }
-</style>
diff --git a/src/views/components/topology/topo-instance-dependency.vue b/src/views/components/topology/topo-instance-dependency.vue
deleted file mode 100644
index 0a8ba60..0000000
--- a/src/views/components/topology/topo-instance-dependency.vue
+++ /dev/null
@@ -1,148 +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. -->
-<template>
- <div class="rk-topo-instance-dependency">
- <div class="rk-dependency-chart">
- <DependencySankey :data="stateTopo.instanceDependency" @showMetrics="showDependencyMetrics" />
- </div>
- <div class="rk-instance-metric-box">
- <div v-if="!stateTopo.instanceDependency.nodes.length">
- No Instance Dependency
- </div>
- <div v-if="stateTopo.selectedInstanceCall" class="rk-instance-dependency-metrics">
- <div class="mb-5 clear">
- <span class="b dib mr-20 vm">{{ $t('detectPoint') }}</span>
- <span
- v-if="stateTopo.selectedInstanceCall.detectPoints.includes('CLIENT')"
- class="link-topo-aside-box-btn tc r sm cp b"
- :class="{ active: stateTopo.queryInstanceMetricsType === 'CLIENT' }"
- @click="setMode('CLIENT')"
- >{{ $t('client') }}</span
- >
- <span
- v-if="stateTopo.selectedInstanceCall.detectPoints.includes('SERVER')"
- class="link-topo-aside-box-btn tc r sm cp b"
- :class="{ active: stateTopo.queryInstanceMetricsType === 'SERVER' }"
- @click="setMode('SERVER')"
- >{{ $t('server') }}</span
- >
- </div>
- <div v-if="stateTopo.selectedInstanceCall">
- <TopoChart
- v-if="stateTopo.instanceDependencyMetrics.getResponseTimeTrend"
- :data="stateTopo.instanceDependencyMetrics.getResponseTimeTrend"
- :intervalTime="intervalTime"
- :title="$t('avgResponseTime')"
- unit="ms"
- />
- <TopoChart
- v-if="stateTopo.instanceDependencyMetrics.getThroughputTrend"
- :data="stateTopo.instanceDependencyMetrics.getThroughputTrend"
- :intervalTime="intervalTime"
- :title="$t('avgThroughput')"
- unit="cpm"
- />
- <TopoChart
- v-if="stateTopo.instanceDependencyMetrics.getSLATrend"
- :data="stateTopo.instanceDependencyMetrics.getSLATrend"
- :intervalTime="intervalTime"
- :precent="true"
- :title="$t('avgSLA')"
- unit="%"
- />
- <ChartLine
- v-if="stateTopo.instanceDependencyMetrics.percentResponse"
- :data="stateTopo.instanceDependencyMetrics.percentResponse"
- :intervalTime="intervalTime"
- :title="$t('percentResponse')"
- />
- </div>
- </div>
- </div>
- </div>
-</template>
-<script lang="ts">
- import { Vue, Component } from 'vue-property-decorator';
- import { State, Action, Getter, Mutation } from 'vuex-class';
- import { State as topoState } from '@/store/modules/topology';
- import Topo from './chart/topo.vue';
- import TopoChart from './topo-chart.vue';
- import DependencySankey from './dependency-sankey.vue';
- import ChartLine from './chart-line.vue';
-
- @Component({
- components: {
- Topo,
- ChartLine,
- TopoChart,
- DependencySankey,
- },
- })
- export default class TopoInstanceDependency extends Vue {
- @Getter('durationTime') private durationTime: any;
- @State('rocketTopo') private stateTopo!: topoState;
- @Getter('intervalTime') private intervalTime: any;
- @Mutation('rocketTopo/SET_INSTANCE_DEPEDENCE_TYPE')
- private SET_MODE_STATUS: any;
- @Action('rocketTopo/GET_INSTANCE_DEPENDENCY_METRICS')
- private GET_INSTANCE_DEPENDENCY_METRICS: any;
-
- private showInfo: boolean = true;
-
- private setMode(mode: string) {
- this.GET_INSTANCE_DEPENDENCY_METRICS({
- ...this.stateTopo.selectedInstanceCall,
- durationTime: this.durationTime,
- mode,
- });
- }
- private showDependencyMetrics(data: any) {
- this.GET_INSTANCE_DEPENDENCY_METRICS({
- ...data,
- durationTime: this.durationTime,
- mode: data.detectPoints[0],
- });
- }
- }
-</script>
-<style lang="scss" scoped>
- .rk-topo-instance-dependency {
- height: 100%;
- display: flex;
- flex-direction: row;
- background: #2b3037;
- & > :first-child {
- line-height: 400px;
- text-align: center;
- width: 100%;
- }
- .rk-instance-metric-box {
- height: 100%;
- display: flex;
- align-items: center;
- }
- .rk-instance-dependency-metrics {
- width: 320px;
- height: 650px;
- margin-top: 10px;
- background: #252a2f;
- padding: 20px;
- }
- .rk-dependency-chart {
- width: 850px;
- height: 100%;
- }
- }
-</style>
diff --git a/src/views/components/topology/topo-service-metrics.vue b/src/views/components/topology/topo-service-metrics.vue
new file mode 100644
index 0000000..292cb51
--- /dev/null
+++ b/src/views/components/topology/topo-service-metrics.vue
@@ -0,0 +1,129 @@
+<!-- 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. -->
+<template>
+ <div class="service-metrics scroll_bar_style" :style="`height: ${height}px`">
+ <DashboardItem
+ v-for="(i, index) in serviceComps || []"
+ :rocketGlobal="rocketGlobal"
+ :item="i"
+ :index="index"
+ :key="i.uuid"
+ :type="type"
+ :updateObjects="true"
+ :rocketOption="stateDashboardOption"
+ :templateTypes="setTemplateTypes()"
+ @setTemplates="setServiceTemplates"
+ />
+ <div v-show="rocketGlobal.edit" class="rk-add-metric-item g-sm-3" @click="addComp">
+ + Add An Item
+ </div>
+ </div>
+</template>
+<script lang="ts">
+ import { State as topoState } from '@/store/modules/topology';
+ import { Component, Vue, Prop, Watch } from 'vue-property-decorator';
+ import { State, Mutation } from 'vuex-class';
+ import { State as optionState } from '@/store/modules/global/selectors';
+ import { State as rocketbotGlobal } from '@/store/modules/global';
+ import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { DEFAULT, TopologyType } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
+
+ @Component({
+ components: {
+ DashboardItem,
+ },
+ })
+ export default class TopoServiceMetrics extends Vue {
+ @Prop() private currentType!: Option;
+ @State('rocketOption') private stateDashboardOption!: optionState;
+ @State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @State('rocketTopo') private stateTopo!: topoState;
+ @Mutation('rocketTopo/ADD_TOPO_SERVICE_COMP') private ADD_TOPO_SERVICE_COMP: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE') private SET_TOPO_SERVICE: any;
+
+ private serviceComps: unknown[] = [];
+ private height: number = 800;
+ private default = DEFAULT;
+ private type: string = '';
+
+ private beforeMount() {
+ this.type = TopologyType.TOPOLOGY_SERVICE;
+ this.height = document.body.clientHeight - 230;
+ this.setServiceTemplates();
+ }
+
+ private addComp() {
+ this.ADD_TOPO_SERVICE_COMP();
+ this.setServiceTemplates();
+ }
+
+ private setServiceTemplates() {
+ const templateTypes = this.setTemplateTypes();
+ this.serviceComps = [];
+ let templates: any = {};
+ for (const type of Object.keys(this.stateTopo.topoServices)) {
+ const metricsTemp = this.stateTopo.topoServices[type].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: metricsTemp,
+ };
+ }
+ this.SET_TOPO_SERVICE(templates);
+ for (const type of templateTypes) {
+ this.serviceComps = [...this.serviceComps, ...this.stateTopo.topoServices[type]];
+ }
+ }
+
+ private setTemplateTypes() {
+ let templateTypes = [];
+ const nodeType = this.stateTopo.currentNode.type;
+ const templates = this.stateTopo.topoTemplatesType;
+
+ if (templates[TopologyType.TOPOLOGY_SERVICE] && templates[TopologyType.TOPOLOGY_SERVICE][nodeType]) {
+ templateTypes = templates[TopologyType.TOPOLOGY_SERVICE][nodeType].map((item: Option) => item.key);
+ } else {
+ templateTypes = this.stateTopo.topoServices[nodeType] ? [nodeType] : [DEFAULT];
+ }
+
+ return templateTypes;
+ }
+
+ @Watch('currentType')
+ private updateServiceMetrics() {
+ this.setServiceTemplates();
+ }
+ }
+</script>
+<style lang="scss">
+ .service-metrics {
+ overflow: auto;
+ }
+ .rk-add-metric-item {
+ height: 200px;
+ text-align: center;
+ line-height: 250px;
+ border: 1px dashed rgba(196, 200, 225, 0.5);
+ cursor: pointer;
+ display: inline-block;
+ font-size: 16px;
+ width: 340px;
+ margin-left: 5px;
+ }
+</style>
diff --git a/src/views/containers/dashboard.vue b/src/views/containers/dashboard.vue
index dd0545e..52ed14e 100644
--- a/src/views/containers/dashboard.vue
+++ b/src/views/containers/dashboard.vue
@@ -32,7 +32,7 @@ limitations under the License. -->
:index="index"
:rocketGlobal="rocketGlobal"
:item="i"
- :updateObjects="ObjectsType.UPDATE_DASHBOARD"
+ :updateObjects="true"
:rocketOption="stateDashboardOption"
>
</DashboardItem>
@@ -50,7 +50,6 @@ limitations under the License. -->
import ToolGroup from '@/views/components/dashboard/tool-group.vue';
import ToolNav from '@/views/components/dashboard/tool-nav.vue';
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
- import { ObjectsType } from '../../constants/constant';
import { State as globalState } from '@/store/modules/global';
import { State as optionState } from '@/store/modules/global/selectors';
import { State as dataState } from '@/store/modules/dashboard/dashboard-data';
@@ -84,8 +83,6 @@ limitations under the License. -->
@Mutation('SET_EDIT') private SET_EDIT: any;
@Mutation('SET_TEMPLATES') private SET_TEMPLATES: any;
- private ObjectsType = ObjectsType;
-
private isRouterAlive: boolean = true;
public reload(): void {
this.isRouterAlive = false;
@@ -150,4 +147,19 @@ limitations under the License. -->
display: inline-block;
font-size: 16px;
}
+ .dashboard-container {
+ overflow: auto;
+ padding: 20px 15px;
+ height: 100%;
+ flex-grow: 1;
+ }
+ .rk-add-dashboard-item {
+ height: 342px;
+ text-align: center;
+ line-height: 250px;
+ border: 1px dashed rgba(196, 200, 225, 0.5);
+ cursor: pointer;
+ display: inline-block;
+ font-size: 16px;
+ }
</style>
diff --git a/src/views/containers/topology/endpoint-dependency/index.vue b/src/views/containers/topology/endpoint-dependency/index.vue
index 6bcf0ee..c064fad 100644
--- a/src/views/containers/topology/endpoint-dependency/index.vue
+++ b/src/views/containers/topology/endpoint-dependency/index.vue
@@ -41,7 +41,7 @@ limitations under the License. -->
import { Action, Getter, State, Mutation } from 'vuex-class';
import ToolBarSelect from '@/views/components/dashboard/tool-bar/tool-bar-select.vue';
import ToolBarEndpointSelect from '@/views/components/dashboard/tool-bar/tool-bar-endpoint-select.vue';
- import TopoEndpointDependency from '@/views/components/topology/topo-endpoint-dependency.vue';
+ import TopoEndpointDependency from '@/views/components/topology/dependency/topo-endpoint-dependency.vue';
@Component({
components: {
@@ -56,7 +56,6 @@ limitations under the License. -->
@Getter('durationTime') private durationTime: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
@Mutation('SET_EDIT') private SET_EDIT: any;
- @Mutation('rocketTopo/SET_ENDPOINT_DEPENDENCY_METRICS') private SET_ENDPOINT_DEPENDENCY_METRICS: any;
@Mutation('rocketTopo/SET_ENDPOINT_DEPTH') private SET_ENDPOINT_DEPTH: any;
@Action('GET_SERVICE_ENDPOINTS') private GET_SERVICE_ENDPOINTS: any;
@Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any;
@@ -78,7 +77,6 @@ limitations under the License. -->
private selectEndpoint(i: any) {
this.SELECT_ENDPOINT({ endpoint: i, duration: this.durationTime });
this.GET_ALL_ENDPOINT_DEPENDENCY({ endpointIds: [i.key], duration: this.durationTime });
- this.SET_ENDPOINT_DEPENDENCY_METRICS({ respTime: [], sla: [], cpm: [], percentile: {} });
}
private selectDepth(i: { key: number; label: string }) {
@@ -87,8 +85,6 @@ limitations under the License. -->
endpointIds: [this.stateDashboardOption.currentEndpoint.key],
duration: this.durationTime,
});
-
- this.SET_ENDPOINT_DEPENDENCY_METRICS({ respTime: [], sla: [], cpm: [], percentile: {} });
}
private beforeDestroy() {
diff --git a/src/views/containers/topology/endpoint/endpoints-survey.vue b/src/views/containers/topology/endpoint/endpoints-survey.vue
index 2f95aad..e18d669 100644
--- a/src/views/containers/topology/endpoint/endpoints-survey.vue
+++ b/src/views/containers/topology/endpoint/endpoints-survey.vue
@@ -16,16 +16,18 @@ limitations under the License. -->
<template>
<div class="dashboard-container clear">
<DashboardItem
- v-for="(i, index) in endpointComps || []"
- :key="index + i.title + i.width"
+ v-for="(i, index) in topoEndpoints || []"
+ :key="i.uuid"
:rocketGlobal="rocketGlobal"
:item="i"
:index="index"
- :type="'TOPOLOGY_ENDPOINT'"
+ :type="type"
:updateObjects="updateObjects"
:rocketOption="stateDashboardOption"
+ :templateTypes="templateTypes"
+ @setTemplates="setTemplates"
/>
- <div v-show="rocketGlobal.edit" class="rk-add-dashboard-item g-sm-3" @click="ADD_TOPO_ENDPOINT_COMP">
+ <div v-show="rocketGlobal.edit" class="rk-add-dashboard-item g-sm-3" @click="addMetrics()">
+ Add An Item
</div>
</div>
@@ -33,10 +35,14 @@ limitations under the License. -->
<script lang="ts">
import Vue from 'vue';
- import { Component, Prop } from 'vue-property-decorator';
+ import { Component, Prop, Watch } from 'vue-property-decorator';
import { State, Mutation } from 'vuex-class';
+ import { State as topoState } from '@/store/modules/topology';
import { State as optionState } from '@/store/modules/global/selectors';
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { TopologyType, DEFAULT } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
@Component({
components: {
@@ -44,10 +50,82 @@ limitations under the License. -->
},
})
export default class InstancesSurvey extends Vue {
+ @State('rocketTopo') private stateTopo!: topoState;
@State('rocketbot') private rocketGlobal: any;
@State('rocketOption') private stateDashboardOption!: optionState;
@Mutation('rocketTopo/ADD_TOPO_ENDPOINT_COMP') private ADD_TOPO_ENDPOINT_COMP: any;
- @Prop() private endpointComps: any;
- @Prop() private updateObjects!: string;
+ @Mutation('rocketTopo/SET_TOPO_ENDPOINT') private SET_TOPO_ENDPOINT: any;
+ @Prop() private currentType!: Option[];
+
+ private type = TopologyType.TOPOLOGY_ENDPOINT;
+ private topoEndpoints: unknown[] = [];
+ private templateTypes: string[] = [];
+ private updateObjects: boolean = false;
+
+ private beforeMount() {
+ this.setEndpointTemplates();
+ }
+
+ private async addMetrics() {
+ await this.ADD_TOPO_ENDPOINT_COMP();
+ this.setEndpointTemplates();
+ }
+
+ private setTemplates() {
+ this.updateObjects = true;
+ this.setEndpointTemplates();
+ }
+
+ private setEndpointTemplates() {
+ this.setTemplateTypes();
+ this.topoEndpoints = [];
+ let templates: any = {};
+ for (const type of Object.keys(this.stateTopo.topoEndpoints)) {
+ const metricsTemp = this.stateTopo.topoEndpoints[type].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: metricsTemp,
+ };
+ }
+ this.SET_TOPO_ENDPOINT(templates);
+ for (const type of this.templateTypes) {
+ this.topoEndpoints = [...this.topoEndpoints, ...this.stateTopo.topoEndpoints[type]];
+ }
+ }
+
+ private setTemplateTypes() {
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+ const templates = this.stateTopo.topoTemplatesType;
+ if (templates[TopologyType.TOPOLOGY_ENDPOINT] && templates[TopologyType.TOPOLOGY_ENDPOINT][nodeType]) {
+ this.templateTypes = templates[TopologyType.TOPOLOGY_ENDPOINT][nodeType].map((item: Option) => item.key);
+ } else {
+ this.templateTypes = this.stateTopo.topoEndpoints[nodeType] ? [nodeType] : [DEFAULT];
+ }
+ }
+
+ @Watch('currentType')
+ private updateMetrics() {
+ this.setTemplates();
+ }
}
</script>
+<style lang="scss" scoped>
+ .rk-add-dashboard-item {
+ height: 342px;
+ text-align: center;
+ line-height: 250px;
+ border: 1px dashed rgba(196, 200, 225, 0.5);
+ cursor: pointer;
+ display: inline-block;
+ font-size: 16px;
+ }
+ .dashboard-container {
+ overflow: auto;
+ padding: 20px 15px;
+ height: 100%;
+ flex-grow: 1;
+ }
+</style>
diff --git a/src/views/containers/topology/endpoint/index.vue b/src/views/containers/topology/endpoint/index.vue
index 4cc39bf..0a578dc 100644
--- a/src/views/containers/topology/endpoint/index.vue
+++ b/src/views/containers/topology/endpoint/index.vue
@@ -55,6 +55,17 @@ limitations under the License. -->
:data="stateDashboardOption.endpoints"
icon="code"
/>
+ <div class="pl-10 pb-5 flex-h">
+ <div class="type grey">{{ $t('templateType') }}</div>
+ <RkSelect
+ class="content grey"
+ :mode="'multiple'"
+ :current="currentType"
+ :data="templateTypesList"
+ :theme="'dark'"
+ @onChoose="(item) => changeTemplatesType(item)"
+ />
+ </div>
</div>
<DashboardEvent
:rocketComps="rocketComps"
@@ -64,7 +75,7 @@ limitations under the License. -->
/>
</div>
</div>
- <endpoints-survey :endpointComps="endpointComps" :updateObjects="updateObjects" />
+ <endpoints-survey :currentType="currentType" ref="survey" />
</div>
</template>
@@ -77,14 +88,14 @@ limitations under the License. -->
import ToolBarEndpointSelect from '@/views/components/dashboard/tool-bar/tool-bar-endpoint-select.vue';
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
- import { ObjectsType } from '../../../../constants/constant';
import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue';
import { State as optionState } from '@/store/modules/global/selectors';
import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
import { State as rocketbotGlobal } from '@/store/modules/global';
import { DurationTime, Option } from '@/types/global';
import { EntityType } from '@/views/components/dashboard/charts/constant';
- import { PageEventsType } from '@/constants/constant';
+ import { PageEventsType, TopologyType, DEFAULT } from '@/constants/constant';
+ import { State as topoState } from '@/store/modules/topology';
@Component({
components: {
@@ -96,20 +107,45 @@ limitations under the License. -->
})
export default class WindowEndpoint extends Vue {
@Prop() private current!: { key: number | string; label: number | string };
- @Prop() private endpointComps: any;
- @Prop() private updateObjects!: string;
@State('rocketOption') private stateDashboardOption!: optionState;
@State('rocketData') private rocketComps!: rocketData;
@State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @State('rocketTopo') private stateTopo!: topoState;
@Getter('durationTime') private durationTime!: DurationTime;
- @Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
@Mutation('SET_EDIT') private SET_EDIT: any;
+ @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any;
+ @Mutation('rocketTopo/SET_TOPO_ENDPOINT') private SET_TOPO_ENDPOINT: any;
@Action('GET_SERVICE_ENDPOINTS') private GET_SERVICE_ENDPOINTS: any;
@Action('MIXHANDLE_CHANGE_GROUP_WITH_CURRENT') private MIXHANDLE_CHANGE_GROUP_WITH_CURRENT: any;
@Action('GET_EVENT') private GET_EVENT: any;
+ @Action('SELECT_ENDPOINT') private SELECT_ENDPOINT: any;
private pageEventsType = PageEventsType;
+ private endpointMetrics: any[] = [];
+ private currentType: Option[] = [{ key: '', label: '' }];
+ private templateTypesList: Option[] = [{ key: '', label: '' }];
+
+ private beforeMount() {
+ this.SET_CURRENT_SERVICE(this.current);
+ this.MIXHANDLE_CHANGE_GROUP_WITH_CURRENT({ index: 0, current: 2 });
+ this.GET_SERVICE_ENDPOINTS({ duration: this.durationTime, serviceId: this.current.key, keyword: '' }).then(() => {
+ this.selectEndpoint(this.stateDashboardOption.endpoints[0]);
+ });
+ this.templateTypesList = Object.keys(this.stateTopo.topoEndpoints).map((item: string) => {
+ return { label: item, key: item };
+ });
+ const topoTemplatesType: any = this.stateTopo.topoTemplatesType;
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ if (topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT]) {
+ this.currentType = topoTemplatesType[TopologyType.TOPOLOGY_ENDPOINT][nodeType] || [
+ { label: DEFAULT, key: DEFAULT },
+ ];
+ } else {
+ this.currentType = [{ label: DEFAULT, key: DEFAULT }];
+ }
+ }
private selectEndpoint(i: Option) {
if (!this.rocketComps.enableEvents) {
@@ -131,21 +167,46 @@ limitations under the License. -->
});
}
- private beforeMount() {
- this.SET_CURRENT_SERVICE(this.current);
- this.MIXHANDLE_CHANGE_GROUP_WITH_CURRENT({ index: 0, current: 2 });
- this.GET_SERVICE_ENDPOINTS({ duration: this.durationTime, serviceId: this.current.key, keyword: '' }).then(() => {
- this.selectEndpoint(this.stateDashboardOption.endpoints[0]);
- });
+ private changeTemplatesType(item: any) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+
+ if (this.currentType.find((d: any) => d.key === item.key)) {
+ this.deleteTemplateTypes(item);
+ return;
+ }
+ this.currentType.push(item);
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_ENDPOINT]: { [nodeType]: this.currentType },
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ }
+
+ private deleteTemplateTypes(item: Option) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+ const index = this.currentType.findIndex((d: any) => item.key === d.key);
+
+ this.currentType.splice(index, 1);
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_ENDPOINT]: { [nodeType]: this.currentType },
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
}
private async importData(event: any) {
try {
const data: any = await readFile(event);
- if (!Array.isArray(data)) {
- throw new Error();
- }
- this.$emit('changeEndpointComps', { json: data, type: ObjectsType.UPDATE_ENDPOINTS });
+
+ this.SET_TOPO_ENDPOINT(data);
+ const survey: any = this.$refs.survey;
+ survey.setTemplates();
const el: any = document.getElementById('endpoint-file');
el!.value = '';
} catch (e) {
@@ -154,14 +215,24 @@ limitations under the License. -->
}
private exportData() {
- const data = this.endpointComps;
+ let topoEndpoints = {};
const name = 'endpointComps.json';
- saveFile(data, name);
+ for (const type of Object.keys(this.stateTopo.topoEndpoints)) {
+ const metricsTemp = this.stateTopo.topoEndpoints[type].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ topoEndpoints = {
+ ...topoEndpoints,
+ [type]: metricsTemp,
+ };
+ }
+ saveFile(topoEndpoints, name);
}
private beforeDestroy() {
this.SET_EDIT(false);
- this.$emit('changeEndpointComps', { type: '' });
+ this.$emit('changeEndpointComps', { type: false });
}
}
</script>
@@ -191,4 +262,14 @@ limitations under the License. -->
.input-label.rk-btn {
line-height: 22px !important;
}
+ .type {
+ display: inline-block;
+ width: 100px;
+ }
+
+ .content {
+ vertical-align: top;
+ display: inline-block;
+ width: 300px;
+ }
</style>
diff --git a/src/views/containers/topology/instance/index.vue b/src/views/containers/topology/instance/index.vue
index b0fae5b..968fc23 100644
--- a/src/views/containers/topology/instance/index.vue
+++ b/src/views/containers/topology/instance/index.vue
@@ -56,16 +56,27 @@ limitations under the License. -->
:data="stateDashboardOption.instances"
icon="disk"
/>
+ <div class="pl-10 pb-5 flex-h">
+ <div class="type grey">{{ $t('templateType') }}</div>
+ <RkSelect
+ class="content grey"
+ :mode="'multiple'"
+ :current="currentType"
+ :data="templateTypesList"
+ :theme="'dark'"
+ @onChoose="(item) => changeTemplatesType(item)"
+ />
+ </div>
</div>
<DashboardEvent
:rocketComps="rocketComps"
:stateDashboard="stateDashboardOption"
:durationTime="durationTime"
- :type="pageEventsType.TOPO_INSTANCE_EVENTS"
+ :type="pageEventsType"
/>
</div>
</div>
- <instances-survey :instanceComps="instanceComps" :updateObjects="updateObjects" />
+ <instances-survey :currentType="currentType" ref="survey" />
</div>
</template>
@@ -78,14 +89,14 @@ limitations under the License. -->
import ToolBarEndpointSelect from '@/views/components/dashboard/tool-bar/tool-bar-endpoint-select.vue';
import { readFile } from '@/utils/readFile';
import { saveFile } from '@/utils/saveFile';
- import { ObjectsType } from '@/constants/constant';
import { EntityType } from '@/views/components/dashboard/charts/constant';
import { DurationTime, Option } from '@/types/global';
import { State as optionState } from '@/store/modules/global/selectors';
import { State as rocketData } from '@/store/modules/dashboard/dashboard-data';
import { State as rocketbotGlobal } from '@/store/modules/global';
import DashboardEvent from '@/views/components/dashboard/tool-bar/dashboard-events.vue';
- import { PageEventsType } from '@/constants/constant';
+ import { PageEventsType, DEFAULT, TopologyType } from '@/constants/constant';
+ import { State as topoState } from '@/store/modules/topology';
@Component({
components: {
@@ -97,11 +108,10 @@ limitations under the License. -->
})
export default class WindowInstance extends Vue {
@Prop() private current!: { key: number | string; label: number | string };
- @Prop() private instanceComps: any;
- @Prop() private updateObjects!: string;
@State('rocketOption') private stateDashboardOption!: optionState;
@State('rocketData') private rocketComps!: rocketData;
@State('rocketbot') private rocketGlobal!: rocketbotGlobal;
+ @State('rocketTopo') private stateTopo!: topoState;
@Getter('durationTime') private durationTime!: DurationTime;
@Action('SELECT_INSTANCE') private SELECT_INSTANCE: any;
@Action('GET_SERVICE_INSTANCES') private GET_SERVICE_INSTANCES: any;
@@ -109,8 +119,66 @@ limitations under the License. -->
@Action('GET_EVENT') private GET_EVENT: any;
@Mutation('SET_EDIT') private SET_EDIT: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
+ @Mutation('rocketTopo/UPDATE_TOPO_TEMPLATE_TYPES') private UPDATE_TOPO_TEMPLATE_TYPES: any;
+ @Mutation('rocketTopo/SET_TOPO_INSTANCE') private SET_TOPO_INSTANCE: any;
- private pageEventsType = PageEventsType;
+ private pageEventsType = PageEventsType.TOPO_INSTANCE_EVENTS;
+ private currentType: Option[] = [{ key: '', label: '' }];
+ private templateTypesList: Option[] = [{ key: '', label: '' }];
+
+ private beforeMount() {
+ this.SET_CURRENT_SERVICE(this.current);
+ this.MIXHANDLE_CHANGE_GROUP_WITH_CURRENT({ index: 0, current: 3 });
+ this.GET_SERVICE_INSTANCES({ duration: this.durationTime, serviceId: this.current.key }).then(() => {
+ this.selectInstance(this.stateDashboardOption.instances[0]);
+ });
+ this.templateTypesList = Object.keys(this.stateTopo.topoInstances).map((item: string) => {
+ return { label: item, key: item };
+ });
+ const topoTemplatesType: any = this.stateTopo.topoTemplatesType;
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ if (topoTemplatesType[TopologyType.TOPOLOGY_INSTANCE]) {
+ this.currentType = topoTemplatesType[TopologyType.TOPOLOGY_INSTANCE][nodeType] || [
+ { label: DEFAULT, key: DEFAULT },
+ ];
+ } else {
+ this.currentType = [{ label: DEFAULT, key: DEFAULT }];
+ }
+ }
+
+ private changeTemplatesType(item: Option) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+
+ if (this.currentType.find((d) => d.key === item.key)) {
+ this.deleteTemplateTypes(item);
+ return;
+ }
+ this.currentType.push(item);
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_INSTANCE]: { [nodeType]: this.currentType },
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ }
+
+ private deleteTemplateTypes(item: Option) {
+ let topoTemplateTypes;
+ const types = this.stateTopo.topoTemplatesType;
+ const index = this.currentType.findIndex((d) => item.key === d.key);
+
+ this.currentType.splice(index, 1);
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+
+ topoTemplateTypes = {
+ ...types,
+ [TopologyType.TOPOLOGY_INSTANCE]: { [nodeType]: this.currentType },
+ };
+ this.UPDATE_TOPO_TEMPLATE_TYPES(topoTemplateTypes);
+ }
private selectInstance(i: Option) {
if (!this.rocketComps.enableEvents) {
@@ -132,21 +200,15 @@ limitations under the License. -->
});
}
- private beforeMount() {
- this.SET_CURRENT_SERVICE(this.current);
- this.MIXHANDLE_CHANGE_GROUP_WITH_CURRENT({ index: 0, current: 3 });
- this.GET_SERVICE_INSTANCES({ duration: this.durationTime, serviceId: this.current.key }).then(() => {
- this.selectInstance(this.stateDashboardOption.instances[0]);
- });
- }
-
private async importData(event: any) {
try {
const data: any = await readFile(event);
if (!Array.isArray(data)) {
throw new Error();
}
- this.$emit('changeInstanceComps', { json: data, type: ObjectsType.UPDATE_ENDPOINTS });
+ this.SET_TOPO_INSTANCE(data);
+ const survey: any = this.$refs.survey;
+ survey.setTemplates();
const el: any = document.getElementById('instance-file');
el!.value = '';
} catch (e) {
@@ -154,13 +216,24 @@ limitations under the License. -->
}
}
private exportData() {
- const data = this.instanceComps;
+ let topoInstances = {};
const name = 'instanceComps.json';
- saveFile(data, name);
+
+ for (const type of Object.keys(this.stateTopo.topoInstances)) {
+ const metricsTemp = this.stateTopo.topoInstances[type].map((item: any) => {
+ delete item.uuid;
+ return item;
+ });
+ topoInstances = {
+ ...topoInstances,
+ [type]: metricsTemp,
+ };
+ }
+ saveFile(topoInstances, name);
}
private beforeDestroy() {
- this.$emit('changeInstanceComps', { type: '' });
+ this.$emit('changeInstanceComps', { type: false });
this.SET_EDIT(false);
}
}
@@ -188,4 +261,14 @@ limitations under the License. -->
display: inline;
line-height: inherit;
}
+ .type {
+ display: inline-block;
+ width: 100px;
+ }
+
+ .content {
+ vertical-align: top;
+ display: inline-block;
+ width: 300px;
+ }
</style>
diff --git a/src/views/containers/topology/instance/instances-survey.vue b/src/views/containers/topology/instance/instances-survey.vue
index 21aa2c1..85a50f6 100644
--- a/src/views/containers/topology/instance/instances-survey.vue
+++ b/src/views/containers/topology/instance/instances-survey.vue
@@ -17,15 +17,17 @@ limitations under the License. -->
<div class="dashboard-container clear">
<DashboardItem
v-for="(i, index) in instanceComps || []"
- :key="index + i.title + i.with"
+ :key="i.uuid"
:rocketGlobal="rocketGlobal"
:item="i"
:index="index"
- :type="'TOPOLOGY_INSTANCE'"
+ :type="type"
:updateObjects="updateObjects"
:rocketOption="stateDashboardOption"
+ :templateTypes="templateTypes"
+ @setTemplates="setTemplates"
/>
- <div v-show="rocketGlobal.edit" class="rk-add-dashboard-item g-sm-3" @click="ADD_TOPO_INSTANCE_COMP">
+ <div v-show="rocketGlobal.edit" class="rk-add-dashboard-item g-sm-3" @click="addInstanceMetrics()">
+ Add An Item
</div>
</div>
@@ -33,10 +35,14 @@ limitations under the License. -->
<script lang="ts">
import Vue from 'vue';
- import { Component, Prop } from 'vue-property-decorator';
+ import { Component, Watch, Prop } from 'vue-property-decorator';
import { State, Mutation } from 'vuex-class';
+ import { State as topoState } from '@/store/modules/topology';
import { State as optionState } from '@/store/modules/global/selectors';
import DashboardItem from '@/views/components/dashboard/dashboard-item.vue';
+ import { TopologyType, DEFAULT } from '@/constants/constant';
+ import { Option } from '@/types/global';
+ import { uuid } from '@/utils/uuid';
@Component({
components: {
@@ -44,10 +50,82 @@ limitations under the License. -->
},
})
export default class InstancesSurvey extends Vue {
+ @State('rocketTopo') private stateTopo!: topoState;
@State('rocketbot') private rocketGlobal: any;
@State('rocketOption') private stateDashboardOption!: optionState;
@Mutation('rocketTopo/ADD_TOPO_INSTANCE_COMP') private ADD_TOPO_INSTANCE_COMP: any;
- @Prop() private instanceComps: any;
- @Prop() private updateObjects!: string;
+ @Mutation('rocketTopo/SET_TOPO_INSTANCE') private SET_TOPO_INSTANCE: any;
+ @Prop() private currentType: any;
+
+ private instanceComps: any = [];
+ private type: string = TopologyType.TOPOLOGY_INSTANCE;
+ private templateTypes: string[] = [];
+ private updateObjects: boolean = false;
+
+ private beforeMount() {
+ this.setInstanceTemplates();
+ }
+
+ private setTemplates() {
+ this.updateObjects = true;
+ this.setInstanceTemplates();
+ }
+
+ private addInstanceMetrics() {
+ this.ADD_TOPO_INSTANCE_COMP();
+ this.setInstanceTemplates();
+ }
+
+ private setInstanceTemplates() {
+ this.setTemplateTypes();
+ this.instanceComps = [];
+ let templates: any = {};
+ for (const type of Object.keys(this.stateTopo.topoInstances)) {
+ const metricsTemp = this.stateTopo.topoInstances[type].map((item: any) => {
+ item.uuid = item.uuid || uuid();
+ return item;
+ });
+ templates = {
+ ...templates,
+ [type]: metricsTemp,
+ };
+ }
+ this.SET_TOPO_INSTANCE(templates);
+ for (const type of this.templateTypes) {
+ this.instanceComps = [...this.instanceComps, ...this.stateTopo.topoInstances[type]];
+ }
+ }
+
+ private setTemplateTypes() {
+ const nodeType = this.stateTopo.currentNode.type || DEFAULT;
+ const templates = this.stateTopo.topoTemplatesType;
+ if (templates[TopologyType.TOPOLOGY_INSTANCE] && templates[TopologyType.TOPOLOGY_INSTANCE][nodeType]) {
+ this.templateTypes = templates[TopologyType.TOPOLOGY_INSTANCE][nodeType].map((item: Option) => item.key);
+ } else {
+ this.templateTypes = this.stateTopo.topoInstances[nodeType] ? [nodeType] : [DEFAULT];
+ }
+ }
+
+ @Watch('currentType')
+ private updateMetrics() {
+ this.setTemplates();
+ }
}
</script>
+<style lang="scss" scoped>
+ .rk-add-dashboard-item {
+ height: 342px;
+ text-align: center;
+ line-height: 250px;
+ border: 1px dashed rgba(196, 200, 225, 0.5);
+ cursor: pointer;
+ display: inline-block;
+ font-size: 16px;
+ }
+ .dashboard-container {
+ overflow: auto;
+ padding: 20px 15px;
+ height: 100%;
+ flex-grow: 1;
+ }
+</style>
diff --git a/src/views/containers/topology/topology.vue b/src/views/containers/topology/topology.vue
index 942be4c..a0cc91f 100644
--- a/src/views/containers/topology/topology.vue
+++ b/src/views/containers/topology/topology.vue
@@ -25,36 +25,19 @@ limitations under the License. -->
<TopoAside />
<TopoGroup />
<rk-sidebox :show="dialog.length" @update:show="dialog = ''" :fixed="true" width="100%">
- <window-endpoint
- v-if="dialog === 'endpoint'"
- :current="this.current"
- :endpointComps="stateTopo.topoEndpoints"
- @changeEndpointComps="changeEndpointComps"
- :updateObjects="updateObjects"
- />
- <window-instance
- v-if="dialog === 'instance'"
- :current="this.current"
- :instanceComps="stateTopo.topoInstances"
- @changeInstanceComps="changeInstanceComps"
- :updateObjects="updateObjects"
- />
+ <window-endpoint v-if="dialog === 'endpoint'" :current="this.current" />
+ <window-instance v-if="dialog === 'instance'" :current="this.current" />
<window-trace v-if="dialog === 'trace'" :current="this.current" />
<window-alarm v-if="dialog === 'alarm'" :current="this.current" />
- <window-endpoint-dependency
- v-if="dialog === 'endpoint_dependency'"
- @changeEndpointComps="changeEndpointComps"
- :current="this.current"
- />
+ <window-endpoint-dependency v-if="dialog === 'endpoint_dependency'" :current="this.current" />
</rk-sidebox>
</div>
</template>
<script lang="ts">
import { Vue, Component } from 'vue-property-decorator';
- import { State, Action, Getter, Mutation } from 'vuex-class';
- import { AxiosResponse } from 'axios';
+ import { State, Action, Mutation } from 'vuex-class';
import { State as topoState } from '@/store/modules/topology';
- import { TopologyType } from '../../../constants/constant';
+ import { TopologyType, PageTypes } from '@/constants/constant';
import WindowEndpoint from '@/views/containers/topology/endpoint/index.vue';
import WindowInstance from '@/views/containers/topology/instance/index.vue';
import WindowTrace from '@/views/containers/topology/trace/index.vue';
@@ -63,6 +46,7 @@ limitations under the License. -->
import TopoAside from '../../components/topology/topo-aside.vue';
import TopoGroup from '../../components/topology/topo-group/index.vue';
import WindowEndpointDependency from '@/views/containers/topology/endpoint-dependency/index.vue';
+ import { Option } from '@/types/global';
@Component({
components: {
@@ -83,24 +67,76 @@ limitations under the License. -->
@Action('GET_ALL_TEMPLATES') private GET_ALL_TEMPLATES: any;
@Mutation('rocketTopo/SET_TOPO_ENDPOINT') private SET_TOPO_ENDPOINT: any;
@Mutation('rocketTopo/SET_TOPO_INSTANCE') private SET_TOPO_INSTANCE: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE') private SET_TOPO_SERVICE: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE_DEPENDENCY') private SET_TOPO_SERVICE_DEPENDENCY: any;
+ @Mutation('rocketTopo/SET_TOPO_SERVICE_INSTANCE_DEPENDENCY') private SET_TOPO_SERVICE_INSTANCE_DEPENDENCY: any;
+ @Mutation('rocketTopo/EDIT_DEPENDENCY_METRICS') private EDIT_DEPENDENCY_METRICS: any;
+ @Mutation('rocketTopo/SET_TOPO_ENDPOINT_DEPENDENCY') private SET_TOPO_ENDPOINT_DEPENDENCY: any;
@Mutation('SET_CURRENT_SERVICE') private SET_CURRENT_SERVICE: any;
- @Getter('durationTime') private durationTime: any;
+ @Mutation('SET_EDIT') private SET_EDIT: any;
+ @Mutation('SET_PAGE_TYPE') private SET_PAGE_TYPE: any;
private current: any = {};
private dialog: string = '';
- private updateObjects: string = '';
private created() {
- if (window.localStorage.getItem('topologyInstances') || window.localStorage.getItem('topologyEndpoints')) {
+ this.SET_PAGE_TYPE(PageTypes.TOPOLOGY);
+ this.initMetricsTemplate();
+ }
+ private initMetricsTemplate() {
+ localStorage.removeItem('topoTemplateTypes');
+ localStorage.removeItem('topologyServices');
+ localStorage.removeItem('topologyServicesDependency');
+
+ if (window.localStorage.getItem('topologyServices')) {
+ const serviceComps: string = `${window.localStorage.getItem('topologyServices')}`;
+ const topoService = serviceComps ? JSON.parse(serviceComps) : [];
+
+ this.SET_TOPO_SERVICE(topoService);
+ }
+ if (window.localStorage.getItem('topologyInstances')) {
const instanceComps: string = `${window.localStorage.getItem('topologyInstances')}`;
const topoInstance = instanceComps ? JSON.parse(instanceComps) : [];
+
+ this.SET_TOPO_INSTANCE(topoInstance);
+ }
+ if (window.localStorage.getItem('topologyEndpoints')) {
const endpointComps: string = `${window.localStorage.getItem('topologyEndpoints')}`;
const topoEndpoint = endpointComps ? JSON.parse(endpointComps) : [];
- this.SET_TOPO_INSTANCE(topoInstance);
+
this.SET_TOPO_ENDPOINT(topoEndpoint);
- } else {
- this.queryTemplates();
}
+ if (localStorage.getItem('topologyServicesDependency')) {
+ const serviceDependencyComps: string = `${localStorage.getItem('topologyServicesDependency')}`;
+ const topoServiceDependency = serviceDependencyComps ? JSON.parse(serviceDependencyComps) : [];
+
+ this.SET_TOPO_SERVICE_DEPENDENCY(topoServiceDependency);
+ }
+ if (localStorage.getItem('topologyServicesInstanceDependency')) {
+ const serviceInstanceDependencyComps: string = `${localStorage.getItem('topologyServicesInstanceDependency')}`;
+ const topoServiceInstanceDependency = serviceInstanceDependencyComps
+ ? JSON.parse(serviceInstanceDependencyComps)
+ : [];
+
+ this.SET_TOPO_SERVICE_INSTANCE_DEPENDENCY(topoServiceInstanceDependency);
+ }
+ if (localStorage.getItem('topologyEndpointDependency')) {
+ const serviceEndpointComps: string = `${localStorage.getItem('topologyEndpointDependency')}`;
+ const topoEndpointDependency = serviceEndpointComps ? JSON.parse(serviceEndpointComps) : [];
+
+ this.SET_TOPO_ENDPOINT_DEPENDENCY(topoEndpointDependency);
+ }
+ if (
+ localStorage.getItem('topologyServices') &&
+ localStorage.getItem('topologyInstances') &&
+ localStorage.getItem('topologyEndpoints') &&
+ localStorage.getItem('topologyServicesDependency') &&
+ localStorage.getItem('topologyServicesInstanceDependency') &&
+ localStorage.getItem('topologyEndpointDependency')
+ ) {
+ return;
+ }
+ this.queryTemplates();
}
private queryTemplates() {
this.GET_ALL_TEMPLATES().then(
@@ -113,40 +149,65 @@ limitations under the License. -->
disabled: boolean;
}>,
) => {
- const template =
- allTemplates.filter((item: any) => item.type === TopologyType.TOPOLOGY_INSTANCE && item.activated)[0] || {};
- const instanceComps = JSON.parse(template.configuration) || [];
- this.SET_TOPO_INSTANCE(instanceComps);
- const endpointTemplate =
- allTemplates.filter((item: any) => item.type === TopologyType.TOPOLOGY_ENDPOINT && item.activated)[0] || {};
- const endpointComps = JSON.parse(endpointTemplate.configuration) || [];
- this.SET_TOPO_ENDPOINT(endpointComps);
+ if (!window.localStorage.getItem('topologyInstances')) {
+ const template =
+ allTemplates.filter((item: any) => item.type === TopologyType.TOPOLOGY_INSTANCE && item.activated)[0] ||
+ {};
+ const instanceComps = JSON.parse(template.configuration) || [];
+ this.SET_TOPO_INSTANCE(instanceComps);
+ }
+ if (!window.localStorage.getItem('topologyEndpoints')) {
+ const endpointTemplate =
+ allTemplates.filter((item: any) => item.type === TopologyType.TOPOLOGY_ENDPOINT && item.activated)[0] ||
+ {};
+ const endpointComps = JSON.parse(endpointTemplate.configuration) || [];
+ this.SET_TOPO_ENDPOINT(endpointComps);
+ }
+ if (!window.localStorage.getItem('topologyServices')) {
+ const serviceTemplate =
+ allTemplates.filter((item: any) => item.type === TopologyType.TOPOLOGY_SERVICE && item.activated)[0] ||
+ {};
+ const topoService = JSON.parse(serviceTemplate.configuration) || [];
+ this.SET_TOPO_SERVICE(topoService);
+ }
+ if (!localStorage.getItem('topologyServicesDependency')) {
+ const serviceDependencyTemplate =
+ allTemplates.filter(
+ (item: any) => item.type === TopologyType.TOPOLOGY_SERVICE_DEPENDENCY && item.activated,
+ )[0] || {};
+ const topoServiceDependency = JSON.parse(serviceDependencyTemplate.configuration) || [];
+ this.SET_TOPO_SERVICE_DEPENDENCY(topoServiceDependency);
+ }
+ if (!localStorage.getItem('topologyServicesInstanceDependency')) {
+ const serviceInstanceDependencyTemplate =
+ allTemplates.filter(
+ (item: any) => item.type === TopologyType.TOPOLOGY_SERVICE_INSTANCE_DEPENDENCY && item.activated,
+ )[0] || {};
+ const topoServiceInstanceDependency = JSON.parse(serviceInstanceDependencyTemplate.configuration) || [];
+ this.SET_TOPO_SERVICE_INSTANCE_DEPENDENCY(topoServiceInstanceDependency);
+ }
+ if (!localStorage.getItem('topologyEndpointDependency')) {
+ const serviceEndpointDependencyTemplate =
+ allTemplates.filter(
+ (item: any) => item.type === TopologyType.TOPOLOGY_ENDPOINT_DEPENDENCY && item.activated,
+ )[0] || {};
+ const topoEndpointDependency = JSON.parse(serviceEndpointDependencyTemplate.configuration) || [];
+ this.SET_TOPO_ENDPOINT_DEPENDENCY(topoEndpointDependency);
+ }
},
);
}
- private setCurrent(d: any): void {
+ private setCurrent(d: Option & { isReal: boolean }): void {
this.current = d;
if (d.isReal) {
- this.SET_CURRENT_SERVICE(d);
- }
- }
- private changeInstanceComps(data: { type: string; json: any }) {
- this.updateObjects = data.type;
- if (!data.json) {
- return;
- }
- this.SET_TOPO_INSTANCE(data.json);
- }
- private changeEndpointComps(data: { type: string; json: any }) {
- this.updateObjects = data.type;
- if (!data.json) {
- return;
+ this.SET_CURRENT_SERVICE({ key: d.key, label: d.label });
}
- this.SET_TOPO_ENDPOINT(data.json);
}
private beforeDestroy() {
this.CLEAR_TOPO_INFO();
this.CLEAR_TOPO();
+ this.SET_EDIT(false);
+ this.EDIT_DEPENDENCY_METRICS(false);
}
}
</script>