feat: supporting expressions to query metrics data (#270)

This commit is contained in:
Fine0830
2023-06-04 14:09:36 +08:00
committed by GitHub
parent ec67b4148c
commit dc22f8da6e
22 changed files with 923 additions and 105 deletions

View File

@@ -23,6 +23,7 @@ limitations under the License. -->
import type { PropType } from "vue";
import type { BarConfig, EventParams, RelatedTrace, Filters } from "@/types/dashboard";
import useLegendProcess from "@/hooks/useLegendProcessor";
import Legend from "./components/Legend.vue";
/*global defineProps, defineEmits */
const emits = defineEmits(["click"]);

View File

@@ -41,6 +41,7 @@ limitations under the License. -->
metrics: colMetrics,
metricConfig,
metricTypes,
metricMode,
}"
v-if="colMetrics.length"
/>
@@ -58,7 +59,8 @@ limitations under the License. -->
import type { Endpoint } from "@/types/selector";
import { useDashboardStore } from "@/store/modules/dashboard";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useMetricsProcessor";
import { EntityType } from "../data";
import { useExpressionsQueryPodsMetrics } from "@/hooks/useExpressionsProcessor";
import { EntityType, MetricModes } from "../data";
import router from "@/router";
import getDashboard from "@/hooks/useDashboardsSession";
import type { MetricConfigOpt } from "@/types/dashboard";
@@ -75,6 +77,11 @@ limitations under the License. -->
i: string;
metrics: string[];
metricTypes: string[];
metricMode: string;
expressions: string[];
typesOfMQE: string[];
subExpressions: string[];
subTypesOfMQE: string[];
} & { metricConfig: MetricConfigOpt[] }
>,
default: () => ({
@@ -98,6 +105,7 @@ limitations under the License. -->
const colMetrics = ref<string[]>([]);
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
const metricTypes = ref<string[]>(props.config.metricTypes || []);
const metricMode = ref<string>(props.config.metricMode);
if (props.needQuery) {
queryEndpoints();
@@ -116,8 +124,20 @@ limitations under the License. -->
endpoints.value = resp.data.pods || [];
queryEndpointMetrics(endpoints.value);
}
async function queryEndpointMetrics(currentPods: Endpoint[]) {
if (!currentPods.length) {
async function queryEndpointMetrics(arr: Endpoint[]) {
if (!arr.length) {
return;
}
const currentPods = arr.map((d: Endpoint) => {
return {
id: d.id,
value: d.value,
label: d.label,
merge: d.merge,
};
});
if (props.config.metricMode === MetricModes.Expression) {
queryEndpointExpressions(currentPods);
return;
}
const metrics = props.config.metrics || [];
@@ -141,6 +161,32 @@ limitations under the License. -->
return;
}
endpoints.value = currentPods;
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
async function queryEndpointExpressions(currentPods: Endpoint[]) {
const expressions = props.config.expressions || [];
const typesOfMQE = props.config.typesOfMQE || [];
const subExpressions = props.config.subExpressions || [];
if (expressions.length && expressions[0] && typesOfMQE.length && typesOfMQE[0]) {
const params = await useExpressionsQueryPodsMetrics(
currentPods,
{ ...props.config, metricConfig: metricConfig.value || [], typesOfMQE, expressions, subExpressions },
EntityType[2].value,
);
endpoints.value = params.data;
colMetrics.value = params.names;
metricTypes.value = params.metricTypesArr;
metricConfig.value = params.metricConfigArr;
return;
}
endpoints.value = currentPods;
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
function clickEndpoint(scope: any) {
const { dashboard } = getDashboard({
@@ -160,12 +206,19 @@ limitations under the License. -->
await queryEndpoints();
}
watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || []), ...(props.config.metricConfig || [])],
() => [
...(props.config.metricTypes || []),
...(props.config.metrics || []),
...(props.config.metricConfig || []),
...(props.config.expressions || []),
props.config.metricMode,
],
(data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
metricConfig.value = props.config.metricConfig;
metricMode.value = props.config.metricMode;
queryEndpointMetrics(endpoints.value);
},
);

View File

@@ -40,6 +40,7 @@ limitations under the License. -->
metrics: colMetrics,
metricConfig,
metricTypes,
metricMode,
}"
v-if="colMetrics.length"
/>
@@ -87,7 +88,8 @@ limitations under the License. -->
import type { InstanceListConfig } from "@/types/dashboard";
import type { Instance } from "@/types/selector";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useMetricsProcessor";
import { EntityType } from "../data";
import { useExpressionsQueryPodsMetrics } from "@/hooks/useExpressionsProcessor";
import { EntityType, MetricModes } from "../data";
import router from "@/router";
import getDashboard from "@/hooks/useDashboardsSession";
import type { MetricConfigOpt } from "@/types/dashboard";
@@ -102,6 +104,11 @@ limitations under the License. -->
metrics: string[];
metricTypes: string[];
isEdit: boolean;
metricMode: string;
expressions: string[];
typesOfMQE: string[];
subExpressions: string[];
subTypesOfMQE: string[];
} & { metricConfig: MetricConfigOpt[] }
>,
default: () => ({
@@ -126,6 +133,7 @@ limitations under the License. -->
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
const metricTypes = ref<string[]>(props.config.metricTypes || []);
const pods = ref<Instance[]>([]); // all instances
const metricMode = ref<string>(props.config.metricMode);
if (props.needQuery) {
queryInstance();
}
@@ -146,8 +154,23 @@ limitations under the License. -->
queryInstanceMetrics(instances.value);
}
async function queryInstanceMetrics(currentInstances: Instance[]) {
if (!currentInstances.length) {
async function queryInstanceMetrics(arr: Instance[]) {
if (!arr.length) {
return;
}
const currentInstances = arr.map((d: Instance) => {
return {
id: d.id,
value: d.value,
label: d.label,
merge: d.merge,
language: d.language,
instanceUUID: d.instanceUUID,
attributes: d.attributes,
};
});
if (props.config.metricMode === MetricModes.Expression) {
queryInstanceExpressions(currentInstances);
return;
}
const metrics = props.config.metrics || [];
@@ -172,6 +195,33 @@ limitations under the License. -->
return;
}
instances.value = currentInstances;
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
async function queryInstanceExpressions(currentInstances: Instance[]) {
const expressions = props.config.expressions || [];
const typesOfMQE = props.config.typesOfMQE || [];
const subExpressions = props.config.subExpressions || [];
if (expressions.length && expressions[0] && typesOfMQE.length && typesOfMQE[0]) {
const params = await useExpressionsQueryPodsMetrics(
currentInstances,
{ ...props.config, metricConfig: metricConfig.value || [], typesOfMQE, expressions, subExpressions },
EntityType[3].value,
);
instances.value = params.data;
colMetrics.value = params.names;
metricTypes.value = params.metricTypesArr;
metricConfig.value = params.metricConfigArr;
return;
}
instances.value = currentInstances;
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
function clickInstance(scope: any) {
@@ -207,12 +257,19 @@ limitations under the License. -->
}
watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || []), ...(props.config.metricConfig || [])],
() => [
...(props.config.metricTypes || []),
...(props.config.metrics || []),
...(props.config.metricConfig || []),
...(props.config.expressions || []),
props.config.metricMode,
],
(data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
metricConfig.value = props.config.metricConfig;
metricMode.value = props.config.metricMode;
queryInstanceMetrics(instances.value);
},
);

View File

@@ -52,6 +52,7 @@ limitations under the License. -->
metrics: colMetrics,
metricConfig,
metricTypes,
metricMode,
}"
v-if="colMetrics.length"
/>
@@ -80,7 +81,8 @@ limitations under the License. -->
import { useAppStoreWithOut } from "@/store/modules/app";
import type { Service } from "@/types/selector";
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useMetricsProcessor";
import { EntityType } from "../data";
import { useExpressionsQueryPodsMetrics } from "@/hooks/useExpressionsProcessor";
import { EntityType, MetricModes } from "../data";
import router from "@/router";
import getDashboard from "@/hooks/useDashboardsSession";
import type { MetricConfigOpt } from "@/types/dashboard";
@@ -100,6 +102,11 @@ limitations under the License. -->
isEdit: boolean;
names: string[];
metricConfig: MetricConfigOpt[];
metricMode: string;
expressions: string[];
typesOfMQE: string[];
subExpressions: string[];
subTypesOfMQE: string[];
}
>,
default: () => ({ dashboardName: "", fontSize: 12 }),
@@ -119,6 +126,7 @@ limitations under the License. -->
const sortServices = ref<(Service & { merge: boolean })[]>([]);
const metricConfig = ref<MetricConfigOpt[]>(props.config.metricConfig || []);
const metricTypes = ref<string[]>(props.config.metricTypes || []);
const metricMode = ref<string>(props.config.metricMode);
queryServices();
@@ -187,8 +195,23 @@ limitations under the License. -->
router.push(path);
}
async function queryServiceMetrics(currentServices: Service[]) {
if (!currentServices.length) {
async function queryServiceMetrics(arr: Service[]) {
if (!arr.length) {
return;
}
const currentServices = arr.map((d: Service) => {
return {
id: d.id,
value: d.value,
label: d.label,
layers: d.layers,
group: d.group,
normal: d.normal,
merge: d.merge,
};
});
if (props.config.metricMode === MetricModes.Expression) {
queryServiceExpressions(currentServices);
return;
}
const metrics = props.config.metrics || [];
@@ -211,6 +234,7 @@ limitations under the License. -->
...props.config,
metricConfig: metricConfig.value || [],
});
services.value = data;
colMetrics.value = names;
metricTypes.value = metricTypesArr;
@@ -219,6 +243,32 @@ limitations under the License. -->
return;
}
services.value = currentServices;
colMetrics.value = [];
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
async function queryServiceExpressions(currentServices: Service[]) {
const expressions = props.config.expressions || [];
const typesOfMQE = props.config.typesOfMQE || [];
const subExpressions = props.config.subExpressions || [];
if (expressions.length && expressions[0] && typesOfMQE.length && typesOfMQE[0]) {
const params = await useExpressionsQueryPodsMetrics(
currentServices,
{ ...props.config, metricConfig: metricConfig.value || [], typesOfMQE, expressions, subExpressions },
EntityType[0].value,
);
services.value = params.data;
colMetrics.value = params.names;
metricTypes.value = params.metricTypesArr;
metricConfig.value = params.metricConfigArr;
return;
}
services.value = currentServices;
colMetrics.value = [];
metricTypes.value = [];
metricConfig.value = [];
}
function objectSpanMethod(param: any): any {
if (!props.config.showGroup) {
@@ -251,15 +301,24 @@ limitations under the License. -->
}
watch(
() => [...(props.config.metricTypes || []), ...(props.config.metrics || []), ...(props.config.metricConfig || [])],
() => [
...(props.config.metricTypes || []),
...(props.config.metrics || []),
...(props.config.metricConfig || []),
...(props.config.expressions || []),
...(props.config.subExpressions || []),
props.config.metricMode,
],
(data, old) => {
if (JSON.stringify(data) === JSON.stringify(old)) {
return;
}
metricConfig.value = props.config.metricConfig;
metricMode.value = props.config.metricMode;
queryServiceMetrics(services.value);
},
);
watch(
() => appStore.durationTime,
() => {

View File

@@ -20,7 +20,7 @@ limitations under the License. -->
<div class="desc">
<span class="calls mr-10">{{ i.value }}</span>
<span class="cp mr-20">
{{ i.name }}
{{ i.name || i.id }}
</span>
</div>
<el-popover placement="bottom" trigger="click">

View File

@@ -23,7 +23,7 @@ limitations under the License. -->
<template #default="scope">
<div class="chart">
<Line
v-if="useListConfig(config, index).isLinear"
v-if="useListConfig(config, index).isLinear && config.metricMode !== MetricModes.Expression"
:data="{
[metric]: scope.row[metric] && scope.row[metric].values,
}"
@@ -35,7 +35,10 @@ limitations under the License. -->
showlabels: false,
}"
/>
<span class="item flex-h" v-else-if="useListConfig(config, index).isAvg">
<span
class="item flex-h"
v-else-if="useListConfig(config, index).isAvg || config.metricMode === MetricModes.Expression"
>
<el-popover placement="left" :width="400" trigger="click">
<template #reference>
<span class="trend">
@@ -79,6 +82,7 @@ limitations under the License. -->
import Line from "../Line.vue";
import Card from "../Card.vue";
import { MetricQueryTypes } from "@/hooks/data";
import { ExpressionResultType, MetricModes } from "@/views/dashboard/data";
/*global defineProps */
const props = defineProps({
@@ -89,6 +93,7 @@ limitations under the License. -->
metrics: string[];
metricTypes: string[];
metricConfig: MetricConfigOpt[];
metricMode: string;
}>,
default: () => ({}),
},
@@ -107,7 +112,15 @@ limitations under the License. -->
const i = Number(index);
const label = props.config.metricConfig && props.config.metricConfig[i] && props.config.metricConfig[i].label;
if (label) {
if (props.config.metricTypes[i] === MetricQueryTypes.ReadLabeledMetricsValues) {
if (
(
[
MetricQueryTypes.ReadLabeledMetricsValues,
ExpressionResultType.TIME_SERIES_VALUES,
ExpressionResultType.SINGLE_VALUE,
] as string[]
).includes(props.config.metricTypes[i])
) {
const name = (label || "").split(",").map((item: string) => item.replace(/^\s*|\s*$/g, ""))[
props.config.metricConfig[i].index || 0
];