diff --git a/src/layout/components/SideBar.vue b/src/layout/components/SideBar.vue index e05e9af5..a343cd59 100644 --- a/src/layout/components/SideBar.vue +++ b/src/layout/components/SideBar.vue @@ -141,7 +141,6 @@ const filterMenus = (menus: any[]) => { .side-bar { background: #252a2f; height: 100%; - position: relative; margin-bottom: 100px; overflow-y: auto; overflow-x: hidden; @@ -174,7 +173,7 @@ span.collapse { .menu-control { position: absolute; top: 7px; - left: 200px; + left: 220px; cursor: pointer; transition: all 0.2s linear; z-index: 99; diff --git a/src/store/modules/network-profiling.ts b/src/store/modules/network-profiling.ts index 88cd54d4..2c45208c 100644 --- a/src/store/modules/network-profiling.ts +++ b/src/store/modules/network-profiling.ts @@ -92,15 +92,21 @@ export const networkProfilingStore = defineStore({ } return prev; }, []); - calls = calls.map((d: any) => { - d.sourceId = d.source; - d.targetId = d.target; - d.source = d.sourceObj; - d.target = d.targetObj; - delete d.sourceObj; - delete d.targetObj; - return d; - }); + const param = {} as any; + calls = data.calls.reduce((prev: (Call | any)[], next: Call | any) => { + if (param[next.targetId + next.sourceId]) { + next.lowerArc = true; + } + param[next.sourceId + next.targetId] = true; + next.sourceId = next.source; + next.targetId = next.target; + next.source = next.sourceObj; + next.target = next.targetObj; + delete next.sourceObj; + delete next.targetObj; + prev.push(next); + return prev; + }, []); this.calls = calls; this.nodes = data.nodes; }, diff --git a/src/types/ebpf.d.ts b/src/types/ebpf.d.ts index 5dfca0ef..e9986ef1 100644 --- a/src/types/ebpf.d.ts +++ b/src/types/ebpf.d.ts @@ -74,4 +74,6 @@ export type ProcessNode = { serviceInstanceName: string; name: string; isReal: boolean; + x?: number; + y?: number; }; diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index ec582664..6d986f2e 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -228,6 +228,11 @@ export default defineComponent({ watch( () => [selectorStore.currentProcess, selectorStore.currentDestProcess], () => { + if ( + !(selectorStore.currentDestProcess && selectorStore.currentProcess) + ) { + return; + } if (dashboardStore.entity === EntityType[7].value) { queryMetrics(); } diff --git a/src/views/dashboard/related/components/utils/zoom.ts b/src/views/dashboard/related/components/utils/zoom.ts index 9227089c..6ba31c04 100644 --- a/src/views/dashboard/related/components/utils/zoom.ts +++ b/src/views/dashboard/related/components/utils/zoom.ts @@ -19,11 +19,11 @@ export default (d3: any, graph: any, diff: number[]) => d3 .zoom() .scaleExtent([0.3, 10]) - .on("zoom", (event: any) => { + .on("zoom", (d: any) => { graph.attr( "transform", - `translate(${event.transform.x + diff[0]},${ - event.transform.y + diff[1] - })scale(${event.transform.k})` + `translate(${d.transform.x + diff[0]},${ + d.transform.y + diff[1] + })scale(${d.transform.k})` ); }); diff --git a/src/views/dashboard/related/network-profiling/Content.vue b/src/views/dashboard/related/network-profiling/Content.vue index f041b75f..d9d615ad 100644 --- a/src/views/dashboard/related/network-profiling/Content.vue +++ b/src/views/dashboard/related/network-profiling/Content.vue @@ -53,7 +53,7 @@ const { t } = useI18n(); height: 100%; flex-grow: 2; min-width: 700px; - overflow: auto; + overflow: hidden; position: relative; width: calc(100% - 330px); } diff --git a/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts b/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts index 858e090a..26c94e4c 100644 --- a/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts +++ b/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts @@ -17,96 +17,6 @@ import icons from "@/assets/img/icons"; import { Call } from "@/types/topology"; -export const linkElement = (graph: any) => { - const linkEnter = graph - .append("path") - .attr("class", "topo-call") - .attr("marker-end", "url(#arrow)") - .attr("stroke", "#97B0F8") - .attr("d", (d: Call) => { - const controlPos = computeControlPoint( - [d.source.x, d.source.y - 5], - [d.target.x, d.target.y - 5], - 0.5 - ); - if (d.lowerArc) { - controlPos[1] = - Math.abs(controlPos[1]) < 50 - ? -controlPos[1] + 90 - : -controlPos[1] - 10; - } - return ( - "M" + - d.source.x + - " " + - (d.source.y - 5) + - " " + - "Q" + - controlPos[0] + - " " + - controlPos[1] + - " " + - d.target.x + - " " + - (d.target.y - 5) - ); - }); - return linkEnter; -}; -export const anchorElement = (graph: any, funcs: any, tip: any) => { - const linkEnter = graph - .append("g") - .attr("class", "topo-line-anchor") - .on("mouseover", function (event: unknown, d: unknown) { - tip.html(funcs.tipHtml).show(d, this); - }) - .on("mouseout", function () { - tip.hide(this); - }) - .on("click", (event: unknown, d: unknown) => { - funcs.handleLinkClick(event, d); - }); - linkEnter - .append("image") - .attr("width", 15) - .attr("height", 15) - .attr("x", (d: Call) => { - const p = getMidpoint(d); - return p[0] - 8; - }) - .attr("y", (d: Call) => { - const p = getMidpoint(d); - return p[1] - 13; - }) - .attr("xlink:href", (d: Call) => { - const types = [...d.sourceComponents, ...d.targetComponents]; - if (types.includes("tcp") || types.includes("http")) { - return icons.HTTPDARK; - } - if (types.includes("https") || types.includes("tls")) { - return icons.HTTPS; - } - }); - return linkEnter; -}; -export const arrowMarker = (graph: any) => { - const defs = graph.append("defs"); - const arrow = defs - .append("marker") - .attr("id", "arrow") - .attr("class", "topo-line-arrow") - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", "8") - .attr("markerHeight", "8") - .attr("viewBox", "0 0 12 12") - .attr("refX", "10") - .attr("refY", "6") - .attr("orient", "auto"); - const arrowPath = "M2,2 L10,6 L2,10 L6,6 L2,2"; - - arrow.append("path").attr("d", arrowPath).attr("fill", "#97B0F8"); - return arrow; -}; // Control Point coordinates of quadratic Bezier curve function computeControlPoint(ps: number[], pe: number[], arc = 0.5) { const deltaX = pe[0] - ps[0]; @@ -137,15 +47,20 @@ function quadraticBezier( const y = (1 - t) * (1 - t) * ps.y + 2 * t * (1 - t) * pc.y + t * t * pe.y; return [x, y]; } -function getMidpoint(d: Call) { +export function getMidpoint(d: Call) { + if (isNaN(d.source.x) || isNaN(d.source.y)) { + return [0, 0]; + } + if (isNaN(d.target.x) || isNaN(d.target.y)) { + return [0, 0]; + } const controlPos = computeControlPoint( [d.source.x, d.source.y], [d.target.x, d.target.y], 0.5 ); if (d.lowerArc) { - controlPos[1] = - Math.abs(controlPos[1]) < 50 ? -controlPos[1] + 100 : -controlPos[1] - 10; + controlPos[1] = -controlPos[1]; } const p = quadraticBezier( 0.5, @@ -155,3 +70,43 @@ function getMidpoint(d: Call) { ); return p; } +export function linkPath(d: Call) { + if (isNaN(d.source.x) || isNaN(d.source.y)) { + return; + } + if (isNaN(d.target.x) || isNaN(d.target.y)) { + return; + } + const controlPos = computeControlPoint( + [d.source.x, d.source.y - 5], + [d.target.x, d.target.y - 5], + 0.5 + ); + if (d.lowerArc) { + controlPos[1] = -controlPos[1] - 10; + } + return ( + "M" + + d.source.x + + " " + + (d.source.y - 5) + + " " + + "Q" + + controlPos[0] + + " " + + controlPos[1] + + " " + + d.target.x + + " " + + (d.target.y - 5) + ); +} +export function getAnchor(d: Call) { + const types = [...d.sourceComponents, ...d.targetComponents]; + if (types.includes("tcp") || types.includes("http")) { + return icons.HTTPDARK; + } + if (types.includes("https") || types.includes("tls")) { + return icons.HTTPS; + } +} diff --git a/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts b/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts deleted file mode 100644 index 23a033d4..00000000 --- a/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts +++ /dev/null @@ -1,54 +0,0 @@ -/** - * 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 icons from "@/assets/img/icons"; -import { Node } from "@/types/topology"; - -export default (d3: any, graph: any, funcs: any, tip: any) => { - const nodeEnter = graph - .append("g") - .call( - d3 - .drag() - .on("start", funcs.dragstart) - .on("drag", funcs.dragged) - .on("end", funcs.dragended) - ) - .on("mouseover", function (event: unknown, d: Node) { - tip.html(funcs.tipHtml).show(d, this); - }) - .on("mouseout", function () { - tip.hide(this); - }); - nodeEnter - .append("image") - .attr("width", 35) - .attr("height", 35) - .attr("x", (d: any) => d.x - 15) - .attr("y", (d: any) => d.y - 15) - .attr("style", "cursor: move;") - .attr("xlink:href", icons.CUBE); - nodeEnter - .append("text") - .attr("fill", "#000") - .attr("text-anchor", "middle") - .attr("x", (d: any) => d.x) - .attr("y", (d: any) => d.y + 28) - .text((d: { name: string }) => - d.name.length > 10 ? `${d.name.substring(0, 10)}...` : d.name - ); - return nodeEnter; -}; diff --git a/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue b/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue index 23df6290..a3316d90 100644 --- a/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue +++ b/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue @@ -13,13 +13,103 @@ 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. -->