add labels for percentile metrics

This commit is contained in:
Qiuxia Fan 2022-03-13 15:49:54 +08:00
parent 30941d6a9d
commit 592fb8220f
10 changed files with 349 additions and 229 deletions

View File

@ -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)",
// },
// },
// ],
// },
// };

View File

@ -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
}`,
};

View File

@ -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}}`;

View File

@ -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

View File

@ -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];

View File

@ -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;

View File

@ -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);
}

View File

@ -35,23 +35,23 @@ limitations under the License. -->
/>
</div>
<div class="item">
<span class="label">{{ t("max") }}</span>
<span class="label">{{ t("labels") }}</span>
<el-input
class="input"
v-model="state.max"
v-model="state.metricLabels"
size="small"
placeholder="auto"
@change="changeStandardOpt({ max: state.max })"
@change="changeStandardOpt({ metricLabels: state.metricLabels })"
/>
</div>
<div class="item">
<span class="label">{{ t("min") }}</span>
<span class="label">{{ t("labelsIndex") }}</span>
<el-input
class="input"
v-model="state.min"
v-model="state.labelsIndex"
size="small"
placeholder="auto"
@change="changeStandardOpt({ min: state.min })"
@change="changeStandardOpt({ labelsIndex: state.labelsIndex })"
/>
</div>
<div class="item">
@ -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: "",

View File

@ -84,7 +84,6 @@ limitations under the License. -->
:row-height="10"
:is-draggable="true"
:is-resizable="true"
:responsive="true"
@layout-updated="layoutUpdatedEvent"
>
<grid-item
@ -144,9 +143,11 @@ export default defineComponent({
const l = dashboardStore.layout.findIndex(
(d: LayoutConfig) => 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();

View File

@ -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() {