update graph

This commit is contained in:
Fine 2022-08-09 20:02:02 +08:00
parent 0f8c522cfd
commit 5f763dafb9
5 changed files with 116 additions and 45 deletions

View File

@ -42,6 +42,8 @@ interface EbpfStore {
aggregateType: string;
nodes: ProcessNode[];
calls: Call[];
node: Nullable<ProcessNode>;
call: Nullable<Call>;
}
export const ebpfStore = defineStore({
@ -61,6 +63,8 @@ export const ebpfStore = defineStore({
aggregateType: "COUNT",
nodes: [],
calls: [],
node: null,
call: null,
}),
actions: {
setSelectedTask(task: EBPFTaskList) {
@ -75,6 +79,35 @@ export const ebpfStore = defineStore({
setAnalyzeTrees(tree: AnalyzationTrees[]) {
this.analyzeTrees = tree;
},
setNode(node: Node) {
this.node = node;
},
setLink(link: Call) {
this.call = link;
},
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")
@ -223,7 +256,9 @@ export const ebpfStore = defineStore({
this.calls = [];
return res.data;
}
const topo = res.data.data;
const { topology } = res.data.data;
this.setTopology(topology);
return res.data;
},
},

View File

@ -45,13 +45,12 @@ import ProcessTopology from "./components/ProcessTopology.vue";
.item {
width: 100%;
overflow: auto;
height: calc(100% - 100px);
padding-bottom: 10px;
height: calc(100% - 210px);
background-color: #333840;
}
.schedules {
min-height: 90px;
height: 200px;
border-bottom: 1px solid #ccc;
padding-right: 10px;
}

View File

@ -13,17 +13,15 @@ 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 ref="chart" class="topology"></div>
<div ref="chart" class="micro-topo-chart"></div>
</template>
<script lang="ts" setup>
import type { PropType } from "vue";
import { ref, onMounted } 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 { useSelectorStore } from "@/store/modules/selectors";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app";
import d3tip from "d3-tip";
import { simulationInit, simulationSkip } from "./utils/simulation";
import { linkElement, anchorElement, arrowMarker } from "./utils/linkElement";
@ -40,10 +38,8 @@ const props = defineProps({
},
});
const { t } = useI18n();
const selectorStore = useSelectorStore();
const dashboardStore = useDashboardStore();
const ebpfStore = useEbpfStore();
const appStore = useAppStoreWithOut();
const height = ref<number>(100);
const width = ref<number>(100);
const simulation = ref<any>(null);
@ -61,20 +57,25 @@ onMounted(() => {
});
async function init() {
await getTopology();
const dom = document.querySelector(".topology")?.getBoundingClientRect() || {
height: 40,
width: 0,
};
height.value = dom.height - 40;
width.value = dom.width;
svg.value = d3.select(chart.value).append("svg").attr("class", "process-svg");
window.addEventListener("resize", resize);
if (!ebpfStore.nodes.length) {
return;
}
drawGraph();
update();
}
function drawGraph() {
const dom = document
.querySelector(".micro-topo-chart")
?.getBoundingClientRect() || {
height: 40,
width: 0,
};
height.value = dom.height - 40;
width.value = dom.width;
svg.value.attr("height", height.value).attr("width", width.value);
tip.value = (d3tip as any)().attr("class", "d3-tip").offset([-8, 0]);
graph.value = svg.value
.append("g")
@ -111,10 +112,6 @@ function update() {
d3,
node.value.enter(),
{
// dragstart: dragstart,
// dragged: dragged,
// dragended: dragended,
handleNodeClick: handleNodeClick,
tipHtml: (data: ProcessNode) => {
return ` <div class="mb-5"><span class="grey">name: </span>${data.name}</div>`;
},
@ -206,31 +203,42 @@ function ticked() {
);
}
function getTopology() {
const serviceInstanceId =
(selectorStore.currentPod && selectorStore.currentPod.id) || "";
ebpfStore.getProcessTopology({
serviceInstanceId,
duration: appStore.durationTime,
});
function resize() {
const dom = chart.value?.getBoundingClientRect() || {
height: 40,
width: 0,
};
height.value = dom.height - 40;
width.value = dom.width;
svg.value.attr("height", height.value).attr("width", width.value);
}
function handleNodeClick(d: Node & { x: number; y: number }) {
ebpfStore.setNode(d);
ebpfStore.setLink(null);
async function freshNodes() {
svg.value.selectAll(".svg-graph").remove();
if (!ebpfStore.nodes.length) {
return;
}
drawGraph();
update();
}
watch(
() => ebpfStore.nodes,
() => {
freshNodes();
}
);
</script>
<style lang="scss" scoped>
.topology {
width: calc(100% - 5px);
.micro-topo-chart {
width: calc(100% - 10px);
margin: 0 5px 5px 0;
height: 100%;
min-height: 150px;
}
.topo-svg {
.process-svg {
width: 100%;
height: calc(100% - 5px);
height: calc(100% - 10px);
cursor: move;
}
</style>

View File

@ -106,7 +106,6 @@ watch(
.time-ranges {
width: calc(100% - 5px);
margin: 0 5px 5px 0;
height: 100%;
min-height: 150px;
height: 150px;
}
</style>

View File

@ -85,10 +85,14 @@ import { useSelectorStore } from "@/store/modules/selectors";
import { EBPFTaskList } from "@/types/ebpf";
import { ElMessage } from "element-plus";
import TaskDetails from "../../components/TaskDetails.vue";
import dateFormatStep from "@/utils/dateFormat";
import getLocalTime from "@/utils/localtime";
import { useAppStoreWithOut } from "@/store/modules/app";
const { t } = useI18n();
const selectorStore = useSelectorStore();
const ebpfStore = useEbpfStore();
const appStore = useAppStoreWithOut();
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
dayjs(date).format(pattern);
const viewDetail = ref<boolean>(false);
@ -97,12 +101,37 @@ fetchTasks();
async function changeTask(item: EBPFTaskList) {
ebpfStore.setSelectedNetworkTask(item);
const res = await ebpfStore.getEBPFSchedules({
taskId: item.taskId,
});
if (res.errors) {
ElMessage.error(res.errors);
getTopology();
}
async function getTopology() {
const serviceInstanceId =
(selectorStore.currentPod && selectorStore.currentPod.id) || "";
const resp = await ebpfStore.getProcessTopology({
serviceInstanceId,
duration: {
start: dateFormatStep(
getLocalTime(
appStore.utc,
new Date(ebpfStore.selectedNetworkTask.taskStartTime)
),
appStore.duration.step,
true
),
end: dateFormatStep(
getLocalTime(
appStore.utc,
new Date(
ebpfStore.selectedNetworkTask.taskStartTime +
ebpfStore.selectedNetworkTask.fixedTriggerDuration * 1000
)
),
appStore.duration.step,
true
),
step: appStore.duration.step,
},
});
return resp;
}
async function createTask() {
const serviceId =
@ -132,8 +161,9 @@ async function fetchTasks() {
});
if (res.errors) {
ElMessage.error(res.errors);
return ElMessage.error(res.errors);
}
getTopology();
}
</script>
<style lang="scss" scoped>