Merge pull request #1151 from bluewave-labs/feat/fe/docker-monitors

Feat/fe/docker monitors, resolves #1139
This commit is contained in:
Alexander Holliday authored and GitHub committed 2024-11-13 18:27:20 -08:00
commit f41f79174b
6 files changed
+72 -42

No files matched your search

@@ -40,7 +40,7 @@ export const checkEndpointResolution = createAsyncThunk(
const res = await networkService.checkEndpointResolution({
authToken: authToken,
monitorURL: monitorURL,
})
});
return res.data;
} catch (error) {
if (error.response && error.response.data) {
@@ -53,7 +53,7 @@ export const checkEndpointResolution = createAsyncThunk(
return thunkApi.rejectWithValue(payload);
}
}
)
);
export const getUptimeMonitorById = createAsyncThunk(
"monitors/getMonitorById",
@@ -86,7 +86,7 @@ export const getUptimeMonitorsByTeamId = createAsyncThunk(
const res = await networkService.getMonitorsAndSummaryByTeamId({
authToken: token,
teamId: user.teamId,
types: ["http", "ping"],
types: ["http", "ping", "docker"],
});
return res.data;
} catch (error) {
@@ -1,10 +1,10 @@
import { useState, useEffect } from "react";
import { Box, Button, ButtonGroup, Stack, Typography } from "@mui/material";
import LoadingButton from '@mui/lab/LoadingButton';
import LoadingButton from "@mui/lab/LoadingButton";
import { useSelector, useDispatch } from "react-redux";
import { monitorValidation } from "../../../Validation/validation";
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"
import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { useNavigate, useParams } from "react-router-dom";
import { useTheme } from "@emotion/react";
import { createToast } from "../../../Utils/toastUtils";
@@ -19,21 +19,40 @@ import { getUptimeMonitorById } from "../../../Features/UptimeMonitors/uptimeMon
import "./index.css";
const CreateMonitor = () => {
const MS_PER_MINUTE = 60000;
const { user, authToken } = useSelector((state) => state.auth);
const { monitors, isLoading } = useSelector((state) => state.uptimeMonitors);
const dispatch = useDispatch();
const navigate = useNavigate();
const theme = useTheme();
const MS_PER_MINUTE = 60000;
const { user, authToken } = useSelector((state) => state.auth);
const { monitors, isLoading } = useSelector((state) => state.uptimeMonitors);
const dispatch = useDispatch();
const navigate = useNavigate();
const theme = useTheme();
const idMap = {
"monitor-url": "url",
"monitor-name": "name",
"monitor-checks-http": "type",
"monitor-checks-ping": "type",
"monitor-checks-docker": "type",
"notify-email-default": "notification-email",
};
const monitorTypeMaps = {
http: {
label: "URL to monitor",
placeholder: "google.com",
namePlaceholder: "Google",
},
ping: {
label: "IP address to monitor",
placeholder: "1.1.1.1",
namePlaceholder: "Google",
},
docker: {
label: "Container ID",
placeholder: "abc123",
namePlaceholder: "My Container",
},
};
const { monitorId } = useParams();
const [monitor, setMonitor] = useState({
url: "",
@@ -112,7 +131,6 @@ const CreateMonitor = () => {
{ [name]: value },
{ abortEarly: false }
);
console.log(error);
setErrors((prev) => {
const updatedErrors = { ...prev };
if (error) updatedErrors[name] = error.details[0].message;
@@ -148,16 +166,18 @@ const CreateMonitor = () => {
setErrors(newErrors);
createToast({ body: "Error validation data." });
} else {
if (monitor.type === "http") {
const checkEndpointAction = await dispatch(
checkEndpointResolution({ authToken, monitorURL: form.url })
)
if (checkEndpointAction.meta.requestStatus === "rejected") {
createToast({ body: "The endpoint you entered doesn't resolve. Check the URL again." });
setErrors({ url: "The entered URL is not reachable." });
return;
}
}
if (monitor.type === "http") {
const checkEndpointAction = await dispatch(
checkEndpointResolution({ authToken, monitorURL: form.url })
);
if (checkEndpointAction.meta.requestStatus === "rejected") {
createToast({
body: "The endpoint you entered doesn't resolve. Check the URL again.",
});
setErrors({ url: "The entered URL is not reachable." });
return;
}
}
form = {
...form,
@@ -232,9 +252,9 @@ const CreateMonitor = () => {
<Field
type={monitor.type === "http" ? "url" : "text"}
id="monitor-url"
label="URL to monitor"
label={monitorTypeMaps[monitor.type].label || "URL to monitor"}
https={https}
placeholder="google.com"
placeholder={monitorTypeMaps[monitor.type].placeholder || ""}
value={monitor.url}
onChange={handleChange}
error={errors["url"]}
@@ -244,7 +264,7 @@ const CreateMonitor = () => {
id="monitor-name"
label="Display name"
isOptional={true}
placeholder="Google"
placeholder={monitorTypeMaps[monitor.type].namePlaceholder || ""}
value={monitor.name}
onChange={handleChange}
error={errors["name"]}
@@ -299,6 +319,15 @@ const CreateMonitor = () => {
checked={monitor.type === "ping"}
onChange={(event) => handleChange(event)}
/>
<Radio
id="monitor-checks-docker"
title="Docker container monitoring"
desc="Check whether your container is running or not."
size="small"
value="docker"
checked={monitor.type === "docker"}
onChange={(event) => handleChange(event)}
/>
{errors["type"] ? (
<Box className="error-container">
<Typography
@@ -386,19 +415,19 @@ const CreateMonitor = () => {
direction="row"
justifyContent="flex-end"
>
<LoadingButton
variant="contained"
color="primary"
onClick={handleCreateMonitor}
disabled={Object.keys(errors).length !== 0 && true}
loading={isLoading}
>
Create monitor
</LoadingButton>
<LoadingButton
variant="contained"
color="primary"
onClick={handleCreateMonitor}
disabled={Object.keys(errors).length !== 0 && true}
loading={isLoading}
>
Create monitor
</LoadingButton>
</Stack>
</Stack>
</Box>
);
};
export default CreateMonitor;
export default CreateMonitor;
@@ -150,7 +150,7 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => {
authToken,
teamId: user.teamId,
limit: 25,
types: ["http", "ping"],
types: ["http", "ping", "docker"],
status: null,
checkOrder: "desc",
normalize: true,
+2 -1
View File
@@ -20,6 +20,7 @@ const SERVICE_NAME = "monitorModule";
const CHECK_MODEL_LOOKUP = {
http: Check,
ping: Check,
docker: Check,
pagespeed: PageSpeedCheck,
hardware: HardwareCheck,
};
@@ -349,7 +350,7 @@ const getMonitorStatsById = async (req) => {
),
};
if (monitor.type === "http" || monitor.type === "ping") {
if (monitor.type === "http" || monitor.type === "ping" || monitor.type === "docker") {
// HTTP/PING Specific stats
monitorStats.periodAvgResponseTime = getAverageResponseTime(checksForDateRange);
monitorStats.periodUptime = getUptimePercentage(checksForDateRange);
+1 -1
View File
@@ -229,7 +229,7 @@ class NetworkService {
});
const containers = await docker.listContainers({ all: true });
const containerExists = containers.some((c) => c.Id === job.data.url);
const containerExists = containers.some((c) => c.Id.startsWith(job.data.url));
if (!containerExists) {
throw new Error(errorMessages.DOCKER_NOT_FOUND);
}
+4 -4
View File
@@ -144,8 +144,8 @@ const getMonitorsAndSummaryByTeamIdQueryValidation = joi.object({
type: joi
.alternatives()
.try(
joi.string().valid("http", "ping", "pagespeed"),
joi.array().items(joi.string().valid("http", "ping", "pagespeed"))
joi.string().valid("http", "ping", "pagespeed", "docker"),
joi.array().items(joi.string().valid("http", "ping", "pagespeed", "docker"))
),
});
@@ -161,8 +161,8 @@ const getMonitorsByTeamIdQueryValidation = joi.object({
type: joi
.alternatives()
.try(
joi.string().valid("http", "ping", "pagespeed"),
joi.array().items(joi.string().valid("http", "ping", "pagespeed"))
joi.string().valid("http", "ping", "pagespeed", "docker"),
joi.array().items(joi.string().valid("http", "ping", "pagespeed", "docker"))
),
page: joi.number(),
rowsPerPage: joi.number(),