Application status
This commit is contained in:
@@ -20,9 +20,10 @@ export default function ApplicationsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetch();
|
fetch();
|
||||||
}, []);
|
|
||||||
|
|
||||||
console.log(applications);
|
const iid = setInterval(fetch, 3000);
|
||||||
|
return () => clearInterval(iid);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DashboardLayout
|
<DashboardLayout
|
||||||
@@ -77,7 +78,9 @@ export default function ApplicationsPage() {
|
|||||||
<div className="text-xs text-muted-foreground mb-1">CPU</div>
|
<div className="text-xs text-muted-foreground mb-1">CPU</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Progress value={app.cpu} className="w-full" />
|
<Progress value={app.cpu} className="w-full" />
|
||||||
<span className="text-xs font-mono w-8">{app.cpu}%</span>
|
<span className="text-xs font-mono w-8">
|
||||||
|
{app.cpu.toFixed(1)}%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -88,7 +91,9 @@ export default function ApplicationsPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Progress value={app.memory} className="w-full" />
|
<Progress value={app.memory} className="w-full" />
|
||||||
<span className="text-xs font-mono w-8">{app.memory}%</span>
|
<span className="text-xs font-mono w-8">
|
||||||
|
{app.memory.toFixed(1)}%
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+11
-15
@@ -35,7 +35,7 @@ type ContainerSummary = {
|
|||||||
status: "running" | "stopped";
|
status: "running" | "stopped";
|
||||||
uptime: string;
|
uptime: string;
|
||||||
cpu: number;
|
cpu: number;
|
||||||
memory: string;
|
memory: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
async function summarizeContainer(
|
async function summarizeContainer(
|
||||||
@@ -56,12 +56,6 @@ async function summarizeContainer(
|
|||||||
|
|
||||||
const stats = await getContainerStats(container.Id);
|
const stats = await getContainerStats(container.Id);
|
||||||
|
|
||||||
// 5. CPU and memory
|
|
||||||
const cpu = stats?.cpu_stats?.cpu_usage?.total_usage || 0;
|
|
||||||
const memory = `${formatBytes(
|
|
||||||
stats?.memory_stats?.usage || 0
|
|
||||||
)} / ${formatBytes(stats?.memory_stats?.max_usage || 0)}`;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: shortId,
|
id: shortId,
|
||||||
name,
|
name,
|
||||||
@@ -69,8 +63,8 @@ async function summarizeContainer(
|
|||||||
node: nodeName,
|
node: nodeName,
|
||||||
status,
|
status,
|
||||||
uptime,
|
uptime,
|
||||||
cpu,
|
cpu: stats?.cpu || 0,
|
||||||
memory,
|
memory: stats?.memory || 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,18 +188,18 @@ export default function ContainersPage() {
|
|||||||
|
|
||||||
<td className="py-3 px-4">{container.node}</td>
|
<td className="py-3 px-4">{container.node}</td>
|
||||||
|
|
||||||
<td className="py-3 px-4">{/* {container.status} */}</td>
|
<td className="py-3 px-4">{container.status}</td>
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-xs">
|
<td className="py-3 px-4 font-mono text-xs">
|
||||||
{container.uptime}
|
{container.uptime}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-xs">
|
<td className="py-3 px-4 font-mono text-xs">
|
||||||
{container.cpu}
|
{container.cpu.toFixed(1)}%
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="py-3 px-4 font-mono text-xs">
|
<td className="py-3 px-4 font-mono text-xs">
|
||||||
{container.memory}
|
{container.memory.toFixed(1)}%
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className="py-3 px-4">
|
<td className="py-3 px-4">
|
||||||
@@ -249,7 +243,7 @@ export default function ContainersPage() {
|
|||||||
<Container className="w-4 h-4 text-muted-foreground" />
|
<Container className="w-4 h-4 text-muted-foreground" />
|
||||||
<span className="font-mono text-sm">{container.name}</span>
|
<span className="font-mono text-sm">{container.name}</span>
|
||||||
</div>
|
</div>
|
||||||
{/* {container.status} */}
|
{container.status}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-[10px] font-mono text-muted-foreground">
|
<div className="text-[10px] font-mono text-muted-foreground">
|
||||||
@@ -271,11 +265,13 @@ export default function ContainersPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">CPU</span>
|
<span className="text-muted-foreground">CPU</span>
|
||||||
<div className="font-mono">{container.cpu}</div>
|
<div className="font-mono">{container.cpu.toFixed(1)}%</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-muted-foreground">Memory</span>
|
<span className="text-muted-foreground">Memory</span>
|
||||||
<div className="font-mono">{container.memory}</div>
|
<div className="font-mono">
|
||||||
|
{container.memory.toFixed(1)}%
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ import { useIsMobile } from "@/hooks/use-mobile";
|
|||||||
import RadialChart from "@/components/RadialChart";
|
import RadialChart from "@/components/RadialChart";
|
||||||
import { getLiveNodes, getNodes } from "@/core/node";
|
import { getLiveNodes, getNodes } from "@/core/node";
|
||||||
import { average } from "@/lib/format";
|
import { average } from "@/lib/format";
|
||||||
import { ContainerStats } from "dockerode";
|
|
||||||
import { getContainerStats, getDocker } from "@/core/docker";
|
import { getContainerStats, getDocker } from "@/core/docker";
|
||||||
|
import { SimpleStats } from "@/lib/types";
|
||||||
|
|
||||||
const cpuChartConfig = {
|
const cpuChartConfig = {
|
||||||
cpu: { label: "CPU Usage", color: "var(--chart-1)" },
|
cpu: { label: "CPU Usage", color: "var(--chart-1)" },
|
||||||
@@ -43,7 +43,7 @@ export default function MonitoringPage() {
|
|||||||
ramUsage: number;
|
ramUsage: number;
|
||||||
}>();
|
}>();
|
||||||
const [containerStats, SetContainerStats] = useState<
|
const [containerStats, SetContainerStats] = useState<
|
||||||
(ContainerStats & { name: string })[]
|
(SimpleStats & { name: string })[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -89,7 +89,7 @@ export default function MonitoringPage() {
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).filter((s): s is ContainerStats & { name: string } => s !== undefined)
|
).filter((s): s is SimpleStats & { name: string } => s !== undefined)
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(containerStats);
|
console.log(containerStats);
|
||||||
@@ -207,31 +207,20 @@ export default function MonitoringPage() {
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between text-[10px] text-muted-foreground mb-1">
|
<div className="flex justify-between text-[10px] text-muted-foreground mb-1">
|
||||||
<span>CPU</span>
|
<span>CPU</span>
|
||||||
<span>
|
<span>{container.cpu.toFixed(1)}%</span>
|
||||||
{container?.cpu_stats?.cpu_usage?.total_usage}%
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<Progress
|
<Progress value={container.cpu} className="w-full" />
|
||||||
value={container?.cpu_stats?.cpu_usage?.total_usage}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div className="flex justify-between text-[10px] text-muted-foreground mb-1">
|
<div className="flex justify-between text-[10px] text-muted-foreground mb-1">
|
||||||
<span>Memory</span>
|
<span>Memory</span>
|
||||||
<span>{container?.memory_stats?.usage}%</span>
|
<span>{container.memory.toFixed(1)}%</span>
|
||||||
</div>
|
</div>
|
||||||
<Progress
|
<Progress value={container.memory} className="w-full" />
|
||||||
value={container?.memory_stats?.usage}
|
|
||||||
className="w-full"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between text-[10px] pt-1 border-t border-border">
|
<div className="flex justify-between text-[10px] pt-1 border-t border-border">
|
||||||
<span className="text-muted-foreground">Network</span>
|
<span className="text-muted-foreground">Network</span>
|
||||||
<span className="font-mono">
|
<span className="font-mono"></span>
|
||||||
{container?.networks &&
|
|
||||||
container?.networks[0]?.tx_packets}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Docker, Node } from "@/lib/types";
|
import { Docker, Node, SimpleStats } from "@/lib/types";
|
||||||
import { verifySession } from "./auth/session";
|
import { verifySession } from "./auth/session";
|
||||||
import { ContainerStats } from "dockerode";
|
|
||||||
import { getNodes } from "./node";
|
import { getNodes } from "./node";
|
||||||
|
|
||||||
export async function getDocker(nodes: Node[]): Promise<Docker[]> {
|
export async function getDocker(nodes: Node[]): Promise<Docker[]> {
|
||||||
@@ -24,7 +23,7 @@ export async function getDocker(nodes: Node[]): Promise<Docker[]> {
|
|||||||
|
|
||||||
export async function getContainerStats(
|
export async function getContainerStats(
|
||||||
containerId: string
|
containerId: string
|
||||||
): Promise<ContainerStats | undefined> {
|
): Promise<SimpleStats | undefined> {
|
||||||
const nodes = await getNodes();
|
const nodes = await getNodes();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import Docker from "dockerode";
|
import Docker, { Container, ContainerStats } from "dockerode";
|
||||||
import { randomUUID } from "crypto";
|
import { randomUUID } from "crypto";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { exec } from "child_process";
|
import { exec } from "child_process";
|
||||||
import util from "util";
|
import util from "util";
|
||||||
import { ImageApp } from "@/lib/types";
|
import { ImageApp } from "@/lib/types";
|
||||||
|
import { CPUusage } from "@/lib/server/calc";
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
const execAsync = util.promisify(exec);
|
const execAsync = util.promisify(exec);
|
||||||
@@ -42,6 +43,9 @@ export async function getApplications(): Promise<ImageApp[]> {
|
|||||||
|
|
||||||
if (containerInfo.State === "running") {
|
if (containerInfo.State === "running") {
|
||||||
const stats = await container.stats({ stream: false });
|
const stats = await container.stats({ stream: false });
|
||||||
|
|
||||||
|
totalMem += (stats.memory_stats.usage / stats.memory_stats.limit) * 100;
|
||||||
|
totalCpu += CPUusage(stats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +66,8 @@ export async function getApplications(): Promise<ImageApp[]> {
|
|||||||
image: imageName,
|
image: imageName,
|
||||||
containers: relatedContainers.length,
|
containers: relatedContainers.length,
|
||||||
replicas: `${running}/${relatedContainers.length}`,
|
replicas: `${running}/${relatedContainers.length}`,
|
||||||
cpu: Math.round(totalCpu),
|
cpu: totalCpu,
|
||||||
memory: Math.round(totalMem),
|
memory: totalMem,
|
||||||
network: "—",
|
network: "—",
|
||||||
status: running > 0 ? ("running" as const) : ("stopped" as const),
|
status: running > 0 ? ("running" as const) : ("stopped" as const),
|
||||||
ports: [...ports],
|
ports: [...ports],
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import Docker, { ContainerStats } from "dockerode";
|
import { CPUusage } from "@/lib/server/calc";
|
||||||
|
import { SimpleStats } from "@/lib/types";
|
||||||
|
import Docker from "dockerode";
|
||||||
|
|
||||||
const docker = new Docker();
|
const docker = new Docker();
|
||||||
|
|
||||||
@@ -12,8 +14,13 @@ export async function getDocker() {
|
|||||||
|
|
||||||
export async function getContainerStats(
|
export async function getContainerStats(
|
||||||
containerId: string
|
containerId: string
|
||||||
): Promise<ContainerStats | undefined> {
|
): Promise<SimpleStats | undefined> {
|
||||||
return await docker.getContainer(containerId).stats();
|
const stats = await docker.getContainer(containerId).stats({ stream: false });
|
||||||
|
|
||||||
|
return {
|
||||||
|
cpu: CPUusage(stats),
|
||||||
|
memory: (stats.memory_stats.usage / stats.memory_stats.limit) * 100,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startContainer(containerId: string) {
|
export async function startContainer(containerId: string) {
|
||||||
|
|||||||
@@ -69,3 +69,8 @@ export interface ImageApp {
|
|||||||
status: "running" | "stopped";
|
status: "running" | "stopped";
|
||||||
ports: string[];
|
ports: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SimpleStats {
|
||||||
|
cpu: number;
|
||||||
|
memory: number;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user