From a4fc5192ac1570a7892feea51ef8c6d967847215 Mon Sep 17 00:00:00 2001 From: Fine0830 Date: Tue, 23 Aug 2022 13:41:05 +0800 Subject: [PATCH] feat: Implement the network profiling widget (#132) --- package-lock.json | 30 +- package.json | 2 +- src/assets/icons/setting_empty.svg | 16 + src/assets/icons/time_range.svg | 6 +- src/layout/components/NavBar.vue | 42 +- src/locales/lang/en.ts | 1 + src/locales/lang/es.ts | 1 + src/locales/lang/zh.ts | 1 + src/router/dashboard.ts | 8 + src/store/modules/app.ts | 11 +- src/store/modules/network-profiling.ts | 183 +++++++ src/utils/dateFormat.ts | 4 + src/views/Settings.vue | 8 +- src/views/alarm/Content.vue | 4 +- .../dashboard/controls/NetworkProfiling.vue | 97 ++++ src/views/dashboard/controls/index.ts | 2 + src/views/dashboard/controls/tab.ts | 2 + src/views/dashboard/data.ts | 7 +- src/views/dashboard/panel/Tool.vue | 80 ++- .../related/components/TaskDetails.vue | 1 - .../components/{D3Graph => utils}/zoom.ts | 15 +- .../related/ebpf/components/EBPFSchedules.vue | 4 +- .../related/ebpf/components/TaskList.vue | 4 +- .../related/log/LogTable/LogBrowser.vue | 5 +- .../related/log/LogTable/LogDetail.vue | 4 +- .../related/log/LogTable/LogService.vue | 4 +- .../related/network-profiling/Content.vue | 59 ++ .../components/Graph/layout.ts | 144 +++++ .../components/Graph/linkProcess.ts | 126 +++++ .../components/Graph/nodeProcess.ts | 54 ++ .../components/ProcessTopology.vue | 503 ++++++++++++++++++ .../network-profiling/components/Settings.vue | 88 +++ .../network-profiling/components/Tasks.vue | 282 ++++++++++ .../network-profiling/components/TimeLine.vue | 178 +++++++ .../profile/components/SegmentList.vue | 4 +- .../related/profile/components/TaskList.vue | 8 +- .../related/topology/components/Graph.vue | 17 +- .../components/utils}/linkElement.ts | 0 .../components/utils}/nodeElement.ts | 0 .../components/utils}/simulation.ts | 8 +- src/views/dashboard/related/trace/Detail.vue | 7 +- .../dashboard/related/trace/TraceList.vue | 4 +- .../trace/components/D3Graph/SpanDetail.vue | 4 +- .../trace/components/Table/TableItem.vue | 7 +- vue.config.js | 3 + 45 files changed, 1899 insertions(+), 139 deletions(-) create mode 100644 src/assets/icons/setting_empty.svg create mode 100644 src/store/modules/network-profiling.ts create mode 100644 src/views/dashboard/controls/NetworkProfiling.vue rename src/views/dashboard/related/components/{D3Graph => utils}/zoom.ts (76%) create mode 100644 src/views/dashboard/related/network-profiling/Content.vue create mode 100644 src/views/dashboard/related/network-profiling/components/Graph/layout.ts create mode 100644 src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts create mode 100644 src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts create mode 100644 src/views/dashboard/related/network-profiling/components/ProcessTopology.vue create mode 100644 src/views/dashboard/related/network-profiling/components/Settings.vue create mode 100644 src/views/dashboard/related/network-profiling/components/Tasks.vue create mode 100644 src/views/dashboard/related/network-profiling/components/TimeLine.vue rename src/views/dashboard/related/{components/D3Graph => topology/components/utils}/linkElement.ts (100%) rename src/views/dashboard/related/{components/D3Graph => topology/components/utils}/nodeElement.ts (100%) rename src/views/dashboard/related/{components/D3Graph => topology/components/utils}/simulation.ts (92%) diff --git a/package-lock.json b/package-lock.json index 59d7203e..4009b611 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "skywalking-booster-ui", - "version": "9.1.0", + "version": "9.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "skywalking-booster-ui", - "version": "9.1.0", + "version": "9.3.0", "dependencies": { "axios": "^0.24.0", "d3": "^7.3.0", @@ -7259,14 +7259,20 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001299", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz", - "integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==", + "version": "1.0.30001379", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001379.tgz", + "integrity": "sha512-zXf+qxuN8OJrK5Bl5HbJg8cc5/Zm01WNW4ooVWUh92YlKqQZW3fwN5lXLB+kI8wkP5vTWkIIN+rutZuJhf4ykw==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] }, "node_modules/capture-exit": { "version": "2.0.0", @@ -34806,9 +34812,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001299", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001299.tgz", - "integrity": "sha512-iujN4+x7QzqA2NCSrS5VUy+4gLmRd4xv6vbBBsmfVqTx8bLAD8097euLqQgKxSVLvxjSDcvF1T/i9ocgnUFexw==", + "version": "1.0.30001379", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001379.tgz", + "integrity": "sha512-zXf+qxuN8OJrK5Bl5HbJg8cc5/Zm01WNW4ooVWUh92YlKqQZW3fwN5lXLB+kI8wkP5vTWkIIN+rutZuJhf4ykw==", "dev": true }, "capture-exit": { diff --git a/package.json b/package.json index 2877874e..84998d51 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "skywalking-booster-ui", - "version": "9.1.0", + "version": "9.3.0", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/src/assets/icons/setting_empty.svg b/src/assets/icons/setting_empty.svg new file mode 100644 index 00000000..5384b35d --- /dev/null +++ b/src/assets/icons/setting_empty.svg @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/src/assets/icons/time_range.svg b/src/assets/icons/time_range.svg index 5b5238ba..7fe09afd 100644 --- a/src/assets/icons/time_range.svg +++ b/src/assets/icons/time_range.svg @@ -12,4 +12,8 @@ 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. --> - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/src/layout/components/NavBar.vue b/src/layout/components/NavBar.vue index 1f3fe066..19355743 100644 --- a/src/layout/components/NavBar.vue +++ b/src/layout/components/NavBar.vue @@ -13,7 +13,7 @@ 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. --> diff --git a/src/views/dashboard/controls/index.ts b/src/views/dashboard/controls/index.ts index 4c7754b1..70cb7f9c 100644 --- a/src/views/dashboard/controls/index.ts +++ b/src/views/dashboard/controls/index.ts @@ -24,6 +24,7 @@ import Text from "./Text.vue"; import Ebpf from "./Ebpf.vue"; import DemandLog from "./DemandLog.vue"; import Event from "./Event.vue"; +import NetworkProfiling from "./NetworkProfiling.vue"; import TimeRange from "./TimeRange.vue"; export default { @@ -37,5 +38,6 @@ export default { Ebpf, DemandLog, Event, + NetworkProfiling, TimeRange, }; diff --git a/src/views/dashboard/controls/tab.ts b/src/views/dashboard/controls/tab.ts index 07f07abf..f081a10d 100644 --- a/src/views/dashboard/controls/tab.ts +++ b/src/views/dashboard/controls/tab.ts @@ -23,6 +23,7 @@ import Text from "./Text.vue"; import Ebpf from "./Ebpf.vue"; import DemandLog from "./DemandLog.vue"; import Event from "./Event.vue"; +import NetworkProfiling from "./NetworkProfiling.vue"; import TimeRange from "./TimeRange.vue"; export default { @@ -35,5 +36,6 @@ export default { Ebpf, DemandLog, Event, + NetworkProfiling, TimeRange, }; diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index 5e68d848..e79af1c0 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -15,7 +15,7 @@ * limitations under the License. */ export const dragIgnoreFrom = - "svg.d3-trace-tree, .dragger, .micro-topo-chart, .schedules, .vis-item, .vis-timeline"; + "svg.d3-trace-tree, .dragger, .micro-topo-chart, .schedules, .vis-item, .vis-timeline, .process-svg"; export const PodsChartTypes = ["EndpointList", "InstanceList"]; @@ -198,6 +198,11 @@ export const InstanceTools = [ { name: "assignment", content: "Add Log", id: "addLog" }, { name: "demand", content: "Add On Demand Log", id: "addDemandLog" }, { name: "event", content: "Add Event", id: "addEvent" }, + { + name: "timeline", + content: "Add Network Profiling", + id: "addNetworkProfiling", + }, ]; export const EndpointTools = [ { name: "playlist_add", content: "Add Widget", id: "addWidget" }, diff --git a/src/views/dashboard/panel/Tool.vue b/src/views/dashboard/panel/Tool.vue index 46ee3a36..b0e72cbc 100644 --- a/src/views/dashboard/panel/Tool.vue +++ b/src/views/dashboard/panel/Tool.vue @@ -287,7 +287,7 @@ async function setSourceSelector() { await selectorStore.getService(String(params.serviceId)); states.currentService = selectorStore.currentService.value; const e = String(params.entity).split("Relation")[0]; - await fetchPods(e, selectorStore.currentService.id, false); + await fetchPods(e, selectorStore.currentService.id, true); if (!(selectorStore.pods.length && selectorStore.pods[0])) { selectorStore.setCurrentPod(null); states.currentPod = ""; @@ -295,32 +295,25 @@ async function setSourceSelector() { return; } const pod = params.podId || selectorStore.pods[0].id; - let currentPod; - if (states.currentPod) { - currentPod = selectorStore.pods.find( - (d: { label: string }) => d.label === states.currentPod - ); - } else { - currentPod = selectorStore.pods.find((d: { id: string }) => d.id === pod); - } + const currentPod = selectorStore.pods.find( + (d: { id: string }) => d.id === pod + ); if (!currentPod) { + selectorStore.setCurrentProcess(null); + states.currentProcess = ""; return; } selectorStore.setCurrentPod(currentPod); states.currentPod = currentPod.label; - const process = - params.processId || - (selectorStore.processes.length && selectorStore.processes[0].id); - let currentProcess; - if (states.currentProcess) { - currentProcess = selectorStore.processes.find( - (d: { label: string }) => d.label === states.currentProcess - ); - } else { - currentProcess = selectorStore.processes.find( - (d: { id: string }) => d.id === process - ); + if (!(selectorStore.processes.length && selectorStore.processes[0])) { + selectorStore.setCurrentProcess(null); + states.currentProcess = ""; + return; } + const process = params.processId || selectorStore.processes[0].id; + const currentProcess = selectorStore.processes.find( + (d: { id: string }) => d.id === process + ); if (currentProcess) { selectorStore.setCurrentProcess(currentProcess); states.currentProcess = currentProcess.label; @@ -333,7 +326,7 @@ async function setDestSelector() { await fetchPods( String(params.entity), selectorStore.currentDestService.id, - false + true ); if (!(selectorStore.destPods.length && selectorStore.destPods[0])) { selectorStore.setCurrentDestPod(null); @@ -341,36 +334,27 @@ async function setDestSelector() { return; } const destPod = params.destPodId || selectorStore.destPods[0].id; - let currentDestPod = { label: "" }; - if (states.currentDestPod) { - currentDestPod = selectorStore.pods.find( - (d: { label: string }) => d.label === states.currentDestPod - ); - } else { - currentDestPod = selectorStore.destPods.find( - (d: { id: string }) => d.id === destPod - ); - } + const currentDestPod = selectorStore.destPods.find( + (d: { id: string }) => d.id === destPod + ); if (!currentDestPod) { + states.currentDestProcess = ""; + selectorStore.setCurrentProcess(null); return; } selectorStore.setCurrentDestPod(currentDestPod); states.currentDestPod = currentDestPod.label; const destProcess = params.destProcessId || selectorStore.destProcesses[0].id; - let currentDestProcess; - if (states.currentDestProcess) { - currentDestProcess = selectorStore.destProcesses.find( - (d: { label: string }) => d.label === states.currentProcess - ); - } else { - currentDestProcess = selectorStore.destProcesses.find( - (d: { id: string }) => d.id === destProcess - ); - } - if (currentDestProcess) { - selectorStore.setCurrentProcess(currentDestProcess); - states.currentProcess = currentDestProcess.label; + const currentDestProcess = selectorStore.destProcesses.find( + (d: { id: string }) => d.id === destProcess + ); + if (!currentDestProcess) { + states.currentDestProcess = ""; + selectorStore.setCurrentProcess(null); + return; } + selectorStore.setCurrentProcess(currentDestProcess); + states.currentDestProcess = currentDestProcess.label; } async function getServices() { @@ -562,6 +546,9 @@ function setTabControls(id: string) { case "addEvent": dashboardStore.addTabControls("Event"); break; + case "addNetworkProfiling": + dashboardStore.addTabControls("NetworkProfiling"); + break; case "addTimeRange": dashboardStore.addTabControls("TimeRange"); break; @@ -603,6 +590,9 @@ function setControls(id: string) { case "addEvent": dashboardStore.addControl("Event"); break; + case "addNetworkProfiling": + dashboardStore.addControl("NetworkProfiling"); + break; case "addTimeRange": dashboardStore.addControl("TimeRange"); break; diff --git a/src/views/dashboard/related/components/TaskDetails.vue b/src/views/dashboard/related/components/TaskDetails.vue index 786bc35c..455a08c0 100644 --- a/src/views/dashboard/related/components/TaskDetails.vue +++ b/src/views/dashboard/related/components/TaskDetails.vue @@ -58,7 +58,6 @@ limitations under the License. --> diff --git a/src/views/dashboard/related/network-profiling/components/Graph/layout.ts b/src/views/dashboard/related/network-profiling/components/Graph/layout.ts new file mode 100644 index 00000000..6a5a5414 --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/Graph/layout.ts @@ -0,0 +1,144 @@ +/** + * 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. + */ +class Orientation { + public f0 = 0; + public f1 = 0; + public f2 = 0; + public f3 = 0; + public b0? = 0; + public b1? = 0; + public b2? = 0; + public b3? = 0; + public start_angle? = 0; + constructor( + f0: number, + f1: number, + f2: number, + f3: number, + b0: number, + b1: number, + b2: number, + b3: number, + start_angle: number + ) { + this.f0 = f0; + this.f1 = f1; + this.f2 = f2; + this.f3 = f3; + this.b0 = b0; + this.b1 = b1; + this.b2 = b2; + this.b3 = b3; + this.start_angle = start_angle; + } +} + +const SQRT3 = Math.sqrt(3.0); +class Layout { + static Pointy = new Orientation( + SQRT3, + SQRT3 / 2.0, + 0.0, + 3.0 / 2.0, + SQRT3 / 3.0, + -1.0 / 3.0, + 0.0, + 2.0 / 3.0, + 0.5 + ); + static Flat = new Orientation( + 3.0 / 2.0, + 0.0, + SQRT3 / 2.0, + SQRT3, + 2.0 / 3.0, + 0.0, + -1.0 / 3.0, + SQRT3 / 3.0, + 0.0 + ); + + static spacing(radius: number, isPointy = false): number[] { + return isPointy + ? [SQRT3 * radius, 2 * radius * (3 / 4)] + : [2 * radius * (3 / 4), SQRT3 * radius]; + } + + private radius = 1; + private orientation: Orientation = { f0: 0, f1: 0, f2: 0, f3: 0 }; + private origin = [0, 0]; + + constructor(radius: number, origin = [0, 0], orientation?: Orientation) { + this.radius = radius; //Layout.spacing( radius, ( orientation === Layout.Pointy ) ); + this.orientation = orientation || Layout.Flat; + this.origin = origin; + } + + // Same as HexToPixel, Except it takes raw coords instead of hex object. + axialToPixel(ax: number, ay: number): number[] { + const M = this.orientation; + const x = (M.f0 * ax + M.f1 * ay) * this.radius; + const y = (M.f2 * ax + M.f3 * ay) * this.radius; + + return [x + this.origin[0], y + this.origin[1]]; + } + + hexToPixel(h: { x: number; y: number }): number[] { + const M = this.orientation; + const x = (M.f0 * h.x + M.f1 * h.y) * this.radius; + const y = (M.f2 * h.x + M.f3 * h.y) * this.radius; + + return [x + this.origin[0], y + this.origin[1]]; + } +} + +class Hex extends Int16Array { + constructor(x: number, y: number, z = null) { + super(3); + this.xyz(x, y, z); + } + + xyz(x: number, y: number, z: number | null = null): Hex { + if (z == null) z = -x - y; + if (x + y + z != 0) { + console.log("Bad Axial Coordinate : : q %d r %d s %d", x, y, z); + } + + this[0] = x; + this[1] = y; + this[2] = z; + return this; + } + + get x(): number { + return this[0]; + } + get y(): number { + return this[1]; + } + get z(): number { + return this[2]; + } + + get len(): number { + return Math.floor( + (Math.abs(this[0]) + Math.abs(this[1]) + Math.abs(this[2])) / 2 + ); + } +} + +export { Hex, Orientation, Layout }; diff --git a/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts b/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts new file mode 100644 index 00000000..06bdb86b --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/Graph/linkProcess.ts @@ -0,0 +1,126 @@ +/** + * 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. + */ + +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: any) => { + const controlPos = computeControlPoint( + [d.source.x, d.source.y - 5], + [d.target.x, d.target.y - 5], + 0.5 + ); + 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("circle") + .attr("class", "topo-line-anchor") + .attr("r", 5) + .attr("fill", "#97B0F8") + .attr("transform", (d: any) => { + const controlPos = computeControlPoint( + [d.source.x, d.source.y - 5], + [d.target.x, d.target.y - 5], + 0.5 + ); + const p = quadraticBezier( + 0.5, + { x: d.source.x, y: d.source.y - 5 }, + { x: controlPos[0], y: controlPos[1] }, + { x: d.target.x, y: d.target.y - 5 } + ); + return `translate(${p[0]}, ${p[1]})`; + }) + .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); + }); + 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]; + const deltaY = pe[1] - ps[1]; + const theta = Math.atan(deltaY / deltaX); + const len = (Math.sqrt(deltaX * deltaX + deltaY * deltaY) / 2) * arc; + const newTheta = theta - Math.PI / 2; + return [ + (ps[0] + pe[0]) / 2 + len * Math.cos(newTheta), + (ps[1] + pe[1]) / 2 + len * Math.sin(newTheta), + ]; +} +// Point coordinates of quadratic Bezier curve +/** + * @param t [0, 1] + * @param ps start position + * @param pc control position + * @param pe end position + * @returns a position in the line + */ +function quadraticBezier( + t: number, + ps: { x: number; y: number }, + pc: { x: number; y: number }, + pe: { x: number; y: number } +) { + const x = (1 - t) * (1 - t) * ps.x + 2 * t * (1 - t) * pc.x + t * t * pe.x; + const y = (1 - t) * (1 - t) * ps.y + 2 * t * (1 - t) * pc.y + t * t * pe.y; + return [x, y]; +} diff --git a/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts b/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts new file mode 100644 index 00000000..1185b4a9 --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/Graph/nodeProcess.ts @@ -0,0 +1,54 @@ +/** + * 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 + 5) + .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 new file mode 100644 index 00000000..2c2552f8 --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/ProcessTopology.vue @@ -0,0 +1,503 @@ + + + + diff --git a/src/views/dashboard/related/network-profiling/components/Settings.vue b/src/views/dashboard/related/network-profiling/components/Settings.vue new file mode 100644 index 00000000..b0cb5aaa --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/Settings.vue @@ -0,0 +1,88 @@ + + + + diff --git a/src/views/dashboard/related/network-profiling/components/Tasks.vue b/src/views/dashboard/related/network-profiling/components/Tasks.vue new file mode 100644 index 00000000..8bc3e334 --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/Tasks.vue @@ -0,0 +1,282 @@ + + + + diff --git a/src/views/dashboard/related/network-profiling/components/TimeLine.vue b/src/views/dashboard/related/network-profiling/components/TimeLine.vue new file mode 100644 index 00000000..aff1b771 --- /dev/null +++ b/src/views/dashboard/related/network-profiling/components/TimeLine.vue @@ -0,0 +1,178 @@ + + + + diff --git a/src/views/dashboard/related/profile/components/SegmentList.vue b/src/views/dashboard/related/profile/components/SegmentList.vue index dac0942e..8c925c3f 100644 --- a/src/views/dashboard/related/profile/components/SegmentList.vue +++ b/src/views/dashboard/related/profile/components/SegmentList.vue @@ -53,16 +53,14 @@ limitations under the License. -->