feat: support multiple metrics for querys

This commit is contained in:
Qiuxia Fan 2022-01-20 20:17:19 +08:00
parent 86ec9c985b
commit 37fad917fb
10 changed files with 164 additions and 56 deletions

View File

@ -332,8 +332,6 @@ watch(
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@keyframes datepicker-anim-in { @keyframes datepicker-anim-in {
0% { 0% {
opacity: 0; opacity: 0;

View File

@ -26,6 +26,8 @@ export const NewControl = {
}, },
graph: {}, graph: {},
standard: {}, standard: {},
metrics: [],
metricTypes: [],
}; };
export const ConfigData: any = { export const ConfigData: any = {
x: 0, x: 0,
@ -33,8 +35,8 @@ export const ConfigData: any = {
w: 8, w: 8,
h: 12, h: 12,
i: "0", i: "0",
metrics: ["service_resp_time"], metrics: ["service_resp_time", "service_cpm"],
metricTypes: ["readMetricsValues"], metricTypes: ["readMetricsValues", "readMetricsValues"],
type: "Widget", type: "Widget",
widget: { widget: {
title: "Title", title: "Title",
@ -49,3 +51,39 @@ export const ConfigData: any = {
}, },
children: [], children: [],
}; };
export const RespFields: any = {
readMetricsValues: `{
label
values {
values {value}
}
}`,
readMetricsValue: "",
sortMetrics: `{
name
id
value
refId
}`,
readLabeledMetricsValues: `{
label
values {
values {value}
}
}`,
readHeatMap: `{
values {
id
values
}
buckets {
min
max
}
}`,
readSampledRecords: `{
name
value
refId
}`,
};

View File

@ -18,10 +18,13 @@ import { defineStore } from "pinia";
import { store } from "@/store"; import { store } from "@/store";
import { LayoutConfig } from "@/types/dashboard"; import { LayoutConfig } from "@/types/dashboard";
import graph from "@/graph"; import graph from "@/graph";
import { AxiosResponse } from "axios";
import { ConfigData } from "../data"; import { ConfigData } from "../data";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
import { NewControl } from "../data"; import { useSelectorStore } from "@/store/modules/selectors";
import { NewControl, RespFields } from "../data";
import { Duration } from "@/types/app";
import axios, { AxiosResponse } from "axios";
import { cancelToken } from "@/utils/cancelToken";
interface DashboardState { interface DashboardState {
showConfig: boolean; showConfig: boolean;
layout: LayoutConfig[]; layout: LayoutConfig[];
@ -29,6 +32,8 @@ interface DashboardState {
entity: string; entity: string;
layerId: string; layerId: string;
activedGridItem: string; activedGridItem: string;
durationTime: Duration;
selectorStore: any;
} }
export const dashboardStore = defineStore({ export const dashboardStore = defineStore({
@ -40,6 +45,8 @@ export const dashboardStore = defineStore({
entity: "", entity: "",
layerId: "", layerId: "",
activedGridItem: "", activedGridItem: "",
durationTime: useAppStoreWithOut().durationTime,
selectorStore: useSelectorStore(),
}), }),
actions: { actions: {
setLayout(data: LayoutConfig[]) { setLayout(data: LayoutConfig[]) {
@ -172,25 +179,83 @@ export const dashboardStore = defineStore({
return res.data; return res.data;
}, },
async fetchMetricValue() { async fetchMetricValue(config: LayoutConfig) {
// if (!config.metricTypes) { if (!(config.metrics && config.metrics.length)) {
// return; return;
// } }
const appStoreWithOut = useAppStoreWithOut(); const conditions: any = {
const variable = { duration: this.durationTime,
condition: {
name: "service_resp_time",
entity: {
normal: true,
scope: "Service",
serviceName: "agentless::app",
},
},
duration: appStoreWithOut.durationTime,
}; };
const res: AxiosResponse = await graph const variables: string[] = [`$duration: Duration!`];
.query("readMetricsValues") const { currentPod, currentService, currentDestPod, currentDestService } =
.params(variable); this.selectorStore;
const isRelation = [
"ServiceRelation",
"ServiceInstanceRelation",
"EndpointRelation",
].includes(this.entity);
const fragment = config.metrics.map((name: string, index: number) => {
const metricTypes = config.metricTypes[index] || "";
if (["readSampledRecords", "sortMetrics"].includes(metricTypes)) {
variables.push(`$condition${index}: TopNCondition!`);
conditions[`condition${index}`] = {
name,
parentService: currentService,
normal: true,
scope: this.entity,
topN: Number(config.standard.maxItemNum || 10),
order: config.standard.sortOrder || "DES",
};
} else {
variables.push(`$condition${index}: MetricsCondition!`);
conditions[`condition${index}`] = {
name,
entity: {
scope: this.entity,
serviceName: currentService,
normal: true,
serviceInstanceName: this.entity.includes("ServiceInstance")
? currentPod
: undefined,
endpointName: this.entity.includes("Endpoint")
? currentPod
: undefined,
destNormal: true,
destServiceName: isRelation ? currentDestService : undefined,
destServiceInstanceName:
this.entity === "ServiceInstanceRelation"
? currentDestPod
: undefined,
destEndpointName:
this.entity === "EndpointRelation" ? currentDestPod : undefined,
},
};
}
return `${name}${index}: ${metricTypes}(condition: $condition${index}, duration: $duration)${RespFields[metricTypes]}`;
});
const graphStr = `query queryData(${variables}) {${fragment}}`;
const res: AxiosResponse = await axios.post(
"/graphql",
{ query: graphStr, variables: { ...conditions } },
{ cancelToken: cancelToken() }
);
// const appStoreWithOut = useAppStoreWithOut();
// const variable = {
// condition: {
// name: "service_resp_time",
// entity: {
// normal: true,
// scope: "Service",
// serviceName: "agentless::app",
// },
// },
// duration: appStoreWithOut.durationTime,
// };
// const res: AxiosResponse = await graph
// .query("readMetricsValues")
// .params(variable);
return res.data; return res.data;
}, },

View File

@ -29,6 +29,7 @@ interface SelectorState {
currentService: string; currentService: string;
currentPod: string; currentPod: string;
currentDestService: string; currentDestService: string;
currentDestPod: string;
durationTime: Duration; durationTime: Duration;
} }
@ -42,6 +43,7 @@ export const selectorStore = defineStore({
currentService: "", currentService: "",
currentPod: "", currentPod: "",
currentDestService: "", currentDestService: "",
currentDestPod: "",
durationTime: useAppStoreWithOut().durationTime, durationTime: useAppStoreWithOut().durationTime,
}), }),
actions: { actions: {

View File

@ -20,12 +20,12 @@ export interface LayoutConfig {
w: number; w: number;
h: number; h: number;
i: string; i: string;
widget?: WidgetConfig; widget: WidgetConfig;
graph?: GraphConfig; graph: GraphConfig;
standard?: StandardConfig; standard: StandardConfig;
metrics?: string[]; metrics: string[];
type?: string; type: string;
metricTypes?: string[]; metricTypes: string[];
children?: any; children?: any;
} }
@ -45,6 +45,7 @@ export interface StandardConfig {
divide?: string; divide?: string;
milliseconds?: string; milliseconds?: string;
seconds?: string; seconds?: string;
maxItemNum?: number;
} }
export type GraphConfig = export type GraphConfig =

View File

@ -46,7 +46,7 @@ limitations under the License. -->
/> />
<Icon <Icon
class="cp mr-5" class="cp mr-5"
v-show="index === states.metrics.length - 1 && index < 6" v-show="index === states.metrics.length - 1 && states.metrics.length < 5"
iconName="add_circle_outlinecontrol_point" iconName="add_circle_outlinecontrol_point"
size="middle" size="middle"
@click="addMetric" @click="addMetric"
@ -61,7 +61,7 @@ limitations under the License. -->
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { reactive } from "vue"; import { reactive, watch } from "vue";
import type { PropType } from "vue"; import type { PropType } from "vue";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { Option } from "@/types/app"; import { Option } from "@/types/app";
@ -203,6 +203,13 @@ function deleteMetric(index: number) {
states.metrics.splice(index, 1); states.metrics.splice(index, 1);
states.metricTypes.splice(index, 1); states.metricTypes.splice(index, 1);
} }
watch(
() => props.graph,
(data: any) => {
states.isTable = TableChartTypes.includes(data.type);
console.log(data);
}
);
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.ds-name { .ds-name {

View File

@ -96,16 +96,13 @@ export default defineComponent({
ElMessage.error(json.error); ElMessage.error(json.error);
return; return;
} }
const metricVal = json.data.readMetricsValues.values.values.map( const keys = Object.keys(json.data);
(d: any) => d.value keys.map((key: string, index) => {
); const m = props.data.metrics[index];
const m = props.data.metrics && props.data.metrics[0]; state.source = {
if (!m) { [m]: json.data[key].values.values.map((d: any) => d.value),
return; };
} });
state.source = {
[m]: metricVal,
};
} }
function removeWidget() { function removeWidget() {

View File

@ -147,23 +147,23 @@ export enum MetricsName {
SERVICE_APDEX = "service_apdex", SERVICE_APDEX = "service_apdex",
} }
export const EntityType = [ export const EntityType = [
{ value: "service", label: "Service", key: 1 }, { value: "Service", label: "Service", key: 1 },
{ value: "all", label: "All", key: 10 }, { value: "All", label: "All", key: 10 },
{ value: "endpoint", label: "Service Endpoint", key: 3 }, { value: "Endpoint", label: "Service Endpoint", key: 3 },
{ value: "serviceInstance", label: "Service Instance", key: 3 }, { value: "ServiceInstance", label: "Service Instance", key: 3 },
{ value: "serviceRelationClient", label: "Service Relation(client)", key: 2 }, { value: "ServiceRelationClient", label: "Service Relation(client)", key: 2 },
{ value: "serviceRelationServer", label: "Service Relation(server)", key: 2 }, { value: "ServiceRelationServer", label: "Service Relation(server)", key: 2 },
{ {
value: "serviceInstanceRelationClient", value: "ServiceInstanceRelationClient",
label: "Service Instance Relation(client)", label: "Service Instance Relation(client)",
key: 4, key: 4,
}, },
{ {
value: "serviceInstanceRelationServer", value: "ServiceInstanceRelationServer",
label: "Service Instance Relation(server)", label: "Service Instance Relation(server)",
key: 4, key: 4,
}, },
{ value: "endpointRelation", label: "Endpoint Relation", key: 4 }, { value: "EndpointRelation", label: "Endpoint Relation", key: 4 },
]; ];
export const SortOrder = [ export const SortOrder = [
{ label: "DES", value: "DES" }, { label: "DES", value: "DES" },

View File

@ -32,7 +32,7 @@ limitations under the License. -->
<el-table <el-table
v-loading="chartLoading" v-loading="chartLoading"
:data="endpoints" :data="endpoints"
style="width: 100%; height: 100%; overflow: auto" style="width: 100%; height: 320px; overflow: auto"
> >
<el-table-column label="Endpoints"> <el-table-column label="Endpoints">
<template #default="scope"> <template #default="scope">
@ -51,7 +51,7 @@ limitations under the License. -->
class="pagination" class="pagination"
background background
layout="prev, pager, next" layout="prev, pager, next"
:page-size="6" :page-size="pageSize"
:total="selectorStore.endpoints.length" :total="selectorStore.endpoints.length"
@current-change="changePage" @current-change="changePage"
@prev-click="changePage" @prev-click="changePage"

View File

@ -32,7 +32,7 @@ limitations under the License. -->
<el-table <el-table
v-loading="chartLoading" v-loading="chartLoading"
:data="services" :data="services"
style="width: 100%; height: 100%; overflow: auto" style="width: 100%; height: 320px; overflow: auto"
> >
<el-table-column label="Services"> <el-table-column label="Services">
<template #default="scope"> <template #default="scope">
@ -51,7 +51,7 @@ limitations under the License. -->
class="pagination" class="pagination"
background background
layout="prev, pager, next" layout="prev, pager, next"
:page-size="6" :page-size="pageSize"
:total="selectorStore.services.length" :total="selectorStore.services.length"
@current-change="changePage" @current-change="changePage"
@prev-click="changePage" @prev-click="changePage"
@ -78,7 +78,7 @@ defineProps({
}); });
const selectorStore = useSelectorStore(); const selectorStore = useSelectorStore();
const chartLoading = ref<boolean>(false); const chartLoading = ref<boolean>(false);
const pageSize = 6; const pageSize = 7;
const services = ref<{ label: string; layer: string }[]>([]); const services = ref<{ label: string; layer: string }[]>([]);
const searchServices = ref<{ layer: string; label: string }[]>([]); const searchServices = ref<{ layer: string; label: string }[]>([]);
const searchText = ref<string>(""); const searchText = ref<string>("");