From 19715d71524e3b97ae880871d9395751212e075b Mon Sep 17 00:00:00 2001 From: Qiuxia Fan Date: Fri, 25 Mar 2022 20:51:50 +0800 Subject: [PATCH] add metric config --- src/assets/icons/arrow_drop_down.svg | 17 ++ src/assets/icons/cancel.svg | 1 - src/assets/icons/clearclose.svg | 1 - ...{createmode_editedit.svg => mode_edit.svg} | 1 - src/hooks/data.ts | 8 + src/hooks/useProcessor.ts | 70 +++-- src/locales/lang/en.ts | 3 +- src/locales/lang/zh.ts | 3 +- src/store/data.ts | 1 + src/types/dashboard.ts | 9 + .../configuration/widget/MetricOptions.vue | 47 +++- .../configuration/widget/StandardOptions.vue | 247 +++++++----------- src/views/dashboard/controls/Widget.vue | 2 +- src/views/dashboard/data.ts | 8 + 14 files changed, 222 insertions(+), 196 deletions(-) create mode 100644 src/assets/icons/arrow_drop_down.svg rename src/assets/icons/{createmode_editedit.svg => mode_edit.svg} (96%) diff --git a/src/assets/icons/arrow_drop_down.svg b/src/assets/icons/arrow_drop_down.svg new file mode 100644 index 00000000..63151de2 --- /dev/null +++ b/src/assets/icons/arrow_drop_down.svg @@ -0,0 +1,17 @@ + + + + diff --git a/src/assets/icons/cancel.svg b/src/assets/icons/cancel.svg index 00ca7954..f52fb3dc 100644 --- a/src/assets/icons/cancel.svg +++ b/src/assets/icons/cancel.svg @@ -13,6 +13,5 @@ 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. --> -cancel diff --git a/src/assets/icons/clearclose.svg b/src/assets/icons/clearclose.svg index af9e3a0a..ddc35190 100644 --- a/src/assets/icons/clearclose.svg +++ b/src/assets/icons/clearclose.svg @@ -13,6 +13,5 @@ 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. --> -clearclose diff --git a/src/assets/icons/createmode_editedit.svg b/src/assets/icons/mode_edit.svg similarity index 96% rename from src/assets/icons/createmode_editedit.svg rename to src/assets/icons/mode_edit.svg index 1a1f2d8b..51f6cef8 100644 --- a/src/assets/icons/createmode_editedit.svg +++ b/src/assets/icons/mode_edit.svg @@ -13,6 +13,5 @@ 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. --> -createmode_editedit diff --git a/src/hooks/data.ts b/src/hooks/data.ts index 8914aff6..45aa326b 100644 --- a/src/hooks/data.ts +++ b/src/hooks/data.ts @@ -22,6 +22,14 @@ export enum MetricQueryTypes { READHEATMAP = "readHeatMap", ReadSampledRecords = "readSampledRecords", } + +export enum Calculations { + Percentage = "percentage", + ByteToKB = "byteToKB", + Apdex = "apdex", + ConvertSeconds = "convertSeconds", + ConvertMilliseconds = "convertMilliseconds", +} export enum sizeEnum { XS = "XS", SM = "SM", diff --git a/src/hooks/useProcessor.ts b/src/hooks/useProcessor.ts index 98f1f762..e7b62495 100644 --- a/src/hooks/useProcessor.ts +++ b/src/hooks/useProcessor.ts @@ -15,13 +15,13 @@ * limitations under the License. */ import dayjs from "dayjs"; -import { RespFields, MetricQueryTypes } from "./data"; +import { RespFields, MetricQueryTypes, Calculations } 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, Service } from "@/types/selector"; -import { StandardConfig } from "@/types/dashboard"; +import { MetricConfigOpt } from "@/types/dashboard"; export function useQueryProcessor(config: any) { if (!(config.metrics && config.metrics[0])) { @@ -48,6 +48,7 @@ export function useQueryProcessor(config: any) { } const fragment = config.metrics.map((name: string, index: number) => { const metricType = config.metricTypes[index] || ""; + const c = (config.metricConfig && config.metricConfig[index]) || {}; if ( [ MetricQueryTypes.ReadSampledRecords, @@ -63,7 +64,7 @@ export function useQueryProcessor(config: any) { normal: selectorStore.currentService.normal, scope: dashboardStore.entity, topN: 10, - order: config.standard.sortOrder || "DES", + order: c.sortOrder || "DES", }; } else { if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) { @@ -128,7 +129,7 @@ export function useSourceProcessor( config: { metrics: string[]; metricTypes: string[]; - standard: StandardConfig; + metricConfig: MetricConfigOpt[]; } ) { if (resp.errors) { @@ -140,23 +141,24 @@ export function useSourceProcessor( config.metricTypes.forEach((type: string, index) => { const m = config.metrics[index]; + const c = (config.metricConfig && config.metricConfig[index]) || {}; if (type === MetricQueryTypes.ReadMetricsValues) { source[m] = resp.data[keys[index]].values.values.map( - (d: { value: number }) => aggregation(d.value, config.standard) + (d: { value: number }) => aggregation(d.value, c) ); } if (type === MetricQueryTypes.ReadLabeledMetricsValues) { const resVal = Object.values(resp.data)[0] || []; - const labels = (config.standard.metricLabels || "") + const labels = (c.label || "") .split(",") .map((item: string) => item.replace(/^\s*|\s*$/g, "")); - const labelsIdx = (config.standard.labelsIndex || "") + const labelsIdx = (c.labelsIndex || "") .split(",") .map((item: string) => item.replace(/^\s*|\s*$/g, "")); for (const item of resVal) { const values = item.values.values.map((d: { value: number }) => - aggregation(Number(d.value), config.standard) + aggregation(Number(d.value), c) ); const indexNum = labelsIdx.findIndex((d: string) => d === item.label); @@ -168,10 +170,7 @@ export function useSourceProcessor( } } if (type === MetricQueryTypes.ReadMetricsValue) { - source[m] = aggregation( - Number(Object.values(resp.data)[0]), - config.standard - ); + source[m] = aggregation(Number(Object.values(resp.data)[0]), c); } if ( type === MetricQueryTypes.SortMetrics || @@ -179,7 +178,7 @@ export function useSourceProcessor( ) { source[m] = (Object.values(resp.data)[0] || []).map( (d: { value: unknown; name: string }) => { - d.value = aggregation(Number(d.value), config.standard); + d.value = aggregation(Number(d.value), c); return d; } @@ -307,33 +306,28 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) { return { queryStr, conditions }; } -function aggregation(val: number, standard: any): number | string { +function aggregation(val: number, config: any): number | string { let data: number | string = val; - if (!isNaN(standard.plus)) { - data = val + Number(standard.plus); - return data; + switch (config.calculation) { + case Calculations.Percentage: + data = val / 100; + break; + case Calculations.ByteToKB: + data = val / 1024; + break; + case Calculations.Apdex: + data = val / 10000; + break; + case Calculations.ConvertSeconds: + data = dayjs(val).format("YYYY-MM-DD HH:mm:ss"); + break; + case Calculations.ConvertMilliseconds: + data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss"); + break; + default: + data; + break; } - if (!isNaN(standard.minus)) { - data = val - Number(standard.plus); - return data; - } - if (!isNaN(standard.multiply) && standard.divide !== 0) { - data = val * Number(standard.multiply); - return data; - } - if (!isNaN(standard.divide) && standard.divide !== 0) { - data = val / Number(standard.divide); - return data; - } - if (standard.milliseconds) { - data = dayjs(val).format("YYYY-MM-DD HH:mm:ss"); - return data; - } - if (standard.milliseconds) { - data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss"); - return data; - } - return data; } diff --git a/src/locales/lang/en.ts b/src/locales/lang/en.ts index f85548c9..6c0f4b2a 100644 --- a/src/locales/lang/en.ts +++ b/src/locales/lang/en.ts @@ -127,6 +127,7 @@ const msg = { kubernetes: "Kubernetes", textUrl: "Text Hyperlink", textAlign: "Text Align", + metricLabel: "Metric Label", hourTip: "Select Hour", minuteTip: "Select Minute", secondTip: "Select Second", @@ -259,7 +260,7 @@ const msg = { independentSelector: "Selectors", unknownMetrics: "Unknown Metrics", labels: "Labels", - aggregation: "Data Calculation", + aggregation: "Calculation", unit: "Unit", labelsIndex: "Label Subscript", parentService: "Parent Service", diff --git a/src/locales/lang/zh.ts b/src/locales/lang/zh.ts index 305eb8d0..9683dd6a 100644 --- a/src/locales/lang/zh.ts +++ b/src/locales/lang/zh.ts @@ -127,6 +127,7 @@ const msg = { kubernetes: "Kubernetes", textUrl: "文本超链接", textAlign: "文本对齐", + metricLabel: "指标标签", hourTip: "选择小时", minuteTip: "选择分钟", secondTip: "选择秒数", @@ -261,7 +262,7 @@ const msg = { independentSelector: "独立选择器", unknownMetrics: "未知指标", labels: "标签", - aggregation: "数据计算", + aggregation: "计算", unit: "单位", labelsIndex: "标签下标", parentService: "父级服务", diff --git a/src/store/data.ts b/src/store/data.ts index 6fdfdd9b..eba3c3bb 100644 --- a/src/store/data.ts +++ b/src/store/data.ts @@ -28,6 +28,7 @@ export const NewControl = { standard: {}, metrics: [""], metricTypes: [""], + metricConfig: [], }; export const TextConfig = { fontColor: "white", diff --git a/src/types/dashboard.ts b/src/types/dashboard.ts index 62d12b9d..48be4187 100644 --- a/src/types/dashboard.ts +++ b/src/types/dashboard.ts @@ -36,8 +36,17 @@ export interface LayoutConfig { metricTypes: string[]; children?: any; activedTabIndex?: number; + metricConfig?: MetricConfigOpt[]; } +export type MetricConfigOpt = { + unit: string; + label: string; + calculation: string; + labelsIndex: string; + sortOrder: string; +}; + export interface WidgetConfig { title?: string; tips?: string; diff --git a/src/views/dashboard/configuration/widget/MetricOptions.vue b/src/views/dashboard/configuration/widget/MetricOptions.vue index 0e399f33..030eda43 100644 --- a/src/views/dashboard/configuration/widget/MetricOptions.vue +++ b/src/views/dashboard/configuration/widget/MetricOptions.vue @@ -49,6 +49,14 @@ limitations under the License. --> @change="changeMetricType(index, $event)" class="selectors" /> + + + + @@ -101,13 +109,15 @@ import { ElMessage } from "element-plus"; import Icon from "@/components/Icon.vue"; import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor"; import { useI18n } from "vue-i18n"; -import { DashboardItem } from "@/types/dashboard"; +import { DashboardItem, MetricConfigOpt } from "@/types/dashboard"; +import StandardOptions from "./StandardOptions.vue"; /*global defineEmits */ const { t } = useI18n(); const emit = defineEmits(["update", "loading", "changeOpt"]); const dashboardStore = useDashboardStore(); const { metrics, metricTypes, graph } = dashboardStore.selectedGrid; +const showConfig = ref(false); const states = reactive<{ metrics: string[]; metricTypes: string[]; @@ -127,6 +137,13 @@ const states = reactive<{ dashboardName: graph.dashboardName, dashboardList: [{ label: "", value: "" }], }); +const currentMetricConfig = ref({ + unit: "", + label: "", + labelsIndex: "", + calculation: "", + sortOrder: "DES", +}); states.isList = ListChartTypes.includes(graph.type); const defaultLen = ref(states.isList ? 5 : 20); @@ -323,8 +340,8 @@ async function queryMetrics() { if (states.isList) { return; } - const { standard } = dashboardStore.selectedGrid; - const params = useQueryProcessor({ ...states, standard }); + const { metricConfig } = dashboardStore.selectedGrid; + const params = useQueryProcessor({ ...states, metricConfig }); if (!params) { emit("update", {}); return; @@ -337,7 +354,7 @@ async function queryMetrics() { ElMessage.error(json.errors); return; } - const source = useSourceProcessor(json, { ...states, standard }); + const source = useSourceProcessor(json, { ...states, metricConfig }); emit("update", source); } @@ -393,6 +410,28 @@ function setMetricTypeList(type: string) { } return MetricTypes[type]; } +function setMetricConfig(index: number) { + showConfig.value = true; + const n = { + unit: "", + label: "", + calculation: "", + labelsIndex: "", + sortOrder: "DES", + }; + if ( + !dashboardStore.selectedGrid.metricConfig || + !dashboardStore.selectedGrid.metricConfig[index] + ) { + currentMetricConfig.value = n; + return; + } + currentMetricConfig.value = { + ...n, + ...dashboardStore.selectedGrid.metricConfig[index], + }; + showConfig.value = true; +} diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index c7915f15..a9b463d2 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -128,7 +128,7 @@ export default defineComponent({ const d = { metrics: props.data.metrics, metricTypes: props.data.metricTypes, - standard: props.data.standard, + metricConfig: props.data.metricConfig || [], }; state.source = useSourceProcessor(json, d); } diff --git a/src/views/dashboard/data.ts b/src/views/dashboard/data.ts index 9668d761..d1e3baaf 100644 --- a/src/views/dashboard/data.ts +++ b/src/views/dashboard/data.ts @@ -264,3 +264,11 @@ export const TextColors: { [key: string]: string } = { black: "#000", orange: "#E6A23C", }; + +export const CalculationOpts = [ + { label: "Percentage", value: "percentage" }, + { label: "ByteToKB", value: "byteToKB" }, + { label: "ConvertMilliseconds", value: "convertMilliseconds" }, + { label: "ConvertSeconds", value: "convertSeconds" }, + { label: "Apdex", value: "apdex" }, +];