Added fallback to default dashboard in case Prometheus is not accesible (#1302)
This commit is contained in:
@@ -42,6 +42,9 @@ type AdminInfoResponse struct {
|
||||
// objects
|
||||
Objects int64 `json:"objects,omitempty"`
|
||||
|
||||
// prometheus not ready
|
||||
PrometheusNotReady bool `json:"prometheusNotReady,omitempty"`
|
||||
|
||||
// servers
|
||||
Servers []*ServerProperties `json:"servers"`
|
||||
|
||||
|
||||
@@ -472,7 +472,12 @@ export const getTimeFromTimestamp = (
|
||||
timestamp: string,
|
||||
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) {
|
||||
return `${dateObject.getFullYear()}-${String(
|
||||
|
||||
@@ -133,6 +133,31 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<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 item xs={12} className={classes.generalStatusTitle}>
|
||||
General Status
|
||||
@@ -241,45 +266,47 @@ const BasicDashboard = ({ classes, usage }: IDashboardProps) => {
|
||||
</TabPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
justifyContent={"center"}
|
||||
alignContent={"center"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Grid item xs={8}>
|
||||
<HelpBox
|
||||
iconComponent={<PrometheusIcon />}
|
||||
title={"Monitoring"}
|
||||
help={
|
||||
<Fragment>
|
||||
The MinIO Dashboard is displaying basic metrics only due to
|
||||
missing the{" "}
|
||||
<a
|
||||
href="https://docs.min.io/minio/baremetal/console/minio-console.html?ref=con#configuration"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
necessary settings
|
||||
</a>{" "}
|
||||
for displaying extended metrics.
|
||||
<br />
|
||||
<br />
|
||||
See{" "}
|
||||
<a
|
||||
href="https://docs.min.io/minio/baremetal/monitoring/metrics-alerts/collect-minio-metrics-using-prometheus.html?ref=con#minio-metrics-collect-using-prometheus"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Collect MinIO Metrics Using Prometheus
|
||||
</a>{" "}
|
||||
for a complete tutorial on scraping and visualizing MinIO
|
||||
metrics with Prometheus.
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
{!usage?.prometheusNotReady && (
|
||||
<Grid
|
||||
container
|
||||
justifyContent={"center"}
|
||||
alignContent={"center"}
|
||||
alignItems={"center"}
|
||||
>
|
||||
<Grid item xs={8}>
|
||||
<HelpBox
|
||||
iconComponent={<PrometheusIcon />}
|
||||
title={"Monitoring"}
|
||||
help={
|
||||
<Fragment>
|
||||
The MinIO Dashboard is displaying basic metrics only due to
|
||||
missing the{" "}
|
||||
<a
|
||||
href="https://docs.min.io/minio/baremetal/console/minio-console.html?ref=con#configuration"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
necessary settings
|
||||
</a>{" "}
|
||||
for displaying extended metrics.
|
||||
<br />
|
||||
<br />
|
||||
See{" "}
|
||||
<a
|
||||
href="https://docs.min.io/minio/baremetal/monitoring/metrics-alerts/collect-minio-metrics-using-prometheus.html?ref=con#minio-metrics-collect-using-prometheus"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Collect MinIO Metrics Using Prometheus
|
||||
</a>{" "}
|
||||
for a complete tutorial on scraping and visualizing MinIO
|
||||
metrics with Prometheus.
|
||||
</Fragment>
|
||||
}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -154,7 +154,12 @@ const LinearGraphWidget = ({
|
||||
if (key === "name") {
|
||||
continue;
|
||||
}
|
||||
const val = parseInt(dp[key]);
|
||||
let val = parseInt(dp[key]);
|
||||
|
||||
if (isNaN(val)) {
|
||||
val = 0;
|
||||
}
|
||||
|
||||
if (maxVal < val) {
|
||||
maxVal = val;
|
||||
}
|
||||
|
||||
@@ -111,6 +111,18 @@ const SingleRepWidget = ({
|
||||
}, [loading, panelItem, timeEnd, timeStart, displayErrorMessage, apiPrefix]);
|
||||
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 (
|
||||
<div className={classes.singleValueContainer}>
|
||||
<div className={classes.titleContainer}>{title}</div>
|
||||
@@ -150,7 +162,7 @@ const SingleRepWidget = ({
|
||||
fill={"#07193E"}
|
||||
>
|
||||
{result
|
||||
? representationNumber(parseInt(result.innerLabel || "0"))
|
||||
? repNumber
|
||||
: ""}
|
||||
</text>
|
||||
</AreaChart>
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface Usage {
|
||||
usage: number;
|
||||
buckets: number;
|
||||
objects: number;
|
||||
prometheusNotReady?: boolean;
|
||||
widgets?: any;
|
||||
servers: ServerInfo[];
|
||||
}
|
||||
|
||||
@@ -89,22 +89,27 @@ const EditConfiguration = ({
|
||||
useState<boolean>(false);
|
||||
//Effects
|
||||
useEffect(() => {
|
||||
const configId = get(selectedConfiguration, "configuration_id", false);
|
||||
if (loadingConfig) {
|
||||
const configId = get(selectedConfiguration, "configuration_id", false);
|
||||
|
||||
if (configId) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/configs/${configId}`)
|
||||
.then((res) => {
|
||||
const keyVals = get(res, "key_values", []);
|
||||
setConfigValues(keyVals);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setLoadingConfig(false);
|
||||
setErrorSnackMessage(err);
|
||||
});
|
||||
if (configId) {
|
||||
api
|
||||
.invoke("GET", `/api/v1/configs/${configId}`)
|
||||
.then((res) => {
|
||||
const keyVals = get(res, "key_values", []);
|
||||
setConfigValues(keyVals);
|
||||
setLoadingConfig(false);
|
||||
})
|
||||
.catch((err: ErrorResponseHandler) => {
|
||||
setLoadingConfig(false);
|
||||
setErrorSnackMessage(err);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
setLoadingConfig(false);
|
||||
}
|
||||
setLoadingConfig(false);
|
||||
}, [selectedConfiguration, setErrorSnackMessage]);
|
||||
}, [loadingConfig, selectedConfiguration, setErrorSnackMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
if (saving) {
|
||||
@@ -153,6 +158,9 @@ const EditConfiguration = ({
|
||||
const continueReset = (restart: boolean) => {
|
||||
setResetConfigurationOpen(false);
|
||||
serverNeedsRestart(restart);
|
||||
if (restart) {
|
||||
setLoadingConfig(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -58,11 +58,12 @@ func registerAdminInfoHandlers(api *operations.ConsoleAPI) {
|
||||
}
|
||||
|
||||
type UsageInfo struct {
|
||||
Buckets int64
|
||||
Objects int64
|
||||
Usage int64
|
||||
DisksUsage int64
|
||||
Servers []*models.ServerProperties
|
||||
Buckets int64
|
||||
Objects int64
|
||||
Usage int64
|
||||
DisksUsage int64
|
||||
Servers []*models.ServerProperties
|
||||
EndpointNotReady bool
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if prometheusURL == "" {
|
||||
prometheusNotReady := false
|
||||
|
||||
if prometheusURL != "" && !testPrometheusURL(prometheusURL) {
|
||||
prometheusNotReady = true
|
||||
}
|
||||
if prometheusURL == "" || prometheusNotReady {
|
||||
// create a minioClient interface implementation
|
||||
// defining the client to be used
|
||||
adminClient := AdminClient{Client: mAdmin}
|
||||
@@ -858,10 +864,11 @@ func getUsageWidgetsForDeployment(prometheusURL string, mAdmin *madmin.AdminClie
|
||||
return nil, prepareError(err)
|
||||
}
|
||||
sessionResp := &models.AdminInfoResponse{
|
||||
Buckets: usage.Buckets,
|
||||
Objects: usage.Objects,
|
||||
Usage: usage.Usage,
|
||||
Servers: usage.Servers,
|
||||
Buckets: usage.Buckets,
|
||||
Objects: usage.Objects,
|
||||
Usage: usage.Usage,
|
||||
Servers: usage.Servers,
|
||||
PrometheusNotReady: prometheusNotReady,
|
||||
}
|
||||
return sessionResp, nil
|
||||
}
|
||||
|
||||
@@ -3655,6 +3655,9 @@ func init() {
|
||||
"objects": {
|
||||
"type": "integer"
|
||||
},
|
||||
"prometheusNotReady": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"servers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
@@ -9503,6 +9506,9 @@ func init() {
|
||||
"objects": {
|
||||
"type": "integer"
|
||||
},
|
||||
"prometheusNotReady": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"servers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
||||
@@ -3228,6 +3228,8 @@ definitions:
|
||||
type: integer
|
||||
usage:
|
||||
type: integer
|
||||
prometheusNotReady:
|
||||
type: boolean
|
||||
widgets:
|
||||
type: array
|
||||
items:
|
||||
|
||||
Reference in New Issue
Block a user