fix: polish the hierarchy topology and dashboard configs (#362)

This commit is contained in:
Fine0830 2024-01-16 17:04:21 +08:00 committed by GitHub
parent f809123b4f
commit 5061b19cf7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 109 deletions

View File

@ -385,7 +385,7 @@ const msg = {
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions", tabExpressions: "Tab Expressions",
hierarchyServicesSettings: "Service Hierarchy Topology Settings", hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeMetrics: "Metrics related with hierarchy topology nodes", hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
}; };
export default msg; export default msg;

View File

@ -385,7 +385,7 @@ const msg = {
traceDesc: traceDesc:
"The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.", "The trace segment serves as a representation of a trace portion executed within one single OS process, such as a JVM. It comprises a collection of spans, typically associated with and collected from a single request or execution context.",
tabExpressions: "Tab Expressions", tabExpressions: "Tab Expressions",
hierarchyServicesSettings: "Service Hierarchy Topology Settings", hierarchyNodeMetrics: "Metrics for Hierarchy Graph Node",
hierarchyNodeMetrics: "Metrics related with hierarchy topology nodes", hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
}; };
export default msg; export default msg;

View File

@ -383,7 +383,7 @@ const msg = {
traceDesc: traceDesc:
"Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。", "Trace Segment代表在单一操作系统进程例如JVM中执行的追踪部分。它包含了一组跨度spans这些跨度通常与单一请求或执行上下文关联。",
tabExpressions: "Tab表达式", tabExpressions: "Tab表达式",
hierarchyServicesSettings: "层次结构服务拓扑设置", hierarchyNodeMetrics: "层次图节点的指标",
hierarchyNodeMetrics: "层级拓扑节点关联的指标", hierarchyNodeDashboard: "作为层次图节点的dashboard",
}; };
export default msg; export default msg;

View File

@ -73,23 +73,7 @@ limitations under the License. -->
<span v-else> -- </span> <span v-else> -- </span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="isDefault" label="Default Dashboard" width="140"> <el-table-column label="Operations" width="400">
<template #default="scope">
<el-popconfirm
:title="t('rootTitle')"
@confirm="handleTopLevel(scope.row)"
v-if="[EntityType[0].value, EntityType[3].value].includes(scope.row.entity)"
>
<template #reference>
<el-button size="small" style="width: 80px">
{{ scope.row.isDefault ? "Disable" : "Enable" }}
</el-button>
</template>
</el-popconfirm>
<span v-else> -- </span>
</template>
</el-table-column>
<el-table-column label="Operations" width="300">
<template #default="scope"> <template #default="scope">
<el-button size="small" @click="handleEdit(scope.row)"> <el-button size="small" @click="handleEdit(scope.row)">
{{ t("edit") }} {{ t("edit") }}
@ -102,7 +86,7 @@ limitations under the License. -->
size="small" size="small"
@click="handleEditMQE(scope.row)" @click="handleEditMQE(scope.row)"
> >
MQE Hierarchy Graph
</el-button> </el-button>
<span v-else class="placeholder"></span> <span v-else class="placeholder"></span>
<el-popconfirm :title="t('deleteTitle')" @confirm="handleDelete(scope.row)"> <el-popconfirm :title="t('deleteTitle')" @confirm="handleDelete(scope.row)">
@ -147,9 +131,13 @@ limitations under the License. -->
@next-click="changePage" @next-click="changePage"
/> />
</div> </div>
<el-dialog v-model="MQEVisible" title="Edit MQE" width="400px"> <el-dialog v-model="MQEVisible" title="Hierarchy Graph" width="400px">
<div class="mb-10">
<span class="label mr-10">{{ t("hierarchyNodeDashboard") }}</span>
<el-switch v-model="currentRow.isDefault" style="height: 25px" />
</div>
<div> <div>
<span>{{ t("hierarchyNodeMetrics") }}</span> <span class="label">{{ t("hierarchyNodeMetrics") }}</span>
<el-popover placement="left" :width="400" trigger="click"> <el-popover placement="left" :width="400" trigger="click">
<template #reference> <template #reference>
<span> <span>
@ -238,10 +226,14 @@ limitations under the License. -->
} }
async function saveMQE() { async function saveMQE() {
if (!currentRow.value.expressionsConfig) {
return;
}
const items: DashboardItem[] = []; const items: DashboardItem[] = [];
loading.value = true; loading.value = true;
for (const d of dashboardStore.dashboards) { for (const d of dashboardStore.dashboards) {
if (d.id === currentRow.value.id) { if (d.id === currentRow.value.id) {
d.isDefault = currentRow.value.isDefault || false;
d.expressions = currentRow.value.expressions; d.expressions = currentRow.value.expressions;
d.expressionsConfig = currentRow.value.expressionsConfig; d.expressionsConfig = currentRow.value.expressionsConfig;
const key = [d.layer, d.entity, d.name].join("_"); const key = [d.layer, d.entity, d.name].join("_");
@ -269,6 +261,38 @@ limitations under the License. -->
loading.value = false; loading.value = false;
return; return;
} }
} else {
if (
d.layer === currentRow.value.layer &&
[EntityType[0].value].includes(d.entity) &&
!currentRow.value.isDefault &&
d.isDefault
) {
d.isDefault = false;
const key = [d.layer, d.entity, d.name].join("_");
const layout = sessionStorage.getItem(key) || "{}";
const c = {
...JSON.parse(layout).configuration,
...d,
};
const setting = {
id: d.id,
configuration: JSON.stringify(c),
};
const res = await dashboardStore.updateDashboard(setting);
if (res.data.changeTemplate.status) {
sessionStorage.setItem(
key,
JSON.stringify({
id: d.id,
configuration: c,
}),
);
} else {
loading.value = false;
return;
}
}
} }
items.push(d); items.push(d);
} }
@ -497,71 +521,7 @@ limitations under the License. -->
searchDashboards(currentPage.value); searchDashboards(currentPage.value);
loading.value = false; loading.value = false;
} }
async function handleTopLevel(row: DashboardItem) {
const items: DashboardItem[] = [];
loading.value = true;
for (const d of dashboardStore.dashboards) {
if (d.id === row.id) {
d.isDefault = !row.isDefault;
const key = [d.layer, d.entity, d.name].join("_");
const layout = sessionStorage.getItem(key) || "{}";
const c = {
...JSON.parse(layout).configuration,
...d,
};
delete c.id;
const setting = {
id: d.id,
configuration: JSON.stringify(c),
};
const res = await dashboardStore.updateDashboard(setting);
if (res.data.changeTemplate.status) {
sessionStorage.setItem(
key,
JSON.stringify({
id: d.id,
configuration: c,
}),
);
} else {
loading.value = false;
return;
}
} else {
if (d.layer === row.layer && [EntityType[0].value].includes(d.entity) && !row.isDefault && d.isDefault) {
d.isDefault = false;
const key = [d.layer, d.entity, d.name].join("_");
const layout = sessionStorage.getItem(key) || "{}";
const c = {
...JSON.parse(layout).configuration,
...d,
};
const setting = {
id: d.id,
configuration: JSON.stringify(c),
};
const res = await dashboardStore.updateDashboard(setting);
if (res.data.changeTemplate.status) {
sessionStorage.setItem(
key,
JSON.stringify({
id: d.id,
configuration: c,
}),
);
} else {
loading.value = false;
return;
}
}
}
items.push(d);
}
dashboardStore.resetDashboards(items);
searchDashboards(currentPage.value);
loading.value = false;
}
function handleRename(row: DashboardItem) { function handleRename(row: DashboardItem) {
ElMessageBox.prompt("Please input dashboard name", "Edit", { ElMessageBox.prompt("Please input dashboard name", "Edit", {
confirmButtonText: "OK", confirmButtonText: "OK",
@ -724,10 +684,14 @@ limitations under the License. -->
.placeholder { .placeholder {
display: inline-block; display: inline-block;
width: 75px; width: 136px;
} }
.expressions { .expressions {
height: 300px; height: 300px;
} }
.label {
font-size: 12px;
}
</style> </style>

View File

@ -152,16 +152,18 @@ limitations under the License. -->
const origin = dashboardStore.entity; const origin = dashboardStore.entity;
event.stopPropagation(); event.stopPropagation();
hideTip(); hideTip();
const dashboard = const { dashboard } = getDashboard(
getDashboard( {
{ layer: d.layer || "",
layer: d.layer || "", entity: EntityType[3].value,
entity: EntityType[3].value, },
}, ConfigFieldTypes.ISDEFAULT,
ConfigFieldTypes.ISDEFAULT, );
).dashboard || {}; if (!dashboard) {
return;
}
const name = dashboard.name; const name = dashboard.name;
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[3].value}/${d.serviceId}/${d.key}/${name}`; const path = `/dashboard/${dashboard.layer}/${EntityType[3].value}/${d.serviceId}/${d.key}/${name}`;
const routeUrl = router.resolve({ path }); const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");

View File

@ -160,16 +160,19 @@ limitations under the License. -->
const origin = dashboardStore.entity; const origin = dashboardStore.entity;
event.stopPropagation(); event.stopPropagation();
hideTip(); hideTip();
const dashboard = const { dashboard } = getDashboard(
getDashboard( {
{ layer: d.layer || "",
layer: d.layer || "", entity: EntityType[0].value,
entity: EntityType[0].value, },
}, ConfigFieldTypes.ISDEFAULT,
ConfigFieldTypes.ISDEFAULT, );
).dashboard || {}; if (!dashboard) {
return;
}
const name = dashboard.name; const name = dashboard.name;
const path = `/dashboard/${dashboardStore.layerId}/${EntityType[0].value}/${d.key}/${name}`; const path = `/dashboard/${dashboard.layer}/${EntityType[0].value}/${d.key}/${name}`;
const routeUrl = router.resolve({ path }); const routeUrl = router.resolve({ path });
window.open(routeUrl.href, "_blank"); window.open(routeUrl.href, "_blank");