Files
Checkmate/Server/service/statusService.js
T

164 lines
5.5 KiB
JavaScript
Raw Normal View History

2024-12-24 11:58:26 -08:00
const SERVICE_NAME = "StatusService";
2024-10-28 14:19:14 +08:00
class StatusService {
2024-12-24 11:58:26 -08:00
static SERVICE_NAME = SERVICE_NAME;
2024-10-28 14:19:14 +08:00
/**
* Creates an instance of StatusService.
*
* @param {Object} db - The database instance.
* @param {Object} logger - The logger instance.
*/
constructor(db, logger) {
this.db = db;
this.logger = logger;
2024-12-24 11:58:26 -08:00
this.SERVICE_NAME = SERVICE_NAME;
2024-10-28 14:19:14 +08:00
}
2024-11-24 15:59:09 +08:00
getStatusString = (status) => {
if (status === true) return "up";
if (status === false) return "down";
return "unknown";
};
2024-10-28 14:19:14 +08:00
/**
* Updates the status of a monitor based on the network response.
*
* @param {Object} networkResponse - The network response containing monitorId and status.
* @param {string} networkResponse.monitorId - The ID of the monitor.
* @param {string} networkResponse.status - The new status of the monitor.
* @returns {Promise<Object>} - A promise that resolves to an object containing the monitor, statusChanged flag, and previous status if the status changed, or false if an error occurred.
* @returns {Promise<Object>} returnObject - The object returned by the function.
* @returns {Object} returnObject.monitor - The monitor object.
* @returns {boolean} returnObject.statusChanged - Flag indicating if the status has changed.
* @returns {boolean} returnObject.prevStatus - The previous status of the monitor
*/
updateStatus = async (networkResponse) => {
this.insertCheck(networkResponse);
try {
const { monitorId, status } = networkResponse;
const monitor = await this.db.getMonitorById(monitorId);
// No change in monitor status, return early
if (monitor.status === status)
return { monitor, statusChanged: false, prevStatus: monitor.status };
2024-10-28 14:19:14 +08:00
// Monitor status changed, save prev status and update monitor
this.logger.info({
service: this.SERVICE_NAME,
2024-11-24 15:59:09 +08:00
message: `${monitor.name} went from ${this.getStatusString(monitor.status)} to ${this.getStatusString(status)}`,
2024-10-28 14:19:14 +08:00
prevStatus: monitor.status,
newStatus: status,
});
const prevStatus = monitor.status;
monitor.status = status;
2024-10-28 15:34:19 +08:00
await monitor.save();
2024-10-28 14:19:14 +08:00
return {
monitor,
statusChanged: true,
prevStatus: prevStatus,
};
//
} catch (error) {
this.logger.error({
service: this.SERVICE_NAME,
message: error.message,
method: "updateStatus",
stack: error.stack,
});
throw error;
}
};
/**
* Builds a check object from the network response.
*
* @param {Object} networkResponse - The network response object.
* @param {string} networkResponse.monitorId - The monitor ID.
* @param {string} networkResponse.type - The type of the response.
* @param {string} networkResponse.status - The status of the response.
* @param {number} networkResponse.responseTime - The response time.
* @param {number} networkResponse.code - The status code.
* @param {string} networkResponse.message - The message.
* @param {Object} networkResponse.payload - The payload of the response.
* @returns {Object} The check object.
*/
buildCheck = (networkResponse) => {
const { monitorId, teamId, type, status, responseTime, code, message, payload } =
2024-10-28 14:19:14 +08:00
networkResponse;
const check = {
monitorId,
teamId,
2024-10-28 14:19:14 +08:00
status,
statusCode: code,
responseTime,
message,
};
2024-11-11 08:52:51 +08:00
2024-10-28 14:19:14 +08:00
if (type === "pagespeed") {
const categories = payload.lighthouseResult?.categories;
const audits = payload.lighthouseResult?.audits;
const {
"cumulative-layout-shift": cls = 0,
"speed-index": si = 0,
"first-contentful-paint": fcp = 0,
"largest-contentful-paint": lcp = 0,
"total-blocking-time": tbt = 0,
} = audits;
check.accessibility = (categories.accessibility?.score || 0) * 100;
check.bestPractices = (categories["best-practices"]?.score || 0) * 100;
check.seo = (categories.seo?.score || 0) * 100;
check.performance = (categories.performance?.score || 0) * 100;
check.audits = { cls, si, fcp, lcp, tbt };
}
2024-10-29 13:51:31 +08:00
if (type === "hardware") {
2024-11-11 08:52:51 +08:00
const { cpu, memory, disk, host } = payload?.data ?? {};
const { errors } = payload?.errors ?? [];
2024-11-11 08:52:51 +08:00
check.cpu = cpu ?? {};
check.memory = memory ?? {};
check.disk = disk ?? {};
check.host = host ?? {};
check.errors = errors ?? [];
2024-10-29 13:51:31 +08:00
}
2024-10-28 14:19:14 +08:00
return check;
};
/**
* Inserts a check into the database based on the network response.
*
* @param {Object} networkResponse - The network response object.
* @param {string} networkResponse.monitorId - The monitor ID.
* @param {string} networkResponse.type - The type of the response.
* @param {string} networkResponse.status - The status of the response.
* @param {number} networkResponse.responseTime - The response time.
* @param {number} networkResponse.code - The status code.
* @param {string} networkResponse.message - The message.
* @param {Object} networkResponse.payload - The payload of the response.
* @returns {Promise<void>} A promise that resolves when the check is inserted.
*/
insertCheck = async (networkResponse) => {
try {
const operationMap = {
http: this.db.createCheck,
ping: this.db.createCheck,
pagespeed: this.db.createPageSpeedCheck,
2024-10-29 13:51:31 +08:00
hardware: this.db.createHardwareCheck,
docker: this.db.createCheck,
2024-12-27 10:49:45 -08:00
port: this.db.createCheck,
2024-10-28 14:19:14 +08:00
};
const operation = operationMap[networkResponse.type];
2024-11-11 08:52:51 +08:00
2024-10-28 14:19:14 +08:00
const check = this.buildCheck(networkResponse);
await operation(check);
} catch (error) {
this.logger.error({
message: error.message,
service: this.SERVICE_NAME,
method: "insertCheck",
2024-10-29 13:51:31 +08:00
details: `Error inserting check for monitor: ${networkResponse?.monitorId}`,
2024-10-28 14:19:14 +08:00
stack: error.stack,
});
}
};
}
export default StatusService;