diff --git a/Client/src/Pages/Uptime/Details/index.jsx b/Client/src/Pages/Uptime/Details/index.jsx
index 7a2aa6756..e161027fa 100644
--- a/Client/src/Pages/Uptime/Details/index.jsx
+++ b/Client/src/Pages/Uptime/Details/index.jsx
@@ -308,7 +308,9 @@ const DetailsPage = () => {
{hoveredUptimeData !== null
? hoveredUptimeData.totalChecks
- : (monitor.stats?.upChecksAggregate?.totalChecks ?? 0)}
+ : (monitor.stats?.upChecks?.reduce((count, checkGroup) => {
+ return count + checkGroup.totalChecks;
+ }, 0) ?? 0)}
{hoveredUptimeData !== null && hoveredUptimeData.time !== null && (
{
{hoveredIncidentsData !== null
? hoveredIncidentsData.totalChecks
- : (monitor.stats?.downChecksAggregate?.totalChecks ?? 0)}
+ : (monitor.stats?.downChecks?.reduce((count, checkGroup) => {
+ return count + checkGroup.totalChecks;
+ }, 0) ?? 0)}
{hoveredIncidentsData !== null &&
hoveredIncidentsData.time !== null && (
diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js
index 1143b9eeb..3a511eb12 100644
--- a/Server/db/mongo/modules/monitorModule.js
+++ b/Server/db/mongo/modules/monitorModule.js
@@ -8,7 +8,10 @@ import { NormalizeData, NormalizeDataUptimeDetails } from "../../../utils/dataUt
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
-
+import {
+ buildUptimeDetailsPipeline,
+ buildHardwareDetailsPipeline,
+} from "./monitorModuleQueries.js";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
@@ -336,272 +339,9 @@ const getUptimeDetailsById = async (req) => {
};
const dateString = formatLookup[dateRange];
- const monitorData = await Check.aggregate([
- {
- $match: {
- monitorId: monitor._id,
- },
- },
- {
- $sort: {
- createdAt: 1,
- },
- },
- {
- $facet: {
- aggregateData: [
- {
- $group: {
- _id: null,
- avgResponseTime: {
- $avg: "$responseTime",
- },
- firstCheck: {
- $first: "$$ROOT",
- },
- lastCheck: {
- $last: "$$ROOT",
- },
- totalChecks: {
- $sum: 1,
- },
- },
- },
- ],
- uptimeDuration: [
- {
- $match: {
- status: false,
- },
- },
- {
- $sort: {
- createdAt: 1,
- },
- },
- {
- $group: {
- _id: null,
- lastFalseCheck: {
- $last: "$$ROOT",
- },
- },
- },
- ],
- groupChecks: [
- {
- $match: {
- createdAt: { $gte: dates.start, $lte: dates.end },
- },
- },
- {
- $group: {
- _id: {
- $dateToString: {
- format: dateString,
- date: "$createdAt",
- },
- },
- avgResponseTime: {
- $avg: "$responseTime",
- },
- totalChecks: {
- $sum: 1,
- },
- },
- },
- {
- $sort: {
- _id: 1,
- },
- },
- ],
- groupAggregate: [
- {
- $match: {
- createdAt: { $gte: dates.start, $lte: dates.end },
- },
- },
- {
- $group: {
- _id: null,
- avgResponseTime: {
- $avg: "$responseTime",
- },
- },
- },
- ],
- upChecksAggregate: [
- {
- $match: {
- status: true,
- },
- },
- {
- $group: {
- _id: null,
- avgResponseTime: {
- $avg: "$responseTime",
- },
- totalChecks: {
- $sum: 1,
- },
- },
- },
- ],
- upChecks: [
- {
- $match: {
- status: true,
- createdAt: { $gte: dates.start, $lte: dates.end },
- },
- },
- {
- $group: {
- _id: {
- $dateToString: {
- format: dateString,
- date: "$createdAt",
- },
- },
- totalChecks: {
- $sum: 1,
- },
- avgResponseTime: {
- $avg: "$responseTime",
- },
- },
- },
- {
- $sort: { _id: 1 },
- },
- ],
- downChecksAggregate: [
- {
- $match: {
- status: false,
- },
- },
- {
- $group: {
- _id: null,
- avgResponseTime: {
- $avg: "$responseTime",
- },
- totalChecks: {
- $sum: 1,
- },
- },
- },
- ],
- downChecks: [
- {
- $match: {
- status: false,
- createdAt: { $gte: dates.start, $lte: dates.end },
- },
- },
- {
- $group: {
- _id: {
- $dateToString: {
- format: dateString,
- date: "$createdAt",
- },
- },
- totalChecks: {
- $sum: 1,
- },
- avgResponseTime: {
- $avg: "$responseTime",
- },
- },
- },
- {
- $sort: { _id: 1 },
- },
- ],
- },
- },
- {
- $project: {
- avgResponseTime: {
- $arrayElemAt: ["$aggregateData.avgResponseTime", 0],
- },
- totalChecks: {
- $arrayElemAt: ["$aggregateData.totalChecks", 0],
- },
- latestResponseTime: {
- $arrayElemAt: ["$aggregateData.lastCheck.responseTime", 0],
- },
- timeSinceLastCheck: {
- $let: {
- vars: {
- lastCheck: {
- $arrayElemAt: ["$aggregateData.lastCheck", 0],
- },
- },
- in: {
- $cond: [
- {
- $ifNull: ["$$lastCheck", false],
- },
- {
- $subtract: [new Date(), "$$lastCheck.createdAt"],
- },
- 0,
- ],
- },
- },
- },
- timeSinceLastFalseCheck: {
- $let: {
- vars: {
- lastFalseCheck: {
- $arrayElemAt: ["$uptimeDuration.lastFalseCheck", 0],
- },
- firstCheck: {
- $arrayElemAt: ["$aggregateData.firstCheck", 0],
- },
- },
- in: {
- $cond: [
- {
- $ifNull: ["$$lastFalseCheck", false],
- },
- {
- $subtract: [new Date(), "$$lastFalseCheck.createdAt"],
- },
- {
- $cond: [
- {
- $ifNull: ["$$firstCheck", false],
- },
- {
- $subtract: [new Date(), "$$firstCheck.createdAt"],
- },
- 0,
- ],
- },
- ],
- },
- },
- },
- groupChecks: "$groupChecks",
- groupAggregate: {
- $arrayElemAt: ["$groupAggregate", 0],
- },
- upChecksAggregate: {
- $arrayElemAt: ["$upChecksAggregate", 0],
- },
- upChecks: "$upChecks",
- downChecksAggregate: {
- $arrayElemAt: ["$downChecksAggregate", 0],
- },
- downChecks: "$downChecks",
- },
- },
- ]);
+ const monitorData = await Check.aggregate(
+ buildUptimeDetailsPipeline(monitor, dates, dateString)
+ );
const normalizedGroupChecks = NormalizeDataUptimeDetails(
monitorData[0].groupChecks,
@@ -715,261 +455,9 @@ const getHardwareDetailsById = async (req) => {
month: "%Y-%m-%dT00:00:00Z",
};
const dateString = formatLookup[dateRange];
- const hardwareStats = await HardwareCheck.aggregate([
- {
- $match: {
- monitorId: monitor._id,
- createdAt: { $gte: dates.start, $lte: dates.end },
- },
- },
- {
- $sort: {
- createdAt: 1,
- },
- },
- {
- $facet: {
- aggregateData: [
- {
- $group: {
- _id: null,
- latestCheck: {
- $last: "$$ROOT",
- },
- totalChecks: {
- $sum: 1,
- },
- },
- },
- ],
- upChecks: [
- {
- $match: {
- status: true,
- },
- },
- {
- $group: {
- _id: null,
- totalChecks: {
- $sum: 1,
- },
- },
- },
- ],
- checks: [
- {
- $limit: 1,
- },
- {
- $project: {
- diskCount: {
- $size: "$disk",
- },
- },
- },
- {
- $lookup: {
- from: "hardwarechecks",
- let: {
- diskCount: "$diskCount",
- },
- pipeline: [
- {
- $match: {
- $expr: {
- $and: [
- { $eq: ["$monitorId", monitor._id] },
- { $gte: ["$createdAt", dates.start] },
- { $lte: ["$createdAt", dates.end] },
- ],
- },
- },
- },
- {
- $group: {
- _id: {
- $dateToString: {
- format: dateString,
- date: "$createdAt",
- },
- },
- avgCpuUsage: {
- $avg: "$cpu.usage_percent",
- },
- avgMemoryUsage: {
- $avg: "$memory.usage_percent",
- },
- avgTemperatures: {
- $push: {
- $ifNull: ["$cpu.temperature", [0]],
- },
- },
- disks: {
- $push: "$disk",
- },
- },
- },
- {
- $project: {
- _id: 1,
- avgCpuUsage: 1,
- avgMemoryUsage: 1,
- avgTemperature: {
- $map: {
- input: {
- $range: [
- 0,
- {
- $size: {
- // Handle null temperatures array
- $ifNull: [
- { $arrayElemAt: ["$avgTemperatures", 0] },
- [0], // Default to single-element array if null
- ],
- },
- },
- ],
- },
- as: "index",
- in: {
- $avg: {
- $map: {
- input: "$avgTemperatures",
- as: "tempArray",
- in: {
- $ifNull: [
- { $arrayElemAt: ["$$tempArray", "$$index"] },
- 0, // Default to 0 if element is null
- ],
- },
- },
- },
- },
- },
- },
- disks: {
- $map: {
- input: {
- $range: [0, "$$diskCount"],
- },
- as: "diskIndex",
- in: {
- name: {
- $concat: [
- "disk",
- {
- $toString: "$$diskIndex",
- },
- ],
- },
- readSpeed: {
- $avg: {
- $map: {
- input: "$disks",
- as: "diskArray",
- in: {
- $arrayElemAt: [
- "$$diskArray.read_speed_bytes",
- "$$diskIndex",
- ],
- },
- },
- },
- },
- writeSpeed: {
- $avg: {
- $map: {
- input: "$disks",
- as: "diskArray",
- in: {
- $arrayElemAt: [
- "$$diskArray.write_speed_bytes",
- "$$diskIndex",
- ],
- },
- },
- },
- },
- totalBytes: {
- $avg: {
- $map: {
- input: "$disks",
- as: "diskArray",
- in: {
- $arrayElemAt: [
- "$$diskArray.total_bytes",
- "$$diskIndex",
- ],
- },
- },
- },
- },
- freeBytes: {
- $avg: {
- $map: {
- input: "$disks",
- as: "diskArray",
- in: {
- $arrayElemAt: [
- "$$diskArray.free_bytes",
- "$$diskIndex",
- ],
- },
- },
- },
- },
- usagePercent: {
- $avg: {
- $map: {
- input: "$disks",
- as: "diskArray",
- in: {
- $arrayElemAt: [
- "$$diskArray.usage_percent",
- "$$diskIndex",
- ],
- },
- },
- },
- },
- },
- },
- },
- },
- },
- ],
- as: "hourlyStats",
- },
- },
- {
- $unwind: "$hourlyStats",
- },
- {
- $replaceRoot: {
- newRoot: "$hourlyStats",
- },
- },
- ],
- },
- },
- {
- $project: {
- aggregateData: {
- $arrayElemAt: ["$aggregateData", 0],
- },
- upChecks: {
- $arrayElemAt: ["$upChecks", 0],
- },
- checks: {
- $sortArray: {
- input: "$checks",
- sortBy: { _id: 1 },
- },
- },
- },
- },
- ]);
+ const hardwareStats = await HardwareCheck.aggregate(
+ buildHardwareDetailsPipeline(monitor, dates, dateString)
+ );
const monitorStats = {
...monitor.toObject(),
diff --git a/Server/db/mongo/modules/monitorModuleQueries.js b/Server/db/mongo/modules/monitorModuleQueries.js
new file mode 100644
index 000000000..ccafbcbdc
--- /dev/null
+++ b/Server/db/mongo/modules/monitorModuleQueries.js
@@ -0,0 +1,525 @@
+const buildUptimeDetailsPipeline = (monitor, dates, dateString) => {
+ return [
+ {
+ $match: {
+ monitorId: monitor._id,
+ },
+ },
+ {
+ $sort: {
+ createdAt: 1,
+ },
+ },
+ {
+ $facet: {
+ aggregateData: [
+ {
+ $group: {
+ _id: null,
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ firstCheck: {
+ $first: "$$ROOT",
+ },
+ lastCheck: {
+ $last: "$$ROOT",
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ ],
+ uptimeDuration: [
+ {
+ $match: {
+ status: false,
+ },
+ },
+ {
+ $sort: {
+ createdAt: 1,
+ },
+ },
+ {
+ $group: {
+ _id: null,
+ lastFalseCheck: {
+ $last: "$$ROOT",
+ },
+ },
+ },
+ ],
+ groupChecks: [
+ {
+ $match: {
+ createdAt: { $gte: dates.start, $lte: dates.end },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ $dateToString: {
+ format: dateString,
+ date: "$createdAt",
+ },
+ },
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ {
+ $sort: {
+ _id: 1,
+ },
+ },
+ ],
+ groupAggregate: [
+ {
+ $match: {
+ createdAt: { $gte: dates.start, $lte: dates.end },
+ },
+ },
+ {
+ $group: {
+ _id: null,
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ },
+ },
+ ],
+ upChecksAggregate: [
+ {
+ $match: {
+ status: true,
+ },
+ },
+ {
+ $group: {
+ _id: null,
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ ],
+ upChecks: [
+ {
+ $match: {
+ status: true,
+ createdAt: { $gte: dates.start, $lte: dates.end },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ $dateToString: {
+ format: dateString,
+ date: "$createdAt",
+ },
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ },
+ },
+ {
+ $sort: { _id: 1 },
+ },
+ ],
+ downChecksAggregate: [
+ {
+ $match: {
+ status: false,
+ },
+ },
+ {
+ $group: {
+ _id: null,
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ ],
+ downChecks: [
+ {
+ $match: {
+ status: false,
+ createdAt: { $gte: dates.start, $lte: dates.end },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ $dateToString: {
+ format: dateString,
+ date: "$createdAt",
+ },
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ avgResponseTime: {
+ $avg: "$responseTime",
+ },
+ },
+ },
+ {
+ $sort: { _id: 1 },
+ },
+ ],
+ },
+ },
+ {
+ $project: {
+ avgResponseTime: {
+ $arrayElemAt: ["$aggregateData.avgResponseTime", 0],
+ },
+ totalChecks: {
+ $arrayElemAt: ["$aggregateData.totalChecks", 0],
+ },
+ latestResponseTime: {
+ $arrayElemAt: ["$aggregateData.lastCheck.responseTime", 0],
+ },
+ timeSinceLastCheck: {
+ $let: {
+ vars: {
+ lastCheck: {
+ $arrayElemAt: ["$aggregateData.lastCheck", 0],
+ },
+ },
+ in: {
+ $cond: [
+ {
+ $ifNull: ["$$lastCheck", false],
+ },
+ {
+ $subtract: [new Date(), "$$lastCheck.createdAt"],
+ },
+ 0,
+ ],
+ },
+ },
+ },
+ timeSinceLastFalseCheck: {
+ $let: {
+ vars: {
+ lastFalseCheck: {
+ $arrayElemAt: ["$uptimeDuration.lastFalseCheck", 0],
+ },
+ firstCheck: {
+ $arrayElemAt: ["$aggregateData.firstCheck", 0],
+ },
+ },
+ in: {
+ $cond: [
+ {
+ $ifNull: ["$$lastFalseCheck", false],
+ },
+ {
+ $subtract: [new Date(), "$$lastFalseCheck.createdAt"],
+ },
+ {
+ $cond: [
+ {
+ $ifNull: ["$$firstCheck", false],
+ },
+ {
+ $subtract: [new Date(), "$$firstCheck.createdAt"],
+ },
+ 0,
+ ],
+ },
+ ],
+ },
+ },
+ },
+ groupChecks: "$groupChecks",
+ groupAggregate: {
+ $arrayElemAt: ["$groupAggregate", 0],
+ },
+ upChecksAggregate: {
+ $arrayElemAt: ["$upChecksAggregate", 0],
+ },
+ upChecks: "$upChecks",
+ downChecksAggregate: {
+ $arrayElemAt: ["$downChecksAggregate", 0],
+ },
+ downChecks: "$downChecks",
+ },
+ },
+ ];
+};
+
+const buildHardwareDetailsPipeline = (monitor, dates, dateString) => {
+ return [
+ {
+ $match: {
+ monitorId: monitor._id,
+ createdAt: { $gte: dates.start, $lte: dates.end },
+ },
+ },
+ {
+ $sort: {
+ createdAt: 1,
+ },
+ },
+ {
+ $facet: {
+ aggregateData: [
+ {
+ $group: {
+ _id: null,
+ latestCheck: {
+ $last: "$$ROOT",
+ },
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ ],
+ upChecks: [
+ {
+ $match: {
+ status: true,
+ },
+ },
+ {
+ $group: {
+ _id: null,
+ totalChecks: {
+ $sum: 1,
+ },
+ },
+ },
+ ],
+ checks: [
+ {
+ $limit: 1,
+ },
+ {
+ $project: {
+ diskCount: {
+ $size: "$disk",
+ },
+ },
+ },
+ {
+ $lookup: {
+ from: "hardwarechecks",
+ let: {
+ diskCount: "$diskCount",
+ },
+ pipeline: [
+ {
+ $match: {
+ $expr: {
+ $and: [
+ { $eq: ["$monitorId", monitor._id] },
+ { $gte: ["$createdAt", dates.start] },
+ { $lte: ["$createdAt", dates.end] },
+ ],
+ },
+ },
+ },
+ {
+ $group: {
+ _id: {
+ $dateToString: {
+ format: dateString,
+ date: "$createdAt",
+ },
+ },
+ avgCpuUsage: {
+ $avg: "$cpu.usage_percent",
+ },
+ avgMemoryUsage: {
+ $avg: "$memory.usage_percent",
+ },
+ avgTemperatures: {
+ $push: {
+ $ifNull: ["$cpu.temperature", [0]],
+ },
+ },
+ disks: {
+ $push: "$disk",
+ },
+ },
+ },
+ {
+ $project: {
+ _id: 1,
+ avgCpuUsage: 1,
+ avgMemoryUsage: 1,
+ avgTemperature: {
+ $map: {
+ input: {
+ $range: [
+ 0,
+ {
+ $size: {
+ // Handle null temperatures array
+ $ifNull: [
+ { $arrayElemAt: ["$avgTemperatures", 0] },
+ [0], // Default to single-element array if null
+ ],
+ },
+ },
+ ],
+ },
+ as: "index",
+ in: {
+ $avg: {
+ $map: {
+ input: "$avgTemperatures",
+ as: "tempArray",
+ in: {
+ $ifNull: [
+ { $arrayElemAt: ["$$tempArray", "$$index"] },
+ 0, // Default to 0 if element is null
+ ],
+ },
+ },
+ },
+ },
+ },
+ },
+ disks: {
+ $map: {
+ input: {
+ $range: [0, "$$diskCount"],
+ },
+ as: "diskIndex",
+ in: {
+ name: {
+ $concat: [
+ "disk",
+ {
+ $toString: "$$diskIndex",
+ },
+ ],
+ },
+ readSpeed: {
+ $avg: {
+ $map: {
+ input: "$disks",
+ as: "diskArray",
+ in: {
+ $arrayElemAt: [
+ "$$diskArray.read_speed_bytes",
+ "$$diskIndex",
+ ],
+ },
+ },
+ },
+ },
+ writeSpeed: {
+ $avg: {
+ $map: {
+ input: "$disks",
+ as: "diskArray",
+ in: {
+ $arrayElemAt: [
+ "$$diskArray.write_speed_bytes",
+ "$$diskIndex",
+ ],
+ },
+ },
+ },
+ },
+ totalBytes: {
+ $avg: {
+ $map: {
+ input: "$disks",
+ as: "diskArray",
+ in: {
+ $arrayElemAt: [
+ "$$diskArray.total_bytes",
+ "$$diskIndex",
+ ],
+ },
+ },
+ },
+ },
+ freeBytes: {
+ $avg: {
+ $map: {
+ input: "$disks",
+ as: "diskArray",
+ in: {
+ $arrayElemAt: ["$$diskArray.free_bytes", "$$diskIndex"],
+ },
+ },
+ },
+ },
+ usagePercent: {
+ $avg: {
+ $map: {
+ input: "$disks",
+ as: "diskArray",
+ in: {
+ $arrayElemAt: [
+ "$$diskArray.usage_percent",
+ "$$diskIndex",
+ ],
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ ],
+ as: "hourlyStats",
+ },
+ },
+ {
+ $unwind: "$hourlyStats",
+ },
+ {
+ $replaceRoot: {
+ newRoot: "$hourlyStats",
+ },
+ },
+ ],
+ },
+ },
+ {
+ $project: {
+ aggregateData: {
+ $arrayElemAt: ["$aggregateData", 0],
+ },
+ upChecks: {
+ $arrayElemAt: ["$upChecks", 0],
+ },
+ checks: {
+ $sortArray: {
+ input: "$checks",
+ sortBy: { _id: 1 },
+ },
+ },
+ },
+ },
+ ];
+};
+
+export { buildUptimeDetailsPipeline, buildHardwareDetailsPipeline };