mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-10-15 04:09:14 +00:00
feat: support labeled value on the service/instance/endpoint list widgets (#177)
This commit is contained in:
@@ -191,7 +191,10 @@ async function setMetricType(chart?: any) {
|
||||
states.metricList = (arr || []).filter(
|
||||
(d: { catalog: string; type: string }) => {
|
||||
if (states.isList) {
|
||||
if (d.type === MetricsType.REGULAR_VALUE) {
|
||||
if (
|
||||
d.type === MetricsType.REGULAR_VALUE ||
|
||||
d.type === MetricsType.LABELED_VALUE
|
||||
) {
|
||||
return d;
|
||||
}
|
||||
} else if (g.type === "Table") {
|
||||
@@ -239,7 +242,10 @@ async function setMetricType(chart?: any) {
|
||||
}
|
||||
|
||||
function setDashboards(type?: string) {
|
||||
const chart = type || dashboardStore.selectedGrid.graph || {};
|
||||
const chart =
|
||||
type ||
|
||||
(dashboardStore.selectedGrid.graph &&
|
||||
dashboardStore.selectedGrid.graph.type);
|
||||
const list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
|
||||
const arr = list.reduce(
|
||||
(
|
||||
@@ -248,9 +254,9 @@ function setDashboards(type?: string) {
|
||||
) => {
|
||||
if (d.layer === dashboardStore.layerId) {
|
||||
if (
|
||||
(d.entity === EntityType[0].value && chart.type === "ServiceList") ||
|
||||
(d.entity === EntityType[2].value && chart.type === "EndpointList") ||
|
||||
(d.entity === EntityType[3].value && chart.type === "InstanceList")
|
||||
(d.entity === EntityType[0].value && chart === "ServiceList") ||
|
||||
(d.entity === EntityType[2].value && chart === "EndpointList") ||
|
||||
(d.entity === EntityType[3].value && chart === "InstanceList")
|
||||
) {
|
||||
prev.push({
|
||||
...d,
|
||||
|
@@ -115,7 +115,9 @@ const currentMetric = ref<MetricConfigOpt>({
|
||||
topN: props.currentMetricConfig.topN || 10,
|
||||
});
|
||||
const metricTypes = dashboardStore.selectedGrid.metricTypes || [];
|
||||
const metricType = ref<string>(metricTypes[props.index]);
|
||||
const metricType = computed(
|
||||
() => (dashboardStore.selectedGrid.metricTypes || [])[props.index]
|
||||
);
|
||||
const hasLabel = computed(() => {
|
||||
const graph = dashboardStore.selectedGrid.graph || {};
|
||||
return (
|
||||
|
@@ -62,7 +62,7 @@ limitations under the License. -->
|
||||
metricTypes: data.metricTypes || [''],
|
||||
i: data.i,
|
||||
id: data.id,
|
||||
metricConfig: data.metricConfig,
|
||||
metricConfig: data.metricConfig || [],
|
||||
filters: data.filters || {},
|
||||
relatedTrace: data.relatedTrace || {},
|
||||
}"
|
||||
|
@@ -31,7 +31,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
<div class="list">
|
||||
<el-table v-loading="chartLoading" :data="endpoints" style="width: 100%">
|
||||
<el-table-column label="Endpoints">
|
||||
<el-table-column label="Endpoints" fixed min-width="220">
|
||||
<template #default="scope">
|
||||
<span
|
||||
class="link"
|
||||
@@ -45,7 +45,12 @@ limitations under the License. -->
|
||||
<ColumnGraph
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
:config="{
|
||||
...config,
|
||||
metrics: colMetrics,
|
||||
metricConfig,
|
||||
metricTypes,
|
||||
}"
|
||||
v-if="colMetrics.length"
|
||||
/>
|
||||
</el-table>
|
||||
@@ -53,7 +58,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, computed } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { useI18n } from "vue-i18n";
|
||||
@@ -99,9 +104,9 @@ const dashboardStore = useDashboardStore();
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const endpoints = ref<Endpoint[]>([]);
|
||||
const searchText = ref<string>("");
|
||||
const colMetrics = computed(() =>
|
||||
(props.config.metrics || []).filter((d: string) => d)
|
||||
);
|
||||
const colMetrics = ref<string[]>([]);
|
||||
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
|
||||
const metricTypes = ref<string[]>(props.config.metricTypes || []);
|
||||
|
||||
if (props.needQuery) {
|
||||
queryEndpoints();
|
||||
@@ -125,8 +130,8 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
||||
return;
|
||||
}
|
||||
const metrics = props.config.metrics || [];
|
||||
const metricTypes = props.config.metricTypes || [];
|
||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||
const types = props.config.metricTypes || [];
|
||||
if (metrics.length && metrics[0] && types.length && types[0]) {
|
||||
const params = await useQueryPodsMetrics(
|
||||
currentPods,
|
||||
props.config,
|
||||
@@ -138,12 +143,18 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
const metricConfig = props.config.metricConfig || [];
|
||||
|
||||
endpoints.value = usePodsSource(currentPods, json, {
|
||||
...props.config,
|
||||
metricConfig: metricConfig,
|
||||
});
|
||||
const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
|
||||
currentPods,
|
||||
json,
|
||||
{
|
||||
...props.config,
|
||||
metricConfig: metricConfig.value,
|
||||
}
|
||||
);
|
||||
endpoints.value = data;
|
||||
colMetrics.value = names;
|
||||
metricTypes.value = metricTypesArr;
|
||||
metricConfig.value = metricConfigArr;
|
||||
return;
|
||||
}
|
||||
endpoints.value = currentPods;
|
||||
@@ -166,11 +177,16 @@ async function searchList() {
|
||||
await queryEndpoints();
|
||||
}
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
() => [
|
||||
...(props.config.metricTypes || []),
|
||||
...(props.config.metrics || []),
|
||||
...(props.config.metricConfig || []),
|
||||
],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
metricConfig.value = props.config.metricConfig;
|
||||
queryEndpointMetrics(endpoints.value);
|
||||
}
|
||||
);
|
||||
@@ -180,15 +196,6 @@ watch(
|
||||
queryEndpoints();
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => [...(props.config.metricConfig || [])],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
queryEndpointMetrics(endpoints.value);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "./style.scss";
|
||||
|
@@ -30,7 +30,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
<div class="list">
|
||||
<el-table v-loading="chartLoading" :data="instances" style="width: 100%">
|
||||
<el-table-column label="Service Instances">
|
||||
<el-table-column label="Service Instances" fixed min-width="320">
|
||||
<template #default="scope">
|
||||
<span
|
||||
class="link"
|
||||
@@ -42,12 +42,17 @@ limitations under the License. -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
<ColumnGraph
|
||||
v-if="colMetrics.length"
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
:config="{
|
||||
...config,
|
||||
metrics: colMetrics,
|
||||
metricConfig,
|
||||
metricTypes,
|
||||
}"
|
||||
v-if="colMetrics.length"
|
||||
/>
|
||||
<el-table-column label="Attributes">
|
||||
<el-table-column label="Attributes" fixed="right" min-width="100">
|
||||
<template #default="scope">
|
||||
<el-popover placement="left" :width="400" trigger="click">
|
||||
<template #reference>
|
||||
@@ -82,7 +87,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ref, watch, computed } from "vue";
|
||||
import { ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { PropType } from "vue";
|
||||
@@ -126,9 +131,9 @@ const chartLoading = ref<boolean>(false);
|
||||
const instances = ref<Instance[]>([]); // current instances
|
||||
const pageSize = 10;
|
||||
const searchText = ref<string>("");
|
||||
const colMetrics = computed(() =>
|
||||
(props.config.metrics || []).filter((d: string) => d)
|
||||
);
|
||||
const colMetrics = ref<string[]>([]);
|
||||
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
|
||||
const metricTypes = ref<string[]>(props.config.metricTypes || []);
|
||||
if (props.needQuery) {
|
||||
queryInstance();
|
||||
}
|
||||
@@ -154,9 +159,9 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
|
||||
return;
|
||||
}
|
||||
const metrics = props.config.metrics || [];
|
||||
const metricTypes = props.config.metricTypes || [];
|
||||
const types = props.config.metricTypes || [];
|
||||
|
||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||
if (metrics.length && metrics[0] && types.length && types[0]) {
|
||||
const params = await useQueryPodsMetrics(
|
||||
currentInstances,
|
||||
props.config,
|
||||
@@ -168,11 +173,18 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
const metricConfig = props.config.metricConfig || [];
|
||||
instances.value = usePodsSource(currentInstances, json, {
|
||||
...props.config,
|
||||
metricConfig,
|
||||
});
|
||||
const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
|
||||
currentInstances,
|
||||
json,
|
||||
{
|
||||
...props.config,
|
||||
metricConfig: metricConfig.value,
|
||||
}
|
||||
);
|
||||
instances.value = data;
|
||||
colMetrics.value = names;
|
||||
metricTypes.value = metricTypesArr;
|
||||
metricConfig.value = metricConfigArr;
|
||||
return;
|
||||
}
|
||||
instances.value = currentInstances;
|
||||
@@ -215,11 +227,16 @@ function searchList() {
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
() => [
|
||||
...(props.config.metricTypes || []),
|
||||
...(props.config.metrics || []),
|
||||
...(props.config.metricConfig || []),
|
||||
],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
metricConfig.value = props.config.metricConfig;
|
||||
queryInstanceMetrics(instances.value);
|
||||
}
|
||||
);
|
||||
@@ -229,15 +246,6 @@ watch(
|
||||
queryInstance();
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => [...(props.config.metricConfig || [])],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
queryInstanceMetrics(instances.value);
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "./style.scss";
|
||||
|
@@ -42,9 +42,9 @@ const props = defineProps({
|
||||
config: {
|
||||
type: Object as PropType<
|
||||
LineConfig & {
|
||||
filters: Filters;
|
||||
relatedTrace: RelatedTrace;
|
||||
} & { id: string }
|
||||
filters?: Filters;
|
||||
relatedTrace?: RelatedTrace;
|
||||
} & { id?: string }
|
||||
>,
|
||||
default: () => ({
|
||||
step: false,
|
||||
|
@@ -37,12 +37,17 @@ limitations under the License. -->
|
||||
:border="true"
|
||||
:style="{ fontSize: '14px' }"
|
||||
>
|
||||
<el-table-column label="Service Groups" v-if="config.showGroup">
|
||||
<el-table-column
|
||||
fixed
|
||||
label="Service Groups"
|
||||
v-if="config.showGroup"
|
||||
min-width="150"
|
||||
>
|
||||
<template #default="scope">
|
||||
{{ scope.row.group }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Service Names">
|
||||
<el-table-column fixed label="Service Names" min-width="220">
|
||||
<template #default="scope">
|
||||
<span
|
||||
class="link"
|
||||
@@ -56,7 +61,12 @@ limitations under the License. -->
|
||||
<ColumnGraph
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
:config="{
|
||||
...config,
|
||||
metrics: colMetrics,
|
||||
metricConfig,
|
||||
metricTypes,
|
||||
}"
|
||||
v-if="colMetrics.length"
|
||||
/>
|
||||
</el-table>
|
||||
@@ -75,7 +85,7 @@ limitations under the License. -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { watch, ref, computed } from "vue";
|
||||
import { watch, ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { PropType } from "vue";
|
||||
import { ServiceListConfig } from "@/types/dashboard";
|
||||
@@ -102,7 +112,9 @@ const props = defineProps({
|
||||
metrics: string[];
|
||||
metricTypes: string[];
|
||||
isEdit: boolean;
|
||||
} & { metricConfig: MetricConfigOpt[] }
|
||||
names: string[];
|
||||
metricConfig: MetricConfigOpt[];
|
||||
}
|
||||
>,
|
||||
default: () => ({ dashboardName: "", fontSize: 12 }),
|
||||
},
|
||||
@@ -115,12 +127,13 @@ const appStore = useAppStoreWithOut();
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const pageSize = 10;
|
||||
const services = ref<Service[]>([]);
|
||||
const colMetrics = ref<string[]>([]);
|
||||
const searchText = ref<string>("");
|
||||
const groups = ref<any>({});
|
||||
const sortServices = ref<(Service & { merge: boolean })[]>([]);
|
||||
const colMetrics = computed(() =>
|
||||
(props.config.metrics || []).filter((d: string) => d)
|
||||
);
|
||||
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
|
||||
const metricTypes = ref<string[]>(props.config.metricTypes || []);
|
||||
|
||||
queryServices();
|
||||
|
||||
async function queryServices() {
|
||||
@@ -198,12 +211,12 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
||||
return;
|
||||
}
|
||||
const metrics = props.config.metrics || [];
|
||||
const metricTypes = props.config.metricTypes || [];
|
||||
const types = props.config.metricTypes || [];
|
||||
|
||||
if (metrics.length && metrics[0] && metricTypes.length && metricTypes[0]) {
|
||||
if (metrics.length && metrics[0] && types.length && types[0]) {
|
||||
const params = await useQueryPodsMetrics(
|
||||
currentServices,
|
||||
props.config,
|
||||
{ ...props.config, metricConfig: metricConfig.value || [] },
|
||||
EntityType[0].value
|
||||
);
|
||||
const json = await dashboardStore.fetchMetricValue(params);
|
||||
@@ -212,14 +225,22 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
const metricConfig = props.config.metricConfig || [];
|
||||
services.value = usePodsSource(currentServices, json, {
|
||||
...props.config,
|
||||
metricConfig: metricConfig || [],
|
||||
});
|
||||
|
||||
const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
|
||||
currentServices,
|
||||
json,
|
||||
{
|
||||
...props.config,
|
||||
metricConfig: metricConfig.value || [],
|
||||
}
|
||||
);
|
||||
services.value = data;
|
||||
colMetrics.value = names;
|
||||
metricTypes.value = metricTypesArr;
|
||||
metricConfig.value = metricConfigArr;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
services.value = currentServices;
|
||||
}
|
||||
function objectSpanMethod(param: any): any {
|
||||
@@ -257,20 +278,16 @@ function searchList() {
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
queryServiceMetrics(services.value);
|
||||
}
|
||||
);
|
||||
watch(
|
||||
() => [...(props.config.metricConfig || [])],
|
||||
() => [
|
||||
...(props.config.metricTypes || []),
|
||||
...(props.config.metrics || []),
|
||||
...(props.config.metricConfig || []),
|
||||
],
|
||||
(data, old) => {
|
||||
if (JSON.stringify(data) === JSON.stringify(old)) {
|
||||
return;
|
||||
}
|
||||
metricConfig.value = props.config.metricConfig;
|
||||
queryServiceMetrics(services.value);
|
||||
}
|
||||
);
|
||||
|
@@ -20,6 +20,7 @@ limitations under the License. -->
|
||||
getLabel(metric, index)
|
||||
)} ${decodeURIComponent(getUnit(index))}`"
|
||||
:key="metric + index"
|
||||
min-width="150"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="chart">
|
||||
@@ -90,18 +91,18 @@ import { MetricConfigOpt } from "@/types/dashboard";
|
||||
import { useListConfig } from "@/hooks/useListConfig";
|
||||
import Line from "../Line.vue";
|
||||
import Card from "../Card.vue";
|
||||
import { MetricQueryTypes } from "@/hooks/data";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
colMetrics: { type: Object },
|
||||
config: {
|
||||
type: Object as PropType<
|
||||
{
|
||||
i: string;
|
||||
metrics: string[];
|
||||
metricTypes: string[];
|
||||
} & { metricConfig: MetricConfigOpt[] }
|
||||
>,
|
||||
type: Object as PropType<{
|
||||
i: string;
|
||||
metrics: string[];
|
||||
metricTypes: string[];
|
||||
metricConfig: MetricConfigOpt[];
|
||||
}>,
|
||||
default: () => ({}),
|
||||
},
|
||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||
@@ -125,6 +126,16 @@ function getLabel(metric: string, index: string) {
|
||||
props.config.metricConfig[i] &&
|
||||
props.config.metricConfig[i].label;
|
||||
if (label) {
|
||||
if (
|
||||
props.config.metricTypes[i] === MetricQueryTypes.ReadLabeledMetricsValues
|
||||
) {
|
||||
const name = (label || "")
|
||||
.split(",")
|
||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""))[
|
||||
props.config.metricConfig[i].index || 0
|
||||
];
|
||||
return encodeURIComponent(name || "");
|
||||
}
|
||||
return encodeURIComponent(label);
|
||||
}
|
||||
return encodeURIComponent(metric);
|
||||
@@ -157,5 +168,6 @@ function getLabel(metric: string, index: string) {
|
||||
display: inline-block;
|
||||
flex-grow: 2;
|
||||
height: 100%;
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user