Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 76 additions & 6 deletions src/proclens.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <limits.h>
#include <sys/select.h>
#include <termios.h>
#include <time.h>
Expand Down Expand Up @@ -130,11 +131,13 @@ struct overview_metrics {
unsigned long long rss_kb;
unsigned long long rx_bytes;
unsigned long long tx_bytes;
unsigned long long read_bytes;
unsigned long long write_bytes;
int has_cpu;
int has_rss;
int has_rx;
int has_tx;
int has_read;
int has_write;
};

Expand Down Expand Up @@ -469,6 +472,48 @@ static int parse_first_u64(const char *line, unsigned long long *value)
return sscanf(cursor, "%llu", value) == 1;
}

static int parse_size_field_bytes(const char *line, unsigned long long *value)
{
char unit[8] = {0};
const char *cursor;
unsigned long long number;
unsigned long long multiplier = 1;

if (!line || !value)
return 0;

cursor = line;
while (*cursor && (*cursor < '0' || *cursor > '9'))
cursor++;

if (*cursor == '\0')
return 0;

if (sscanf(cursor, "%llu %7s", &number, unit) < 1)
return 0;

if (unit[0] != '\0') {
if (strcmp(unit, "B") == 0)
multiplier = 1;
else if (strcmp(unit, "KB") == 0)
multiplier = 1024ULL;
else if (strcmp(unit, "MB") == 0)
multiplier = 1024ULL * 1024ULL;
else if (strcmp(unit, "GB") == 0)
multiplier = 1024ULL * 1024ULL * 1024ULL;
else if (strcmp(unit, "TB") == 0)
multiplier = 1024ULL * 1024ULL * 1024ULL * 1024ULL;
else
return 0;
}

if (number > (ULLONG_MAX / multiplier))
return 0;

*value = number * multiplier;
return 1;
}

static void extract_overview_metrics(const struct live_snapshot *snapshot,
struct overview_metrics *metrics)
{
Expand All @@ -495,17 +540,22 @@ static void extract_overview_metrics(const struct live_snapshot *snapshot,
}

if (copy_line_with_prefix(snapshot->det_content, "rx_bytes:", line, sizeof(line)) &&
parse_first_u64(line, &metrics->rx_bytes)) {
parse_size_field_bytes(line, &metrics->rx_bytes)) {
metrics->has_rx = 1;
}

if (copy_line_with_prefix(snapshot->det_content, "tx_bytes:", line, sizeof(line)) &&
parse_first_u64(line, &metrics->tx_bytes)) {
parse_size_field_bytes(line, &metrics->tx_bytes)) {
metrics->has_tx = 1;
}

if (copy_line_with_prefix(snapshot->det_content, "read_bytes:", line, sizeof(line)) &&
parse_size_field_bytes(line, &metrics->read_bytes)) {
metrics->has_read = 1;
}

if (copy_line_with_prefix(snapshot->det_content, "write_bytes:", line, sizeof(line)) &&
parse_first_u64(line, &metrics->write_bytes)) {
parse_size_field_bytes(line, &metrics->write_bytes)) {
metrics->has_write = 1;
}
}
Expand Down Expand Up @@ -592,6 +642,7 @@ static int collect_overview_series(const struct live_snapshot *history,
unsigned long long *rss_values,
unsigned long long *rx_rate_values,
unsigned long long *tx_rate_values,
unsigned long long *read_rate_values,
unsigned long long *write_rate_values,
int max_values)
{
Expand Down Expand Up @@ -636,6 +687,13 @@ static int collect_overview_series(const struct live_snapshot *history,
tx_rate_values[points] = 0;
}

if (have_previous && metrics.has_read && previous_metrics.has_read &&
metrics.read_bytes >= previous_metrics.read_bytes) {
read_rate_values[points] = metrics.read_bytes - previous_metrics.read_bytes;
} else {
read_rate_values[points] = 0;
}

if (have_previous && metrics.has_write && previous_metrics.has_write &&
metrics.write_bytes >= previous_metrics.write_bytes) {
write_rate_values[points] =
Expand All @@ -662,47 +720,56 @@ static void print_overview_plots(const struct live_snapshot *snapshot,
unsigned long long rss_values[OVERVIEW_PLOT_WIDTH];
unsigned long long rx_rate_values[OVERVIEW_PLOT_WIDTH];
unsigned long long tx_rate_values[OVERVIEW_PLOT_WIDTH];
unsigned long long read_rate_values[OVERVIEW_PLOT_WIDTH];
unsigned long long write_rate_values[OVERVIEW_PLOT_WIDTH];
struct overview_metrics current_metrics;
char cpu_plot[OVERVIEW_PLOT_BUF_SIZE];
char rss_plot[OVERVIEW_PLOT_BUF_SIZE];
char rx_plot[OVERVIEW_PLOT_BUF_SIZE];
char tx_plot[OVERVIEW_PLOT_BUF_SIZE];
char read_plot[OVERVIEW_PLOT_BUF_SIZE];
char write_plot[OVERVIEW_PLOT_BUF_SIZE];
char rss_label[32];
char rx_label[32];
char tx_label[32];
char read_label[32];
char write_label[32];
unsigned long long current_rx_rate = 0;
unsigned long long current_tx_rate = 0;
unsigned long long current_read_rate = 0;
unsigned long long current_write_rate = 0;
int point_count;

memset(cpu_values, 0, sizeof(cpu_values));
memset(rss_values, 0, sizeof(rss_values));
memset(rx_rate_values, 0, sizeof(rx_rate_values));
memset(tx_rate_values, 0, sizeof(tx_rate_values));
memset(read_rate_values, 0, sizeof(read_rate_values));
memset(write_rate_values, 0, sizeof(write_rate_values));

point_count = collect_overview_series(
history, history_count, history_next, browse_offset, cpu_values, rss_values,
rx_rate_values, tx_rate_values, write_rate_values, ARRAY_SIZE(cpu_values));
point_count = collect_overview_series(history, history_count, history_next, browse_offset,
cpu_values, rss_values, rx_rate_values,
tx_rate_values, read_rate_values, write_rate_values,
ARRAY_SIZE(cpu_values));
render_sparkline(cpu_values, point_count, cpu_plot, sizeof(cpu_plot));
render_sparkline(rss_values, point_count, rss_plot, sizeof(rss_plot));
render_sparkline(rx_rate_values, point_count, rx_plot, sizeof(rx_plot));
render_sparkline(tx_rate_values, point_count, tx_plot, sizeof(tx_plot));
render_sparkline(read_rate_values, point_count, read_plot, sizeof(read_plot));
render_sparkline(write_rate_values, point_count, write_plot, sizeof(write_plot));

extract_overview_metrics(snapshot, &current_metrics);
if (point_count > 0) {
current_rx_rate = rx_rate_values[point_count - 1];
current_tx_rate = tx_rate_values[point_count - 1];
current_read_rate = read_rate_values[point_count - 1];
current_write_rate = write_rate_values[point_count - 1];
}

format_compact_size(current_metrics.rss_kb * 1024ULL, rss_label, sizeof(rss_label), NULL);
format_compact_size(current_rx_rate, rx_label, sizeof(rx_label), "/s");
format_compact_size(current_tx_rate, tx_label, sizeof(tx_label), "/s");
format_compact_size(current_read_rate, read_label, sizeof(read_label), "/s");
format_compact_size(current_write_rate, write_label, sizeof(write_label), "/s");

printf("%s%sTRENDS%s\n", color_code(C_CYAN), color_code(C_BOLD), color_code(C_RESET));
Expand All @@ -725,6 +792,9 @@ static void print_overview_plots(const struct live_snapshot *snapshot,
printf("%s TX/s |%s| %s%s\n", color_code(C_CYAN), tx_plot, tx_label,
color_code(C_RESET));
puts("");
printf("%s RD/s |%s| %s%s\n", color_code(C_CYAN), read_plot, read_label,
color_code(C_RESET));
puts("");
printf("%s WR/s |%s| %s%s\n", color_code(C_CYAN), write_plot, write_label,
color_code(C_RESET));
puts("");
Expand Down
11 changes: 8 additions & 3 deletions src/proclens_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ static void test_overview_view_combines_sections(void)
"[io]\n"
"syscr: 12\n"
"syscw: 13\n"
"read_bytes: 1024\n"
"write_bytes: 2048\n"
"read_bytes: 1 GB\n"
"write_bytes: 2 GB\n"
"io_intensity: 3072\n";
const char *det_older_1 = "Process ID: 4321\n"
"Name: demo\n"
Expand All @@ -437,6 +437,7 @@ static void test_overview_view_combines_sections(void)
" none\n"
"Open Sockets:\n"
"[io]\n"
"read_bytes: 100 MB\n"
"write_bytes: 300\n";
const char *det_older_2 = "Process ID: 4321\n"
"Name: demo\n"
Expand All @@ -450,7 +451,8 @@ static void test_overview_view_combines_sections(void)
" none\n"
"Open Sockets:\n"
"[io]\n"
"write_bytes: 900\n";
"read_bytes: 512 MB\n"
"write_bytes: 900 MB\n";
const char *threads =
"TID NAME CPU(%) STATE PRIORITY NICE CPU_AFFINITY\n"
"----- --------------- ------- ----- -------- ---- ----------------\n"
Expand Down Expand Up @@ -492,6 +494,7 @@ static void test_overview_view_combines_sections(void)
assert(strstr(output_buf, "█|"));
assert(strstr(output_buf, "RX/s"));
assert(strstr(output_buf, "TX/s"));
assert(strstr(output_buf, "RD/s"));
{
char *rx_line = strstr(output_buf, "RX/s |");
char *tx_line = strstr(output_buf, "TX/s |");
Expand All @@ -511,6 +514,8 @@ static void test_overview_view_combines_sections(void)
assert(has_blank_line);
}
assert(strstr(output_buf, "WR/s"));
assert(strstr(output_buf, "512 MB/s"));
assert(strstr(output_buf, "1 GB/s"));
assert(strstr(output_buf, "MEMORY SNAPSHOT"));
assert(strstr(output_buf, "NETWORK SNAPSHOT"));
assert(strstr(output_buf, "I/O SNAPSHOT"));
Expand Down
Loading