Skip to content

Commit

Permalink
Merge pull request #997 from bluewave-labs/feat/be/create-hardware-mo…
Browse files Browse the repository at this point in the history
…nitor

feat/be/create-hardware-monitor, references #985
  • Loading branch information
ajhollid authored Oct 22, 2024
2 parents 9be1441 + 6f358d2 commit 78fcc2e
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Server/db/models/Monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const MonitorSchema = mongoose.Schema(
type: {
type: String,
required: true,
enum: ["http", "ping", "pagespeed"],
enum: ["http", "ping", "pagespeed", "hardware"],
},
url: {
type: String,
Expand Down
6 changes: 6 additions & 0 deletions Server/db/mongo/MongoDB.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ import {
deletePageSpeedChecksByMonitorId,
} from "./modules/pageSpeedCheckModule.js";

//****************************************
// Hardware Checks
//****************************************
import { createHardwareCheck } from "./modules/hardwareCheckModule.js";

//****************************************
// Checks
//****************************************
Expand Down Expand Up @@ -179,6 +184,7 @@ export default {
createPageSpeedCheck,
getPageSpeedChecks,
deletePageSpeedChecksByMonitorId,
createHardwareCheck,
createMaintenanceWindow,
getMaintenanceWindowsByTeamId,
getMaintenanceWindowById,
Expand Down
16 changes: 16 additions & 0 deletions Server/db/mongo/modules/hardwareCheckModule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import HardwareCheck from "../../models/HardwareCheck.js";
const SERVICE_NAME = "hardwareCheckModule";
const createHardwareCheck = async (hardwareCheckData) => {
try {
const hardwareCheck = await new HardwareCheck({
...hardwareCheckData,
}).save();
return hardwareCheck;
} catch (error) {
error.service = SERVICE_NAME;
error.method = "createHardwareCheck";
throw error;
}
};

export { createHardwareCheck };
82 changes: 82 additions & 0 deletions Server/service/networkService.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class NetworkService {
this.TYPE_PING = "ping";
this.TYPE_HTTP = "http";
this.TYPE_PAGESPEED = "pagespeed";
this.TYPE_HARDWARE = "hardware";
this.SERVICE_NAME = "NetworkService";
this.NETWORK_ERROR = 5000;
this.axios = axios;
Expand Down Expand Up @@ -293,6 +294,85 @@ class NetworkService {
}
}

async handleHardware(job) {
const url = job.data.url;
let isAlive;
//TODO Fetch hardware data
//For now, fake hardware data:

const hardwareData = {
monitorId: job.data._id,
cpu: {
physical_core: 1,
logical_core: 1,
frequency: 266,
temperature: null,
free_percent: null,
usage_percent: null,
},
memory: {
total_bytes: 4,
available_bytes: 4,
used_bytes: 2,
usage_percent: 0.5,
},
disk: [
{
read_speed_bytes: 3,
write_speed_bytes: 3,
total_bytes: 10,
free_bytes: 2,
usage_percent: 0.8,
},
],
host: {
os: "Linux",
platform: "Ubuntu",
kernel_version: "24.04",
},
};
try {
isAlive = true;
this.logAndStoreCheck(hardwareData, this.db.createHardwareCheck);
} catch (error) {
isAlive = false;
const nullData = {
monitorId: job.data._id,
cpu: {
physical_core: 0,
logical_core: 0,
frequency: 0,
temperature: 0,
free_percent: 0,
usage_percent: 0,
},
memory: {
total_bytes: 0,
available_bytes: 0,
used_bytes: 0,
usage_percent: 0,
},
disk: [
{
read_speed_bytes: 0,
write_speed_bytes: 0,
total_bytes: 0,
free_bytes: 0,
usage_percent: 0,
},
],
host: {
os: "",
platform: "",
kernel_version: "",
},
};
this.logAndStoreCheck(nullData, this.db.createHardwareCheck);
} finally {
this.handleStatusUpdate(job, isAlive);
}
}

/**
* Retrieves the status of a given job based on its type.
* For unsupported job types, it logs an error and returns false.
Expand All @@ -308,6 +388,8 @@ class NetworkService {
return await this.handleHttp(job);
case this.TYPE_PAGESPEED:
return await this.handlePagespeed(job);
case this.TYPE_HARDWARE:
return await this.handleHardware(job);
default:
this.logger.error(`Unsupported type: ${job.data.type}`, {
service: this.SERVICE_NAME,
Expand Down
111 changes: 111 additions & 0 deletions Server/tests/services/networkService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,105 @@ describe("networkService - handlePagespeed", () => {
});
});

describe("networkService - handleHardware", () => {
let dbMock,
axiosMock,
jobMock,
emailServiceMock,
pingMock,
loggerMock,
httpMock,
networkService,
logAndStoreCheckStub,
handleStatusUpdateStub;
beforeEach(() => {
jobMock = {
data: {
_id: "12345",
url: "http://example.com",
},
};
dbMock = { getMonitorById: sinon.stub() };
axiosMock = { get: sinon.stub() };

emailServiceMock = sinon.stub();
pingMock = { promise: { probe: sinon.stub() } };
loggerMock = { error: sinon.stub() };
httpMock = {
STATUS_CODES: {
200: "OK",
500: "Internal Server Error",
},
};
networkService = new NetworkService(
dbMock,
emailServiceMock,
axiosMock,
pingMock,
loggerMock,
httpMock
);
logAndStoreCheckStub = sinon.stub(networkService, "logAndStoreCheck").resolves();
handleStatusUpdateStub = sinon.stub(networkService, "handleStatusUpdate").resolves();
});

afterEach(() => {
sinon.restore();
});

it("should handle a successful Hardware response", async () => {
const responseMock = {
monitorId: jobMock.data._id,
cpu: {
physical_core: 1,
logical_core: 1,
frequency: 266,
temperature: null,
free_percent: null,
usage_percent: null,
},
memory: {
total_bytes: 4,
available_bytes: 4,
used_bytes: 2,
usage_percent: 0.5,
},
disk: [
{
read_speed_bytes: 3,
write_speed_bytes: 3,
total_bytes: 10,
free_bytes: 2,
usage_percent: 0.8,
},
],
host: {
os: "Linux",
platform: "Ubuntu",
kernel_version: "24.04",
},
};
axiosMock.get.resolves(responseMock);

await networkService.handleHardware(jobMock);
expect(networkService.logAndStoreCheck.calledOnce).to.be.true;
const hardwareData = networkService.logAndStoreCheck.getCall(0).args[0];
expect(hardwareData.cpu).to.include({
...responseMock.cpu,
});
expect(networkService.handleStatusUpdate.calledOnceWith(jobMock, true)).to.be.true;
});

it("should handle an error Hardware response", async () => {
logAndStoreCheckStub.throws(new Error("Hardware error"));
try {
await networkService.handleHardware(jobMock);
} catch (error) {
expect(error.message).to.equal("Hardware error");
}
});
});

describe("NetworkService - getStatus", () => {
let dbMock, emailServiceMock, axiosMock, pingMock, loggerMock, httpMock, networkService;

Expand Down Expand Up @@ -685,6 +784,18 @@ describe("NetworkService - getStatus", () => {
const result = await networkService.getStatus(job);
expect(result).to.be.false;
});
it("should return true if the job type is hardware and handleHardware is successful", async () => {
const job = { data: { type: networkService.TYPE_HARDWARE } };
sinon.stub(networkService, "handleHardware").resolves(true);
const result = await networkService.getStatus(job);
expect(result).to.be.true;
});
it("should return false if the job type is hardware and handleHardware is not successful", async () => {
const job = { data: { type: networkService.TYPE_HARDWARE } };
sinon.stub(networkService, "handleHardware").resolves(false);
const result = await networkService.getStatus(job);
expect(result).to.be.false;
});
it("should log an error and return false if the job type is unknown", async () => {
const job = { data: { type: "unknown" } };
const result = await networkService.getStatus(job);
Expand Down

0 comments on commit 78fcc2e

Please sign in to comment.