Added FreeBSD support to the cpu module
authorocto <octo>
Thu, 8 Dec 2005 14:27:19 +0000 (14:27 +0000)
committerocto <octo>
Thu, 8 Dec 2005 14:27:19 +0000 (14:27 +0000)
configure.in
src/config.h.in
src/cpu.c [new file with mode: 0644]
src/cpu.h [new file with mode: 0644]

index 7941cd5..889706e 100644 (file)
@@ -1,6 +1,6 @@
 dnl Process this file with autoconf to produce a configure script.
 AC_INIT(src/collectd.c)
-AM_INIT_AUTOMAKE(collectd, 3.5.alpha0)
+AM_INIT_AUTOMAKE(collectd, 3.5.alpha1)
 AM_CONFIG_HEADER(src/config.h src/libping/config.h)
 AC_LANG(C)
 
@@ -38,6 +38,9 @@ AC_CHECK_HEADERS(errno.h)
 AC_CHECK_HEADERS(syslog.h)
 AC_CHECK_HEADERS(dlfcn.h)
 
+# For cpu modules
+AC_CHECK_HEADERS(sys/sysctl.h sys/dkstat.h)
+
 # For load module
 AC_CHECK_HEADERS(sys/loadavg.h)
 
@@ -71,6 +74,9 @@ AC_CHECK_FUNCS(gethostbyname, , AC_CHECK_LIB(nsl, gethostbyname))
 AC_CHECK_FUNCS(strchr memcpy strstr strcmp strncmp strncpy strlen)
 AC_CHECK_FUNCS(strncasecmp strcasecmp strncmp)
 
+# For cpu module
+AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"])
+
 # For load module
 AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
 
@@ -151,6 +157,8 @@ AC_ARG_WITH(libstatgrab, AC_HELP_STRING([--with-libstatgrab@<:@=PFX@:>@], [Path
 ])
 if test "x$with_libstatgrab" = "xyes"
 then
+       AC_CHECK_LIB(devstat, getdevs)
+       AC_CHECK_LIB(kvm, kvm_getargv)
        AC_CHECK_LIB(statgrab, sg_init,, [with_libstatgrab="no (not found)"])
        AC_CHECK_HEADERS(statgrab.h,,    [with_libstatgrab="no (not found)"])
 fi
@@ -201,7 +209,7 @@ fi
 AC_ARG_ENABLE(cpu, AC_HELP_STRING([--disable-cpu], [Disable CPU usage statistics]),, [enable_cpu="yes"])
 if test "x$enable_cpu" != "xno"
 then
-       if test "x$ac_system" = "xLinux" -o "x$with_kstat" = "xyes" -o "x$with_libstatgrab" = "xyes"
+       if test "x$ac_system" = "xLinux" -o "x$with_kstat" = "xyes" -o "x$have_sysctlbyname" = "xyes"
        then
                enable_cpu="yes"
        else
index 1c63a1f..33baece 100644 (file)
 /* Define to 1 if you have the `devinfo' library (-ldevinfo). */
 #undef HAVE_LIBDEVINFO
 
+/* Define to 1 if you have the `devstat' library (-ldevstat). */
+#undef HAVE_LIBDEVSTAT
+
 /* Define to 1 if you have the `dl' library (-ldl). */
 #undef HAVE_LIBDL
 
 /* Define to 1 if you have the `kstat' library (-lkstat). */
 #undef HAVE_LIBKSTAT
 
+/* Define to 1 if you have the `kvm' library (-lkvm). */
+#undef HAVE_LIBKVM
+
 /* Define to 1 if you have the `m' library (-lm). */
 #undef HAVE_LIBM
 
 /* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
+/* Define to 1 if you have the `sysctlbyname' function. */
+#undef HAVE_SYSCTLBYNAME
+
 /* Define to 1 if you have the <syslog.h> header file. */
 #undef HAVE_SYSLOG_H
 
+/* Define to 1 if you have the <sys/dkstat.h> header file. */
+#undef HAVE_SYS_DKSTAT_H
+
 /* Define to 1 if you have the <sys/loadavg.h> header file. */
 #undef HAVE_SYS_LOADAVG_H
 
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
 /* Define to 1 if you have the <sys/times.h> header file. */
 #undef HAVE_SYS_TIMES_H
 
diff --git a/src/cpu.c b/src/cpu.c
new file mode 100644 (file)
index 0000000..adafbea
--- /dev/null
+++ b/src/cpu.c
@@ -0,0 +1,231 @@
+#include "cpu.h"
+
+#if COLLECT_CPU
+#define MODULE_NAME "cpu"
+
+#ifdef HAVE_LIBKSTAT
+#include <sys/sysinfo.h>
+#endif /* HAVE_LIBKSTAT */
+
+#ifdef HAVE_SYSCTLBYNAME
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+#ifdef HAVE_SYS_DKSTAT_H
+#include <sys/dkstat.h>
+#endif
+
+#if !defined(CP_USER) || !defined(CP_NICE) || !defined(CP_SYS) || !defined(CP_INTR) || !defined(CP_IDLE) || !defined(CPUSTATES)
+#define CP_USER   0
+#define CP_NICE   1
+#define CP_SYS    2
+#define CP_INTR   3
+#define CP_IDLE   4
+#define CPUSTATES 5
+#endif
+#endif /* HAVE_SYSCTLBYNAME */
+
+#include "plugin.h"
+#include "common.h"
+
+#ifdef HAVE_LIBKSTAT
+/* colleague tells me that Sun doesn't sell systems with more than 100 or so CPUs.. */
+#define MAX_NUMCPU 256
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMCPU];
+static int numcpu;
+#endif /* HAVE_LIBKSTAT */
+
+#ifdef HAVE_SYSCTLBYNAME
+static int numcpu;
+#endif /* HAVE_SYSCTLBYNAME */
+
+static char *cpu_filename = "cpu-%s.rrd";
+
+static char *ds_def[] =
+{
+       "DS:user:COUNTER:25:0:100",
+       "DS:nice:COUNTER:25:0:100",
+       "DS:syst:COUNTER:25:0:100",
+       "DS:idle:COUNTER:25:0:100",
+       "DS:wait:COUNTER:25:0:100",
+       NULL
+};
+static int ds_num = 5;
+
+extern time_t curtime;
+
+void cpu_init (void)
+{
+#ifdef HAVE_LIBKSTAT
+       kstat_t *ksp_chain;
+
+       numcpu = 0;
+
+       if (kc == NULL)
+               return;
+
+       /* Solaris doesn't count linear.. *sigh* */
+       for (numcpu = 0, ksp_chain = kc->kc_chain;
+                       (numcpu < MAX_NUMCPU) && (ksp_chain != NULL);
+                       ksp_chain = ksp_chain->ks_next)
+               if (strncmp (ksp_chain->ks_module, "cpu_stat", 8) == 0)
+                       ksp[numcpu++] = ksp_chain;
+/* #endif HAVE_LIBKSTAT */
+
+#elif defined (HAVE_SYSCTLBYNAME)
+       size_t numcpu_size;
+
+       numcpu_size = sizeof (numcpu);
+
+       if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
+       {
+               syslog (LOG_WARNING, "cpu: sysctlbyname: %s", strerror (errno));
+               return;
+       }
+
+       if (numcpu != 1)
+               syslog (LOG_NOTICE, "cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
+#endif
+
+       return;
+}
+
+void cpu_write (char *host, char *inst, char *val)
+{
+       char file[512];
+       int status;
+
+       status = snprintf (file, 512, cpu_filename, inst);
+       if (status < 1)
+               return;
+       else if (status >= 512)
+               return;
+
+       rrd_update_file (host, file, val, ds_def, ds_num);
+}
+
+#define BUFSIZE 512
+void cpu_submit (int cpu_num, unsigned long long user, unsigned long long nice, unsigned long long syst,
+               unsigned long long idle, unsigned long long wait)
+{
+       char buf[BUFSIZE];
+       char cpu[16];
+
+       if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu", (unsigned int) curtime,
+                               user, nice, syst, idle, wait) >= BUFSIZE)
+               return;
+       snprintf (cpu, 16, "%i", cpu_num);
+
+       plugin_submit (MODULE_NAME, cpu, buf);
+}
+#undef BUFSIZE
+
+void cpu_read (void)
+{
+#ifdef KERNEL_LINUX
+#define BUFSIZE 1024
+       int cpu;
+       unsigned long long user, nice, syst, idle;
+       unsigned long long wait, intr, sitr; /* sitr == soft interrupt */
+       FILE *fh;
+       char buf[BUFSIZE];
+
+       char *fields[9];
+       int numfields;
+
+       if ((fh = fopen ("/proc/stat", "r")) == NULL)
+       {
+               syslog (LOG_WARNING, "cpu: fopen: %s", strerror (errno));
+               return;
+       }
+
+       while (fgets (buf, BUFSIZE, fh) != NULL)
+       {
+               if (strncmp (buf, "cpu", 3))
+                       continue;
+               if ((buf[3] < '0') || (buf[3] > '9'))
+                       continue;
+
+               numfields = strsplit (buf, fields, 9);
+               if (numfields < 5)
+                       continue;
+
+               cpu = atoi (fields[0] + 3);
+               user = atoll (fields[1]);
+               nice = atoll (fields[2]);
+               syst = atoll (fields[3]);
+               idle = atoll (fields[4]);
+
+               if (numfields >= 8)
+               {
+                       wait = atoll (fields[5]);
+                       intr = atoll (fields[6]);
+                       sitr = atoll (fields[7]);
+
+                       /* I doubt anyone cares about the time spent in
+                        * interrupt handlers.. */
+                       syst += intr + sitr;
+               }
+               else
+               {
+                       wait = 0LL;
+               }
+
+               cpu_submit (cpu, user, nice, syst, idle, wait);
+       }
+
+       fclose (fh);
+#undef BUFSIZE
+/* #endif defined(KERNEL_LINUX) */
+
+#elif defined(HAVE_LIBKSTAT)
+       int cpu;
+       unsigned long long user, syst, idle, wait;
+       static cpu_stat_t cs;
+
+       if (kc == NULL)
+               return;
+
+       for (cpu = 0; cpu < numcpu; cpu++)
+       {
+               if (kstat_read (kc, ksp[cpu], &cs) == -1)
+                       continue; /* error message? */
+
+               idle = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_IDLE];
+               user = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_USER];
+               syst = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_KERNEL];
+               wait = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_WAIT];
+
+               cpu_submit (ksp[cpu]->ks_instance,
+                               user, 0LL, syst, idle, wait);
+       }
+/* #endif defined(HAVE_LIBKSTAT) */
+
+#elif defined (HAVE_SYSCTLBYNAME)
+       long cpuinfo[CPUSTATES];
+       size_t cpuinfo_size;
+
+       cpuinfo_size = sizeof (cpuinfo);
+
+       if (sysctlbyname("kern.cp_time", &cpuinfo, &cpuinfo_size, NULL, 0) < 0)
+       {
+               syslog (LOG_WARNING, "cpu: sysctlbyname: %s", strerror (errno));
+               return;
+       }
+
+       cpuinfo[CP_SYS] += cpuinfo[CP_INTR];
+
+       /* FIXME: Instance is always `0' */
+       cpu_submit (0, cpuinfo[CP_USER], cpuinfo[CP_NICE], cpuinfo[CP_SYS], cpuinfo[CP_IDLE], 0LL);
+#endif
+}
+
+void module_register (void)
+{
+       plugin_register (MODULE_NAME, cpu_init, cpu_read, cpu_write);
+}
+
+#undef MODULE_NAME
+#endif /* COLLECT_CPU */
diff --git a/src/cpu.h b/src/cpu.h
new file mode 100644 (file)
index 0000000..340035f
--- /dev/null
+++ b/src/cpu.h
@@ -0,0 +1,20 @@
+#ifndef CPU_H
+#define CPU_H
+
+#include "collectd.h"
+
+#ifndef COLLECT_CPU
+#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME)
+#define COLLECT_CPU 1
+#else
+#define COLLECT_CPU 0
+#endif
+#endif /* !defined(COLLECT_CPU) */
+
+#if COLLECT_CPU
+
+void cpu_init (void);
+void cpu_read (void);
+
+#endif /* COLLECT_CPU */
+#endif /* CPU_H */