#include <stdio.
h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#define MAX_METRICS 1024
#define NAME_LEN 64
#define THRESHOLD 1000 // Default threshold for alerting
typedef struct {
char name[NAME_LEN];
long start_val;
long end_val;
} VmstatMetric;
int read_vmstat(VmstatMetric *metrics, int *count, int is_initial_read) {
FILE *fp = fopen("/proc/vmstat", "r");
if (!fp) {
perror("Failed to open /proc/vmstat");
return -1;
char line[256];
int index = 0;
while (fgets(line, sizeof(line), fp)) {
char key[NAME_LEN];
long val;
if (sscanf(line, "%s %ld", key, &val) == 2) {
if (is_initial_read) {
strncpy(metrics[index].name, key, NAME_LEN);
metrics[index].start_val = val;
metrics[index].end_val = val;
index++;
} else {
for (int i = 0; i < *count; i++) {
if (strcmp(metrics[i].name, key) == 0) {
metrics[i].end_val = val;
break;
if (is_initial_read) {
*count = index;
fclose(fp);
return 0;
int compare_growth(const void *a, const void *b) {
VmstatMetric *ma = (VmstatMetric *)a;
VmstatMetric *mb = (VmstatMetric *)b;
long growth_a = ma->end_val - ma->start_val;
long growth_b = mb->end_val - mb->start_val;
return (growth_b - growth_a); // Descending
void export_csv(const char *filename, VmstatMetric *metrics, int count, long duration) {
FILE *fp = fopen(filename, "w");
if (!fp) {
perror("Failed to open output CSV file");
return;
fprintf(fp, "metric,growth,duration(seconds),start,end\n");
for (int i = 0; i < count; i++) {
long growth = metrics[i].end_val - metrics[i].start_val;
if (growth > 0) {
fprintf(fp, "%s,%ld,%ld,%ld,%ld\n",
metrics[i].name, growth, duration,
metrics[i].start_val, metrics[i].end_val);
fclose(fp);
printf("[✔] CSV exported to %s\n", filename);
void display_top_growth(VmstatMetric *metrics, int count, int top_n, long alert_threshold) {
qsort(metrics, count, sizeof(VmstatMetric), compare_growth);
printf("\nTop %d Growing /proc/vmstat Metrics:\n", top_n);
printf("%-25s | %-10s | %-10s\n", "Metric", "Growth", "Alert?");
printf("-------------------------+------------+-----------\n");
for (int i = 0; i < top_n && i < count; i++) {
long growth = metrics[i].end_val - metrics[i].start_val;
if (growth > 0) {
const char *alert = (growth > alert_threshold) ? "YES" : "";
printf("%-25s | %10ld | %s\n", metrics[i].name, growth, alert);
int main(int argc, char *argv[]) {
int interval = 5;
int duration = 30;
int top_n = 10;
long alert_threshold = THRESHOLD;
const char *csv_file = "vmstat_output.csv";
if (argc >= 2) interval = atoi(argv[1]);
if (argc >= 3) duration = atoi(argv[2]);
if (argc >= 4) top_n = atoi(argv[3]);
if (argc >= 5) alert_threshold = atol(argv[4]);
if (argc >= 6) csv_file = argv[5];
printf("Monitoring /proc/vmstat every %d seconds for %d seconds...\n", interval, duration);
printf("Alert threshold: %ld | Output CSV: %s\n", alert_threshold, csv_file);
VmstatMetric metrics[MAX_METRICS];
int metric_count = 0;
if (read_vmstat(metrics, &metric_count, 1) != 0) return 1;
sleep(duration);
if (read_vmstat(metrics, &metric_count, 0) != 0) return 1;
display_top_growth(metrics, metric_count, top_n, alert_threshold);
export_csv(csv_file, metrics, metric_count, duration);
return 0;
}
import pandas as pd
import [Link] as plt
import argparse
def plot_csv(csv_file):
df = pd.read_csv(csv_file)
df = df.sort_values(by="growth", ascending=False)
top = [Link](10)
[Link](figsize=(10, 5))
[Link](top['metric'], top['growth'], color='skyblue')
[Link]("Growth")
[Link]("Top Growing /proc/vmstat Metrics")
[Link]().invert_yaxis()
[Link](True)
plt.tight_layout()
[Link]()
if __name__ == "__main__":
parser = [Link]()
parser.add_argument("csv_file", help="CSV file from vmstat_monitor")
args = parser.parse_args()
plot_csv(args.csv_file)