From 592fb8220f742611a81f3013495fb4b35874c2cb Mon Sep 17 00:00:00 2001 From: Qiuxia Fan Date: Sun, 13 Mar 2022 15:49:54 +0800 Subject: [PATCH] add labels for percentile metrics --- src/constants/templates.ts | 463 ++++++++++-------- src/graphql/fragments/app.ts | 29 ++ src/graphql/query/app.ts | 15 +- src/hooks/useProcessor.ts | 19 +- src/store/modules/dashboard.ts | 6 +- src/types/dashboard.ts | 4 +- .../configuration/widget/MetricOptions.vue | 10 +- .../configuration/widget/StandardOptions.vue | 16 +- src/views/dashboard/controls/Tab.vue | 9 +- src/views/dashboard/controls/Widget.vue | 7 +- 10 files changed, 349 insertions(+), 229 deletions(-) diff --git a/src/constants/templates.ts b/src/constants/templates.ts index c3f97573..4adfd9e5 100644 --- a/src/constants/templates.ts +++ b/src/constants/templates.ts @@ -45,8 +45,6 @@ export const All = { metrics: ["all_percentile"], metricTypes: ["readLabeledMetricsValues"], type: "Widget", - metricLabels: "P50, P75, P90, P95, P99", - labelsIndex: "0, 1, 2, 3, 4", widget: { title: "Global Response Latency", tips: "Tooltip", @@ -56,6 +54,8 @@ export const All = { }, standard: { unit: "percentile in ms", + metricLabels: "P50, P75, P90, P95, P99", + labelsIndex: "0, 1, 2, 3, 4", }, }, { @@ -82,217 +82,274 @@ export const All = { }, }; -export const Service = { +export const ServiceLayout = { id: "1", configuration: { name: "Service", isRoot: true, children: [ { - w: 8, - h: 12, + x: 0, + y: 0, + w: 24, + h: 36, i: "0", - metrics: ["service_apdex"], - metricTypes: ["readMetricsValue"], - type: "Widget", + type: "Tab", widget: { - title: "Service Apdex", - tips: "Tooltip", - }, - graph: { - type: "Card", - }, - standard: { - aggregation: "/", - aggregationNum: "10000", - }, - }, - { - w: 8, - h: 12, - i: "1", - metrics: ["service_sla"], - metricTypes: ["readMetricsValue"], - type: "Widget", - widget: { - title: "Successful Rate", - tips: "Tooltip", - }, - graph: { - type: "Card", - }, - standard: { - unit: "%", - aggregation: "/", - aggregationNum: "100", - }, - }, - { - w: 8, - h: 12, - i: "2", - metrics: ["service_cpm"], - metricTypes: ["readMetricsValue"], - type: "Widget", - widget: { - title: "Service Load", - tips: "For HTTP 1/2, gRPC, RPC services, this means Calls Per Minute (CPM), for TCP services, this means Packets Per Minute (PPM)", - }, - graph: { - type: "Card", - }, - standard: { - unit: "CPM / PPM", - aggregation: "/", - aggregationNum: "100", - }, - }, - { - w: 8, - h: 12, - i: "3", - metrics: ["service_cpm"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Service cpm", - tips: "For HTTP 1/2, gRPC, RPC services, this means Calls Per Minute (CPM), for TCP services, this means Packets Per Minute (PPM)", - }, - graph: { - type: "Card", - }, - standard: { - unit: "CPM / PPM", - aggregation: "/", - aggregationNum: "100", - }, - }, - { - w: 8, - h: 12, - i: "4", - metrics: ["service_resp_time"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Service Avg Response Time", - }, - graph: { - type: "Line", - }, - standard: { - unit: "ms", - }, - }, - { - w: 8, - h: 12, - i: "5", - metrics: ["service_apdex"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Service Apdex", - }, - graph: { - type: "Line", - }, - standard: { - aggregation: "/", - aggregationNum: "10000", - }, - }, - { - w: 8, - h: 12, - i: "6", - metrics: ["service_percentile"], - metricTypes: ["readLabeledMetricsValues"], - type: "Widget", - metricLabels: "P50, P75, P90, P95, P99", - labelsIndex: "0, 1, 2, 3, 4", - widget: { - title: "Service Response Time Percentile", - }, - graph: { - type: "Line", - }, - standard: { - unit: "ms", - }, - }, - { - w: 8, - h: 12, - i: "7", - metrics: ["service_sla"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Successful Rate", - }, - graph: { - type: "Line", - }, - standard: { - unit: "%", - aggregation: "/", - aggregationNum: "100", - }, - }, - { - w: 8, - h: 12, - i: "8", - metrics: ["service_throughput_received", "service_throughput_sent"], - metricTypes: ["readMetricsValues", "readMetricsValues"], - type: "Widget", - widget: { - title: "Service Throughput", - }, - graph: { - type: "Line", - }, - standard: { - unit: "Bytes", - tips: "This metrics is only avaible for TCP services", - }, - }, - { - w: 8, - h: 12, - i: "9", - metrics: ["service_mq_consume_count"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Message Queue Consuming Count", - }, - graph: { - type: "Line", - }, - standard: { - tips: "The number of consumed messages.", - }, - }, - { - w: 8, - h: 12, - i: "10", - metrics: ["service_mq_consume_latency"], - metricTypes: ["readMetricsValues"], - type: "Widget", - widget: { - title: "Message Queue Consuming Count", - }, - graph: { - type: "Line", - }, - standard: { - unit: "ms", - tips: "The avg latency of message consuming. Latency = timestamp(received) - timestamp(producing)", + title: "Title", }, + graph: {}, + standard: {}, + metrics: [""], + metricTypes: [""], + children: [ + { + name: "Overview", + children: [ + { + x: 0, + y: 0, + w: 8, + h: 12, + i: "6", + metrics: ["service_percentile"], + metricTypes: ["readLabeledMetricsValues"], + type: "Widget", + widget: { + title: "Service Response Time Percentile", + }, + graph: { + type: "Line", + }, + standard: { + unit: "ms", + metricLabels: "P50, P75, P90, P95, P99", + labelsIndex: "0, 1, 2, 3, 4", + }, + }, + ], + }, + { + name: "Trace", + children: [], + }, + ], }, ], }, }; + +// export const ServiceLayout = { +// id: "1", +// configuration: { +// name: "Service", +// isRoot: true, +// children: [ +// { +// w: 8, +// h: 12, +// i: "0", +// metrics: ["service_apdex"], +// metricTypes: ["readMetricsValue"], +// type: "Widget", +// widget: { +// title: "Service Apdex", +// tips: "Tooltip", +// }, +// graph: { +// type: "Card", +// }, +// standard: { +// aggregation: "/", +// aggregationNum: "10000", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "1", +// metrics: ["service_sla"], +// metricTypes: ["readMetricsValue"], +// type: "Widget", +// widget: { +// title: "Successful Rate", +// tips: "Tooltip", +// }, +// graph: { +// type: "Card", +// }, +// standard: { +// unit: "%", +// aggregation: "/", +// aggregationNum: "100", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "2", +// metrics: ["service_cpm"], +// metricTypes: ["readMetricsValue"], +// type: "Widget", +// widget: { +// title: "Service Load", +// tips: "For HTTP 1/2, gRPC, RPC services, this means Calls Per Minute (CPM), for TCP services, this means Packets Per Minute (PPM)", +// }, +// graph: { +// type: "Card", +// }, +// standard: { +// unit: "CPM / PPM", +// aggregation: "/", +// aggregationNum: "100", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "3", +// metrics: ["service_cpm"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Service cpm", +// tips: "For HTTP 1/2, gRPC, RPC services, this means Calls Per Minute (CPM), for TCP services, this means Packets Per Minute (PPM)", +// }, +// graph: { +// type: "Card", +// }, +// standard: { +// unit: "CPM / PPM", +// aggregation: "/", +// aggregationNum: "100", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "4", +// metrics: ["service_resp_time"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Service Avg Response Time", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// unit: "ms", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "5", +// metrics: ["service_apdex"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Service Apdex", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// aggregation: "/", +// aggregationNum: "10000", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "6", +// metrics: ["service_percentile"], +// metricTypes: ["readLabeledMetricsValues"], +// type: "Widget", +// metricLabels: "P50, P75, P90, P95, P99", +// labelsIndex: "0, 1, 2, 3, 4", +// widget: { +// title: "Service Response Time Percentile", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// unit: "ms", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "7", +// metrics: ["service_sla"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Successful Rate", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// unit: "%", +// aggregation: "/", +// aggregationNum: "100", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "8", +// metrics: ["service_throughput_received", "service_throughput_sent"], +// metricTypes: ["readMetricsValues", "readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Service Throughput", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// unit: "Bytes", +// tips: "This metrics is only avaible for TCP services", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "9", +// metrics: ["service_mq_consume_count"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Message Queue Consuming Count", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// tips: "The number of consumed messages.", +// }, +// }, +// { +// w: 8, +// h: 12, +// i: "10", +// metrics: ["service_mq_consume_latency"], +// metricTypes: ["readMetricsValues"], +// type: "Widget", +// widget: { +// title: "Message Queue Consuming Count", +// }, +// graph: { +// type: "Line", +// }, +// standard: { +// unit: "ms", +// tips: "The avg latency of message consuming. Latency = timestamp(received) - timestamp(producing)", +// }, +// }, +// ], +// }, +// }; diff --git a/src/graphql/fragments/app.ts b/src/graphql/fragments/app.ts index f4b1374c..66838a1b 100644 --- a/src/graphql/fragments/app.ts +++ b/src/graphql/fragments/app.ts @@ -35,3 +35,32 @@ export const getAllTemplates = { } `, }; + +export const addTemplate = { + variable: "$setting: NewDashboardSetting!", + query: ` + addTemplate(setting: $setting) { + id + status + message + }`, +}; +export const changeTemplate = { + variable: "$setting: DashboardSetting!", + query: ` + changeTemplate(setting: $setting) { + id + status + message + }`, +}; + +export const deleteTemplate = { + variable: "$id: String!", + query: ` + disableTemplate(id: $id) { + id + status + message + }`, +}; diff --git a/src/graphql/query/app.ts b/src/graphql/query/app.ts index afd7747b..d70df7b4 100644 --- a/src/graphql/query/app.ts +++ b/src/graphql/query/app.ts @@ -14,10 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { OAPTimeInfo, OAPVersion, getAllTemplates } from "../fragments/app"; +import { + OAPTimeInfo, + OAPVersion, + getAllTemplates, + addTemplate, + changeTemplate, + deleteTemplate, +} from "../fragments/app"; export const queryOAPTimeInfo = `query queryOAPTimeInfo {${OAPTimeInfo.query}}`; export const queryOAPVersion = `query ${OAPVersion.query}`; export const getTemplates = `query queryTemplates {${getAllTemplates.query}}`; + +export const addNewTemplate = `query queryAlarms(${addTemplate.variable}) {${addTemplate.query}}`; + +export const updateTemplate = `query queryAlarms(${changeTemplate.variable}) {${changeTemplate.query}}`; + +export const removeTemplate = `query queryAlarms(${deleteTemplate.variable}) {${deleteTemplate.query}}`; diff --git a/src/hooks/useProcessor.ts b/src/hooks/useProcessor.ts index 85030381..6666657d 100644 --- a/src/hooks/useProcessor.ts +++ b/src/hooks/useProcessor.ts @@ -20,6 +20,7 @@ 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"; export function useQueryProcessor(config: any) { if (!(config.metrics && config.metrics[0])) { @@ -46,7 +47,6 @@ export function useQueryProcessor(config: any) { } const fragment = config.metrics.map((name: string, index: number) => { const metricType = config.metricTypes[index] || ""; - const labels = ["0", "1", "2", "3", "4"]; if ( [ MetricQueryTypes.ReadSampledRecords, @@ -66,6 +66,9 @@ export function useQueryProcessor(config: any) { }; } else { if (metricType === MetricQueryTypes.ReadLabeledMetricsValues) { + const labels = (config.labelsIndex || "") + .split(",") + .map((item: string) => item.replace(/^\s*|\s*$/g, "")); variables.push(`$labels${index}: [String!]!`); conditions[`labels${index}`] = labels; } @@ -121,7 +124,11 @@ export function useQueryProcessor(config: any) { } export function useSourceProcessor( resp: { errors: string; data: { [key: string]: any } }, - config: { metrics: string[]; metricTypes: string[] } + config: { + metrics: string[]; + metricTypes: string[]; + standard: StandardConfig; + } ) { if (resp.errors) { ElMessage.error(resp.errors); @@ -140,8 +147,12 @@ export function useSourceProcessor( } 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"]; + const labels = (config.standard.metricLabels || "") + .split(",") + .map((item: string) => item.replace(/^\s*|\s*$/g, "")); + const labelsIdx = (config.standard.labelsIndex || "") + .split(",") + .map((item: string) => item.replace(/^\s*|\s*$/g, "")); for (const item of resVal) { const values = item.values.values.map( (d: { value: number }) => d.value diff --git a/src/store/modules/dashboard.ts b/src/store/modules/dashboard.ts index 84af4f57..c3cf9f48 100644 --- a/src/store/modules/dashboard.ts +++ b/src/store/modules/dashboard.ts @@ -20,7 +20,6 @@ import { LayoutConfig } from "@/types/dashboard"; import graphql from "@/graphql"; import query from "@/graphql/fetch"; import { - ConfigData, ConfigData1, ConfigData2, ConfigData3, @@ -28,6 +27,7 @@ import { ConfigData5, ConfigData6, } from "../data"; +import { ServiceLayout } from "@/constants/templates"; import { useAppStoreWithOut } from "@/store/modules/app"; import { useSelectorStore } from "@/store/modules/selectors"; import { NewControl } from "../data"; @@ -49,7 +49,7 @@ interface DashboardState { export const dashboardStore = defineStore({ id: "dashboard", state: (): DashboardState => ({ - layout: [ConfigData], + layout: ServiceLayout.configuration.children, showConfig: false, selectedGrid: null, entity: "", @@ -240,7 +240,7 @@ export const dashboardStore = defineStore({ this.layout = ConfigData3; } if (type == "Service") { - this.layout = [ConfigData]; + this.layout = ServiceLayout.configuration.children; } if (type == "ServiceRelation") { this.layout = [ConfigData4]; diff --git a/src/types/dashboard.ts b/src/types/dashboard.ts index c0ec3d86..b9f1a817 100644 --- a/src/types/dashboard.ts +++ b/src/types/dashboard.ts @@ -38,8 +38,8 @@ export interface WidgetConfig { export interface StandardConfig { sortOrder?: string; unit?: string; - max?: string; - min?: string; + labelsIndex?: string; + metricLabels?: string; plus?: string; minus?: string; multiply?: string; diff --git a/src/views/dashboard/configuration/widget/MetricOptions.vue b/src/views/dashboard/configuration/widget/MetricOptions.vue index 3e9ef323..831322c5 100644 --- a/src/views/dashboard/configuration/widget/MetricOptions.vue +++ b/src/views/dashboard/configuration/widget/MetricOptions.vue @@ -199,7 +199,10 @@ function changeChartType(item: Option) { } } -function changeMetrics(index: number, arr: (Option & { type: string })[]) { +function changeMetrics( + index: number, + arr: (Option & { type: string })[] | any +) { if (!arr.length) { states.metricTypeList = []; states.metricTypes = []; @@ -224,7 +227,7 @@ function changeMetrics(index: number, arr: (Option & { type: string })[]) { queryMetrics(); } -function changeMetricType(index: number, opt: Option[]) { +function changeMetricType(index: number, opt: Option[] | any) { const metric = states.metricList.filter( (d: Option) => states.metrics[index] === d.value @@ -266,7 +269,8 @@ async function queryMetrics() { ElMessage.error(json.errors); return; } - const source = useSourceProcessor(json, states); + const { standard } = dashboardStore.selectedGrid; + const source = useSourceProcessor(json, { ...states, standard }); emit("update", source); } diff --git a/src/views/dashboard/configuration/widget/StandardOptions.vue b/src/views/dashboard/configuration/widget/StandardOptions.vue index 6b4c3029..a049a3ad 100644 --- a/src/views/dashboard/configuration/widget/StandardOptions.vue +++ b/src/views/dashboard/configuration/widget/StandardOptions.vue @@ -35,23 +35,23 @@ limitations under the License. --> />
- {{ t("max") }} + {{ t("labels") }}
- {{ t("min") }} + {{ t("labelsIndex") }}
@@ -126,8 +126,8 @@ const { selectedGrid } = dashboardStore; const { t } = useI18n(); const state = reactive({ unit: selectedGrid.standard.unit, - max: "", - min: "", + labelsIndex: selectedGrid.standard.labelsIndex, + metricLabels: selectedGrid.standard.metricLabels, plus: "", minus: "", multiply: "", diff --git a/src/views/dashboard/controls/Tab.vue b/src/views/dashboard/controls/Tab.vue index 78f45864..3ffcd15a 100644 --- a/src/views/dashboard/controls/Tab.vue +++ b/src/views/dashboard/controls/Tab.vue @@ -84,7 +84,6 @@ limitations under the License. --> :row-height="10" :is-draggable="true" :is-resizable="true" - :responsive="true" @layout-updated="layoutUpdatedEvent" > d.i === props.data.i ); - dashboardStore.setCurrentTabItems( - dashboardStore.layout[l].children[activeTabIndex.value].children - ); + if (dashboardStore.layout[l].children.length) { + dashboardStore.setCurrentTabItems( + dashboardStore.layout[l].children[activeTabIndex.value].children + ); + } function clickTabs(e: Event, idx: number) { e.stopPropagation(); diff --git a/src/views/dashboard/controls/Widget.vue b/src/views/dashboard/controls/Widget.vue index 56de4729..f4d550d7 100644 --- a/src/views/dashboard/controls/Widget.vue +++ b/src/views/dashboard/controls/Widget.vue @@ -111,7 +111,12 @@ export default defineComponent({ if (!json) { return; } - state.source = useSourceProcessor(json, props.data); + const d = { + metrics: props.data.metrics, + metricTypes: props.data.metricTypes, + standard: props.data.standard, + }; + state.source = useSourceProcessor(json, d); } function removeWidget() {