mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-14 09:00:50 +00:00
update graph
This commit is contained in:
parent
0f8c522cfd
commit
5f763dafb9
@ -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;
|
||||
},
|
||||
},
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -106,7 +106,6 @@ watch(
|
||||
.time-ranges {
|
||||
width: calc(100% - 5px);
|
||||
margin: 0 5px 5px 0;
|
||||
height: 100%;
|
||||
min-height: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
</style>
|
||||
|
@ -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,
|
||||
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,
|
||||
},
|
||||
});
|
||||
if (res.errors) {
|
||||
ElMessage.error(res.errors);
|
||||
}
|
||||
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>
|
||||
|
Loading…
Reference in New Issue
Block a user