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;
|
aggregateType: string;
|
||||||
nodes: ProcessNode[];
|
nodes: ProcessNode[];
|
||||||
calls: Call[];
|
calls: Call[];
|
||||||
|
node: Nullable<ProcessNode>;
|
||||||
|
call: Nullable<Call>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ebpfStore = defineStore({
|
export const ebpfStore = defineStore({
|
||||||
@ -61,6 +63,8 @@ export const ebpfStore = defineStore({
|
|||||||
aggregateType: "COUNT",
|
aggregateType: "COUNT",
|
||||||
nodes: [],
|
nodes: [],
|
||||||
calls: [],
|
calls: [],
|
||||||
|
node: null,
|
||||||
|
call: null,
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
setSelectedTask(task: EBPFTaskList) {
|
setSelectedTask(task: EBPFTaskList) {
|
||||||
@ -75,6 +79,35 @@ export const ebpfStore = defineStore({
|
|||||||
setAnalyzeTrees(tree: AnalyzationTrees[]) {
|
setAnalyzeTrees(tree: AnalyzationTrees[]) {
|
||||||
this.analyzeTrees = tree;
|
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) {
|
async getCreateTaskData(serviceId: string) {
|
||||||
const res: AxiosResponse = await graphql
|
const res: AxiosResponse = await graphql
|
||||||
.query("getCreateTaskData")
|
.query("getCreateTaskData")
|
||||||
@ -223,7 +256,9 @@ export const ebpfStore = defineStore({
|
|||||||
this.calls = [];
|
this.calls = [];
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
const topo = res.data.data;
|
const { topology } = res.data.data;
|
||||||
|
|
||||||
|
this.setTopology(topology);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -45,13 +45,12 @@ import ProcessTopology from "./components/ProcessTopology.vue";
|
|||||||
|
|
||||||
.item {
|
.item {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: auto;
|
height: calc(100% - 210px);
|
||||||
height: calc(100% - 100px);
|
background-color: #333840;
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedules {
|
.schedules {
|
||||||
min-height: 90px;
|
height: 200px;
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
padding-right: 10px;
|
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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div ref="chart" class="topology"></div>
|
<div ref="chart" class="micro-topo-chart"></div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted, watch } from "vue";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { useEbpfStore } from "@/store/modules/ebpf";
|
import { useEbpfStore } from "@/store/modules/ebpf";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
|
||||||
import d3tip from "d3-tip";
|
import d3tip from "d3-tip";
|
||||||
import { simulationInit, simulationSkip } from "./utils/simulation";
|
import { simulationInit, simulationSkip } from "./utils/simulation";
|
||||||
import { linkElement, anchorElement, arrowMarker } from "./utils/linkElement";
|
import { linkElement, anchorElement, arrowMarker } from "./utils/linkElement";
|
||||||
@ -40,10 +38,8 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const selectorStore = useSelectorStore();
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
const appStore = useAppStoreWithOut();
|
|
||||||
const height = ref<number>(100);
|
const height = ref<number>(100);
|
||||||
const width = ref<number>(100);
|
const width = ref<number>(100);
|
||||||
const simulation = ref<any>(null);
|
const simulation = ref<any>(null);
|
||||||
@ -61,20 +57,25 @@ onMounted(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function init() {
|
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");
|
svg.value = d3.select(chart.value).append("svg").attr("class", "process-svg");
|
||||||
|
window.addEventListener("resize", resize);
|
||||||
|
if (!ebpfStore.nodes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
drawGraph();
|
drawGraph();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawGraph() {
|
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]);
|
tip.value = (d3tip as any)().attr("class", "d3-tip").offset([-8, 0]);
|
||||||
graph.value = svg.value
|
graph.value = svg.value
|
||||||
.append("g")
|
.append("g")
|
||||||
@ -111,10 +112,6 @@ function update() {
|
|||||||
d3,
|
d3,
|
||||||
node.value.enter(),
|
node.value.enter(),
|
||||||
{
|
{
|
||||||
// dragstart: dragstart,
|
|
||||||
// dragged: dragged,
|
|
||||||
// dragended: dragended,
|
|
||||||
handleNodeClick: handleNodeClick,
|
|
||||||
tipHtml: (data: ProcessNode) => {
|
tipHtml: (data: ProcessNode) => {
|
||||||
return ` <div class="mb-5"><span class="grey">name: </span>${data.name}</div>`;
|
return ` <div class="mb-5"><span class="grey">name: </span>${data.name}</div>`;
|
||||||
},
|
},
|
||||||
@ -206,31 +203,42 @@ function ticked() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTopology() {
|
function resize() {
|
||||||
const serviceInstanceId =
|
const dom = chart.value?.getBoundingClientRect() || {
|
||||||
(selectorStore.currentPod && selectorStore.currentPod.id) || "";
|
height: 40,
|
||||||
ebpfStore.getProcessTopology({
|
width: 0,
|
||||||
serviceInstanceId,
|
};
|
||||||
duration: appStore.durationTime,
|
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 }) {
|
async function freshNodes() {
|
||||||
ebpfStore.setNode(d);
|
svg.value.selectAll(".svg-graph").remove();
|
||||||
ebpfStore.setLink(null);
|
if (!ebpfStore.nodes.length) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
drawGraph();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => ebpfStore.nodes,
|
||||||
|
() => {
|
||||||
|
freshNodes();
|
||||||
|
}
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.topology {
|
.micro-topo-chart {
|
||||||
width: calc(100% - 5px);
|
width: calc(100% - 10px);
|
||||||
margin: 0 5px 5px 0;
|
margin: 0 5px 5px 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
min-height: 150px;
|
min-height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.topo-svg {
|
.process-svg {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 5px);
|
height: calc(100% - 10px);
|
||||||
cursor: move;
|
cursor: move;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -106,7 +106,6 @@ watch(
|
|||||||
.time-ranges {
|
.time-ranges {
|
||||||
width: calc(100% - 5px);
|
width: calc(100% - 5px);
|
||||||
margin: 0 5px 5px 0;
|
margin: 0 5px 5px 0;
|
||||||
height: 100%;
|
height: 150px;
|
||||||
min-height: 150px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -85,10 +85,14 @@ import { useSelectorStore } from "@/store/modules/selectors";
|
|||||||
import { EBPFTaskList } from "@/types/ebpf";
|
import { EBPFTaskList } from "@/types/ebpf";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import TaskDetails from "../../components/TaskDetails.vue";
|
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 { t } = useI18n();
|
||||||
const selectorStore = useSelectorStore();
|
const selectorStore = useSelectorStore();
|
||||||
const ebpfStore = useEbpfStore();
|
const ebpfStore = useEbpfStore();
|
||||||
|
const appStore = useAppStoreWithOut();
|
||||||
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
const dateFormat = (date: number, pattern = "YYYY-MM-DD HH:mm:ss") =>
|
||||||
dayjs(date).format(pattern);
|
dayjs(date).format(pattern);
|
||||||
const viewDetail = ref<boolean>(false);
|
const viewDetail = ref<boolean>(false);
|
||||||
@ -97,12 +101,37 @@ fetchTasks();
|
|||||||
|
|
||||||
async function changeTask(item: EBPFTaskList) {
|
async function changeTask(item: EBPFTaskList) {
|
||||||
ebpfStore.setSelectedNetworkTask(item);
|
ebpfStore.setSelectedNetworkTask(item);
|
||||||
const res = await ebpfStore.getEBPFSchedules({
|
getTopology();
|
||||||
taskId: item.taskId,
|
|
||||||
});
|
|
||||||
if (res.errors) {
|
|
||||||
ElMessage.error(res.errors);
|
|
||||||
}
|
}
|
||||||
|
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() {
|
async function createTask() {
|
||||||
const serviceId =
|
const serviceId =
|
||||||
@ -132,8 +161,9 @@ async function fetchTasks() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (res.errors) {
|
if (res.errors) {
|
||||||
ElMessage.error(res.errors);
|
return ElMessage.error(res.errors);
|
||||||
}
|
}
|
||||||
|
getTopology();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
Loading…
Reference in New Issue
Block a user