Files
Checkmate/Server/db/mongo/modules/monitorModule.js
T

839 lines
21 KiB
JavaScript
Raw Normal View History

2024-10-15 11:57:37 +08:00
import Monitor from "../../models/Monitor.js";
import Check from "../../models/Check.js";
import PageSpeedCheck from "../../models/PageSpeedCheck.js";
import HardwareCheck from "../../models/HardwareCheck.js";
2024-10-15 11:57:37 +08:00
import { errorMessages } from "../../../utils/messages.js";
import Notification from "../../models/Notification.js";
2024-12-31 13:42:25 -08:00
import { NormalizeData, NormalizeDataUptimeDetails } from "../../../utils/dataUtils.js";
2024-10-15 11:57:37 +08:00
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import {
buildUptimeDetailsPipeline,
buildHardwareDetailsPipeline,
} from "./monitorModuleQueries.js";
2025-01-07 16:27:35 -08:00
import { ObjectId } from "mongodb";
2024-10-15 11:57:37 +08:00
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
2024-10-17 12:07:30 +08:00
const demoMonitorsPath = path.resolve(__dirname, "../../../utils/demoMonitors.json");
2024-10-15 11:57:37 +08:00
const demoMonitors = JSON.parse(fs.readFileSync(demoMonitorsPath, "utf8"));
const SERVICE_NAME = "monitorModule";
2024-07-26 18:25:20 -07:00
const CHECK_MODEL_LOOKUP = {
http: Check,
ping: Check,
2024-11-13 15:34:31 +08:00
docker: Check,
2024-12-27 11:16:09 -08:00
port: Check,
2024-11-08 09:46:30 +08:00
pagespeed: PageSpeedCheck,
hardware: HardwareCheck,
};
2024-07-26 18:25:20 -07:00
/**
* Get all monitors
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Array<Monitor>>}
* @throws {Error}
*/
const getAllMonitors = async (req, res) => {
2024-10-17 12:07:30 +08:00
try {
const monitors = await Monitor.find();
return monitors;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getAllMonitors";
throw error;
}
2024-07-26 18:25:20 -07:00
};
/**
* Get all monitors with uptime stats for 1,7,30, and 90 days
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Array<Monitor>>}
* @throws {Error}
*/
const getAllMonitorsWithUptimeStats = async () => {
const timeRanges = {
1: new Date(Date.now() - 24 * 60 * 60 * 1000),
7: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
30: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
90: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000),
};
try {
const monitors = await Monitor.find();
const monitorsWithStats = await Promise.all(
monitors.map(async (monitor) => {
const model = CHECK_MODEL_LOOKUP[monitor.type];
const uptimeStats = await Promise.all(
Object.entries(timeRanges).map(async ([days, startDate]) => {
const checks = await model.find({
monitorId: monitor._id,
createdAt: { $gte: startDate },
});
return [days, getUptimePercentage(checks)];
})
);
return {
...monitor.toObject(),
...Object.fromEntries(uptimeStats),
};
})
);
return monitorsWithStats;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getAllMonitorsWithUptimeStats";
throw error;
}
};
2024-08-12 12:05:57 -07:00
/**
* Function to calculate uptime duration based on the most recent check.
* @param {Array} checks Array of check objects.
* @returns {number} Uptime duration in ms.
*/
2024-08-12 15:07:03 -07:00
const calculateUptimeDuration = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0;
}
const latestCheck = new Date(checks[0].createdAt);
let latestDownCheck = 0;
2024-11-05 12:22:48 +08:00
for (let i = checks.length - 1; i >= 0; i--) {
2024-10-17 12:07:30 +08:00
if (checks[i].status === false) {
latestDownCheck = new Date(checks[i].createdAt);
break;
}
}
// If no down check is found, uptime is from the last check to now
if (latestDownCheck === 0) {
return Date.now() - new Date(checks[checks.length - 1].createdAt);
}
// Otherwise the uptime is from the last check to the last down check
return latestCheck - latestDownCheck;
2024-08-12 12:05:57 -07:00
};
/**
* Helper function to get duration since last check
* @param {Array} checks Array of check objects.
* @returns {number} Timestamp of the most recent check.
*/
const getLastChecked = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0; // Handle case when no checks are available
}
// Data is sorted newest->oldest, so last check is the most recent
return new Date() - new Date(checks[0].createdAt);
2024-08-12 12:05:57 -07:00
};
/**
* Helper function to get latestResponseTime
* @param {Array} checks Array of check objects.
* @returns {number} Timestamp of the most recent check.
*/
const getLatestResponseTime = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0;
}
2024-11-05 13:31:10 +08:00
return checks[0]?.responseTime ?? 0;
2024-08-12 12:05:57 -07:00
};
/**
* Helper function to get average response time
2024-08-12 12:05:57 -07:00
* @param {Array} checks Array of check objects.
* @returns {number} Timestamp of the most recent check.
*/
const getAverageResponseTime = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0;
}
2024-11-05 13:36:31 +08:00
const validChecks = checks.filter((check) => typeof check.responseTime === "number");
if (validChecks.length === 0) {
return 0;
}
const aggResponseTime = validChecks.reduce((sum, check) => {
2024-10-17 12:07:30 +08:00
return sum + check.responseTime;
}, 0);
2024-11-05 13:36:31 +08:00
return aggResponseTime / validChecks.length;
2024-08-12 12:05:57 -07:00
};
/**
* Helper function to get percentage 24h uptime
2024-08-12 12:05:57 -07:00
* @param {Array} checks Array of check objects.
* @returns {number} Timestamp of the most recent check.
*/
const getUptimePercentage = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0;
}
const upCount = checks.reduce((count, check) => {
return check.status === true ? count + 1 : count;
}, 0);
return (upCount / checks.length) * 100;
2024-08-12 12:05:57 -07:00
};
/**
* Helper function to get all incidents
* @param {Array} checks Array of check objects.
* @returns {number} Timestamp of the most recent check.
*/
const getIncidents = (checks) => {
2024-10-17 12:07:30 +08:00
if (!checks || checks.length === 0) {
return 0; // Handle case when no checks are available
}
return checks.reduce((acc, check) => {
return check.status === false ? (acc += 1) : acc;
}, 0);
2024-08-12 12:05:57 -07:00
};
2024-11-05 12:08:19 +08:00
/**
* Get date range parameters
* @param {string} dateRange - 'day' | 'week' | 'month' | 'all'
2024-11-05 12:08:19 +08:00
* @returns {Object} Start and end dates
*/
const getDateRange = (dateRange) => {
const startDates = {
day: new Date(new Date().setDate(new Date().getDate() - 1)),
week: new Date(new Date().setDate(new Date().getDate() - 7)),
month: new Date(new Date().setMonth(new Date().getMonth() - 1)),
all: new Date(0),
2024-11-05 12:08:19 +08:00
};
return {
start: startDates[dateRange],
end: new Date(),
};
};
/**
* Get checks for a monitor
* @param {string} monitorId - Monitor ID
* @param {Object} model - Check model to use
* @param {Object} dateRange - Date range parameters
* @param {number} sortOrder - Sort order (1 for ascending, -1 for descending)
* @returns {Promise<Object>} All checks and date-ranged checks
*/
const getMonitorChecks = async (monitorId, model, dateRange, sortOrder) => {
2024-12-28 09:37:00 -08:00
const indexSpec = {
monitorId: 1,
createdAt: sortOrder, // This will be 1 or -1
};
2024-11-05 12:08:19 +08:00
const [checksAll, checksForDateRange] = await Promise.all([
2024-12-28 09:37:00 -08:00
model.find({ monitorId }).sort({ createdAt: sortOrder }).hint(indexSpec).lean(),
2024-11-05 12:08:19 +08:00
model
.find({
monitorId,
createdAt: { $gte: dateRange.start, $lte: dateRange.end },
})
2024-12-28 09:37:00 -08:00
.hint(indexSpec)
.lean(),
2024-11-05 12:08:19 +08:00
]);
2024-12-28 09:37:00 -08:00
2024-11-05 12:08:19 +08:00
return { checksAll, checksForDateRange };
};
/**
* Process checks for display
* @param {Array} checks - Checks to process
* @param {number} numToDisplay - Number of checks to display
* @param {boolean} normalize - Whether to normalize the data
* @returns {Array} Processed checks
*/
const processChecksForDisplay = (normalizeData, checks, numToDisplay, normalize) => {
2024-11-05 12:08:19 +08:00
let processedChecks = checks;
if (numToDisplay && checks.length > numToDisplay) {
const n = Math.ceil(checks.length / numToDisplay);
processedChecks = checks.filter((_, index) => index % n === 0);
}
return normalize ? normalizeData(processedChecks, 1, 100) : processedChecks;
2024-11-05 12:08:19 +08:00
};
/**
* Get time-grouped checks based on date range
* @param {Array} checks Array of check objects
* @param {string} dateRange 'day' | 'week' | 'month'
* @returns {Object} Grouped checks by time period
*/
const groupChecksByTime = (checks, dateRange) => {
return checks.reduce((acc, check) => {
2024-11-05 14:09:32 +08:00
// Validate the date
const checkDate = new Date(check.createdAt);
2024-11-07 11:05:48 +08:00
if (Number.isNaN(checkDate.getTime()) || checkDate.getTime() === 0) {
2024-11-05 14:09:32 +08:00
return acc;
}
2024-11-05 12:08:19 +08:00
const time =
dateRange === "day"
2024-11-05 14:09:32 +08:00
? checkDate.setMinutes(0, 0, 0)
: checkDate.toISOString().split("T")[0];
2024-11-05 12:08:19 +08:00
if (!acc[time]) {
acc[time] = { time, checks: [] };
}
acc[time].checks.push(check);
return acc;
}, {});
};
/**
* Calculate aggregate stats for a group of checks
* @param {Object} group Group of checks
* @returns {Object} Stats for the group
*/
const calculateGroupStats = (group) => {
const totalChecks = group.checks.length;
2024-11-05 14:09:32 +08:00
const checksWithResponseTime = group.checks.filter(
2024-11-07 11:05:48 +08:00
(check) => typeof check.responseTime === "number" && !Number.isNaN(check.responseTime)
2024-11-05 14:09:32 +08:00
);
2024-11-05 12:08:19 +08:00
return {
time: group.time,
uptimePercentage: getUptimePercentage(group.checks),
totalChecks,
totalIncidents: group.checks.filter((check) => !check.status).length,
avgResponseTime:
2024-11-05 14:09:32 +08:00
checksWithResponseTime.length > 0
? checksWithResponseTime.reduce((sum, check) => sum + check.responseTime, 0) /
checksWithResponseTime.length
: 0,
2024-11-05 12:08:19 +08:00
};
};
/**
* Get uptime details by monitor ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const getUptimeDetailsById = async (req) => {
try {
const { monitorId } = req.params;
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
const { dateRange, normalize } = req.query;
const dates = getDateRange(dateRange);
const formatLookup = {
day: "%Y-%m-%dT%H:00:00Z",
week: "%Y-%m-%dT%H:00:00Z",
month: "%Y-%m-%dT00:00:00Z",
};
const dateString = formatLookup[dateRange];
2025-01-10 12:12:33 -08:00
const results = await Check.aggregate(
buildUptimeDetailsPipeline(monitor, dates, dateString)
);
2025-01-10 12:12:33 -08:00
const monitorData = results[0];
2024-12-31 13:42:25 -08:00
const normalizedGroupChecks = NormalizeDataUptimeDetails(
2025-01-10 12:12:33 -08:00
monitorData.groupedChecks,
2024-12-31 13:42:25 -08:00
10,
100
);
2024-12-30 16:07:28 -08:00
const monitorStats = {
...monitor.toObject(),
2025-01-10 12:12:33 -08:00
...monitorData,
groupedChecks: normalizedGroupChecks,
2024-12-30 16:07:28 -08:00
};
return monitorStats;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getUptimeDetailsById";
throw error;
}
};
2024-08-12 12:05:57 -07:00
/**
* Get stats by monitor ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const getMonitorStatsById = async (req) => {
2024-10-17 12:07:30 +08:00
try {
const { monitorId } = req.params;
2024-11-05 12:08:19 +08:00
// Get monitor, if we can't find it, abort with error
2024-10-17 12:07:30 +08:00
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
2024-11-05 12:08:19 +08:00
// Get query params
let { limit, sortOrder, dateRange, numToDisplay, normalize } = req.query;
const sort = sortOrder === "asc" ? 1 : -1;
// Get Checks for monitor in date range requested
const model = CHECK_MODEL_LOOKUP[monitor.type];
const dates = getDateRange(dateRange);
const { checksAll, checksForDateRange } = await getMonitorChecks(
monitorId,
model,
dates,
sort
);
2024-10-17 12:07:30 +08:00
2024-11-05 12:08:19 +08:00
// Build monitor stats
2024-10-17 12:07:30 +08:00
const monitorStats = {
...monitor.toObject(),
2024-11-05 12:08:19 +08:00
uptimeDuration: calculateUptimeDuration(checksAll),
lastChecked: getLastChecked(checksAll),
latestResponseTime: getLatestResponseTime(checksAll),
periodIncidents: getIncidents(checksForDateRange),
periodTotalChecks: checksForDateRange.length,
checks: processChecksForDisplay(
NormalizeData,
checksForDateRange,
numToDisplay,
normalize
),
2024-10-17 12:07:30 +08:00
};
2024-12-27 11:16:09 -08:00
if (
monitor.type === "http" ||
monitor.type === "ping" ||
monitor.type === "docker" ||
monitor.type === "port"
) {
2024-10-17 12:07:30 +08:00
// HTTP/PING Specific stats
monitorStats.periodAvgResponseTime = getAverageResponseTime(checksForDateRange);
monitorStats.periodUptime = getUptimePercentage(checksForDateRange);
2024-11-05 12:08:19 +08:00
const groupedChecks = groupChecksByTime(checksForDateRange, dateRange);
monitorStats.aggregateData = Object.values(groupedChecks).map(calculateGroupStats);
2024-10-17 12:07:30 +08:00
}
return monitorStats;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getMonitorStatsById";
throw error;
}
2024-08-12 12:05:57 -07:00
};
2024-12-31 15:05:14 -08:00
const getHardwareDetailsById = async (req) => {
try {
const { monitorId } = req.params;
2024-12-31 17:39:02 -08:00
const { dateRange } = req.query;
2024-12-31 15:05:14 -08:00
const monitor = await Monitor.findById(monitorId);
2024-12-31 17:39:02 -08:00
const dates = getDateRange(dateRange);
const formatLookup = {
day: "%Y-%m-%dT%H:00:00Z",
week: "%Y-%m-%dT%H:00:00Z",
month: "%Y-%m-%dT00:00:00Z",
};
const dateString = formatLookup[dateRange];
const hardwareStats = await HardwareCheck.aggregate(
buildHardwareDetailsPipeline(monitor, dates, dateString)
);
const monitorStats = {
...monitor.toObject(),
stats: hardwareStats[0],
};
return monitorStats;
2024-12-31 15:05:14 -08:00
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getHardwareDetailsById";
throw error;
}
};
2024-07-26 18:25:20 -07:00
/**
* Get a monitor by ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const getMonitorById = async (monitorId) => {
2024-10-17 12:07:30 +08:00
try {
const monitor = await Monitor.findById(monitorId);
if (monitor === null || monitor === undefined) {
const error = new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
error.status = 404;
throw error;
2024-10-17 12:07:30 +08:00
}
// Get notifications
const notifications = await Notification.find({
monitorId: monitorId,
});
2024-11-05 12:27:13 +08:00
// Update monitor with notifications and save
monitor.notifications = notifications;
await monitor.save();
return monitor;
2024-10-17 12:07:30 +08:00
} catch (error) {
error.service = SERVICE_NAME;
error.method = "getMonitorById";
throw error;
}
2024-07-26 18:25:20 -07:00
};
2025-01-08 13:44:24 -08:00
const getMonitorsByTeamId = async (req) => {
let { limit, type, page, rowsPerPage, filter, field, order } = req.query;
limit = parseInt(limit);
page = parseInt(page);
rowsPerPage = parseInt(rowsPerPage);
// Build the match stage
const matchStage = { teamId: ObjectId.createFromHexString(req.params.teamId) };
if (type !== undefined) {
matchStage.type = Array.isArray(type) ? { $in: type } : type;
2024-10-17 12:07:30 +08:00
}
2024-09-05 11:17:31 -07:00
2025-01-08 13:44:24 -08:00
const skip = page && rowsPerPage ? page * rowsPerPage : 0;
2024-10-17 12:07:30 +08:00
2025-01-08 13:44:24 -08:00
const sort = { [field]: order === "asc" ? 1 : -1 };
2024-10-17 12:07:30 +08:00
2025-01-08 13:44:24 -08:00
const results = await Monitor.aggregate([
{ $match: matchStage },
{
$facet: {
summary: [
{
$group: {
_id: null,
totalMonitors: { $sum: 1 },
upMonitors: {
$sum: {
$cond: [{ $eq: ["$status", true] }, 1, 0],
},
2025-01-07 16:27:35 -08:00
},
2025-01-08 13:44:24 -08:00
downMonitors: {
$sum: {
$cond: [{ $eq: ["$status", false] }, 1, 0],
},
2025-01-07 16:27:35 -08:00
},
2025-01-08 13:44:24 -08:00
pausedMonitors: {
$sum: {
$cond: [{ $eq: ["$isActive", false] }, 1, 0],
},
2025-01-07 16:27:35 -08:00
},
},
2025-01-08 13:44:24 -08:00
},
{
$project: {
_id: 0,
},
},
],
monitors: [
{ $sort: sort },
{
$project: {
_id: 1,
name: 1,
},
},
],
filteredMonitors: [
2025-01-08 14:17:29 -08:00
...(filter !== undefined
? [
{
$match: {
$or: [
{ name: { $regex: filter, $options: "i" } },
{ url: { $regex: filter, $options: "i" } },
],
},
},
]
: []),
2025-01-08 13:44:24 -08:00
{ $sort: sort },
{ $skip: skip },
...(rowsPerPage ? [{ $limit: rowsPerPage }] : []),
2025-01-09 10:42:25 -08:00
...(limit
? [
2025-01-07 16:27:35 -08:00
{
2025-01-09 10:42:25 -08:00
$lookup: {
from: "checks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "standardchecks",
2025-01-08 13:44:24 -08:00
},
2025-01-07 16:27:35 -08:00
},
2025-01-09 10:42:25 -08:00
]
: []),
...(limit
? [
2025-01-07 16:27:35 -08:00
{
2025-01-09 10:42:25 -08:00
$lookup: {
from: "pagespeedchecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "pagespeedchecks",
2025-01-08 13:44:24 -08:00
},
2025-01-07 16:27:35 -08:00
},
2025-01-09 10:42:25 -08:00
]
: []),
...(limit
? [
2025-01-07 16:27:35 -08:00
{
2025-01-09 10:42:25 -08:00
$lookup: {
from: "hardwarechecks",
let: { monitorId: "$_id" },
pipeline: [
{
$match: {
$expr: { $eq: ["$monitorId", "$$monitorId"] },
},
},
{ $sort: { createdAt: -1 } },
...(limit ? [{ $limit: limit }] : []),
],
as: "hardwarechecks",
2025-01-08 13:44:24 -08:00
},
2025-01-07 16:27:35 -08:00
},
2025-01-09 10:42:25 -08:00
]
: []),
2025-01-08 13:44:24 -08:00
{
$addFields: {
checks: {
$switch: {
branches: [
{
case: { $in: ["$type", ["http", "ping", "docker", "port"]] },
then: "$standardchecks",
},
{
case: { $eq: ["$type", "pagespeed"] },
then: "$pagespeedchecks",
},
{
case: { $eq: ["$type", "hardware"] },
then: "$hardwarechecks",
},
],
default: [],
},
},
},
},
{
$project: {
standardchecks: 0,
pagespeedchecks: 0,
hardwarechecks: 0,
},
},
],
2025-01-07 16:27:35 -08:00
},
2025-01-08 13:44:24 -08:00
},
{
$project: {
summary: { $arrayElemAt: ["$summary", 0] },
filteredMonitors: 1,
2025-01-08 13:44:24 -08:00
monitors: 1,
2025-01-07 16:27:35 -08:00
},
2025-01-08 13:44:24 -08:00
},
]);
let { monitors, filteredMonitors, summary } = results[0];
filteredMonitors = filteredMonitors.map((monitor) => {
2025-01-09 10:42:25 -08:00
if (!monitor.checks) {
return monitor;
}
2025-01-08 13:44:24 -08:00
monitor.checks = NormalizeData(monitor.checks, 10, 100);
return monitor;
});
return { monitors, filteredMonitors, summary };
2024-07-26 18:25:20 -07:00
};
/**
* Create a monitor
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const createMonitor = async (req, res) => {
2024-10-17 12:07:30 +08:00
try {
const monitor = new Monitor({ ...req.body });
// Remove notifications fom monitor as they aren't needed here
monitor.notifications = undefined;
await monitor.save();
return monitor;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "createMonitor";
throw error;
}
2024-07-26 18:25:20 -07:00
};
/**
* Delete a monitor by ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const deleteMonitor = async (req, res) => {
2024-10-17 12:07:30 +08:00
const monitorId = req.params.monitorId;
try {
const monitor = await Monitor.findByIdAndDelete(monitorId);
if (!monitor) {
throw new Error(errorMessages.DB_FIND_MONITOR_BY_ID(monitorId));
}
return monitor;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "deleteMonitor";
throw error;
}
2024-07-26 18:25:20 -07:00
};
/**
* DELETE ALL MONITORS (TEMP)
*/
2024-09-11 11:22:33 +08:00
const deleteAllMonitors = async (teamId) => {
2024-10-17 12:07:30 +08:00
try {
const monitors = await Monitor.find({ teamId });
const { deletedCount } = await Monitor.deleteMany({ teamId });
return { monitors, deletedCount };
} catch (error) {
error.service = SERVICE_NAME;
error.method = "deleteAllMonitors";
throw error;
}
2024-07-26 18:25:20 -07:00
};
/**
* Delete all monitors associated with a user ID
* @async
* @param {string} userId - The ID of the user whose monitors are to be deleted.
* @returns {Promise} A promise that resolves when the operation is complete.
*/
const deleteMonitorsByUserId = async (userId) => {
2024-10-17 12:07:30 +08:00
try {
const result = await Monitor.deleteMany({ userId: userId });
return result;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "deleteMonitorsByUserId";
throw error;
}
2024-07-26 18:25:20 -07:00
};
/**
* Edit a monitor by ID
* @async
* @param {Express.Request} req
* @param {Express.Response} res
* @returns {Promise<Monitor>}
* @throws {Error}
*/
const editMonitor = async (candidateId, candidateMonitor) => {
2024-10-17 12:07:30 +08:00
candidateMonitor.notifications = undefined;
try {
const editedMonitor = await Monitor.findByIdAndUpdate(candidateId, candidateMonitor, {
new: true,
});
return editedMonitor;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "editMonitor";
throw error;
}
};
const addDemoMonitors = async (userId, teamId) => {
2024-10-17 12:07:30 +08:00
try {
const demoMonitorsToInsert = demoMonitors.map((monitor) => {
return {
userId,
teamId,
name: monitor.name,
description: monitor.name,
type: "http",
url: monitor.url,
interval: 60000,
};
});
const insertedMonitors = await Monitor.insertMany(demoMonitorsToInsert);
return insertedMonitors;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "addDemoMonitors";
throw error;
}
2024-07-26 18:25:20 -07:00
};
2024-10-15 11:57:37 +08:00
export {
2024-10-17 12:07:30 +08:00
getAllMonitors,
getAllMonitorsWithUptimeStats,
2024-10-17 12:07:30 +08:00
getMonitorStatsById,
getMonitorById,
getMonitorsByTeamId,
2025-01-08 13:44:24 -08:00
getUptimeDetailsById,
2024-10-17 12:07:30 +08:00
createMonitor,
deleteMonitor,
deleteAllMonitors,
deleteMonitorsByUserId,
editMonitor,
addDemoMonitors,
2024-12-31 15:05:14 -08:00
getHardwareDetailsById,
2024-07-26 18:25:20 -07:00
};
2024-11-05 13:31:10 +08:00
// Helper functions
export {
calculateUptimeDuration,
getLastChecked,
getLatestResponseTime,
getAverageResponseTime,
getUptimePercentage,
getIncidents,
getDateRange,
getMonitorChecks,
processChecksForDisplay,
groupChecksByTime,
calculateGroupStats,
2024-11-05 13:31:10 +08:00
};