diff --git a/src/app/api/metrics/route.ts b/src/app/api/metrics/route.ts index e1864c8..2e0681b 100644 --- a/src/app/api/metrics/route.ts +++ b/src/app/api/metrics/route.ts @@ -2,12 +2,7 @@ import { NextRequest, NextResponse } from "next/server"; import testAuth from "../auth"; import { StatusCodes } from "http-status-codes"; import si from "systeminformation"; - -function average(values: Array, p: (v: T) => number) { - return values.length > 0 - ? values.reduce((sum, value) => sum + p(value), 0) / values.length - : 0; -} +import { average } from "@/lib/format"; type Usage = { cpu: number; diff --git a/src/app/monitoring/page.tsx b/src/app/monitoring/page.tsx index 1194c0c..cb0945e 100644 --- a/src/app/monitoring/page.tsx +++ b/src/app/monitoring/page.tsx @@ -7,6 +7,11 @@ import { type ChartConfig } from "@/components/ui/chart"; import GradientAreaChart from "@/components/GradientAreaChart"; import { getMetrics } from "@/core/client/metrics"; import { useEffect, useState } from "react"; +import { useIsMobile } from "@/hooks/use-mobile"; +import RadialChart from "@/components/RadialChart"; +import { Node, NodeLiveData } from "@/lib/types"; +import { getLiveNodes } from "@/core/client/node"; +import { average } from "@/lib/format"; const containerMetrics = [ { name: "api-gateway-1", cpu: 45, memory: 62, network: "12.4 MB/s" }, @@ -42,6 +47,24 @@ export default function MonitoringPage() { out: number; }[] >([]); + const isMobile = useIsMobile(); + const [liveData, setLiveData] = useState<{ + cpuUsage: number; + ramUsage: number; + }>(); + + useEffect(() => { + const fetchNodes = async () => { + const nodes = await getLiveNodes(); + setLiveData({ + cpuUsage: average(nodes, (n) => n.liveData.cpu.usage), + ramUsage: average(nodes, (n) => n.liveData.memory.usage), + }); + }; + fetchNodes(); + const interval = setInterval(fetchNodes, 3000); + return () => clearInterval(interval); + }, []); useEffect(() => { async function fetchMetrics() { @@ -61,46 +84,61 @@ export default function MonitoringPage() { subtitle="Resource utilization and metrics" > {/* Summary Stats */} -
- - -
- Cluster CPU -
-
68%
- -
-
- - -
- Cluster Memory -
-
71%
- -
-
- - -
- Network In -
-
38 MB/s
-
↑ 12% from avg
-
-
- - -
- Network Out -
-
28 MB/s
-
- ↓ 5% from avg -
-
-
-
+ {isMobile ? ( +
+ + + CPU + + + + + RAM + + +
+ ) : ( +
+ + +
+ Cluster CPU +
+
68%
+ +
+
+ + +
+ Cluster Memory +
+
71%
+ +
+
+ + +
+ Network In +
+
38 MB/s
+
↑ 12% from avg
+
+
+ + +
+ Network Out +
+
28 MB/s
+
+ ↓ 5% from avg +
+
+
+
+ )} {/* CPU & Memory Charts */}
diff --git a/src/components/RadialChart.tsx b/src/components/RadialChart.tsx index 95d8361..8f68bea 100644 --- a/src/components/RadialChart.tsx +++ b/src/components/RadialChart.tsx @@ -2,7 +2,7 @@ import { Label, - PolarGrid, + PolarAngleAxis, PolarRadiusAxis, RadialBar, RadialBarChart, @@ -15,6 +15,8 @@ const chartConfig = { }, } satisfies ChartConfig; +const INNER_RADIUS = 80; + export default function RadialChart({ value, children, @@ -23,22 +25,25 @@ export default function RadialChart({ children?: React.ReactNode; }) { const chartData = [{ value, fill: "var(--color-chart-1)" }]; + const startAngle = 230; + const totalSweep = 280; return ( - + - @@ -57,7 +62,7 @@ export default function RadialChart({ y={viewBox.cy} className="fill-foreground text-xl font-bold" > - {chartData[0].value.toLocaleString()} + {chartData[0].value.toFixed(1)}% (values: Array, p: (v: T) => number) { + return values.length > 0 + ? values.reduce((sum, value) => sum + p(value), 0) / values.length + : 0; +} \ No newline at end of file