blob: 35b2511fca25aec1b9899e87f745c67d0abc5556 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Commit, ActionTree, Dispatch } from 'vuex';
import graph from '@/graph';
import * as types from '../../mutation-types';
import axios, { AxiosPromise, AxiosResponse } from 'axios';
import { cancelToken } from '@/utils/cancelToken';
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[];
nodes: Node[];
detectPoints: string[];
selectedServiceCall: Call | null;
currentNode: any;
currentLink: any;
current: Option;
mode: boolean;
instanceDependency: {
calls: Call[];
nodes: Node[];
};
endpointDependency: {
calls: Call[];
nodes: Node[];
};
selectedInstanceCall: Call | null;
selectedEndpointCall: Call | null;
endpointDependencyMetrics: { [key: string]: any };
currentEndpointDepth: { key: number; label: string };
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 };
endpointErrors: string;
getTopoErrors: string;
endpointTopoErrors: string;
instanceTopoErrors: string;
topoErrors: { [key: string]: string };
}
const DefaultConfig = {
width: 12,
title: 'Title',
height: 250,
metricType: 'UNKNOWN',
};
const initState: State = {
callback: '',
mode: true,
detectPoints: [],
selectedServiceCall: null,
calls: [],
nodes: [],
currentNode: {},
currentLink: {},
current: {
key: 'default',
label: 'default',
},
instanceDependency: {
calls: [],
nodes: [],
},
endpointDependency: {
calls: [],
nodes: [],
},
selectedInstanceCall: null,
selectedEndpointCall: null,
endpointDependencyMetrics: {},
currentEndpointDepth: { key: 2, label: '2' },
topoEndpoints: {},
topoInstances: {},
topoServices: {},
topoServicesDependency: {},
topoServicesInstanceDependency: {},
instanceDependencyMode: '',
editDependencyMetrics: false,
topoEndpointDependency: {},
topoTemplatesType: JSON.parse(localStorage.getItem('topoTemplateTypes') || JSON.stringify({})),
endpointErrors: '',
getTopoErrors: '',
endpointTopoErrors: '',
instanceTopoErrors: '',
topoErrors: {},
};
// getters
const getters = {};
// mutations
const mutations = {
[types.SET_MODE](state: State, data: string[]) {
state.detectPoints = data;
const temp = state.mode ? 'SERVER' : 'CLIENT';
if (data.indexOf(temp) === -1) {
state.mode = !state.mode;
}
},
[types.SET_MODE_STATUS](state: State, data: boolean) {
state.mode = data;
},
[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: Call) {
state.currentLink = data;
},
[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_INSTANCE_DEPENDENCY](state: State, data: any) {
state.instanceDependency = data;
},
[types.SET_SELECTED_INSTANCE_CALL](state: State, data: Call) {
state.selectedInstanceCall = data;
},
[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));
}
}
},
[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;
}
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.DELETE_TOPO_ENDPOINT_DEPENDENCY](state: State, id: string) {
if (!state.selectedEndpointCall) {
return;
}
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.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.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_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_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.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.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,
uuid: uuid(),
entityType: 'ServiceInstance',
};
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,
uuid: uuid(),
entityType: 'Endpoint',
};
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[] }) {
const obj = {} as any;
let nodes = [];
let calls = [];
nodes = data.nodes.reduce((prev: Node[], next: Node) => {
if (!obj[next.id]) {
obj[next.id] = true;
prev.push(next);
}
return prev;
}, []);
calls = data.calls.reduce((prev: Call[], next: Call) => {
if (!obj[next.id]) {
obj[next.id] = true;
prev.push(next);
}
return prev;
}, []);
state.endpointDependency = { nodes, calls };
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));
},
[types.SET_TOPO_ERRORS](state: State, data: { msg: string; desc: string }) {
state.topoErrors = {
...state.topoErrors,
[data.msg]: data.desc,
};
},
};
// actions
const actions: ActionTree<State, any> = {
GET_SERVICES(context: { commit: Commit }, params: { duration: Duration; keyword: string }) {
if (!params.keyword) {
params.keyword = '';
}
return graph
.query('queryServices')
.params(params)
.then((res: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, { msg: 'serviceTopoErrors', desc: res.data.errors });
if (res.data.errors) {
return [];
}
return res.data.data.services || [];
});
},
GET_SERVICE_ENDPOINTS(context: { commit: Commit }, params: { serviceId: string; keyword: string }) {
if (!params.serviceId) {
return new Promise((resolve) => resolve([]));
}
if (!params.keyword) {
params.keyword = '';
}
return graph
.query('queryEndpoints')
.params(params)
.then((res: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointErrors', desc: res.data.errors });
if (res.data.errors) {
return [];
}
return res.data.data.getEndpoints || [];
});
},
CLEAR_TOPO(context: { commit: Commit; state: State }) {
context.commit(types.SET_TOPO, { calls: [], nodes: [] });
},
CLEAR_TOPO_INFO(context: { commit: Commit; state: State }) {
context.commit(types.SET_SELECTED_CALL, null);
},
GET_TOPO(context: { commit: Commit; state: State }, params: any) {
let query = 'queryTopo';
if (params.serviceId) {
query = 'queryServiceTopo';
}
if (params.serviceIds) {
query = 'queryServicesTopo';
}
return graph
.query(query)
.params(params)
.then((res: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, { msg: query, desc: res.data.errors || '' });
if (!res.data.data) {
context.commit(types.SET_TOPO, { calls: [], nodes: [] });
return;
}
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.includes('CLIENT')).map((b: any) => b.id);
const idsS = calls.filter((i: any) => i.detectPoints.includes('SERVER')).map((b: any) => b.id);
if (!ids.length) {
return context.commit(types.SET_TOPO, { calls: [], nodes: [] });
}
const queryName = !idsC.length ? 'queryTopoInfoServer' : !idsS.length ? 'queryTopoInfoClient' : 'queryTopoInfo';
return graph
.query(queryName)
.params({ ...params, ids, idsC, idsS })
.then((info: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, { msg: 'queryTopoInfo', desc: info.data.errors || '' });
const resInfo = info.data.data;
if (!resInfo) {
context.commit(types.SET_TOPO, { calls: [], nodes: [] });
return;
}
if (!resInfo.sla) {
return context.commit(types.SET_TOPO, { calls, nodes });
}
for (let i = 0; i < resInfo.sla.values.length; i += 1) {
for (let j = 0; j < nodes.length; j += 1) {
if (nodes[j].id === resInfo.sla.values[i].id) {
nodes[j] = {
...nodes[j],
isGroupActive: true,
sla: resInfo.sla.values[i].value ? resInfo.sla.values[i].value / 100 : -1,
cpm: resInfo.nodeCpm.values[i] ? resInfo.nodeCpm.values[i].value : -1,
latency: resInfo.nodeLatency.values[i] ? resInfo.nodeLatency.values[i].value : -1,
};
}
}
}
if (!resInfo.cpmC) {
return context.commit(types.SET_TOPO, { calls, nodes });
}
for (let i = 0; i < resInfo.cpmC.values.length; i += 1) {
for (let j = 0; j < calls.length; j += 1) {
if (calls[j].id === resInfo.cpmC.values[i].id) {
calls[j] = {
...calls[j],
isGroupActive: true,
cpm: resInfo.cpmC.values[i] ? resInfo.cpmC.values[i].value : '',
latency: resInfo.latencyC.values[i] ? resInfo.latencyC.values[i].value : '',
};
}
}
}
if (!resInfo.cpmS) {
return context.commit(types.SET_TOPO, { calls, nodes });
}
for (let i = 0; i < resInfo.cpmS.values.length; i += 1) {
for (let j = 0; j < calls.length; j += 1) {
if (calls[j].id === resInfo.cpmS.values[i].id) {
calls[j] = {
...calls[j],
cpm: resInfo.cpmS.values[i] ? resInfo.cpmS.values[i].value : '',
latency: resInfo.latencyS.values[i] ? resInfo.latencyS.values[i].value : '',
};
}
}
}
context.commit(types.SET_TOPO, { calls, nodes });
});
});
},
// todo sync
GET_ALL_ENDPOINT_DEPENDENCY(
context: { commit: Commit; state: State; dispatch: Dispatch },
params: { endpointIds: string[]; duration: Duration },
) {
context.dispatch('GET_ENDPOINT_TOPO', params).then((res) => {
if (!res) {
return;
}
if (context.state.currentEndpointDepth.key > 1) {
const endpointIds = res.nodes
.map((item: Node) => item.id)
.filter((d: string) => !params.endpointIds.includes(d));
if (!endpointIds.length) {
context.commit(types.SET_ENDPOINT_DEPENDENCY, res);
return;
}
context.dispatch('GET_ENDPOINT_TOPO', { endpointIds, duration: params.duration }).then((json) => {
if (context.state.currentEndpointDepth.key > 2) {
const ids = json.nodes
.map((item: Node) => item.id)
.filter((d: string) => ![...endpointIds, ...params.endpointIds].includes(d));
if (!ids.length) {
const nodes = [...res.nodes, ...json.nodes];
const calls = [...res.calls, ...json.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
return;
}
context.dispatch('GET_ENDPOINT_TOPO', { endpointIds: ids, duration: params.duration }).then((topo) => {
if (context.state.currentEndpointDepth.key > 3) {
const endpoints = topo.nodes
.map((item: Node) => item.id)
.filter((d: string) => ![...ids, ...endpointIds, ...params.endpointIds].includes(d));
if (!endpoints.length) {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
}
context
.dispatch('GET_ENDPOINT_TOPO', { endpointIds: endpoints, duration: params.duration })
.then((data) => {
if (context.state.currentEndpointDepth.key > 4) {
const nodeIds = data.nodes
.map((item: Node) => item.id)
.filter(
(d: string) => ![...endpoints, ...ids, ...endpointIds, ...params.endpointIds].includes(d),
);
if (!nodeIds.length) {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
return;
}
context
.dispatch('GET_ENDPOINT_TOPO', { endpointIds: nodeIds, duration: params.duration })
.then((toposObj) => {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes, ...toposObj.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls, ...toposObj.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
});
} else {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes, ...data.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls, ...data.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
}
});
} else {
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
const calls = [...res.calls, ...json.calls, ...topo.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
}
});
} else {
const nodes = [...res.nodes, ...json.nodes];
const calls = [...res.calls, ...json.calls];
context.commit(types.SET_ENDPOINT_DEPENDENCY, { nodes, calls });
}
});
} else {
context.commit(types.SET_ENDPOINT_DEPENDENCY, res);
}
});
},
GET_ENDPOINT_TOPO(context: { commit: Commit; state: State }, params: { endpointIds: string[]; duration: Duration }) {
const variables = ['$duration: Duration!'];
const fragment = params.endpointIds.map((id: string, index: number) => {
return `endpointTopology${index}: getEndpointDependencies(endpointId: "${id}", duration: $duration) {
nodes {
id
name
serviceId
serviceName
type
isReal
}
calls {
id
source
target
detectPoints
}
}`;
});
const querys = `query queryData(${variables}) {${fragment}}`;
return axios
.post('/graphql', { query: querys, variables: { duration: params.duration } }, { cancelToken: cancelToken() })
.then((res: AxiosResponse) => {
if (res.data.errors) {
const msg = res.data.errors.map((e: { message: string }) => e.message).join(' ');
context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: msg });
context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] });
return;
}
const topo = res.data.data;
let calls = [] as any;
let nodes = [] as any;
for (const key of Object.keys(topo)) {
calls.push(...topo[key].calls);
nodes.push(...topo[key].nodes);
}
if (!nodes.length) {
context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: '' });
context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] });
return;
}
const obj = {} as any;
nodes = nodes.reduce((prev: Node[], next: Node) => {
if (!obj[next.id]) {
obj[next.id] = true;
prev.push(next);
}
return prev;
}, []);
calls = calls.reduce((prev: Call[], next: Call) => {
if (!obj[next.id]) {
obj[next.id] = true;
prev.push(next);
}
return prev;
}, []);
const queryVariables = ['$duration: Duration!'];
const fragments = calls
.map((call: Call & EndpointDependencyConidition, index: number) => {
let source = {} as any;
let target = {} as any;
for (const node of nodes) {
if (node.id === call.source) {
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: {
name: "endpoint_relation_cpm"
entity: {
scope: EndpointRelation
serviceName: "${source.serviceName}"
normal: true
endpointName: "${source.name}"
destNormal: true
destServiceName: "${target.serviceName}"
destEndpointName: "${target.name}"
}
}, duration: $duration)`;
})
.join(' ');
const query = `query queryData(${queryVariables}) {${fragments}}`;
return axios
.post('/graphql', { query, variables: { duration: params.duration } }, { cancelToken: cancelToken() })
.then((json: AxiosResponse<any>) => {
if (json.data.errors) {
const msg = json.data.errors.map((e: { message: string }) => e.message).join(' ');
context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: msg });
context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] });
return;
}
context.commit(types.SET_TOPO_ERRORS, { msg: 'endpointDependencyError', desc: '' });
const cpms = json.data.data;
const keys = Object.keys(cpms);
for (const key of keys) {
const index = Number(key.split('_')[1]);
calls[index].value = cpms[key] || 0.01;
}
return { calls, nodes };
})
.catch(() => {
context.commit(types.SET_ENDPOINT_DEPENDENCY, { calls: [], nodes: [] });
});
});
},
GET_TOPO_INSTANCE_DEPENDENCY(
context: { commit: Commit; state: State },
params: {
clientServiceId: string;
serverServiceId: string;
duration: Duration;
},
) {
graph
.query('queryTopoInstanceDependency')
.params(params)
.then((res: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, { msg: 'queryTopoInstanceDependency', desc: res.data.errors || '' });
if (res.data.errors) {
return [];
}
const clientIdsC = [] as string[];
const serverIdsC = [] as string[];
const topoCalls = res.data.data.topo.calls;
for (const call of topoCalls) {
if (call.detectPoints.includes('CLIENT')) {
clientIdsC.push(call.id);
} else {
serverIdsC.push(call.id);
}
}
let callback;
let callbackServer;
if (clientIdsC.length) {
callback = graph
.query('queryDependencyInstanceClientMetric')
.params({
idsC: clientIdsC,
duration: params.duration,
})
.then((json: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, {
msg: 'queryDependencyInstanceClientMetric',
desc: json.data.errors || '',
});
if (json.data.errors) {
return [];
}
const clientCalls = [] as string[];
for (const call of topoCalls) {
for (const cpm of json.data.data.cpmC.values) {
if (cpm.id === call.id) {
clientCalls.push({
...call,
...cpm,
});
}
}
}
return clientCalls;
});
} else {
callback = new Promise((resolve) => resolve([]));
}
if (serverIdsC.length) {
callbackServer = graph
.query('queryDependencyInstanceServerMetric')
.params({
idsC: serverIdsC,
duration: params.duration,
})
.then((jsonResp: AxiosResponse) => {
context.commit(types.SET_TOPO_ERRORS, {
msg: 'queryDependencyInstanceServerMetric',
desc: jsonResp.data.errors || '',
});
if (jsonResp.data.errors) {
return [];
}
const serverCalls = [] as string[];
for (const call of topoCalls) {
for (const cpm of jsonResp.data.data.cpmC.values) {
if (cpm.id === call.id) {
serverCalls.push({
...call,
...cpm,
});
}
}
}
return serverCalls;
});
} else {
callbackServer = new Promise((resolve) => resolve([]));
}
Promise.all([callback, callbackServer]).then((values: any) => {
const instanceDependency = {
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);
});
});
},
};
export default {
namespaced: true,
state: initState,
getters,
actions,
mutations,
};