mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 17:04:48 +00:00
feat: support multiple metrics for querys
This commit is contained in:
parent
86ec9c985b
commit
37fad917fb
@ -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;
|
||||||
|
@ -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
|
||||||
|
}`,
|
||||||
|
};
|
||||||
|
@ -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;
|
||||||
},
|
},
|
||||||
|
@ -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: {
|
||||||
|
@ -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 =
|
||||||
|
@ -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 {
|
||||||
|
@ -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];
|
|
||||||
if (!m) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
state.source = {
|
state.source = {
|
||||||
[m]: metricVal,
|
[m]: json.data[key].values.values.map((d: any) => d.value),
|
||||||
};
|
};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeWidget() {
|
function removeWidget() {
|
||||||
|
@ -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" },
|
||||||
|
@ -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"
|
||||||
|
@ -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>("");
|
||||||
|
Loading…
Reference in New Issue
Block a user