mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-07-18 14:45:25 +00:00
set endpoint topology with depth
This commit is contained in:
parent
832521af9d
commit
995f572a47
@ -173,20 +173,6 @@ export const topologyStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
async getEndpointTopology() {
|
|
||||||
const endpointId = useSelectorStore().currentPod.id;
|
|
||||||
const duration = useAppStoreWithOut().durationTime;
|
|
||||||
const res: AxiosResponse = await graphql
|
|
||||||
.query("getEndpointTopology")
|
|
||||||
.params({
|
|
||||||
endpointId,
|
|
||||||
duration,
|
|
||||||
});
|
|
||||||
if (!res.data.errors) {
|
|
||||||
this.setEndpointTopology(res.data.data.topology);
|
|
||||||
}
|
|
||||||
return res.data;
|
|
||||||
},
|
|
||||||
async getInstanceTopology() {
|
async getInstanceTopology() {
|
||||||
const serverServiceId = useSelectorStore().currentService.id;
|
const serverServiceId = useSelectorStore().currentService.id;
|
||||||
const clientServiceId = useSelectorStore().currentDestService.id;
|
const clientServiceId = useSelectorStore().currentDestService.id;
|
||||||
@ -203,6 +189,150 @@ export const topologyStore = defineStore({
|
|||||||
}
|
}
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
|
async updateEndpointTopology(endpointIds: string[], depth: number) {
|
||||||
|
const res = await this.getEndpointTopology(endpointIds);
|
||||||
|
if (depth > 1) {
|
||||||
|
const ids = res.nodes
|
||||||
|
.map((item: Node) => item.id)
|
||||||
|
.filter((d: string) => !endpointIds.includes(d));
|
||||||
|
if (!ids.length) {
|
||||||
|
this.setEndpointTopology(res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const json = await this.getEndpointTopology(ids);
|
||||||
|
if (depth > 2) {
|
||||||
|
const pods = json.nodes
|
||||||
|
.map((item: Node) => item.id)
|
||||||
|
.filter((d: string) => ![...ids, ...endpointIds].includes(d));
|
||||||
|
if (!pods.length) {
|
||||||
|
const nodes = [...res.nodes, ...json.nodes];
|
||||||
|
const calls = [...res.calls, ...json.calls];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const topo = await this.getEndpointTopology(pods);
|
||||||
|
if (depth > 3) {
|
||||||
|
const endpoints = topo.nodes
|
||||||
|
.map((item: Node) => item.id)
|
||||||
|
.filter(
|
||||||
|
(d: string) => ![...ids, ...pods, ...endpointIds].includes(d)
|
||||||
|
);
|
||||||
|
if (!endpoints.length) {
|
||||||
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
||||||
|
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = await this.getEndpointTopology(endpoints);
|
||||||
|
if (depth > 4) {
|
||||||
|
const nodeIds = data.nodes
|
||||||
|
.map((item: Node) => item.id)
|
||||||
|
.filter(
|
||||||
|
(d: string) =>
|
||||||
|
![...endpoints, ...ids, ...pods, ...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,
|
||||||
|
];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const toposObj = await this.getEndpointTopology(nodeIds);
|
||||||
|
const nodes = [
|
||||||
|
...res.nodes,
|
||||||
|
...json.nodes,
|
||||||
|
...topo.nodes,
|
||||||
|
...data.nodes,
|
||||||
|
...toposObj.nodes,
|
||||||
|
];
|
||||||
|
const calls = [
|
||||||
|
...res.calls,
|
||||||
|
...json.calls,
|
||||||
|
...topo.calls,
|
||||||
|
...data.calls,
|
||||||
|
...toposObj.calls,
|
||||||
|
];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
} else {
|
||||||
|
const nodes = [
|
||||||
|
...res.nodes,
|
||||||
|
...json.nodes,
|
||||||
|
...topo.nodes,
|
||||||
|
...data.nodes,
|
||||||
|
];
|
||||||
|
const calls = [
|
||||||
|
...res.calls,
|
||||||
|
...json.calls,
|
||||||
|
...topo.calls,
|
||||||
|
...data.calls,
|
||||||
|
];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const nodes = [...res.nodes, ...json.nodes, ...topo.nodes];
|
||||||
|
const calls = [...res.calls, ...json.calls, ...topo.calls];
|
||||||
|
this.setEndpointTopology({ nodes, calls });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setEndpointTopology({
|
||||||
|
nodes: [...res.nodes, ...json.nodes],
|
||||||
|
calls: [...res.calls, ...json.calls],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.setEndpointTopology(res);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getEndpointTopology(endpointIds: string[]) {
|
||||||
|
// const endpointId = useSelectorStore().currentPod.id;
|
||||||
|
const duration = useAppStoreWithOut().durationTime;
|
||||||
|
const variables = ["$duration: Duration!"];
|
||||||
|
const fragment = 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 queryStr = `query queryData(${variables}) {${fragment}}`;
|
||||||
|
const conditions = { duration };
|
||||||
|
const res: AxiosResponse = await query({ queryStr, conditions });
|
||||||
|
|
||||||
|
if (res.data.errors) {
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
const topo = res.data.data;
|
||||||
|
const calls = [] as any;
|
||||||
|
const nodes = [] as any;
|
||||||
|
for (const key of Object.keys(topo)) {
|
||||||
|
calls.push(...topo[key].calls);
|
||||||
|
nodes.push(...topo[key].nodes);
|
||||||
|
}
|
||||||
|
// this.setEndpointTopology({ calls, nodes });
|
||||||
|
|
||||||
|
return { calls, nodes };
|
||||||
|
},
|
||||||
async getNodeMetrics(param: {
|
async getNodeMetrics(param: {
|
||||||
queryStr: string;
|
queryStr: string;
|
||||||
conditions: { [key: string]: unknown };
|
conditions: { [key: string]: unknown };
|
||||||
|
@ -14,6 +14,15 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="tool">
|
<div class="tool">
|
||||||
|
<span class="label">{{ t("currentDepth") }}</span>
|
||||||
|
<Selector
|
||||||
|
class="inputs"
|
||||||
|
:value="depth"
|
||||||
|
:options="depthList"
|
||||||
|
placeholder="Select metrics"
|
||||||
|
@change="changeDepth"
|
||||||
|
:style="`background: '#2b3037';`"
|
||||||
|
/>
|
||||||
<span class="switch-icon ml-5" title="Settings">
|
<span class="switch-icon ml-5" title="Settings">
|
||||||
<Icon @click="setConfig" size="middle" iconName="settings" />
|
<Icon @click="setConfig" size="middle" iconName="settings" />
|
||||||
</span>
|
</span>
|
||||||
@ -21,18 +30,48 @@ limitations under the License. -->
|
|||||||
<Settings @update="updateConfig" />
|
<Settings @update="updateConfig" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="sankey" :style="`height:${height}px;width:${width}px;`">
|
<div
|
||||||
|
class="sankey"
|
||||||
|
:style="`height:${height}px;width:${width}px;`"
|
||||||
|
v-loading="loading"
|
||||||
|
>
|
||||||
<Sankey />
|
<Sankey />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
import { Option } from "@/types/app";
|
||||||
|
import { useTopologyStore } from "@/store/modules/topology";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
|
import { EntityType } from "../../../data";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
import Sankey from "./Sankey.vue";
|
import Sankey from "./Sankey.vue";
|
||||||
import Settings from "./Settings.vue";
|
import Settings from "./Settings.vue";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
const selectorStore = useSelectorStore();
|
||||||
|
const topologyStore = useTopologyStore();
|
||||||
|
const loading = ref<boolean>(false);
|
||||||
const height = ref<number>(document.body.clientHeight - 110);
|
const height = ref<number>(document.body.clientHeight - 110);
|
||||||
const width = ref<number>(document.body.clientWidth - 40);
|
const width = ref<number>(document.body.clientWidth - 40);
|
||||||
const showSettings = ref<boolean>(false);
|
const showSettings = ref<boolean>(false);
|
||||||
|
const depth = ref<string>("2");
|
||||||
|
const depthList = [1, 2, 3, 4, 5].map((item: number) => ({
|
||||||
|
value: String(item),
|
||||||
|
label: String(item),
|
||||||
|
}));
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
loading.value = true;
|
||||||
|
const resp = await getTopology();
|
||||||
|
loading.value = false;
|
||||||
|
if (resp && resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function setConfig() {
|
function setConfig() {
|
||||||
showSettings.value = !showSettings.value;
|
showSettings.value = !showSettings.value;
|
||||||
@ -41,6 +80,33 @@ function setConfig() {
|
|||||||
function updateConfig(config: any) {
|
function updateConfig(config: any) {
|
||||||
console.log(config);
|
console.log(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function changeDepth(opt: Option[]) {
|
||||||
|
depth.value = opt[0].value;
|
||||||
|
console.log(depth.value);
|
||||||
|
loading.value = true;
|
||||||
|
const resp = await getTopology();
|
||||||
|
loading.value = false;
|
||||||
|
if (resp && resp.errors) {
|
||||||
|
ElMessage.error(resp.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getTopology() {
|
||||||
|
let resp;
|
||||||
|
switch (dashboardStore.entity) {
|
||||||
|
case EntityType[2].value:
|
||||||
|
resp = await topologyStore.updateEndpointTopology(
|
||||||
|
[selectorStore.currentPod.id],
|
||||||
|
Number(depth.value)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case EntityType[4].value:
|
||||||
|
resp = await topologyStore.getInstanceTopology();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.sankey {
|
.sankey {
|
||||||
@ -81,4 +147,10 @@ function updateConfig(config: any) {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #ccc;
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -14,29 +14,15 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Graph :option="option" v-loading="loading" />
|
<Graph :option="option" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted } from "vue";
|
import { computed } from "vue";
|
||||||
import { useTopologyStore } from "@/store/modules/topology";
|
import { useTopologyStore } from "@/store/modules/topology";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
|
||||||
import { EntityType } from "../../../data";
|
|
||||||
import { ElMessage } from "element-plus";
|
|
||||||
|
|
||||||
const topologyStore = useTopologyStore();
|
const topologyStore = useTopologyStore();
|
||||||
const dashboardStore = useDashboardStore();
|
|
||||||
const loading = ref<boolean>(false);
|
|
||||||
const option = computed(() => getOption());
|
const option = computed(() => getOption());
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
loading.value = true;
|
|
||||||
const resp = await getTopology();
|
|
||||||
loading.value = false;
|
|
||||||
if (resp && resp.errors) {
|
|
||||||
ElMessage.error(resp.errors);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function getOption() {
|
function getOption() {
|
||||||
return {
|
return {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
@ -85,19 +71,6 @@ function getOption() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getTopology() {
|
|
||||||
let resp;
|
|
||||||
switch (dashboardStore.entity) {
|
|
||||||
case EntityType[2].value:
|
|
||||||
resp = await topologyStore.getEndpointTopology();
|
|
||||||
break;
|
|
||||||
case EntityType[4].value:
|
|
||||||
resp = await topologyStore.getInstanceTopology();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return resp;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.sankey {
|
.sankey {
|
||||||
|
Loading…
Reference in New Issue
Block a user