mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-20 00:29:45 -06:00
Merge pull request #1084 from bluewave-labs/feat/be/hardware-monitor-type
feat/be/hardware monitor type
This commit is contained in:
@@ -36,11 +36,31 @@ const HardwareCheckSchema = mongoose.Schema(
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Monitor",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
|
||||
status: {
|
||||
type: Boolean,
|
||||
index: true,
|
||||
},
|
||||
|
||||
responseTime: {
|
||||
type: Number,
|
||||
},
|
||||
|
||||
statusCode: {
|
||||
type: Number,
|
||||
index: true,
|
||||
},
|
||||
|
||||
message: {
|
||||
type: String,
|
||||
},
|
||||
expiry: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
expires: 60 * 60 * 24 * 30, // 30 days
|
||||
},
|
||||
cpu: {
|
||||
type: cpuSchema,
|
||||
default: () => ({}),
|
||||
|
||||
@@ -61,6 +61,9 @@ const MonitorSchema = mongoose.Schema(
|
||||
ref: "Notification",
|
||||
},
|
||||
],
|
||||
secret: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
|
||||
@@ -163,7 +163,6 @@ class JobQueue {
|
||||
// Get the current status
|
||||
const networkResponse = await this.networkService.getStatus(job);
|
||||
// Handle status change
|
||||
|
||||
const { monitor, statusChanged, prevStatus } =
|
||||
await this.statusService.updateStatus(networkResponse);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { errorMessages, successMessages } from "../utils/messages.js";
|
||||
|
||||
/**
|
||||
* Constructs a new NetworkService instance.
|
||||
*
|
||||
@@ -94,6 +93,7 @@ class NetworkService {
|
||||
* @param {Object} job.data - The data object within the job.
|
||||
* @param {string} job.data.url - The URL to send the HTTP GET request to.
|
||||
* @param {string} job.data._id - The monitor ID for the HTTP request.
|
||||
* @param {string} [job.data.secret] - Secret for authorization if provided.
|
||||
* @returns {Promise<Object>} An object containing the HTTP response details.
|
||||
* @property {string} monitorId - The monitor ID for the HTTP request.
|
||||
* @property {string} type - The type of request, which is "http".
|
||||
@@ -105,13 +105,18 @@ class NetworkService {
|
||||
*/
|
||||
async requestHttp(job) {
|
||||
const url = job.data.url;
|
||||
const config = {};
|
||||
|
||||
job.data.secret !== undefined &&
|
||||
(config.headers = { Authorization: `Bearer ${job.data.secret}` });
|
||||
|
||||
const { response, responseTime, error } = await this.timeRequest(() =>
|
||||
this.axios.get(url)
|
||||
this.axios.get(url, config)
|
||||
);
|
||||
|
||||
const httpResponse = {
|
||||
monitorId: job.data._id,
|
||||
type: "http",
|
||||
type: job.data.type,
|
||||
responseTime,
|
||||
payload: response?.data,
|
||||
};
|
||||
@@ -147,34 +152,15 @@ class NetworkService {
|
||||
*/
|
||||
async requestPagespeed(job) {
|
||||
const url = job.data.url;
|
||||
const { response, responseTime, error } = await this.timeRequest(() =>
|
||||
this.axios.get(
|
||||
`https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}&category=seo&category=accessibility&category=best-practices&category=performance`
|
||||
)
|
||||
);
|
||||
|
||||
const pagespeedResponse = {
|
||||
monitorId: job.data._id,
|
||||
type: "pagespeed",
|
||||
responseTime,
|
||||
payload: response?.data,
|
||||
};
|
||||
|
||||
if (error) {
|
||||
const code = error.response?.status || this.NETWORK_ERROR;
|
||||
pagespeedResponse.code = code;
|
||||
pagespeedResponse.status = false;
|
||||
pagespeedResponse.message = this.http.STATUS_CODES[code] || "Network Error";
|
||||
return pagespeedResponse;
|
||||
}
|
||||
|
||||
pagespeedResponse.status = true;
|
||||
pagespeedResponse.code = response.status;
|
||||
pagespeedResponse.message = this.http.STATUS_CODES[response.status];
|
||||
return pagespeedResponse;
|
||||
const updatedJob = { ...job };
|
||||
const pagespeedUrl = `https://pagespeedonline.googleapis.com/pagespeedonline/v5/runPagespeed?url=${url}&category=seo&category=accessibility&category=best-practices&category=performance`;
|
||||
updatedJob.data.url = pagespeedUrl;
|
||||
return this.requestHttp(updatedJob);
|
||||
}
|
||||
|
||||
async requestHandleHardware(job) {}
|
||||
async requestHardware(job) {
|
||||
return this.requestHttp(job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of a job based on its type and returns the appropriate response.
|
||||
@@ -194,7 +180,7 @@ class NetworkService {
|
||||
case this.TYPE_PAGESPEED:
|
||||
return await this.requestPagespeed(job);
|
||||
case this.TYPE_HARDWARE:
|
||||
return await this.requestHandleHardware(job);
|
||||
return await this.requestHardware(job);
|
||||
default:
|
||||
this.logger.error({
|
||||
message: `Unsupported type: ${job.data.type}`,
|
||||
|
||||
@@ -99,6 +99,13 @@ class StatusService {
|
||||
check.performance = (categories.performance?.score || 0) * 100;
|
||||
check.audits = { cls, si, fcp, lcp, tbt };
|
||||
}
|
||||
|
||||
if (type === "hardware") {
|
||||
check.cpu = payload?.cpu ?? {};
|
||||
check.memory = payload?.memory ?? {};
|
||||
check.disk = payload?.disk ?? {};
|
||||
check.host = payload?.host ?? {};
|
||||
}
|
||||
return check;
|
||||
};
|
||||
|
||||
@@ -121,6 +128,7 @@ class StatusService {
|
||||
http: this.db.createCheck,
|
||||
ping: this.db.createCheck,
|
||||
pagespeed: this.db.createPageSpeedCheck,
|
||||
hardware: this.db.createHardwareCheck,
|
||||
};
|
||||
const operation = operationMap[networkResponse.type];
|
||||
const check = this.buildCheck(networkResponse);
|
||||
@@ -130,7 +138,7 @@ class StatusService {
|
||||
message: error.message,
|
||||
service: this.SERVICE_NAME,
|
||||
method: "insertCheck",
|
||||
details: `Error inserting check for monitor: ${networkResponse.monitorId}`,
|
||||
details: `Error inserting check for monitor: ${networkResponse?.monitorId}`,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import sinon from "sinon";
|
||||
import NetworkService from "../../service/networkService.js";
|
||||
import { expect } from "chai";
|
||||
import http from "http";
|
||||
import exp from "constants";
|
||||
describe("Network Service", () => {
|
||||
let axios, ping, logger, networkService;
|
||||
|
||||
@@ -74,7 +73,7 @@ describe("Network Service", () => {
|
||||
});
|
||||
describe("requestHttp", () => {
|
||||
it("should return a response object if http successful", async () => {
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "http" } };
|
||||
const httpResult = await networkService.requestHttp(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("http");
|
||||
@@ -87,7 +86,7 @@ describe("Network Service", () => {
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "http" } };
|
||||
const httpResult = await networkService.requestHttp(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("http");
|
||||
@@ -101,7 +100,7 @@ describe("Network Service", () => {
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "http" } };
|
||||
const httpResult = await networkService.requestHttp(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("http");
|
||||
@@ -113,7 +112,7 @@ describe("Network Service", () => {
|
||||
|
||||
describe("requestPagespeed", () => {
|
||||
it("should return a response object if pagespeed successful", async () => {
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "pagespeed" } };
|
||||
const pagespeedResult = await networkService.requestPagespeed(job);
|
||||
expect(pagespeedResult.monitorId).to.equal("123");
|
||||
expect(pagespeedResult.type).to.equal("pagespeed");
|
||||
@@ -126,7 +125,7 @@ describe("Network Service", () => {
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "pagespeed" } };
|
||||
const pagespeedResult = await networkService.requestPagespeed(job);
|
||||
expect(pagespeedResult.monitorId).to.equal("123");
|
||||
expect(pagespeedResult.type).to.equal("pagespeed");
|
||||
@@ -140,7 +139,7 @@ describe("Network Service", () => {
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123" } };
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "pagespeed" } };
|
||||
const pagespeedResult = await networkService.requestPagespeed(job);
|
||||
expect(pagespeedResult.monitorId).to.equal("123");
|
||||
expect(pagespeedResult.type).to.equal("pagespeed");
|
||||
@@ -150,6 +149,60 @@ describe("Network Service", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("requestHardware", () => {
|
||||
it("should return a response object if hardware successful", async () => {
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "hardware" } };
|
||||
const httpResult = await networkService.requestHardware(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("hardware");
|
||||
expect(httpResult.responseTime).to.be.a("number");
|
||||
expect(httpResult.status).to.be.true;
|
||||
});
|
||||
it("should return a response object if hardware successful and job has a secret", async () => {
|
||||
const job = {
|
||||
data: {
|
||||
url: "http://test.com",
|
||||
_id: "123",
|
||||
type: "hardware",
|
||||
secret: "my_secret",
|
||||
},
|
||||
};
|
||||
const httpResult = await networkService.requestHardware(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("hardware");
|
||||
expect(httpResult.responseTime).to.be.a("number");
|
||||
expect(httpResult.status).to.be.true;
|
||||
});
|
||||
it("should return a response object if hardware unsuccessful", async () => {
|
||||
const error = new Error("Test error");
|
||||
error.response = { status: 404 };
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "hardware" } };
|
||||
const httpResult = await networkService.requestHardware(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("hardware");
|
||||
expect(httpResult.responseTime).to.be.a("number");
|
||||
expect(httpResult.status).to.be.false;
|
||||
expect(httpResult.code).to.equal(404);
|
||||
});
|
||||
it("should return a response object if hardware unsuccessful with unknown code", async () => {
|
||||
const error = new Error("Test error");
|
||||
error.response = {};
|
||||
networkService.timeRequest = sinon
|
||||
.stub()
|
||||
.resolves({ response: null, responseTime: 1, error });
|
||||
const job = { data: { url: "http://test.com", _id: "123", type: "hardware" } };
|
||||
const httpResult = await networkService.requestHardware(job);
|
||||
expect(httpResult.monitorId).to.equal("123");
|
||||
expect(httpResult.type).to.equal("hardware");
|
||||
expect(httpResult.responseTime).to.be.a("number");
|
||||
expect(httpResult.status).to.be.false;
|
||||
expect(httpResult.code).to.equal(networkService.NETWORK_ERROR);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getStatus", () => {
|
||||
beforeEach(() => {
|
||||
networkService.requestPing = sinon.stub();
|
||||
@@ -179,10 +232,10 @@ describe("Network Service", () => {
|
||||
expect(networkService.requestHttp.notCalled).to.be.true;
|
||||
expect(networkService.requestPagespeed.calledOnce).to.be.true;
|
||||
});
|
||||
it("should call requestHandleHardware if type is hardware", () => {
|
||||
it("should call requestHardware if type is hardware", () => {
|
||||
networkService.getStatus({ data: { type: "hardware" } });
|
||||
expect(networkService.requestHardware.calledOnce).to.be.true;
|
||||
expect(networkService.requestPing.notCalled).to.be.true;
|
||||
expect(networkService.requestHttp.notCalled).to.be.true;
|
||||
expect(networkService.requestPagespeed.notCalled).to.be.true;
|
||||
});
|
||||
it("should log an error if an unknown type is provided", () => {
|
||||
|
||||
@@ -173,6 +173,26 @@ describe("StatusService", () => {
|
||||
tbt: 0,
|
||||
});
|
||||
});
|
||||
it("should build a check for hardware type", () => {
|
||||
const check = statusService.buildCheck({
|
||||
monitorId: "test",
|
||||
type: "hardware",
|
||||
status: true,
|
||||
responseTime: 100,
|
||||
code: 200,
|
||||
message: "Test message",
|
||||
payload: { cpu: "cpu", memory: "memory", disk: "disk", host: "host" },
|
||||
});
|
||||
expect(check.monitorId).to.equal("test");
|
||||
expect(check.status).to.be.true;
|
||||
expect(check.statusCode).to.equal(200);
|
||||
expect(check.responseTime).to.equal(100);
|
||||
expect(check.message).to.equal("Test message");
|
||||
expect(check.cpu).to.equal("cpu");
|
||||
expect(check.memory).to.equal("memory");
|
||||
expect(check.disk).to.equal("disk");
|
||||
expect(check.host).to.equal("host");
|
||||
});
|
||||
});
|
||||
describe("insertCheck", () => {
|
||||
it("should log an error if one is thrown", async () => {
|
||||
|
||||
@@ -228,6 +228,7 @@ const createMonitorBodyValidation = joi.object({
|
||||
usage_disk: joi.number(),
|
||||
}),
|
||||
notifications: joi.array().items(joi.object()),
|
||||
secret: joi.string(),
|
||||
});
|
||||
|
||||
const editMonitorBodyValidation = joi.object({
|
||||
@@ -235,6 +236,7 @@ const editMonitorBodyValidation = joi.object({
|
||||
description: joi.string(),
|
||||
interval: joi.number(),
|
||||
notifications: joi.array().items(joi.object()),
|
||||
secret: joi.string(),
|
||||
});
|
||||
|
||||
const pauseMonitorParamValidation = joi.object({
|
||||
|
||||
Reference in New Issue
Block a user