Skip to content

Commit

Permalink
Merge pull request #1151 from bluewave-labs/feat/fe/docker-monitors
Browse files Browse the repository at this point in the history
Feat/fe/docker monitors, resolves #1139
  • Loading branch information
ajhollid authored Nov 14, 2024
2 parents 3f81d8f + 9db3e0e commit f41f791
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 42 deletions.
6 changes: 3 additions & 3 deletions Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -53,7 +53,7 @@ export const checkEndpointResolution = createAsyncThunk(
return thunkApi.rejectWithValue(payload);
}
}
)
);

export const getUptimeMonitorById = createAsyncThunk(
"monitors/getMonitorById",
Expand Down Expand Up @@ -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) {
Expand Down
93 changes: 61 additions & 32 deletions Client/src/Pages/Monitors/CreateMonitor/index.jsx
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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: "",
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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"]}
Expand All @@ -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"]}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
2 changes: 1 addition & 1 deletion Client/src/Pages/Monitors/Home/MonitorTable/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion Server/db/mongo/modules/monitorModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SERVICE_NAME = "monitorModule";
const CHECK_MODEL_LOOKUP = {
http: Check,
ping: Check,
docker: Check,
pagespeed: PageSpeedCheck,
hardware: HardwareCheck,
};
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Server/service/networkService.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
8 changes: 4 additions & 4 deletions Server/validation/joi.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
),
});

Expand All @@ -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(),
Expand Down

0 comments on commit f41f791

Please sign in to comment.