From 81e9ffca942112b092d5cc7d187222b4dfb088f5 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 18:24:14 +0000 Subject: [PATCH 01/11] plugins: adding C version of multicpu1sec --- plugins/system/multicpu1sec/multicpu1sec-c.c | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 plugins/system/multicpu1sec/multicpu1sec-c.c diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c new file mode 100644 index 00000000..a875e677 --- /dev/null +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -0,0 +1,76 @@ +/* + * multicpu1sec C plugin + */ +#include +#include + +#define PROC_STAT "/proc/stat" + +int fail(char* msg) { + perror(msg); + + return 1; +} + +int config() { + /* Get the number of CPU */ + FILE* f; + if ( !(f=fopen(PROC_STAT, "r")) ) { + return fail("cannot open " PROC_STAT); + } + + // Starting with -1, since the first line is the "global cpu line" + int ncpu = -1; + while (! feof(f)) { + char buffer[1024]; + if (fgets(buffer, 1024, f) == 0) { + break; + } + + if (! strncmp(buffer, "cpu", 3)) ncpu ++; + } + + fclose(f); + + printf( + "graph_title multicpu1sec\n" + "graph_category system::1sec\n" + "graph_vlabel average cpu use %\n" + "graph_scale no\n" + "graph_total All CPUs\n" + "update_rate 1\n" + "graph_data_size custom 1d, 10s for 1w, 1m for 1t, 5m for 1y\n" + ); + + int i; + for (i = 0; i < ncpu; i++) { + printf("cpu%d.label CPU %d\n", i, i); + printf("cpu%d.draw %s\n", i, "AREASTACK"); + printf("cpu%d.min 0\n", i); + } + + +} + +int acquire() { + printf("acquire()\n"); +} + +int fetch() { + printf("fetch()\n"); +} + +int main(int argc, char **argv) { + if (argc > 1) { + char* first_arg = argv[1]; + if (! strcmp(first_arg, "config")) { + return config(); + } + + if (! strcmp(first_arg, "acquire")) { + return acquire(); + } + } + + return fetch(); +} From 9ac74f8d9b6e942745b010eee97b558bd8593253 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:28:37 +0000 Subject: [PATCH 02/11] multicpu1sec-c: implement the "acquire" cmd --- plugins/system/multicpu1sec/multicpu1sec-c.c | 72 +++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index a875e677..cc31288a 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -3,6 +3,9 @@ */ #include #include +#include + +#include #define PROC_STAT "/proc/stat" @@ -35,7 +38,7 @@ int config() { printf( "graph_title multicpu1sec\n" "graph_category system::1sec\n" - "graph_vlabel average cpu use %\n" + "graph_vlabel average cpu use %%\n" "graph_scale no\n" "graph_total All CPUs\n" "update_rate 1\n" @@ -50,14 +53,81 @@ int config() { } + return 0; +} + +char* pid_filename = "./multicpu1sec.pid"; +char* cache_filename = "./multicpu1sec.value"; + +/* Wait until the next second, and return the EPOCH */ +time_t wait_until_next_second() { + struct timespec tp; + clock_gettime(CLOCK_REALTIME, &tp); + + time_t current_epoch = tp.tv_sec; + long nsec_to_sleep = 1000*1000*1000 - tp.tv_nsec; + + + /* Only sleep if needed */ + if (nsec_to_sleep > 0) { + tp.tv_sec = 0; + tp.tv_nsec = nsec_to_sleep; + nanosleep(&tp, NULL); + } + + return current_epoch + 1; } int acquire() { printf("acquire()\n"); + + /* write the pid */ + FILE* pid_file = fopen(pid_filename, "w"); + fprintf(pid_file, "%d\n", getpid()); + fclose(pid_file); + + /* loop each second */ + while (1) { + /* wait until next second */ + time_t epoch = wait_until_next_second(); + + /* Reading /proc/stat */ + FILE* f = fopen(PROC_STAT, "r"); + // Read and ignore the 1rst line + char buffer[1024]; + fgets(buffer, 1024, f); + + /* open the spoolfile */ + + FILE* cache_file = fopen(cache_filename, "a"); + + while (! feof(f)) { + if (fgets(buffer, 1024, f) == 0) { + // EOF + break; + } + + // Not on CPU lines anymore + if (strncmp(buffer, "cpu", 3)) break; + + char cpu_id[64]; + long usr, nice, sys, idle, iowait, irq, softirq; + sscanf(buffer, "%s %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq); + + long used = usr + nice + sys + idle + iowait + irq + softirq; + + fprintf(cache_file, "%s.value %ld:%ld\n", cpu_id, epoch, used); + } + + fclose(cache_file); + fclose(f); + } } int fetch() { printf("fetch()\n"); + + return 0; } int main(int argc, char **argv) { From c86e4ab2fd17a23f62d44bcda5fc90f6776d94c0 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:29:41 +0000 Subject: [PATCH 03/11] multicpu1sec-c: implement the "fetch" cmd --- plugins/system/multicpu1sec/multicpu1sec-c.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index cc31288a..e3c02956 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -126,8 +126,16 @@ int acquire() { int fetch() { printf("fetch()\n"); + FILE* cache_file = fopen(cache_filename, "r"); - return 0; + /* cat the cache_file to stdout */ + char buffer[1024]; + while (fgets(buffer, 1024, cache_file)) { + printf("%s", buffer); + } + + ftruncate(fileno(cache_file), 0); + fclose(cache_file); } int main(int argc, char **argv) { From 6dec8c33578bc22d925b64fa02626fe75229ce58 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:35:46 +0000 Subject: [PATCH 04/11] multicpu1sec-c: opening the file r/w to truncate it --- plugins/system/multicpu1sec/multicpu1sec-c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index e3c02956..5c99d831 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -126,7 +126,7 @@ int acquire() { int fetch() { printf("fetch()\n"); - FILE* cache_file = fopen(cache_filename, "r"); + FILE* cache_file = fopen(cache_filename, "r+"); /* cat the cache_file to stdout */ char buffer[1024]; From 339bfec68fc4c86da37c77710c16b0eee6426360 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:40:37 +0000 Subject: [PATCH 05/11] multicpu1sec-c: adding locking to avoid races --- plugins/system/multicpu1sec/multicpu1sec-c.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index 5c99d831..95718d33 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -7,6 +7,8 @@ #include +#include + #define PROC_STAT "/proc/stat" int fail(char* msg) { @@ -98,8 +100,9 @@ int acquire() { fgets(buffer, 1024, f); /* open the spoolfile */ - FILE* cache_file = fopen(cache_filename, "a"); + /* lock */ + flock(fileno(cache_file), LOCK_EX); while (! feof(f)) { if (fgets(buffer, 1024, f) == 0) { @@ -128,6 +131,9 @@ int fetch() { printf("fetch()\n"); FILE* cache_file = fopen(cache_filename, "r+"); + /* lock */ + flock(fileno(cache_file), LOCK_EX); + /* cat the cache_file to stdout */ char buffer[1024]; while (fgets(buffer, 1024, cache_file)) { From 4a9b0e47968c7572252fd42cfbbe7cd5750e642e Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:43:39 +0000 Subject: [PATCH 06/11] multicpu1sec-c: remove debugging statements --- plugins/system/multicpu1sec/multicpu1sec-c.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index 95718d33..ebe40249 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -81,7 +81,6 @@ time_t wait_until_next_second() { } int acquire() { - printf("acquire()\n"); /* write the pid */ FILE* pid_file = fopen(pid_filename, "w"); @@ -128,7 +127,6 @@ int acquire() { } int fetch() { - printf("fetch()\n"); FILE* cache_file = fopen(cache_filename, "r+"); /* lock */ From b0e8dcea3966275151c94c21c9d30ce1cb9812f1 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 22:48:20 +0000 Subject: [PATCH 07/11] multicpu1sec-c: using DERIVE We just delegate the whole CPU % computing to RRD --- plugins/system/multicpu1sec/multicpu1sec-c.c | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index ebe40249..fd11c359 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -51,6 +51,7 @@ int config() { for (i = 0; i < ncpu; i++) { printf("cpu%d.label CPU %d\n", i, i); printf("cpu%d.draw %s\n", i, "AREASTACK"); + printf("cpu%d.type %s\n", i, "DERIVE"); printf("cpu%d.min 0\n", i); } From 16b017fcd77bbe3893c1c94118857cac54fa3f6a Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 23:16:41 +0000 Subject: [PATCH 08/11] multicpu1sec-c: handle fork --- plugins/system/multicpu1sec/multicpu1sec-c.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index fd11c359..477d57c0 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -1,6 +1,7 @@ /* * multicpu1sec C plugin */ +#include #include #include #include @@ -83,6 +84,21 @@ time_t wait_until_next_second() { int acquire() { + /* fork ourselves if not asked otherwise */ + char* no_fork = getenv("no_fork"); + if (! no_fork || strcmp("1", no_fork)) { + if (fork()) return; + // we are the child, complete the daemonization + + /* Close standard IO */ + fclose(stdin); + fclose(stdout); + fclose(stderr); + + /* create new session and process group */ + setsid(); + } + /* write the pid */ FILE* pid_file = fopen(pid_filename, "w"); fprintf(pid_file, "%d\n", getpid()); From 79f72b87fb98d281a218d0524963a2f15d760b88 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 3 Mar 2015 23:17:23 +0000 Subject: [PATCH 09/11] multicpu1sec-c: fix value (remove idle) --- plugins/system/multicpu1sec/multicpu1sec-c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index 477d57c0..380e0d3d 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -133,7 +133,7 @@ int acquire() { long usr, nice, sys, idle, iowait, irq, softirq; sscanf(buffer, "%s %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq); - long used = usr + nice + sys + idle + iowait + irq + softirq; + long used = usr + nice + sys + iowait + irq + softirq; fprintf(cache_file, "%s.value %ld:%ld\n", cpu_id, epoch, used); } From 99d3a426271e072375b3e3e7a579b36eccb04766 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Wed, 4 Mar 2015 00:00:05 +0000 Subject: [PATCH 10/11] multicpu1sec-c: fix the /proc/stat parsing --- plugins/system/multicpu1sec/multicpu1sec-c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index 380e0d3d..27d6f15a 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -131,7 +131,7 @@ int acquire() { char cpu_id[64]; long usr, nice, sys, idle, iowait, irq, softirq; - sscanf(buffer, "%s %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq); + sscanf(buffer, "%s %ld %ld %ld %ld %ld %ld %ld", cpu_id, &usr, &nice, &sys, &idle, &iowait, &irq, &softirq); long used = usr + nice + sys + iowait + irq + softirq; From 308ba4757e2768292dc8896fa7346a68b01679cd Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Sun, 8 Mar 2015 18:58:49 +0000 Subject: [PATCH 11/11] multicpu1sec-c: use the env vars for tmp file paths --- plugins/system/multicpu1sec/multicpu1sec-c.c | 21 ++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/plugins/system/multicpu1sec/multicpu1sec-c.c b/plugins/system/multicpu1sec/multicpu1sec-c.c index 27d6f15a..b66eab79 100644 --- a/plugins/system/multicpu1sec/multicpu1sec-c.c +++ b/plugins/system/multicpu1sec/multicpu1sec-c.c @@ -60,8 +60,8 @@ int config() { return 0; } -char* pid_filename = "./multicpu1sec.pid"; -char* cache_filename = "./multicpu1sec.value"; +char* pid_filename; +char* cache_filename; /* Wait until the next second, and return the EPOCH */ time_t wait_until_next_second() { @@ -160,6 +160,23 @@ int fetch() { } int main(int argc, char **argv) { + /* resolve paths */ + char *MUNIN_PLUGSTATE = getenv("MUNIN_PLUGSTATE"); + + /* Default is current directory */ + if (! MUNIN_PLUGSTATE) MUNIN_PLUGSTATE = "."; + + size_t MUNIN_PLUGSTATE_length = strlen(MUNIN_PLUGSTATE); + + pid_filename = malloc(MUNIN_PLUGSTATE_length + strlen("/multicpu1sec.") + strlen("pid") + 1); pid_filename[0] = '\0'; + cache_filename = malloc(MUNIN_PLUGSTATE_length + strlen("/multicpu1sec.") + strlen("value") + 1); cache_filename[0] = '\0'; + + strcat(pid_filename, MUNIN_PLUGSTATE); + strcat(pid_filename, "/multicpu1sec.pid"); + + strcat(cache_filename, MUNIN_PLUGSTATE); + strcat(cache_filename, "/multicpu1sec.value"); + if (argc > 1) { char* first_arg = argv[1]; if (! strcmp(first_arg, "config")) {