import * as plugins from '../plugins.js'; import { tspmIpcClient } from '../../client/tspm.ipcclient.js'; import type { CliArguments } from '../types.js'; import { registerIpcCommand } from '../registration/index.js'; import { pad } from '../helpers/formatting.js'; import { formatMemory } from '../helpers/memory.js'; export function registerStatsCommand(smartcli: plugins.smartcli.Smartcli) { registerIpcCommand( smartcli, 'stats', async (_argvArg: CliArguments) => { // Daemon status const status = await tspmIpcClient.request('daemon:status', {}); console.log('TSPM Daemon:'); console.log('─'.repeat(60)); console.log(`Version: ${status.version || 'unknown'}`); console.log(`PID: ${status.pid}`); console.log(`Uptime: ${Math.floor((status.uptime || 0) / 1000)}s`); console.log(`Processes: ${status.processCount}`); if (typeof status.memoryUsage === 'number') { console.log(`Memory: ${formatMemory(status.memoryUsage)}`); } if (typeof status.cpuUsage === 'number') { console.log(`CPU (user): ${status.cpuUsage.toFixed(3)}s`); } if ((status as any).paths) { const pathsInfo = (status as any).paths as { tspmDir?: string; socketPath?: string; pidFile?: string }; console.log(`tspmDir: ${pathsInfo.tspmDir || '-'}`); console.log(`Socket: ${pathsInfo.socketPath || '-'}`); console.log(`PID File: ${pathsInfo.pidFile || '-'}`); } if ((status as any).configs) { const cfg = (status as any).configs as { processConfigs?: number }; console.log(`Configs: ${cfg.processConfigs ?? 0}`); } if ((status as any).logsInMemory) { const lm = (status as any).logsInMemory as { totalCount: number; totalBytes: number }; console.log(`Logs (mem): ${lm.totalCount} entries, ${formatMemory(lm.totalBytes)}`); } console.log(''); // Process list (reuse list view with CPU column) const response = await tspmIpcClient.request('list', {}); const processes = response.processes; console.log('Process List:'); console.log('┌─────────┬─────────────┬───────────┬───────────┬──────────┬──────────┬─────────┐'); console.log('│ ID │ Name │ Status │ PID │ Memory │ CPU │ Restarts │'); console.log('├─────────┼─────────────┼───────────┼───────────┼──────────┼──────────┼──────────┤'); for (const proc of processes) { const statusColor = proc.status === 'online' ? '\x1b[32m' : proc.status === 'errored' ? '\x1b[31m' : '\x1b[33m'; const resetColor = '\x1b[0m'; const cpuStr = typeof proc.cpu === 'number' && isFinite(proc.cpu) ? `${proc.cpu.toFixed(1)}%` : '-'; const nameDisplay = String(proc.id); // name not carried in IProcessInfo console.log( `│ ${pad(String(proc.id), 7)} │ ${pad(nameDisplay, 11)} │ ${statusColor}${pad(proc.status, 9)}${resetColor} │ ${pad((proc.pid || '-').toString(), 9)} │ ${pad(formatMemory(proc.memory), 8)} │ ${pad(cpuStr, 8)} │ ${pad(proc.restarts.toString(), 8)} │`, ); } console.log('└─────────┴─────────────┴───────────┴───────────┴──────────┴──────────┴──────────┘'); }, { actionLabel: 'get daemon stats' }, ); }