feat: support labeled value on the service/instance/endpoint list widgets (#177)

This commit is contained in:
Fine0830 2022-10-31 10:27:37 +08:00 committed by GitHub
parent e597f91448
commit 09051e916b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 235 additions and 108 deletions

View File

@ -26,14 +26,18 @@ export function useListConfig(config: any, index: string) {
config.metricConfig && config.metricConfig &&
config.metricConfig[i] && config.metricConfig[i] &&
config.metricConfig[i].calculation; config.metricConfig[i].calculation;
const line = const isLinear =
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues && [
!types.includes(calculation); MetricQueryTypes.ReadMetricsValues,
MetricQueryTypes.ReadLabeledMetricsValues,
].includes(config.metricTypes[i]) && !types.includes(calculation);
const isAvg = const isAvg =
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues && [
types.includes(calculation); MetricQueryTypes.ReadMetricsValues,
MetricQueryTypes.ReadLabeledMetricsValues,
].includes(config.metricTypes[i]) && types.includes(calculation);
return { return {
isLinear: line, isLinear,
isAvg, isAvg,
}; };
} }

View File

@ -154,6 +154,7 @@ export function useQueryProcessor(config: any) {
} }
}); });
const queryStr = `query queryData(${variables}) {${fragment}}`; const queryStr = `query queryData(${variables}) {${fragment}}`;
return { return {
queryStr, queryStr,
conditions, conditions,
@ -254,13 +255,19 @@ export function useSourceProcessor(
export function useQueryPodsMetrics( export function useQueryPodsMetrics(
pods: Array<Instance | Endpoint | Service | any>, pods: Array<Instance | Endpoint | Service | any>,
config: { metrics: string[]; metricTypes: string[] }, config: {
metrics: string[];
metricTypes: string[];
metricConfig: MetricConfigOpt[];
},
scope: string scope: string
) { ) {
if (!(config.metrics && config.metrics[0])) { const metricTypes = (config.metricTypes || []).filter((m: string) => m);
if (!metricTypes.length) {
return; return;
} }
if (!(config.metricTypes && config.metricTypes[0])) { const metrics = (config.metrics || []).filter((m: string) => m);
if (!metrics.length) {
return; return;
} }
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();
@ -282,14 +289,24 @@ export function useQueryPodsMetrics(
endpointName: scope === "Endpoint" ? d.label : undefined, endpointName: scope === "Endpoint" ? d.label : undefined,
normal: scope === "Service" ? d.normal : currentService.normal, normal: scope === "Service" ? d.normal : currentService.normal,
}; };
const f = config.metrics.map((name: string, idx: number) => { const f = metrics.map((name: string, idx: number) => {
const metricType = config.metricTypes[idx] || ""; const metricType = metricTypes[idx] || "";
variables.push(`$condition${index}${idx}: MetricsCondition!`);
conditions[`condition${index}${idx}`] = { conditions[`condition${index}${idx}`] = {
name, name,
entity: param, entity: param,
}; };
variables.push(`$condition${index}${idx}: MetricsCondition!`); let labelStr = "";
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, duration: $duration)${RespFields[metricType]}`; if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
const c = config.metricConfig[idx] || {};
variables.push(`$labels${index}${idx}: [String!]!`);
labelStr = `labels: $labels${index}${idx}, `;
const labels = (c.labelsIndex || "")
.split(",")
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
conditions[`labels${index}${idx}`] = labels;
}
return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, ${labelStr}duration: $duration)${RespFields[metricType]}`;
}); });
return f; return f;
} }
@ -299,6 +316,7 @@ export function useQueryPodsMetrics(
return { queryStr, conditions }; return { queryStr, conditions };
} }
export function usePodsSource( export function usePodsSource(
pods: Array<Instance | Endpoint>, pods: Array<Instance | Endpoint>,
resp: { errors: string; data: { [key: string]: any } }, resp: { errors: string; data: { [key: string]: any } },
@ -312,12 +330,20 @@ export function usePodsSource(
ElMessage.error(resp.errors); ElMessage.error(resp.errors);
return {}; return {};
} }
const names: string[] = [];
const metricConfigArr: MetricConfigOpt[] = [];
const metricTypesArr: string[] = [];
const data = pods.map((d: Instance | any, idx: number) => { const data = pods.map((d: Instance | any, idx: number) => {
config.metrics.map((name: string, index: number) => { config.metrics.map((name: string, index: number) => {
const c: any = (config.metricConfig && config.metricConfig[index]) || {}; const c: any = (config.metricConfig && config.metricConfig[index]) || {};
const key = name + idx + index; const key = name + idx + index;
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) { if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) {
d[name] = aggregation(resp.data[key], c); d[name] = aggregation(resp.data[key], c);
if (idx === 0) {
names.push(name);
metricConfigArr.push(c);
metricTypesArr.push(config.metricTypes[index]);
}
} }
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) { if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
d[name] = {}; d[name] = {};
@ -333,12 +359,56 @@ export function usePodsSource(
d[name]["values"] = resp.data[key].values.values.map( d[name]["values"] = resp.data[key].values.values.map(
(val: { value: number }) => aggregation(val.value, c) (val: { value: number }) => aggregation(val.value, c)
); );
if (idx === 0) {
names.push(name);
metricConfigArr.push(c);
metricTypesArr.push(config.metricTypes[index]);
}
}
if (
config.metricTypes[index] === MetricQueryTypes.ReadLabeledMetricsValues
) {
const resVal = resp.data[key] || [];
const labels = (c.label || "")
.split(",")
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
const labelsIdx = (c.labelsIndex || "")
.split(",")
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
for (let i = 0; i < resVal.length; i++) {
const item = resVal[i];
const values = item.values.values.map((d: { value: number }) =>
aggregation(Number(d.value), c)
);
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
let key = item.label;
if (labels[indexNum] && indexNum > -1) {
key = labels[indexNum];
}
if (!d[key]) {
d[key] = {};
}
if (
[
Calculations.Average,
Calculations.ApdexAvg,
Calculations.PercentageAvg,
].includes(c.calculation)
) {
d[key]["avg"] = calculateExp(item.values.values, c);
}
d[key]["values"] = values;
if (idx === 0) {
names.push(key);
metricConfigArr.push({ ...c, index: i });
metricTypesArr.push(config.metricTypes[index]);
}
}
} }
}); });
return d; return d;
}); });
return data; return { data, names, metricConfigArr, metricTypesArr };
} }
export function useQueryTopologyMetrics(metrics: string[], ids: string[]) { export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
const appStore = useAppStoreWithOut(); const appStore = useAppStoreWithOut();

View File

@ -74,6 +74,7 @@ export type MetricConfigOpt = {
labelsIndex: string; labelsIndex: string;
sortOrder: string; sortOrder: string;
topN?: number; topN?: number;
index?: number;
}; };
export interface WidgetConfig { export interface WidgetConfig {

View File

@ -191,7 +191,10 @@ async function setMetricType(chart?: any) {
states.metricList = (arr || []).filter( states.metricList = (arr || []).filter(
(d: { catalog: string; type: string }) => { (d: { catalog: string; type: string }) => {
if (states.isList) { if (states.isList) {
if (d.type === MetricsType.REGULAR_VALUE) { if (
d.type === MetricsType.REGULAR_VALUE ||
d.type === MetricsType.LABELED_VALUE
) {
return d; return d;
} }
} else if (g.type === "Table") { } else if (g.type === "Table") {
@ -239,7 +242,10 @@ async function setMetricType(chart?: any) {
} }
function setDashboards(type?: string) { 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 list = JSON.parse(sessionStorage.getItem("dashboards") || "[]");
const arr = list.reduce( const arr = list.reduce(
( (
@ -248,9 +254,9 @@ function setDashboards(type?: string) {
) => { ) => {
if (d.layer === dashboardStore.layerId) { if (d.layer === dashboardStore.layerId) {
if ( if (
(d.entity === EntityType[0].value && chart.type === "ServiceList") || (d.entity === EntityType[0].value && chart === "ServiceList") ||
(d.entity === EntityType[2].value && chart.type === "EndpointList") || (d.entity === EntityType[2].value && chart === "EndpointList") ||
(d.entity === EntityType[3].value && chart.type === "InstanceList") (d.entity === EntityType[3].value && chart === "InstanceList")
) { ) {
prev.push({ prev.push({
...d, ...d,

View File

@ -115,7 +115,9 @@ const currentMetric = ref<MetricConfigOpt>({
topN: props.currentMetricConfig.topN || 10, topN: props.currentMetricConfig.topN || 10,
}); });
const metricTypes = dashboardStore.selectedGrid.metricTypes || []; const metricTypes = dashboardStore.selectedGrid.metricTypes || [];
const metricType = ref<string>(metricTypes[props.index]); const metricType = computed(
() => (dashboardStore.selectedGrid.metricTypes || [])[props.index]
);
const hasLabel = computed(() => { const hasLabel = computed(() => {
const graph = dashboardStore.selectedGrid.graph || {}; const graph = dashboardStore.selectedGrid.graph || {};
return ( return (

View File

@ -62,7 +62,7 @@ limitations under the License. -->
metricTypes: data.metricTypes || [''], metricTypes: data.metricTypes || [''],
i: data.i, i: data.i,
id: data.id, id: data.id,
metricConfig: data.metricConfig, metricConfig: data.metricConfig || [],
filters: data.filters || {}, filters: data.filters || {},
relatedTrace: data.relatedTrace || {}, relatedTrace: data.relatedTrace || {},
}" }"

View File

@ -31,7 +31,7 @@ limitations under the License. -->
</div> </div>
<div class="list"> <div class="list">
<el-table v-loading="chartLoading" :data="endpoints" style="width: 100%"> <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"> <template #default="scope">
<span <span
class="link" class="link"
@ -45,7 +45,12 @@ limitations under the License. -->
<ColumnGraph <ColumnGraph
:intervalTime="intervalTime" :intervalTime="intervalTime"
:colMetrics="colMetrics" :colMetrics="colMetrics"
:config="config" :config="{
...config,
metrics: colMetrics,
metricConfig,
metricTypes,
}"
v-if="colMetrics.length" v-if="colMetrics.length"
/> />
</el-table> </el-table>
@ -53,7 +58,7 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, computed } from "vue"; import { ref, watch } from "vue";
import { useSelectorStore } from "@/store/modules/selectors"; import { useSelectorStore } from "@/store/modules/selectors";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
@ -99,9 +104,9 @@ const dashboardStore = useDashboardStore();
const chartLoading = ref<boolean>(false); const chartLoading = ref<boolean>(false);
const endpoints = ref<Endpoint[]>([]); const endpoints = ref<Endpoint[]>([]);
const searchText = ref<string>(""); const searchText = ref<string>("");
const colMetrics = computed(() => const colMetrics = ref<string[]>([]);
(props.config.metrics || []).filter((d: string) => d) const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
); const metricTypes = ref<string[]>(props.config.metricTypes || []);
if (props.needQuery) { if (props.needQuery) {
queryEndpoints(); queryEndpoints();
@ -125,8 +130,8 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
return; return;
} }
const metrics = props.config.metrics || []; 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( const params = await useQueryPodsMetrics(
currentPods, currentPods,
props.config, props.config,
@ -138,12 +143,18 @@ async function queryEndpointMetrics(currentPods: Endpoint[]) {
ElMessage.error(json.errors); ElMessage.error(json.errors);
return; return;
} }
const metricConfig = props.config.metricConfig || []; const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
currentPods,
endpoints.value = usePodsSource(currentPods, json, { json,
...props.config, {
metricConfig: metricConfig, ...props.config,
}); metricConfig: metricConfig.value,
}
);
endpoints.value = data;
colMetrics.value = names;
metricTypes.value = metricTypesArr;
metricConfig.value = metricConfigArr;
return; return;
} }
endpoints.value = currentPods; endpoints.value = currentPods;
@ -166,11 +177,16 @@ async function searchList() {
await queryEndpoints(); await queryEndpoints();
} }
watch( watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])], () => [
...(props.config.metricTypes || []),
...(props.config.metrics || []),
...(props.config.metricConfig || []),
],
(data, old) => { (data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) { if (JSON.stringify(data) === JSON.stringify(old)) {
return; return;
} }
metricConfig.value = props.config.metricConfig;
queryEndpointMetrics(endpoints.value); queryEndpointMetrics(endpoints.value);
} }
); );
@ -180,15 +196,6 @@ watch(
queryEndpoints(); queryEndpoints();
} }
); );
watch(
() => [...(props.config.metricConfig || [])],
(data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
queryEndpointMetrics(endpoints.value);
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "./style.scss"; @import "./style.scss";

View File

@ -30,7 +30,7 @@ limitations under the License. -->
</div> </div>
<div class="list"> <div class="list">
<el-table v-loading="chartLoading" :data="instances" style="width: 100%"> <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"> <template #default="scope">
<span <span
class="link" class="link"
@ -42,12 +42,17 @@ limitations under the License. -->
</template> </template>
</el-table-column> </el-table-column>
<ColumnGraph <ColumnGraph
v-if="colMetrics.length"
:intervalTime="intervalTime" :intervalTime="intervalTime"
:colMetrics="colMetrics" :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"> <template #default="scope">
<el-popover placement="left" :width="400" trigger="click"> <el-popover placement="left" :width="400" trigger="click">
<template #reference> <template #reference>
@ -82,7 +87,7 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch, computed } from "vue"; import { ref, watch } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import type { PropType } from "vue"; import type { PropType } from "vue";
@ -126,9 +131,9 @@ const chartLoading = ref<boolean>(false);
const instances = ref<Instance[]>([]); // current instances const instances = ref<Instance[]>([]); // current instances
const pageSize = 10; const pageSize = 10;
const searchText = ref<string>(""); const searchText = ref<string>("");
const colMetrics = computed(() => const colMetrics = ref<string[]>([]);
(props.config.metrics || []).filter((d: string) => d) const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
); const metricTypes = ref<string[]>(props.config.metricTypes || []);
if (props.needQuery) { if (props.needQuery) {
queryInstance(); queryInstance();
} }
@ -154,9 +159,9 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
return; return;
} }
const metrics = props.config.metrics || []; 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( const params = await useQueryPodsMetrics(
currentInstances, currentInstances,
props.config, props.config,
@ -168,11 +173,18 @@ async function queryInstanceMetrics(currentInstances: Instance[]) {
ElMessage.error(json.errors); ElMessage.error(json.errors);
return; return;
} }
const metricConfig = props.config.metricConfig || []; const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
instances.value = usePodsSource(currentInstances, json, { currentInstances,
...props.config, json,
metricConfig, {
}); ...props.config,
metricConfig: metricConfig.value,
}
);
instances.value = data;
colMetrics.value = names;
metricTypes.value = metricTypesArr;
metricConfig.value = metricConfigArr;
return; return;
} }
instances.value = currentInstances; instances.value = currentInstances;
@ -215,11 +227,16 @@ function searchList() {
} }
watch( watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])], () => [
...(props.config.metricTypes || []),
...(props.config.metrics || []),
...(props.config.metricConfig || []),
],
(data, old) => { (data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) { if (JSON.stringify(data) === JSON.stringify(old)) {
return; return;
} }
metricConfig.value = props.config.metricConfig;
queryInstanceMetrics(instances.value); queryInstanceMetrics(instances.value);
} }
); );
@ -229,15 +246,6 @@ watch(
queryInstance(); queryInstance();
} }
); );
watch(
() => [...(props.config.metricConfig || [])],
(data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
queryInstanceMetrics(instances.value);
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import "./style.scss"; @import "./style.scss";

View File

@ -42,9 +42,9 @@ const props = defineProps({
config: { config: {
type: Object as PropType< type: Object as PropType<
LineConfig & { LineConfig & {
filters: Filters; filters?: Filters;
relatedTrace: RelatedTrace; relatedTrace?: RelatedTrace;
} & { id: string } } & { id?: string }
>, >,
default: () => ({ default: () => ({
step: false, step: false,

View File

@ -37,12 +37,17 @@ limitations under the License. -->
:border="true" :border="true"
:style="{ fontSize: '14px' }" :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"> <template #default="scope">
{{ scope.row.group }} {{ scope.row.group }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="Service Names"> <el-table-column fixed label="Service Names" min-width="220">
<template #default="scope"> <template #default="scope">
<span <span
class="link" class="link"
@ -56,7 +61,12 @@ limitations under the License. -->
<ColumnGraph <ColumnGraph
:intervalTime="intervalTime" :intervalTime="intervalTime"
:colMetrics="colMetrics" :colMetrics="colMetrics"
:config="config" :config="{
...config,
metrics: colMetrics,
metricConfig,
metricTypes,
}"
v-if="colMetrics.length" v-if="colMetrics.length"
/> />
</el-table> </el-table>
@ -75,7 +85,7 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { watch, ref, computed } from "vue"; import { watch, ref } from "vue";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import type { PropType } from "vue"; import type { PropType } from "vue";
import { ServiceListConfig } from "@/types/dashboard"; import { ServiceListConfig } from "@/types/dashboard";
@ -102,7 +112,9 @@ const props = defineProps({
metrics: string[]; metrics: string[];
metricTypes: string[]; metricTypes: string[];
isEdit: boolean; isEdit: boolean;
} & { metricConfig: MetricConfigOpt[] } names: string[];
metricConfig: MetricConfigOpt[];
}
>, >,
default: () => ({ dashboardName: "", fontSize: 12 }), default: () => ({ dashboardName: "", fontSize: 12 }),
}, },
@ -115,12 +127,13 @@ const appStore = useAppStoreWithOut();
const chartLoading = ref<boolean>(false); const chartLoading = ref<boolean>(false);
const pageSize = 10; const pageSize = 10;
const services = ref<Service[]>([]); const services = ref<Service[]>([]);
const colMetrics = ref<string[]>([]);
const searchText = ref<string>(""); const searchText = ref<string>("");
const groups = ref<any>({}); const groups = ref<any>({});
const sortServices = ref<(Service & { merge: boolean })[]>([]); const sortServices = ref<(Service & { merge: boolean })[]>([]);
const colMetrics = computed(() => const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
(props.config.metrics || []).filter((d: string) => d) const metricTypes = ref<string[]>(props.config.metricTypes || []);
);
queryServices(); queryServices();
async function queryServices() { async function queryServices() {
@ -198,12 +211,12 @@ async function queryServiceMetrics(currentServices: Service[]) {
return; return;
} }
const metrics = props.config.metrics || []; 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( const params = await useQueryPodsMetrics(
currentServices, currentServices,
props.config, { ...props.config, metricConfig: metricConfig.value || [] },
EntityType[0].value EntityType[0].value
); );
const json = await dashboardStore.fetchMetricValue(params); const json = await dashboardStore.fetchMetricValue(params);
@ -212,14 +225,22 @@ async function queryServiceMetrics(currentServices: Service[]) {
ElMessage.error(json.errors); ElMessage.error(json.errors);
return; return;
} }
const metricConfig = props.config.metricConfig || [];
services.value = usePodsSource(currentServices, json, { const { data, names, metricConfigArr, metricTypesArr } = usePodsSource(
...props.config, currentServices,
metricConfig: metricConfig || [], json,
}); {
...props.config,
metricConfig: metricConfig.value || [],
}
);
services.value = data;
colMetrics.value = names;
metricTypes.value = metricTypesArr;
metricConfig.value = metricConfigArr;
return; return;
} }
services.value = currentServices; services.value = currentServices;
} }
function objectSpanMethod(param: any): any { function objectSpanMethod(param: any): any {
@ -257,20 +278,16 @@ function searchList() {
} }
watch( watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])], () => [
(data, old) => { ...(props.config.metricTypes || []),
if (JSON.stringify(data) === JSON.stringify(old)) { ...(props.config.metrics || []),
return; ...(props.config.metricConfig || []),
} ],
queryServiceMetrics(services.value);
}
);
watch(
() => [...(props.config.metricConfig || [])],
(data, old) => { (data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) { if (JSON.stringify(data) === JSON.stringify(old)) {
return; return;
} }
metricConfig.value = props.config.metricConfig;
queryServiceMetrics(services.value); queryServiceMetrics(services.value);
} }
); );

View File

@ -20,6 +20,7 @@ limitations under the License. -->
getLabel(metric, index) getLabel(metric, index)
)} ${decodeURIComponent(getUnit(index))}`" )} ${decodeURIComponent(getUnit(index))}`"
:key="metric + index" :key="metric + index"
min-width="150"
> >
<template #default="scope"> <template #default="scope">
<div class="chart"> <div class="chart">
@ -90,18 +91,18 @@ import { MetricConfigOpt } from "@/types/dashboard";
import { useListConfig } from "@/hooks/useListConfig"; import { useListConfig } from "@/hooks/useListConfig";
import Line from "../Line.vue"; import Line from "../Line.vue";
import Card from "../Card.vue"; import Card from "../Card.vue";
import { MetricQueryTypes } from "@/hooks/data";
/*global defineProps */ /*global defineProps */
const props = defineProps({ const props = defineProps({
colMetrics: { type: Object }, colMetrics: { type: Object },
config: { config: {
type: Object as PropType< type: Object as PropType<{
{ i: string;
i: string; metrics: string[];
metrics: string[]; metricTypes: string[];
metricTypes: string[]; metricConfig: MetricConfigOpt[];
} & { metricConfig: MetricConfigOpt[] } }>,
>,
default: () => ({}), default: () => ({}),
}, },
intervalTime: { type: Array as PropType<string[]>, 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] &&
props.config.metricConfig[i].label; props.config.metricConfig[i].label;
if (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(label);
} }
return encodeURIComponent(metric); return encodeURIComponent(metric);
@ -157,5 +168,6 @@ function getLabel(metric: string, index: string) {
display: inline-block; display: inline-block;
flex-grow: 2; flex-grow: 2;
height: 100%; height: 100%;
width: calc(100% - 30px);
} }
</style> </style>