Feat/monitor endpoint refactor (#463)
* Moved all methods to modules * removed old mongoDB file * Refactored endpoints to take query params, removed duplicate methods, updated routes, updated Client queries * Added comment * Add model differentiation * Add sort order, fix minor bug, add validation for query params
This commit is contained in:
1 parent
e47d3685ce
commit
477cad7cc9
11 files changed
+132
-166
No files matched your search
@@ -51,7 +51,7 @@ export const getMonitorsByUserId = createAsyncThunk(
|
||||
const user = jwtDecode(token);
|
||||
try {
|
||||
const res = await axiosInstance.get(
|
||||
`/monitors/user/${user._id}?limit=25`,
|
||||
`/monitors/user/${user._id}?limit=25&type=http&type=ping&sortOrder=desc`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
|
||||
@@ -33,7 +33,7 @@ const Incidents = () => {
|
||||
useEffect(() => {
|
||||
const fetchIncidents = async () => {
|
||||
const res = await axiosInstance.get(
|
||||
`/monitors/incidents/user/${authState.user._id}`,
|
||||
`/monitors/user/${authState.user._id}?status=false`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${authState.authToken}`,
|
||||
|
||||
@@ -82,11 +82,14 @@ const DetailsPage = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitor = async () => {
|
||||
const res = await axiosInstance.get(`/monitors/${monitorId}`, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
});
|
||||
const res = await axiosInstance.get(
|
||||
`/monitors/${monitorId}?sortOrder=asc`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
setMonitor(res.data.data);
|
||||
const data = {
|
||||
cols: [
|
||||
|
||||
@@ -100,6 +100,9 @@ const Monitors = () => {
|
||||
: "var(--env-var-color-19)",
|
||||
};
|
||||
|
||||
// Reverse checks so latest check is on the right
|
||||
const reversedChecks = monitor.checks.slice().reverse();
|
||||
|
||||
return {
|
||||
id: monitor._id,
|
||||
handleClick: () => navigate(`/monitors/${monitor._id}`),
|
||||
@@ -117,7 +120,7 @@ const Monitors = () => {
|
||||
/>
|
||||
),
|
||||
},
|
||||
{ id: idx + 2, data: <ResponseTimeChart checks={monitor.checks} /> },
|
||||
{ id: idx + 2, data: <ResponseTimeChart checks={reversedChecks} /> },
|
||||
{ id: idx + 3, data: monitor.type },
|
||||
{ id: idx + 4, data: "TODO" },
|
||||
],
|
||||
|
||||
@@ -6,16 +6,12 @@
|
||||

|
||||

|
||||
|
||||
|
||||
<h1 align="center"><a href="https://bluewavelabs.ca" target="_blank">BlueWave Uptime</a></h1>
|
||||
|
||||
<p align="center"><strong>An open source server monitoring application</strong></p>
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
BlueWave Uptime is an open source server monitoring application used to track the operational status and performance of servers and websites. It regularly checks whether a server/website is accessible and performs optimally, providing real-time alerts and reports on the monitored services' availability, downtime, and response time.
|
||||
|
||||
## Contributing
|
||||
@@ -776,7 +772,7 @@ curl --request GET \
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary id='get-monitor-id'><code>GET</code> <b>/api/v1/monitor/{id}</b></summary>
|
||||
<summary id='get-monitor-id'><code>GET</code> <b>/api/v1/monitor/{id}?status</b></summary>
|
||||
|
||||
###### Method/Headers
|
||||
|
||||
@@ -785,6 +781,14 @@ curl --request GET \
|
||||
> | Method | GET |
|
||||
> | content-type | application/json |
|
||||
|
||||
###### Query Params
|
||||
|
||||
> | Name | Type | Required | Notes |
|
||||
> | --------- | --------- | -------- | ------------------------------------------------ |
|
||||
> | status | `boolean` | Optional | Check status |
|
||||
> | limit | `number` | Optional | Number of checks to return |
|
||||
> | sortOrder | `string` | Optional | `desc`:Newest -> Oldest, `asc`: Oldest -> Newest |
|
||||
|
||||
###### Response Payload
|
||||
|
||||
> | Type | Notes |
|
||||
@@ -795,7 +799,7 @@ curl --request GET \
|
||||
|
||||
```
|
||||
curl --request GET \
|
||||
--url http://localhost:5000/api/v1/monitors/664d070786e62625ac612ca1 \
|
||||
--url http://localhost:5000/api/v1/monitors/664d070786e62625ac612ca1?status=true?limit=0 \
|
||||
--header '<bearer_token>' \
|
||||
```
|
||||
|
||||
@@ -857,6 +861,15 @@ curl --request GET \
|
||||
> | Method | GET |
|
||||
> | content-type | application/json |
|
||||
|
||||
###### Query Params
|
||||
|
||||
> | Name | Type | Required | Notes |
|
||||
> | --------- | --------- | -------- | ------------------------------------------------- |
|
||||
> | status | `boolean` | Optional | Check status |
|
||||
> | type | `string` | Optional | Multiple allowed: `http` \| `ping` \| `pagespeed` |
|
||||
> | limit | `number` | Optional | Monitor status |
|
||||
> | sortOrder | `string` | Optional | `desc`:Newest -> Oldest, `asc`: Oldest -> Newest |
|
||||
|
||||
###### Response Payload
|
||||
|
||||
> | Type | Notes |
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const {
|
||||
getMonitorByIdValidation,
|
||||
getMonitorByIdParamValidation,
|
||||
getMonitorByIdQueryValidation,
|
||||
getMonitorsByUserIdValidation,
|
||||
monitorValidation,
|
||||
editMonitorBodyValidation,
|
||||
getMonitorsByUserIdQueryValidation,
|
||||
} = require("../validation/joi");
|
||||
|
||||
const SERVICE_NAME = "monitorController";
|
||||
@@ -41,7 +43,8 @@ const getAllMonitors = async (req, res, next) => {
|
||||
*/
|
||||
const getMonitorById = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdValidation.validateAsync(req.params);
|
||||
await getMonitorByIdParamValidation.validateAsync(req.params);
|
||||
await getMonitorByIdQueryValidation.validateAsync(req.query);
|
||||
} catch (error) {
|
||||
error.status = 422;
|
||||
error.message = error.details[0].message;
|
||||
@@ -77,14 +80,9 @@ const getMonitorById = async (req, res, next) => {
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorsByUserId = async (req, res, next) => {
|
||||
const { error } = getMonitorsByUserIdValidation.validate(req.params);
|
||||
if (error) {
|
||||
return res
|
||||
.status(422)
|
||||
.json({ success: false, msg: error.details[0].message });
|
||||
}
|
||||
|
||||
try {
|
||||
await getMonitorsByUserIdValidation.validateAsync(req.params);
|
||||
await getMonitorsByUserIdQueryValidation.validateAsync(req.query);
|
||||
const userId = req.params.userId;
|
||||
const monitors = await req.db.getMonitorsByUserId(req, res);
|
||||
|
||||
@@ -99,60 +97,6 @@ const getMonitorsByUserId = async (req, res, next) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns monitor with matching ID and incidents
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorByIdForIncidents = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorByIdValidation.validateAsync(req.params);
|
||||
|
||||
let monitorWithIncidents = await req.db.getMonitorByIdForIncidents(
|
||||
req,
|
||||
res
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
msg: successMessages.MONTIOR_GET_BY_ID,
|
||||
data: monitorWithIncidents,
|
||||
});
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns all monitors with incidents that belong to User with UserID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<Express.Response>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorsByUserIdForIncidents = async (req, res, next) => {
|
||||
try {
|
||||
await getMonitorsByUserIdValidation.validateAsync(req.params);
|
||||
let monitorsWithIncidents = await req.db.getMonitorsByUserIdForIncidents(
|
||||
req,
|
||||
res
|
||||
);
|
||||
return res.json({
|
||||
success: true,
|
||||
msg: successMessages.MONITOR_GET_BY_USER_ID(req.params.userId),
|
||||
data: monitorsWithIncidents,
|
||||
});
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new monitor
|
||||
* @async
|
||||
@@ -282,8 +226,6 @@ module.exports = {
|
||||
getAllMonitors,
|
||||
getMonitorById,
|
||||
getMonitorsByUserId,
|
||||
getMonitorByIdForIncidents,
|
||||
getMonitorsByUserIdForIncidents,
|
||||
createMonitor,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const Monitor = require("../../../models/Monitor");
|
||||
const Check = require("../../../models/Check");
|
||||
|
||||
const PageSpeedCheck = require("../../../models/PageSpeedCheck");
|
||||
const { errorMessages } = require("../../../utils/messages");
|
||||
|
||||
/**
|
||||
@@ -30,10 +30,40 @@ const getAllMonitors = async (req, res) => {
|
||||
*/
|
||||
const getMonitorById = async (req, res) => {
|
||||
try {
|
||||
const monitor = await Monitor.findById(req.params.monitorId);
|
||||
const checks = await Check.find({ monitorId: monitor._id }).sort({
|
||||
createdAt: 1,
|
||||
});
|
||||
|
||||
const { monitorId } = req.params;
|
||||
let { status, limit, sortOrder } = req.query;
|
||||
|
||||
// This effectively removes limit, returning all checks
|
||||
if (limit === undefined) limit = 0;
|
||||
|
||||
// Default sort order is newest -> oldest
|
||||
if (sortOrder === "asc") {
|
||||
sortOrder = 1;
|
||||
} else if (sortOrder === "desc") {
|
||||
sortOrder = -1;
|
||||
} else sortOrder = -1;
|
||||
|
||||
const monitor = await Monitor.findById(monitorId);
|
||||
|
||||
const checksQuery = { monitorId: monitor._id };
|
||||
|
||||
if (status !== undefined) {
|
||||
checksQuery.status = status;
|
||||
}
|
||||
|
||||
// Determine model type
|
||||
let model =
|
||||
monitor.type === "http" || monitor.type === "ping"
|
||||
? Check
|
||||
: PageSpeedCheck;
|
||||
|
||||
const checks = await model
|
||||
.find(checksQuery)
|
||||
.sort({
|
||||
createdAt: sortOrder,
|
||||
})
|
||||
.limit(limit);
|
||||
const monitorWithChecks = { ...monitor.toObject(), checks };
|
||||
return monitorWithChecks;
|
||||
} catch (error) {
|
||||
@@ -51,79 +81,45 @@ const getMonitorById = async (req, res) => {
|
||||
*/
|
||||
const getMonitorsByUserId = async (req, res) => {
|
||||
try {
|
||||
const limit = req.query ? req.query.limit : undefined;
|
||||
const monitors = await Monitor.find({ userId: req.params.userId });
|
||||
console.log("monitors", monitors);
|
||||
let { limit, type, status, sortOrder } = req.query;
|
||||
const monitorQuery = { userId: req.params.userId };
|
||||
|
||||
if (type !== undefined) {
|
||||
const types = Array.isArray(type) ? type : [type];
|
||||
monitorQuery.type = { $in: types };
|
||||
}
|
||||
|
||||
// Default sort order is newest -> oldest
|
||||
if (sortOrder === "asc") {
|
||||
sortOrder = 1;
|
||||
} else if (sortOrder === "desc") {
|
||||
sortOrder = -1;
|
||||
} else sortOrder = -1;
|
||||
|
||||
// This effectively removes limit, returning all checks
|
||||
if (limit === undefined) limit = 0;
|
||||
|
||||
const monitors = await Monitor.find(monitorQuery);
|
||||
// Map each monitor to include its associated checks
|
||||
const monitorsWithChecks = await Promise.all(
|
||||
monitors.map(async (monitor) => {
|
||||
if (limit) {
|
||||
// Checks are order newest -> oldest
|
||||
const checks = await Check.find({ monitorId: monitor._id })
|
||||
.sort({
|
||||
createdAt: -1,
|
||||
})
|
||||
.limit(limit);
|
||||
return { ...monitor.toObject(), checks };
|
||||
} else {
|
||||
const checks = await Check.find({ monitorId: monitor._id }).sort({
|
||||
createdAt: -1,
|
||||
});
|
||||
return { ...monitor.toObject(), checks };
|
||||
const checksQuery = { monitorId: monitor._id };
|
||||
if (status !== undefined) {
|
||||
checksQuery.status = status;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return monitorsWithChecks;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
let model =
|
||||
monitor.type === "http" || monitor.type === "ping"
|
||||
? Check
|
||||
: PageSpeedCheck;
|
||||
|
||||
/**
|
||||
* Get monitors by UserID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<Monitor>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorByIdForIncidents = async (req, res, next) => {
|
||||
try {
|
||||
const monitor = await Monitor.findById(req.params.monitorId);
|
||||
const checks = await Check.find({
|
||||
monitorId: monitor._id,
|
||||
status: false,
|
||||
}).sort({
|
||||
createdAt: 1,
|
||||
});
|
||||
const monitorWithChecks = { ...monitor.toObject(), checks };
|
||||
return monitorWithChecks;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get monitors by UserID
|
||||
* @async
|
||||
* @param {Express.Request} req
|
||||
* @param {Express.Response} res
|
||||
* @returns {Promise<Array<Monitor>>}
|
||||
* @throws {Error}
|
||||
*/
|
||||
const getMonitorsByUserIdForIncidents = async (req, res) => {
|
||||
try {
|
||||
const monitors = await Monitor.find({ userId: req.params.userId });
|
||||
// Map each monitor to include its associated checks
|
||||
const monitorsWithChecks = await Promise.all(
|
||||
monitors.map(async (monitor) => {
|
||||
const checks = await Check.find({
|
||||
monitorId: monitor._id,
|
||||
status: false,
|
||||
}).sort({
|
||||
createdAt: 1,
|
||||
});
|
||||
// Checks are order newest -> oldest
|
||||
const checks = await model
|
||||
.find(checksQuery)
|
||||
.sort({
|
||||
createdAt: sortOrder,
|
||||
})
|
||||
.limit(limit);
|
||||
return { ...monitor.toObject(), checks };
|
||||
})
|
||||
);
|
||||
@@ -228,8 +224,6 @@ module.exports = {
|
||||
getAllMonitors,
|
||||
getMonitorById,
|
||||
getMonitorsByUserId,
|
||||
getMonitorByIdForIncidents,
|
||||
getMonitorsByUserIdForIncidents,
|
||||
createMonitor,
|
||||
deleteMonitor,
|
||||
deleteAllMonitors,
|
||||
|
||||
@@ -14,7 +14,7 @@ const PageSpeedCheck = require("../../../models/PageSpeedCheck");
|
||||
*/
|
||||
const createPageSpeedCheck = async (pageSpeedCheckData) => {
|
||||
try {
|
||||
const pageSpeedCheck = await new pageSpeedCheck({
|
||||
const pageSpeedCheck = await new PageSpeedCheck({
|
||||
...pageSpeedCheckData,
|
||||
}).save();
|
||||
return pageSpeedCheck;
|
||||
|
||||
@@ -7,15 +7,6 @@ router.get("/", monitorController.getAllMonitors);
|
||||
router.get("/:monitorId", monitorController.getMonitorById);
|
||||
router.get("/user/:userId", monitorController.getMonitorsByUserId);
|
||||
|
||||
router.get(
|
||||
"/incidents/:monitorId",
|
||||
monitorController.getMonitorByIdForIncidents
|
||||
);
|
||||
router.get(
|
||||
"/incidents/user/:userId",
|
||||
monitorController.getMonitorsByUserIdForIncidents
|
||||
);
|
||||
|
||||
router.post("/", monitorController.createMonitor);
|
||||
router.post(
|
||||
"/delete/:monitorId",
|
||||
|
||||
@@ -189,6 +189,7 @@ class NetworkService {
|
||||
const insertedCheck = await writeToDB(data);
|
||||
return insertedCheck.status;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
logger.error(`Error wrtiting check for ${data.monitorId}`, {
|
||||
service: this.SERVICE_NAME,
|
||||
monitorId: data.monitorId,
|
||||
|
||||
@@ -118,14 +118,32 @@ const inviteVerifciationBodyValidation = joi.object({
|
||||
// Monitors
|
||||
//****************************************
|
||||
|
||||
const getMonitorByIdValidation = joi.object({
|
||||
const getMonitorByIdParamValidation = joi.object({
|
||||
monitorId: joi.string().required(),
|
||||
});
|
||||
|
||||
const getMonitorByIdQueryValidation = joi.object({
|
||||
status: joi.boolean(),
|
||||
sortOrder: joi.string().valid("asc", "desc"),
|
||||
limit: joi.number(),
|
||||
});
|
||||
|
||||
const getMonitorsByUserIdValidation = joi.object({
|
||||
userId: joi.string().required(),
|
||||
});
|
||||
|
||||
const getMonitorsByUserIdQueryValidation = joi.object({
|
||||
status: joi.boolean(),
|
||||
sortOrder: joi.string().valid("asc", "desc"),
|
||||
limit: joi.number(),
|
||||
type: joi
|
||||
.alternatives()
|
||||
.try(
|
||||
joi.string().valid("http", "ping", "pagespeed"),
|
||||
joi.array().items(joi.string().valid("http", "ping", "pagespeed"))
|
||||
),
|
||||
});
|
||||
|
||||
const monitorValidation = joi.object({
|
||||
_id: joi.string(),
|
||||
userId: joi.string().required(),
|
||||
@@ -244,9 +262,10 @@ module.exports = {
|
||||
inviteRoleValidation,
|
||||
inviteBodyValidation,
|
||||
inviteVerifciationBodyValidation,
|
||||
getMonitorByIdValidation,
|
||||
getMonitorByIdParamValidation,
|
||||
getMonitorByIdQueryValidation,
|
||||
getMonitorsByUserIdValidation,
|
||||
monitorValidation,
|
||||
getMonitorsByUserIdQueryValidation,
|
||||
editMonitorBodyValidation,
|
||||
editUserParamValidation,
|
||||
editUserBodyValidation,
|
||||
|
||||
Reference in new issue
Block a user