add backend changes
This commit is contained in:
1 parent
5463542532
commit
155adf549e
17 files changed
+228
-643
No files matched your search
@@ -47,8 +47,6 @@ import { ParseBoolean } from "../utils/utils.js";
|
||||
|
||||
// Models
|
||||
import Check from "../db/models/Check.js";
|
||||
import HardwareCheck from "../db/models/HardwareCheck.js";
|
||||
import PageSpeedCheck from "../db/models/PageSpeedCheck.js";
|
||||
import Monitor from "../db/models/Monitor.js";
|
||||
import User from "../db/models/User.js";
|
||||
import InviteToken from "../db/models/InviteToken.js";
|
||||
@@ -56,7 +54,6 @@ import StatusPage from "../db/models/StatusPage.js";
|
||||
import Team from "../db/models/Team.js";
|
||||
import MaintenanceWindow from "../db/models/MaintenanceWindow.js";
|
||||
import MonitorStats from "../db/models/MonitorStats.js";
|
||||
import NetworkCheck from "../db/models/NetworkCheck.js";
|
||||
import Notification from "../db/models/Notification.js";
|
||||
import RecoveryToken from "../db/models/RecoveryToken.js";
|
||||
import AppSettings from "../db/models/AppSettings.js";
|
||||
@@ -65,12 +62,9 @@ import InviteModule from "../db/mongo/modules/inviteModule.js";
|
||||
import CheckModule from "../db/mongo/modules/checkModule.js";
|
||||
import StatusPageModule from "../db/mongo/modules/statusPageModule.js";
|
||||
import UserModule from "../db/mongo/modules/userModule.js";
|
||||
import HardwareCheckModule from "../db/mongo/modules/hardwareCheckModule.js";
|
||||
import MaintenanceWindowModule from "../db/mongo/modules/maintenanceWindowModule.js";
|
||||
import MonitorModule from "../db/mongo/modules/monitorModule.js";
|
||||
import NetworkCheckModule from "../db/mongo/modules/networkCheckModule.js";
|
||||
import NotificationModule from "../db/mongo/modules/notificationModule.js";
|
||||
import PageSpeedCheckModule from "../db/mongo/modules/pageSpeedCheckModule.js";
|
||||
import RecoveryModule from "../db/mongo/modules/recoveryModule.js";
|
||||
import SettingsModule from "../db/mongo/modules/settingsModule.js";
|
||||
|
||||
@@ -84,18 +78,15 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
||||
const stringService = new StringService(translationService);
|
||||
|
||||
// Create DB
|
||||
const checkModule = new CheckModule({ logger, Check, HardwareCheck, PageSpeedCheck, Monitor, User });
|
||||
const checkModule = new CheckModule({ logger, Check, Monitor, User });
|
||||
const inviteModule = new InviteModule({ InviteToken, crypto, stringService });
|
||||
const statusPageModule = new StatusPageModule({ StatusPage, NormalizeData, stringService });
|
||||
const userModule = new UserModule({ User, Team, GenerateAvatarImage, ParseBoolean, stringService });
|
||||
const hardwareCheckModule = new HardwareCheckModule({ HardwareCheck, Monitor, logger });
|
||||
const maintenanceWindowModule = new MaintenanceWindowModule({ MaintenanceWindow });
|
||||
const monitorModule = new MonitorModule({
|
||||
Monitor,
|
||||
MonitorStats,
|
||||
Check,
|
||||
PageSpeedCheck,
|
||||
HardwareCheck,
|
||||
stringService,
|
||||
fs,
|
||||
path,
|
||||
@@ -104,9 +95,7 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
||||
NormalizeData,
|
||||
NormalizeDataUptimeDetails,
|
||||
});
|
||||
const networkCheckModule = new NetworkCheckModule({ NetworkCheck });
|
||||
const notificationModule = new NotificationModule({ Notification, Monitor });
|
||||
const pageSpeedCheckModule = new PageSpeedCheckModule({ PageSpeedCheck });
|
||||
const recoveryModule = new RecoveryModule({ User, RecoveryToken, crypto, stringService });
|
||||
const settingsModule = new SettingsModule({ AppSettings });
|
||||
|
||||
@@ -117,12 +106,9 @@ export const initializeServices = async ({ logger, envSettings, settingsService
|
||||
inviteModule,
|
||||
statusPageModule,
|
||||
userModule,
|
||||
hardwareCheckModule,
|
||||
maintenanceWindowModule,
|
||||
monitorModule,
|
||||
networkCheckModule,
|
||||
notificationModule,
|
||||
pageSpeedCheckModule,
|
||||
recoveryModule,
|
||||
settingsModule,
|
||||
});
|
||||
|
||||
+166
-98
@@ -1,108 +1,176 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
const BaseCheckSchema = mongoose.Schema({
|
||||
/**
|
||||
* Reference to the associated Monitor document.
|
||||
*
|
||||
* @type {mongoose.Schema.Types.ObjectId}
|
||||
*/
|
||||
monitorId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Monitor",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
|
||||
teamId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Team",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
/**
|
||||
* Status of the check (true for up, false for down).
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
status: {
|
||||
type: Boolean,
|
||||
index: true,
|
||||
},
|
||||
/**
|
||||
* Response time of the check in milliseconds.
|
||||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
responseTime: {
|
||||
type: Number,
|
||||
},
|
||||
/**
|
||||
* Timings from Got.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
timings: {
|
||||
type: Object, // Accepts any object
|
||||
default: {},
|
||||
},
|
||||
/**
|
||||
* HTTP status code received during the check.
|
||||
*
|
||||
* @type {Number}
|
||||
*/
|
||||
statusCode: {
|
||||
type: Number,
|
||||
index: true,
|
||||
},
|
||||
/**
|
||||
* Message or description of the check result.
|
||||
*
|
||||
* @type {String}
|
||||
*/
|
||||
message: {
|
||||
type: String,
|
||||
},
|
||||
/**
|
||||
* Expiry date of the check, auto-calculated to expire after 30 days.
|
||||
*
|
||||
* @type {Date}
|
||||
*/
|
||||
|
||||
expiry: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
expires: 60 * 60 * 24 * 30, // 30 days
|
||||
},
|
||||
/**
|
||||
* Acknowledgment of the check.
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
ack: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* Resolution date of the check (when the check was resolved).
|
||||
*
|
||||
* @type {Date}
|
||||
*/
|
||||
ackAt: {
|
||||
type: Date,
|
||||
},
|
||||
const cpuSchema = mongoose.Schema({
|
||||
physical_core: { type: Number, default: 0 },
|
||||
logical_core: { type: Number, default: 0 },
|
||||
frequency: { type: Number, default: 0 },
|
||||
temperature: { type: [Number], default: [] },
|
||||
free_percent: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
/**
|
||||
* Check Schema for MongoDB collection.
|
||||
*
|
||||
* Represents a check associated with a monitor, storing information
|
||||
* about the status and response of a particular check event.
|
||||
*/
|
||||
const CheckSchema = mongoose.Schema({ ...BaseCheckSchema.obj }, { timestamps: true });
|
||||
const memorySchema = mongoose.Schema({
|
||||
total_bytes: { type: Number, default: 0 },
|
||||
available_bytes: { type: Number, default: 0 },
|
||||
used_bytes: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const diskSchema = mongoose.Schema({
|
||||
read_speed_bytes: { type: Number, default: 0 },
|
||||
write_speed_bytes: { type: Number, default: 0 },
|
||||
total_bytes: { type: Number, default: 0 },
|
||||
free_bytes: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const hostSchema = mongoose.Schema({
|
||||
os: { type: String, default: "" },
|
||||
platform: { type: String, default: "" },
|
||||
kernel_version: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const errorSchema = mongoose.Schema({
|
||||
metric: { type: [String], default: [] },
|
||||
err: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const captureSchema = mongoose.Schema({
|
||||
version: { type: String, default: "" },
|
||||
mode: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const networkInterfaceSchema = mongoose.Schema({
|
||||
name: { type: String },
|
||||
bytes_sent: { type: Number, default: 0 },
|
||||
bytes_recv: { type: Number, default: 0 },
|
||||
packets_sent: { type: Number, default: 0 },
|
||||
packets_recv: { type: Number, default: 0 },
|
||||
err_in: { type: Number, default: 0 },
|
||||
err_out: { type: Number, default: 0 },
|
||||
drop_in: { type: Number, default: 0 },
|
||||
drop_out: { type: Number, default: 0 },
|
||||
fifo_in: { type: Number, default: 0 },
|
||||
fifo_out: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const CheckSchema = new mongoose.Schema(
|
||||
{
|
||||
// Common fields
|
||||
monitorId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Monitor",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
|
||||
teamId: {
|
||||
type: mongoose.Schema.Types.ObjectId,
|
||||
ref: "Team",
|
||||
immutable: true,
|
||||
index: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: ["http", "hardware", "pagespeed", "distributed"],
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
|
||||
status: {
|
||||
type: Boolean,
|
||||
index: true,
|
||||
},
|
||||
|
||||
responseTime: {
|
||||
type: Number,
|
||||
},
|
||||
|
||||
timings: {
|
||||
type: Object,
|
||||
default: {},
|
||||
},
|
||||
|
||||
statusCode: {
|
||||
type: Number,
|
||||
index: true,
|
||||
},
|
||||
|
||||
message: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
expiry: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
expires: 60 * 60 * 24 * 30, // 30 days
|
||||
},
|
||||
|
||||
ack: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
ackAt: {
|
||||
type: Date,
|
||||
},
|
||||
|
||||
// Hardware fields
|
||||
cpu: {
|
||||
type: cpuSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
memory: {
|
||||
type: memorySchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
disk: {
|
||||
type: [diskSchema],
|
||||
default: () => [],
|
||||
},
|
||||
host: {
|
||||
type: hostSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
errors: {
|
||||
type: [errorSchema],
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
capture: {
|
||||
type: captureSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
net: {
|
||||
type: [networkInterfaceSchema],
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
// PageSpeed fields
|
||||
accessibility: {
|
||||
type: Number,
|
||||
},
|
||||
bestPractices: {
|
||||
type: Number,
|
||||
},
|
||||
seo: {
|
||||
type: Number,
|
||||
},
|
||||
performance: {
|
||||
type: Number,
|
||||
},
|
||||
audits: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
CheckSchema.index({ updatedAt: 1 });
|
||||
CheckSchema.index({ monitorId: 1, updatedAt: 1 });
|
||||
CheckSchema.index({ monitorId: 1, updatedAt: -1 });
|
||||
CheckSchema.index({ teamId: 1, updatedAt: -1 });
|
||||
|
||||
export default mongoose.model("Check", CheckSchema);
|
||||
export { BaseCheckSchema };
|
||||
@@ -1,100 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
import { BaseCheckSchema } from "./Check.js";
|
||||
const cpuSchema = mongoose.Schema({
|
||||
physical_core: { type: Number, default: 0 },
|
||||
logical_core: { type: Number, default: 0 },
|
||||
frequency: { type: Number, default: 0 },
|
||||
temperature: { type: [Number], default: [] },
|
||||
free_percent: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const memorySchema = mongoose.Schema({
|
||||
total_bytes: { type: Number, default: 0 },
|
||||
available_bytes: { type: Number, default: 0 },
|
||||
used_bytes: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const diskSchema = mongoose.Schema({
|
||||
read_speed_bytes: { type: Number, default: 0 },
|
||||
write_speed_bytes: { type: Number, default: 0 },
|
||||
total_bytes: { type: Number, default: 0 },
|
||||
free_bytes: { type: Number, default: 0 },
|
||||
usage_percent: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const hostSchema = mongoose.Schema({
|
||||
os: { type: String, default: "" },
|
||||
platform: { type: String, default: "" },
|
||||
kernel_version: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const errorSchema = mongoose.Schema({
|
||||
metric: { type: [String], default: [] },
|
||||
err: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const captureSchema = mongoose.Schema({
|
||||
version: { type: String, default: "" },
|
||||
mode: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const networkInterfaceSchema = mongoose.Schema({
|
||||
name: { type: String },
|
||||
bytes_sent: { type: Number, default: 0 },
|
||||
bytes_recv: { type: Number, default: 0 },
|
||||
packets_sent: { type: Number, default: 0 },
|
||||
packets_recv: { type: Number, default: 0 },
|
||||
err_in: { type: Number, default: 0 },
|
||||
err_out: { type: Number, default: 0 },
|
||||
drop_in: { type: Number, default: 0 },
|
||||
drop_out: { type: Number, default: 0 },
|
||||
fifo_in: { type: Number, default: 0 },
|
||||
fifo_out: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const HardwareCheckSchema = mongoose.Schema(
|
||||
{
|
||||
...BaseCheckSchema.obj,
|
||||
cpu: {
|
||||
type: cpuSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
memory: {
|
||||
type: memorySchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
disk: {
|
||||
type: [diskSchema],
|
||||
default: () => [],
|
||||
},
|
||||
host: {
|
||||
type: hostSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
errors: {
|
||||
type: [errorSchema],
|
||||
default: () => [],
|
||||
},
|
||||
|
||||
capture: {
|
||||
type: captureSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
|
||||
net: {
|
||||
type: [networkInterfaceSchema],
|
||||
default: () => [],
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
HardwareCheckSchema.index({ createdAt: 1 });
|
||||
HardwareCheckSchema.index({ monitorId: 1, createdAt: 1 });
|
||||
HardwareCheckSchema.index({ monitorId: 1, createdAt: -1 });
|
||||
|
||||
export default mongoose.model("HardwareCheck", HardwareCheckSchema);
|
||||
@@ -1,6 +1,4 @@
|
||||
import mongoose from "mongoose";
|
||||
import HardwareCheck from "./HardwareCheck.js";
|
||||
import PageSpeedCheck from "./PageSpeedCheck.js";
|
||||
import Check from "./Check.js";
|
||||
import MonitorStats from "./MonitorStats.js";
|
||||
import StatusPage from "./StatusPage.js";
|
||||
@@ -133,13 +131,7 @@ MonitorSchema.pre("findOneAndDelete", async function (next) {
|
||||
throw new Error("Monitor not found");
|
||||
}
|
||||
|
||||
if (doc?.type === "pagespeed") {
|
||||
await PageSpeedCheck.deleteMany({ monitorId: doc._id });
|
||||
} else if (doc?.type === "hardware") {
|
||||
await HardwareCheck.deleteMany({ monitorId: doc._id });
|
||||
} else {
|
||||
await Check.deleteMany({ monitorId: doc._id });
|
||||
}
|
||||
await Check.deleteMany({ monitorId: doc._id });
|
||||
|
||||
// Deal with status pages
|
||||
await StatusPage.updateMany({ monitors: doc?._id }, { $pull: { monitors: doc?._id } });
|
||||
@@ -156,13 +148,7 @@ MonitorSchema.pre("deleteMany", async function (next) {
|
||||
const monitors = await this.model.find(filter).select(["_id", "type"]).lean();
|
||||
|
||||
for (const monitor of monitors) {
|
||||
if (monitor.type === "pagespeed") {
|
||||
await PageSpeedCheck.deleteMany({ monitorId: monitor._id });
|
||||
} else if (monitor.type === "hardware") {
|
||||
await HardwareCheck.deleteMany({ monitorId: monitor._id });
|
||||
} else {
|
||||
await Check.deleteMany({ monitorId: monitor._id });
|
||||
}
|
||||
await Check.deleteMany({ monitorId: monitor._id });
|
||||
await StatusPage.updateMany({ monitors: monitor._id }, { $pull: { monitors: monitor._id } });
|
||||
await MonitorStats.deleteMany({ monitorId: monitor._id.toString() });
|
||||
}
|
||||
|
||||
@@ -40,10 +40,6 @@ const MonitorStatsSchema = new mongoose.Schema(
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
uptBurnt: {
|
||||
type: mongoose.Schema.Types.Decimal128,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
import { BaseCheckSchema } from "./Check.js";
|
||||
|
||||
const networkInterfaceSchema = mongoose.Schema({
|
||||
name: { type: String, required: true },
|
||||
bytes_sent: { type: Number, default: 0 },
|
||||
bytes_recv: { type: Number, default: 0 },
|
||||
packets_sent: { type: Number, default: 0 },
|
||||
packets_recv: { type: Number, default: 0 },
|
||||
err_in: { type: Number, default: 0 },
|
||||
err_out: { type: Number, default: 0 },
|
||||
drop_in: { type: Number, default: 0 },
|
||||
drop_out: { type: Number, default: 0 },
|
||||
fifo_in: { type: Number, default: 0 },
|
||||
fifo_out: { type: Number, default: 0 },
|
||||
});
|
||||
|
||||
const captureSchema = mongoose.Schema({
|
||||
version: { type: String, default: "" },
|
||||
mode: { type: String, default: "" },
|
||||
});
|
||||
|
||||
const NetworkCheckSchema = mongoose.Schema(
|
||||
{
|
||||
...BaseCheckSchema.obj,
|
||||
data: {
|
||||
type: [networkInterfaceSchema],
|
||||
default: () => [],
|
||||
},
|
||||
capture: {
|
||||
type: captureSchema,
|
||||
default: () => ({}),
|
||||
},
|
||||
errors: {
|
||||
type: mongoose.Schema.Types.Mixed,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
NetworkCheckSchema.index({ createdAt: 1 });
|
||||
NetworkCheckSchema.index({ monitorId: 1, createdAt: 1 });
|
||||
NetworkCheckSchema.index({ monitorId: 1, createdAt: -1 });
|
||||
|
||||
export default mongoose.model("NetworkCheck", NetworkCheckSchema);
|
||||
@@ -1,83 +0,0 @@
|
||||
import mongoose from "mongoose";
|
||||
import { BaseCheckSchema } from "./Check.js";
|
||||
const AuditSchema = mongoose.Schema({
|
||||
id: { type: String, required: true },
|
||||
title: { type: String, required: true },
|
||||
description: { type: String, required: true },
|
||||
score: { type: Number, required: true },
|
||||
scoreDisplayMode: { type: String, required: true },
|
||||
displayValue: { type: String, required: true },
|
||||
numericValue: { type: Number, required: true },
|
||||
numericUnit: { type: String, required: true },
|
||||
});
|
||||
|
||||
const AuditsSchema = mongoose.Schema({
|
||||
cls: {
|
||||
type: AuditSchema,
|
||||
required: true,
|
||||
},
|
||||
si: {
|
||||
type: AuditSchema,
|
||||
required: true,
|
||||
},
|
||||
fcp: {
|
||||
type: AuditSchema,
|
||||
required: true,
|
||||
},
|
||||
lcp: {
|
||||
type: AuditSchema,
|
||||
required: true,
|
||||
},
|
||||
tbt: {
|
||||
type: AuditSchema,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Mongoose schema for storing metrics from Google Lighthouse.
|
||||
* @typedef {Object} PageSpeedCheck
|
||||
* @property {mongoose.Schema.Types.ObjectId} monitorId - Reference to the Monitor model.
|
||||
* @property {number} accessibility - Accessibility score.
|
||||
* @property {number} bestPractices - Best practices score.
|
||||
* @property {number} seo - SEO score.
|
||||
* @property {number} performance - Performance score.
|
||||
*/
|
||||
|
||||
const PageSpeedCheck = mongoose.Schema(
|
||||
{
|
||||
...BaseCheckSchema.obj,
|
||||
accessibility: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
bestPractices: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
seo: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
performance: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
audits: {
|
||||
type: AuditsSchema,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
/**
|
||||
* Mongoose model for storing metrics from Google Lighthouse.
|
||||
* @typedef {mongoose.Model<PageSpeedCheck>} LighthouseMetricsModel
|
||||
*/
|
||||
|
||||
PageSpeedCheck.index({ createdAt: 1 });
|
||||
PageSpeedCheck.index({ monitorId: 1, createdAt: 1 });
|
||||
PageSpeedCheck.index({ monitorId: 1, createdAt: -1 });
|
||||
|
||||
export default mongoose.model("PageSpeedCheck", PageSpeedCheck);
|
||||
@@ -31,7 +31,7 @@ class CheckModule {
|
||||
}
|
||||
};
|
||||
|
||||
getChecksByMonitor = async ({ monitorId, type, sortOrder, dateRange, filter, ack, page, rowsPerPage, status }) => {
|
||||
getChecksByMonitor = async ({ monitorId, sortOrder, dateRange, filter, ack, page, rowsPerPage, status }) => {
|
||||
try {
|
||||
status = status === "true" ? true : status === "false" ? false : undefined;
|
||||
page = parseInt(page);
|
||||
@@ -79,19 +79,7 @@ class CheckModule {
|
||||
skip = page * rowsPerPage;
|
||||
}
|
||||
|
||||
const checkModels = {
|
||||
http: this.Check,
|
||||
ping: this.Check,
|
||||
docker: this.Check,
|
||||
port: this.Check,
|
||||
pagespeed: this.PageSpeedCheck,
|
||||
hardware: this.HardwareCheck,
|
||||
game: this.Check,
|
||||
};
|
||||
|
||||
const Model = checkModels[type];
|
||||
|
||||
const checks = await Model.aggregate([
|
||||
const checks = await this.Check.aggregate([
|
||||
{ $match: matchStage },
|
||||
{ $sort: { createdAt: sortOrder } },
|
||||
{
|
||||
@@ -166,18 +154,6 @@ class CheckModule {
|
||||
|
||||
const aggregatePipeline = [
|
||||
{ $match: matchStage },
|
||||
{
|
||||
$unionWith: {
|
||||
coll: "hardwarechecks",
|
||||
pipeline: [{ $match: matchStage }],
|
||||
},
|
||||
},
|
||||
{
|
||||
$unionWith: {
|
||||
coll: "pagespeedchecks",
|
||||
pipeline: [{ $match: matchStage }],
|
||||
},
|
||||
},
|
||||
|
||||
{ $sort: { createdAt: sortOrder } },
|
||||
{
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
const SERVICE_NAME = "hardwareCheckModule";
|
||||
|
||||
class HardwareCheckModule {
|
||||
constructor({ HardwareCheck, Monitor, logger }) {
|
||||
this.HardwareCheck = HardwareCheck;
|
||||
this.Monitor = Monitor;
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
createHardwareChecks = async (hardwareChecks) => {
|
||||
try {
|
||||
await this.HardwareCheck.insertMany(hardwareChecks, { ordered: false });
|
||||
return true;
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "createHardwareChecks";
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default HardwareCheckModule;
|
||||
@@ -11,25 +11,10 @@ import {
|
||||
const SERVICE_NAME = "monitorModule";
|
||||
|
||||
class MonitorModule {
|
||||
constructor({
|
||||
Monitor,
|
||||
MonitorStats,
|
||||
Check,
|
||||
PageSpeedCheck,
|
||||
HardwareCheck,
|
||||
stringService,
|
||||
fs,
|
||||
path,
|
||||
fileURLToPath,
|
||||
ObjectId,
|
||||
NormalizeData,
|
||||
NormalizeDataUptimeDetails,
|
||||
}) {
|
||||
constructor({ Monitor, MonitorStats, Check, stringService, fs, path, fileURLToPath, ObjectId, NormalizeData, NormalizeDataUptimeDetails }) {
|
||||
this.Monitor = Monitor;
|
||||
this.MonitorStats = MonitorStats;
|
||||
this.Check = Check;
|
||||
this.PageSpeedCheck = PageSpeedCheck;
|
||||
this.HardwareCheck = HardwareCheck;
|
||||
this.stringService = stringService;
|
||||
this.fs = fs;
|
||||
this.path = path;
|
||||
@@ -38,15 +23,6 @@ class MonitorModule {
|
||||
this.NormalizeData = NormalizeData;
|
||||
this.NormalizeDataUptimeDetails = NormalizeDataUptimeDetails;
|
||||
|
||||
this.CHECK_MODEL_LOOKUP = {
|
||||
http: Check,
|
||||
ping: Check,
|
||||
docker: Check,
|
||||
port: Check,
|
||||
pagespeed: PageSpeedCheck,
|
||||
hardware: HardwareCheck,
|
||||
};
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
@@ -146,19 +122,18 @@ class MonitorModule {
|
||||
};
|
||||
|
||||
//Helper
|
||||
getMonitorChecks = async (monitorId, model, dateRange, sortOrder) => {
|
||||
getMonitorChecks = async (monitorId, dateRange, sortOrder) => {
|
||||
const indexSpec = {
|
||||
monitorId: 1,
|
||||
createdAt: sortOrder, // This will be 1 or -1
|
||||
updatedAt: sortOrder, // This will be 1 or -1
|
||||
};
|
||||
|
||||
const [checksAll, checksForDateRange] = await Promise.all([
|
||||
model.find({ monitorId }).sort({ createdAt: sortOrder }).hint(indexSpec).lean(),
|
||||
model
|
||||
.find({
|
||||
monitorId,
|
||||
createdAt: { $gte: dateRange.start, $lte: dateRange.end },
|
||||
})
|
||||
this.Check.find({ monitorId }).sort({ createdAt: sortOrder }).hint(indexSpec).lean(),
|
||||
this.Check.find({
|
||||
monitorId,
|
||||
createdAt: { $gte: dateRange.start, $lte: dateRange.end },
|
||||
})
|
||||
.hint(indexSpec)
|
||||
.lean(),
|
||||
]);
|
||||
@@ -295,9 +270,8 @@ class MonitorModule {
|
||||
const sort = sortOrder === "asc" ? 1 : -1;
|
||||
|
||||
// Get Checks for monitor in date range requested
|
||||
const model = this.CHECK_MODEL_LOOKUP[monitor.type];
|
||||
const dates = this.getDateRange(dateRange);
|
||||
const { checksAll, checksForDateRange } = await this.getMonitorChecks(monitorId, model, dates, sort);
|
||||
const { checksAll, checksForDateRange } = await this.getMonitorChecks(monitorId, dates, sort);
|
||||
|
||||
// Build monitor stats
|
||||
const monitorStats = {
|
||||
@@ -339,7 +313,7 @@ class MonitorModule {
|
||||
};
|
||||
const dateString = formatLookup[dateRange];
|
||||
|
||||
const hardwareStats = await this.HardwareCheck.aggregate(buildHardwareDetailsPipeline(monitor, dates, dateString));
|
||||
const hardwareStats = await this.Check.aggregate(buildHardwareDetailsPipeline(monitor, dates, dateString));
|
||||
|
||||
const stats = hardwareStats[0];
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ const buildUptimeDetailsPipeline = (monitorId, dates, dateString) => {
|
||||
{
|
||||
$match: {
|
||||
monitorId: new ObjectId(monitorId),
|
||||
createdAt: { $gte: dates.start, $lte: dates.end },
|
||||
updatedAt: { $gte: dates.start, $lte: dates.end },
|
||||
},
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
createdAt: 1,
|
||||
updatedAt: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -173,6 +173,7 @@ const buildHardwareDetailsPipeline = (monitor, dates, dateString) => {
|
||||
{
|
||||
$match: {
|
||||
monitorId: monitor._id,
|
||||
type: "hardware",
|
||||
createdAt: { $gte: dates.start, $lte: dates.end },
|
||||
},
|
||||
},
|
||||
@@ -225,7 +226,7 @@ const buildHardwareDetailsPipeline = (monitor, dates, dateString) => {
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "hardwarechecks",
|
||||
from: "checks",
|
||||
let: {
|
||||
diskCount: "$diskCount",
|
||||
netCount: "$netCount",
|
||||
@@ -987,11 +988,6 @@ const buildMonitorsWithChecksByTeamIdPipeline = ({ matchStage, filter, page, row
|
||||
// Add checks
|
||||
if (limit) {
|
||||
let checksCollection = "checks";
|
||||
if (type === "pagespeed") {
|
||||
checksCollection = "pagespeedchecks";
|
||||
} else if (type === "hardware") {
|
||||
checksCollection = "hardwarechecks";
|
||||
}
|
||||
monitorsPipeline.push({
|
||||
$lookup: {
|
||||
from: checksCollection,
|
||||
@@ -1057,11 +1053,7 @@ const buildFilteredMonitorsByTeamIdPipeline = ({ matchStage, filter, page, rowsP
|
||||
// Add checks
|
||||
if (limit) {
|
||||
let checksCollection = "checks";
|
||||
if (type === "pagespeed") {
|
||||
checksCollection = "pagespeedchecks";
|
||||
} else if (type === "hardware") {
|
||||
checksCollection = "hardwarechecks";
|
||||
}
|
||||
|
||||
pipeline.push({
|
||||
$lookup: {
|
||||
from: checksCollection,
|
||||
@@ -1175,46 +1167,6 @@ const buildGetMonitorsByTeamIdPipeline = (req) => {
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(limit
|
||||
? [
|
||||
{
|
||||
$lookup: {
|
||||
from: "pagespeedchecks",
|
||||
let: { monitorId: "$_id" },
|
||||
pipeline: [
|
||||
{
|
||||
$match: {
|
||||
$expr: { $eq: ["$monitorId", "$$monitorId"] },
|
||||
},
|
||||
},
|
||||
{ $sort: { createdAt: -1 } },
|
||||
...(limit ? [{ $limit: limit }] : []),
|
||||
],
|
||||
as: "pagespeedchecks",
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(limit
|
||||
? [
|
||||
{
|
||||
$lookup: {
|
||||
from: "hardwarechecks",
|
||||
let: { monitorId: "$_id" },
|
||||
pipeline: [
|
||||
{
|
||||
$match: {
|
||||
$expr: { $eq: ["$monitorId", "$$monitorId"] },
|
||||
},
|
||||
},
|
||||
{ $sort: { createdAt: -1 } },
|
||||
...(limit ? [{ $limit: limit }] : []),
|
||||
],
|
||||
as: "hardwarechecks",
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
{
|
||||
$addFields: {
|
||||
@@ -1225,14 +1177,6 @@ const buildGetMonitorsByTeamIdPipeline = (req) => {
|
||||
case: { $in: ["$type", ["http", "ping", "docker", "port", "game"]] },
|
||||
then: "$standardchecks",
|
||||
},
|
||||
{
|
||||
case: { $eq: ["$type", "pagespeed"] },
|
||||
then: "$pagespeedchecks",
|
||||
},
|
||||
{
|
||||
case: { $eq: ["$type", "hardware"] },
|
||||
then: "$hardwarechecks",
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
},
|
||||
@@ -1242,8 +1186,6 @@ const buildGetMonitorsByTeamIdPipeline = (req) => {
|
||||
{
|
||||
$project: {
|
||||
standardchecks: 0,
|
||||
pagespeedchecks: 0,
|
||||
hardwarechecks: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
const SERVICE_NAME = "networkCheckModule";
|
||||
|
||||
class NetworkCheckModule {
|
||||
constructor({ NetworkCheck }) {
|
||||
this.NetworkCheck = NetworkCheck;
|
||||
}
|
||||
createNetworkCheck = async (networkCheckData) => {
|
||||
try {
|
||||
const networkCheck = await new this.NetworkCheck(networkCheckData);
|
||||
await networkCheck.save();
|
||||
return networkCheck;
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "createNetworkCheck";
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
getNetworkChecksByMonitorId = async (monitorId, limit = 100) => {
|
||||
try {
|
||||
const networkChecks = await this.NetworkCheck.find({ monitorId }).sort({ createdAt: -1 }).limit(limit);
|
||||
return networkChecks;
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "getNetworkChecksByMonitorId";
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default NetworkCheckModule;
|
||||
@@ -1,31 +0,0 @@
|
||||
// import PageSpeedCheck from "../../models/PageSpeedCheck.js";
|
||||
const SERVICE_NAME = "pageSpeedCheckModule";
|
||||
|
||||
class PageSpeedCheckModule {
|
||||
constructor({ PageSpeedCheck }) {
|
||||
this.PageSpeedCheck = PageSpeedCheck;
|
||||
}
|
||||
|
||||
createPageSpeedChecks = async (pageSpeedChecks) => {
|
||||
try {
|
||||
await this.PageSpeedCheck.insertMany(pageSpeedChecks, { ordered: false });
|
||||
return true;
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "createPageSpeedCheck";
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
deletePageSpeedChecksByMonitorId = async (monitorId) => {
|
||||
try {
|
||||
const result = await this.PageSpeedCheck.deleteMany({ monitorId });
|
||||
return result.deletedCount;
|
||||
} catch (error) {
|
||||
error.service = SERVICE_NAME;
|
||||
error.method = "deletePageSpeedChecksByMonitorId";
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
export default PageSpeedCheckModule;
|
||||
@@ -33,10 +33,9 @@ class CheckService {
|
||||
throw this.errorService.createAuthorizationError();
|
||||
}
|
||||
|
||||
let { type, sortOrder, dateRange, filter, ack, page, rowsPerPage, status } = query;
|
||||
let { sortOrder, dateRange, filter, ack, page, rowsPerPage, status } = query;
|
||||
const result = await this.db.checkModule.getChecksByMonitor({
|
||||
monitorId,
|
||||
type,
|
||||
sortOrder,
|
||||
dateRange,
|
||||
filter,
|
||||
|
||||
@@ -2,6 +2,16 @@ const SERVICE_NAME = "JobQueueHelper";
|
||||
|
||||
class SuperSimpleQueueHelper {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* db: import("../database").Database,
|
||||
* logger: import("../logger").Logger,
|
||||
* networkService: import("../networkService").NetworkService,
|
||||
* statusService: import("../statusService").StatusService,
|
||||
* notificationService: import("../notificationService").NotificationService
|
||||
* }}
|
||||
*/
|
||||
constructor({ db, logger, networkService, statusService, notificationService }) {
|
||||
this.db = db;
|
||||
this.logger = logger;
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
const SERVICE_NAME = "BufferService";
|
||||
const TYPE_MAP = {
|
||||
http: "checks",
|
||||
ping: "checks",
|
||||
port: "checks",
|
||||
docker: "checks",
|
||||
pagespeed: "pagespeedChecks",
|
||||
hardware: "hardwareChecks",
|
||||
game: "checks",
|
||||
};
|
||||
|
||||
class BufferService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
@@ -16,17 +7,7 @@ class BufferService {
|
||||
this.db = db;
|
||||
this.logger = logger;
|
||||
this.SERVICE_NAME = SERVICE_NAME;
|
||||
this.buffers = {
|
||||
checks: [],
|
||||
pagespeedChecks: [],
|
||||
hardwareChecks: [],
|
||||
};
|
||||
this.OPERATION_MAP = {
|
||||
checks: this.db.checkModule.createChecks,
|
||||
pagespeedChecks: this.db.pageSpeedCheckModule.createPageSpeedChecks,
|
||||
hardwareChecks: this.db.hardwareCheckModule.createHardwareChecks,
|
||||
};
|
||||
|
||||
this.buffer = [];
|
||||
this.scheduleNextFlush();
|
||||
this.logger.info({
|
||||
message: `Buffer service initialized, flushing every ${this.BUFFER_TIMEOUT / 1000}s`,
|
||||
@@ -39,9 +20,9 @@ class BufferService {
|
||||
return BufferService.SERVICE_NAME;
|
||||
}
|
||||
|
||||
addToBuffer({ check, type }) {
|
||||
addToBuffer({ check }) {
|
||||
try {
|
||||
this.buffers[TYPE_MAP[type]].push(check);
|
||||
this.buffer.push(check);
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
@@ -55,7 +36,7 @@ class BufferService {
|
||||
scheduleNextFlush() {
|
||||
this.bufferTimer = setTimeout(async () => {
|
||||
try {
|
||||
await this.flushBuffers();
|
||||
await this.flushBuffer();
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
message: `Error in flush cycle: ${error.message}`,
|
||||
@@ -69,35 +50,24 @@ class BufferService {
|
||||
}
|
||||
}, this.BUFFER_TIMEOUT);
|
||||
}
|
||||
async flushBuffers() {
|
||||
let items = 0;
|
||||
for (const [bufferName, buffer] of Object.entries(this.buffers)) {
|
||||
items += buffer.length;
|
||||
const operation = this.OPERATION_MAP[bufferName];
|
||||
if (!operation) {
|
||||
this.logger.error({
|
||||
message: `No operation found for ${bufferName}`,
|
||||
service: this.SERVICE_NAME,
|
||||
method: "flushBuffers",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await operation(buffer);
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
service: this.SERVICE_NAME,
|
||||
method: "flushBuffers",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
this.buffers[bufferName] = [];
|
||||
async flushBuffer() {
|
||||
let items = this.buffer.length;
|
||||
|
||||
try {
|
||||
await this.db.checkModule.createChecks(this.buffer);
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
service: this.SERVICE_NAME,
|
||||
method: "flushBuffer",
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
this.buffer = [];
|
||||
this.logger.debug({
|
||||
message: `Flushed ${items} items`,
|
||||
service: this.SERVICE_NAME,
|
||||
method: "flushBuffers",
|
||||
method: "flushBuffer",
|
||||
});
|
||||
items = 0;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import MonitorStats from "../../db/models/MonitorStats.js";
|
||||
import { safelyParseFloat } from "../../utils/dataUtils.js";
|
||||
const SERVICE_NAME = "StatusService";
|
||||
|
||||
class StatusService {
|
||||
static SERVICE_NAME = SERVICE_NAME;
|
||||
|
||||
/**
|
||||
* Creates an instance of StatusService.
|
||||
*
|
||||
* @param {Object} db - The database instance.
|
||||
* @param {Object} logger - The logger instance.
|
||||
*/
|
||||
constructor({ db, logger, buffer }) {
|
||||
* @param {{
|
||||
* buffer: import("./bufferService.js").BufferService
|
||||
* }}
|
||||
*/ constructor({ db, logger, buffer }) {
|
||||
this.db = db;
|
||||
this.logger = logger;
|
||||
this.buffer = buffer;
|
||||
@@ -24,7 +21,7 @@ class StatusService {
|
||||
async updateRunningStats({ monitor, networkResponse }) {
|
||||
try {
|
||||
const monitorId = monitor._id;
|
||||
const { responseTime, status, upt_burnt } = networkResponse;
|
||||
const { responseTime, status } = networkResponse;
|
||||
// Get stats
|
||||
let stats = await MonitorStats.findOne({ monitorId });
|
||||
if (!stats) {
|
||||
@@ -36,8 +33,6 @@ class StatusService {
|
||||
totalDownChecks: 0,
|
||||
uptimePercentage: 0,
|
||||
lastCheck: null,
|
||||
timeSInceLastCheck: 0,
|
||||
uptBurnt: 0,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -82,12 +77,6 @@ class StatusService {
|
||||
// latest check
|
||||
stats.lastCheckTimestamp = new Date().getTime();
|
||||
|
||||
// UPT burned
|
||||
if (typeof upt_burnt !== "undefined" && upt_burnt !== null) {
|
||||
const currentUptBurnt = safelyParseFloat(stats.uptBurnt);
|
||||
const newUptBurnt = safelyParseFloat(upt_burnt);
|
||||
stats.uptBurnt = currentUptBurnt + newUptBurnt;
|
||||
}
|
||||
await stats.save();
|
||||
return true;
|
||||
} catch (error) {
|
||||
@@ -119,7 +108,8 @@ class StatusService {
|
||||
* @returns {boolean} returnObject.prevStatus - The previous status of the monitor
|
||||
*/
|
||||
updateStatus = async (networkResponse) => {
|
||||
this.insertCheck(networkResponse);
|
||||
const check = this.buildCheck(networkResponse);
|
||||
await this.insertCheck(check);
|
||||
try {
|
||||
const { monitorId, status, code } = networkResponse;
|
||||
const monitor = await this.db.monitorModule.getMonitorById(monitorId);
|
||||
@@ -198,6 +188,7 @@ class StatusService {
|
||||
const check = {
|
||||
monitorId,
|
||||
teamId,
|
||||
type,
|
||||
status,
|
||||
statusCode: code,
|
||||
responseTime,
|
||||
@@ -264,25 +255,24 @@ class StatusService {
|
||||
* @param {Object} networkResponse.payload - The payload of the response.
|
||||
* @returns {Promise<void>} A promise that resolves when the check is inserted.
|
||||
*/
|
||||
insertCheck = async (networkResponse) => {
|
||||
insertCheck = async (check) => {
|
||||
try {
|
||||
const check = this.buildCheck(networkResponse);
|
||||
if (typeof check === "undefined") {
|
||||
this.logger.warn({
|
||||
message: "Failed to build check",
|
||||
service: this.SERVICE_NAME,
|
||||
method: "insertCheck",
|
||||
details: networkResponse,
|
||||
});
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
this.buffer.addToBuffer({ check, type: networkResponse.type });
|
||||
this.buffer.addToBuffer({ check });
|
||||
return true;
|
||||
} catch (error) {
|
||||
this.logger.error({
|
||||
message: error.message,
|
||||
service: error.service || this.SERVICE_NAME,
|
||||
method: error.method || "insertCheck",
|
||||
details: error.details || `Error inserting check for monitor: ${networkResponse?.monitorId}`,
|
||||
details: error.details || `Error inserting check for monitor: ${check?.monitorId}`,
|
||||
stack: error.stack,
|
||||
});
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user