tuimon 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/quick/presets/docker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"docker.d.ts","sourceRoot":"","sources":["../../../src/quick/presets/docker.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAmC9C,wBAAgB,YAAY,IAAI,YAAY,CA2I3C"}
|
|
@@ -2,6 +2,22 @@ import { execSync, spawn } from 'node:child_process';
|
|
|
2
2
|
function parsePercent(value) {
|
|
3
3
|
return parseFloat(value.replace('%', '')) || 0;
|
|
4
4
|
}
|
|
5
|
+
function parseMemToMB(memStr) {
|
|
6
|
+
// "25.82MiB", "1.23GiB", "500KiB", "78.13MiB / 31.27GiB"
|
|
7
|
+
const used = memStr.split('/')[0]?.trim() ?? memStr;
|
|
8
|
+
const match = used.match(/([\d.]+)\s*(KiB|MiB|GiB|B|KB|MB|GB)/i);
|
|
9
|
+
if (!match)
|
|
10
|
+
return 0;
|
|
11
|
+
const val = parseFloat(match[1] ?? '0');
|
|
12
|
+
const unit = (match[2] ?? '').toLowerCase();
|
|
13
|
+
if (unit === 'gib' || unit === 'gb')
|
|
14
|
+
return Math.round(val * 1024);
|
|
15
|
+
if (unit === 'mib' || unit === 'mb')
|
|
16
|
+
return Math.round(val);
|
|
17
|
+
if (unit === 'kib' || unit === 'kb')
|
|
18
|
+
return Math.round(val / 1024);
|
|
19
|
+
return 0;
|
|
20
|
+
}
|
|
5
21
|
export function dockerPreset() {
|
|
6
22
|
// Verify docker is available
|
|
7
23
|
try {
|
|
@@ -17,31 +33,40 @@ export function dockerPreset() {
|
|
|
17
33
|
const statsProc = spawn('docker', [
|
|
18
34
|
'stats', '--format', '{{json .}}',
|
|
19
35
|
], { stdio: ['ignore', 'pipe', 'ignore'] });
|
|
36
|
+
// Strip ANSI escape sequences from docker stats output
|
|
37
|
+
function stripAnsi(s) {
|
|
38
|
+
return s.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '').replace(/\x1b\[?[0-9;]*[A-Za-z]/g, '');
|
|
39
|
+
}
|
|
20
40
|
let lineBuf = '';
|
|
41
|
+
let currentBatch = [];
|
|
21
42
|
statsProc.stdout.on('data', (chunk) => {
|
|
22
|
-
lineBuf += chunk.toString();
|
|
23
|
-
// docker stats outputs a batch of lines (one per container) then a blank separator
|
|
43
|
+
lineBuf += stripAnsi(chunk.toString());
|
|
24
44
|
const lines = lineBuf.split('\n');
|
|
25
|
-
|
|
45
|
+
// Keep last potentially incomplete line
|
|
46
|
+
lineBuf = lines.pop() ?? '';
|
|
26
47
|
for (const line of lines) {
|
|
27
48
|
const trimmed = line.trim();
|
|
28
|
-
if (!trimmed)
|
|
29
|
-
// End of batch - update cache
|
|
30
|
-
if (batch.length > 0) {
|
|
31
|
-
latestStats = batch.slice();
|
|
32
|
-
statsReady = true;
|
|
33
|
-
}
|
|
49
|
+
if (!trimmed)
|
|
34
50
|
continue;
|
|
35
|
-
|
|
51
|
+
// Try to parse each line as JSON
|
|
36
52
|
try {
|
|
37
|
-
|
|
53
|
+
const entry = JSON.parse(trimmed);
|
|
54
|
+
currentBatch.push(entry);
|
|
55
|
+
// Docker stats outputs one line per container then repeats.
|
|
56
|
+
// We detect a new batch when we see a Name we already have in the current batch.
|
|
57
|
+
const names = currentBatch.map((e) => e.Name);
|
|
58
|
+
const hasDuplicate = names.length !== new Set(names).size;
|
|
59
|
+
if (hasDuplicate) {
|
|
60
|
+
// The last entry is the start of a new batch - save everything before it
|
|
61
|
+
latestStats = currentBatch.slice(0, -1);
|
|
62
|
+
currentBatch = [entry];
|
|
63
|
+
statsReady = true;
|
|
64
|
+
}
|
|
38
65
|
}
|
|
39
66
|
catch {
|
|
40
|
-
//
|
|
67
|
+
// Not JSON, skip
|
|
41
68
|
}
|
|
42
69
|
}
|
|
43
|
-
// Keep the last incomplete line in buffer
|
|
44
|
-
lineBuf = lines[lines.length - 1] ?? '';
|
|
45
70
|
});
|
|
46
71
|
// Clean up on exit
|
|
47
72
|
process.once('beforeExit', () => { statsProc.kill(); });
|
|
@@ -52,14 +77,14 @@ export function dockerPreset() {
|
|
|
52
77
|
stats: [
|
|
53
78
|
{ id: 'containers', label: 'Containers', type: 'stat' },
|
|
54
79
|
{ id: 'running', label: 'Running', type: 'stat' },
|
|
55
|
-
{ id: 'totalCpu', label: 'CPU
|
|
56
|
-
{ id: 'totalMem', label: 'Memory', type: '
|
|
80
|
+
{ id: 'totalCpu', label: 'Total CPU %', type: 'stat' },
|
|
81
|
+
{ id: 'totalMem', label: 'Total Memory', type: 'stat' },
|
|
57
82
|
],
|
|
58
83
|
panels: [
|
|
59
|
-
{ id: 'cpuHistory', label: 'CPU per Container', type: 'line', span: 2 },
|
|
84
|
+
{ id: 'cpuHistory', label: 'CPU % per Container', type: 'line', span: 2 },
|
|
60
85
|
{ id: 'health', label: 'Container Status', type: 'status-grid' },
|
|
61
|
-
{ id: 'memUsage', label: 'Memory
|
|
62
|
-
{ id: '
|
|
86
|
+
{ id: 'memUsage', label: 'Memory Usage', type: 'bar' },
|
|
87
|
+
{ id: 'containerTable', label: 'Container Details', type: 'table', span: 2 },
|
|
63
88
|
],
|
|
64
89
|
};
|
|
65
90
|
const data = () => {
|
|
@@ -84,30 +109,39 @@ export function dockerPreset() {
|
|
|
84
109
|
const totalContainers = psEntries.length;
|
|
85
110
|
const runningCount = psEntries.filter((c) => c.State === 'running').length;
|
|
86
111
|
const totalCpu = statsEntries.reduce((sum, e) => sum + parsePercent(e.CPUPerc), 0);
|
|
87
|
-
const
|
|
88
|
-
? statsEntries.reduce((sum, e) => sum + parsePercent(e.MemPerc), 0) / statsEntries.length
|
|
89
|
-
: 0;
|
|
112
|
+
const totalMemMB = statsEntries.reduce((sum, e) => sum + parseMemToMB(e.MemUsage), 0);
|
|
90
113
|
const cpuHistory = {};
|
|
114
|
+
const memUsage = {};
|
|
91
115
|
for (const entry of statsEntries) {
|
|
92
116
|
cpuHistory[entry.Name] = parsePercent(entry.CPUPerc);
|
|
117
|
+
memUsage[entry.Name] = parseMemToMB(entry.MemUsage);
|
|
93
118
|
}
|
|
94
119
|
const health = psEntries.map((c) => ({
|
|
95
120
|
label: c.Names,
|
|
96
121
|
status: c.State === 'running' ? 'ok' : c.State === 'exited' ? 'error' : 'warn',
|
|
97
122
|
}));
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
123
|
+
// Full container details table
|
|
124
|
+
const containerTable = {
|
|
125
|
+
columns: ['Name', 'CPU %', 'Memory', 'Mem %', 'Net I/O', 'Block I/O', 'PIDs'],
|
|
126
|
+
rows: statsEntries.map((e) => ({
|
|
127
|
+
'Name': e.Name,
|
|
128
|
+
'CPU %': e.CPUPerc,
|
|
129
|
+
'Memory': e.MemUsage.split('/')[0]?.trim() ?? '',
|
|
130
|
+
'Mem %': e.MemPerc,
|
|
131
|
+
'Net I/O': e.NetIO,
|
|
132
|
+
'Block I/O': e.BlockIO,
|
|
133
|
+
'PIDs': e.PIDs,
|
|
134
|
+
})),
|
|
135
|
+
};
|
|
102
136
|
return {
|
|
103
137
|
containers: totalContainers,
|
|
104
138
|
running: runningCount,
|
|
105
|
-
totalCpu:
|
|
106
|
-
totalMem:
|
|
139
|
+
totalCpu: { value: totalCpu.toFixed(2) + '%', trend: statsEntries.length > 0 ? `${statsEntries.length} containers` : '' },
|
|
140
|
+
totalMem: { value: totalMemMB > 1024 ? (totalMemMB / 1024).toFixed(1) + ' GB' : totalMemMB + ' MB' },
|
|
107
141
|
cpuHistory,
|
|
108
142
|
health,
|
|
109
143
|
memUsage,
|
|
110
|
-
|
|
144
|
+
containerTable,
|
|
111
145
|
};
|
|
112
146
|
};
|
|
113
147
|
return { layout, data, refresh: 1000 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../src/quick/presets/docker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../../src/quick/presets/docker.ts"],"names":[],"mappings":"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"}
|