add metric config
17
src/assets/icons/arrow_drop_down.svg
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!-- 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. -->
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M6.984 9.984h10.031l-5.016 5.016z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 922 B |
@ -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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<title>cancel</title>
|
|
||||||
<path d="M17.016 15.609l-3.609-3.609 3.609-3.609-1.406-1.406-3.609 3.609-3.609-3.609-1.406 1.406 3.609 3.609-3.609 3.609 1.406 1.406 3.609-3.609 3.609 3.609zM12 2.016q4.125 0 7.055 2.93t2.93 7.055-2.93 7.055-7.055 2.93-7.055-2.93-2.93-7.055 2.93-7.055 7.055-2.93z"></path>
|
<path d="M17.016 15.609l-3.609-3.609 3.609-3.609-1.406-1.406-3.609 3.609-3.609-3.609-1.406 1.406 3.609 3.609-3.609 3.609 1.406 1.406 3.609-3.609 3.609 3.609zM12 2.016q4.125 0 7.055 2.93t2.93 7.055-2.93 7.055-7.055 2.93-7.055-2.93-2.93-7.055 2.93-7.055 7.055-2.93z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<title>clearclose</title>
|
|
||||||
<path d="M18.984 6.422l-5.578 5.578 5.578 5.578-1.406 1.406-5.578-5.578-5.578 5.578-1.406-1.406 5.578-5.578-5.578-5.578 1.406-1.406 5.578 5.578 5.578-5.578z"></path>
|
<path d="M18.984 6.422l-5.578 5.578 5.578 5.578-1.406 1.406-5.578-5.578-5.578 5.578-1.406-1.406 5.578-5.578-5.578-5.578 1.406-1.406 5.578 5.578 5.578-5.578z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@ -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
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
<title>createmode_editedit</title>
|
|
||||||
<path d="M20.719 7.031l-1.828 1.828-3.75-3.75 1.828-1.828q0.281-0.281 0.703-0.281t0.703 0.281l2.344 2.344q0.281 0.281 0.281 0.703t-0.281 0.703zM3 17.25l11.063-11.063 3.75 3.75-11.063 11.063h-3.75v-3.75z"></path>
|
<path d="M20.719 7.031l-1.828 1.828-3.75-3.75 1.828-1.828q0.281-0.281 0.703-0.281t0.703 0.281l2.344 2.344q0.281 0.281 0.281 0.703t-0.281 0.703zM3 17.25l11.063-11.063 3.75 3.75-11.063 11.063h-3.75v-3.75z"></path>
|
||||||
</svg>
|
</svg>
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@ -22,6 +22,14 @@ export enum MetricQueryTypes {
|
|||||||
READHEATMAP = "readHeatMap",
|
READHEATMAP = "readHeatMap",
|
||||||
ReadSampledRecords = "readSampledRecords",
|
ReadSampledRecords = "readSampledRecords",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum Calculations {
|
||||||
|
Percentage = "percentage",
|
||||||
|
ByteToKB = "byteToKB",
|
||||||
|
Apdex = "apdex",
|
||||||
|
ConvertSeconds = "convertSeconds",
|
||||||
|
ConvertMilliseconds = "convertMilliseconds",
|
||||||
|
}
|
||||||
export enum sizeEnum {
|
export enum sizeEnum {
|
||||||
XS = "XS",
|
XS = "XS",
|
||||||
SM = "SM",
|
SM = "SM",
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { RespFields, MetricQueryTypes } from "./data";
|
import { RespFields, MetricQueryTypes, Calculations } from "./data";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { useAppStoreWithOut } from "@/store/modules/app";
|
import { useAppStoreWithOut } from "@/store/modules/app";
|
||||||
import { Instance, Endpoint, Service } from "@/types/selector";
|
import { Instance, Endpoint, Service } from "@/types/selector";
|
||||||
import { StandardConfig } from "@/types/dashboard";
|
import { MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
|
||||||
export function useQueryProcessor(config: any) {
|
export function useQueryProcessor(config: any) {
|
||||||
if (!(config.metrics && config.metrics[0])) {
|
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 fragment = config.metrics.map((name: string, index: number) => {
|
||||||
const metricType = config.metricTypes[index] || "";
|
const metricType = config.metricTypes[index] || "";
|
||||||
|
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
MetricQueryTypes.ReadSampledRecords,
|
MetricQueryTypes.ReadSampledRecords,
|
||||||
@ -63,7 +64,7 @@ export function useQueryProcessor(config: any) {
|
|||||||
normal: selectorStore.currentService.normal,
|
normal: selectorStore.currentService.normal,
|
||||||
scope: dashboardStore.entity,
|
scope: dashboardStore.entity,
|
||||||
topN: 10,
|
topN: 10,
|
||||||
order: config.standard.sortOrder || "DES",
|
order: c.sortOrder || "DES",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
@ -128,7 +129,7 @@ export function useSourceProcessor(
|
|||||||
config: {
|
config: {
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
standard: StandardConfig;
|
metricConfig: MetricConfigOpt[];
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
if (resp.errors) {
|
if (resp.errors) {
|
||||||
@ -140,23 +141,24 @@ export function useSourceProcessor(
|
|||||||
|
|
||||||
config.metricTypes.forEach((type: string, index) => {
|
config.metricTypes.forEach((type: string, index) => {
|
||||||
const m = config.metrics[index];
|
const m = config.metrics[index];
|
||||||
|
const c = (config.metricConfig && config.metricConfig[index]) || {};
|
||||||
|
|
||||||
if (type === MetricQueryTypes.ReadMetricsValues) {
|
if (type === MetricQueryTypes.ReadMetricsValues) {
|
||||||
source[m] = resp.data[keys[index]].values.values.map(
|
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) {
|
if (type === MetricQueryTypes.ReadLabeledMetricsValues) {
|
||||||
const resVal = Object.values(resp.data)[0] || [];
|
const resVal = Object.values(resp.data)[0] || [];
|
||||||
const labels = (config.standard.metricLabels || "")
|
const labels = (c.label || "")
|
||||||
.split(",")
|
.split(",")
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
const labelsIdx = (config.standard.labelsIndex || "")
|
const labelsIdx = (c.labelsIndex || "")
|
||||||
.split(",")
|
.split(",")
|
||||||
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
.map((item: string) => item.replace(/^\s*|\s*$/g, ""));
|
||||||
for (const item of resVal) {
|
for (const item of resVal) {
|
||||||
const values = item.values.values.map((d: { value: number }) =>
|
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);
|
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
||||||
@ -168,10 +170,7 @@ export function useSourceProcessor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === MetricQueryTypes.ReadMetricsValue) {
|
if (type === MetricQueryTypes.ReadMetricsValue) {
|
||||||
source[m] = aggregation(
|
source[m] = aggregation(Number(Object.values(resp.data)[0]), c);
|
||||||
Number(Object.values(resp.data)[0]),
|
|
||||||
config.standard
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
type === MetricQueryTypes.SortMetrics ||
|
type === MetricQueryTypes.SortMetrics ||
|
||||||
@ -179,7 +178,7 @@ export function useSourceProcessor(
|
|||||||
) {
|
) {
|
||||||
source[m] = (Object.values(resp.data)[0] || []).map(
|
source[m] = (Object.values(resp.data)[0] || []).map(
|
||||||
(d: { value: unknown; name: string }) => {
|
(d: { value: unknown; name: string }) => {
|
||||||
d.value = aggregation(Number(d.value), config.standard);
|
d.value = aggregation(Number(d.value), c);
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@ -307,33 +306,28 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
|||||||
return { queryStr, conditions };
|
return { queryStr, conditions };
|
||||||
}
|
}
|
||||||
|
|
||||||
function aggregation(val: number, standard: any): number | string {
|
function aggregation(val: number, config: any): number | string {
|
||||||
let data: number | string = val;
|
let data: number | string = val;
|
||||||
|
|
||||||
if (!isNaN(standard.plus)) {
|
switch (config.calculation) {
|
||||||
data = val + Number(standard.plus);
|
case Calculations.Percentage:
|
||||||
return data;
|
data = val / 100;
|
||||||
}
|
break;
|
||||||
if (!isNaN(standard.minus)) {
|
case Calculations.ByteToKB:
|
||||||
data = val - Number(standard.plus);
|
data = val / 1024;
|
||||||
return data;
|
break;
|
||||||
}
|
case Calculations.Apdex:
|
||||||
if (!isNaN(standard.multiply) && standard.divide !== 0) {
|
data = val / 10000;
|
||||||
data = val * Number(standard.multiply);
|
break;
|
||||||
return data;
|
case Calculations.ConvertSeconds:
|
||||||
}
|
|
||||||
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");
|
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
||||||
return data;
|
break;
|
||||||
}
|
case Calculations.ConvertMilliseconds:
|
||||||
if (standard.milliseconds) {
|
|
||||||
data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss");
|
data = dayjs.unix(val).format("YYYY-MM-DD HH:mm:ss");
|
||||||
return data;
|
break;
|
||||||
|
default:
|
||||||
|
data;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +127,7 @@ const msg = {
|
|||||||
kubernetes: "Kubernetes",
|
kubernetes: "Kubernetes",
|
||||||
textUrl: "Text Hyperlink",
|
textUrl: "Text Hyperlink",
|
||||||
textAlign: "Text Align",
|
textAlign: "Text Align",
|
||||||
|
metricLabel: "Metric Label",
|
||||||
hourTip: "Select Hour",
|
hourTip: "Select Hour",
|
||||||
minuteTip: "Select Minute",
|
minuteTip: "Select Minute",
|
||||||
secondTip: "Select Second",
|
secondTip: "Select Second",
|
||||||
@ -259,7 +260,7 @@ const msg = {
|
|||||||
independentSelector: "Selectors",
|
independentSelector: "Selectors",
|
||||||
unknownMetrics: "Unknown Metrics",
|
unknownMetrics: "Unknown Metrics",
|
||||||
labels: "Labels",
|
labels: "Labels",
|
||||||
aggregation: "Data Calculation",
|
aggregation: "Calculation",
|
||||||
unit: "Unit",
|
unit: "Unit",
|
||||||
labelsIndex: "Label Subscript",
|
labelsIndex: "Label Subscript",
|
||||||
parentService: "Parent Service",
|
parentService: "Parent Service",
|
||||||
|
@ -127,6 +127,7 @@ const msg = {
|
|||||||
kubernetes: "Kubernetes",
|
kubernetes: "Kubernetes",
|
||||||
textUrl: "文本超链接",
|
textUrl: "文本超链接",
|
||||||
textAlign: "文本对齐",
|
textAlign: "文本对齐",
|
||||||
|
metricLabel: "指标标签",
|
||||||
hourTip: "选择小时",
|
hourTip: "选择小时",
|
||||||
minuteTip: "选择分钟",
|
minuteTip: "选择分钟",
|
||||||
secondTip: "选择秒数",
|
secondTip: "选择秒数",
|
||||||
@ -261,7 +262,7 @@ const msg = {
|
|||||||
independentSelector: "独立选择器",
|
independentSelector: "独立选择器",
|
||||||
unknownMetrics: "未知指标",
|
unknownMetrics: "未知指标",
|
||||||
labels: "标签",
|
labels: "标签",
|
||||||
aggregation: "数据计算",
|
aggregation: "计算",
|
||||||
unit: "单位",
|
unit: "单位",
|
||||||
labelsIndex: "标签下标",
|
labelsIndex: "标签下标",
|
||||||
parentService: "父级服务",
|
parentService: "父级服务",
|
||||||
|
@ -28,6 +28,7 @@ export const NewControl = {
|
|||||||
standard: {},
|
standard: {},
|
||||||
metrics: [""],
|
metrics: [""],
|
||||||
metricTypes: [""],
|
metricTypes: [""],
|
||||||
|
metricConfig: [],
|
||||||
};
|
};
|
||||||
export const TextConfig = {
|
export const TextConfig = {
|
||||||
fontColor: "white",
|
fontColor: "white",
|
||||||
|
@ -36,8 +36,17 @@ export interface LayoutConfig {
|
|||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
children?: any;
|
children?: any;
|
||||||
activedTabIndex?: number;
|
activedTabIndex?: number;
|
||||||
|
metricConfig?: MetricConfigOpt[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MetricConfigOpt = {
|
||||||
|
unit: string;
|
||||||
|
label: string;
|
||||||
|
calculation: string;
|
||||||
|
labelsIndex: string;
|
||||||
|
sortOrder: string;
|
||||||
|
};
|
||||||
|
|
||||||
export interface WidgetConfig {
|
export interface WidgetConfig {
|
||||||
title?: string;
|
title?: string;
|
||||||
tips?: string;
|
tips?: string;
|
||||||
|
@ -49,6 +49,14 @@ limitations under the License. -->
|
|||||||
@change="changeMetricType(index, $event)"
|
@change="changeMetricType(index, $event)"
|
||||||
class="selectors"
|
class="selectors"
|
||||||
/>
|
/>
|
||||||
|
<el-popover placement="top" :width="400" :visible="showConfig">
|
||||||
|
<template #reference>
|
||||||
|
<span @click="setMetricConfig(index)">
|
||||||
|
<Icon class="cp mr-5" iconName="mode_edit" size="middle" />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<StandardOptions @update="queryMetrics" @close="showConfig = false" />
|
||||||
|
</el-popover>
|
||||||
<span
|
<span
|
||||||
v-show="states.isList || states.metricTypes[0] === 'readMetricsValues'"
|
v-show="states.isList || states.metricTypes[0] === 'readMetricsValues'"
|
||||||
>
|
>
|
||||||
@ -101,13 +109,15 @@ import { ElMessage } from "element-plus";
|
|||||||
import Icon from "@/components/Icon.vue";
|
import Icon from "@/components/Icon.vue";
|
||||||
import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor";
|
import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { DashboardItem } from "@/types/dashboard";
|
import { DashboardItem, MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
import StandardOptions from "./StandardOptions.vue";
|
||||||
|
|
||||||
/*global defineEmits */
|
/*global defineEmits */
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(["update", "loading", "changeOpt"]);
|
const emit = defineEmits(["update", "loading", "changeOpt"]);
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { metrics, metricTypes, graph } = dashboardStore.selectedGrid;
|
const { metrics, metricTypes, graph } = dashboardStore.selectedGrid;
|
||||||
|
const showConfig = ref<boolean>(false);
|
||||||
const states = reactive<{
|
const states = reactive<{
|
||||||
metrics: string[];
|
metrics: string[];
|
||||||
metricTypes: string[];
|
metricTypes: string[];
|
||||||
@ -127,6 +137,13 @@ const states = reactive<{
|
|||||||
dashboardName: graph.dashboardName,
|
dashboardName: graph.dashboardName,
|
||||||
dashboardList: [{ label: "", value: "" }],
|
dashboardList: [{ label: "", value: "" }],
|
||||||
});
|
});
|
||||||
|
const currentMetricConfig = ref<MetricConfigOpt>({
|
||||||
|
unit: "",
|
||||||
|
label: "",
|
||||||
|
labelsIndex: "",
|
||||||
|
calculation: "",
|
||||||
|
sortOrder: "DES",
|
||||||
|
});
|
||||||
|
|
||||||
states.isList = ListChartTypes.includes(graph.type);
|
states.isList = ListChartTypes.includes(graph.type);
|
||||||
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
const defaultLen = ref<number>(states.isList ? 5 : 20);
|
||||||
@ -323,8 +340,8 @@ async function queryMetrics() {
|
|||||||
if (states.isList) {
|
if (states.isList) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { standard } = dashboardStore.selectedGrid;
|
const { metricConfig } = dashboardStore.selectedGrid;
|
||||||
const params = useQueryProcessor({ ...states, standard });
|
const params = useQueryProcessor({ ...states, metricConfig });
|
||||||
if (!params) {
|
if (!params) {
|
||||||
emit("update", {});
|
emit("update", {});
|
||||||
return;
|
return;
|
||||||
@ -337,7 +354,7 @@ async function queryMetrics() {
|
|||||||
ElMessage.error(json.errors);
|
ElMessage.error(json.errors);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const source = useSourceProcessor(json, { ...states, standard });
|
const source = useSourceProcessor(json, { ...states, metricConfig });
|
||||||
emit("update", source);
|
emit("update", source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,6 +410,28 @@ function setMetricTypeList(type: string) {
|
|||||||
}
|
}
|
||||||
return MetricTypes[type];
|
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;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.ds-name {
|
.ds-name {
|
||||||
|
@ -13,174 +13,125 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License. -->
|
limitations under the License. -->
|
||||||
<template>
|
<template>
|
||||||
<div class="item">
|
<div class="config-panel">
|
||||||
|
<Icon
|
||||||
|
class="cp mr-5 close"
|
||||||
|
iconName="cancel"
|
||||||
|
size="middle"
|
||||||
|
@click="closePopper"
|
||||||
|
/>
|
||||||
|
<div class="item mb-10">
|
||||||
<span class="label">{{ t("unit") }}</span>
|
<span class="label">{{ t("unit") }}</span>
|
||||||
<el-input
|
<el-input
|
||||||
class="input"
|
class="input"
|
||||||
v-model="selectedGrid.standard.unit"
|
v-model="currentMetric.unit"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="Please input Unit"
|
placeholder="Please input unit"
|
||||||
|
@change="changeConfigs(index, { unit: currentMetricConfig.unit })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item mb-10">
|
||||||
|
<span class="label">{{ t("metricLabel") }}</span>
|
||||||
|
<el-input
|
||||||
|
class="input"
|
||||||
|
v-model="currentMetric.label"
|
||||||
|
size="small"
|
||||||
|
placeholder="Please input a name"
|
||||||
|
@change="changeConfigs(index, { label: currentMetricConfig.label })"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item mb-10">
|
||||||
|
<span class="label">{{ t("labelsIndex") }}</span>
|
||||||
|
<el-input
|
||||||
|
class="input"
|
||||||
|
v-model="currentMetric.labelsIndex"
|
||||||
|
size="small"
|
||||||
|
placeholder="auto"
|
||||||
|
@change="
|
||||||
|
changeConfigs(index, { label: currentMetricConfig.labelsIndex })
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="item mb-10">
|
||||||
|
<span class="label">{{ t("aggregation") }}</span>
|
||||||
|
<Selector
|
||||||
|
:value="currentMetric.calculation"
|
||||||
|
:options="CalculationOpts"
|
||||||
|
size="small"
|
||||||
|
placeholder="Select a option"
|
||||||
|
@change="changeConfigs(index, { calculation: $event[0].value })"
|
||||||
|
class="aggregation"
|
||||||
|
:clearable="true"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
<div class="item">
|
||||||
<span class="label">{{ t("sortOrder") }}</span>
|
<span class="label">{{ t("sortOrder") }}</span>
|
||||||
<Selector
|
<Selector
|
||||||
:value="sortOrder"
|
:value="currentMetric.sortOrder || 'DES'"
|
||||||
:options="SortOrder"
|
:options="SortOrder"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="Select a sort order"
|
placeholder="Select a sort order"
|
||||||
class="selector"
|
class="aggregation"
|
||||||
@change="changeStandardOpt({ sortOrder })"
|
@change="changeConfigs(index, { sortOrder: $event[0].value })"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("labels") }}</span>
|
|
||||||
<el-input
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.metricLabels"
|
|
||||||
size="small"
|
|
||||||
placeholder="auto"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("labelsIndex") }}</span>
|
|
||||||
<el-input
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.labelsIndex"
|
|
||||||
size="small"
|
|
||||||
placeholder="auto"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("plus") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.plus"
|
|
||||||
:min="0"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("minus") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.minus"
|
|
||||||
:min="0"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("multiply") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.multiply"
|
|
||||||
:min="1"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("divide") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
v-model="selectedGrid.standard.divide"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
:min="1"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("convertToMilliseconds") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
:min="0"
|
|
||||||
v-model="selectedGrid.standard.milliseconds"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="item">
|
|
||||||
<span class="label">{{ t("convertToSeconds") }}</span>
|
|
||||||
<el-input-number
|
|
||||||
class="input"
|
|
||||||
:min="0"
|
|
||||||
v-model="selectedGrid.standard.seconds"
|
|
||||||
size="small"
|
|
||||||
placeholder="Please input"
|
|
||||||
@change="changeStandardOpt"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
|
import type { PropType } from "vue";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { SortOrder } from "../../data";
|
import { SortOrder, CalculationOpts } from "../../data";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useQueryProcessor, useSourceProcessor } from "@/hooks/useProcessor";
|
import { MetricConfigOpt } from "@/types/dashboard";
|
||||||
import { ElMessage } from "element-plus";
|
|
||||||
|
|
||||||
/*global defineEmits */
|
/*global defineEmits, defineProps */
|
||||||
|
const props = defineProps({
|
||||||
|
currentMetricConfig: {
|
||||||
|
type: Object as PropType<MetricConfigOpt>,
|
||||||
|
default: () => ({ unit: "" }),
|
||||||
|
},
|
||||||
|
index: { type: Number, default: 0 },
|
||||||
|
});
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const emit = defineEmits(["update", "loading"]);
|
const emit = defineEmits(["update", "close"]);
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
const { selectedGrid } = dashboardStore;
|
const currentMetric = ref<MetricConfigOpt>(props.currentMetricConfig);
|
||||||
const sortOrder = ref<string>(selectedGrid.standard.sortOrder || "DES");
|
|
||||||
|
|
||||||
function changeStandardOpt(param?: any) {
|
function changeConfigs(index: number, param: { [key: string]: string }) {
|
||||||
let standard = dashboardStore.selectedGrid.standard;
|
const metricConfig = dashboardStore.selectedGrid.metricConfig || [];
|
||||||
if (param) {
|
metricConfig[index] = { ...metricConfig[index], ...param };
|
||||||
standard = {
|
dashboardStore.selectWidget({
|
||||||
...dashboardStore.selectedGrid.standard,
|
...dashboardStore.selectedGrid,
|
||||||
...param,
|
metricConfig,
|
||||||
};
|
});
|
||||||
dashboardStore.selectWidget({ ...dashboardStore.selectedGrid, standard });
|
console.log(dashboardStore.selectedGrid);
|
||||||
}
|
emit("update");
|
||||||
queryMetrics();
|
|
||||||
}
|
}
|
||||||
async function queryMetrics() {
|
|
||||||
const params = useQueryProcessor(dashboardStore.selectedGrid);
|
|
||||||
if (!params) {
|
|
||||||
emit("update", {});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit("loading", true);
|
function closePopper() {
|
||||||
const json = await dashboardStore.fetchMetricValue(params);
|
emit("close");
|
||||||
emit("loading", false);
|
|
||||||
if (json.errors) {
|
|
||||||
ElMessage.error(json.errors);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const source = useSourceProcessor(json, dashboardStore.selectedGrid);
|
|
||||||
emit("update", source);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.config-panel {
|
||||||
|
padding: 10px 5px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: 13px;
|
width: 150px;
|
||||||
font-weight: 500;
|
display: inline-block;
|
||||||
display: block;
|
font-size: 12px;
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.close {
|
||||||
width: 500px;
|
position: absolute;
|
||||||
|
top: -8px;
|
||||||
|
right: -15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item {
|
.aggregation {
|
||||||
margin-bottom: 10px;
|
width: 365px;
|
||||||
}
|
|
||||||
|
|
||||||
.selector {
|
|
||||||
width: 500px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -128,7 +128,7 @@ export default defineComponent({
|
|||||||
const d = {
|
const d = {
|
||||||
metrics: props.data.metrics,
|
metrics: props.data.metrics,
|
||||||
metricTypes: props.data.metricTypes,
|
metricTypes: props.data.metricTypes,
|
||||||
standard: props.data.standard,
|
metricConfig: props.data.metricConfig || [],
|
||||||
};
|
};
|
||||||
state.source = useSourceProcessor(json, d);
|
state.source = useSourceProcessor(json, d);
|
||||||
}
|
}
|
||||||
|
@ -264,3 +264,11 @@ export const TextColors: { [key: string]: string } = {
|
|||||||
black: "#000",
|
black: "#000",
|
||||||
orange: "#E6A23C",
|
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" },
|
||||||
|
];
|
||||||
|