From: octo Date: Thu, 8 Dec 2005 14:27:19 +0000 (+0000) Subject: Added FreeBSD support to the cpu module X-Git-Tag: collectd-3.5.0~23 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=e1d497b742e7a12098c44fc6fd5ffc29df32c4d9;p=collectd.git Added FreeBSD support to the cpu module --- diff --git a/configure.in b/configure.in index 7941cd53..889706e4 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/src/config.h.in b/src/config.h.in index 1c63a1fb..33baece7 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -81,12 +81,18 @@ /* 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 @@ -180,9 +186,15 @@ /* 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 header file. */ #undef HAVE_SYSLOG_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DKSTAT_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_LOADAVG_H @@ -198,6 +210,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SYSCTL_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIMES_H diff --git a/src/cpu.c b/src/cpu.c new file mode 100644 index 00000000..adafbeac --- /dev/null +++ b/src/cpu.c @@ -0,0 +1,231 @@ +#include "cpu.h" + +#if COLLECT_CPU +#define MODULE_NAME "cpu" + +#ifdef HAVE_LIBKSTAT +#include +#endif /* HAVE_LIBKSTAT */ + +#ifdef HAVE_SYSCTLBYNAME +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + +#ifdef HAVE_SYS_DKSTAT_H +#include +#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 index 00000000..340035f7 --- /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 */