diff --git a/src/App.vue b/src/App.vue index 74859ffc..93fd29d8 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> diff --git a/src/graph/fragments/dashboard.ts b/src/graph/fragments/dashboard.ts index 7ad1a9a4..8819dd52 100644 --- a/src/graph/fragments/dashboard.ts +++ b/src/graph/fragments/dashboard.ts @@ -18,47 +18,16 @@ export const TypeOfMetrics = { variable: "$name: String!", query: `typeOfMetrics(name: $name)`, }; -export const queryMetricsValues = { - variable: ["$condition: MetricsCondition!, $duration: Duration!"], +export const listMetrics = { + variable: "$regex: String", query: ` - readMetricsValues: readMetricsValues(condition: $condition, duration: $duration) { - label - values { - values {value} - } - }`, -}; - -export const queryMetricsValue = { - variable: ["$condition: MetricsCondition!, $duration: Duration!"], - query: ` - readMetricsValue: readMetricsValue(condition: $condition, duration: $duration)`, -}; - -export const querySortMetrics = { - variable: ["$condition: TopNCondition!, $duration: Duration!"], - query: ` - sortMetrics: sortMetrics(condition: $condition, duration: $duration) { - name - id - value - refId - }`, -}; -export const queryLabeledMetricsValues = { - variable: [ - "$condition: MetricsCondition!, $labels: [String!]!, $duration: Duration!", - ], - query: ` - readLabeledMetricsValues: readLabeledMetricsValues( - condition: $condition, - labels: $labels, - duration: $duration) { - label - values { - values {value} - } - }`, + metrics: listMetrics(regex: $regex) { + value: name + label: name + type + catalog + } + `, }; export const queryHeatMap = { @@ -75,12 +44,3 @@ export const queryHeatMap = { } }`, }; -export const querySampledRecords = { - variable: ["$condition: TopNCondition!, $duration: Duration!"], - query: ` - readSampledRecords: readSampledRecords(condition: $condition, duration: $duration) { - name - value - refId - }`, -}; diff --git a/src/graph/fragments/selector.ts b/src/graph/fragments/selector.ts index d66aae0b..4b90d4f9 100644 --- a/src/graph/fragments/selector.ts +++ b/src/graph/fragments/selector.ts @@ -15,14 +15,16 @@ * limitations under the License. */ export const Services = { - variable: ["$layer: String!"], + variable: "$layer: String!", query: ` - services: listServices(layer: $layer) { - value: id + services: listServices(layer: $layer) { + id + value: name label: name group - layer - } + layers + normal + } `, }; export const Layers = { @@ -33,10 +35,13 @@ export const Layers = { export const Instances = { variable: "$serviceId: ID!, $duration: Duration!", query: ` - getServiceInstances(duration: $duration, serviceId: $serviceId) { - key: id + pods: listInstances(duration: $duration, serviceId: $serviceId) { + id + value: name label: name language + instanceUUID + layer attributes { name value @@ -47,9 +52,55 @@ export const Instances = { export const Endpoints = { variable: "$serviceId: ID!, $keyword: String!", query: ` - getEndpoints: searchEndpoint(serviceId: $serviceId, keyword: $keyword, limit: 100) { - key: id - label: name + pods: findEndpoint(serviceId: $serviceId, keyword: $keyword, limit: 100) { + id + value: name + label: name } `, }; + +export const getService = { + variable: "$serviceId: String!", + query: ` + service: getService(serviceId: $serviceId) { + id + value: name + label: name + group + layers + normal + } + `, +}; + +export const getInstance = { + variable: "$instanceId: String!", + query: ` + instance: getInstance(instanceId: $instanceId) { + id + value: name + label: name + language + instanceUUID + layer + attributes { + name + value + } + } + `, +}; + +export const getEndpoint = { + variable: "$endpointId: ID!", + query: ` + endpoint: getEndpointInfo(endpointId: $endpointId) { + id + value: name + label: name + serviceId + serviceName + } + `, +}; diff --git a/src/graph/query/dashboard.ts b/src/graph/query/dashboard.ts index e5ffac98..9717f42e 100644 --- a/src/graph/query/dashboard.ts +++ b/src/graph/query/dashboard.ts @@ -16,25 +16,12 @@ */ import { TypeOfMetrics, - querySampledRecords, queryHeatMap, - queryLabeledMetricsValues, - querySortMetrics, - queryMetricsValue, - queryMetricsValues, + listMetrics, } from "../fragments/dashboard"; export const queryTypeOfMetrics = `query typeOfMetrics(${TypeOfMetrics.variable}) {${TypeOfMetrics.query}}`; export const readHeatMap = `query queryData(${queryHeatMap.variable}) {${queryHeatMap.query}}`; -export const readSampledRecords = `query queryData(${querySampledRecords.variable}) {${querySampledRecords.query}}`; - -export const readLabeledMetricsValues = `query queryData(${queryLabeledMetricsValues.variable}) { - ${queryLabeledMetricsValues.query}}`; - -export const sortMetrics = `query queryData(${querySortMetrics.variable}) {${querySortMetrics.query}}`; - -export const readMetricsValue = `query queryData(${queryMetricsValue.variable}) {${queryMetricsValue.query}}`; - -export const readMetricsValues = `query queryData(${queryMetricsValues.variable}) {${queryMetricsValues.query}}`; +export const queryMetrics = `query queryData(${listMetrics.variable}) {${listMetrics.query}}`; diff --git a/src/graph/query/selector.ts b/src/graph/query/selector.ts index 1681ff5c..cbbccc30 100644 --- a/src/graph/query/selector.ts +++ b/src/graph/query/selector.ts @@ -14,10 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Services, Layers, Endpoints, Instances } from "../fragments/selector"; +import { + Services, + Layers, + Endpoints, + Instances, + getService, + getInstance, + getEndpoint, +} from "../fragments/selector"; export const queryServices = `query queryServices(${Services.variable}) {${Services.query}}`; -export const queryLayers = `query ${Layers.query}`; export const queryEndpoints = `query queryEndpoints(${Endpoints.variable}) {${Endpoints.query}}`; - export const queryInstances = `query queryInstances(${Instances.variable}) {${Instances.query}}`; +export const queryLayers = `query listLayer {${Layers.query}}`; +export const queryService = `query queryService(${getService.variable}) {${getService.query}}`; +export const queryInstance = `query queryInstance(${getInstance.variable}) {${getInstance.query}}`; +export const queryEndpoint = `query queryInstance(${getEndpoint.variable}) {${getEndpoint.query}}`; diff --git a/src/hooks/data.ts b/src/hooks/data.ts index 17b8a1f4..3bd270bf 100644 --- a/src/hooks/data.ts +++ b/src/hooks/data.ts @@ -14,6 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export enum MetricQueryTypes { + ReadMetricsValue = "readMetricsValue", + ReadMetricsValues = "readMetricsValues", + SortMetrics = "sortMetrics", + ReadLabeledMetricsValues = "readLabeledMetricsValues", + READHEATMAP = "readHeatMap", + ReadSampledRecords = "readSampledRecords", +} export enum sizeEnum { XS = "XS", SM = "SM", @@ -32,7 +40,7 @@ export enum screenEnum { XXL = 1600, } -const screenMap = new Map(); +export const screenMap = new Map(); screenMap.set(sizeEnum.XS, screenEnum.XS); screenMap.set(sizeEnum.SM, screenEnum.SM); @@ -41,4 +49,47 @@ screenMap.set(sizeEnum.LG, screenEnum.LG); screenMap.set(sizeEnum.XL, screenEnum.XL); screenMap.set(sizeEnum.XXL, screenEnum.XXL); -export { screenMap }; +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 + }`, +}; +export enum CalculationType { + Plus = "+", + Minus = "-", + Multiplication = "*", + Division = "/", + "Convert Unix Timestamp(milliseconds)" = "milliseconds", + "Convert Unix Timestamp(seconds)" = "seconds", +} diff --git a/src/hooks/useProcessor.ts b/src/hooks/useProcessor.ts new file mode 100644 index 00000000..888694f0 --- /dev/null +++ b/src/hooks/useProcessor.ts @@ -0,0 +1,254 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { RespFields, MetricQueryTypes } from "./data"; +import { ElMessage } from "element-plus"; +import { useDashboardStore } from "@/store/modules/dashboard"; +import { useSelectorStore } from "@/store/modules/selectors"; +import { useAppStoreWithOut } from "@/store/modules/app"; +import { Instance, Endpoint } from "@/types/selector"; + +export function useQueryProcessor(config: any) { + if (!(config.metrics && config.metrics[0])) { + return; + } + const appStore = useAppStoreWithOut(); + const dashboardStore = useDashboardStore(); + const selectorStore = useSelectorStore(); + if (!selectorStore.currentService) { + return; + } + const conditions: { [key: string]: unknown } = { + duration: appStore.durationTime, + }; + const variables: string[] = [`$duration: Duration!`]; + const isRelation = [ + "ServiceRelation", + "ServiceInstanceRelation", + "EndpointRelation", + ].includes(dashboardStore.entity); + const fragment = config.metrics.map((name: string, index: number) => { + const metricType = config.metricTypes[index] || ""; + const labels = ["0", "1", "2", "3", "4"]; + if ( + [ + MetricQueryTypes.ReadSampledRecords, + MetricQueryTypes.SortMetrics, + ].includes(metricType) + ) { + variables.push(`$condition${index}: TopNCondition!`); + conditions[`condition${index}`] = { + name, + parentService: ["Service", "All"].includes(dashboardStore.entity) + ? null + : selectorStore.currentService.value, + normal: selectorStore.currentService.normal, + scope: dashboardStore.entity, + topN: 10, + order: "DES", + }; + } else { + if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) { + variables.push(`$labels${index}: [String!]!`); + conditions[`labels${index}`] = labels; + } + variables.push(`$condition${index}: MetricsCondition!`); + conditions[`condition${index}`] = { + name, + entity: { + scope: dashboardStore.entity, + serviceName: + dashboardStore.entity === "All" + ? undefined + : selectorStore.currentService.value, + normal: + dashboardStore.entity === "All" + ? undefined + : selectorStore.currentService.normal, + serviceInstanceName: dashboardStore.entity.includes("ServiceInstance") + ? selectorStore.currentPod && selectorStore.currentPod.value + : undefined, + endpointName: dashboardStore.entity.includes("Endpoint") + ? selectorStore.currentPod && selectorStore.currentPod.value + : undefined, + destNormal: isRelation + ? selectorStore.currentDestService.normal + : undefined, + destServiceName: isRelation + ? selectorStore.currentDestService.value + : undefined, + destServiceInstanceName: + dashboardStore.entity === "ServiceInstanceRelation" + ? selectorStore.currentDestPod && + selectorStore.currentDestPod.value + : undefined, + destEndpointName: + dashboardStore.entity === "EndpointRelation" + ? selectorStore.currentDestPod && + selectorStore.currentDestPod.value + : undefined, + }, + }; + } + if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) { + return `${name}${index}: ${metricType}(condition: $condition${index}, labels: $labels${index}, duration: $duration)${RespFields[metricType]}`; + } else { + return `${name}${index}: ${metricType}(condition: $condition${index}, duration: $duration)${RespFields[metricType]}`; + } + }); + const queryStr = `query queryData(${variables}) {${fragment}}`; + return { + queryStr, + conditions, + }; +} +export function useSourceProcessor( + resp: { errors: string; data: { [key: string]: any } }, + config: { metrics: string[]; metricTypes: string[] } +) { + if (resp.errors) { + ElMessage.error(resp.errors); + return {}; + } + const source: { [key: string]: unknown } = {}; + const keys = Object.keys(resp.data); + + config.metricTypes.forEach((type: string, index) => { + const m = config.metrics[index]; + + if (type === MetricQueryTypes.ReadMetricsValues) { + source[m] = resp.data[keys[index]].values.values.map( + (d: { value: number }) => d.value + ); + } + if (type === MetricQueryTypes.ReadLabeledMetricsValues) { + const resVal = Object.values(resp.data)[0] || []; + const labelsIdx = ["0", "1", "2", "3", "4"]; + const labels = ["P50", "P75", "P90", "P95", "P99"]; + for (const item of resVal) { + const values = item.values.values.map( + (d: { value: number }) => d.value + ); + + const indexNum = labelsIdx.findIndex((d: string) => d === item.label); + if (labels[indexNum] && indexNum > -1) { + source[labels[indexNum]] = values; + } else { + source[item.label] = values; + } + } + } + if (type === MetricQueryTypes.ReadMetricsValue) { + source[m] = Object.values(resp.data)[0]; + } + if ( + type === MetricQueryTypes.SortMetrics || + type === MetricQueryTypes.ReadSampledRecords + ) { + source[m] = Object.values(resp.data)[0] || []; + } + if (type === MetricQueryTypes.READHEATMAP) { + const resVal = Object.values(resp.data)[0] || {}; + const nodes = [] as any; + if (!(resVal && resVal.values)) { + source[m] = { nodes: [] }; + return; + } + resVal.values.forEach((items: { values: number[] }, x: number) => { + const grids = items.values.map((val: number, y: number) => [x, y, val]); + + nodes.push(...grids); + }); + let buckets = [] as any; + if (resVal.buckets.length) { + buckets = [ + resVal.buckets[0].min, + ...resVal.buckets.map( + (item: { min: string; max: string }) => item.max + ), + ]; + } + + source[m] = { nodes, buckets }; // nodes: number[][] + } + }); + + return source; +} + +export function useQueryPodsMetrics( + pods: Array, + config: { metrics: string[]; metricTypes: string[] }, + scope: string +) { + const appStore = useAppStoreWithOut(); + const selectorStore = useSelectorStore(); + const conditions: { [key: string]: unknown } = { + duration: appStore.durationTime, + }; + const variables: string[] = [`$duration: Duration!`]; + const { currentService } = selectorStore; + + const fragmentList = pods.map((d: Instance | Endpoint, index: number) => { + const param = { + scope, + serviceName: currentService.label, + serviceInstanceName: scope === "ServiceInstance" ? d.label : undefined, + endpointName: scope === "Endpoint" ? d.label : undefined, + normal: currentService.normal, + }; + const f = config.metrics.map((name: string, idx: number) => { + const metricType = config.metricTypes[idx] || ""; + conditions[`condition${index}${idx}`] = { + name, + entity: param, + }; + variables.push(`$condition${index}${idx}: MetricsCondition!`); + return `${name}${index}${idx}: ${metricType}(condition: $condition${index}${idx}, duration: $duration)${RespFields[metricType]}`; + }); + return f; + }); + const fragment = fragmentList.flat(1).join(" "); + const queryStr = `query queryData(${variables}) {${fragment}}`; + + return { queryStr, conditions }; +} +export function usePodsSource( + pods: Array, + resp: { errors: string; data: { [key: string]: any } }, + config: { metrics: string[]; metricTypes: string[] } +): any { + if (resp.errors) { + ElMessage.error(resp.errors); + return {}; + } + const data = pods.map((d: Instance | any, idx: number) => { + config.metrics.map((name: string, index: number) => { + const key = name + idx + index; + if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValue) { + d[name] = resp.data[key]; + } + if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) { + d[name] = resp.data[key].values.values.map( + (d: { value: number }) => d.value + ); + } + }); + + return d; + }); + return data; +} diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue index 4be1f20f..a00568ae 100644 --- a/src/layout/components/AppMain.vue +++ b/src/layout/components/AppMain.vue @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. --> + diff --git a/src/views/dashboard/configuration/StandardOptions.vue b/src/views/dashboard/configuration/StandardOptions.vue index 56081354..42558448 100644 --- a/src/views/dashboard/configuration/StandardOptions.vue +++ b/src/views/dashboard/configuration/StandardOptions.vue @@ -116,22 +116,16 @@ limitations under the License. --> diff --git a/src/views/dashboard/configuration/graph-styles/InstanceList.vue b/src/views/dashboard/configuration/graph-styles/InstanceList.vue new file mode 100644 index 00000000..78df72d3 --- /dev/null +++ b/src/views/dashboard/configuration/graph-styles/InstanceList.vue @@ -0,0 +1,60 @@ + + + + diff --git a/src/views/dashboard/configuration/graph-styles/Line.vue b/src/views/dashboard/configuration/graph-styles/Line.vue index 4afb630a..159bca52 100644 --- a/src/views/dashboard/configuration/graph-styles/Line.vue +++ b/src/views/dashboard/configuration/graph-styles/Line.vue @@ -42,25 +42,23 @@ limitations under the License. --> diff --git a/src/views/dashboard/configuration/graph-styles/Table.vue b/src/views/dashboard/configuration/graph-styles/Table.vue index 100550f9..e12498b5 100644 --- a/src/views/dashboard/configuration/graph-styles/Table.vue +++ b/src/views/dashboard/configuration/graph-styles/Table.vue @@ -44,29 +44,23 @@ limitations under the License. --> diff --git a/src/views/dashboard/graphs/EndpointList.vue b/src/views/dashboard/graphs/EndpointList.vue index 3f14aa94..a895349c 100644 --- a/src/views/dashboard/graphs/EndpointList.vue +++ b/src/views/dashboard/graphs/EndpointList.vue @@ -13,22 +13,159 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> + diff --git a/src/views/dashboard/graphs/HeatMap.vue b/src/views/dashboard/graphs/HeatMap.vue index a07f22ce..952658e1 100644 --- a/src/views/dashboard/graphs/HeatMap.vue +++ b/src/views/dashboard/graphs/HeatMap.vue @@ -16,10 +16,11 @@ limitations under the License. --> + diff --git a/src/views/dashboard/graphs/Line.vue b/src/views/dashboard/graphs/Line.vue index 34b7ec74..0aaabe0f 100644 --- a/src/views/dashboard/graphs/Line.vue +++ b/src/views/dashboard/graphs/Line.vue @@ -16,11 +16,12 @@ limitations under the License. --> + diff --git a/src/views/dashboard/graphs/Table.vue b/src/views/dashboard/graphs/Table.vue index 4e69adbb..a84576f9 100644 --- a/src/views/dashboard/graphs/Table.vue +++ b/src/views/dashboard/graphs/Table.vue @@ -22,9 +22,9 @@ limitations under the License. --> >
{{ config.tableHeaderCol1 || $t("name") }} - + + +
{{ config.tableHeaderCol2 || $t("value") }} @@ -45,11 +45,12 @@ limitations under the License. -->