Fixed dashboards capacity Widgets (#2055)

- Added new calculation for prometheus capacity
- Added indicator colors to capacity widgets
- Adjusted capacity in drives for common dashboard

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2022-05-31 10:03:58 -05:00
committed by GitHub
parent 68e98be376
commit b02e649405
6 changed files with 208 additions and 60 deletions

View File

@@ -456,3 +456,8 @@ export interface IRetentionConfig {
unit: string;
validity: number;
}
export interface IBytesCalc {
total: number;
unit: string;
}

View File

@@ -16,6 +16,7 @@
import storage from "local-storage-fallback";
import {
IBytesCalc,
ICapacity,
IErasureCodeCalc,
IStorageDistribution,
@@ -576,7 +577,7 @@ export const calculateBytes = (
showDecimals = false,
roundFloor = true,
k8sUnit = false
) => {
): IBytesCalc => {
let bytes;
if (typeof x === "string") {
@@ -696,3 +697,15 @@ export const getCookieValue = (cookieName: string) => {
?.pop() || ""
);
};
export const capacityColors = (usedSpace: number, maxSpace: number) => {
const percCalculate = (usedSpace * 100) / maxSpace;
if (percCalculate >= 90) {
return "#C83B51";
} else if (percCalculate >= 70) {
return "#FFAB0F";
}
return "#07193E";
};

View File

@@ -19,7 +19,11 @@ import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import { IDriveInfo } from "../types";
import { niceBytes, niceBytesInt } from "../../../../common/utils";
import {
capacityColors,
niceBytes,
niceBytesInt,
} from "../../../../common/utils";
import { Box } from "@mui/material";
import { Cell, Pie, PieChart } from "recharts";
import { CircleIcon } from "../../../../icons";
@@ -48,11 +52,13 @@ const driveStatusColor = (health_status: string) => {
};
const DriveInfoItem = ({ drive }: ICardProps) => {
const freeSpace = drive.totalSpace - drive.usedSpace;
const plotValues = [
{ value: drive.totalSpace, color: "#D6D6D6", label: "Free Space" },
{ value: freeSpace, color: "#D6D6D6", label: "Free Space" },
{
value: drive.usedSpace,
color: "#073052",
color: capacityColors(drive.usedSpace, drive.totalSpace),
label: "Used Space",
},
];

View File

@@ -22,7 +22,11 @@ import { widgetDetailsToPanel } from "../utils";
import { ErrorResponseHandler } from "../../../../../common/types";
import { useDispatch } from "react-redux";
import { niceBytes } from "../../../../../common/utils";
import {
calculateBytes,
capacityColors,
niceBytesInt,
} from "../../../../../common/utils";
import { Cell, Pie, PieChart } from "recharts";
import { ReportedUsageIcon } from "../../../../../icons";
import Loader from "../../../Common/Loader/Loader";
@@ -43,8 +47,10 @@ const CapacityItem = ({
}) => {
const dispatch = useDispatch();
const [loading, setLoading] = useState<boolean>(true);
const [dataInner, setDataInner] = useState<Record<string, any>>([]);
const [result, setResult] = useState<IDashboardPanel | null>(null);
const [totalUsableFree, setTotalUsableFree] = useState<number>(0);
const [totalUsed, setTotalUsed] = useState<number>(0);
const [totalUsable, setTotalUsable] = useState<number>(0);
useEffect(() => {
if (propLoading) {
@@ -73,8 +79,30 @@ const CapacityItem = ({
)
.then((res: any) => {
const widgetsWithValue = widgetDetailsToPanel(res, value);
setDataInner(widgetsWithValue.data);
setResult(widgetsWithValue);
let tUsable = 0;
let tUsed = 0;
let tFree = 0;
widgetsWithValue.data.forEach((eachArray: any[]) => {
eachArray.forEach((itemSum) => {
switch (itemSum.legend) {
case "Total Usable":
tUsable += itemSum.value;
break;
case "Used Space":
tUsed += itemSum.value;
break;
case "Usable Free":
tFree += itemSum.value;
break;
}
});
});
setTotalUsableFree(tFree);
setTotalUsed(tUsed);
setTotalUsable(tUsable);
setLoading(false);
})
@@ -85,21 +113,18 @@ const CapacityItem = ({
}
}, [loading, value, timeEnd, timeStart, dispatch, apiPrefix]);
const [middleLabel, unitValue] = (result?.innerLabel || "").split(" ");
const usableValueObj = dataInner[0];
const { value: usableValue = 0 } = usableValueObj || { value: 0 };
const usedConvert = calculateBytes(totalUsed, true, false);
const plotValues = [
{
value: parseInt(usableValue),
value: totalUsableFree,
color: "#D6D6D6",
label: "Usable Space",
label: "Usable Available Space",
},
{
value: parseInt(usableValue),
color: "#073052",
label: "Usable Space",
value: totalUsed,
color: capacityColors(totalUsed, totalUsable),
label: "Used Space",
},
];
return (
@@ -150,7 +175,7 @@ const CapacityItem = ({
fontSize: 12,
}}
>
{niceBytes(usableValue)}
{niceBytesInt(totalUsableFree)}
<br />
<Box
sx={{
@@ -193,25 +218,51 @@ const CapacityItem = ({
},
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
"& .value": {
fontSize: "50px",
fontFamily: "Lato",
fontWeight: 600,
},
"& .unit": {
<Box>
<Box
sx={{
color: "#5E5E5E",
fontSize: "18px",
marginLeft: "12px",
marginTop: "10px",
},
}}
>
<div className="value">{middleLabel}</div>{" "}
<div className="unit">{unitValue}</div>
fontWeight: "bold",
fontSize: "14px",
}}
>
Used:
</Box>
<Box
sx={{
display: "flex",
"& .value": {
fontSize: "50px",
fontFamily: "Lato",
fontWeight: 600,
alignSelf: "flex-end",
lineHeight: 1,
},
"& .unit": {
color: "#5E5E5E",
fontWeight: "bold",
fontSize: "14px",
marginLeft: "12px",
alignSelf: "flex-end",
},
}}
>
<div className="value">{usedConvert.total}</div>
<div className="unit">{usedConvert.unit}</div>
</Box>
<Box
sx={{
marginTop: "5px",
"& .value": {
color: "#5E5E5E",
fontWeight: "bold",
fontSize: "14px",
textAlign: "right",
},
}}
>
<div className="value">Of: {niceBytesInt(totalUsable)}</div>
</Box>
</Box>
<Box

View File

@@ -83,6 +83,31 @@ export const panelsConfiguration: IDashboardPanel[] = [
innerLabel: "N/A",
labelDisplayFunction: niceBytes,
},
{
id: 51,
title: "Usable Capacity",
data: [],
dataOuter: [{ name: "outer", value: 100 }],
widgetConfiguration: {
outerChart: {
colorList: ["#9c9c9c"],
innerRadius: 0,
outerRadius: 0,
startAngle: 0,
endAngle: 0,
},
innerChart: {
colorList: colorsMain,
innerRadius: 20,
outerRadius: 50,
startAngle: 90,
endAngle: -200,
},
},
type: widgetType.pieChart,
innerLabel: "N/A",
labelDisplayFunction: niceBytes,
},
{
id: 68,
title: "Data Usage Growth",
@@ -560,35 +585,49 @@ export const widgetDetailsToPanel = (
break;
case widgetType.pieChart:
if (typeOfPayload === "gauge") {
let chartSeries = get(payloadData, "targets[0].result", []);
if (chartSeries === null) {
chartSeries = [];
}
const metricCalc = get(
payloadData,
"options.reduceOptions.calcs[0]",
"lastNotNull"
);
const valuesArray = chartSeries.length > 0 ? chartSeries[0].values : [];
let chartSeries = get(payloadData, "targets", []).filter(
(seriesItem: any) => seriesItem !== null
);
const totalValues = calculateMainValue(valuesArray, metricCalc);
const values = chartSeries.map((chartTarget: any) => {
const resultMap =
chartTarget.result && Array.isArray(chartTarget.result)
? chartTarget.result
: [];
const values = chartSeries.map((elementValue: any) => {
const values = get(elementValue, "values", []);
const metricKeyItem = Object.keys(elementValue.metric);
const sortResult = values.sort(
(value1: any[], value2: any[]) =>
parseInt(value1[0][1]) - parseInt(value2[0][1])
);
const values = resultMap.map((elementValue: any) => {
const values = get(elementValue, "values", []);
const metricKeyItem = Object.keys(elementValue.metric);
const sortResult = values.sort(
(value1: any[], value2: any[]) =>
parseInt(value1[0][1]) - parseInt(value2[0][1])
);
const metricName = elementValue.metric[metricKeyItem[0]];
const value = sortResult[sortResult.length - 1];
return { name: metricName, value: parseInt(value[1]) };
const metricName = elementValue.metric[metricKeyItem[0]];
const value = sortResult[sortResult.length - 1];
return {
name: metricName,
value: parseInt(value[1]),
legend: chartTarget.legendFormat,
};
});
return values;
});
const firstTarget =
chartSeries[0].result && chartSeries[0].result.length > 0
? chartSeries[0].result[0].values
: [];
const totalValues = calculateMainValue(firstTarget, metricCalc);
const innerLabel = panelItem.labelDisplayFunction
? panelItem.labelDisplayFunction(totalValues[1])
: totalValues[1];

View File

@@ -27,14 +27,12 @@ import (
"strings"
"time"
"github.com/minio/madmin-go"
"github.com/go-openapi/swag"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/swag"
"github.com/minio/console/models"
"github.com/minio/console/restapi/operations"
systemApi "github.com/minio/console/restapi/operations/system"
"github.com/minio/madmin-go"
)
func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
@@ -222,7 +220,7 @@ var widgets = []Metric{
},
{
ID: 50,
Title: "Current Usable Capacity",
Title: "Current Usable Free Capacity",
Type: "gauge",
MaxDataPoints: 100,
GridPos: GridPos{
@@ -239,8 +237,44 @@ var widgets = []Metric{
},
},
Targets: []Target{
{
Expr: `topk(1, sum(minio_cluster_capacity_usable_total_bytes{$__query}) by (instance))`,
LegendFormat: "Total Usable",
Step: 300,
},
{
Expr: `topk(1, sum(minio_cluster_capacity_usable_free_bytes{$__query}) by (instance))`,
LegendFormat: "Usable Free",
Step: 300,
},
{
Expr: `topk(1, sum(minio_cluster_capacity_usable_total_bytes{$__query}) by (instance)) - topk(1, sum(minio_cluster_capacity_usable_free_bytes{$__query}) by (instance))`,
LegendFormat: "Used Space",
Step: 300,
},
},
},
{
ID: 51,
Title: "Current Usable Total Bytes",
Type: "gauge",
MaxDataPoints: 100,
GridPos: GridPos{
H: 6,
W: 3,
X: 6,
Y: 0,
},
Options: MetricOptions{
ReduceOptions: ReduceOptions{
Calcs: []string{
"lastNotNull",
},
},
},
Targets: []Target{
{
Expr: `topk(1, sum(minio_cluster_capacity_usable_total_bytes{$__query}) by (instance))`,
LegendFormat: "",
Step: 300,
},