diff --git a/src/ui/http_server.c b/src/ui/http_server.c index e08ed8dbe..3d83bd990 100644 --- a/src/ui/http_server.c +++ b/src/ui/http_server.c @@ -50,6 +50,7 @@ #include #include #include /* GetProcessMemoryInfo */ +#include /* CreateToolhelp32Snapshot, Process32First/Next */ #else #include #include @@ -501,7 +502,7 @@ static void handle_processes(cbm_http_conn_t *c) { int pos = 0; #ifdef _WIN32 - /* Windows: GetProcessMemoryInfo + GetProcessTimes */ + /* Windows: GetProcessMemoryInfo + GetProcessTimes for the current process */ PROCESS_MEMORY_COUNTERS pmc; FILETIME ft_create, ft_exit, ft_kernel, ft_user; double user_s = 0, sys_s = 0; @@ -519,8 +520,77 @@ static void handle_processes(cbm_http_conn_t *c) { } http_appendf(buf, sizeof(buf), &pos, "{\"self_pid\":%d,\"self_rss_mb\":%.1f," - "\"self_user_cpu_s\":%.1f,\"self_sys_cpu_s\":%.1f,\"processes\":[]}", + "\"self_user_cpu_s\":%.1f,\"self_sys_cpu_s\":%.1f,\"processes\":[", (int)_getpid(), (double)rss_bytes / (1024.0 * 1024.0), user_s, sys_s); + + /* Enumerate all codebase-memory-mcp.exe processes via toolhelp snapshot */ + int proc_count = 0; + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap != INVALID_HANDLE_VALUE) { + PROCESSENTRY32 pe; + pe.dwSize = sizeof(pe); + for (BOOL ok = Process32First(hSnap, &pe); ok; ok = Process32Next(hSnap, &pe)) { + if (_stricmp(pe.szExeFile, "codebase-memory-mcp.exe") == 0) { + HANDLE hProc = OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, pe.th32ProcessID); + if (hProc) { + PROCESS_MEMORY_COUNTERS ppmc; + FILETIME ftc, fte, ftk, ftu; + double cpu_user = 0, cpu_sys = 0; + size_t proc_rss = 0; + + if (GetProcessMemoryInfo(hProc, &ppmc, sizeof(ppmc))) + proc_rss = ppmc.WorkingSetSize; + + if (GetProcessTimes(hProc, &ftc, &fte, &ftk, &ftu)) { + ULARGE_INTEGER pu, pk; + pu.LowPart = ftu.dwLowDateTime; + pu.HighPart = ftu.dwHighDateTime; + pk.LowPart = ftk.dwLowDateTime; + pk.HighPart = ftk.dwHighDateTime; + cpu_user = (double)pu.QuadPart / 1e7; + cpu_sys = (double)pk.QuadPart / 1e7; + } + + /* Elapsed time since process creation */ + FILETIME now_ft; + GetSystemTimeAsFileTime(&now_ft); + ULARGE_INTEGER now_uli, start_uli; + now_uli.LowPart = now_ft.dwLowDateTime; + now_uli.HighPart = now_ft.dwHighDateTime; + start_uli.LowPart = ftc.dwLowDateTime; + start_uli.HighPart = ftc.dwHighDateTime; + ULONGLONG elapsed_100ns = now_uli.QuadPart - start_uli.QuadPart; + DWORD elapsed_sec = (DWORD)(elapsed_100ns / 10000000ULL); + + if (proc_count > 0) + buf[pos++] = ','; + http_appendf(buf, sizeof(buf), &pos, + "{\"pid\":%lu,\"cpu\":%.1f,\"rss_mb\":%.1f," + "\"elapsed\":\"%lu-%02lu:%02lu:%02lu\"," + "\"command\":\"codebase-memory-mcp\"," + "\"is_self\":%s}", + pe.th32ProcessID, cpu_user + cpu_sys, + (double)proc_rss / (1024.0 * 1024.0), + elapsed_sec / 86400, + (elapsed_sec % 86400) / 3600, + (elapsed_sec % 3600) / 60, + elapsed_sec % 60, + pe.th32ProcessID == (DWORD)_getpid() + ? "true" : "false"); + if (pos >= (int)sizeof(buf)) { + pos = (int)sizeof(buf) - 1; + } + proc_count++; + CloseHandle(hProc); + } + } + } + CloseHandle(hSnap); + } + + http_appendf(buf, sizeof(buf), &pos, "]}"); #else struct rusage ru; getrusage(RUSAGE_SELF, &ru);