10 files changed
+103
-50
No files matched your search
@@ -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];
|
||||
};
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<MonitorType, "hardware" | "pagespeed">;
|
||||
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"
|
||||
|
||||
@@ -594,8 +594,8 @@ class NetworkService {
|
||||
* @async
|
||||
* @returns {Promise<AxiosResponse>} 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}`);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -33,7 +33,7 @@ export interface IChecksRepository {
|
||||
dateString: string,
|
||||
options?: { type?: MonitorType }
|
||||
): Promise<UptimeChecksResult | HardwareChecksResult | PageSpeedChecksResult>;
|
||||
findSummaryByTeamId(teamId: string): Promise<ChecksSummary>;
|
||||
findSummaryByTeamId(teamId: string, dateRange: string): Promise<ChecksSummary>;
|
||||
// update
|
||||
//delete
|
||||
deleteByMonitorId(monitorId: string): Promise<number>;
|
||||
|
||||
@@ -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<number> => {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user