mirror of
https://github.com/apache/skywalking-booster-ui.git
synced 2025-05-02 18:15:22 +00:00
feat: add an avg calculation for metrics of list graphs (#65)
This commit is contained in:
parent
2dd9df19d7
commit
69a9c6de13
@ -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>timeline</title>
|
|
||||||
<path d="M23.016 8.016q0 0.797-0.609 1.383t-1.406 0.586h-0.047q-0.328 0-0.469-0.047l-3.563 3.563q0.094 0.281 0.094 0.516 0 0.797-0.609 1.383t-1.406 0.586-1.406-0.586-0.609-1.383q0-0.234 0.094-0.516l-2.578-2.578q-0.281 0.094-0.516 0.094t-0.516-0.094l-4.547 4.547q0.094 0.281 0.094 0.516 0 0.797-0.609 1.406t-1.406 0.609-1.406-0.609-0.609-1.406 0.609-1.383 1.406-0.586q0.375 0 0.516 0.047l4.547-4.547q-0.047-0.141-0.047-0.516 0-0.797 0.586-1.406t1.383-0.609 1.406 0.609 0.609 1.406q0 0.375-0.047 0.516l2.531 2.531q0.141-0.047 0.516-0.047t0.516 0.047l3.563-3.516q-0.094-0.281-0.094-0.516 0-0.797 0.609-1.406t1.406-0.609 1.406 0.609 0.609 1.406z"></path>
|
<path d="M23.016 8.016q0 0.797-0.609 1.383t-1.406 0.586h-0.047q-0.328 0-0.469-0.047l-3.563 3.563q0.094 0.281 0.094 0.516 0 0.797-0.609 1.383t-1.406 0.586-1.406-0.586-0.609-1.383q0-0.234 0.094-0.516l-2.578-2.578q-0.281 0.094-0.516 0.094t-0.516-0.094l-4.547 4.547q0.094 0.281 0.094 0.516 0 0.797-0.609 1.406t-1.406 0.609-1.406-0.609-0.609-1.406 0.609-1.383 1.406-0.586q0.375 0 0.516 0.047l4.547-4.547q-0.047-0.141-0.047-0.516 0-0.797 0.586-1.406t1.383-0.609 1.406 0.609 0.609 1.406q0 0.375-0.047 0.516l2.531 2.531q0.141-0.047 0.516-0.047t0.516 0.047l3.563-3.516q-0.094-0.281-0.094-0.516 0-0.797 0.609-1.406t1.406-0.609 1.406 0.609 0.609 1.406z"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@ -33,6 +33,7 @@ export enum Calculations {
|
|||||||
ConvertSeconds = "convertSeconds",
|
ConvertSeconds = "convertSeconds",
|
||||||
ConvertMilliseconds = "convertMilliseconds",
|
ConvertMilliseconds = "convertMilliseconds",
|
||||||
MsTos = "msTos",
|
MsTos = "msTos",
|
||||||
|
Average = "average",
|
||||||
}
|
}
|
||||||
export enum sizeEnum {
|
export enum sizeEnum {
|
||||||
XS = "XS",
|
XS = "XS",
|
||||||
|
34
src/hooks/useListConfig.ts
Normal file
34
src/hooks/useListConfig.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
import { MetricQueryTypes, Calculations } from "./data";
|
||||||
|
export function useListConfig(config: any, index: string) {
|
||||||
|
const i = Number(index);
|
||||||
|
const calculation =
|
||||||
|
config.metricConfig &&
|
||||||
|
config.metricConfig[i] &&
|
||||||
|
config.metricConfig[i].calculation;
|
||||||
|
const line =
|
||||||
|
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues &&
|
||||||
|
calculation !== Calculations.Average;
|
||||||
|
const isAvg =
|
||||||
|
config.metricTypes[i] === MetricQueryTypes.ReadMetricsValues &&
|
||||||
|
calculation === Calculations.Average;
|
||||||
|
return {
|
||||||
|
isLinear: line,
|
||||||
|
isAvg,
|
||||||
|
};
|
||||||
|
}
|
@ -150,9 +150,7 @@ export function useSourceProcessor(
|
|||||||
const c = (config.metricConfig && config.metricConfig[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] = calculateExp(resp.data[keys[index]].values.values, c);
|
||||||
(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] || [];
|
||||||
@ -166,7 +164,6 @@ export function useSourceProcessor(
|
|||||||
const values = item.values.values.map((d: { value: number }) =>
|
const values = item.values.values.map((d: { value: number }) =>
|
||||||
aggregation(Number(d.value), c)
|
aggregation(Number(d.value), c)
|
||||||
);
|
);
|
||||||
|
|
||||||
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
const indexNum = labelsIdx.findIndex((d: string) => d === item.label);
|
||||||
if (labels[indexNum] && indexNum > -1) {
|
if (labels[indexNum] && indexNum > -1) {
|
||||||
source[labels[indexNum]] = values;
|
source[labels[indexNum]] = values;
|
||||||
@ -287,8 +284,12 @@ export function usePodsSource(
|
|||||||
d[name] = aggregation(resp.data[key], c);
|
d[name] = aggregation(resp.data[key], c);
|
||||||
}
|
}
|
||||||
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
if (config.metricTypes[index] === MetricQueryTypes.ReadMetricsValues) {
|
||||||
d[name] = resp.data[key].values.values.map((d: { value: number }) =>
|
d[name] = {};
|
||||||
aggregation(d.value, c)
|
if (c.calculation === Calculations.Average) {
|
||||||
|
d[name]["avg"] = calculateExp(resp.data[key].values.values, c);
|
||||||
|
}
|
||||||
|
d[name]["values"] = resp.data[key].values.values.map(
|
||||||
|
(val: { value: number }) => aggregation(val.value, c)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -322,25 +323,48 @@ export function useQueryTopologyMetrics(metrics: string[], ids: string[]) {
|
|||||||
|
|
||||||
return { queryStr, conditions };
|
return { queryStr, conditions };
|
||||||
}
|
}
|
||||||
|
function calculateExp(
|
||||||
|
arr: any[],
|
||||||
|
config: { calculation: string }
|
||||||
|
): (number | string)[] {
|
||||||
|
let data: (number | string)[] = [];
|
||||||
|
switch (config.calculation) {
|
||||||
|
case Calculations.Average:
|
||||||
|
data = [
|
||||||
|
(
|
||||||
|
arr.map((d: { value: number }) => d.value).reduce((a, b) => a + b) /
|
||||||
|
arr.length
|
||||||
|
).toFixed(2),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
data = arr.map((d) => aggregation(d.value, config));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
export function aggregation(val: number, config: any): number | string {
|
export function aggregation(
|
||||||
|
val: number,
|
||||||
|
config: { calculation: string }
|
||||||
|
): number | string {
|
||||||
let data: number | string = Number(val);
|
let data: number | string = Number(val);
|
||||||
|
|
||||||
switch (config.calculation) {
|
switch (config.calculation) {
|
||||||
case Calculations.Percentage:
|
case Calculations.Percentage:
|
||||||
data = val / 100;
|
data = (val / 100).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.ByteToKB:
|
case Calculations.ByteToKB:
|
||||||
data = val / 1024;
|
data = (val / 1024).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.ByteToMB:
|
case Calculations.ByteToMB:
|
||||||
data = val / 1024 / 1024;
|
data = (val / 1024 / 1024).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.ByteToGB:
|
case Calculations.ByteToGB:
|
||||||
data = val / 1024 / 1024 / 1024;
|
data = (val / 1024 / 1024 / 1024).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.Apdex:
|
case Calculations.Apdex:
|
||||||
data = val / 10000;
|
data = (val / 10000).toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.ConvertSeconds:
|
case Calculations.ConvertSeconds:
|
||||||
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
data = dayjs(val).format("YYYY-MM-DD HH:mm:ss");
|
||||||
@ -352,7 +376,7 @@ export function aggregation(val: number, config: any): number | string {
|
|||||||
data = data.toFixed(2);
|
data = data.toFixed(2);
|
||||||
break;
|
break;
|
||||||
case Calculations.MsTos:
|
case Calculations.MsTos:
|
||||||
data = val / 1000;
|
data = (val / 1000).toFixed(2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data;
|
data;
|
||||||
|
@ -75,7 +75,7 @@ export const topologyStore = defineStore({
|
|||||||
setTopology(data: { nodes: Node[]; calls: Call[] }) {
|
setTopology(data: { nodes: Node[]; calls: Call[] }) {
|
||||||
const obj = {} as any;
|
const obj = {} as any;
|
||||||
const services = useSelectorStore().services;
|
const services = useSelectorStore().services;
|
||||||
const nodes = data.nodes.reduce((prev: Node[], next: Node) => {
|
const nodes = (data.nodes || []).reduce((prev: Node[], next: Node) => {
|
||||||
if (!obj[next.id]) {
|
if (!obj[next.id]) {
|
||||||
obj[next.id] = true;
|
obj[next.id] = true;
|
||||||
const s = services.filter((d: Service) => d.id === next.id)[0] || {};
|
const s = services.filter((d: Service) => d.id === next.id)[0] || {};
|
||||||
@ -84,7 +84,7 @@ export const topologyStore = defineStore({
|
|||||||
}
|
}
|
||||||
return prev;
|
return prev;
|
||||||
}, []);
|
}, []);
|
||||||
const calls = data.calls.reduce((prev: Call[], next: Call) => {
|
const calls = (data.calls || []).reduce((prev: Call[], next: Call) => {
|
||||||
if (!obj[next.id]) {
|
if (!obj[next.id]) {
|
||||||
obj[next.id] = true;
|
obj[next.id] = true;
|
||||||
next.value = next.value || 1;
|
next.value = next.value || 1;
|
||||||
@ -117,7 +117,7 @@ export const topologyStore = defineStore({
|
|||||||
async getDepthServiceTopology(serviceIds: string[], depth: number) {
|
async getDepthServiceTopology(serviceIds: string[], depth: number) {
|
||||||
const res = await this.getServicesTopology(serviceIds);
|
const res = await this.getServicesTopology(serviceIds);
|
||||||
if (depth > 1) {
|
if (depth > 1) {
|
||||||
const ids = res.nodes
|
const ids = (res.nodes || [])
|
||||||
.map((item: Node) => item.id)
|
.map((item: Node) => item.id)
|
||||||
.filter((d: string) => !serviceIds.includes(d));
|
.filter((d: string) => !serviceIds.includes(d));
|
||||||
if (!ids.length) {
|
if (!ids.length) {
|
||||||
|
@ -73,6 +73,7 @@ export interface LineConfig extends AreaConfig {
|
|||||||
showXAxis?: boolean;
|
showXAxis?: boolean;
|
||||||
showYAxis?: boolean;
|
showYAxis?: boolean;
|
||||||
smallTips?: boolean;
|
smallTips?: boolean;
|
||||||
|
showlabels?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AreaConfig {
|
export interface AreaConfig {
|
||||||
|
@ -466,7 +466,7 @@ function setMetricConfig(index: number) {
|
|||||||
.chart-types {
|
.chart-types {
|
||||||
span {
|
span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 5px 10px;
|
padding: 2px 10px;
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
|
@ -105,6 +105,7 @@ function editConfig() {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tools {
|
.tools {
|
||||||
|
@ -266,11 +266,12 @@ export const CalculationOpts = [
|
|||||||
{ label: "Byte to KB", value: "byteToKB" },
|
{ label: "Byte to KB", value: "byteToKB" },
|
||||||
{ label: "Byte to MB", value: "byteToMB" },
|
{ label: "Byte to MB", value: "byteToMB" },
|
||||||
{ label: "Byte to GB", value: "byteToGB" },
|
{ 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",
|
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: "Precision is 2", value: "precision" },
|
||||||
{ label: "Milliseconds to seconds", value: "msTos" },
|
{ label: "Milliseconds to seconds", value: "msTos" },
|
||||||
];
|
];
|
||||||
|
@ -17,11 +17,13 @@ limitations under the License. -->
|
|||||||
<div
|
<div
|
||||||
v-if="!isNaN(singleVal)"
|
v-if="!isNaN(singleVal)"
|
||||||
class="chart-card"
|
class="chart-card"
|
||||||
:class="{ center: config.textAlign === 'center' }"
|
:style="{
|
||||||
:style="{ fontSize: `${config.fontSize}px`, textAlign: config.textAlign }"
|
fontSize: `${config.fontSize}px`,
|
||||||
|
justifyContent: config.textAlign || 'center',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
{{ singleVal.toFixed(2) }}
|
{{ singleVal.toFixed(2) }}
|
||||||
<span v-show="config.showUnit">
|
<span class="unit" v-show="config.showUnit">
|
||||||
{{ decodeURIComponent(unit) }}
|
{{ decodeURIComponent(unit) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -59,19 +61,19 @@ const unit = computed(
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.chart-card {
|
.chart-card {
|
||||||
color: #333;
|
color: #333;
|
||||||
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
.center {
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: horizontal;
|
|
||||||
-webkit-box-pack: center;
|
|
||||||
-webkit-box-align: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-data {
|
.no-data {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unit {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -42,34 +42,11 @@ limitations under the License. -->
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<ColumnGraph
|
||||||
v-for="(metric, index) in colMetrics"
|
:intervalTime="intervalTime"
|
||||||
:label="`${decodeURIComponent(
|
:colMetrics="colMetrics"
|
||||||
getLabel(metric, index)
|
:config="config"
|
||||||
)} ${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>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -83,12 +60,11 @@ import { EndpointListConfig } from "@/types/dashboard";
|
|||||||
import { Endpoint } from "@/types/selector";
|
import { Endpoint } from "@/types/selector";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
|
import { useQueryPodsMetrics, usePodsSource } from "@/hooks/useProcessor";
|
||||||
import Line from "./Line.vue";
|
|
||||||
import Card from "./Card.vue";
|
|
||||||
import { EntityType } from "../data";
|
import { EntityType } from "../data";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import getDashboard from "@/hooks/useDashboardsSession";
|
import getDashboard from "@/hooks/useDashboardsSession";
|
||||||
import { MetricConfigOpt } from "@/types/dashboard";
|
import { MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -184,26 +160,6 @@ function clickEndpoint(scope: any) {
|
|||||||
async function searchList() {
|
async function searchList() {
|
||||||
await queryEndpoints();
|
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(
|
watch(
|
||||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||||
(data, old) => {
|
(data, old) => {
|
||||||
|
@ -42,35 +42,11 @@ limitations under the License. -->
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<ColumnGraph
|
||||||
v-for="(metric, index) in colMetrics"
|
:intervalTime="intervalTime"
|
||||||
:label="`${decodeURIComponent(
|
:colMetrics="colMetrics"
|
||||||
getLabel(metric, index)
|
:config="config"
|
||||||
)} ${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>
|
|
||||||
<el-table-column label="Attributes">
|
<el-table-column label="Attributes">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-popover placement="left" :width="400" trigger="click">
|
<el-popover placement="left" :width="400" trigger="click">
|
||||||
@ -110,8 +86,6 @@ import { ref, watch, computed } from "vue";
|
|||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import Line from "./Line.vue";
|
|
||||||
import Card from "./Card.vue";
|
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { InstanceListConfig } from "@/types/dashboard";
|
import { InstanceListConfig } from "@/types/dashboard";
|
||||||
@ -121,6 +95,7 @@ import { EntityType } from "../data";
|
|||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import getDashboard from "@/hooks/useDashboardsSession";
|
import getDashboard from "@/hooks/useDashboardsSession";
|
||||||
import { MetricConfigOpt } from "@/types/dashboard";
|
import { MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -236,28 +211,6 @@ function searchList() {
|
|||||||
queryInstanceMetrics(instances.value);
|
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(
|
watch(
|
||||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||||
(data, old) => {
|
(data, old) => {
|
||||||
|
@ -40,6 +40,7 @@ const props = defineProps({
|
|||||||
showXAxis: true,
|
showXAxis: true,
|
||||||
showYAxis: true,
|
showYAxis: true,
|
||||||
smallTips: false,
|
smallTips: false,
|
||||||
|
showlabels: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -185,7 +186,8 @@ function getOption() {
|
|||||||
left: 0,
|
left: 0,
|
||||||
right: 10,
|
right: 10,
|
||||||
bottom: 5,
|
bottom: 5,
|
||||||
containLabel: true,
|
containLabel:
|
||||||
|
props.config.showlabels === undefined ? true : props.config.showlabels,
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: "category",
|
type: "category",
|
||||||
@ -199,6 +201,7 @@ function getOption() {
|
|||||||
axisLabel: { color: "#9da5b2", fontSize: "11" },
|
axisLabel: { color: "#9da5b2", fontSize: "11" },
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
|
show: props.config.showYAxis,
|
||||||
type: "value",
|
type: "value",
|
||||||
axisLine: { show: false },
|
axisLine: { show: false },
|
||||||
axisTick: { show: false },
|
axisTick: { show: false },
|
||||||
|
@ -54,34 +54,11 @@ limitations under the License. -->
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<ColumnGraph
|
||||||
v-for="(metric, index) in colMetrics"
|
:intervalTime="intervalTime"
|
||||||
:label="`${decodeURIComponent(
|
:colMetrics="colMetrics"
|
||||||
getLabel(metric, index)
|
:config="config"
|
||||||
)} ${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>
|
|
||||||
</el-table>
|
</el-table>
|
||||||
</div>
|
</div>
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@ -102,8 +79,6 @@ import { watch, ref, computed } from "vue";
|
|||||||
import { ElMessage } from "element-plus";
|
import { ElMessage } from "element-plus";
|
||||||
import type { PropType } from "vue";
|
import type { PropType } from "vue";
|
||||||
import { ServiceListConfig } from "@/types/dashboard";
|
import { ServiceListConfig } from "@/types/dashboard";
|
||||||
import Line from "./Line.vue";
|
|
||||||
import Card from "./Card.vue";
|
|
||||||
import { useSelectorStore } from "@/store/modules/selectors";
|
import { useSelectorStore } from "@/store/modules/selectors";
|
||||||
import { useDashboardStore } from "@/store/modules/dashboard";
|
import { useDashboardStore } from "@/store/modules/dashboard";
|
||||||
import { Service } from "@/types/selector";
|
import { Service } from "@/types/selector";
|
||||||
@ -112,6 +87,7 @@ import { EntityType } from "../data";
|
|||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
import getDashboard from "@/hooks/useDashboardsSession";
|
import getDashboard from "@/hooks/useDashboardsSession";
|
||||||
import { MetricConfigOpt } from "@/types/dashboard";
|
import { MetricConfigOpt } from "@/types/dashboard";
|
||||||
|
import ColumnGraph from "./components/ColumnGraph.vue";
|
||||||
|
|
||||||
/*global defineProps */
|
/*global defineProps */
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -240,6 +216,7 @@ async function queryServiceMetrics(currentServices: Service[]) {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
services.value = currentServices;
|
services.value = currentServices;
|
||||||
}
|
}
|
||||||
function objectSpanMethod(param: any): any {
|
function objectSpanMethod(param: any): any {
|
||||||
@ -275,26 +252,6 @@ function searchList() {
|
|||||||
);
|
);
|
||||||
setServices(services);
|
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(
|
watch(
|
||||||
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
() => [...(props.config.metricTypes || []), ...(props.config.metrics || [])],
|
||||||
@ -318,10 +275,6 @@ watch(
|
|||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@import "./style.scss";
|
@import "./style.scss";
|
||||||
|
|
||||||
.chart {
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inputs {
|
.inputs {
|
||||||
width: 300px;
|
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.setCurrentService(null);
|
||||||
selectorStore.setCurrentPod(null);
|
selectorStore.setCurrentPod(null);
|
||||||
dashboardStore.setEntity("");
|
dashboardStore.setEntity("");
|
||||||
|
dashboardStore.setConfigPanel(false);
|
||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
dashboardStore,
|
dashboardStore,
|
||||||
|
Loading…
Reference in New Issue
Block a user