Skip to content

Commit 8b847ea

Browse files
authored
feat(dashmate): collect docker stats in the doctor command (#2180)
1 parent 54b12ac commit 8b847ea

File tree

3 files changed

+69
-5
lines changed

3 files changed

+69
-5
lines changed
-23.2 KB
Binary file not shown.

packages/dashmate/src/doctor/analyse/analyseServiceContainersFactory.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ export default function analyseServiceContainersFactory(
2020
const servicesNotStarted = [];
2121
const servicesFailed = [];
2222
const servicesOOMKilled = [];
23+
const servicesHighCpuUsage = [];
24+
const servicesHighMemoryUsage = [];
2325

2426
for (const service of services) {
2527
const dockerInspect = samples.getServiceInfo(service.name, 'dockerInspect');
28+
const dockerStats = samples.getServiceInfo(service.name, 'dockerStats');
2629

2730
if (!dockerInspect) {
2831
continue;
@@ -47,6 +50,34 @@ export default function analyseServiceContainersFactory(
4750
service,
4851
});
4952
}
53+
54+
const cpuSystemUsage = dockerStats?.cpuStats?.system_cpu_usage ?? 0;
55+
const cpuServiceUsage = dockerStats?.cpuStats?.cpu_usage?.total_usage ?? 0;
56+
57+
if (cpuSystemUsage > 0) {
58+
const cpuUsage = cpuServiceUsage / cpuSystemUsage;
59+
60+
if (cpuUsage > 0.8) {
61+
servicesHighCpuUsage.push({
62+
service,
63+
cpuUsage,
64+
});
65+
}
66+
}
67+
68+
const memoryLimit = dockerStats?.memoryStats?.limit ?? 0;
69+
const memoryServiceUsage = dockerStats?.memoryStats?.usage ?? 0;
70+
71+
if (memoryLimit > 0) {
72+
const memoryUsage = memoryServiceUsage / memoryLimit;
73+
74+
if (memoryUsage > 0.8) {
75+
servicesHighMemoryUsage.push({
76+
service,
77+
memoryUsage,
78+
});
79+
}
80+
}
5081
}
5182

5283
const problems = [];
@@ -103,6 +134,34 @@ export default function analyseServiceContainersFactory(
103134
problems.push(problem);
104135
}
105136

137+
if (servicesHighCpuUsage.length > 0) {
138+
for (const highCpuService of servicesHighCpuUsage) {
139+
const description = `Service ${highCpuService.service.title} is consuming ${(highCpuService.cpuUsage * 100).toFixed(2)}% CPU.`;
140+
141+
const problem = new Problem(
142+
description,
143+
'Consider upgrading CPU or report in case of misbehaviour.',
144+
SEVERITY.MEDIUM,
145+
);
146+
147+
problems.push(problem);
148+
}
149+
}
150+
151+
if (servicesHighMemoryUsage.length > 0) {
152+
for (const highMemoryService of servicesHighMemoryUsage) {
153+
const description = `Service ${highMemoryService.service.title} is consuming ${(highMemoryService.memoryUsage * 100).toFixed(2)}% RAM.`;
154+
155+
const problem = new Problem(
156+
description,
157+
'Consider upgrading RAM or report in case of misbehaviour.',
158+
SEVERITY.MEDIUM,
159+
);
160+
161+
problems.push(problem);
162+
}
163+
}
164+
106165
return problems;
107166
}
108167

packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'fs';
22
import { Listr } from 'listr2';
33
import path from 'path';
44
import process from 'process';
5+
import si from 'systeminformation';
56
import obfuscateConfig from '../../../config/obfuscateConfig.js';
67
import { DASHMATE_VERSION } from '../../../constants.js';
78
import Certificate from '../../../ssl/zerossl/Certificate.js';
@@ -312,20 +313,23 @@ export default function collectSamplesTaskFactory(
312313
},
313314
},
314315
{
315-
title: 'Logs',
316-
task: async (ctx, task) => {
316+
title: 'Docker containers info',
317+
task: async (ctx) => {
317318
const services = await getServiceList(config);
318319

319-
// eslint-disable-next-line no-param-reassign
320-
task.output = `Pulling logs from ${services.map((e) => e.name)}`;
321-
322320
await Promise.all(
323321
services.map(async (service) => {
324322
const [inspect, logs] = (await Promise.allSettled([
325323
dockerCompose.inspectService(config, service.name),
326324
dockerCompose.logs(config, [service.name], { tail: 300000 }),
327325
])).map((e) => e.value || e.reason);
328326

327+
const containerId = inspect?.Id;
328+
let dockerStats;
329+
if (containerId) {
330+
dockerStats = await si.dockerContainerStats(containerId);
331+
}
332+
329333
if (logs?.out) {
330334
// Hide username & external ip from logs
331335
logs.out = logs.out.replaceAll(
@@ -354,6 +358,7 @@ export default function collectSamplesTaskFactory(
354358
ctx.samples.setServiceInfo(service.name, 'stdOut', logs?.out);
355359
ctx.samples.setServiceInfo(service.name, 'stdErr', logs?.err);
356360
ctx.samples.setServiceInfo(service.name, 'dockerInspect', inspect);
361+
ctx.samples.setServiceInfo(service.name, 'dockerStats', dockerStats);
357362
}),
358363
);
359364
},

0 commit comments

Comments
 (0)