diff --git a/src/graph/fragments/dashboard.ts b/src/graph/fragments/dashboard.ts index de6c5ba1..7021e380 100644 --- a/src/graph/fragments/dashboard.ts +++ b/src/graph/fragments/dashboard.ts @@ -90,6 +90,7 @@ export const querySampledRecords = { variable: ["$condition: TopNCondition!, $duration: Duration!"], query: ` readSampledRecords: readSampledRecords(condition: $condition, duration: $duration) { + id name value refId diff --git a/src/graph/fragments/selector.ts b/src/graph/fragments/selector.ts index 436f6b15..f4676ec8 100644 --- a/src/graph/fragments/selector.ts +++ b/src/graph/fragments/selector.ts @@ -18,7 +18,8 @@ export const Services = { variable: "$layer: String!", query: ` services: listServices(layer: $layer) { - value: id + id + value: name label: name group layers diff --git a/src/hooks/data.ts b/src/hooks/data.ts index 9736195c..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", @@ -77,3 +85,11 @@ export const RespFields: any = { 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 index 09f10f56..816e0013 100644 --- a/src/hooks/useProcessor.ts +++ b/src/hooks/useProcessor.ts @@ -14,21 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Duration } from "@/types/app"; -import { RespFields } from "./data"; +import { RespFields, MetricQueryTypes, CalculationType } 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"; -export function useQueryProcessor( - config: any, - selectorStore: any, - dashboardStore: any, - durationTime: Duration -) { +export function useQueryProcessor(config: any) { if (!(config.metrics && config.metrics.length)) { return; } + const appStore = useAppStoreWithOut(); + const dashboardStore = useDashboardStore(); + const selectorStore = useSelectorStore(); const conditions: { [key: string]: unknown } = { - duration: durationTime, + duration: appStore.durationTime, }; const variables: string[] = [`$duration: Duration!`]; const { currentPod, currentService, currentDestPod, currentDestService } = @@ -40,31 +40,42 @@ export function useQueryProcessor( "EndpointRelation", ].includes(entity); const fragment = config.metrics.map((name: string, index: number) => { - const metricTypes = config.metricTypes[index] || ""; - // const labels = config.metricType === 'LABELED_VALUE' ? labelsIndex : undefined; - if (["readSampledRecords", "sortMetrics"].includes(metricTypes)) { + 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: entity === "All" ? null : currentService, + parentService: ["Service", "All"].includes(entity) + ? null + : currentService, normal: normal, scope: entity, - topN: Number(config.standard.maxItemNum || 10), - order: config.standard.sortOrder || "DES", + 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: entity, serviceName: entity === "All" ? undefined : currentService, - normal: true, + normal: entity === "All" ? undefined : normal, serviceInstanceName: entity.includes("ServiceInstance") ? currentPod : undefined, endpointName: entity.includes("Endpoint") ? currentPod : undefined, - destNormal: entity === "All" ? undefined : destNormal, + destNormal: entity === "All" ? undefined : undefined, destServiceName: isRelation ? currentDestService : undefined, destServiceInstanceName: entity === "ServiceInstanceRelation" ? currentDestPod : undefined, @@ -73,8 +84,11 @@ export function useQueryProcessor( }, }; } - - return `${name}${index}: ${metricTypes}(condition: $condition${index}, duration: $duration)${RespFields[metricTypes]}`; + 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 { @@ -84,20 +98,72 @@ export function useQueryProcessor( } export function useSourceProcessor( resp: { errors: string; data: { [key: string]: any } }, - config: { metrics: string[] } + config: { metrics: string[]; metricTypes: string[] } ) { - const source: { [key: string]: unknown } = {}; if (resp.errors) { ElMessage.error(resp.errors); return {}; } + const source: { [key: string]: unknown } = {}; const keys = Object.keys(resp.data); - keys.forEach((key: string, index) => { + + config.metricTypes.forEach((type: string, index) => { const m = config.metrics[index]; - source[m] = resp.data[key].values.values.map( - (d: { value: number }) => d.value - ); + + 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] || []; + } }); return source; } +function aggregation(json: { + data: number; + type: string; + aggregationNum: number; +}) { + if (isNaN(json.aggregationNum)) { + return json.data; + } + if (json.type === CalculationType.Plus) { + return json.data + json.aggregationNum; + } + if (json.type === CalculationType.Minus) { + return json.data - json.aggregationNum; + } + if (json.type === CalculationType.Multiplication) { + return json.data * json.aggregationNum; + } + if (json.type === CalculationType.Division) { + return json.data / json.aggregationNum; + } + return json.data; +} diff --git a/src/store/data.ts b/src/store/data.ts index 62fcee64..b874b0bc 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -35,7 +35,7 @@ export const ConfigData: any = { w: 8, h: 12, i: "0", - metrics: ["service_resp_time", "service_cpm"], + metrics: ["service_resp_time", "service_apdex"], metricTypes: ["readMetricsValues", "readMetricsValues"], type: "Widget", widget: { diff --git a/src/views/dashboard/Edit.vue b/src/views/dashboard/Edit.vue index febba3d6..8dda6c22 100644 --- a/src/views/dashboard/Edit.vue +++ b/src/views/dashboard/Edit.vue @@ -23,7 +23,7 @@ limitations under the License. --> :destroy-on-close="true" @closed="dashboardStore.setConfigPanel(false)" > - + @@ -32,7 +32,7 @@ import { useI18n } from "vue-i18n"; import GridLayout from "./panel/Layout.vue"; // import { LayoutConfig } from "@/types/dashboard"; import Tool from "./panel/Tool.vue"; -import WidgetConfig from "./configuration/ConfigEdit.vue"; +import ConfigEdit from "./configuration/ConfigEdit.vue"; import { useDashboardStore } from "@/store/modules/dashboard"; const { t } = useI18n(); diff --git a/src/views/dashboard/configuration/MetricOptions.vue b/src/views/dashboard/configuration/MetricOptions.vue index c33a6511..72e2cb24 100644 --- a/src/views/dashboard/configuration/MetricOptions.vue +++ b/src/views/dashboard/configuration/MetricOptions.vue @@ -69,6 +69,7 @@ import { useDashboardStore } from "@/store/modules/dashboard"; import { MetricTypes, TableChartTypes, MetricCatalog } from "../data"; import { ElMessage } from "element-plus"; import Icon from "@/components/Icon.vue"; +import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor"; /*global defineProps, defineEmits */ const props = defineProps({ @@ -122,8 +123,9 @@ async function setMetricType() { for (const metric of metrics) { states.metricTypeList.push(MetricTypes[metric.type]); } - - queryMetrics(); + if (states.metrics && states.metrics[0]) { + queryMetrics(); + } } function changeMetrics(index: number, arr: (Option & { type: string })[]) { @@ -135,6 +137,7 @@ function changeMetrics(index: number, arr: (Option & { type: string })[]) { } states.metrics[index] = arr[0].value; const typeOfMetrics = arr[0].type; + states.metricTypeList[index] = MetricTypes[typeOfMetrics]; states.metricTypes[index] = MetricTypes[typeOfMetrics][0].value; emit("apply", { metricTypes: states.metricTypes, metrics: states.metrics }); @@ -164,26 +167,21 @@ function changeMetricType(index: number, opt: Option[]) { queryMetrics(); } async function queryMetrics() { - const json = await dashboardStore.fetchMetricValue( - dashboardStore.selectedGrid - ); - if (!json) { + const params = useQueryProcessor(states); + if (!params) { + emit("update", {}); return; } + const json = await dashboardStore.fetchMetricValue(params); if (json.errors) { ElMessage.error(json.errors); return; } - const metricVal = json.data.readMetricsValues.values.values.map( - (d: { value: number }) => d.value - ); - const m = states.metrics[0]; - if (!m) { - return; - } - emit("update", { [m]: metricVal }); + const source = useSourceProcessor(json, states); + emit("update", source); } + function changeDashboard(item: Option[]) { states.graph.dashboardName = item[0].value; } @@ -204,7 +202,6 @@ watch( () => props.graph, (data: any) => { states.isTable = TableChartTypes.includes(data.type); - console.log(data); } ); diff --git a/src/views/dashboard/configuration/graph-styles/Card.vue b/src/views/dashboard/configuration/graph-styles/Card.vue index ffc18ceb..c9119d3e 100644 --- a/src/views/dashboard/configuration/graph-styles/Card.vue +++ b/src/views/dashboard/configuration/graph-styles/Card.vue @@ -20,9 +20,9 @@ limitations under the License. --> v-model="fontSize" show-input input-size="small" - :min="0.1" - :max="1" - :step="0.1" + :min="10" + :max="20" + :step="1" @change="updateConfig({ fontSize })" /> diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index 9319688b..4a681cab 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -87,14 +87,11 @@ export default defineComponent({ const dashboardStore = useDashboardStore(); const selectorStore = useSelectorStore(); - queryMetrics(); + if (props.data.metrics && props.data.metrics[0]) { + queryMetrics(); + } async function queryMetrics() { - const params = useQueryProcessor( - props.data, - selectorStore, - dashboardStore, - appStore.durationTime - ); + const params = await useQueryProcessor(props.data); if (!params) { state.source = {}; return; @@ -102,6 +99,9 @@ export default defineComponent({ loading.value = true; const json = await dashboardStore.fetchMetricValue(params); loading.value = false; + if (!json) { + return; + } state.source = useSourceProcessor(json, props.data); } diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index 87d75cc7..d8730f17 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -78,14 +78,6 @@ export const DefaultGraphConfig: { [key: string]: any } = { }, }; -export enum MetricQueryTypes { - ReadMetricsValue = "readMetricsValue", - ReadMetricsValues = "readMetricsValues", - SortMetrics = "sortMetrics", - ReadLabeledMetricsValues = "readLabeledMetricsValues", - READHEATMAP = "readHeatMap", - ReadSampledRecords = "readSampledRecords", -} export enum MetricsType { UNKNOWN = "UNKNOWN", REGULAR_VALUE = "REGULAR_VALUE", diff --git a/src/views/dashboard/graphs/Card.vue b/src/views/dashboard/graphs/Card.vue index d7c73e97..af08c4fd 100644 --- a/src/views/dashboard/graphs/Card.vue +++ b/src/views/dashboard/graphs/Card.vue @@ -16,11 +16,11 @@ limitations under the License. -->