mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 16:54:52 +00:00
feat: View data value related dashboards in TopList widgets (#425)
This commit is contained in:
parent
224e761d70
commit
14fa5d65b6
@ -57,6 +57,16 @@ export const RespFields: Indexable = {
|
|||||||
name: id
|
name: id
|
||||||
value
|
value
|
||||||
refId: traceID
|
refId: traceID
|
||||||
|
owner {
|
||||||
|
scope
|
||||||
|
serviceID
|
||||||
|
serviceName
|
||||||
|
normal
|
||||||
|
serviceInstanceID
|
||||||
|
serviceInstanceName
|
||||||
|
endpointID
|
||||||
|
endpointName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error
|
error
|
||||||
|
@ -61,7 +61,7 @@ limitations under the License. -->
|
|||||||
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
|
<Icon iconName="retry" :loading="appStore.autoRefresh" class="middle" />
|
||||||
</span>
|
</span>
|
||||||
<span class="version ml-5 cp">
|
<span class="version ml-5 cp">
|
||||||
<el-popover trigger="hover" width="250" placement="bottom" :content="appStore.version">
|
<el-popover trigger="hover" :width="250" placement="bottom" :content="appStore.version">
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<span>
|
<span>
|
||||||
<Icon iconName="info_outline" size="middle" />
|
<Icon iconName="info_outline" size="middle" />
|
||||||
|
@ -388,5 +388,7 @@ const msg = {
|
|||||||
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
||||||
valueMappings: "Value Mappings",
|
valueMappings: "Value Mappings",
|
||||||
mappingTip: "Notice: The mapping key is a Regex string, e.g. ^([0-9])$",
|
mappingTip: "Notice: The mapping key is a Regex string, e.g. ^([0-9])$",
|
||||||
|
valueDashboard: "Data Value Related Dashboard",
|
||||||
|
viewValueDashboard: "View Dashboard",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -388,5 +388,7 @@ const msg = {
|
|||||||
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
hierarchyNodeDashboard: "As dashboard for Hierarchy Graph Node",
|
||||||
valueMappings: "Value Mappings",
|
valueMappings: "Value Mappings",
|
||||||
mappingTip: "Aviso: La clave de mapeo es una cadena Regex, p. ej. ^([0-9])$",
|
mappingTip: "Aviso: La clave de mapeo es una cadena Regex, p. ej. ^([0-9])$",
|
||||||
|
valueDashboard: "Data Value Related Dashboard",
|
||||||
|
viewValueDashboard: "View Dashboard",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
@ -386,5 +386,7 @@ const msg = {
|
|||||||
hierarchyNodeDashboard: "作为层次图节点的dashboard",
|
hierarchyNodeDashboard: "作为层次图节点的dashboard",
|
||||||
valueMappings: "值映射",
|
valueMappings: "值映射",
|
||||||
mappingTip: "注意: 映射键是一个正则表达式字符串,比如 ^([0-9])$",
|
mappingTip: "注意: 映射键是一个正则表达式字符串,比如 ^([0-9])$",
|
||||||
|
valueDashboard: "数据值相关的仪表板",
|
||||||
|
viewValueDashboard: "查看仪表板",
|
||||||
};
|
};
|
||||||
export default msg;
|
export default msg;
|
||||||
|
1
src/types/dashboard.d.ts
vendored
1
src/types/dashboard.d.ts
vendored
@ -46,6 +46,7 @@ export interface LayoutConfig {
|
|||||||
relatedTrace?: RelatedTrace;
|
relatedTrace?: RelatedTrace;
|
||||||
subExpressions?: string[];
|
subExpressions?: string[];
|
||||||
subTypesOfMQE?: string[];
|
subTypesOfMQE?: string[];
|
||||||
|
valueRelatedDashboard?: string;
|
||||||
}
|
}
|
||||||
export type RelatedTrace = {
|
export type RelatedTrace = {
|
||||||
duration: DurationTime;
|
duration: DurationTime;
|
||||||
|
@ -38,6 +38,7 @@ limitations under the License. -->
|
|||||||
typesOfMQE: typesOfMQE || [],
|
typesOfMQE: typesOfMQE || [],
|
||||||
subExpressions: config.subExpressions || [],
|
subExpressions: config.subExpressions || [],
|
||||||
subTypesOfMQE: config.subTypesOfMQE || [],
|
subTypesOfMQE: config.subTypesOfMQE || [],
|
||||||
|
valueRelatedDashboard: config.valueRelatedDashboard,
|
||||||
}"
|
}"
|
||||||
:needQuery="true"
|
:needQuery="true"
|
||||||
/>
|
/>
|
||||||
|
@ -41,6 +41,7 @@ limitations under the License. -->
|
|||||||
typesOfMQE: dashboardStore.selectedGrid.typesOfMQE || [],
|
typesOfMQE: dashboardStore.selectedGrid.typesOfMQE || [],
|
||||||
subExpressions: dashboardStore.selectedGrid.subExpressions || [],
|
subExpressions: dashboardStore.selectedGrid.subExpressions || [],
|
||||||
subTypesOfMQE: dashboardStore.selectedGrid.subTypesOfMQE || [],
|
subTypesOfMQE: dashboardStore.selectedGrid.subTypesOfMQE || [],
|
||||||
|
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard,
|
||||||
}"
|
}"
|
||||||
:needQuery="true"
|
:needQuery="true"
|
||||||
@expressionTips="getErrors"
|
@expressionTips="getErrors"
|
||||||
|
@ -95,6 +95,20 @@ limitations under the License. -->
|
|||||||
{{ type.label }}
|
{{ type.label }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="states.isTopList" class="mt-10">
|
||||||
|
<div>{{ t("valueDashboard") }}</div>
|
||||||
|
<div>
|
||||||
|
<Selector
|
||||||
|
:value="states.valueRelatedDashboard || ''"
|
||||||
|
:options="states.dashboardList"
|
||||||
|
size="small"
|
||||||
|
placeholder="Please select a dashboard name"
|
||||||
|
@change="changeValueDashboard"
|
||||||
|
class="selectors"
|
||||||
|
:clearable="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, computed } from "vue";
|
import { reactive, ref, computed } from "vue";
|
||||||
@ -140,21 +154,25 @@ limitations under the License. -->
|
|||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
metricTypeList: Option[][];
|
metricTypeList: Option[][];
|
||||||
isList: boolean;
|
isList: boolean;
|
||||||
|
isTopList: boolean;
|
||||||
dashboardName: string;
|
dashboardName: string;
|
||||||
dashboardList: ((DashboardItem & { label: string; value: string }) | any)[];
|
dashboardList: ((DashboardItem & { label: string; value: string }) | any)[];
|
||||||
tips: string[];
|
tips: string[];
|
||||||
subTips: string[];
|
subTips: string[];
|
||||||
|
valueRelatedDashboard: string;
|
||||||
}>({
|
}>({
|
||||||
metrics: metrics.value.length ? metrics.value : [""],
|
metrics: metrics.value.length ? metrics.value : [""],
|
||||||
metricTypes: typesOfMQE.value.length ? typesOfMQE.value : [""],
|
metricTypes: typesOfMQE.value.length ? typesOfMQE.value : [""],
|
||||||
metricTypeList: [],
|
metricTypeList: [],
|
||||||
isList: false,
|
isList: false,
|
||||||
|
isTopList: false,
|
||||||
dashboardName: graph.value.dashboardName,
|
dashboardName: graph.value.dashboardName,
|
||||||
dashboardList: [{ label: "", value: "" }],
|
dashboardList: [{ label: "", value: "" }],
|
||||||
tips: [],
|
tips: [],
|
||||||
subTips: [],
|
subTips: [],
|
||||||
subMetrics: subMetrics.value.length ? subMetrics.value : [""],
|
subMetrics: subMetrics.value.length ? subMetrics.value : [""],
|
||||||
subMetricTypes: subMetricTypes.value.length ? subMetricTypes.value : [""],
|
subMetricTypes: subMetricTypes.value.length ? subMetricTypes.value : [""],
|
||||||
|
valueRelatedDashboard: dashboardStore.selectedGrid.valueRelatedDashboard,
|
||||||
});
|
});
|
||||||
const currentMetricConfig = ref<MetricConfigOpt>({
|
const currentMetricConfig = ref<MetricConfigOpt>({
|
||||||
unit: "",
|
unit: "",
|
||||||
@ -163,6 +181,7 @@ limitations under the License. -->
|
|||||||
sortOrder: "DES",
|
sortOrder: "DES",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
states.isTopList = graph.value.type === ChartTypes[4].value;
|
||||||
states.isList = ListChartTypes.includes(graph.value.type);
|
states.isList = ListChartTypes.includes(graph.value.type);
|
||||||
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
||||||
|
|
||||||
@ -187,9 +206,10 @@ limitations under the License. -->
|
|||||||
const arr = list.reduce((prev: (DashboardItem & { label: string; value: string })[], d: DashboardItem) => {
|
const arr = list.reduce((prev: (DashboardItem & { label: string; value: string })[], d: DashboardItem) => {
|
||||||
if (d.layer === dashboardStore.layerId) {
|
if (d.layer === dashboardStore.layerId) {
|
||||||
if (
|
if (
|
||||||
(d.entity === EntityType[0].value && chart === "ServiceList") ||
|
(d.entity === EntityType[0].value && chart === ChartTypes[8].value) ||
|
||||||
(d.entity === EntityType[2].value && chart === "EndpointList") ||
|
(d.entity === EntityType[2].value && chart === ChartTypes[9].value) ||
|
||||||
(d.entity === EntityType[3].value && chart === "InstanceList")
|
(d.entity === EntityType[3].value && chart === ChartTypes[10].value) ||
|
||||||
|
states.isTopList
|
||||||
) {
|
) {
|
||||||
prev.push({
|
prev.push({
|
||||||
...d,
|
...d,
|
||||||
@ -254,9 +274,28 @@ limitations under the License. -->
|
|||||||
typesOfMQE: states.metricTypes,
|
typesOfMQE: states.metricTypes,
|
||||||
});
|
});
|
||||||
emit("update", params.source || {});
|
emit("update", params.source || {});
|
||||||
|
if (states.isTopList) {
|
||||||
|
const values: any = Object.values(params.source)[0];
|
||||||
|
if (!values) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
states.dashboardList = states.dashboardList.filter((d) => d.entity === values[0].owner.scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeDashboard(opt: any) {
|
function changeValueDashboard(opt: { value: string }[]) {
|
||||||
|
if (!opt[0]) {
|
||||||
|
states.valueRelatedDashboard = "";
|
||||||
|
} else {
|
||||||
|
states.valueRelatedDashboard = opt[0].value;
|
||||||
|
}
|
||||||
|
dashboardStore.selectWidget({
|
||||||
|
...dashboardStore.selectedGrid,
|
||||||
|
valueRelatedDashboard: states.valueRelatedDashboard,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeDashboard(opt: { value: string }[]) {
|
||||||
if (!opt[0]) {
|
if (!opt[0]) {
|
||||||
states.dashboardName = "";
|
states.dashboardName = "";
|
||||||
} else {
|
} else {
|
||||||
|
@ -61,6 +61,7 @@ limitations under the License. -->
|
|||||||
typesOfMQE: typesOfMQE || [],
|
typesOfMQE: typesOfMQE || [],
|
||||||
subExpressions: data.subExpressions || [],
|
subExpressions: data.subExpressions || [],
|
||||||
subTypesOfMQE: data.subTypesOfMQE || [],
|
subTypesOfMQE: data.subTypesOfMQE || [],
|
||||||
|
valueRelatedDashboard: data.valueRelatedDashboard,
|
||||||
}"
|
}"
|
||||||
:needQuery="needQuery"
|
:needQuery="needQuery"
|
||||||
@click="clickHandle"
|
@click="clickHandle"
|
||||||
|
@ -35,6 +35,9 @@ limitations under the License. -->
|
|||||||
<div class="operation" @click="viewTrace(i)" v-show="refIdType === RefIdTypes[0].value">
|
<div class="operation" @click="viewTrace(i)" v-show="refIdType === RefIdTypes[0].value">
|
||||||
<span>{{ t("viewTrace") }}</span>
|
<span>{{ t("viewTrace") }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="operation" @click="viewDashboard(i)">
|
||||||
|
<span>{{ t("viewValueDashboard") }}</span>
|
||||||
|
</div>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<el-progress
|
<el-progress
|
||||||
@ -61,12 +64,14 @@ limitations under the License. -->
|
|||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
|
import router from "@/router";
|
||||||
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import copy from "@/utils/copy";
|
import copy from "@/utils/copy";
|
||||||
import { TextColors } from "@/views/dashboard/data";
|
import { TextColors, MetricCatalog } from "@/views/dashboard/data";
|
||||||
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
import Trace from "@/views/dashboard/related/trace/Index.vue";
|
||||||
import { WidgetType, QueryOrders, Status, RefIdTypes, ExpressionResultType } from "@/views/dashboard/data";
|
import { WidgetType, QueryOrders, Status, RefIdTypes, ExpressionResultType } from "@/views/dashboard/data";
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps, Recordable*/
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object as PropType<{
|
type: Object as PropType<{
|
||||||
@ -80,12 +85,14 @@ limitations under the License. -->
|
|||||||
expressions: string[];
|
expressions: string[];
|
||||||
typesOfMQE: string[];
|
typesOfMQE: string[];
|
||||||
relatedTrace: any;
|
relatedTrace: any;
|
||||||
|
valueRelatedDashboard: string;
|
||||||
}>,
|
}>,
|
||||||
default: () => ({ color: "purple" }),
|
default: () => ({ color: "purple" }),
|
||||||
},
|
},
|
||||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||||
});
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
const showTrace = ref<boolean>(false);
|
const showTrace = ref<boolean>(false);
|
||||||
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
const traceOptions = ref<{ type: string; filters?: unknown }>({
|
||||||
type: WidgetType.Trace,
|
type: WidgetType.Trace,
|
||||||
@ -122,6 +129,23 @@ limitations under the License. -->
|
|||||||
};
|
};
|
||||||
showTrace.value = true;
|
showTrace.value = true;
|
||||||
}
|
}
|
||||||
|
function viewDashboard(item: Recordable) {
|
||||||
|
const { owner } = item;
|
||||||
|
let path;
|
||||||
|
if (owner.scope === MetricCatalog.SERVICE) {
|
||||||
|
path = `/dashboard/${dashboardStore.layerId}/${owner.scope}/${owner.serviceID}/${props.config.valueRelatedDashboard}`;
|
||||||
|
}
|
||||||
|
if (owner.scope === MetricCatalog.SERVICE_INSTANCE) {
|
||||||
|
path = `/dashboard/${dashboardStore.layerId}/${owner.scope}/${owner.serviceID}/${owner.serviceInstanceID}/${props.config.valueRelatedDashboard}`;
|
||||||
|
}
|
||||||
|
if (owner.scope === MetricCatalog.ENDPOINT) {
|
||||||
|
path = `/dashboard/${dashboardStore.layerId}/${owner.scope}/${owner.serviceID}/${owner.endpointID}/${props.config.valueRelatedDashboard}`;
|
||||||
|
}
|
||||||
|
if (!path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push(path);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.top-list {
|
.top-list {
|
||||||
@ -187,11 +211,10 @@ limitations under the License. -->
|
|||||||
}
|
}
|
||||||
|
|
||||||
.operation {
|
.operation {
|
||||||
padding: 5px 0;
|
padding: 5px;
|
||||||
color: $font-color;
|
color: $font-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
text-align: center;
|
|
||||||
font-size: $font-size-smaller;
|
font-size: $font-size-smaller;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
Loading…
Reference in New Issue
Block a user