Added fallback to default dashboard in case Prometheus is not accesible (#1302)

This commit is contained in:
Alex
2021-12-07 15:39:50 -06:00
committed by GitHub
parent 1e59f131e8
commit bf126d3a84
10 changed files with 141 additions and 65 deletions

View File

@@ -42,6 +42,9 @@ type AdminInfoResponse struct {
// objects // objects
Objects int64 `json:"objects,omitempty"` Objects int64 `json:"objects,omitempty"`
// prometheus not ready
PrometheusNotReady bool `json:"prometheusNotReady,omitempty"`
// servers // servers
Servers []*ServerProperties `json:"servers"` Servers []*ServerProperties `json:"servers"`

View File

@@ -472,7 +472,12 @@ export const getTimeFromTimestamp = (
timestamp: string, timestamp: string,
fullDate: boolean = false fullDate: boolean = false
) => { ) => {
const dateObject = new Date(parseInt(timestamp) * 1000); const timestampToInt = parseInt(timestamp);
if (isNaN(timestampToInt)) {
return "";
}
const dateObject = new Date(timestampToInt * 1000);
if (fullDate) { if (fullDate) {
return `${dateObject.getFullYear()}-${String( return `${dateObject.getFullYear()}-${String(

View File

@@ -133,6 +133,31 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
return ( return (
<Fragment> <Fragment>
<div className={classes.dashboardBG} /> <div className={classes.dashboardBG} />
{usage?.prometheusNotReady && (
<Grid
container
justifyContent={"center"}
alignContent={"center"}
alignItems={"center"}
>
<Grid item xs={8}>
<HelpBox
iconComponent={<PrometheusIcon />}
title={"We can't retrieve advanced metrics at this time"}
help={
<Fragment>
MinIO Dashboard will display basic metrics as we couldn't
connect to Prometheus successfully.
<br /> <br />
Please try again in a few minutes. If the problem persists,
you can review your configuration and confirm that Prometheus
server is up and running.
</Fragment>
}
/>
</Grid>
</Grid>
)}
<Grid container spacing={2}> <Grid container spacing={2}>
<Grid item xs={12} className={classes.generalStatusTitle}> <Grid item xs={12} className={classes.generalStatusTitle}>
General Status General Status
@@ -241,45 +266,47 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
</TabPanel> </TabPanel>
</Grid> </Grid>
</Grid> </Grid>
<Grid {!usage?.prometheusNotReady && (
container <Grid
justifyContent={"center"} container
alignContent={"center"} justifyContent={"center"}
alignItems={"center"} alignContent={"center"}
> alignItems={"center"}
<Grid item xs={8}> >
<HelpBox <Grid item xs={8}>
iconComponent={<PrometheusIcon />} <HelpBox
title={"Monitoring"} iconComponent={<PrometheusIcon />}
help={ title={"Monitoring"}
<Fragment> help={
The MinIO Dashboard is displaying basic metrics only due to <Fragment>
missing the{" "} The MinIO Dashboard is displaying basic metrics only due to
<a missing the{" "}
href="https://docs.min.io/minio/baremetal/console/minio-console.html?ref=con#configuration" <a
target="_blank" href="https://docs.min.io/minio/baremetal/console/minio-console.html?ref=con#configuration"
rel="noreferrer" target="_blank"
> rel="noreferrer"
necessary settings >
</a>{" "} necessary settings
for displaying extended metrics. </a>{" "}
<br /> for displaying extended metrics.
<br /> <br />
See{" "} <br />
<a See{" "}
href="https://docs.min.io/minio/baremetal/monitoring/metrics-alerts/collect-minio-metrics-using-prometheus.html?ref=con#minio-metrics-collect-using-prometheus" <a
target="_blank" href="https://docs.min.io/minio/baremetal/monitoring/metrics-alerts/collect-minio-metrics-using-prometheus.html?ref=con#minio-metrics-collect-using-prometheus"
rel="noreferrer" target="_blank"
> rel="noreferrer"
Collect MinIO Metrics Using Prometheus >
</a>{" "} Collect MinIO Metrics Using Prometheus
for a complete tutorial on scraping and visualizing MinIO </a>{" "}
metrics with Prometheus. for a complete tutorial on scraping and visualizing MinIO
</Fragment> metrics with Prometheus.
} </Fragment>
/> }
/>
</Grid>
</Grid> </Grid>
</Grid> )}
</Fragment> </Fragment>
); );
}; };

View File

@@ -154,7 +154,12 @@ const LinearGraphWidget = ({
if (key === "name") { if (key === "name") {
continue; continue;
} }
const val = parseInt(dp[key]); let val = parseInt(dp[key]);
if (isNaN(val)) {
val = 0;
}
if (maxVal < val) { if (maxVal < val) {
maxVal = val; maxVal = val;
} }

View File

@@ -111,6 +111,18 @@ const SingleRepWidget = ({
}, [loading, panelItem, timeEnd, timeStart, displayErrorMessage, apiPrefix]); }, [loading, panelItem, timeEnd, timeStart, displayErrorMessage, apiPrefix]);
const gradientID = `colorGradient-${title.split(" ").join("-")}`; const gradientID = `colorGradient-${title.split(" ").join("-")}`;
let repNumber = "";
if (result) {
const resultRep = parseInt(result.innerLabel || "0");
if (!isNaN(resultRep)) {
repNumber = representationNumber(resultRep);
} else {
repNumber = "0";
}
}
return ( return (
<div className={classes.singleValueContainer}> <div className={classes.singleValueContainer}>
<div className={classes.titleContainer}>{title}</div> <div className={classes.titleContainer}>{title}</div>
@@ -150,7 +162,7 @@ const SingleRepWidget = ({
fill={"#07193E"} fill={"#07193E"}
> >
{result {result
? representationNumber(parseInt(result.innerLabel || "0")) ? repNumber
: ""} : ""}
</text> </text>
</AreaChart> </AreaChart>

View File

@@ -20,6 +20,7 @@ export interface Usage {
usage: number; usage: number;
buckets: number; buckets: number;
objects: number; objects: number;
prometheusNotReady?: boolean;
widgets?: any; widgets?: any;
servers: ServerInfo[]; servers: ServerInfo[];
} }

View File

@@ -89,22 +89,27 @@ const EditConfiguration = ({
useState<boolean>(false); useState<boolean>(false);
//Effects //Effects
useEffect(() => { useEffect(() => {
const configId = get(selectedConfiguration, "configuration_id", false); if (loadingConfig) {
const configId = get(selectedConfiguration, "configuration_id", false);
if (configId) { if (configId) {
api api
.invoke("GET", `/api/v1/configs/${configId}`) .invoke("GET", `/api/v1/configs/${configId}`)
.then((res) => { .then((res) => {
const keyVals = get(res, "key_values", []); const keyVals = get(res, "key_values", []);
setConfigValues(keyVals); setConfigValues(keyVals);
}) setLoadingConfig(false);
.catch((err: ErrorResponseHandler) => { })
setLoadingConfig(false); .catch((err: ErrorResponseHandler) => {
setErrorSnackMessage(err); setLoadingConfig(false);
}); setErrorSnackMessage(err);
});
return;
}
setLoadingConfig(false);
} }
setLoadingConfig(false); }, [loadingConfig, selectedConfiguration, setErrorSnackMessage]);
}, [selectedConfiguration, setErrorSnackMessage]);
useEffect(() => { useEffect(() => {
if (saving) { if (saving) {
@@ -153,6 +158,9 @@ const EditConfiguration = ({
const continueReset = (restart: boolean) => { const continueReset = (restart: boolean) => {
setResetConfigurationOpen(false); setResetConfigurationOpen(false);
serverNeedsRestart(restart); serverNeedsRestart(restart);
if (restart) {
setLoadingConfig(true);
}
}; };
return ( return (

View File

@@ -58,11 +58,12 @@ func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
} }
type UsageInfo struct { type UsageInfo struct {
Buckets int64 Buckets int64
Objects int64 Objects int64
Usage int64 Usage int64
DisksUsage int64 DisksUsage int64
Servers []*models.ServerProperties Servers []*models.ServerProperties
EndpointNotReady bool
} }
// GetAdminInfo invokes admin info and returns a parsed `UsageInfo` structure // GetAdminInfo invokes admin info and returns a parsed `UsageInfo` structure
@@ -845,7 +846,12 @@ func getAdminInfoResponse(session *models.Principal, params admin_api.AdminInfoP
} }
func getUsageWidgetsForDeployment(prometheusURL string, mAdmin *madmin.AdminClient) (*models.AdminInfoResponse, *models.Error) { func getUsageWidgetsForDeployment(prometheusURL string, mAdmin *madmin.AdminClient) (*models.AdminInfoResponse, *models.Error) {
if prometheusURL == "" { prometheusNotReady := false
if prometheusURL != "" && !testPrometheusURL(prometheusURL) {
prometheusNotReady = true
}
if prometheusURL == "" || prometheusNotReady {
// create a minioClient interface implementation // create a minioClient interface implementation
// defining the client to be used // defining the client to be used
adminClient := AdminClient{Client: mAdmin} adminClient := AdminClient{Client: mAdmin}
@@ -858,10 +864,11 @@ func getUsageWidgetsForDeployment(prometheusURL string, mAdmin *madmin.AdminClie
return nil, prepareError(err) return nil, prepareError(err)
} }
sessionResp := &models.AdminInfoResponse{ sessionResp := &models.AdminInfoResponse{
Buckets: usage.Buckets, Buckets: usage.Buckets,
Objects: usage.Objects, Objects: usage.Objects,
Usage: usage.Usage, Usage: usage.Usage,
Servers: usage.Servers, Servers: usage.Servers,
PrometheusNotReady: prometheusNotReady,
} }
return sessionResp, nil return sessionResp, nil
} }

View File

@@ -3655,6 +3655,9 @@ func init() {
"objects": { "objects": {
"type": "integer" "type": "integer"
}, },
"prometheusNotReady": {
"type": "boolean"
},
"servers": { "servers": {
"type": "array", "type": "array",
"items": { "items": {
@@ -9503,6 +9506,9 @@ func init() {
"objects": { "objects": {
"type": "integer" "type": "integer"
}, },
"prometheusNotReady": {
"type": "boolean"
},
"servers": { "servers": {
"type": "array", "type": "array",
"items": { "items": {

View File

@@ -3228,6 +3228,8 @@ definitions:
type: integer type: integer
usage: usage:
type: integer type: integer
prometheusNotReady:
type: boolean
widgets: widgets:
type: array type: array
items: items: