feat: add cpu tab and detail view

refactor: move display overview to display.c
feat: display cpu core usage and temperature
feat: display memory usage and swap
feat: display process list with basic info
feat: format bytes for memory and disk stats
feat: display network interfaces and disk stats
feat: display filesystem stats
feat: update memory detail view to include task info
This commit is contained in:
retoor 2025-12-13 05:40:55 +01:00
parent 11926c5459
commit 166092bd6f
4 changed files with 23 additions and 188 deletions

View File

@ -4,7 +4,7 @@
## Version 0.1.0 - 2025-12-13 ## Version 0.1.0 - 2025-12-13
A new system monitoring tool, rtop, has been added. It provides real-time information about CPU, memory, processes, network, disk, and filesystem usage. The application now includes a CPU tab with core usage and temperature details. Users can view memory, process, network, disk, and filesystem statistics, along with improved memory detail views.
**Changes:** 24 files, 2293 lines **Changes:** 3 files, 205 lines
**Languages:** C (1927 lines), Markdown (331 lines), Other (35 lines) **Languages:** C (205 lines)

BIN
rtop

Binary file not shown.

View File

@ -101,181 +101,6 @@ void display_footer(Terminal *term, double refresh_rate) {
terminal_buffer_append(term, buf); terminal_buffer_append(term, buf);
} }
void display_overview(Terminal *term, CpuInfo *cpu, MemoryInfo *mem,
ProcessList *procs, NetworkInfo *net,
DiskInfo *disk, FilesystemInfo *fs) {
char buf[256], tmp[16], tmp2[16];
int row = 4;
int bar_w = 20;
int col2 = 45;
int half = (cpu->num_cores + 1) / 2;
if (half > 4) half = 4;
for (int i = 0; i < half; i++) {
terminal_move_cursor(term, row, 1);
snprintf(buf, sizeof(buf), "%sCPU%-2d%s ", COLOR_CYAN, i, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, cpu->cores[i].usage_percent, bar_w);
snprintf(buf, sizeof(buf), " %5.1f%%", cpu->cores[i].usage_percent);
terminal_buffer_append(term, buf);
int j = i + half;
if (j < cpu->num_cores) {
terminal_move_cursor(term, row, col2);
snprintf(buf, sizeof(buf), "%sCPU%-2d%s ", COLOR_CYAN, j, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, cpu->cores[j].usage_percent, bar_w);
snprintf(buf, sizeof(buf), " %5.1f%%", cpu->cores[j].usage_percent);
terminal_buffer_append(term, buf);
}
row++;
}
terminal_move_cursor(term, row, 1);
snprintf(buf, sizeof(buf), "%sAvg %s ", COLOR_CYAN, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, cpu->total.usage_percent, bar_w);
snprintf(buf, sizeof(buf), " %5.1f%% %s%d cores%s", cpu->total.usage_percent, COLOR_YELLOW, cpu->num_cores, COLOR_RESET);
terminal_buffer_append(term, buf);
terminal_move_cursor(term, row, col2);
if (cpu->temperature > 0) {
const char *tc = cpu->temperature >= 80 ? COLOR_RED : cpu->temperature >= 60 ? COLOR_YELLOW : COLOR_GREEN;
snprintf(buf, sizeof(buf), "%sTemp%s %s%3.0f°C%s ", COLOR_CYAN, COLOR_RESET, tc, cpu->temperature, COLOR_RESET);
terminal_buffer_append(term, buf);
}
if (cpu->frequency_mhz > 0) {
snprintf(buf, sizeof(buf), "%sFreq%s %4.0fMHz", COLOR_CYAN, COLOR_RESET, cpu->frequency_mhz);
terminal_buffer_append(term, buf);
}
row++;
terminal_move_cursor(term, row, 1);
snprintf(buf, sizeof(buf), "%sCtx%s %9.0f/s %sIRQ%s %9.0f/s",
COLOR_CYAN, COLOR_RESET, cpu->context_switches_per_sec,
COLOR_CYAN, COLOR_RESET, cpu->interrupts_per_sec);
terminal_buffer_append(term, buf);
row++;
format_bytes(mem->used * 1024, tmp, sizeof(tmp));
format_bytes(mem->total * 1024, tmp2, sizeof(tmp2));
terminal_move_cursor(term, row, 1);
snprintf(buf, sizeof(buf), "%sMem %s ", COLOR_CYAN, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, mem->used_percent, bar_w);
snprintf(buf, sizeof(buf), " %5.1f%% %s / %s", mem->used_percent, tmp, tmp2);
terminal_buffer_append(term, buf);
format_bytes(mem->swap_used * 1024, tmp, sizeof(tmp));
format_bytes(mem->swap_total * 1024, tmp2, sizeof(tmp2));
terminal_move_cursor(term, row, col2);
snprintf(buf, sizeof(buf), "%sSwap %s ", COLOR_CYAN, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, mem->swap_percent, bar_w);
snprintf(buf, sizeof(buf), " %5.1f%% %s / %s", mem->swap_percent, tmp, tmp2);
terminal_buffer_append(term, buf);
row++;
format_bytes(mem->available * 1024, tmp, sizeof(tmp));
format_bytes(mem->buffers * 1024, tmp2, sizeof(tmp2));
terminal_move_cursor(term, row, 1);
char cache[16];
format_bytes(mem->cached * 1024, cache, sizeof(cache));
snprintf(buf, sizeof(buf), "%sAvail%s %s %sBuf%s %s %sCache%s %s %sPgIn%s %6.0f/s %sPgOut%s %6.0f/s",
COLOR_CYAN, COLOR_RESET, tmp,
COLOR_CYAN, COLOR_RESET, tmp2,
COLOR_CYAN, COLOR_RESET, cache,
COLOR_CYAN, COLOR_RESET, mem->page_in_per_sec,
COLOR_CYAN, COLOR_RESET, mem->page_out_per_sec);
terminal_buffer_append(term, buf);
row++;
terminal_move_cursor(term, row, 1);
snprintf(buf, sizeof(buf), "%sTasks%s %-4d %sRun%s %s%-3d%s %sSlp%s %-4d %sStp%s %s%-2d%s %sZmb%s %s%-2d%s",
COLOR_CYAN, COLOR_RESET, procs->total,
COLOR_CYAN, COLOR_RESET, COLOR_GREEN, procs->running, COLOR_RESET,
COLOR_CYAN, COLOR_RESET, procs->sleeping,
COLOR_CYAN, COLOR_RESET, COLOR_YELLOW, procs->stopped, COLOR_RESET,
COLOR_CYAN, COLOR_RESET, COLOR_RED, procs->zombie, COLOR_RESET);
terminal_buffer_append(term, buf);
row++;
int net_start = row;
for (int i = 0; i < net->count && i < 4; i++) {
NetworkInterface *n = &net->interfaces[i];
char rx[16], tx[16];
format_rate(n->rx_rate, rx, sizeof(rx));
format_rate(n->tx_rate, tx, sizeof(tx));
terminal_move_cursor(term, row++, 1);
snprintf(buf, sizeof(buf), "%s%-10s%s %s%-15s%s %s▼%s%-10s %s▲%s%-10s",
COLOR_CYAN, n->name, COLOR_RESET,
n->up ? COLOR_GREEN : COLOR_RED, n->ip[0] ? n->ip : "-", COLOR_RESET,
COLOR_GREEN, COLOR_RESET, rx,
COLOR_RED, COLOR_RESET, tx);
terminal_buffer_append(term, buf);
}
row = net_start;
for (int i = 0; i < disk->count && i < 4; i++) {
DiskStats *d = &disk->disks[i];
char rd[16], wr[16];
format_rate(d->read_bytes_per_sec, rd, sizeof(rd));
format_rate(d->write_bytes_per_sec, wr, sizeof(wr));
terminal_move_cursor(term, row++, col2);
snprintf(buf, sizeof(buf), "%s%-8s%s %sR%s%-10s %sW%s%-10s %4.0f/%4.0f",
COLOR_CYAN, d->name, COLOR_RESET,
COLOR_GREEN, COLOR_RESET, rd,
COLOR_RED, COLOR_RESET, wr,
d->reads_per_sec, d->writes_per_sec);
terminal_buffer_append(term, buf);
}
int max_net_disk = net->count > disk->count ? net->count : disk->count;
if (max_net_disk > 4) max_net_disk = 4;
row = net_start + max_net_disk;
for (int i = 0; i < fs->count && i < 3; i++) {
FilesystemStats *f = &fs->filesystems[i];
char used[16], total[16];
format_bytes(f->used * 1024, used, sizeof(used));
format_bytes(f->total * 1024, total, sizeof(total));
const char *c = f->used_percent >= 90 ? COLOR_RED : f->used_percent >= 70 ? COLOR_YELLOW : COLOR_GREEN;
terminal_move_cursor(term, row++, 1);
snprintf(buf, sizeof(buf), "%s%-12s%s ", COLOR_CYAN, f->mount_point, COLOR_RESET);
terminal_buffer_append(term, buf);
draw_bar(term, f->used_percent, 15);
snprintf(buf, sizeof(buf), " %s%5.1f%%%s %7s / %7s %s",
c, f->used_percent, COLOR_RESET, used, total, f->fs_type);
terminal_buffer_append(term, buf);
}
row++;
terminal_move_cursor(term, row++, 1);
snprintf(buf, sizeof(buf), "%s%7s %7s %-8s S %5s %5s %7s %6s %3s %3s %-20s%s",
COLOR_BOLD_WHITE, "PID", "PPID", "USER", "CPU%", "MEM%", "RSS", "VIRT", "THR", "NI", "COMMAND", COLOR_RESET);
terminal_buffer_append(term, buf);
int max_procs = term->rows - row - 2;
if (max_procs > 10) max_procs = 10;
for (int i = 0; i < procs->count && i < max_procs; i++) {
ProcessInfo *p = &procs->processes[i];
char rss[16], virt[16];
format_bytes(p->rss, rss, sizeof(rss));
format_bytes(p->vsize, virt, sizeof(virt));
const char *sc = p->state == 'R' ? COLOR_GREEN : p->state == 'D' || p->state == 'Z' ? COLOR_RED : p->state == 'T' ? COLOR_YELLOW : COLOR_RESET;
const char *cpuc = p->cpu_percent >= 50 ? COLOR_RED : p->cpu_percent >= 20 ? COLOR_YELLOW : COLOR_RESET;
const char *memc = p->mem_percent >= 10 ? COLOR_RED : p->mem_percent >= 5 ? COLOR_YELLOW : COLOR_RESET;
terminal_move_cursor(term, row++, 1);
snprintf(buf, sizeof(buf), "%7d %7d %-8.8s %s%c%s %s%5.1f%s %s%5.1f%s %7s %6s %3d %3d %-20.20s",
p->pid, p->ppid, p->user,
sc, p->state, COLOR_RESET,
cpuc, p->cpu_percent, COLOR_RESET,
memc, p->mem_percent, COLOR_RESET,
rss, virt, p->threads, p->nice, p->cmd);
terminal_buffer_append(term, buf);
}
}
void display_cpu_detail(Terminal *term, CpuInfo *cpu) { void display_cpu_detail(Terminal *term, CpuInfo *cpu) {
char buf[128]; char buf[128];
int row = 4; int row = 4;
@ -327,13 +152,23 @@ void display_cpu_detail(Terminal *term, CpuInfo *cpu) {
terminal_buffer_append(term, buf); terminal_buffer_append(term, buf);
} }
void display_memory_detail(Terminal *term, MemoryInfo *mem) { void display_memory_detail(Terminal *term, MemoryInfo *mem, ProcessList *procs) {
char buf[128], tmp[16], tmp2[16]; char buf[256], tmp[16], tmp2[16];
int row = 4; int row = 4;
int bar_w = term->cols - 25; int bar_w = term->cols - 25;
if (bar_w > 50) bar_w = 50; if (bar_w > 50) bar_w = 50;
if (bar_w < 20) bar_w = 20; if (bar_w < 20) bar_w = 20;
terminal_move_cursor(term, row++, 1);
snprintf(buf, sizeof(buf), "%sTasks:%s %d total, %s%d running%s, %d sleeping, %s%d stopped%s, %s%d zombie%s",
COLOR_CYAN, COLOR_RESET, procs->total,
COLOR_GREEN, procs->running, COLOR_RESET,
procs->sleeping,
COLOR_YELLOW, procs->stopped, COLOR_RESET,
COLOR_RED, procs->zombie, COLOR_RESET);
terminal_buffer_append(term, buf);
row++;
format_bytes(mem->used * 1024, tmp, sizeof(tmp)); format_bytes(mem->used * 1024, tmp, sizeof(tmp));
format_bytes(mem->total * 1024, tmp2, sizeof(tmp2)); format_bytes(mem->total * 1024, tmp2, sizeof(tmp2));
terminal_move_cursor(term, row++, 1); terminal_move_cursor(term, row++, 1);

View File

@ -75,7 +75,7 @@ int main(int argc, char *argv[]) {
double refresh_interval = 1.0; double refresh_interval = 1.0;
double rotate_interval = 0.0; double rotate_interval = 0.0;
int sort_by_mem = 0; int sort_by_mem = 0;
int current_tab = TAB_OVERVIEW; int current_tab = TAB_CPU;
static struct option long_options[] = { static struct option long_options[] = {
{"delay", required_argument, 0, 'd'}, {"delay", required_argument, 0, 'd'},