From 6b91411de5740989180cecf84d3bc245f9326a76 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Thu, 17 Jul 2025 10:40:36 -0500 Subject: [PATCH] live monitoring --- src/app/api/servers/route.ts | 80 +++++++++++++++++++++++++++++++----- src/app/dashboard/page.tsx | 54 +++++++++++++++++++----- src/app/dashboard/server.tsx | 51 ++++++++++++++++++++--- src/app/servers/Map.tsx | 4 +- 4 files changed, 159 insertions(+), 30 deletions(-) diff --git a/src/app/api/servers/route.ts b/src/app/api/servers/route.ts index b79b738..49b673d 100644 --- a/src/app/api/servers/route.ts +++ b/src/app/api/servers/route.ts @@ -4,7 +4,54 @@ import Server, { ServerAPI } from "@/types/server"; import { HttpStatusCode } from "axios"; import { validate } from "../auth/route"; +const useServer = (server: ServerAPI, index: number) => { + const ws = new WebSocket(`ws://${server.ip}:5273`); + ws.onmessage = (msg) => { + try { + if (deletes.has(index) || !currentServers[index]) { + ws.close(); + return; + } + if (msg.data === "Success") {return} + const data = JSON.parse(msg.data); + + if (data.status) { + currentServers[index].status = data.status; + } + if (data.cpu) { + currentServers[index].cpu = data.cpu; + } + if (data.memory) { + currentServers[index].memory = data.memory; + } + if (data.disk) { + currentServers[index].storage = data.disk; + } + if (data.network) { + currentServers[index].network = data.network; + } + } catch (e) { + console.error("Error parsing WebSocket message:", e); + } + }; + ws.onopen = () => ws.send("my-key"); +}; + +const deletes = new Set(); export const servers = new Data("sentryx/servers.json", []); +export var currentServers: Server[] = servers.data.map( + (s) => + ({ + ...s, + status: "offline", + cpu: 0, + memory: 0, + storage: 0, + network: 0, + } as Server) + ); + +servers.data.map(useServer); export async function GET(request: Request) { const { searchParams } = new URL(request.url); @@ -17,17 +64,6 @@ export async function GET(request: Request) { { status: HttpStatusCode.Unauthorized } ); - const currentServers = servers.data.map( - (s) => - ({ - ...s, - status: "online", - cpu: 20, - memory: 70, - storage: 40, - network: 30, - } as Server) - ); if (query) { let tokens = (query || "").toLocaleLowerCase().split(" "); @@ -76,6 +112,25 @@ export async function POST(request: Request) { location: body.location, }); + currentServers.push({ + name: body.name, + ip: body.ip, + coordinates: body.coordinates, + location: body.location, + status: "offline", + cpu: 0, + memory: 0, + storage: 0, + network: 0, + }); + + useServer({ + name: body.name, + ip: body.ip, + coordinates: body.coordinates, + location: body.location, + }, servers.data.length - 1); + servers.write(); return NextResponse.json({ @@ -105,6 +160,9 @@ export async function DELETE(request: Request) { ); servers.data.splice(parseInt(index), 1); + currentServers.splice(parseInt(index), 1); + + deletes.add(parseInt(index)); servers.write(); diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index b89497d..0e17d38 100644 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -3,11 +3,11 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Label } from "@/components/ui/label"; import { cn } from "@/lib/utils"; -import { CircleCheckBig, Cpu, MemoryStick, TriangleAlert } from "lucide-react"; +import { CircleCheckBig, Cpu, HardDrive, MemoryStick, Network, TriangleAlert } from "lucide-react"; import { ChartAreaGradient } from "./chart"; import { Progress } from "@/components/ui/progress"; import getSession from "@/hooks/getSession"; -import ServerComponent from "./server"; +import ServerComponent, { ByteUnit, UsageBar } from "./server"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { useEffect, useState } from "react"; @@ -90,7 +90,7 @@ export default function Dashboard() { network: 0, }); - useEffect(() => { + const getServers = () => { if (!session) return; session.getServers().then((servers) => { @@ -107,9 +107,21 @@ export default function Dashboard() { cpu: average(servers, (s) => s.cpu), memory: average(servers, (s) => s.memory), storage: average(servers, (s) => s.storage), - network: average(servers, (s) => s.network), - }); - }); + network: servers.reduce((sum, s) => sum + s.network, 0), + });`` + }).catch((e) => { + console.error("Error fetching servers:", e); + }) + }; + + useEffect(() => { + const interval = setInterval(() => { + console.log("Refreshing servers data..."); + getServers(); + }, 3000); + + // Cleanup on unmount + return () => clearInterval(interval); }, [session]); useEffect(() => { @@ -171,11 +183,31 @@ export default function Dashboard() { System Overview - - Average CPU - Average Memory - Storage - Average Network + + + + + diff --git a/src/app/dashboard/server.tsx b/src/app/dashboard/server.tsx index da314ef..0d59c53 100644 --- a/src/app/dashboard/server.tsx +++ b/src/app/dashboard/server.tsx @@ -64,6 +64,43 @@ export function UsageBar({ ); } +function formatBytes(bytes: number, decimals = 2): string { + if (bytes === 0) return "0 Bytes"; + + const k = 1024; + const dm = decimals < 0 ? 0 : decimals; + + const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + const size = parseFloat((bytes / Math.pow(k, i)).toFixed(dm)); + + return `${size} ${sizes[i]}`; +} + +export function ByteUnit({ + value, + Icon, + text, + color, +}: { + value: number; + Icon: React.ElementType; + text: string; + color: string; +}) { + return ( +
+
+ + +
+
+ ) +} + export default function ServerComponent({ server, index, @@ -127,12 +164,14 @@ export default function ServerComponent({ text="Storage" color="var(--chart-5)" /> - +
+
+ + +
+
diff --git a/src/app/servers/Map.tsx b/src/app/servers/Map.tsx index 82d7d55..9f7ac13 100644 --- a/src/app/servers/Map.tsx +++ b/src/app/servers/Map.tsx @@ -10,7 +10,7 @@ import { SheetTitle, SheetTrigger, } from "@/components/ui/sheet"; -import ServerComponent, { UsageBar } from "../dashboard/server"; +import ServerComponent, { ByteUnit, UsageBar } from "../dashboard/server"; import { Cpu, HardDrive, @@ -117,7 +117,7 @@ export default function Map({ servers }: { servers: Server[] }) { text="Storage" color="var(--chart-5)" /> -