diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index 49a9b6ba3..2d7edd677 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -137,7 +137,7 @@ const useFetchChecksByMonitor = ({ return [checks, checksCount, isLoading, networkError]; }; -const useFetchChecksSummaryByTeamId = ({ updateTrigger } = {}) => { +const useFetchChecksSummaryByTeamId = ({ dateRange, updateTrigger } = {}) => { const [summary, setSummary] = useState(undefined); const [isLoading, setIsLoading] = useState(false); const [networkError, setNetworkError] = useState(false); @@ -147,7 +147,7 @@ const useFetchChecksSummaryByTeamId = ({ updateTrigger } = {}) => { try { setIsLoading(true); - const res = await networkService.getChecksAndSummaryByTeamId(); + const res = await networkService.getChecksAndSummaryByTeamId({ dateRange }); setSummary(res.data.data); } catch (error) { setNetworkError(true); @@ -158,7 +158,7 @@ const useFetchChecksSummaryByTeamId = ({ updateTrigger } = {}) => { }; fetchSummary(); - }, [updateTrigger]); + }, [dateRange, updateTrigger]); return [summary, isLoading, networkError]; }; diff --git a/client/src/Pages/Checks/Components/IncidentTable/index.jsx b/client/src/Pages/Checks/Components/IncidentTable/index.jsx index 857f31bff..bac2a00cb 100644 --- a/client/src/Pages/Checks/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Checks/Components/IncidentTable/index.jsx @@ -19,7 +19,7 @@ import { useState } from "react"; import PropTypes from "prop-types"; import { useTranslation } from "react-i18next"; import { useFetchChecksTeam, useFetchChecksByMonitor } from "@/Hooks/checkHooks.js"; -import { Button, Typography, useTheme } from "@mui/material"; +import { Typography, useTheme } from "@mui/material"; import { lighten } from "@mui/material/styles"; const GetTooltip = (row) => { diff --git a/client/src/Pages/Checks/index.jsx b/client/src/Pages/Checks/index.jsx index aa8717c1a..bcd036a58 100644 --- a/client/src/Pages/Checks/index.jsx +++ b/client/src/Pages/Checks/index.jsx @@ -5,7 +5,6 @@ import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; import IncidentTable from "./Components/IncidentTable/index.jsx"; import OptionsHeader from "./Components/OptionsHeader/index.jsx"; import StatusBoxes from "./Components/StatusBoxes/index.jsx"; -import { Box, Button } from "@mui/material"; //Utils import { useTheme } from "@emotion/react"; @@ -26,7 +25,7 @@ const Checks = () => { // Local state const [selectedMonitor, setSelectedMonitor] = useState("0"); const [filter, setFilter] = useState(undefined); - const [dateRange, setDateRange] = useState(undefined); + const [dateRange, setDateRange] = useState("hour"); const [monitorLookup, setMonitorLookup] = useState(undefined); const [updateTrigger, setUpdateTrigger] = useState(false); @@ -36,6 +35,7 @@ const Checks = () => { const theme = useTheme(); const [monitors, , isLoading, networkError] = useFetchMonitorsByTeamId({}); const [summary, isLoadingSummary, networkErrorSummary] = useFetchChecksSummaryByTeamId({ + dateRange, updateTrigger, }); const { monitorId } = useParams(); diff --git a/client/src/Types/Check.ts b/client/src/Types/Check.ts index 09f851e3b..05063291f 100644 --- a/client/src/Types/Check.ts +++ b/client/src/Types/Check.ts @@ -154,6 +154,79 @@ export interface ChecksResponse { checksCount: number; } +export type MonitorType = + | "http" + | "ping" + | "pagespeed" + | "hardware" + | "docker" + | "port" + | "game" + | "unknown"; + +export interface ChecksQueryResult { + checksCount: number; + checks: Check[]; +} + +export interface PageSpeedChecksResult { + monitorType: "pagespeed"; + checks: Check[]; +} + +export interface HardwareChecksResult { + monitorType: "hardware"; + aggregateData: { + totalChecks: number; + }; + upChecks: { + totalChecks: number; + }; + checks: Array<{ + _id: string; + avgCpuUsage: number; + avgMemoryUsage: number; + avgTemperature: number[]; + disks: Array<{ + name: string; + readSpeed: number; + writeSpeed: number; + totalBytes: number; + freeBytes: number; + usagePercent: number; + }>; + net: Array<{ + name: string; + bytesSentPerSecond: number; + deltaBytesRecv: number; + deltaPacketsSent: number; + deltaPacketsRecv: number; + deltaErrIn: number; + deltaErrOut: number; + deltaDropIn: number; + deltaDropOut: number; + deltaFifoIn: number; + deltaFifoOut: number; + }>; + }>; +} + +export interface UptimeChecksResult { + monitorType: Exclude; + groupedChecks: GroupedCheck[]; + groupedUpChecks: GroupedCheck[]; + groupedDownChecks: GroupedCheck[]; + uptimePercentage: number; + avgResponseTime: number; +} + +export interface ChecksSummary { + totalChecks: number; + resolvedChecks: number; + downChecks: number; + cannotResolveChecks: number; +} + export type CheckSnapshot = Omit< Check, "metadata" | "ack" | "ackAt" | "expiry" | "__v" | "updatedAt" diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index 4a096badd..f703b1043 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -594,8 +594,8 @@ class NetworkService { * @async * @returns {Promise} The response from the axios GET request. */ - getChecksAndSummaryByTeamId = async () => { - return this.axiosInstance.get(`/checks/team/summary`); + getChecksAndSummaryByTeamId = async ({ dateRange }) => { + return this.axiosInstance.get(`/checks/team/summary?dateRange=${dateRange}`); }; /** diff --git a/server/scripts/generate-checks.js b/server/scripts/generate-checks.js index d3a33b033..544770bb6 100644 --- a/server/scripts/generate-checks.js +++ b/server/scripts/generate-checks.js @@ -54,8 +54,8 @@ async function ensureMonitor({ monitorId, teamId, userId, type }) { async function run() { const mongoUri = process.env.MONGO_URI ?? "mongodb://localhost:27017/uptime_db"; const monitorId = parseObjectId(process.env.MONITOR_ID ?? DEFAULT_MONITOR_ID, DEFAULT_MONITOR_ID); - const teamId = parseObjectId("69648b0578209af45f9ffe30"); - const userId = parseObjectId("69648b0678209af45f9ffe32"); + const teamId = parseObjectId("6971546de1b2bc3de6498e6e"); + const userId = parseObjectId("6971546de1b2bc3de6498e70"); const monitorType = process.env.MONITOR_TYPE ?? DEFAULT_MONITOR_TYPE; const total = Number(process.env.CHECK_TOTAL ?? DEFAULT_TOTAL); const batchSize = Number(process.env.CHECK_BATCH_SIZE ?? DEFAULT_BATCH_SIZE); diff --git a/server/src/controllers/checkController.ts b/server/src/controllers/checkController.ts index 8277df3e7..b13663d97 100755 --- a/server/src/controllers/checkController.ts +++ b/server/src/controllers/checkController.ts @@ -66,7 +66,8 @@ class CheckController { getChecksSummaryByTeamId = async (req: Request, res: Response, next: NextFunction) => { try { - const summary = await this.checkService.getChecksSummaryByTeamId({ teamId: req?.user?.teamId }); + const dateRange = req.query?.dateRange || "hour"; + const summary = await this.checkService.getChecksSummaryByTeamId({ teamId: req?.user?.teamId, dateRange }); return res.status(200).json({ success: true, msg: "Checks summary retrieved successfully", diff --git a/server/src/repositories/checks/IChecksRepository.ts b/server/src/repositories/checks/IChecksRepository.ts index ab5dc6ce5..74def03c2 100644 --- a/server/src/repositories/checks/IChecksRepository.ts +++ b/server/src/repositories/checks/IChecksRepository.ts @@ -33,7 +33,7 @@ export interface IChecksRepository { dateString: string, options?: { type?: MonitorType } ): Promise; - findSummaryByTeamId(teamId: string): Promise; + findSummaryByTeamId(teamId: string, dateRange: string): Promise; // update //delete deleteByMonitorId(monitorId: string): Promise; diff --git a/server/src/repositories/checks/MongoChecksRepistory.ts b/server/src/repositories/checks/MongoChecksRepistory.ts index 16f00778a..a6814fbf3 100644 --- a/server/src/repositories/checks/MongoChecksRepistory.ts +++ b/server/src/repositories/checks/MongoChecksRepistory.ts @@ -365,51 +365,30 @@ class MongoChecksRepository implements IChecksRepository { return this.findUptimeDateRangeChecks(options?.type ?? "http", monitorObjectId, startDate, endDate, dateString); }; - findSummaryByTeamId = async (teamId: string) => { + findSummaryByTeamId = async (teamId: string, dateRange: string) => { const matchStage = { "metadata.teamId": new mongoose.Types.ObjectId(teamId), + status: false, + ...(dateRangeLookup[dateRange] && { + createdAt: { + $gte: dateRangeLookup[dateRange], + }, + }), }; const checks = await CheckModel.aggregate([ { $match: matchStage }, { - $facet: { - summary: [ - { - $group: { - _id: null, - totalChecks: { $sum: { $cond: [{ $eq: ["$status", false] }, 1, 0] } }, - resolvedChecks: { - $sum: { - $cond: [{ $and: [{ $eq: ["$ack", true] }, { $eq: ["$status", false] }] }, 1, 0], - }, - }, - downChecks: { - $sum: { - $cond: [{ $and: [{ $eq: ["$ack", false] }, { $eq: ["$status", false] }] }, 1, 0], - }, - }, - cannotResolveChecks: { - $sum: { - $cond: [{ $eq: ["$statusCode", 5000] }, 1, 0], - }, - }, - }, - }, - { - $project: { - _id: 0, - }, - }, - ], - }, - }, - { - $project: { - summary: { $arrayElemAt: ["$summary", 0] }, + $group: { + _id: null, + totalChecks: { $sum: 1 }, + resolvedChecks: { $sum: { $cond: [{ $eq: ["$ack", true] }, 1, 0] } }, + downChecks: { $sum: { $cond: [{ $eq: ["$ack", false] }, 1, 0] } }, + cannotResolveChecks: { $sum: { $cond: [{ $eq: ["$statusCode", 5000] }, 1, 0] } }, }, }, + { $project: { _id: 0 } }, ]); - return checks[0].summary; + return checks[0] ?? { totalChecks: 0, resolvedChecks: 0, downChecks: 0, cannotResolveChecks: 0 }; }; deleteByMonitorId = async (monitorId: string): Promise => { diff --git a/server/src/service/business/checkService.ts b/server/src/service/business/checkService.ts index bd4684f11..5564d1d7f 100644 --- a/server/src/service/business/checkService.ts +++ b/server/src/service/business/checkService.ts @@ -145,11 +145,11 @@ class CheckService { return checkData; }; - getChecksSummaryByTeamId = async ({ teamId }: { teamId: string }) => { + getChecksSummaryByTeamId = async ({ teamId, dateRange }: { teamId: string; dateRange: string }) => { if (!teamId) { throw new AppError({ message: "No team ID in request", service: SERVICE_NAME, method: "getChecksSummaryByTeamId", status: 400 }); } - const summary = await this.checksRepository.findSummaryByTeamId(teamId); + const summary = await this.checksRepository.findSummaryByTeamId(teamId, dateRange); return summary; };