From c136d37bc59c6fa7c325806c733b282b9a0644e6 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 20 Oct 2015 09:04:14 +0200 Subject: [PATCH 1/6] plugins: use a specific load-proc.c for procfs os --- configure.ac | 10 ++++++++++ src/plugins/Makefile.am | 7 ++++++- src/plugins/{load.c => load-proc.c} | 0 3 files changed, 16 insertions(+), 1 deletion(-) rename src/plugins/{load.c => load-proc.c} (100%) diff --git a/configure.ac b/configure.ac index c642204..e403a97 100644 --- a/configure.ac +++ b/configure.ac @@ -15,6 +15,16 @@ AM_INIT_AUTOMAKE([foreign subdir-objects]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AM_MAINTAINER_MODE([enable]) +AC_CANONICAL_HOST +case $host in + *bsd* | *darwin* ) + LOAD_SYSTEM='load-sysctl.$(OBJEXT)' ;; + *) + LOAD_SYSTEM='load-proc.$(OBJEXT)' ;; +esac + +AC_SUBST([LOAD_SYSTEM]) + AC_PROG_CC AC_PROG_CC_C_O diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 4082452..a1c4161 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -21,7 +21,6 @@ munin_plugins_c_SOURCES = \ fw_packets.c \ if_err_.c \ interrupts.c \ - load.c \ main.c \ open_files.c \ open_inodes.c \ @@ -30,6 +29,12 @@ munin_plugins_c_SOURCES = \ threads.c \ memory.c \ uptime.c + +EXTRA_munin_plugins_c_SOURCES = load-proc.c load-sysctl.c + +munin_plugins_c_LDADD = $(LOAD_SYSTEM) +munin_plugins_c_DEPENDENCIES = $(LOAD_SYSTEM) + man_MANS = munin-plugins-c.1 CLEANFILES = $(man_MANS) EXTRA_DIST = munin-plugins-c.pod diff --git a/src/plugins/load.c b/src/plugins/load-proc.c similarity index 100% rename from src/plugins/load.c rename to src/plugins/load-proc.c From 6d943e5826f5d61e1ba1ca3bd850e6f4f04204e4 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Tue, 20 Oct 2015 19:40:00 +0200 Subject: [PATCH 2/6] plugins: adding load-sysctl The BSD systems are sysctl based systems. They don't use the /proc filesystem for that purpose. --- src/plugins/load-sysctl.c | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/plugins/load-sysctl.c diff --git a/src/plugins/load-sysctl.c b/src/plugins/load-sysctl.c new file mode 100644 index 0000000..ca4d751 --- /dev/null +++ b/src/plugins/load-sysctl.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2015 Steve Schnepp - All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2 or v.3. + */ + +/* This plugin is compatible with munin-mainline version 2.0.25. */ + +#include +#include +#include +#include +#include +#include "common.h" +#include "plugins.h" + +#include + +int load(int argc, char **argv) { + if(argc > 1) { + if(!strcmp(argv[1], "config")) { + puts("graph_title Load average\n" + "graph_args --base 1000 -l 0\n" + "graph_vlabel load\n" + "graph_scale no\n" + "graph_category system\n" + "load.label load"); + print_warncrit("load"); + puts("graph_info The load average of the machine describes how many processes are in the run-queue (scheduled to run \"immediately\").\n" + "load.info 5 minute load average"); + return 0; + } + if(!strcmp(argv[1], "autoconf")) + return writeyes(); + } + + struct loadavg l; + size_t len = sizeof(l); + + if (sysctlbyname("vm.loadavg", &l, &len, NULL, 0) < 0) { + return fail("sysctl"); + } + + double ldavg = l.ldavg[0]; + double fscale = l.fscale; + + printf("# vm.loadavg, ldavg:%f fscale:%f -", ldavg, fscale); + printf("\n"); + + double load_1 = ldavg / fscale; + printf("load.value %.2f\n", load_1); + return 0; +} From a0355246e5ebff3f85f936c4d53833d035b34092 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Wed, 6 Apr 2016 20:42:15 +0200 Subject: [PATCH 3/6] plugins: adding the sysctl/proc build config It makes it very easy to have 2 implementation of plugins. Only the correct one gets compiled and linked to the global executable. --- configure.ac | 6 +++--- src/plugins/Makefile.am | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index e403a97..82ca0a3 100644 --- a/configure.ac +++ b/configure.ac @@ -18,12 +18,12 @@ AM_MAINTAINER_MODE([enable]) AC_CANONICAL_HOST case $host in *bsd* | *darwin* ) - LOAD_SYSTEM='load-sysctl.$(OBJEXT)' ;; + SYS_API='sysctl' ;; *) - LOAD_SYSTEM='load-proc.$(OBJEXT)' ;; + SYS_API='proc' ;; esac -AC_SUBST([LOAD_SYSTEM]) +AC_SUBST([SYS_API]) AC_PROG_CC AC_PROG_CC_C_O diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index a1c4161..1af5991 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -12,6 +12,7 @@ include $(top_srcdir)/common.am pkglibexec_PROGRAMS = munin-plugins-c munin_plugins_c_SOURCES = \ + load-$(SYS_API).c \ common.c \ common.h \ plugins.h \ @@ -30,11 +31,6 @@ munin_plugins_c_SOURCES = \ memory.c \ uptime.c -EXTRA_munin_plugins_c_SOURCES = load-proc.c load-sysctl.c - -munin_plugins_c_LDADD = $(LOAD_SYSTEM) -munin_plugins_c_DEPENDENCIES = $(LOAD_SYSTEM) - man_MANS = munin-plugins-c.1 CLEANFILES = $(man_MANS) EXTRA_DIST = munin-plugins-c.pod From 9f0fa9988c371fdfc9eb6a5a27ca45da3a63b7e8 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Wed, 6 Apr 2016 21:02:13 +0200 Subject: [PATCH 4/6] Makefile: fix the .pod -> .1 for non-gnu make --- common.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common.am b/common.am index c6946da..f0dbfc2 100644 --- a/common.am +++ b/common.am @@ -1,7 +1,9 @@ MANCENTER="Munin C Documentation" RELEASE="$(shell $(top_srcdir)/getversion)" -%.1:%.pod +.pod.1: $(AM_V_GEN)pod2man --section=1 --release=$(RELEASE) --center=$(MANCENTER) $< > $@ +SUFFIXES = .1 .pod + # vim:ft=make From 106fdbb4b8f6610eda6aab6bd8da912790e02999 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Wed, 6 Apr 2016 21:07:32 +0200 Subject: [PATCH 5/6] load: sys/resource.h is needed on FreeBSD --- src/plugins/load-sysctl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/load-sysctl.c b/src/plugins/load-sysctl.c index ca4d751..472e2a0 100644 --- a/src/plugins/load-sysctl.c +++ b/src/plugins/load-sysctl.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include "common.h" From 43ff3982e7af9aa63435c5b547b7169b6b529f60 Mon Sep 17 00:00:00 2001 From: Steve Schnepp Date: Sat, 23 Jun 2018 13:58:50 +0200 Subject: [PATCH 6/6] plugins: first BSD version of plugins --- src/common/xctype.h | 7 ++ src/plugins/cpu-sysctl.c | 189 ++++++++++++++++++++++++++++++++++++ src/plugins/memory-sysctl.c | 106 ++++++++++++++++++++ 3 files changed, 302 insertions(+) create mode 100644 src/common/xctype.h create mode 100644 src/plugins/cpu-sysctl.c create mode 100644 src/plugins/memory-sysctl.c diff --git a/src/common/xctype.h b/src/common/xctype.h new file mode 100644 index 0000000..fe67da3 --- /dev/null +++ b/src/common/xctype.h @@ -0,0 +1,7 @@ +/* put here extended versions of + * Only use #define tricks to avoid the overhead of func call + */ + +/* Defined by the ctype(3) in NetBSD */ +#define xisdigit(x) isdigit((int)(unsigned char) (x)) +#define xisspace(x) isspace((int)(unsigned char) (x)) diff --git a/src/plugins/cpu-sysctl.c b/src/plugins/cpu-sysctl.c new file mode 100644 index 0000000..3ea6ead --- /dev/null +++ b/src/plugins/cpu-sysctl.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2015 Steve Schnepp - All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2 or v.3. + */ +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "plugins.h" + +#define SYSWARNING 30 +#define SYSCRITICAL 50 +#define USRWARNING 80 + +/* TODO: port support for env.foo_warning and env.foo_critical from mainline plugin */ + +static int print_stat_value(const char* field_name, const char* stat_value, int hz_) { + return printf("%s.value %llu\n", field_name, strtoull(stat_value, NULL, 0) * 100 / hz_); +} + +int cpu(int argc, char **argv) { + FILE *f; + char buff[256], *s; + int ncpu=0, extinfo=0, hz_; + bool scaleto100 = false; + if(argc > 1) { + if(!strcmp(argv[1], "config")) { + s = getenv("scaleto100"); + if(s && !strcmp(s, "yes")) + scaleto100 = true; + + if(!(f=fopen(PROC_STAT, "r"))) + return fail("cannot open " PROC_STAT); + while(fgets(buff, 256, f)) { + if(!strncmp(buff, "cpu", 3)) { + if(isdigit(buff[3])) + ncpu++; + if(buff[3] == ' ' && 0 == extinfo) { + strtok(buff+4, " \t"); + for(extinfo=1;strtok(NULL, " \t");extinfo++) + ; + } + } + } + fclose(f); + + if(ncpu < 1 || extinfo < 4) + return fail("cannot parse " PROC_STAT); + + puts("graph_title CPU usage"); + if(extinfo >= 7) + puts("graph_order system user nice idle iowait irq softirq"); + else + puts("graph_order system user nice idle"); + if(scaleto100) + puts("graph_args --base 1000 -r --lower-limit 0 --upper-limit 100"); + else + printf("graph_args --base 1000 -r --lower-limit 0 --upper-limit %d\n", 100 * ncpu); + puts("graph_vlabel %\n" + "graph_scale no\n" + "graph_info This graph shows how CPU time is spent.\n" + "graph_category system\n" + "graph_period second\n" + "system.label system\n" + "system.draw AREA"); + printf("system.max %d\n", 100 * ncpu); + puts("system.min 0\n" + "system.type DERIVE"); + printf("system.warning %d\n", SYSWARNING * ncpu); + printf("system.critical %d\n", SYSCRITICAL * ncpu); + puts("system.info CPU time spent by the kernel in system activities\n" + "user.label user\n" + "user.draw STACK\n" + "user.min 0"); + printf("user.max %d\n", 100 * ncpu); + printf("user.warning %d\n", USRWARNING * ncpu); + puts("user.type DERIVE\n" + "user.info CPU time spent by normal programs and daemons\n" + "nice.label nice\n" + "nice.draw STACK\n" + "nice.min 0"); + printf("nice.max %d\n", 100 * ncpu); + puts("nice.type DERIVE\n" + "nice.info CPU time spent by nice(1)d programs\n" + "idle.label idle\n" + "idle.draw STACK\n" + "idle.min 0"); + printf("idle.max %d\n", 100 * ncpu); + puts("idle.type DERIVE\n" + "idle.info Idle CPU time"); + if(scaleto100) + printf("system.cdef system,%d,/\n" + "user.cdef user,%d,/\n" + "nice.cdef nice,%d,/\n" + "idle.cdef idle,%d,/\n", ncpu, ncpu, ncpu, ncpu); + if(extinfo >= 7) { + puts("iowait.label iowait\n" + "iowait.draw STACK\n" + "iowait.min 0"); + printf("iowait.max %d\n", 100 * ncpu); + puts("iowait.type DERIVE\n" + "iowait.info CPU time spent waiting for I/O operations to finish\n" + "irq.label irq\n" + "irq.draw STACK\n" + "irq.min 0"); + printf("irq.max %d\n", 100 * ncpu); + puts("irq.type DERIVE\n" + "irq.info CPU time spent handling interrupts\n" + "softirq.label softirq\n" + "softirq.draw STACK\n" + "softirq.min 0"); + printf("softirq.max %d\n", 100 * ncpu); + puts("softirq.type DERIVE\n" + "softirq.info CPU time spent handling \"batched\" interrupts"); + if(scaleto100) + printf("iowait.cdef iowait,%d,/\n" + "irq.cdef irq,%d,/\n" + "softirq.cdef softirq,%d,/\n", ncpu, ncpu, ncpu); + } + if(extinfo >= 8) { + puts("steal.label steal\n" + "steal.draw STACK\n" + "steal.min 0"); + printf("steal.max %d\n", 100 * ncpu); + puts("steal.type DERIVE\n" + "steal.info The time that a virtual CPU had runnable tasks, but the virtual CPU itself was not running"); + if(scaleto100) + printf("steal.cdef steal,%d,/\n", ncpu); + } + if(extinfo >= 9) { + puts("guest.label guest\n" + "guest.draw STACK\n" + "guest.min 0"); + printf("guest.max %d\n", 100 * ncpu); + puts("guest.type DERIVE\n" + "guest.info The time spent running a virtual CPU for guest operating systems under the control of the Linux kernel."); + if(scaleto100) + printf("guest.cdef guest,%d,/\n", ncpu); + } + return 0; + } + if(!strcmp(argv[1], "autoconf")) + return autoconf_check_readable(PROC_STAT); + } + if(!(f=fopen(PROC_STAT, "r"))) + return fail("cannot open " PROC_STAT); + hz_ = getenvint("HZ", 100); + while(fgets(buff, 256, f)) { + if(!strncmp(buff, "cpu ", 4)) { + fclose(f); + if(!(s = strtok(buff+4, " \t"))) + break; + print_stat_value("user", s, hz_); + if(!(s = strtok(NULL, " \t"))) + break; + print_stat_value("nice", s, hz_); + if(!(s = strtok(NULL, " \t"))) + break; + print_stat_value("system", s, hz_); + if(!(s = strtok(NULL, " \t"))) + break; + print_stat_value("idle", s, hz_); + if(!(s = strtok(NULL, " \t"))) + return 0; + print_stat_value("iowait", s, hz_); + if(!(s = strtok(NULL, " \t"))) + return 0; + print_stat_value("irq", s, hz_); + if(!(s = strtok(NULL, " \t"))) + return 0; + print_stat_value("softirq", s, hz_); + if(!(s = strtok(NULL, " \t"))) + return 0; + print_stat_value("steal", s, hz_); + if(!(s = strtok(NULL, " \t"))) + return 0; + print_stat_value("guest", s, hz_); + return 0; + } + } + fclose(f); + return fail("no cpu line found in " PROC_STAT); +} diff --git a/src/plugins/memory-sysctl.c b/src/plugins/memory-sysctl.c new file mode 100644 index 0000000..07fb433 --- /dev/null +++ b/src/plugins/memory-sysctl.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2015 Steve Schnepp - All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2 or v.3. + */ + +/* This plugin is compatible with munin-mainline version 2.0.25. */ + +#include +#include +#include +#include +#include +#include "common.h" +#include "plugins.h" + +#include + +int memory(int argc, char **argv) { + + if(argc > 1) { + if(!strcmp(argv[1], "config")) { + printf( + "graph_vlabel Bytes\n" + "graph_args --base 1024 -l 0\n" + "graph_title Memory usage\n" + "graph_category system\n" + "graph_info This graph shows what the machine uses memory for.\n" + ); + printf("apps.label apps\n"); + printf("apps.draw AREA\n"); + printf("apps.info Memory used by user-space applications.\n"); + + printf("free.label free\n"); + printf("free.draw STACK\n"); + printf("free.info Wasted memory. Memory that is not used for anything at all.\n"); + + printf("swap.label swap\n"); + printf("swap.draw STACK\n"); + printf("swap.info Swap space used.\n"); + + +if [ "$1" = "config" ]; then + echo 'graph_args --base 1024 -l 0 --vertical-label Bytes --upper-limit' $MEMMAX + echo 'graph_title Memory usage' + echo 'graph_category system' + echo 'graph_info This graph shows what the machine uses its memory for.' + echo 'graph_order active inactive wired cached free swap buffers' + echo 'active.label active' + echo 'active.info pages recently statistically used' + echo 'active.draw AREA' + echo 'inactive.label inactive' + echo 'inactive.info pages recently statistically unused' + echo 'inactive.draw STACK' + echo 'wired.label wired' + echo 'wired.info pages that are fixed into memory, usually for kernel purposes, but also sometimes for special use in processes' + echo 'wired.draw STACK' + echo 'cached.label cache' + echo 'cached.info pages that have percolated from inactive to a status where they maintain their data, but can often be immediately reused' + echo 'cached.draw STACK' + echo 'free.label free' + echo 'free.info pages without data content' + echo 'free.draw STACK' + echo 'swap.label swap' + echo 'swap.info Swap space used' + echo 'swap.draw STACK' + echo 'buffers.label buffers' + echo 'buffers.info pages used for filesystem buffers' + echo 'buffers.draw LINE' + exit 0 +fi + + + + + + + + + + + return 0; + } + if(!strcmp(argv[1], "autoconf")) + return writeyes(); + } + + struct vmtotal s; + size_t len = sizeof(s); + + if (sysctlbyname("vm.total", &s, &len, NULL, 0) < 0) { + return fail("sysctl"); + } + + double ldavg = l.ldavg[0]; + double fscale = l.fscale; + + printf("# vm.loadavg, ldavg:%f fscale:%f -", ldavg, fscale); + printf("\n"); + + double load_1 = ldavg / fscale; + printf("load.value %.2f\n", load_1); + return 0; +}