Merge branch 'main' into main

This commit is contained in:
吴晟 Wu Sheng 2022-09-03 19:39:17 +08:00 committed by GitHub
commit b437ebe7eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 132 additions and 193 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 847 B

After

Width:  |  Height:  |  Size: 895 B

View File

@ -37,6 +37,7 @@ export enum Calculations {
PercentageAvg = "percentageAvg", PercentageAvg = "percentageAvg",
ApdexAvg = "apdexAvg", ApdexAvg = "apdexAvg",
SecondToDay = "secondToDay", SecondToDay = "secondToDay",
NanosecondToMillisecond = "nanosecondToMillisecond",
} }
export enum sizeEnum { export enum sizeEnum {
XS = "XS", XS = "XS",

View File

@ -397,7 +397,7 @@ export function aggregation(
data = (val / 1024 / 1024 / 1024).toFixed(2); data = (val / 1024 / 1024 / 1024).toFixed(2);
break; break;
case Calculations.Apdex: case Calculations.Apdex:
data = val / 10000; data = (val / 10000).toFixed(2);
break; break;
case Calculations.ConvertSeconds: case Calculations.ConvertSeconds:
data = dayjs(val * 1000).format("YYYY-MM-DD HH:mm:ss"); data = dayjs(val * 1000).format("YYYY-MM-DD HH:mm:ss");
@ -414,6 +414,9 @@ export function aggregation(
case Calculations.SecondToDay: case Calculations.SecondToDay:
data = (val / 86400).toFixed(2); data = (val / 86400).toFixed(2);
break; break;
case Calculations.NanosecondToMillisecond:
data = (val / 1000 / 1000).toFixed(2);
break;
default: default:
data; data;
break; break;

View File

@ -40,15 +40,16 @@ const widgetIds = ref<string[]>(
associate.map((d: { widgetId: string }) => d.widgetId) associate.map((d: { widgetId: string }) => d.widgetId)
); );
const widgets: any = computed(() => { const widgets: any = computed(() => {
const all = getDashboard(dashboardStore.currentDashboard).widgets; const widgetList = getDashboard(dashboardStore.currentDashboard).widgets;
const items = all.filter((d: any) => { const items = [];
for (const d of widgetList) {
const isLinear = ["Bar", "Line", "Area"].includes( const isLinear = ["Bar", "Line", "Area"].includes(
(d.graph && d.graph.type) || "" (d.graph && d.graph.type) || ""
); );
if (isLinear && d.id && dashboardStore.selectedGrid.id !== d.id) { if (isLinear && d.id && dashboardStore.selectedGrid.id !== d.id) {
return { value: d.id, label: (d.widget && d.widget.name) || d.id }; items.push({ value: d.id, label: (d.widget && d.widget.name) || d.id });
} }
}); }
return items; return items;
}); });
function updateWidgetConfig(options: Option[]) { function updateWidgetConfig(options: Option[]) {

View File

@ -30,7 +30,7 @@ limitations under the License. -->
<span>{{ t("delete") }}</span> <span>{{ t("delete") }}</span>
</div> </div>
</el-popover> </el-popover>
<Content /> <Content :config="props.data" />
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -194,6 +194,7 @@ export default defineComponent({
editTabIndex.value = index; editTabIndex.value = index;
} }
function handleClick(el: any) { function handleClick(el: any) {
el.stopPropagation();
needQuery.value = true; needQuery.value = true;
if (["tab-name", "edit-tab"].includes(el.target.className)) { if (["tab-name", "edit-tab"].includes(el.target.className)) {
return; return;

View File

@ -297,4 +297,5 @@ export const CalculationOpts = [
{ label: "Precision is 2", value: "precision" }, { label: "Precision is 2", value: "precision" },
{ label: "Milliseconds to seconds", value: "msTos" }, { label: "Milliseconds to seconds", value: "msTos" },
{ label: "Seconds to days", value: "secondToDay" }, { label: "Seconds to days", value: "secondToDay" },
{ label: "Nanoseconds to milliseconds", value: "nanosecondToMillisecond" },
]; ];

View File

@ -288,36 +288,6 @@ async function setSourceSelector() {
states.currentService = selectorStore.currentService.value; states.currentService = selectorStore.currentService.value;
const e = String(params.entity).split("Relation")[0]; const e = String(params.entity).split("Relation")[0];
await fetchPods(e, selectorStore.currentService.id, true); await fetchPods(e, selectorStore.currentService.id, true);
if (!(selectorStore.pods.length && selectorStore.pods[0])) {
selectorStore.setCurrentPod(null);
states.currentPod = "";
states.currentProcess = "";
return;
}
const pod = params.podId || selectorStore.pods[0].id;
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;
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;
}
} }
async function setDestSelector() { async function setDestSelector() {
@ -328,33 +298,6 @@ async function setDestSelector() {
selectorStore.currentDestService.id, selectorStore.currentDestService.id,
true true
); );
if (!(selectorStore.destPods.length && selectorStore.destPods[0])) {
selectorStore.setCurrentDestPod(null);
states.currentDestPod = "";
return;
}
const destPod = params.destPodId || selectorStore.destPods[0].id;
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;
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() { async function getServices() {
@ -482,10 +425,12 @@ function changeDestPods(pod: Option[]) {
function changeDestProcess(pod: Option[]) { function changeDestProcess(pod: Option[]) {
selectorStore.setCurrentDestProcess(pod[0] || null); selectorStore.setCurrentDestProcess(pod[0] || null);
states.currentDestProcess = pod[0].label || "";
} }
function changeProcess(pod: Option[]) { function changeProcess(pod: Option[]) {
selectorStore.setCurrentProcess(pod[0] || null); selectorStore.setCurrentProcess(pod[0] || null);
states.currentProcess = pod[0].label || "";
} }
function changeMode() { function changeMode() {
@ -612,35 +557,13 @@ async function fetchPods(
case EntityType[2].value: case EntityType[2].value:
resp = await selectorStore.getEndpoints({ serviceId, ...param }); resp = await selectorStore.getEndpoints({ serviceId, ...param });
if (setPod) { if (setPod) {
let p; updateCurrentPod();
if (states.currentPod) {
p = selectorStore.pods.find(
(d: { label: unknown }) => d.label === states.currentPod
);
} else {
p = selectorStore.pods.find(
(d: unknown, index: number) => index === 0
);
}
selectorStore.setCurrentPod(p || null);
states.currentPod = selectorStore.currentPod.label;
} }
break; break;
case EntityType[3].value: case EntityType[3].value:
resp = await selectorStore.getServiceInstances({ serviceId }); resp = await selectorStore.getServiceInstances({ serviceId });
if (setPod) { if (setPod) {
let p; updateCurrentPod();
if (states.currentPod) {
p = selectorStore.pods.find(
(d: { label: string }) => d.label === states.currentPod
);
} else {
p = selectorStore.pods.find(
(d: { label: string }, index: number) => index === 0
);
}
selectorStore.setCurrentPod(p || null);
states.currentPod = selectorStore.currentPod.label;
} }
break; break;
case EntityType[6].value: case EntityType[6].value:
@ -650,18 +573,7 @@ async function fetchPods(
...param, ...param,
}); });
if (setPod) { if (setPod) {
let p; updateCurrentDestPod();
if (states.currentDestPod) {
p = selectorStore.destPods.find(
(d: { label: string }) => d.label === states.currentDestPod
);
} else {
p = selectorStore.destPods.find(
(d: { label: string }, index: number) => index === 0
);
}
selectorStore.setCurrentDestPod(p || null);
states.currentDestPod = selectorStore.currentDestPod.label;
} }
break; break;
case EntityType[5].value: case EntityType[5].value:
@ -670,18 +582,7 @@ async function fetchPods(
isRelation: true, isRelation: true,
}); });
if (setPod) { if (setPod) {
let p; updateCurrentDestPod();
if (states.currentDestPod) {
p = selectorStore.destPods.find(
(d: { label: string }) => d.label === states.currentDestPod
);
} else {
p = selectorStore.destPods.find(
(d: { label: string }, index: number) => index === 0
);
}
selectorStore.setCurrentDestPod(p || null);
states.currentDestPod = selectorStore.currentDestPod.label;
} }
break; break;
case EntityType[7].value: case EntityType[7].value:
@ -705,18 +606,14 @@ async function fetchProcess(setPod: boolean) {
instanceId: selectorStore.currentPod.id, instanceId: selectorStore.currentPod.id,
}); });
if (setPod) { if (setPod) {
let m; const process = params.processId || selectorStore.processes[0].id;
if (states.currentProcess) { const currentProcess = selectorStore.processes.find(
m = selectorStore.processes.find( (d: { id: string }) => d.id === process
(d: { label: string }) => d.label === states.currentProcess );
); if (currentProcess) {
} else { selectorStore.setCurrentProcess(currentProcess);
m = selectorStore.processes.find( states.currentProcess = currentProcess.label;
(d: { label: string }, index: number) => index === 0
);
} }
selectorStore.setCurrentProcess(m || null);
states.currentProcess = m && m.label;
} }
return resp; return resp;
} }
@ -726,21 +623,58 @@ async function fetchDestProcess(setPod: boolean) {
isRelation: true, isRelation: true,
}); });
if (setPod) { if (setPod) {
let m; const destProcess =
if (states.currentDestProcess) { params.destProcessId || selectorStore.destProcesses[0].id;
m = selectorStore.destProcesses.find( const currentDestProcess = selectorStore.destProcesses.find(
(d: { label: string }) => d.label === states.currentDestProcess (d: { id: string }) => d.id === destProcess
); );
} else { if (!currentDestProcess) {
m = selectorStore.destProcesses.find( states.currentDestProcess = "";
(d: { label: string }, index: number) => index === 1 selectorStore.setCurrentDestProcess(null);
); return;
} }
selectorStore.setCurrentDestProcess(m || null); selectorStore.setCurrentDestProcess(currentDestProcess);
states.currentDestProcess = m && m.label; states.currentDestProcess = currentDestProcess.label;
} }
return resp; return resp;
} }
function updateCurrentDestPod() {
if (!(selectorStore.destPods.length && selectorStore.destPods[0])) {
selectorStore.setCurrentDestPod(null);
states.currentDestPod = "";
return;
}
const destPod = params.destPodId || selectorStore.destPods[0].id;
const currentDestPod = selectorStore.destPods.find(
(d: { id: string }) => d.id === destPod
);
if (!currentDestPod) {
states.currentDestPod = "";
selectorStore.setCurrentDestPod(null);
return;
}
selectorStore.setCurrentDestPod(currentDestPod);
states.currentDestPod = currentDestPod.label;
}
function updateCurrentPod() {
if (!(selectorStore.pods.length && selectorStore.pods[0])) {
selectorStore.setCurrentPod(null);
states.currentPod = "";
return;
}
const pod = params.podId || selectorStore.pods[0].id;
const currentPod = selectorStore.pods.find(
(d: { id: string }) => d.id === pod
);
if (!currentPod) {
selectorStore.setCurrentPod(null);
states.currentPod = "";
return;
}
selectorStore.setCurrentPod(currentPod);
states.currentPod = currentPod.label;
}
function getTools() { function getTools() {
switch (params.entity) { switch (params.entity) {
case EntityType[1].value: case EntityType[1].value:

View File

@ -15,24 +15,31 @@ limitations under the License. -->
<template> <template>
<div class="flex-h content"> <div class="flex-h content">
<Tasks /> <Tasks />
<div <div class="vis-graph ml-5" v-loading="networkProfilingStore.loadNodes">
class="vis-graph ml-5" <process-topology
v-if="networkProfilingStore.nodes.length" v-if="networkProfilingStore.nodes.length"
v-loading="networkProfilingStore.loadNodes" :config="config"
> />
<process-topology /> <div class="text" v-else>
</div> {{ t("noData") }}
<div class="text" v-else v-loading="networkProfilingStore.loadNodes"> </div>
{{ t("noData") }}
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { PropType } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import Tasks from "./components/Tasks.vue"; import Tasks from "./components/Tasks.vue";
import ProcessTopology from "./components/ProcessTopology.vue"; import ProcessTopology from "./components/ProcessTopology.vue";
import { useNetworkProfilingStore } from "@/store/modules/network-profiling"; import { useNetworkProfilingStore } from "@/store/modules/network-profiling";
/*global defineProps */
defineProps({
config: {
type: Object as PropType<any>,
default: () => ({ graph: {} }),
},
});
const networkProfilingStore = useNetworkProfilingStore(); const networkProfilingStore = useNetworkProfilingStore();
const { t } = useI18n(); const { t } = useI18n();
</script> </script>
@ -52,7 +59,7 @@ const { t } = useI18n();
} }
.text { .text {
width: calc(100% - 330px); width: 100%;
text-align: center; text-align: center;
margin-top: 30px; margin-top: 30px;
} }

View File

@ -25,18 +25,21 @@ export const linkElement = (graph: any) => {
.attr("stroke", "#97B0F8") .attr("stroke", "#97B0F8")
.attr("d", (d: Call) => { .attr("d", (d: Call) => {
const controlPos = computeControlPoint( const controlPos = computeControlPoint(
[d.source.x, d.source.y], [d.source.x, d.source.y - 5],
[d.target.x, d.target.y], [d.target.x, d.target.y - 5],
0.5 0.5
); );
if (d.lowerArc) { if (d.lowerArc) {
controlPos[1] = -controlPos[1]; controlPos[1] =
Math.abs(controlPos[1]) < 50
? -controlPos[1] + 90
: -controlPos[1] - 10;
} }
return ( return (
"M" + "M" +
d.source.x + d.source.x +
" " + " " +
d.source.y + (d.source.y - 5) +
" " + " " +
"Q" + "Q" +
controlPos[0] + controlPos[0] +
@ -45,7 +48,7 @@ export const linkElement = (graph: any) => {
" " + " " +
d.target.x + d.target.x +
" " + " " +
d.target.y (d.target.y - 5)
); );
}); });
return linkEnter; return linkEnter;
@ -53,7 +56,7 @@ export const linkElement = (graph: any) => {
export const anchorElement = (graph: any, funcs: any, tip: any) => { export const anchorElement = (graph: any, funcs: any, tip: any) => {
const linkEnter = graph const linkEnter = graph
.append("g") .append("g")
.attr("style", "cursor: move;") .attr("class", "topo-line-anchor")
.on("mouseover", function (event: unknown, d: unknown) { .on("mouseover", function (event: unknown, d: unknown) {
tip.html(funcs.tipHtml).show(d, this); tip.html(funcs.tipHtml).show(d, this);
}) })
@ -63,44 +66,17 @@ export const anchorElement = (graph: any, funcs: any, tip: any) => {
.on("click", (event: unknown, d: unknown) => { .on("click", (event: unknown, d: unknown) => {
funcs.handleLinkClick(event, d); funcs.handleLinkClick(event, d);
}); });
linkEnter
.append("text")
.attr("fill", "#444")
.attr("text-anchor", "middle")
.attr("x", (d: Call) => {
const p = getMidpoint(d);
return p[0] + 10;
})
.attr("y", (d: Call) => {
const p = getMidpoint(d);
return p[1] + 3;
})
.text((d: Call) => {
const types = [...d.sourceComponents, ...d.targetComponents];
if (types.includes("tcp")) {
return "TCP";
}
if (types.includes("https")) {
return "HTTPS";
}
if (types.includes("http")) {
return "HTTP";
}
if (types.includes("tls")) {
return "TLS";
}
});
linkEnter linkEnter
.append("image") .append("image")
.attr("width", 15) .attr("width", 15)
.attr("height", 15) .attr("height", 15)
.attr("x", (d: Call) => { .attr("x", (d: Call) => {
const p = getMidpoint(d); const p = getMidpoint(d);
return p[0] - 16; return p[0] - 8;
}) })
.attr("y", (d: Call) => { .attr("y", (d: Call) => {
const p = getMidpoint(d); const p = getMidpoint(d);
return p[1] - 9; return p[1] - 13;
}) })
.attr("xlink:href", (d: Call) => { .attr("xlink:href", (d: Call) => {
const types = [...d.sourceComponents, ...d.targetComponents]; const types = [...d.sourceComponents, ...d.targetComponents];
@ -168,7 +144,8 @@ function getMidpoint(d: Call) {
0.5 0.5
); );
if (d.lowerArc) { if (d.lowerArc) {
controlPos[1] = -controlPos[1]; controlPos[1] =
Math.abs(controlPos[1]) < 50 ? -controlPos[1] + 100 : -controlPos[1] - 10;
} }
const p = quadraticBezier( const p = quadraticBezier(
0.5, 0.5,

View File

@ -14,14 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License. --> limitations under the License. -->
<template> <template>
<div ref="chart" class="process-topo"></div> <div ref="chart" class="process-topo"></div>
<el-popover placement="bottom" :width="295" trigger="click"> <el-popover
placement="bottom"
:width="295"
trigger="click"
v-if="dashboardStore.editMode"
>
<template #reference> <template #reference>
<div <div class="switch-icon-edit ml-5" title="Settings" @click="setConfig">
class="switch-icon-edit ml-5"
title="Settings"
@click="setConfig"
v-if="dashboardStore.editMode"
>
<Icon size="middle" iconName="setting_empty" /> <Icon size="middle" iconName="setting_empty" />
</div> </div>
</template> </template>
@ -76,7 +76,7 @@ const link = ref<any>(null);
const anchor = ref<any>(null); const anchor = ref<any>(null);
const arrow = ref<any>(null); const arrow = ref<any>(null);
const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 }); const oldVal = ref<{ width: number; height: number }>({ width: 0, height: 0 });
const config = ref<any>({}); const config = ref<any>(props.config || {});
const diff = ref<number[]>([220, 200]); const diff = ref<number[]>([220, 200]);
const radius = 210; const radius = 210;
const dates = ref<Nullable<{ start: number; end: number }>>(null); const dates = ref<Nullable<{ start: number; end: number }>>(null);
@ -315,9 +315,21 @@ function drawTopology(nodeArr: any[]) {
{ {
handleLinkClick: handleLinkClick, handleLinkClick: handleLinkClick,
tipHtml: (data: Call) => { tipHtml: (data: Call) => {
const types = [...data.sourceComponents, ...data.targetComponents];
let l = "TCP";
if (types.includes("https")) {
l = "HTTPS";
}
if (types.includes("http")) {
l = "HTTP";
}
if (types.includes("tls")) {
l = "TLS";
}
const html = `<div><span class="grey">${t( const html = `<div><span class="grey">${t(
"detectPoint" "detectPoint"
)}:</span>${data.detectPoints.join(" | ")}</div>`; )}: </span>${data.detectPoints.join(" | ")}</div>
<div><span class="grey">Type: </span>${l}</div>`;
return html; return html;
}, },
}, },
@ -441,6 +453,10 @@ watch(
cursor: move; cursor: move;
} }
.topo-line-anchor {
cursor: pointer;
}
.switch-icon-edit { .switch-icon-edit {
cursor: pointer; cursor: pointer;
transition: all 0.5ms linear; transition: all 0.5ms linear;

View File

@ -15,7 +15,7 @@ limitations under the License. -->
<template> <template>
<div class="label">{{ t("linkDashboard") }}</div> <div class="label">{{ t("linkDashboard") }}</div>
<Selector <Selector
:value="linkDashboard" :value="dashboardStore.selectedGrid.linkDashboard || ''"
:options="linkDashboards" :options="linkDashboards"
size="small" size="small"
placeholder="Please input a dashboard name for calls" placeholder="Please input a dashboard name for calls"
@ -37,8 +37,6 @@ const dashboardStore = useDashboardStore();
const linkDashboards = ref< const linkDashboards = ref<
(DashboardItem & { label: string; value: string })[] (DashboardItem & { label: string; value: string })[]
>([]); >([]);
const { selectedGrid } = dashboardStore;
const linkDashboard = ref<string>(selectedGrid.linkDashboard || "");
onMounted(() => { onMounted(() => {
getDashboards(); getDashboards();
@ -64,10 +62,10 @@ function getDashboards() {
} }
function changeLinkDashboard(opt: { value: string }[]) { function changeLinkDashboard(opt: { value: string }[]) {
linkDashboard.value = opt[0].value; const linkDashboard = opt.length ? opt[0].value : "";
const p = { const p = {
...dashboardStore.selectedGrid, ...dashboardStore.selectedGrid,
linkDashboard: opt[0].value, linkDashboard,
}; };
dashboardStore.selectWidget(p); dashboardStore.selectWidget(p);
dashboardStore.setConfigs(p); dashboardStore.setConfigs(p);