diff --git a/src/store/modules/ebpf.ts b/src/store/modules/ebpf.ts index e5f0646a..5dc89855 100644 --- a/src/store/modules/ebpf.ts +++ b/src/store/modules/ebpf.ts @@ -21,16 +21,12 @@ import { EBPFProfilingSchedule, EBPFTaskList, AnalyzationTrees, - ProcessNode, } from "@/types/ebpf"; import { store } from "@/store"; import graphql from "@/graphql"; import { AxiosResponse } from "axios"; -import { Call } from "@/types/topology"; -import { LayoutConfig } from "@/types/dashboard"; -interface EbpfStore { +interface EbpfState { taskList: EBPFTaskList[]; - networkTasks: EBPFTaskList[]; eBPFSchedules: EBPFProfilingSchedule[]; currentSchedule: EBPFProfilingSchedule | Record; analyzeTrees: AnalyzationTrees[]; @@ -39,22 +35,13 @@ interface EbpfStore { tip: string; networkTip: string; selectedTask: Recordable; - selectedNetworkTask: Recordable; aggregateType: string; - nodes: ProcessNode[]; - calls: Call[]; - node: Nullable; - call: Nullable; - metricsLayout: LayoutConfig[]; - selectedMetric: Nullable; - activeMetricIndex: string; } export const ebpfStore = defineStore({ id: "eBPF", - state: (): EbpfStore => ({ + state: (): EbpfState => ({ taskList: [], - networkTasks: [], eBPFSchedules: [], currentSchedule: {}, analyzeTrees: [], @@ -63,15 +50,7 @@ export const ebpfStore = defineStore({ tip: "", networkTip: "", selectedTask: {}, - selectedNetworkTask: {}, aggregateType: "COUNT", - nodes: [], - calls: [], - node: null, - call: null, - metricsLayout: [], - selectedMetric: null, - activeMetricIndex: "", }), actions: { setSelectedTask(task: EBPFTaskList) { @@ -86,44 +65,6 @@ export const ebpfStore = defineStore({ setAnalyzeTrees(tree: AnalyzationTrees[]) { this.analyzeTrees = tree; }, - setNode(node: Node) { - this.node = node; - }, - setLink(link: Call) { - this.call = link; - }, - setMetricsLayout(layout: LayoutConfig[]) { - this.metricsLayout = layout; - }, - setSelectedMetric(item: LayoutConfig) { - this.selectedMetric = item; - }, - setActiveItem(index: string) { - this.activeMetricIndex = index; - }, - setTopology(data: { nodes: ProcessNode[]; calls: Call[] }) { - const obj = {} as any; - const calls = (data.calls || []).reduce((prev: Call[], next: Call) => { - if (!obj[next.id]) { - obj[next.id] = true; - next.value = next.value || 1; - for (const node of data.nodes) { - if (next.source === node.id) { - next.sourceObj = node; - } - if (next.target === node.id) { - next.targetObj = node; - } - } - next.value = next.value || 1; - prev.push(next); - } - return prev; - }, []); - - this.calls = calls; - this.nodes = data.nodes; - }, async getCreateTaskData(serviceId: string) { const res: AxiosResponse = await graphql .query("getCreateTaskData") @@ -153,23 +94,6 @@ export const ebpfStore = defineStore({ }); return res.data; }, - async createNetworkTask(param: { - serviceId: string; - serviceInstanceId: string; - }) { - const res: AxiosResponse = await graphql - .query("newNetworkProfiling") - .params({ request: { instanceId: param.serviceInstanceId } }); - - if (res.data.errors) { - return res.data; - } - this.getTaskList({ - ...param, - targets: ["NETWORK"], - }); - return res.data; - }, async getTaskList(params: { serviceId: string; serviceInstanceId: string; @@ -182,27 +106,17 @@ export const ebpfStore = defineStore({ .query("getEBPFTasks") .params(params); - if (params.serviceInstanceId) { - this.networkTip = ""; - if (res.data.errors) { - return res.data; - } - this.networkTasks = res.data.data.queryEBPFTasks || []; - this.selectedNetworkTask = this.networkTasks[0] || {}; - this.setSelectedNetworkTask(this.selectedNetworkTask); - } else { - this.tip = ""; - if (res.data.errors) { - return res.data; - } - this.taskList = res.data.data.queryEBPFTasks || []; - this.selectedTask = this.taskList[0] || {}; - this.setSelectedTask(this.selectedTask); - if (!this.taskList.length) { - return res.data; - } - this.getEBPFSchedules({ taskId: this.taskList[0].taskId }); + this.tip = ""; + if (res.data.errors) { + return res.data; } + this.taskList = res.data.data.queryEBPFTasks || []; + this.selectedTask = this.taskList[0] || {}; + this.setSelectedTask(this.selectedTask); + if (!this.taskList.length) { + return res.data; + } + this.getEBPFSchedules({ taskId: this.taskList[0].taskId }); return res.data; }, async getEBPFSchedules(params: { taskId: string }) { @@ -260,23 +174,6 @@ export const ebpfStore = defineStore({ this.analyzeTrees = analysisEBPFResult.trees; return res.data; }, - async getProcessTopology(params: { - duration: any; - serviceInstanceId: string; - }) { - const res: AxiosResponse = await graphql - .query("getProcessTopology") - .params(params); - if (res.data.errors) { - this.nodes = []; - this.calls = []; - return res.data; - } - const { topology } = res.data.data; - - this.setTopology(topology); - return res.data; - }, }, }); diff --git a/src/store/modules/network-profiling.ts b/src/store/modules/network-profiling.ts new file mode 100644 index 00000000..b1bbedf9 --- /dev/null +++ b/src/store/modules/network-profiling.ts @@ -0,0 +1,154 @@ +/** + * 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 { defineStore } from "pinia"; +import { EBPFTaskList, ProcessNode } from "@/types/ebpf"; +import { store } from "@/store"; +import graphql from "@/graphql"; +import { AxiosResponse } from "axios"; +import { Call } from "@/types/topology"; +import { LayoutConfig } from "@/types/dashboard"; + +interface NetworkProfilingState { + networkTasks: EBPFTaskList[]; + networkTip: string; + selectedNetworkTask: Recordable; + nodes: ProcessNode[]; + calls: Call[]; + node: Nullable; + call: Nullable; + metricsLayout: LayoutConfig[]; + selectedMetric: Nullable; + activeMetricIndex: string; +} + +export const networkProfilingStore = defineStore({ + id: "networkProfiling", + state: (): NetworkProfilingState => ({ + networkTasks: [], + networkTip: "", + selectedNetworkTask: {}, + nodes: [], + calls: [], + node: null, + call: null, + metricsLayout: [], + selectedMetric: null, + activeMetricIndex: "", + }), + actions: { + setSelectedNetworkTask(task: EBPFTaskList) { + this.selectedNetworkTask = task || {}; + }, + setNode(node: Node) { + this.node = node; + }, + setLink(link: Call) { + this.call = link; + }, + setMetricsLayout(layout: LayoutConfig[]) { + this.metricsLayout = layout; + }, + setSelectedMetric(item: LayoutConfig) { + this.selectedMetric = item; + }, + setActiveItem(index: string) { + this.activeMetricIndex = index; + }, + setTopology(data: { nodes: ProcessNode[]; calls: Call[] }) { + const obj = {} as any; + const calls = (data.calls || []).reduce((prev: Call[], next: Call) => { + if (!obj[next.id]) { + obj[next.id] = true; + next.value = next.value || 1; + for (const node of data.nodes) { + if (next.source === node.id) { + next.sourceObj = node; + } + if (next.target === node.id) { + next.targetObj = node; + } + } + next.value = next.value || 1; + prev.push(next); + } + return prev; + }, []); + + this.calls = calls; + this.nodes = data.nodes; + }, + async createNetworkTask(param: { + serviceId: string; + serviceInstanceId: string; + }) { + const res: AxiosResponse = await graphql + .query("newNetworkProfiling") + .params({ request: { instanceId: param.serviceInstanceId } }); + + if (res.data.errors) { + return res.data; + } + this.getTaskList({ + ...param, + targets: ["NETWORK"], + }); + return res.data; + }, + async getTaskList(params: { + serviceId: string; + serviceInstanceId: string; + targets: string[]; + }) { + if (!params.serviceId) { + return new Promise((resolve) => resolve({})); + } + const res: AxiosResponse = await graphql + .query("getEBPFTasks") + .params(params); + + this.networkTip = ""; + if (res.data.errors) { + return res.data; + } + this.networkTasks = res.data.data.queryEBPFTasks || []; + this.selectedNetworkTask = this.networkTasks[0] || {}; + this.setSelectedNetworkTask(this.selectedNetworkTask); + return res.data; + }, + async getProcessTopology(params: { + duration: any; + serviceInstanceId: string; + }) { + const res: AxiosResponse = await graphql + .query("getProcessTopology") + .params(params); + if (res.data.errors) { + this.nodes = []; + this.calls = []; + return res.data; + } + const { topology } = res.data.data; + + this.setTopology(topology); + return res.data; + }, + }, +}); + +export function useNetworkProfilingStore(): any { + return networkProfilingStore(store); +} diff --git a/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue b/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue index d74e106a..919ce920 100644 --- a/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue +++ b/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue @@ -20,7 +20,7 @@ import type { PropType } from "vue"; import { ref, onMounted, watch } from "vue"; import * as d3 from "d3"; import { useI18n } from "vue-i18n"; -import { useEbpfStore } from "@/store/modules/ebpf"; +import { useNetworkProfilingStore } from "@/store/modules/network-profiling"; import { useDashboardStore } from "@/store/modules/dashboard"; import d3tip from "d3-tip"; import { @@ -47,7 +47,7 @@ const props = defineProps({ }); const { t } = useI18n(); const dashboardStore = useDashboardStore(); -const ebpfStore = useEbpfStore(); +const networkProfilingStore = useNetworkProfilingStore(); const height = ref(100); const width = ref(100); const simulation = ref(null); @@ -71,7 +71,7 @@ onMounted(() => { async function init() { svg.value = d3.select(chart.value).append("svg").attr("class", "process-svg"); - if (!ebpfStore.nodes.length) { + if (!networkProfilingStore.nodes.length) { return; } drawGraph(); @@ -94,8 +94,8 @@ function drawGraph() { graph.value.call(tip.value); simulation.value = simulationInit( d3, - ebpfStore.nodes, - ebpfStore.calls, + networkProfilingStore.nodes, + networkProfilingStore.calls, ticked ); node.value = graph.value.append("g").selectAll(".topo-node"); @@ -106,8 +106,8 @@ function drawGraph() { svg.value.on("click", (event: any) => { event.stopPropagation(); event.preventDefault(); - ebpfStore.setNode(null); - ebpfStore.setLink(null); + networkProfilingStore.setNode(null); + networkProfilingStore.setLink(null); dashboardStore.selectWidget(props.config); }); useThrottleFn(resize, 500)(); @@ -117,7 +117,10 @@ function update() { if (!node.value || !link.value) { return; } - node.value = node.value.data(ebpfStore.nodes, (d: ProcessNode) => d.id); + node.value = node.value.data( + networkProfilingStore.nodes, + (d: ProcessNode) => d.id + ); node.value.exit().remove(); node.value = nodeElement( d3, @@ -130,11 +133,14 @@ function update() { tip.value ).merge(node.value); // line element - link.value = link.value.data(ebpfStore.calls, (d: Call) => d.id); + link.value = link.value.data(networkProfilingStore.calls, (d: Call) => d.id); link.value.exit().remove(); link.value = linkElement(link.value.enter()).merge(link.value); // anchorElement - anchor.value = anchor.value.data(ebpfStore.calls, (d: Call) => d.id); + anchor.value = anchor.value.data( + networkProfilingStore.calls, + (d: Call) => d.id + ); anchor.value.exit().remove(); anchor.value = anchorElement( anchor.value.enter(), @@ -150,25 +156,28 @@ function update() { tip.value ).merge(anchor.value); // arrow marker - arrow.value = arrow.value.data(ebpfStore.calls, (d: Call) => d.id); + arrow.value = arrow.value.data( + networkProfilingStore.calls, + (d: Call) => d.id + ); arrow.value.exit().remove(); arrow.value = arrowMarker(arrow.value.enter()).merge(arrow.value); // force element - simulation.value.nodes(ebpfStore.nodes); + simulation.value.nodes(networkProfilingStore.nodes); simulation.value .force("link") - .links(ebpfStore.calls) + .links(networkProfilingStore.calls) .id((d: Call) => d.id); simulationSkip(d3, simulation.value, ticked); const loopMap: any = {}; - for (let i = 0; i < ebpfStore.calls.length; i++) { - const link: any = ebpfStore.calls[i]; + for (let i = 0; i < networkProfilingStore.calls.length; i++) { + const link: any = networkProfilingStore.calls[i]; link.loopFactor = 1; - for (let j = 0; j < ebpfStore.calls.length; j++) { + for (let j = 0; j < networkProfilingStore.calls.length; j++) { if (i === j || loopMap[i]) { continue; } - const otherLink = ebpfStore.calls[j]; + const otherLink = networkProfilingStore.calls[j]; if ( link.source.id === otherLink.target.id && link.target.id === otherLink.source.id @@ -189,8 +198,8 @@ function handleLinkClick(event: any, d: Call) { return; } event.stopPropagation(); - ebpfStore.setNode(null); - ebpfStore.setLink(d); + networkProfilingStore.setNode(null); + networkProfilingStore.setLink(d); } function ticked() { @@ -234,14 +243,14 @@ function resize() { async function freshNodes() { svg.value.selectAll(".svg-graph").remove(); - if (!ebpfStore.nodes.length) { + if (!networkProfilingStore.nodes.length) { return; } drawGraph(); update(); } watch( - () => ebpfStore.nodes, + () => networkProfilingStore.nodes, () => { freshNodes(); } diff --git a/src/views/dashboard/related/network-profiling/components/Schedules.vue b/src/views/dashboard/related/network-profiling/components/Schedules.vue index fa310bc4..6b6e7cae 100644 --- a/src/views/dashboard/related/network-profiling/components/Schedules.vue +++ b/src/views/dashboard/related/network-profiling/components/Schedules.vue @@ -21,14 +21,14 @@ limitations under the License. --> diff --git a/src/views/dashboard/related/network-profiling/components/metrics-panel/MetricWidget.vue b/src/views/dashboard/related/network-profiling/components/metrics-panel/MetricWidget.vue index feaea61d..1cb8d4dc 100644 --- a/src/views/dashboard/related/network-profiling/components/metrics-panel/MetricWidget.vue +++ b/src/views/dashboard/related/network-profiling/components/metrics-panel/MetricWidget.vue @@ -72,7 +72,7 @@ limitations under the License. -->