mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-01 19:13:58 +00:00
feat: query metric list and add pagination for list components
This commit is contained in:
parent
2e82d52e71
commit
d9cb7500c8
18
src/assets/icons/add_circle_outlinecontrol_point.svg
Normal file
18
src/assets/icons/add_circle_outlinecontrol_point.svg
Normal file
@ -0,0 +1,18 @@
|
||||
<!-- 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">
|
||||
<title>add_circle_outlinecontrol_point</title>
|
||||
<path d="M12 20.016q3.281 0 5.648-2.367t2.367-5.648-2.367-5.648-5.648-2.367-5.648 2.367-2.367 5.648 2.367 5.648 5.648 2.367zM12 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.93zM12.984 6.984v4.031h4.031v1.969h-4.031v4.031h-1.969v-4.031h-4.031v-1.969h4.031v-4.031h1.969z"></path>
|
||||
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
@ -18,6 +18,17 @@ export const TypeOfMetrics = {
|
||||
variable: "$name: String!",
|
||||
query: `typeOfMetrics(name: $name)`,
|
||||
};
|
||||
export const listMetrics = {
|
||||
variable: "$regex: String",
|
||||
query: `
|
||||
metrics: listMetrics(regex: $regex) {
|
||||
value: name
|
||||
label: name
|
||||
type
|
||||
catalog
|
||||
}
|
||||
`,
|
||||
};
|
||||
export const queryMetricsValues = {
|
||||
variable: ["$condition: MetricsCondition!, $duration: Duration!"],
|
||||
query: `
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
querySortMetrics,
|
||||
queryMetricsValue,
|
||||
queryMetricsValues,
|
||||
listMetrics,
|
||||
} from "../fragments/dashboard";
|
||||
|
||||
export const queryTypeOfMetrics = `query typeOfMetrics(${TypeOfMetrics.variable}) {${TypeOfMetrics.query}}`;
|
||||
@ -38,3 +39,5 @@ export const sortMetrics = `query queryData(${querySortMetrics.variable}) {${que
|
||||
export const readMetricsValue = `query queryData(${queryMetricsValue.variable}) {${queryMetricsValue.query}}`;
|
||||
|
||||
export const readMetricsValues = `query queryData(${queryMetricsValues.variable}) {${queryMetricsValues.query}}`;
|
||||
|
||||
export const queryMetrics = `query queryData(${listMetrics.variable}) {${listMetrics.query}}`;
|
||||
|
@ -165,6 +165,13 @@ export const dashboardStore = defineStore({
|
||||
|
||||
return res.data;
|
||||
},
|
||||
async fetchMetricList(regex: string) {
|
||||
const res: AxiosResponse = await graph
|
||||
.query("queryMetrics")
|
||||
.params({ regex });
|
||||
|
||||
return res.data;
|
||||
},
|
||||
async fetchMetricValue(config: LayoutConfig) {
|
||||
// if (!config.queryMetricType) {
|
||||
// return;
|
||||
|
@ -38,37 +38,22 @@ limitations under the License. -->
|
||||
v-model="states.activeNames"
|
||||
:style="{ '--el-collapse-header-font-size': '15px' }"
|
||||
>
|
||||
<el-collapse-item :title="t('selectVisualization')" name="1">
|
||||
<div class="chart-types">
|
||||
<span
|
||||
v-for="(type, index) in states.visType"
|
||||
:key="index"
|
||||
@click="changeChartType(type)"
|
||||
:class="{ active: type.value === states.graph.type }"
|
||||
>
|
||||
{{ type.label }}
|
||||
</span>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item
|
||||
:title="t(states.isTable ? 'dashboardName' : 'metricName')"
|
||||
name="2"
|
||||
>
|
||||
<div v-if="states.isTable">
|
||||
<el-collapse-item :title="t('metricName')" name="1">
|
||||
<div v-show="states.isTable" class="ds-name">
|
||||
<Selector
|
||||
:value="states.graph.dashboardName"
|
||||
:options="metricOpts"
|
||||
:options="states.metricList"
|
||||
size="mini"
|
||||
placeholder="Select a dashboard"
|
||||
@change="changeDashboard"
|
||||
class="selectors"
|
||||
/>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
<Selector
|
||||
:value="states.metrics"
|
||||
:options="metricOpts"
|
||||
:multiple="true"
|
||||
:options="states.metricList"
|
||||
:multiple="!states.isTable"
|
||||
size="mini"
|
||||
placeholder="Select a metric"
|
||||
@change="changeMetrics"
|
||||
@ -83,6 +68,25 @@ limitations under the License. -->
|
||||
class="selectors"
|
||||
v-loading="loading"
|
||||
/>
|
||||
<Icon
|
||||
iconName="add_circle_outlinecontrol_point"
|
||||
size="middle"
|
||||
v-show="states.isTable"
|
||||
@click="addMetricName"
|
||||
class="cp"
|
||||
/>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="t('selectVisualization')" name="2">
|
||||
<div class="chart-types">
|
||||
<span
|
||||
v-for="(type, index) in states.visType"
|
||||
:key="index"
|
||||
@click="changeChartType(type)"
|
||||
:class="{ active: type.value === states.graph.type }"
|
||||
>
|
||||
{{ type.label }}
|
||||
</span>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item :title="t('graphStyles')" name="3">
|
||||
@ -147,6 +151,7 @@ export default defineComponent({
|
||||
StandardOptions,
|
||||
},
|
||||
setup() {
|
||||
const configHeight = document.documentElement.clientHeight - 520;
|
||||
const loading = ref<boolean>(false);
|
||||
const { t } = useI18n();
|
||||
const dashboardStore = useDashboardStore();
|
||||
@ -166,6 +171,7 @@ export default defineComponent({
|
||||
standard: StandardConfig;
|
||||
visType: Option[];
|
||||
isTable: boolean;
|
||||
metricList: (Option & { type: string })[];
|
||||
}>({
|
||||
metrics: selectedGrid.metrics || [],
|
||||
valueTypes: [],
|
||||
@ -179,14 +185,11 @@ export default defineComponent({
|
||||
standard: selectedGrid.standard,
|
||||
visType: [],
|
||||
isTable: false,
|
||||
metricList: [],
|
||||
});
|
||||
|
||||
states.isTable = TableChartTypes.includes(states.graph.type || "");
|
||||
|
||||
if (states.metrics[0]) {
|
||||
queryMetricType(states.metrics[0]);
|
||||
}
|
||||
|
||||
if (params.entity === "service") {
|
||||
states.visType = ChartTypes.filter(
|
||||
(d: Option) => d.value !== "serviceList"
|
||||
@ -201,32 +204,23 @@ export default defineComponent({
|
||||
);
|
||||
}
|
||||
|
||||
async function changeMetrics(arr: Option[]) {
|
||||
setMetricType(states.metrics[0]);
|
||||
|
||||
async function changeMetrics(arr: (Option & { type: string })[]) {
|
||||
if (!arr.length) {
|
||||
states.valueTypes = [];
|
||||
states.valueType = "";
|
||||
return;
|
||||
}
|
||||
states.metrics = arr.map((d: Option) => String(d.value));
|
||||
if (arr[0].value) {
|
||||
queryMetricType(String(arr[0].value));
|
||||
states.metrics = arr.map((d: Option) => d.value);
|
||||
if (arr[0]) {
|
||||
const typeOfMetrics = arr[0].type;
|
||||
states.valueTypes = ValuesTypes[typeOfMetrics];
|
||||
states.valueType = ValuesTypes[typeOfMetrics][0].value;
|
||||
queryMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
async function queryMetricType(metric: string) {
|
||||
loading.value = true;
|
||||
const resp = await dashboardStore.fetchMetricType(metric);
|
||||
loading.value = false;
|
||||
if (resp.error) {
|
||||
ElMessage.error(resp.data.error);
|
||||
return;
|
||||
}
|
||||
const { typeOfMetrics } = resp.data;
|
||||
states.valueTypes = ValuesTypes[typeOfMetrics];
|
||||
states.valueType = ValuesTypes[typeOfMetrics][0].value;
|
||||
queryMetrics();
|
||||
}
|
||||
|
||||
function changeValueType(val: Option[]) {
|
||||
states.valueType = String(val[0].value);
|
||||
states.metricQueryType = (MetricQueryTypes as any)[states.valueType];
|
||||
@ -244,20 +238,6 @@ export default defineComponent({
|
||||
states.graph.dashboardName = item[0].value;
|
||||
}
|
||||
|
||||
const metricOpts = [
|
||||
{ value: "service_apdex", label: "service_apdex" },
|
||||
{ value: "service_sla", label: "service_sla" },
|
||||
{ value: "service_cpm", label: "service_cpm" },
|
||||
{ value: "service_resp_time", label: "service_resp_time" },
|
||||
{ value: "service_percentile", label: "service_percentile" },
|
||||
{
|
||||
value: "service_mq_consume_latency",
|
||||
label: "service_mq_consume_latency",
|
||||
},
|
||||
{ value: "service_mq_consume_count", label: "service_mq_consume_count" },
|
||||
];
|
||||
const configHeight = document.documentElement.clientHeight - 520;
|
||||
|
||||
function updateWidgetOptions(param: { [key: string]: unknown }) {
|
||||
states.widget = {
|
||||
...states.widget,
|
||||
@ -288,10 +268,11 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
if (json.errors) {
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
const metricVal = json.data.readMetricsValues.values.values.map(
|
||||
(d: { value: number }) => d.value + 1
|
||||
(d: { value: number }) => d.value
|
||||
);
|
||||
const m = states.metrics[0];
|
||||
if (!m) {
|
||||
@ -301,8 +282,28 @@ export default defineComponent({
|
||||
[m]: metricVal,
|
||||
};
|
||||
}
|
||||
async function setMetricType(regex: string) {
|
||||
const json = await dashboardStore.fetchMetricList(regex);
|
||||
if (json.errors) {
|
||||
ElMessage.error(json.errors);
|
||||
return;
|
||||
}
|
||||
states.metricList = json.data.metrics || [];
|
||||
const name = states.metrics[0];
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
const typeOfMetrics: any = states.metricList.filter(
|
||||
(d: { value: string }) => d.value === name
|
||||
)[0];
|
||||
states.valueTypes = ValuesTypes[typeOfMetrics];
|
||||
states.valueType = ValuesTypes[typeOfMetrics][0].value;
|
||||
queryMetrics();
|
||||
}
|
||||
|
||||
queryMetrics();
|
||||
function addMetricName() {
|
||||
console.log(states);
|
||||
}
|
||||
|
||||
function applyConfig() {
|
||||
const opts = {
|
||||
@ -325,13 +326,13 @@ export default defineComponent({
|
||||
t,
|
||||
appStoreWithOut,
|
||||
ChartTypes,
|
||||
metricOpts,
|
||||
updateWidgetOptions,
|
||||
configHeight,
|
||||
updateGraphOptions,
|
||||
updateStandardOptions,
|
||||
applyConfig,
|
||||
changeDashboard,
|
||||
addMetricName,
|
||||
loading,
|
||||
};
|
||||
},
|
||||
@ -369,7 +370,7 @@ export default defineComponent({
|
||||
|
||||
.render-chart {
|
||||
padding: 5px;
|
||||
height: 350px;
|
||||
height: 360px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -427,4 +428,8 @@ span.active {
|
||||
margin-top: 10px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.ds-name {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
@ -18,9 +18,12 @@
|
||||
import AreaConfig from "./Area.vue";
|
||||
import LineConfig from "./Line.vue";
|
||||
import BarConfig from "./Bar.vue";
|
||||
import TableConfig from "./Table.vue";
|
||||
import CardConfig from "./Card.vue";
|
||||
import InstanceListConfig from "./InstanceList.vue";
|
||||
import EndpointListConfig from "./EndpointList.vue";
|
||||
import ServiceListConfig from "./ServiceList.vue";
|
||||
import TopListConfig from "./TopList.vue";
|
||||
|
||||
export default {
|
||||
AreaConfig,
|
||||
@ -29,4 +32,7 @@ export default {
|
||||
InstanceListConfig,
|
||||
EndpointListConfig,
|
||||
ServiceListConfig,
|
||||
TableConfig,
|
||||
CardConfig,
|
||||
TopListConfig,
|
||||
};
|
||||
|
@ -13,24 +13,36 @@ 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. -->
|
||||
<template>
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="selectorStore.endpoints"
|
||||
style="width: 100%; height: 100%; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Endpoints">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/endpoint/${selectorStore.currentService}/${scope.row.value}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="table">
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="endpoints"
|
||||
style="width: 100%; height: 100%; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Endpoints">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/endpoint/${selectorStore.currentService}/${scope.row.value}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:page-size="6"
|
||||
:total="selectorStore.endpoints.length"
|
||||
@current-change="changePage"
|
||||
@prev-click="changePage"
|
||||
@next-click="changePage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { defineProps, onBeforeMount, ref } from "vue";
|
||||
@ -50,6 +62,8 @@ defineProps({
|
||||
});
|
||||
const selectorStore = useSelectorStore();
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const endpoints = ref<{ label: string; value: string }[]>([]);
|
||||
const pageSize = 7;
|
||||
|
||||
onBeforeMount(async () => {
|
||||
chartLoading.value = true;
|
||||
@ -58,10 +72,26 @@ onBeforeMount(async () => {
|
||||
chartLoading.value = false;
|
||||
if (resp.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
return;
|
||||
}
|
||||
endpoints.value = selectorStore.endpoints.splice(0, pageSize);
|
||||
});
|
||||
function changePage(pageIndex: number) {
|
||||
endpoints.value = selectorStore.endpoints.splice(pageIndex - 1, pageSize);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: #409eff;
|
||||
|
@ -13,24 +13,36 @@ 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. -->
|
||||
<template>
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="selectorStore.instances"
|
||||
style="width: 100%; height: 100%; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Service Instances">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/serviceInstance/${selectorStore.currentService}/${scope.row.value}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="table">
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="instances"
|
||||
style="width: 100%; height: 320px; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Service Instances">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/serviceInstance/${selectorStore.currentService}/${scope.row.value}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:page-size="6"
|
||||
:total="selectorStore.instances.length"
|
||||
@current-change="changePage"
|
||||
@prev-click="changePage"
|
||||
@next-click="changePage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { defineProps, onBeforeMount, ref } from "vue";
|
||||
@ -50,6 +62,8 @@ defineProps({
|
||||
});
|
||||
const selectorStore = useSelectorStore();
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const instances = ref<any[]>([]);
|
||||
const pageSize = 7;
|
||||
|
||||
onBeforeMount(async () => {
|
||||
chartLoading.value = true;
|
||||
@ -58,10 +72,26 @@ onBeforeMount(async () => {
|
||||
chartLoading.value = false;
|
||||
if (resp.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
return;
|
||||
}
|
||||
instances.value = selectorStore.instances.splice(0, pageSize);
|
||||
});
|
||||
function changePage(pageIndex: number) {
|
||||
instances.value = selectorStore.instances.splice(pageIndex - 1, pageSize);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: #409eff;
|
||||
|
@ -13,24 +13,36 @@ 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. -->
|
||||
<template>
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="selectorStore.services"
|
||||
style="width: 100%; height: 100%; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Services">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/service/${selectorStore.currentService}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="table">
|
||||
<el-table
|
||||
v-loading="chartLoading"
|
||||
:data="services"
|
||||
style="width: 100%; height: 100%; overflow: auto"
|
||||
>
|
||||
<el-table-column label="Services">
|
||||
<template #default="scope">
|
||||
<router-link
|
||||
target="_blank"
|
||||
class="link"
|
||||
:to="`/dashboard/${scope.row.layer}/service/${selectorStore.currentService}/${config.dashboardName}`"
|
||||
:style="{ fontSize: `${config.fontSize}px` }"
|
||||
>
|
||||
{{ scope.row.label }}
|
||||
</router-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
class="pagination"
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:page-size="6"
|
||||
:total="selectorStore.services.length"
|
||||
@current-change="changePage"
|
||||
@prev-click="changePage"
|
||||
@next-click="changePage"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { defineProps, onBeforeMount, ref } from "vue";
|
||||
@ -50,6 +62,8 @@ defineProps({
|
||||
});
|
||||
const selectorStore = useSelectorStore();
|
||||
const chartLoading = ref<boolean>(false);
|
||||
const pageSize = 6;
|
||||
const services = ref<{ label: string; layer: string }>([]);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
chartLoading.value = true;
|
||||
@ -59,9 +73,24 @@ onBeforeMount(async () => {
|
||||
if (resp.errors) {
|
||||
ElMessage.error(resp.errors);
|
||||
}
|
||||
services.value = selectorStore.services.splice(0, pageSize);
|
||||
});
|
||||
function changePage(pageIndex: number) {
|
||||
services.value = selectorStore.services.splice(pageIndex - 1, pageSize);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
height: 30px;
|
||||
padding: 3px 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: #409eff;
|
||||
|
Loading…
Reference in New Issue
Block a user