mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-10-14 11:21:29 +00:00
feat: add an avg calculation for metrics of list graphs (#65)
This commit is contained in:
@@ -466,7 +466,7 @@ function setMetricConfig(index: number) {
|
||||
.chart-types {
|
||||
span {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
padding: 2px 10px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #fff;
|
||||
border-right: 0;
|
||||
|
@@ -105,6 +105,7 @@ function editConfig() {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tools {
|
||||
|
@@ -266,11 +266,12 @@ export const CalculationOpts = [
|
||||
{ label: "Byte to KB", value: "byteToKB" },
|
||||
{ label: "Byte to MB", value: "byteToMB" },
|
||||
{ label: "Byte to GB", value: "byteToGB" },
|
||||
{ label: "Average", value: "average" },
|
||||
{
|
||||
label: "Convert milliseconds to YYYY-MM-DD HH:mm:ss",
|
||||
label: "Milliseconds to YYYY-MM-DD HH:mm:ss",
|
||||
value: "convertMilliseconds",
|
||||
},
|
||||
{ label: "Convert seconds to YYYY-MM-DD HH:mm:ss", value: "convertSeconds" },
|
||||
{ label: "Seconds to YYYY-MM-DD HH:mm:ss", value: "convertSeconds" },
|
||||
{ label: "Precision is 2", value: "precision" },
|
||||
{ label: "Milliseconds to seconds", value: "msTos" },
|
||||
];
|
||||
|
@@ -17,11 +17,13 @@ limitations under the License. -->
|
||||
<div
|
||||
v-if="!isNaN(singleVal)"
|
||||
class="chart-card"
|
||||
:class="{ center: config.textAlign === 'center' }"
|
||||
:style="{ fontSize: `${config.fontSize}px`, textAlign: config.textAlign }"
|
||||
:style="{
|
||||
fontSize: `${config.fontSize}px`,
|
||||
justifyContent: config.textAlign || 'center',
|
||||
}"
|
||||
>
|
||||
{{ singleVal.toFixed(2) }}
|
||||
<span v-show="config.showUnit">
|
||||
<span class="unit" v-show="config.showUnit">
|
||||
{{ decodeURIComponent(unit) }}
|
||||
</span>
|
||||
</div>
|
||||
@@ -59,19 +61,19 @@ const unit = computed(
|
||||
<style lang="scss" scoped>
|
||||
.chart-card {
|
||||
color: #333;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.center {
|
||||
box-sizing: border-box;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-pack: center;
|
||||
-webkit-box-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
height: 100%;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.unit {
|
||||
display: inline-block;
|
||||
margin-left: 2px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -42,34 +42,11 @@ limitations under the License. -->
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(metric, index) in colMetrics"
|
||||
:label="`${decodeURIComponent(
|
||||
getLabel(metric, index)
|
||||
)} ${decodeURIComponent(getUnit(index))}`"
|
||||
:key="metric + index"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="chart">
|
||||
<Line
|
||||
v-if="config.metricTypes[index] === 'readMetricsValues'"
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:intervalTime="intervalTime"
|
||||
:config="{
|
||||
showXAxis: false,
|
||||
showYAxis: false,
|
||||
smallTips: true,
|
||||
showSymbol: true,
|
||||
}"
|
||||
/>
|
||||
<Card
|
||||
v-else
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:config="{ textAlign: 'left' }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<ColumnGraph
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
/>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
@@ -83,12 +60,11 @@ import { EndpointListConfig } from "@/types/dashboard";
|
||||
import { Endpoint } from "@/types/selector";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
|
||||
import Line from "./Line.vue";
|
||||
import Card from "./Card.vue";
|
||||
import { EntityType } from "../data";
|
||||
import router from "@/router";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import { MetricConfigOpt } from "@/types/dashboard";
|
||||
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
@@ -184,26 +160,6 @@ function clickEndpoint(scope: any) {
|
||||
async function searchList() {
|
||||
await queryEndpoints();
|
||||
}
|
||||
function getUnit(index: number) {
|
||||
const u =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].unit;
|
||||
if (u) {
|
||||
return `(${encodeURIComponent(u)})`;
|
||||
}
|
||||
return encodeURIComponent("");
|
||||
}
|
||||
function getLabel(metric: string, index: number) {
|
||||
const label =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].label;
|
||||
if (label) {
|
||||
return encodeURIComponent(label);
|
||||
}
|
||||
return encodeURIComponent(metric);
|
||||
}
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
(data, old) => {
|
||||
|
@@ -42,35 +42,11 @@ limitations under the License. -->
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(metric, index) in colMetrics"
|
||||
:label="`${decodeURIComponent(
|
||||
getLabel(metric, index)
|
||||
)} ${decodeURIComponent(getUnit(index))}`"
|
||||
:key="metric + index"
|
||||
min-width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="chart">
|
||||
<Line
|
||||
v-if="config.metricTypes[index] === 'readMetricsValues'"
|
||||
:data="metric ? { [metric]: scope.row[metric] } : {}"
|
||||
:intervalTime="intervalTime"
|
||||
:config="{
|
||||
showXAxis: false,
|
||||
showYAxis: false,
|
||||
smallTips: true,
|
||||
showSymbol: true,
|
||||
}"
|
||||
/>
|
||||
<Card
|
||||
v-else
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:config="{ textAlign: 'left' }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<ColumnGraph
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
/>
|
||||
<el-table-column label="Attributes">
|
||||
<template #default="scope">
|
||||
<el-popover placement="left" :width="400" trigger="click">
|
||||
@@ -110,8 +86,6 @@ import { ref, watch, computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { PropType } from "vue";
|
||||
import Line from "./Line.vue";
|
||||
import Card from "./Card.vue";
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { InstanceListConfig } from "@/types/dashboard";
|
||||
@@ -121,6 +95,7 @@ import { EntityType } from "../data";
|
||||
import router from "@/router";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import { MetricConfigOpt } from "@/types/dashboard";
|
||||
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
@@ -236,28 +211,6 @@ function searchList() {
|
||||
queryInstanceMetrics(instances.value);
|
||||
}
|
||||
|
||||
function getUnit(index: number) {
|
||||
const u =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].unit;
|
||||
if (u) {
|
||||
return `(${encodeURIComponent(u)})`;
|
||||
}
|
||||
return encodeURIComponent("");
|
||||
}
|
||||
|
||||
function getLabel(metric: string, index: number) {
|
||||
const label =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].label;
|
||||
if (label) {
|
||||
return encodeURIComponent(label);
|
||||
}
|
||||
return encodeURIComponent(metric);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
(data, old) => {
|
||||
|
@@ -40,6 +40,7 @@ const props = defineProps({
|
||||
showXAxis: true,
|
||||
showYAxis: true,
|
||||
smallTips: false,
|
||||
showlabels: true,
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -185,7 +186,8 @@ function getOption() {
|
||||
left: 0,
|
||||
right: 10,
|
||||
bottom: 5,
|
||||
containLabel: true,
|
||||
containLabel:
|
||||
props.config.showlabels === undefined ? true : props.config.showlabels,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
@@ -199,6 +201,7 @@ function getOption() {
|
||||
axisLabel: { color: "#9da5b2", fontSize: "11" },
|
||||
},
|
||||
yAxis: {
|
||||
show: props.config.showYAxis,
|
||||
type: "value",
|
||||
axisLine: { show: false },
|
||||
axisTick: { show: false },
|
||||
|
@@ -54,34 +54,11 @@ limitations under the License. -->
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(metric, index) in colMetrics"
|
||||
:label="`${decodeURIComponent(
|
||||
getLabel(metric, index)
|
||||
)} ${decodeURIComponent(getUnit(index))}`"
|
||||
:key="metric + index"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="chart">
|
||||
<Line
|
||||
v-if="config.metricTypes[index] === 'readMetricsValues'"
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:intervalTime="intervalTime"
|
||||
:config="{
|
||||
showXAxis: false,
|
||||
showYAxis: false,
|
||||
smallTips: true,
|
||||
showSymbol: true,
|
||||
}"
|
||||
/>
|
||||
<Card
|
||||
v-else
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:config="{ textAlign: 'left' }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<ColumnGraph
|
||||
:intervalTime="intervalTime"
|
||||
:colMetrics="colMetrics"
|
||||
:config="config"
|
||||
/>
|
||||
</el-table>
|
||||
</div>
|
||||
<el-pagination
|
||||
@@ -102,8 +79,6 @@ import { watch, ref, computed } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { PropType } from "vue";
|
||||
import { ServiceListConfig } from "@/types/dashboard";
|
||||
import Line from "./Line.vue";
|
||||
import Card from "./Card.vue";
|
||||
import { useSelectorStore } from "@/store/modules/selectors";
|
||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||
import { Service } from "@/types/selector";
|
||||
@@ -112,6 +87,7 @@ import { EntityType } from "../data";
|
||||
import router from "@/router";
|
||||
import getDashboard from "@/hooks/useDashboardsSession";
|
||||
import { MetricConfigOpt } from "@/types/dashboard";
|
||||
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
@@ -240,6 +216,7 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
services.value = currentServices;
|
||||
}
|
||||
function objectSpanMethod(param: any): any {
|
||||
@@ -275,26 +252,6 @@ function searchList() {
|
||||
);
|
||||
setServices(services);
|
||||
}
|
||||
function getUnit(index: number) {
|
||||
const u =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].unit;
|
||||
if (u) {
|
||||
return `(${encodeURIComponent(u)})`;
|
||||
}
|
||||
return encodeURIComponent("");
|
||||
}
|
||||
function getLabel(metric: string, index: number) {
|
||||
const label =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[index] &&
|
||||
props.config.metricConfig[index].label;
|
||||
if (label) {
|
||||
return encodeURIComponent(label);
|
||||
}
|
||||
return encodeURIComponent(metric);
|
||||
}
|
||||
|
||||
watch(
|
||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||
@@ -318,10 +275,6 @@ watch(
|
||||
<style lang="scss" scoped>
|
||||
@import "./style.scss";
|
||||
|
||||
.chart {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.inputs {
|
||||
width: 300px;
|
||||
}
|
||||
|
161
src/views/dashboard/graphs/components/ColumnGraph.vue
Normal file
161
src/views/dashboard/graphs/components/ColumnGraph.vue
Normal file
@@ -0,0 +1,161 @@
|
||||
<!-- 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. -->
|
||||
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(metric, index) in colMetrics"
|
||||
:label="`${decodeURIComponent(
|
||||
getLabel(metric, index)
|
||||
)} ${decodeURIComponent(getUnit(index))}`"
|
||||
:key="metric + index"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="chart">
|
||||
<Line
|
||||
v-if="useListConfig(config, index).isLinear"
|
||||
:data="{
|
||||
[metric]: scope.row[metric] && scope.row[metric].values,
|
||||
}"
|
||||
:intervalTime="intervalTime"
|
||||
:config="{
|
||||
showXAxis: false,
|
||||
showYAxis: false,
|
||||
smallTips: true,
|
||||
showlabels: false,
|
||||
}"
|
||||
/>
|
||||
<span
|
||||
class="item flex-h"
|
||||
v-else-if="useListConfig(config, index).isAvg"
|
||||
>
|
||||
<el-popover placement="left" :width="400" trigger="click">
|
||||
<template #reference>
|
||||
<span class="trend">
|
||||
<Icon
|
||||
iconName="timeline"
|
||||
size="middle"
|
||||
style="color: #409eff"
|
||||
/>
|
||||
</span>
|
||||
</template>
|
||||
<div class="view-line">
|
||||
<Line
|
||||
:data="{
|
||||
[metric]: scope.row[metric] && scope.row[metric].values,
|
||||
}"
|
||||
:intervalTime="intervalTime"
|
||||
:config="{
|
||||
showXAxis: true,
|
||||
showYAxis: true,
|
||||
smallTips: false,
|
||||
showlabels: true,
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
</el-popover>
|
||||
<span class="value">
|
||||
<Card
|
||||
:data="{
|
||||
[metric]: scope.row[metric] && scope.row[metric].avg,
|
||||
}"
|
||||
:config="{ textAlign: 'left' }"
|
||||
/>
|
||||
</span>
|
||||
</span>
|
||||
<Card
|
||||
v-else
|
||||
:data="{ [metric]: scope.row[metric] }"
|
||||
:config="{ textAlign: 'left' }"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { PropType } from "vue";
|
||||
import { MetricConfigOpt } from "@/types/dashboard";
|
||||
import { useListConfig } from "@/hooks/useListConfig";
|
||||
import Line from "../Line.vue";
|
||||
import Card from "../Card.vue";
|
||||
|
||||
/*global defineProps */
|
||||
const props = defineProps({
|
||||
colMetrics: { type: Object },
|
||||
config: {
|
||||
type: Object as PropType<
|
||||
{
|
||||
i: string;
|
||||
metrics: string[];
|
||||
metricTypes: string[];
|
||||
} & { metricConfig: MetricConfigOpt[] }
|
||||
>,
|
||||
default: () => ({}),
|
||||
},
|
||||
intervalTime: { type: Array as PropType<string[]>, default: () => [] },
|
||||
});
|
||||
|
||||
function getUnit(index: string) {
|
||||
const i = Number(index);
|
||||
const u =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[i] &&
|
||||
props.config.metricConfig[i].unit;
|
||||
if (u) {
|
||||
return `(${encodeURIComponent(u)})`;
|
||||
}
|
||||
return encodeURIComponent("");
|
||||
}
|
||||
function getLabel(metric: string, index: string) {
|
||||
const i = Number(index);
|
||||
const label =
|
||||
props.config.metricConfig &&
|
||||
props.config.metricConfig[i] &&
|
||||
props.config.metricConfig[i].label;
|
||||
if (label) {
|
||||
return encodeURIComponent(label);
|
||||
}
|
||||
return encodeURIComponent(metric);
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.chart {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.view-line {
|
||||
width: 380px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.trend {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.value {
|
||||
display: inline-block;
|
||||
width: calc(100% - 30px);
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@@ -66,6 +66,7 @@ export default defineComponent({
|
||||
selectorStore.setCurrentService(null);
|
||||
selectorStore.setCurrentPod(null);
|
||||
dashboardStore.setEntity("");
|
||||
dashboardStore.setConfigPanel(false);
|
||||
});
|
||||
return {
|
||||
dashboardStore,
|
||||
|
Reference in New Issue
Block a user