mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-20 08:39:43 -06:00
Fetch data from gist
This commit is contained in:
@@ -1,133 +0,0 @@
|
||||
function generateMonitorEntries(monitorId, count = 10, options = {}) {
|
||||
const defaultOptions = {
|
||||
timeRange: {
|
||||
start: new Date(Date.now() - 24 * 60 * 60 * 1000 * 20),
|
||||
end: new Date(),
|
||||
},
|
||||
statusVariation: [true, false],
|
||||
responseTimeRange: [50, 500],
|
||||
cpuUsageRange: [0, 1],
|
||||
memoryUsageRange: [0, 1],
|
||||
diskUsageRange: [0, 1],
|
||||
};
|
||||
|
||||
const mergedOptions = { ...defaultOptions, ...options };
|
||||
const startTime = mergedOptions.timeRange.start.getTime();
|
||||
const endTime = mergedOptions.timeRange.end.getTime();
|
||||
const totalTimeSpan = endTime - startTime;
|
||||
|
||||
// Generate sorted random time points
|
||||
const timePoints = Array.from({ length: count }, (_, index) => {
|
||||
// Use a non-linear distribution to create more varied spacing
|
||||
const progress = Math.pow(Math.random(), 2); // Bias towards earlier times
|
||||
return startTime + progress * totalTimeSpan;
|
||||
}).sort((a, b) => a - b);
|
||||
|
||||
return timePoints.map((timestamp) => {
|
||||
const createdAt = new Date(timestamp);
|
||||
|
||||
return {
|
||||
_id: "123",
|
||||
monitorId: monitorId,
|
||||
status: randomFromArray(mergedOptions.statusVariation),
|
||||
responseTime: randomInRange(mergedOptions.responseTimeRange),
|
||||
statusCode: randomStatusCode(),
|
||||
message: randomMessage(),
|
||||
cpu: {
|
||||
physical_core: randomInRange([4, 8]),
|
||||
logical_core: randomInRange([4, 16]),
|
||||
frequency: randomInRange([10, 4000]),
|
||||
temperature: randomInRange([20, 90]),
|
||||
free_percent: 1 - randomInRange(mergedOptions.cpuUsageRange),
|
||||
usage_percent: randomInRange(mergedOptions.cpuUsageRange),
|
||||
_id: "123",
|
||||
},
|
||||
memory: {
|
||||
total_bytes: randomInRange([8, 32]) * 1024 * 1024 * 1024,
|
||||
available_bytes: randomInRange([4, 16]) * 1024 * 1024 * 1024,
|
||||
used_bytes: randomInRange([4, 16]) * 1024 * 1024 * 1024,
|
||||
usage_percent: randomInRange(mergedOptions.memoryUsageRange),
|
||||
_id: "123",
|
||||
},
|
||||
disk: [
|
||||
{
|
||||
read_speed_bytes: randomInRange([100, 1000]) * 1024 * 1024,
|
||||
write_speed_bytes: randomInRange([100, 1000]) * 1024 * 1024,
|
||||
total_bytes: randomInRange([100, 1000]) * 1024 * 1024 * 1024,
|
||||
free_bytes: randomInRange([50, 500]) * 1024 * 1024 * 1024,
|
||||
usage_percent: randomInRange(mergedOptions.diskUsageRange),
|
||||
_id: "123",
|
||||
},
|
||||
],
|
||||
host: {
|
||||
os: randomOS(),
|
||||
platform: randomPlatform(),
|
||||
kernel_version: randomKernelVersion(),
|
||||
_id: "123",
|
||||
},
|
||||
errors: randomErrors(),
|
||||
expiry: new Date(createdAt.getTime() + 365 * 24 * 60 * 60 * 1000),
|
||||
createdAt: createdAt,
|
||||
updatedAt: createdAt,
|
||||
__v: 0,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Modify randomInRange to work with decimal ranges
|
||||
function randomInRange([min, max]) {
|
||||
return Number((Math.random() * (max - min) + min).toFixed(2));
|
||||
}
|
||||
|
||||
// ... rest of the code remains the same
|
||||
function randomFromArray(arr) {
|
||||
return arr[Math.floor(Math.random() * arr.length)];
|
||||
}
|
||||
|
||||
function randomStatusCode() {
|
||||
const statusCodes = [200, 201, 204, 400, 401, 403, 404, 500, 502, 503];
|
||||
return randomFromArray(statusCodes);
|
||||
}
|
||||
|
||||
function randomMessage() {
|
||||
const messages = [
|
||||
"OK",
|
||||
"Created",
|
||||
"No Content",
|
||||
"Bad Request",
|
||||
"Unauthorized",
|
||||
"Forbidden",
|
||||
"Not Found",
|
||||
"Internal Server Error",
|
||||
];
|
||||
return randomFromArray(messages);
|
||||
}
|
||||
|
||||
function randomOS() {
|
||||
const oss = ["Windows", "Linux", "macOS", "Ubuntu", "CentOS"];
|
||||
return randomFromArray(oss);
|
||||
}
|
||||
|
||||
function randomPlatform() {
|
||||
const platforms = ["x64", "x86", "ARM", "ARM64"];
|
||||
return randomFromArray(platforms);
|
||||
}
|
||||
|
||||
function randomKernelVersion() {
|
||||
return `${randomInRange([4, 6])}.${randomInRange([0, 20])}.${randomInRange([0, 100])}`;
|
||||
}
|
||||
|
||||
function randomErrors() {
|
||||
const possibleErrors = [
|
||||
"Network timeout",
|
||||
"Connection refused",
|
||||
"SSL certificate error",
|
||||
"DNS resolution failed",
|
||||
"",
|
||||
];
|
||||
return Math.random() < 0.2 ? [randomFromArray(possibleErrors)] : [];
|
||||
}
|
||||
|
||||
// Usage
|
||||
const monitorId = "123";
|
||||
export const monitorData = generateMonitorEntries(monitorId, 20);
|
||||
@@ -1,10 +1,11 @@
|
||||
import { monitorData } from "./data";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useEffect, useState } from "react";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import { Stack, Box, Typography } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import CustomGauge from "../../../Components/Charts/CustomGauge";
|
||||
import AreaChart from "../../../Components/Charts/AreaChart";
|
||||
import axios from "axios";
|
||||
import {
|
||||
TzTick,
|
||||
PercentTick,
|
||||
@@ -17,11 +18,18 @@ import PropTypes from "prop-types";
|
||||
* @param {number} bytes - Number of bytes to convert
|
||||
* @returns {number} Converted value in gigabytes
|
||||
*/
|
||||
const bytesToGB = (bytes) => {
|
||||
if (typeof bytes !== "number") return 0;
|
||||
if (bytes === 0) return 0;
|
||||
const formatBytes = (bytes) => {
|
||||
if (typeof bytes !== "number") return "0 GB";
|
||||
if (bytes === 0) return "0 GB";
|
||||
|
||||
const GB = bytes / (1024 * 1024 * 1024);
|
||||
return Number(GB.toFixed(0));
|
||||
const MB = bytes / (1024 * 1024);
|
||||
|
||||
if (GB >= 1) {
|
||||
return `${Number(GB.toFixed(0))} GB`;
|
||||
} else {
|
||||
return `${Number(MB.toFixed(0))} MB`;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -130,12 +138,12 @@ const GaugeBox = ({ value, heading, metricOne, valueOne, metricTwo, valueTwo })
|
||||
};
|
||||
|
||||
GaugeBox.propTypes = {
|
||||
value: PropTypes.number.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
|
||||
heading: PropTypes.string.isRequired,
|
||||
metricOne: PropTypes.string.isRequired,
|
||||
valueOne: PropTypes.string.isRequired,
|
||||
valueOne: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
metricTwo: PropTypes.string.isRequired,
|
||||
valueTwo: PropTypes.string.isRequired,
|
||||
valueTwo: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -145,189 +153,207 @@ GaugeBox.propTypes = {
|
||||
const InfrastructureDetails = () => {
|
||||
const theme = useTheme();
|
||||
const { monitorId } = useParams();
|
||||
const testData = monitorData;
|
||||
const latestCheck = testData[testData.length - 1];
|
||||
const navList = [
|
||||
{ name: "infrastructure monitors", path: "/infrastructure" },
|
||||
{ name: "details", path: `/infrastructure/${monitorId}` },
|
||||
];
|
||||
const [monitor, setMonitor] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const response = await axios.get("http://localhost:5000/api/v1/dummy-data", {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Cache-Control": "no-cache",
|
||||
},
|
||||
});
|
||||
setMonitor(response.data.data);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Breadcrumbs list={navList} />
|
||||
<Stack
|
||||
direction="column"
|
||||
gap={theme.spacing(10)}
|
||||
mt={theme.spacing(10)}
|
||||
>
|
||||
monitor && (
|
||||
<Box>
|
||||
<Breadcrumbs list={navList} />
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
direction="column"
|
||||
gap={theme.spacing(10)}
|
||||
mt={theme.spacing(10)}
|
||||
>
|
||||
<StatBox
|
||||
heading={"CPU"}
|
||||
subHeading={`${latestCheck.cpu.physical_core} cores`}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Memory"}
|
||||
subHeading={`${bytesToGB(latestCheck.memory.total_bytes)}GB`}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Disk"}
|
||||
subHeading={`${bytesToGB(latestCheck.disk[0].total_bytes)}GB`}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Uptime"}
|
||||
subHeading={"100%"}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Status"}
|
||||
subHeading={latestCheck.status === true ? "Active" : "Inactive"}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<GaugeBox
|
||||
value={latestCheck.cpu.usage_percent * 100}
|
||||
heading={"Memory Usage"}
|
||||
metricOne={"Used"}
|
||||
valueOne={`${bytesToGB(latestCheck.memory.used_bytes)}GB`}
|
||||
metricTwo={"Total"}
|
||||
valueTwo={`${bytesToGB(latestCheck.memory.total_bytes)}GB`}
|
||||
/>
|
||||
<GaugeBox
|
||||
value={latestCheck.cpu.usage_percent * 100}
|
||||
heading={"CPU Usage"}
|
||||
metricOne={"Cores"}
|
||||
valueOne={latestCheck.cpu.physical_core}
|
||||
metricTwo={"Frequency"}
|
||||
valueTwo={`${latestCheck.cpu.frequency} Ghz`}
|
||||
/>
|
||||
{latestCheck.disk.map((disk, idx) => {
|
||||
return (
|
||||
<GaugeBox
|
||||
key={disk._id}
|
||||
value={disk.usage_percent * 100}
|
||||
heading={`Disk${idx} usage`}
|
||||
metricOne={"Used"}
|
||||
valueOne={`${bytesToGB(disk.total_bytes - disk.free_bytes)}GB`}
|
||||
metricTwo={"Total"}
|
||||
valueTwo={`${bytesToGB(disk.total_bytes)}GB`}
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<StatBox
|
||||
heading={"CPU"}
|
||||
subHeading={`${monitor.checks[0].cpu.physical_core} cores`}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Memory"}
|
||||
subHeading={formatBytes(monitor.checks[0].memory.total_bytes)}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Disk"}
|
||||
subHeading={formatBytes(monitor.checks[0].disk[0].total_bytes)}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Uptime"}
|
||||
subHeading={"100%"}
|
||||
/>
|
||||
<StatBox
|
||||
heading={"Status"}
|
||||
subHeading={monitor.status === true ? "Active" : "Inactive"}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
gap={theme.spacing(8)}
|
||||
>
|
||||
<GaugeBox
|
||||
value={monitor.checks[0].memory.usage_percent * 100}
|
||||
heading={"Memory Usage"}
|
||||
metricOne={"Used"}
|
||||
valueOne={formatBytes(monitor.checks[0].memory.used_bytes)}
|
||||
metricTwo={"Total"}
|
||||
valueTwo={formatBytes(monitor.checks[0].memory.total_bytes)}
|
||||
/>
|
||||
<GaugeBox
|
||||
value={monitor.checks[0].cpu.usage_percent * 100}
|
||||
heading={"CPU Usage"}
|
||||
metricOne={"Cores"}
|
||||
valueOne={monitor.checks[0].cpu.physical_core}
|
||||
metricTwo={"Frequency"}
|
||||
valueTwo={`${(monitor.checks[0].cpu.frequency / 1000).toFixed(2)} Ghz`}
|
||||
/>
|
||||
{monitor.checks[0].disk.map((disk, idx) => {
|
||||
return (
|
||||
<GaugeBox
|
||||
key={disk._id}
|
||||
value={disk.usage_percent * 100}
|
||||
heading={`Disk${idx} usage`}
|
||||
metricOne={"Used"}
|
||||
valueOne={formatBytes(disk.total_bytes - disk.free_bytes)}
|
||||
metricTwo={"Total"}
|
||||
valueTwo={formatBytes(disk.total_bytes)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
height={300} // FE team HELP!
|
||||
gap={theme.spacing(8)} // FE team HELP!
|
||||
flexWrap="wrap" // //FE team HELP! Better way to do this?
|
||||
sx={{
|
||||
"& > *": {
|
||||
flexBasis: `calc(50% - ${theme.spacing(8)})`,
|
||||
maxWidth: `calc(50% - ${theme.spacing(8)})`,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<BaseBox>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
Memory usage
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={monitor?.checks ?? []}
|
||||
dataKey="memory.usage_percent"
|
||||
xKey="createdAt"
|
||||
yKey="memory.usage_percent"
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label}
|
||||
yKey="memory.usage_percent"
|
||||
yLabel="Memory Usage"
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.primary.main}
|
||||
gradient={true}
|
||||
gradientStartColor={theme.palette.primary.main} //FE team HELP! Not sure what colors to use
|
||||
gradientEndColor="#ffffff" // FE team HELP!
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</BaseBox>
|
||||
<BaseBox>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
CPU usage
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={monitor?.checks ?? []}
|
||||
dataKey="cpu.usage_percent"
|
||||
xKey="createdAt"
|
||||
yKey="cpu.usage_percent"
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label}
|
||||
yKey="cpu.usage_percent"
|
||||
yLabel="CPU Usage"
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.success.main} // FE team HELP!
|
||||
gradient={true}
|
||||
fill={theme.palette.success.main} // FE team HELP!
|
||||
gradientStartColor={theme.palette.success.main}
|
||||
gradientEndColor="#ffffff"
|
||||
/>
|
||||
</BaseBox>
|
||||
{monitor?.checks?.[0]?.disk?.map((disk, idx) => {
|
||||
// disk is an array of disks, so we need to map over it
|
||||
return (
|
||||
<BaseBox key={disk._id}>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
{`Disk${idx} usage`}
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={monitor?.checks ?? []}
|
||||
dataKey={`disk[${idx}].usage_percent`}
|
||||
xKey="createdAt"
|
||||
yKey={`disk[${idx}].usage_percent`} // We are looking for the usage_percent of the current disk in the array
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label} // label must be a string
|
||||
yKey={`disk.usage_percent`}
|
||||
yLabel="Disk Usage"
|
||||
yIdx={idx}
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.warning.main}
|
||||
gradient={true}
|
||||
gradientStartColor={theme.palette.warning.main}
|
||||
gradientEndColor="#ffffff"
|
||||
/>
|
||||
</BaseBox>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
height={300} // FE team HELP!
|
||||
gap={theme.spacing(8)} // FE team HELP!
|
||||
flexWrap="wrap" // //FE team HELP! Better way to do this?
|
||||
sx={{
|
||||
"& > *": {
|
||||
flexBasis: `calc(50% - ${theme.spacing(8)})`,
|
||||
maxWidth: `calc(50% - ${theme.spacing(8)})`,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<BaseBox>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
Memory usage
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={testData}
|
||||
dataKey="memory.usage_percent"
|
||||
xKey="createdAt"
|
||||
yKey="memory.usage_percent"
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label}
|
||||
yKey="memory.usage_percent"
|
||||
yLabel="Memory Usage"
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.primary.main}
|
||||
gradient={true}
|
||||
gradientStartColor={theme.palette.primary.main} //FE team HELP! Not sure what colors to use
|
||||
gradientEndColor="#ffffff" // FE team HELP!
|
||||
/>
|
||||
</BaseBox>
|
||||
<BaseBox>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
CPU usage
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={testData}
|
||||
dataKey="cpu.usage_percent"
|
||||
xKey="createdAt"
|
||||
yKey="cpu.usage_percent"
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label}
|
||||
yKey="cpu.usage_percent"
|
||||
yLabel="CPU Usage"
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.success.main} // FE team HELP!
|
||||
gradient={true}
|
||||
fill={theme.palette.success.main} // FE team HELP!
|
||||
gradientStartColor={theme.palette.success.main}
|
||||
gradientEndColor="#ffffff"
|
||||
/>
|
||||
</BaseBox>
|
||||
{latestCheck.disk.map((disk, idx) => {
|
||||
// disk is an array of disks, so we need to map over it
|
||||
return (
|
||||
<BaseBox key={disk._id}>
|
||||
<Typography
|
||||
component="h2"
|
||||
padding={theme.spacing(8)}
|
||||
>
|
||||
{`Disk${idx} usage`}
|
||||
</Typography>
|
||||
<AreaChart
|
||||
data={testData}
|
||||
dataKey={`disk[${idx}].usage_percent`}
|
||||
xKey="createdAt"
|
||||
yKey={`disk[${idx}].usage_percent`} // We are looking for the usage_percent of the current disk in the array
|
||||
customTooltip={({ active, payload, label }) => (
|
||||
<InfrastructureTooltip
|
||||
label={label} // label must be a string
|
||||
yKey={`disk.usage_percent`}
|
||||
yLabel="Disk Usage"
|
||||
yIdx={idx}
|
||||
active={active}
|
||||
payload={payload}
|
||||
/>
|
||||
)}
|
||||
xTick={<TzTick />}
|
||||
yTick={<PercentTick />}
|
||||
strokeColor={theme.palette.warning.main}
|
||||
gradient={true}
|
||||
gradientStartColor={theme.palette.warning.main}
|
||||
gradientEndColor="#ffffff"
|
||||
/>
|
||||
</BaseBox>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user