From 2a1afc8610d8ecf7391ff98c413b30b8e7537983 Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Wed, 4 Sep 2024 19:17:12 -0400 Subject: [PATCH] Implemented basic gauge chart --- .../Charts/MonitorDetails60MinChart/index.jsx | 53 ----------- .../Pages/Monitors/Details/Charts/index.jsx | 90 ++++++++++++++++++- Client/src/Pages/Monitors/Details/index.jsx | 9 +- Client/src/Pages/Monitors/Details/styled.jsx | 1 - Server/db/mongo/modules/monitorModule.js | 19 +++- 5 files changed, 109 insertions(+), 63 deletions(-) delete mode 100644 Client/src/Components/Charts/MonitorDetails60MinChart/index.jsx diff --git a/Client/src/Components/Charts/MonitorDetails60MinChart/index.jsx b/Client/src/Components/Charts/MonitorDetails60MinChart/index.jsx deleted file mode 100644 index 57cb344e7..000000000 --- a/Client/src/Components/Charts/MonitorDetails60MinChart/index.jsx +++ /dev/null @@ -1,53 +0,0 @@ -import { BarChart, Bar, Cell, ReferenceLine, Label } from "recharts"; - -import PropTypes from "prop-types"; -import { useTheme } from "@emotion/react"; - -const MonitorDetails60MinChart = ({ data }) => { - const theme = useTheme(); - - const labelStyle = { - fontSize: "10px", - fill: theme.palette.text.tertiary, - }; - - const color = { - true: theme.palette.success.main, - false: theme.palette.error.text, - undefined: theme.palette.unresolved.main, - }; - return ( - - - {data.map((check, index) => ( - - ))} - - - - - - - - - ); -}; - -MonitorDetails60MinChart.propTypes = { - data: PropTypes.array.isRequired, -}; - -export default MonitorDetails60MinChart; diff --git a/Client/src/Pages/Monitors/Details/Charts/index.jsx b/Client/src/Pages/Monitors/Details/Charts/index.jsx index 2927a6cc0..c390a3699 100644 --- a/Client/src/Pages/Monitors/Details/Charts/index.jsx +++ b/Client/src/Pages/Monitors/Details/Charts/index.jsx @@ -6,6 +6,8 @@ import { CartesianGrid, ResponsiveContainer, Cell, + RadialBarChart, + RadialBar, } from "recharts"; import { formatDate } from "../../../../Utils/timeUtils"; import { useState } from "react"; @@ -28,10 +30,10 @@ const CustomLabels = ({ return ( <> - + {formatDate(new Date(firstDataPoint.time), options)} - + {formatDate(new Date(lastDataPoint.time), options)} @@ -186,3 +188,87 @@ export const DownBarChart = ({ data, type, onBarHover }) => { ); }; + +export const ResponseGaugeChart = ({ data }) => { + const theme = useTheme(); + + let max = 1000; // max ms + data = [{ response: max, fill: "transparent", background: false }, ...data]; + + let responseTime = Math.floor(data[1].response); + let responseProps = + responseTime <= 200 + ? { + category: "Excellent", + main: theme.palette.success.main, + bg: theme.palette.success.bg, + } + : responseTime <= 500 + ? { + category: "Fair", + main: theme.palette.success.main, + bg: theme.palette.success.bg, + } + : responseTime <= 600 + ? { + category: "Acceptable", + main: theme.palette.warning.main, + bg: theme.palette.warning.bg, + } + : { + category: "Poor", + main: theme.palette.error.text, + bg: theme.palette.error.bg, + }; + + return ( + + + + low + + + high + + + {responseProps.category} + + + {responseTime}{" "} + ms + + + + + + + + ); +}; diff --git a/Client/src/Pages/Monitors/Details/index.jsx b/Client/src/Pages/Monitors/Details/index.jsx index 46d4772d7..dff958dd6 100644 --- a/Client/src/Pages/Monitors/Details/index.jsx +++ b/Client/src/Pages/Monitors/Details/index.jsx @@ -32,7 +32,7 @@ import PaginationTable from "./PaginationTable"; import Breadcrumbs from "../../../Components/Breadcrumbs"; import PulseDot from "../../../Components/Animated/PulseDot"; import { StatBox, ChartBox, IconBox } from "./styled"; -import { DownBarChart, UpBarChart } from "./Charts"; +import { DownBarChart, ResponseGaugeChart, UpBarChart } from "./Charts"; import SkeletonLayout from "./skeleton"; import "./index.css"; @@ -133,8 +133,6 @@ const DetailsPage = ({ isAdmin }) => { undefined: "Pending...", }; - console.log(monitor); - return ( {loading ? ( @@ -463,7 +461,7 @@ const DetailsPage = ({ isAdmin }) => { onBarHover={setHoveredIncidentsData} /> - + @@ -472,6 +470,9 @@ const DetailsPage = ({ isAdmin }) => { Average Response Time + diff --git a/Client/src/Pages/Monitors/Details/styled.jsx b/Client/src/Pages/Monitors/Details/styled.jsx index 6c3f8eb04..b8de5edfc 100644 --- a/Client/src/Pages/Monitors/Details/styled.jsx +++ b/Client/src/Pages/Monitors/Details/styled.jsx @@ -37,7 +37,6 @@ export const ChartBox = styled(Stack)(({ theme }) => ({ alignItems: "center", }, "& tspan, & text": { - fontSize: 11, fill: theme.palette.text.tertiary, }, "& path": { diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js index ab867ff47..9451b6187 100644 --- a/Server/db/mongo/modules/monitorModule.js +++ b/Server/db/mongo/modules/monitorModule.js @@ -182,8 +182,9 @@ const getMonitorStatsById = async (req) => { if (monitor.type === "http" || monitor.type === "ping") { // HTTP/PING Specific stats - monitorStats.avgResponseTime = getAverageResponseTime(checksForDateRange); - monitorStats.uptime = getUptimePercentage(checksForDateRange); + monitorStats.periodAvgResponseTime = + getAverageResponseTime(checksForDateRange); + monitorStats.periodUptime = getUptimePercentage(checksForDateRange); // Aggregate data let groupedChecks; @@ -198,11 +199,21 @@ const getMonitorStatsById = async (req) => { acc[time].checks.push(check); return acc; }, {}); + } else { + groupedChecks = checksForDateRange.reduce((acc, check) => { + const time = new Date(check.createdAt).toISOString().split("T")[0]; // Extract the date part + if (!acc[time]) { + acc[time] = { time, checks: [] }; + } + acc[time].checks.push(check); + return acc; + }, {}); } // Map grouped checks to stats const aggregateData = Object.values(groupedChecks).map((group) => { const totalChecks = group.checks.length; + const uptimePercentage = getUptimePercentage(group.checks); const totalIncidents = group.checks.filter( (check) => check.status === false ).length; @@ -212,6 +223,7 @@ const getMonitorStatsById = async (req) => { return { time: group.time, + uptimePercentage, totalChecks, totalIncidents, avgResponseTime, @@ -220,7 +232,8 @@ const getMonitorStatsById = async (req) => { monitorStats.aggregateData = aggregateData; } - monitorStats.incidents = getIncidents(checksForDateRange); + monitorStats.periodIncidents = getIncidents(checksForDateRange); + monitorStats.periodTotalChecks = checksForDateRange.length; // If more than numToDisplay checks, pick every nth check