+
{{ appStore.pageTitle || t(pageName) }}
{{ t("timeTips") }}
@@ -49,34 +49,38 @@ 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 @@
+
+
+ {{ t("linkDashboard") }}
+
+
+
+
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 @@
+
+
+
+
+
+ {{ t("taskList") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ t("noData") }}
+
+
+
+
+
+
+ {{ dateFormat(i.taskStartTime) }}
+
+
+ {{
+ dateFormat(i.taskStartTime + i.fixedTriggerDuration * 1000)
+ }}
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+
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 @@
+
+
+
+
+
+
+
+
+
+
+ {{ t("query") }}
+
+
+
+
+
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. -->