Add resource usage stats to the compose page (#700)

Co-authored-by: cmcooper1980 <31871143+cmcooper1980@users.noreply.github.com>
This commit is contained in:
Justin Wiebe
2026-04-11 23:42:38 -05:00
committed by GitHub
parent 078f762631
commit b02f5e092e
9 changed files with 247 additions and 26 deletions

View File

@@ -240,6 +240,22 @@ export class DockerSocketHandler extends AgentSocketHandler {
}
});
// Docker stats
agentSocket.on("dockerStats", async (callback) => {
try {
checkLogin(socket);
const dockerStats = Object.fromEntries(await server.getDockerStats());
callbackResult({
ok: true,
dockerStats,
}, callback);
server.sendStackList();
} catch (e) {
callbackError(e, callback);
}
});
// Start a service
agentSocket.on("startService", async (stackName: unknown, serviceName: unknown, callback) => {
try {

View File

@@ -637,6 +637,35 @@ export class DockgeServer {
return list;
}
async getDockerStats() : Promise<Map<string, object>> {
let stats = new Map<string, object>();
try {
let res = await childProcessAsync.spawn("docker", [ "stats", "--format", "json", "--no-stream" ], {
encoding: "utf-8",
});
if (!res.stdout) {
return stats;
}
let lines = res.stdout?.toString().split("\n");
for (let line of lines) {
try {
let obj = JSON.parse(line);
stats.set(obj.Name, obj);
} catch (e) {
}
}
return stats;
} catch (e) {
log.error("getDockerStats", e);
return stats;
}
}
get stackDirFullPath() {
return path.resolve(this.stacksDir);
}

View File

@@ -508,7 +508,7 @@ export class Stack {
}
async getServiceStatusList() {
let statusList = new Map<string, { state: string, ports: string[] }>();
let statusList = new Map<string, Array<object>>();
try {
let res = await childProcessAsync.spawn("docker", this.getComposeOptions("ps", "--format", "json"), {
@@ -522,22 +522,23 @@ export class Stack {
let lines = res.stdout?.toString().split("\n");
const addLine = (obj: { Service: string, State: string, Name: string, Health: string }) => {
if (!statusList.has(obj.Service)) {
statusList.set(obj.Service, []);
}
statusList.get(obj.Service)?.push({
status: obj.Health || obj.State,
name: obj.Name
});
};
for (let line of lines) {
try {
let obj = JSON.parse(line);
let ports = (obj.Ports as string).split(/,\s*/).filter((s) => {
return s.indexOf("->") >= 0;
});
if (obj.Health === "") {
statusList.set(obj.Service, {
state: obj.State,
ports: ports
});
if (obj instanceof Array) {
obj.forEach(addLine);
} else {
statusList.set(obj.Service, {
state: obj.Health,
ports: ports
});
addLine(obj);
}
} catch (e) {
}
@@ -548,7 +549,6 @@ export class Stack {
log.error("getServiceStatusList", e);
return statusList;
}
}
async startService(socket: DockgeSocket, serviceName: string) {