Merged `branches/log-mode' to `trunk'
authorocto <octo>
Fri, 14 Apr 2006 10:53:44 +0000 (10:53 +0000)
committerocto <octo>
Fri, 14 Apr 2006 10:53:44 +0000 (10:53 +0000)
62 files changed:
AUTHORS
ChangeLog
README
TODO
collectd.spec
configure.in
contrib/collectd.conf
contrib/collection.cgi
debian/changelog
debian/collectd-apache.files [new file with mode: 0644]
debian/control
debian/rules
src/Makefile.am
src/apache.c [new file with mode: 0644]
src/apple_sensors.c [new file with mode: 0644]
src/battery.c
src/collectd.c
src/collectd.conf.pod
src/collectd.h
src/collectd.pod
src/common.c
src/common.h
src/configfile.c
src/cpu.c
src/cpu.h [deleted file]
src/cpufreq.c
src/cpufreq.h [deleted file]
src/df.c
src/disk.c
src/disk.h [deleted file]
src/hddtemp.c
src/hddtemp.h [deleted file]
src/liboping/Makefile.am
src/liboping/liboping.c
src/load.c
src/load.h [deleted file]
src/memory.c
src/memory.h [deleted file]
src/mysql.c
src/network.c
src/nfs.c
src/nfs.h [deleted file]
src/ping.c
src/ping.h [deleted file]
src/plugin.c
src/processes.c
src/processes.h [deleted file]
src/sensors.c
src/sensors.h [deleted file]
src/serial.c
src/serial.h [deleted file]
src/swap.c
src/swap.h [deleted file]
src/tape.c
src/tape.h [deleted file]
src/traffic.c
src/traffic.h [deleted file]
src/users.c
src/users.h [deleted file]
src/utils_mount.c
src/vserver.c [new file with mode: 0644]
src/wireless.c

diff --git a/AUTHORS b/AUTHORS
index 30e95ce..7c0f895 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,6 +22,9 @@ tape module by:
 users module by:
   Sebastian Harl <sh at tokkee.org>
 
+vserver module by:
+  Sebastian Harl <sh at tokkee.org>
+
 PID-file patch by:
   Tommie Gannert <d00-tga at d.kth.se>
 
index 92c421c..1338d13 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2006-04-02, Version 3.9.0
+       * A plugin to monitor the Apache webserver has been added.
+         <http://httpd.apache.org/>
+       * A plugin to collect statistics about virtual servers using VServer.
+         <http://linux-vserver.org/> Thanks to Sebastian Harl for writing
+         this plugin :)
+       * A plugin for wireless LAN cards has been added. It monitors signal
+         strength, link quality and noise ratio..
+       * An option to compile collectd with different `step' and `hearbeat'
+         settings has been added. The size of RRAs is no longer static but
+         calculated based on the settings for `step' and `width'.
+       * The `ping' plugin can now be configured to use a certain TTL.
+       * A plugin to monitor the hardware sensors of Apple computers has been
+         added.
+       * The plugins `cpu', `memory', `processes' and `traffic' have been
+         ported to Mach/Darwin (Mac OS X).
+
 2006-04-09, Version 3.8.4
        * Applied patch by Vincent StehlĂ© which improves the disk-name
          resolution in the `hddtemp' plugin for Linux systems.
diff --git a/README b/README
index 016a14b..327d2ef 100644 (file)
--- a/README
+++ b/README
@@ -66,6 +66,9 @@ Features
     - Users
       (Currently logged in users)
 
+    - VServer
+      (System ressources used by vservers)
+
   * Performance: Running as a daemon collectd doesn't spend much time in
     startup. Since collectd links against libping, librrd and libsensors it
     doesn't need to start any other processes.
diff --git a/TODO b/TODO
index 1fe76c8..b8a5b33 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,18 @@
+src/apple_sensors.c: Check for more sensor types.
+src/battery.c: commend not working code.
+general: build Darwin package
+
+Near future:
+* Update the RPM specfile to
+  - build `collectd-apache'
+  - be free of syntax erros.
+
 For version 3.*:
 * Port nfs module to solaris
 * Port tape module to Linux
 * Maybe look into porting the serial module
+
+http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_IOKitLib_API/chapter_5_section_1.html
+http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/index.html#//apple_ref/doc/uid/TP0000011
+http://www.gauchosoft.com/Software/X%20Resource%20Graph/
+http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification/
index 146bd98..d06ca04 100644 (file)
@@ -1,6 +1,6 @@
 Summary:       Statistics collection daemon for filling RRD files.
 Name:           collectd
-Version:       3.8.4
+Version:       3.9.0
 Release:       1
 Source:                http://verplant.org/collectd/%{name}-%{version}.tar.gz
 License:       GPL
@@ -79,6 +79,8 @@ rm -rf $RPM_BUILD_ROOT
 %attr(0444,root,root) %{_libdir}/%{name}/tape.so*
 %attr(0444,root,root) %{_libdir}/%{name}/traffic.so*
 %attr(0444,root,root) %{_libdir}/%{name}/users.so*
+%attr(0444,root,root) %{_libdir}/%{name}/vserver.so*
+%attr(0444,root,root) %{_libdir}/%{name}/wireless.so*
 %dir /var/lib/collectd
 
 %files mysql
@@ -88,10 +90,7 @@ rm -rf $RPM_BUILD_ROOT
 %attr(0444,root,root) %{_libdir}/%{name}/sensors.so*
 
 %changelog
-* Sun Apr 09 2006 Florian octo Forster <octo@verplant.org> 3.8.4-1
-- New upstream version
-
-* Sun Apr 02 2006 Florian octo Forster <octo@verplant.org> 3.8.3-1
+* Thu Mar 21 2006 Florian octo Forster <octo@verplant.org> 3.9.0-1
 - New upstream version
 
 * Thu Mar 14 2006 Florian octo Forster <octo@verplant.org> 3.8.2-1
index dd20a8a..a56c48b 100644 (file)
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-AC_INIT(collectd, 3.8.4)
+AC_INIT(collectd, 3.9.0-alpha1)
 AC_CONFIG_SRCDIR(src/collectd.c)
 AC_CONFIG_HEADERS(src/config.h)
 AM_INIT_AUTOMAKE(dist-bzip2)
@@ -34,7 +34,9 @@ AC_HEADER_STDC
 AC_HEADER_SYS_WAIT
 AC_HEADER_DIRENT
 AC_CHECK_HEADERS(stdint.h)
+AC_CHECK_HEADERS(stdio.h)
 AC_CHECK_HEADERS(errno.h)
+AC_CHECK_HEADERS(math.h)
 AC_CHECK_HEADERS(syslog.h)
 AC_CHECK_HEADERS(fcntl.h)
 AC_CHECK_HEADERS(signal.h)
@@ -134,10 +136,44 @@ AC_CHECK_HEADERS(netinet/icmp6.h, [], [],
 
 # For cpu modules
 AC_CHECK_HEADERS(sys/sysctl.h sys/dkstat.h)
+AC_CHECK_HEADERS(mach/mach_init.h)
+AC_CHECK_HEADERS(mach/host_priv.h)
+AC_CHECK_HEADERS(mach/mach_error.h)
+AC_CHECK_HEADERS(mach/mach_host.h)
+AC_CHECK_HEADERS(mach/mach_port.h)
+AC_CHECK_HEADERS(mach/mach_types.h)
+AC_CHECK_HEADERS(mach/message.h)
+AC_CHECK_HEADERS(mach/processor_set.h)
+AC_CHECK_HEADERS(mach/processor.h)
+AC_CHECK_HEADERS(mach/processor_info.h)
+AC_CHECK_HEADERS(mach/task.h)
+AC_CHECK_HEADERS(mach/thread_act.h)
+AC_CHECK_HEADERS(mach/vm_region.h)
+AC_CHECK_HEADERS(mach/vm_map.h)
+AC_CHECK_HEADERS(mach/vm_prot.h)
+AC_CHECK_HEADERS(mach/vm_statistics.h)
+AC_CHECK_HEADERS(mach/kern_return.h)
 
 # For hddtemp module
 AC_CHECK_HEADERS(linux/major.h)
 
+# For the apple_sensors module
+AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h)
+AC_CHECK_HEADERS(IOKit/IOKitLib.h)
+AC_CHECK_HEADERS(IOKit/IOTypes.h)
+
+# For the battery plugin
+AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [],
+[
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+])
+AC_CHECK_HEADERS(IOKit/ps/IOPSKeys.h)
+
 # For load module
 AC_CHECK_HEADERS(sys/loadavg.h)
 
@@ -145,6 +181,42 @@ AC_CHECK_HEADERS(sys/loadavg.h)
 AC_CHECK_HEADERS(utmp.h)
 AC_CHECK_HEADERS(utmpx.h)
 
+# For traffic plugin
+AC_CHECK_HEADERS(ifaddrs.h)
+AC_CHECK_HEADERS(net/if.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+])
+AC_CHECK_HEADERS(linux/if.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+])
+AC_CHECK_HEADERS(linux/netdevice.h, [], [],
+[
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+#if HAVE_LINUX_IF_H
+# include <linux/if.h>
+#endif
+])
+
+# For apache plugin
+AC_CHECK_HEADERS(curl/curl.h)
+
 # For quota module
 AC_CHECK_HEADERS(grp.h pwd.h sys/ucred.h)
 AC_CHECK_HEADERS(ctype.h)
@@ -203,6 +275,9 @@ AC_CHECK_FUNCS(statfs statvfs)
 # For load module
 AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
 
+# For the `processes' plugin
+AC_CHECK_FUNCS(thread_info)
+
 # For users module
 AC_CHECK_FUNCS(getutent getutxent)
 
@@ -210,6 +285,9 @@ AC_CHECK_FUNCS(getutent getutxent)
 AC_CHECK_FUNCS(quotactl)
 AC_CHECK_FUNCS(getgrgid getpwuid)
 
+# For traffic module
+AC_CHECK_FUNCS(getifaddrs)
+
 # For mount interface
 AC_CHECK_FUNCS(getfsent getvfsent listmntent)
 AC_CHECK_FUNCS(getfsstat)
@@ -280,14 +358,33 @@ if test "x$fu_cv_getmntent2" = "xyes"; then
                )
 fi
 
+# Check for structures
+AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_obytes],
+       [AC_DEFINE(HAVE_STRUCT_IF_DATA, 1, [Define if struct if_data exists and is usable.])],
+       [],
+       [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <net/if.h>
+       ])
+AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_bytes],
+       [AC_DEFINE(HAVE_STRUCT_NET_DEVICE_STATS, 1, [Define if struct net_device_stats exists and is usable.])],
+       [],
+       [
+       #include <sys/types.h>
+       #include <sys/socket.h>
+       #include <linux/if.h>
+       #include <linux/netdevice.h>
+       ])
+
 AC_MSG_CHECKING([for kernel type ($host_os)])
 case $host_os in
        *linux*)
-       AC_DEFINE([KERNEL_LINUX], [], [True if program is to be compiled for a Linux kernel])
+       AC_DEFINE([KERNEL_LINUX], 1, [True if program is to be compiled for a Linux kernel])
        ac_system="Linux"
        ;;
        *solaris*)
-       AC_DEFINE([KERNEL_SOLARIS], [], [True if program is to be compiled for a Solaris kernel])
+       AC_DEFINE([KERNEL_SOLARIS], 1, [True if program is to be compiled for a Solaris kernel])
        ac_system="Solaris"
        ;;
        *)
@@ -311,6 +408,7 @@ AC_CHECK_LIB(resolv, res_search,
 [with_libresolv="no"])
 AM_CONDITIONAL(BUILD_WITH_LIBRESOLV, test "x$with_libresolv" = "xyes")
 
+
 m4_divert_once([HELP_WITH], [
 collectd additional packages:])
 
@@ -396,9 +494,92 @@ AC_DEFINE_UNQUOTED(COLLECT_KSTAT, [$collect_kstat],
        [Wether or not to use kstat library (Solaris)])
 AM_CONDITIONAL(BUILD_WITH_KSTAT, test "x$with_kstat" = "xyes")
 
+### BEGIN of check for libcurl ###
+with_curl_config="curl-config"
+with_curl_prefix=0
+with_curl_libs=""
+AC_ARG_WITH(libcurl, [AS_HELP_STRING([--with-libcurl@<:@=PREFIX@:>@], [Path to libcurl.])],
+[
+       if test "x$withval" != "xno" -a "x$withval" != "xyes"
+       then
+               if test -x "$withval/bin/curl-config"
+               then
+                       with_curl_config="$withval/bin/curl-config"
+                       with_curl_prefix=1
+               fi
+       fi
+       if test "x$withval" = "xno"
+       then
+               with_libcurl="no"
+       else
+               with_libcurl="yes"
+       fi
+],
+[
+       with_libcurl="yes"
+])
+if test "x$with_libcurl" = "xyes"
+then
+       with_curl_libs=`$with_curl_config --libs 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no"
+       else
+               AC_CHECK_LIB(curl, curl_easy_init,
+               [
+                       BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
+                       AC_SUBST(BUILD_WITH_LIBCURL_LIBS)
+               ],
+               [
+                       with_libcurl="no"
+               ],
+               [$with_curl_libs])
+       fi
+fi
+if test "x$with_libcurl" = "xyes" -a $with_curl_prefix -ne 0
+then
+       with_curl_prefix=`$with_curl_config --libs 2>/dev/null`
+       curl_config_status=$?
+
+       if test $curl_config_status -ne 0
+       then
+               with_libcurl="no"
+       else
+               if test -d "$with_curl_prefix/include"
+               then
+                       CPPFLAGS="$CPPFLAGS -I$with_curl_prefix/include"
+               fi
+       fi
+fi
+
+with_libcurl_numeric=0
+if test "x$with_libcurl" = "xyes"
+then
+       with_libcurl_numeric=1
+fi
+AC_DEFINE_UNQUOTED(HAVE_LIBCURL, [$with_libcurl_numeric], [Define to 1 if you have the 'curl' library (-lcurl).])
+AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
+### END of check for libcurl ###
+
+with_libiokit="no"
+collectd_libiokit=0
+AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices,
+[
+       with_libiokit="yes"
+       collectd_libiokit=1
+], 
+[
+       with_libiokit="no"
+       collectd_libiokit=0
+])
+AC_DEFINE_UNQUOTED(COLLECT_LIBIOKIT, [$collect_libiokit], [Wether or not to use the IOKit library])
+AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes")
+
 AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])],
 [
-       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       if test "x$withval" != "xno" -a "x$withval" != "xyes"
        then
                LDFLAGS="$LDFLAGS -L$withval/lib"
                CPPFLAGS="$CPPFLAGS -I$withval/include"
@@ -512,6 +693,42 @@ AC_DEFINE_UNQUOTED(COLLECT_LIBMYSQL, [$collect_libmysql],
        [Wether or not to use mysql library])
 AM_CONDITIONAL(BUILD_WITH_LIBMYSQL, test "x$with_libmysql" = "xyes")
 
+# Define `step' and `hearbeat' values..
+declare -i collectd_step=10
+declare -i collectd_heartbeat=25
+AC_ARG_WITH(step, [AS_HELP_STRING([--with-step=SECONDS], [Interval in which plugins are queried.])],
+[
+       if test "x$withval" != "xno" -a "x$withval" != "xyes"
+       then
+               declare -i tmp_collectd_step="$withval"
+               if test $tmp_collectd_step -gt 0
+               then
+                       collectd_step=$tmp_collectd_step
+                       let "collectd_heartbeat=$collectd_step*2"
+               fi
+       fi
+], [])
+AC_ARG_WITH(heartbeat, [AS_HELP_STRING([--with-heartbeat=SECONDS], [Heartbeat of the DS in generated RRD files.])],
+[
+       if test "x$withval" != "xno" -a "x$withval" != "xyes"
+       then
+               declare -i tmp_collectd_heartbeat="$withval"
+               if test $tmp_collectd_heartbeat -gt 0
+               then
+                       collectd_heartbeat=$tmp_collectd_heartbeat
+               fi
+       fi
+], [])
+
+if test $collectd_step -ne 10
+then
+       AC_DEFINE_UNQUOTED(COLLECTD_STEP, "$collectd_step", [Interval in which plugins are queried.])
+fi
+if test $collectd_heartbeat -ne 25
+then
+       AC_DEFINE_UNQUOTED(COLLECTD_HEARTBEAT, "$collectd_heartbeat", [Interval in which plugins are queried.])
+fi
+
 #
 # Check for enabled/disabled features
 #
@@ -583,6 +800,8 @@ AC_COLLECTD([daemon],    [disable], [feature], [daemon mode])
 
 m4_divert_once([HELP_ENABLE], [
 collectd modules:])
+AC_COLLECTD([apache],    [disable], [module], [Apache httpd statistics])
+AC_COLLECTD([apple_sensors], [disable], [module], [Apple's hardware sensors])
 AC_COLLECTD([battery],   [disable], [module], [battery statistics])
 AC_COLLECTD([cpu],       [disable], [module], [cpu usage statistics])
 AC_COLLECTD([cpufreq],   [disable], [module], [system cpu frequency statistics])
@@ -602,6 +821,7 @@ AC_COLLECTD([swap],      [disable], [module], [swap statistics])
 AC_COLLECTD([tape],      [disable], [module], [tape statistics])
 AC_COLLECTD([traffic],   [disable], [module], [system traffic statistics])
 AC_COLLECTD([users],     [disable], [module], [user count statistics])
+AC_COLLECTD([vserver],   [disable], [module], [vserver statistics])
 AC_COLLECTD([wireless],  [disable], [module], [wireless link statistics])
 
 #m4_divert_once([HELP_ENABLE], [
@@ -826,6 +1046,8 @@ cat <<EOF;
 
 Configuration:
   Libraries:
+    libcurl . . . . . . $with_libcurl
+    libiokit  . . . . . $with_libiokit
     librrd  . . . . . . $with_rrdtool
     lm_sensors  . . . . $with_lm_sensors
     libstatgrab . . . . $with_libstatgrab
@@ -835,8 +1057,12 @@ Configuration:
   Features:
     debug . . . . . . . $enable_debug
     daemon mode . . . . $enable_daemon
+    step  . . . . . . . $collectd_step seconds
+    heartbeat . . . . . $collectd_heartbeat seconds
 
   Modules:
+    apache  . . . . . . $enable_apache
+    apple_sensors . . . $enable_apple_sensors
     battery . . . . . . $enable_battery
     cpu . . . . . . . . $enable_cpu
     cpufreq . . . . . . $enable_cpufreq
@@ -855,6 +1081,7 @@ Configuration:
     tape  . . . . . . . $enable_tape
     traffic . . . . . . $enable_traffic
     users . . . . . . . $enable_users
+    vserver . . . . . . $enable_vserver
     wireless  . . . . . $enable_wireless
 
 EOF
index 147f88d..593143f 100644 (file)
@@ -9,22 +9,31 @@ DataDir   /var/lib/collectd
 PIDFile   /var/run/collectd.pid
 PluginDir /usr/lib/collectd
 
+#LoadPlugin apache
+#LoadPlugin battery
 LoadPlugin cpu
 LoadPlugin cpufreq
 LoadPlugin df
 LoadPlugin disk
+#LoadPlugin hddtemp
 LoadPlugin load
 LoadPlugin memory
+#LoadPlugin mysql
 LoadPlugin nfs
 LoadPlugin ping
 LoadPlugin processes
+#LoadPlugin sensors
 LoadPlugin serial
 LoadPlugin swap
 LoadPlugin traffic
 LoadPlugin users
-#LoadPlugin hddtemp
-#LoadPlugin mysql
-#LoadPlugin sensors
+#LoadPlugin vserver
+
+#<Plugin apache>
+#      URL http://localhost/status?auto
+#      User www-user
+#      Password secret
+#</Plugin>
 
 #<Plugin ping>
 #      Host host.foo.bar
index 5684475..51e187d 100755 (executable)
@@ -53,6 +53,47 @@ our $GraphDefs;
        
        $GraphDefs =
        {
+               apache_bytes => ['DEF:min_raw={file}:count:MIN',
+                       'DEF:avg_raw={file}:count:AVERAGE',
+                       'DEF:max_raw={file}:count:MAX',
+                       'CDEF:min=min_raw,8,*',
+                       'CDEF:avg=avg_raw,8,*',
+                       'CDEF:max=max_raw,8,*',
+                       'CDEF:mytime=avg_raw,TIME,TIME,IF',
+                       'CDEF:sample_len_raw=mytime,PREV(mytime),-',
+                       'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF',
+                       'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*',
+                       'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+',
+                       "AREA:avg#$HalfBlue",
+                       "LINE1:avg#$FullBlue:Bit/s",
+                       'GPRINT:min:MIN:%5.1lf%s Min,',
+                       'GPRINT:avg:AVERAGE:%5.1lf%s Avg,',
+                       'GPRINT:max:MAX:%5.1lf%s Max,',
+                       'GPRINT:avg:LAST:%5.1lf%s Last',
+                       'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
+               ],
+               apache_requests => ['DEF:min={file}:count:MIN',
+                       'DEF:avg={file}:count:AVERAGE',
+                       'DEF:max={file}:count:MAX',
+                       "AREA:max#$HalfBlue",
+                       "AREA:min#$Canvas",
+                       "LINE1:avg#$FullBlue:Requests/s",
+                       'GPRINT:min:MIN:%6.2lf Min,',
+                       'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+                       'GPRINT:max:MAX:%6.2lf Max,',
+                       'GPRINT:avg:LAST:%6.2lf Last'
+               ],
+               apache_scoreboard => ['DEF:min={file}:count:MIN',
+                       'DEF:avg={file}:count:AVERAGE',
+                       'DEF:max={file}:count:MAX',
+                       "AREA:max#$HalfBlue",
+                       "AREA:min#$Canvas",
+                       "LINE1:avg#$FullBlue:Processes",
+                       'GPRINT:min:MIN:%6.2lf Min,',
+                       'GPRINT:avg:AVERAGE:%6.2lf Avg,',
+                       'GPRINT:max:MAX:%6.2lf Max,',
+                       'GPRINT:avg:LAST:%6.2lf Last'
+               ],
                charge => [
                        'DEF:avg={file}:charge:AVERAGE',
                        'DEF:min={file}:charge:MIN',
@@ -262,8 +303,10 @@ our $GraphDefs;
                        'DEF:free_max={file}:free:MAX',
                        'DEF:buffers_max={file}:buffers:MAX',
                        'DEF:cached_max={file}:cached:MAX',
-                       'CDEF:free_cached_buffers_used=free_avg,cached_avg,+,buffers_avg,+,used_avg,+',
-                       'CDEF:cached_buffers_used=cached_avg,buffers_avg,+,used_avg,+',
+                       'CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF',
+                       'CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF',
+                       'CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+',
+                       'CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+',
                        'CDEF:buffers_used=buffers_avg,used_avg,+',
                        "AREA:free_cached_buffers_used#$HalfGreen",
                        "AREA:cached_buffers_used#$HalfBlue",
@@ -718,7 +761,87 @@ our $GraphDefs;
                        'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,',
                        'GPRINT:max:MAX:%5.1lf%sV Max,',
                        'GPRINT:avg:LAST:%5.1lf%sV Last\l'
-               ]
+               ],
+               threads => [
+                       "DEF:total_avg={file}:total:AVERAGE",
+                       "DEF:total_min={file}:total:MIN",
+                       "DEF:total_max={file}:total:MAX",
+                       "DEF:running_avg={file}:running:AVERAGE",
+                       "DEF:running_min={file}:running:MIN",
+                       "DEF:running_max={file}:running:MAX",
+                       "DEF:uninterruptible_avg={file}:uninterruptible:AVERAGE",
+                       "DEF:uninterruptible_min={file}:uninterruptible:MIN",
+                       "DEF:uninterruptible_max={file}:uninterruptible:MAX",
+                       "DEF:onhold_avg={file}:onhold:AVERAGE",
+                       "DEF:onhold_min={file}:onhold:MIN",
+                       "DEF:onhold_max={file}:onhold:MAX",
+                       "LINE1:total_avg#$FullYellow:Total   ",
+                       'GPRINT:total_min:MIN:%5.1lf Min,',
+                       'GPRINT:total_avg:AVERAGE:%5.1lf Avg.,',
+                       'GPRINT:total_max:MAX:%5.1lf Max,',
+                       'GPRINT:total_avg:LAST:%5.1lf Last\l',
+                       "LINE1:running_avg#$FullRed:Running ",
+                       'GPRINT:running_min:MIN:%5.1lf Min,',
+                       'GPRINT:running_avg:AVERAGE:%5.1lf Avg.,',          
+                       'GPRINT:running_max:MAX:%5.1lf Max,',
+                       'GPRINT:running_avg:LAST:%5.1lf Last\l',
+                       "LINE1:uninterruptible_avg#$FullGreen:Unintr  ",
+                       'GPRINT:uninterruptible_min:MIN:%5.1lf Min,',
+                       'GPRINT:uninterruptible_avg:AVERAGE:%5.1lf Avg.,',
+                       'GPRINT:uninterruptible_max:MAX:%5.1lf Max,',
+                       'GPRINT:uninterruptible_avg:LAST:%5.1lf Last\l',
+                       "LINE1:onhold_avg#$FullBlue:Onhold  ",
+                       'GPRINT:onhold_min:MIN:%5.1lf Min,',
+                       'GPRINT:onhold_avg:AVERAGE:%5.1lf Avg.,',
+                       'GPRINT:onhold_max:MAX:%5.1lf Max,',
+                       'GPRINT:onhold_avg:LAST:%5.1lf Last\l'
+               ],
+               vs_memory => [
+                       'DEF:vm_avg={file}:vm:AVERAGE',
+                       'DEF:vm_min={file}:vm:MIN',
+                       'DEF:vm_max={file}:vm:MAX',
+                       'DEF:vml_avg={file}:vml:AVERAGE',
+                       'DEF:vml_min={file}:vml:MIN',
+                       'DEF:vml_max={file}:vml:MAX',
+                       'DEF:rss_avg={file}:rss:AVERAGE',
+                       'DEF:rss_min={file}:rss:MIN',
+                       'DEF:rss_max={file}:rss:MAX',
+                       'DEF:anon_avg={file}:anon:AVERAGE',
+                       'DEF:anon_min={file}:anon:MIN',
+                       'DEF:anon_max={file}:anon:MAX',
+                       "LINE1:vm_avg#$FullYellow:VM     ",
+                       'GPRINT:vm_min:MIN:%5.1lf%s Min,',
+                       'GPRINT:vm_avg:AVERAGE:%5.1lf%s Avg.,',
+                       'GPRINT:vm_max:MAX:%5.1lf%s Avg.,',
+                       'GPRINT:vm_avg:LAST:%5.1lf%s Last\l',
+                       "LINE1:vml_avg#$FullRed:Locked ",
+                       'GPRINT:vml_min:MIN:%5.1lf%s Min,',
+                       'GPRINT:vml_avg:AVERAGE:%5.1lf%s Avg.,',
+                       'GPRINT:vml_max:MAX:%5.1lf%s Avg.,',
+                       'GPRINT:vml_avg:LAST:%5.1lf%s Last\l',
+                       "LINE1:rss_avg#$FullGreen:RSS    ",
+                       'GPRINT:rss_min:MIN:%5.1lf%s Min,',
+                       'GPRINT:rss_avg:AVERAGE:%5.1lf%s Avg.,',
+                       'GPRINT:rss_max:MAX:%5.1lf%s Avg.,',
+                       'GPRINT:rss_avg:LAST:%5.1lf%s Last\l',
+                       "LINE1:anon_avg#$FullBlue:Anon.  ",
+                       'GPRINT:anon_min:MIN:%5.1lf%s Min,',
+                       'GPRINT:anon_avg:AVERAGE:%5.1lf%s Avg.,',
+                       'GPRINT:anon_max:MAX:%5.1lf%s Avg.,',
+                       'GPRINT:anon_avg:LAST:%5.1lf%s Last\l',
+               ],
+               vs_processes => [
+                       'DEF:proc_avg={file}:total:AVERAGE',
+                       'DEF:proc_min={file}:total:MIN',
+                       'DEF:proc_max={file}:total:MAX',
+                       "AREA:proc_max#$HalfBlue",
+                       "AREA:proc_min#$Canvas",
+                       "LINE1:proc_avg#$FullBlue:Processes",
+                       'GPRINT:proc_min:MIN:%4.1lf Min,',
+                       'GPRINT:proc_avg:AVERAGE:%4.1lf Avg.,',
+                       'GPRINT:proc_max:MAX:%4.1lf Max,',
+                       'GPRINT:proc_avg:LAST:%4.1lf Last\l'
+               ],
        };
        $GraphDefs->{'disk'} = $GraphDefs->{'partition'};
        $GraphDefs->{'meminfo'} = $GraphDefs->{'memory'};
@@ -726,6 +849,9 @@ our $GraphDefs;
 
 our $GraphArgs =
 {
+       apache_bytes => ['-t', 'apache traffic', '-v', 'Bit/s'],
+       apache_requests => ['-t', 'apache requests', '-v', 'Requests/s'],
+       apache_scoreboard => ['-t', 'apache scoreboard {inst}', '-v', 'Processes'],
        charge => ['-t', '{host} charge', '-v', 'Ampere hours'],
        cpu => ['-t', '{host} cpu{inst} usage', '-v', 'Percent', '-l', '0'],
        cpufreq => ['-t', '{host} cpu{inst} usage', '-v', 'Mhz'],
@@ -749,11 +875,15 @@ our $GraphArgs =
        swap => ['-t', '{host} swap usage', '-v', 'Bytes', '-b', '1024', '-l', '0'],
        traffic => ['-t', '{host} {inst} traffic', '-v', 'Bit/s'],
        users => ['-t', '{host} users', '-v', 'Users'],
-       voltage => ['-t', '{host} voltage', '-v', 'Volts']
+       voltage => ['-t', '{host} voltage', '-v', 'Volts'],
+       threads => ['-t', '{host} threads', '-v', 'Threads'],
+       vs_memory => ['-t', '{host} memory usage', '-v', 'Bytes'],
+       vs_processes => ['-t', '{host} processes', '-v', 'Processes'],
 };
 
 our $GraphMulti =
 {
+       apache_scoreboard => \&output_graph_apache_scoreboard,
        cpu     => \&output_graph_cpu,
        cpufreq => 1,
        disk    => 1,
@@ -856,6 +986,49 @@ sub output_graph_cpu
        return (@ret);
 }
 
+sub output_graph_apache_scoreboard
+{
+       my @inst = @_;
+       my @ret = ();
+
+       die if (@inst < 2);
+
+       my @colors = get_n_colors (scalar (@inst));
+
+       for (my $i = 0; $i < scalar (@inst); $i++)
+       {
+               my $inst = $inst[$i];
+               push (@ret,
+                       "DEF:avg_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:AVERAGE",
+                       "DEF:min_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:MIN",
+                       "DEF:max_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:MAX");
+       }
+
+       for (my $i = 0; $i < scalar (@inst); $i++)
+       {
+               my $inst = $inst[$i];
+               my $color = $colors[$i];
+
+               if (length ($inst) > 15)
+               {
+                       $inst = substr ($inst, 0, 12) . '...';
+               }
+               else
+               {
+                       $inst = sprintf ('%-15s', $inst);
+               }
+
+               push (@ret,
+                       "LINE1:avg_$i#$color:$inst",
+                       "GPRINT:min_$i:MIN:%6.2lf Min,",
+                       "GPRINT:avg_$i:AVERAGE:%6.2lf Avg,",
+                       "GPRINT:max_$i:MAX:%6.2lf Max,",
+                       "GPRINT:avg_$i:LAST:%6.2lf Last\\l");
+       }
+
+       return (@ret);
+}
+
 sub output_graph_ping
 {
        my @inst = @_;
@@ -1025,6 +1198,7 @@ sub output_graph
                $Inst = $files->{$Type}[0];
        }
 
+       #push (@cmd, '-', '-a', 'PNG', '-s', $TimeSpan, '-w', 800, '-h', 150);
        push (@cmd, '-', '-a', 'PNG', '-s', $TimeSpan);
        push (@cmd, @{$GraphArgs->{$Type}}) if (defined ($GraphArgs->{$Type}));
 
@@ -1119,6 +1293,8 @@ HEADER
                print <<HTML;
                </ul>
 
+               <h3>Hourly</h3>
+               <div><img src="$MySelf$RelDir/$Type/hour" /></div>
                <h3>Daily</h3>
                <div><img src="$MySelf$RelDir/$Type/day" /></div>
                <h3>Weekly</h3>
@@ -1143,6 +1319,8 @@ HTML
                }
 
                print <<HTML;
+               <h3>Hourly</h3>
+               <div><img src="$MySelf$RelDir/$ext/hour" /></div>
                <h3>Daily</h3>
                <div><img src="$MySelf$RelDir/$ext/day" /></div>
                <h3>Weekly</h3>
index 29cfeda..d35c75f 100644 (file)
@@ -1,14 +1,8 @@
-collectd (3.8.4-1) unstable; urgency=low
+collectd (3.9.0-1) unstable; urgency=low
 
   * New upstream version
 
- -- Florian Forster <octo@verplant.org>  Sun,  9 Apr 2006 16:01:11 +0200
-
-collectd (3.8.3-1) unstable; urgency=low
-
-  * New upstream version
-
- -- Florian Forster <octo@verplant.org>  Sun,  2 Apr 2006 10:34:05 +0200
+ -- Florian Forster <octo@verplant.org>  Tue, 21 Mar 2006 22:52:54 +0200
 
 collectd (3.8.2-1) unstable; urgency=low
 
diff --git a/debian/collectd-apache.files b/debian/collectd-apache.files
new file mode 100644 (file)
index 0000000..f983e90
--- /dev/null
@@ -0,0 +1 @@
+usr/lib/collectd/apache.so*
index 9b3b9ca..69918a5 100644 (file)
@@ -2,7 +2,7 @@ Source: collectd
 Section: utils
 Priority: optional
 Maintainer: Florian Forster <octo@verplant.org>
-Build-Depends: debhelper (>= 4.0.0), autotools-dev, librrd0-dev | librrd2-dev, libsensors-dev, libmysqlclient14-dev
+Build-Depends: debhelper (>= 4.0.0), autotools-dev, librrd0-dev | librrd2-dev, libsensors-dev, libmysqlclient14-dev, libcurl3-dev
 Standards-Version: 3.6.1
 
 Package: collectd
@@ -16,6 +16,13 @@ Description: Statistics collection daemon for filling RRD files.
  it's very fast and easy on the system. Also, the statistics are very fine
  grained since the files are updated every 10 seconds.
 
+Package: collectd-apache
+Architecture: any
+Depends: collectd (= ${Source-Version}), apache2 | apache, libcurl3
+Description: collectd plugin for Apache-statistics
+ collectd module to collect Apache statistics. It reads the page generated by
+ `mod_status' and writes it's content into RRD files.
+
 Package: collectd-mysql
 Architecture: any
 Depends: collectd (= ${Source-Version}), libmysqlclient14
index d64075d..5ae5761 100755 (executable)
@@ -18,7 +18,7 @@ DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
 
 CFLAGS = -Wall -g
 
-PLUGINS = mysql sensors
+PLUGINS = apache mysql sensors
 
 ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
        CFLAGS += -O0
index 2563462..c554abe 100644 (file)
@@ -44,17 +44,42 @@ collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la
 
 pkglib_LTLIBRARIES = 
 
+if BUILD_MODULE_APACHE
+pkglib_LTLIBRARIES += apache.la
+apache_la_SOURCES = apache.c
+apache_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBCURL
+apache_la_LDFLAGS += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+collectd_LDADD += "-dlopen" apache.la
+collectd_DEPENDENCIES += apache.la
+endif
+
+if BUILD_MODULE_APPLE_SENSORS
+pkglib_LTLIBRARIES += apple_sensors.la
+apple_sensors_la_SOURCES = apple_sensors.c
+apple_sensors_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBIOKIT
+apple_sensors_la_LDFLAGS += -lIOKit
+endif
+collectd_LDADD += "-dlopen" apple_sensors.la
+collectd_DEPENDENCIES += apple_sensors.la
+endif
+
 if BUILD_MODULE_BATTERY
 pkglib_LTLIBRARIES += battery.la
 battery_la_SOURCES = battery.c
 battery_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBIOKIT
+battery_la_LDFLAGS += -lIOKit
+endif
 collectd_LDADD += "-dlopen" battery.la
 collectd_DEPENDENCIES += battery.la
 endif
 
 if BUILD_MODULE_CPU
 pkglib_LTLIBRARIES += cpu.la
-cpu_la_SOURCES = cpu.c cpu.h
+cpu_la_SOURCES = cpu.c
 cpu_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" cpu.la
 collectd_DEPENDENCIES += cpu.la
@@ -62,7 +87,7 @@ endif
 
 if BUILD_MODULE_CPUFREQ
 pkglib_LTLIBRARIES += cpufreq.la
-cpufreq_la_SOURCES = cpufreq.c cpufreq.h
+cpufreq_la_SOURCES = cpufreq.c
 cpufreq_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" cpufreq.la
 collectd_DEPENDENCIES += cpufreq.la
@@ -78,7 +103,7 @@ endif
 
 if BUILD_MODULE_DISK
 pkglib_LTLIBRARIES += disk.la
-disk_la_SOURCES = disk.c disk.h
+disk_la_SOURCES = disk.c
 disk_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" disk.la
 collectd_DEPENDENCIES += disk.la
@@ -97,7 +122,7 @@ endif
 
 if BUILD_MODULE_HDDTEMP
 pkglib_LTLIBRARIES += hddtemp.la
-hddtemp_la_SOURCES = hddtemp.c hddtemp.h
+hddtemp_la_SOURCES = hddtemp.c
 hddtemp_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" hddtemp.la
 collectd_DEPENDENCIES += hddtemp.la
@@ -105,7 +130,7 @@ endif
 
 if BUILD_MODULE_LOAD
 pkglib_LTLIBRARIES += load.la
-load_la_SOURCES = load.c load.h
+load_la_SOURCES = load.c
 load_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" load.la
 collectd_DEPENDENCIES += load.la
@@ -113,7 +138,7 @@ endif
 
 if BUILD_MODULE_MEMORY
 pkglib_LTLIBRARIES += memory.la
-memory_la_SOURCES = memory.c memory.h
+memory_la_SOURCES = memory.c
 memory_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" memory.la
 collectd_DEPENDENCIES += memory.la
@@ -132,7 +157,7 @@ endif
 
 if BUILD_MODULE_NFS
 pkglib_LTLIBRARIES += nfs.la
-nfs_la_SOURCES = nfs.c nfs.h
+nfs_la_SOURCES = nfs.c
 nfs_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" nfs.la
 collectd_DEPENDENCIES += nfs.la
@@ -140,7 +165,7 @@ endif
 
 if BUILD_MODULE_PING
 pkglib_LTLIBRARIES += ping.la
-ping_la_SOURCES = ping.c ping.h
+ping_la_SOURCES = ping.c
 ping_la_LDFLAGS = -module -avoid-version
 ping_la_LIBADD  = liboping/liboping.la
 ping_la_DEPENDENCIES = liboping/liboping.la
@@ -150,7 +175,7 @@ endif
 
 if BUILD_MODULE_PROCESSES
 pkglib_LTLIBRARIES += processes.la
-processes_la_SOURCES = processes.c processes.h
+processes_la_SOURCES = processes.c
 processes_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" processes.la
 collectd_DEPENDENCIES += processes.la
@@ -158,7 +183,7 @@ endif
 
 if BUILD_MODULE_SENSORS
 pkglib_LTLIBRARIES += sensors.la
-sensors_la_SOURCES = sensors.c sensors.h
+sensors_la_SOURCES = sensors.c
 sensors_la_LDFLAGS = -module -avoid-version
 if BUILD_WITH_LM_SENSORS
 sensors_la_LDFLAGS += -lsensors
@@ -169,7 +194,7 @@ endif
 
 if BUILD_MODULE_SERIAL
 pkglib_LTLIBRARIES += serial.la
-serial_la_SOURCES = serial.c serial.h
+serial_la_SOURCES = serial.c
 serial_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" serial.la
 collectd_DEPENDENCIES += serial.la
@@ -177,7 +202,7 @@ endif
 
 if BUILD_MODULE_SWAP
 pkglib_LTLIBRARIES += swap.la
-swap_la_SOURCES = swap.c swap.h
+swap_la_SOURCES = swap.c
 swap_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" swap.la
 collectd_DEPENDENCIES += swap.la
@@ -185,7 +210,7 @@ endif
 
 if BUILD_MODULE_TAPE
 pkglib_LTLIBRARIES += tape.la
-tape_la_SOURCES = tape.c tape.h
+tape_la_SOURCES = tape.c
 tape_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" tape.la
 collectd_DEPENDENCIES += tape.la
@@ -193,7 +218,7 @@ endif
 
 if BUILD_MODULE_TRAFFIC
 pkglib_LTLIBRARIES += traffic.la
-traffic_la_SOURCES = traffic.c traffic.h
+traffic_la_SOURCES = traffic.c
 traffic_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" traffic.la
 collectd_DEPENDENCIES += traffic.la
@@ -201,18 +226,24 @@ endif
 
 if BUILD_MODULE_USERS
 pkglib_LTLIBRARIES += users.la
-users_la_SOURCES = users.c users.h
+users_la_SOURCES = users.c
 users_la_LDFLAGS = -module -avoid-version
 collectd_LDADD += "-dlopen" users.la
 collectd_DEPENDENCIES += users.la
 endif
 
+if BUILD_MODULE_VSERVER
+pkglib_LTLIBRARIES += vserver.la
+vserver_la_SOURCES = vserver.c
+vserver_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" vserver.la
+collectd_DEPENDENCIES += vserver.la
+endif
+
 if BUILD_MODULE_WIRELESS
 pkglib_LTLIBRARIES += wireless.la
 wireless_la_SOURCES = wireless.c
 wireless_la_LDFLAGS = -module -avoid-version
-# FIXME Make `-lm' conditional
-wireless_la_LDFLAGS += -lm
 collectd_LDADD += "-dlopen" wireless.la
 collectd_DEPENDENCIES += wireless.la
 endif
diff --git a/src/apache.c b/src/apache.c
new file mode 100644 (file)
index 0000000..c410dc4
--- /dev/null
@@ -0,0 +1,328 @@
+/**
+ * collectd - src/apache.c
+ * Copyright (C) 2006  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#define MODULE_NAME "apache"
+
+#if HAVE_LIBCURL && HAVE_CURL_CURL_H
+#  define APACHE_HAVE_READ 1
+#  include <curl/curl.h>
+#else
+#  define APACHE_HAVE_READ 0
+#endif
+
+static char *url  = NULL;
+static char *user = NULL;
+static char *pass = NULL;
+
+#if APACHE_HAVE_READ
+static CURL *curl = NULL;
+
+static char apache_buffer[4096];
+static int  apache_buffer_len = 0;
+static char apache_curl_error[CURL_ERROR_SIZE];
+#endif
+
+/* Limit to 2^27 bytes/s. That's what a gigabit-ethernet link can handle, in
+ * theory. */
+static char *bytes_file = "apache/apache_bytes.rrd";
+static char *bytes_ds_def[] =
+{
+       "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:134217728",
+       NULL
+};
+static int bytes_ds_num = 1;
+
+/* Limit to 2^20 requests/s */
+static char *requests_file = "apache/apache_requests.rrd";
+static char *requests_ds_def[] =
+{
+       "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:1048576",
+       NULL
+};
+static int requests_ds_num = 1;
+
+static char *scoreboard_file = "apache/apache_scoreboard-%s.rrd";
+static char *scoreboard_ds_def[] =
+{
+       "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       NULL
+};
+static int scoreboard_ds_num = 1;
+
+static char *config_keys[] =
+{
+       "URL",
+       "User",
+       "Password",
+       NULL
+};
+static int config_keys_num = 3;
+
+
+static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *stream)
+{
+       size_t len = size * nmemb;
+
+       if ((apache_buffer_len + len) >= 4096)
+       {
+               len = 4095 - apache_buffer_len;
+       }
+
+       if (len <= 0)
+               return (len);
+
+       memcpy (apache_buffer + apache_buffer_len, (char *) buf, len);
+       apache_buffer_len += len;
+       apache_buffer[apache_buffer_len] = '\0';
+
+       return (len);
+}
+
+static int config_set (char **var, char *value)
+{
+       if (*var != NULL)
+       {
+               free (*var);
+               *var = NULL;
+       }
+
+       if ((*var = strdup (value)) == NULL)
+               return (1);
+       else
+               return (0);
+}
+
+static int config (char *key, char *value)
+{
+       if (strcasecmp (key, "url") == 0)
+               return (config_set (&url, value));
+       else if (strcasecmp (key, "user") == 0)
+               return (config_set (&user, value));
+       else if (strcasecmp (key, "password") == 0)
+               return (config_set (&pass, value));
+       else
+               return (-1);
+}
+
+static void init (void)
+{
+#if APACHE_HAVE_READ
+       static char credentials[1024];
+
+       if (curl != NULL)
+       {
+               curl_easy_cleanup (curl);
+       }
+
+       if ((curl = curl_easy_init ()) == NULL)
+       {
+               syslog (LOG_ERR, "apache: `curl_easy_init' failed.");
+               return;
+       }
+
+       curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
+       curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+       curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, apache_curl_error);
+
+       if (user != NULL)
+       {
+               if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
+               {
+                       syslog (LOG_ERR, "apache: Credentials would have been truncated.");
+                       return;
+               }
+
+               curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
+       }
+
+       if (url != NULL)
+       {
+               curl_easy_setopt (curl, CURLOPT_URL, url);
+       }
+#endif /* APACHE_HAVE_READ */
+}
+
+static void bytes_write (char *host, char *inst, char *val)
+{
+       rrd_update_file (host, bytes_file, val, bytes_ds_def, bytes_ds_num);
+}
+
+static void requests_write (char *host, char *inst, char *val)
+{
+       rrd_update_file (host, requests_file, val, requests_ds_def, requests_ds_num);
+}
+
+static void scoreboard_write (char *host, char *inst, char *val)
+{
+       char buf[1024];
+
+       if (snprintf (buf, 1024, scoreboard_file, inst) >= 1024)
+               return;
+
+       rrd_update_file (host, buf, val, scoreboard_ds_def, scoreboard_ds_num);
+}
+
+#if APACHE_HAVE_READ
+static void submit (char *type, char *inst, long long value)
+{
+       char buf[1024];
+       int  status;
+
+       status = snprintf (buf, 1024, "%u:%lli", (unsigned int) curtime, value);
+       if (status < 0)
+       {
+               syslog (LOG_ERR, "apache: bytes_submit: snprintf failed");
+               return;
+       }
+       else if (status >= 1024)
+       {
+               syslog (LOG_WARNING, "apache: bytes_submit: snprintf was truncated");
+               return;
+       }
+
+       plugin_submit (type, inst, buf);
+}
+
+static void submit_scoreboard (char *buf)
+{
+       /*
+        * Scoreboard Key:
+        * "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
+        * "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
+        * "C" Closing connection, "L" Logging, "G" Gracefully finishing,
+        * "I" Idle cleanup of worker, "." Open slot with no current process
+        */
+       long long open      = 0LL;
+       long long waiting   = 0LL;
+       long long starting  = 0LL;
+       long long reading   = 0LL;
+       long long sending   = 0LL;
+       long long keepalive = 0LL;
+       long long dnslookup = 0LL;
+       long long closing   = 0LL;
+       long long logging   = 0LL;
+       long long finishing = 0LL;
+       long long idle_cleanup = 0LL;
+
+       int i;
+
+       for (i = 0; buf[i] != '\0'; i++)
+       {
+               if (buf[i] == '.') open++;
+               else if (buf[i] == '_') waiting++;
+               else if (buf[i] == 'S') starting++;
+               else if (buf[i] == 'R') reading++;
+               else if (buf[i] == 'W') sending++;
+               else if (buf[i] == 'K') keepalive++;
+               else if (buf[i] == 'D') dnslookup++;
+               else if (buf[i] == 'C') closing++;
+               else if (buf[i] == 'L') logging++;
+               else if (buf[i] == 'G') finishing++;
+               else if (buf[i] == 'I') idle_cleanup++;
+       }
+
+       submit ("apache_scoreboard", "open"     , open);
+       submit ("apache_scoreboard", "waiting"  , waiting);
+       submit ("apache_scoreboard", "starting" , starting);
+       submit ("apache_scoreboard", "reading"  , reading);
+       submit ("apache_scoreboard", "sending"  , sending);
+       submit ("apache_scoreboard", "keepalive", keepalive);
+       submit ("apache_scoreboard", "dnslookup", dnslookup);
+       submit ("apache_scoreboard", "closing"  , closing);
+       submit ("apache_scoreboard", "logging"  , logging);
+       submit ("apache_scoreboard", "finishing", finishing);
+       submit ("apache_scoreboard", "idle_cleanup", idle_cleanup);
+}
+
+static void apache_read (void)
+{
+       int i;
+
+       char *ptr;
+       char *lines[16];
+       int   lines_num = 0;
+
+       char *fields[4];
+       int   fields_num;
+
+       if (curl == NULL)
+               return;
+       if (url == NULL)
+               return;
+
+       if (curl_easy_perform (curl) != 0)
+       {
+               syslog (LOG_WARNING, "apache: curl_easy_perform failed: %s", apache_curl_error);
+               return;
+       }
+
+       ptr = apache_buffer;
+       while ((lines[lines_num] = strtok (ptr, "\n\r")) != NULL)
+       {
+               ptr = NULL;
+               lines_num++;
+
+               if (lines_num >= 16)
+                       break;
+       }
+
+       for (i = 0; i < lines_num; i++)
+       {
+               fields_num = strsplit (lines[i], fields, 4);
+
+               if (fields_num == 3)
+               {
+                       if ((strcmp (fields[0], "Total") == 0)
+                                       && (strcmp (fields[1], "Accesses:") == 0))
+                               submit ("apache_requests", NULL, atoll (fields[2]));
+                       else if ((strcmp (fields[0], "Total") == 0)
+                                       && (strcmp (fields[1], "kBytes:") == 0))
+                               submit ("apache_bytes", NULL, 1024LL * atoll (fields[2]));
+               }
+               else if (fields_num == 2)
+               {
+                       if (strcmp (fields[0], "Scoreboard:") == 0)
+                               submit_scoreboard (fields[1]);
+               }
+       }
+
+       apache_buffer_len = 0;
+}
+#else
+#  define apache_read NULL
+#endif /* APACHE_HAVE_READ */
+
+void module_register (void)
+{
+       plugin_register (MODULE_NAME, init, apache_read, NULL);
+       plugin_register ("apache_requests",   NULL, NULL, requests_write);
+       plugin_register ("apache_bytes",      NULL, NULL, bytes_write);
+       plugin_register ("apache_scoreboard", NULL, NULL, scoreboard_write);
+       cf_register (MODULE_NAME, config, config_keys, config_keys_num);
+}
+
+#undef MODULE_NAME
diff --git a/src/apple_sensors.c b/src/apple_sensors.c
new file mode 100644 (file)
index 0000000..24e8f97
--- /dev/null
@@ -0,0 +1,268 @@
+/**
+ * collectd - src/apple_sensors.c
+ * Copyright (C) 2006  Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_debug.h"
+
+#define MODULE_NAME "apple_sensors"
+
+#if HAVE_CTYPE_H
+#  include <ctype.h>
+#endif
+
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_MACH_MACH_PORT_H
+#  include <mach/mach_port.h>
+#endif
+#if HAVE_COREFOUNDATION_COREFOUNDATION_H
+#  include <CoreFoundation/CoreFoundation.h>
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+
+#if HAVE_IOKIT_IOKITLIB_H
+# define IOKIT_HAVE_READ 1
+#else
+# define IOKIT_HAVE_READ 0
+#endif
+
+#if HAVE_IOKIT_IOKITLIB_H
+static mach_port_t io_master_port = MACH_PORT_NULL;
+#endif
+
+static char *temperature_file = "apple_sensors/temperature-%s.rrd";
+static char *fanspeed_file    = "apple_sensors/fanspeed-%s.rrd";
+
+static char *ds_def[] =
+{
+       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
+       NULL
+};
+static int ds_num = 1;
+
+static void as_init (void)
+{
+#if IOKIT_HAVE_READ
+       kern_return_t status;
+       
+       if (io_master_port != MACH_PORT_NULL)
+       {
+               mach_port_deallocate (mach_task_self (),
+                               io_master_port);
+               io_master_port = MACH_PORT_NULL;
+       }
+
+       status = IOMasterPort (MACH_PORT_NULL, &io_master_port);
+       if (status != kIOReturnSuccess)
+       {
+               syslog (LOG_ERR, "IOMasterPort failed: %s",
+                               mach_error_string (status));
+               io_master_port = MACH_PORT_NULL;
+               return;
+       }
+#endif /* IOKIT_HAVE_READ */
+
+       return;
+}
+
+static void as_write (char *host, char *inst, char *val, const char *template)
+{
+       char filename[256];
+       int  status;
+
+       status = snprintf (filename, 256, template, inst);
+       if ((status < 1) || (status >= 256))
+               return;
+
+       rrd_update_file (host, filename, val, ds_def, ds_num);
+}
+
+static void temperature_write (char *host, char *inst, char *val)
+{
+       as_write (host, inst, val, temperature_file);
+}
+
+static void fanspeed_write (char *host, char *inst, char *val)
+{
+       as_write (host, inst, val, fanspeed_file);
+}
+
+#if IOKIT_HAVE_READ
+static void as_submit (char *type, char *inst, double value)
+{
+       char buf[128];
+
+       if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime,
+                               value) >= 128)
+               return;
+
+       plugin_submit (type, inst, buf);
+}
+
+static void as_read (void)
+{
+       kern_return_t   status;
+       io_iterator_t   iterator;
+       io_object_t     io_obj;
+       CFMutableDictionaryRef prop_dict;
+       CFTypeRef       property;
+
+       char   type[128];
+       char   inst[128];
+       int    value_int;
+       double value_double;
+       int    i;
+
+       if (!io_master_port || (io_master_port == MACH_PORT_NULL))
+               return;
+
+       status = IOServiceGetMatchingServices (io_master_port,
+                       IOServiceNameMatching("IOHWSensor"),
+                       &iterator);
+       if (status != kIOReturnSuccess)
+               {
+               syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s",
+                               mach_error_string (status));
+               return;
+       }
+
+       while ((io_obj = IOIteratorNext (iterator)))
+       {
+               prop_dict = NULL;
+               status = IORegistryEntryCreateCFProperties (io_obj,
+                               &prop_dict,
+                               kCFAllocatorDefault,
+                               kNilOptions);
+               if (status != kIOReturnSuccess)
+               {
+                       DBG ("IORegistryEntryCreateCFProperties failed: %s",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               /* Copy the sensor type. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("type"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFStringGetTypeID ())
+                       continue;
+               if (!CFStringGetCString (property,
+                                       type, 128,
+                                       kCFStringEncodingASCII))
+                       continue;
+               type[127] = '\0';
+
+               /* Copy the sensor location. This will be used as `instance'. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("location"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFStringGetTypeID ())
+                       continue;
+               if (!CFStringGetCString (property,
+                                       inst, 128,
+                                       kCFStringEncodingASCII))
+                       continue;
+               inst[127] = '\0';
+               for (i = 0; i < 128; i++)
+               {
+                       if (inst[i] == '\0')
+                               break;
+                       else if (isalnum (inst[i]))
+                               inst[i] = (char) tolower (inst[i]);
+                       else
+                               inst[i] = '_';
+               }
+
+               /* Get the actual value. Some computation, based on the `type'
+                * is neccessary. */
+               property = NULL;
+               if (!CFDictionaryGetValueIfPresent (prop_dict,
+                                       CFSTR ("current-value"),
+                                       &property))
+                       continue;
+               if (CFGetTypeID (property) != CFNumberGetTypeID ())
+                       continue;
+               if (!CFNumberGetValue (property,
+                                       kCFNumberIntType,
+                                       &value_int))
+                       continue;
+
+               if (strcmp (type, "temperature") == 0)
+               {
+                       value_double = ((double) value_int) / 65536.0;
+                       strncpy (type, "apple_temperature", 128);
+               }
+               else if (strcmp (type, "fanspeed") == 0)
+               {
+                       value_double = ((double) value_int) / 65536.0;
+                       strncpy (type, "apple_fanspeed", 128);
+               }
+               else if (strcmp (type, "voltage") == 0)
+               {
+                       /* Leave this to the battery plugin. */
+                       continue;
+               }
+               else
+               {
+                       DBG ("apple_sensors: Read unknown sensor type: %s",
+                                       type);
+                       value_double = (double) value_int;
+               }
+
+               as_submit (type, inst, value_double);
+
+               CFRelease (prop_dict);
+               IOObjectRelease (io_obj);
+       } /* while (iterator) */
+
+       IOObjectRelease (iterator);
+}
+#else
+# define as_read NULL
+#endif /* IOKIT_HAVE_READ */
+
+void module_register (void)
+{
+       plugin_register (MODULE_NAME, as_init, as_read, NULL);
+       plugin_register ("apple_temperature", NULL, NULL, temperature_write);
+       plugin_register ("apple_fanspeed",    NULL, NULL, fanspeed_write);
+}
+
+#undef MODULE_NAME
index 21b19bb..61379e0 100644 (file)
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
+#include "utils_debug.h"
 
 #define MODULE_NAME "battery"
 #define BUFSIZE 512
 
-#if defined(KERNEL_LINUX)
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_COREFOUNDATION_COREFOUNDATION_H
+#  include <CoreFoundation/CoreFoundation.h>
+#endif
+#if HAVE_IOKIT_IOKITLIB_H
+#  include <IOKit/IOKitLib.h>
+#endif
+#if HAVE_IOKIT_IOTYPES_H
+#  include <IOKit/IOTypes.h>
+#endif
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+#  include <IOKit/ps/IOPowerSources.h>
+#endif
+#if HAVE_IOKIT_PS_IOPSKEYS_H
+#  include <IOKit/ps/IOPSKeys.h>
+#endif
+
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || KERNEL_LINUX
 # define BATTERY_HAVE_READ 1
 #else
 # define BATTERY_HAVE_READ 0
@@ -41,33 +67,41 @@ static char *battery_charge_file  = "battery-%s/charge.rrd";
 
 static char *ds_def_current[] =
 {
-       "DS:current:GAUGE:25:U:U",
+       "DS:current:GAUGE:"COLLECTD_HEARTBEAT":U:U",
        NULL
 };
 static int ds_num_current = 1;
 
 static char *ds_def_voltage[] =
 {
-       "DS:voltage:GAUGE:25:U:U",
+       "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
        NULL
 };
 static int ds_num_voltage = 1;
 
 static char *ds_def_charge[] =
 {
-       "DS:charge:GAUGE:25:0:U",
+       "DS:charge:GAUGE:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num_charge = 1;
 
-#if BATTERY_HAVE_READ
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+       /* No global variables */
+/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+#elif KERNEL_LINUX
 static int   battery_pmu_num = 0;
 static char *battery_pmu_file = "/proc/pmu/battery_%i";
-#endif
+#endif /* KERNEL_LINUX */
 
 static void battery_init (void)
 {
-#if BATTERY_HAVE_READ
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+       /* No init neccessary */
+/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+#elif KERNEL_LINUX
        int len;
        char filename[BUFSIZE];
 
@@ -81,7 +115,7 @@ static void battery_init (void)
                if (access (filename, R_OK))
                        break;
        }
-#endif
+#endif /* KERNEL_LINUX */
 
        return;
 }
@@ -170,7 +204,134 @@ static void battery_submit (char *inst, double current, double voltage, double c
 
 static void battery_read (void)
 {
-#ifdef KERNEL_LINUX
+#if HAVE_IOKIT_PS_IOPOWERSOURCES_H
+       CFTypeRef       ps_raw;
+       CFArrayRef      ps_array;
+       int             ps_array_len;
+       CFDictionaryRef ps_dict;
+       CFTypeRef       ps_obj;
+       CFTypeRef       ps_value;
+
+       int i;
+
+       char   name[128];
+       double charge  = INVALID_VALUE;
+       double current = INVALID_VALUE;
+       double voltage = INVALID_VALUE;
+
+       ps_raw       = IOPSCopyPowerSourcesInfo ();
+       ps_array     = IOPSCopyPowerSourcesList (ps_raw);
+       ps_array_len = CFArrayGetCount (ps_array);
+
+       DBG ("ps_array_len == %i", ps_array_len);
+
+       for (i = 0; i < ps_array_len; i++)
+       {
+               ps_obj  = CFArrayGetValueAtIndex (ps_array, i);
+               ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj);
+
+               if (CFGetTypeID (ps_dict) != CFDictionaryGetTypeID ())
+               {
+                       DBG ("IOPSGetPowerSourceDescription did not return a CFDictionaryRef");
+                       continue;
+               }
+
+               if (ps_dict != NULL)
+               {
+                       /* Get the current capacity/charge */
+                       ps_value = NULL;
+                       charge   = INVALID_VALUE;
+                       if (CFDictionaryGetValueIfPresent (ps_dict,
+                                               CFSTR (kIOPSCurrentCapacityKey),
+                                               &ps_value))
+                       {
+                               if (CFGetTypeID (ps_value) != CFNumberGetTypeID ())
+                                       CFNumberGetValue (ps_value,
+                                                       kCFNumberDoubleType,
+                                                       &charge);
+                               else
+                                       DBG ("kIOPSCurrentCapacityKey: Not a CFNumber");
+
+                               DBG ("charge = %f", charge);
+                       }
+                       else
+                               DBG ("`%s' does not exist", kIOPSCurrentCapacityKey);
+
+                       /* Get the current */
+                       ps_value = NULL;
+                       current  = INVALID_VALUE;
+                       if (CFDictionaryGetValueIfPresent (ps_dict,
+                                               CFSTR (kIOPSCurrentKey),
+                                               &ps_value))
+                       {
+                               if (CFGetTypeID (ps_value) != CFNumberGetTypeID ())
+                                       CFNumberGetValue (ps_value,
+                                                       kCFNumberDoubleType,
+                                                       &current);
+                               else
+                                       DBG ("kIOPSCurrentKey: Not a CFNumber");
+                               DBG ("current = %f", current);
+                       }
+                       else
+                               DBG ("`%s' does not exist", kIOPSCurrentKey);
+
+                       /* Get the voltage */
+                       ps_value = NULL;
+                       voltage  = INVALID_VALUE;
+                       if (CFDictionaryGetValueIfPresent (ps_dict,
+                                               CFSTR (kIOPSVoltageKey),
+                                               &ps_value))
+                       {
+                               if (CFGetTypeID (ps_value) != CFNumberGetTypeID ())
+                                       CFNumberGetValue (ps_value,
+                                                       kCFNumberDoubleType,
+                                                       &voltage);
+                               else
+                                       DBG ("kIOPSVoltageKey: Not a CFNumber");
+                               DBG ("voltage = %f", voltage);
+                       }
+                       else
+                               DBG ("`%s' does not exist", kIOPSVoltageKey);
+
+                       /* Get the name of the device.. */
+                       ps_value = NULL;
+                       if (CFDictionaryGetValueIfPresent (ps_dict,
+                                               CFSTR (kIOPSNameKey),
+                                               &ps_value))
+                       {
+                               if (CFGetTypeID (ps_value) != CFStringGetTypeID ())
+                                       if (!CFStringGetCString (ps_value,
+                                                               name, 128,
+                                                               kCFStringEncodingASCII))
+                                               continue;
+                               else
+                                       DBG ("kIOPSNameKey: Not a CFStringGetTypeID");
+                               DBG ("Original string: `%s'", name);
+                       }
+                       else
+                       {
+                               strncpy (name, "unknown", 128);
+                       }
+                       name[127] = '\0';
+                       for (i = 0; i < 128; i++)
+                       {
+                               if (name[i] == '\0')
+                                       break;
+                               else if (isalnum (name[i]))
+                                       name[i] = (char) tolower (name[i]);
+                               else
+                                       name[i] = '_';
+                       }
+
+                       battery_submit (name, current, voltage, charge);
+               }
+       }
+
+       CFRelease(ps_array);
+       CFRelease(ps_raw);
+/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */
+
+#elif KERNEL_LINUX
        FILE *fh;
        char buffer[BUFSIZE];
        char filename[BUFSIZE];
index 7b264e8..0c80365 100644 (file)
@@ -29,8 +29,6 @@
 #include "plugin.h"
 #include "configfile.h"
 
-#include "ping.h"
-
 static int loop = 0;
 
 #if HAVE_LIBKSTAT
@@ -135,6 +133,8 @@ static void exit_usage (char *name)
 #if COLLECT_DEBUG
                        "  Log-File          "LOGFILE"\n"
 #endif
+                       "  Step              "COLLECTD_STEP" seconds\n"
+                       "  Heartbeat         "COLLECTD_HEARTBEAT" seconds\n"
                        "\n"PACKAGE" "VERSION", http://verplant.org/collectd/\n"
                        "by Florian octo Forster <octo@verplant.org>\n"
                        "for contributions see `AUTHORS'\n");
@@ -143,7 +143,15 @@ static void exit_usage (char *name)
 
 static int start_client (void)
 {
-       int sleepingtime;
+       int step;
+
+       struct timeval tv_now;
+       struct timeval tv_next;
+       struct timespec ts_wait;
+
+       step = atoi (COLLECTD_STEP);
+       if (step <= 0)
+               step = 10;
 
 #if HAVE_LIBKSTAT
        kc = NULL;
@@ -168,18 +176,42 @@ static int start_client (void)
 
        while (loop == 0)
        {
-               curtime = time (NULL);
+               if (gettimeofday (&tv_next, NULL) < 0)
+               {
+                       syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno));
+                       return (-1);
+               }
+               tv_next.tv_sec += step;
+
 #if HAVE_LIBKSTAT
                update_kstat ();
 #endif
+               /* `curtime' is used by many (all?) plugins as the
+                * data-sample-time passed to RRDTool */
+               curtime = time (NULL);
+
+               /* Issue all plugins */
                plugin_read_all ();
 
-               sleepingtime = 10;
-               while (sleepingtime != 0)
+               if (gettimeofday (&tv_now, NULL) < 0)
                {
-                       if (loop != 0)
+                       syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno));
+                       return (-1);
+               }
+
+               if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0)
+               {
+                       syslog (LOG_WARNING, "No sleeping because `timeval_sub_timespec' returned non-zero!");
+                       continue;
+               }
+
+               while (nanosleep (&ts_wait, &ts_wait) == -1)
+               {
+                       if (errno != EINTR)
+                       {
+                               syslog (LOG_ERR, "nanosleep failed: %s", strerror (errno));
                                break;
-                       sleepingtime = sleep (sleepingtime);
+                       }
                }
        }
 
index 5852b6d..a00bbb2 100644 (file)
@@ -104,6 +104,26 @@ operating systems.
 Some Plugins may register own options. These options must be inclosed in a
 C<Plugin>-Section. Which options exist depends on the plugin used:
 
+=head2 Plugin C<apache>
+
+=over 4
+
+=item B<URL> I<http://host/mod_status?auto>
+
+Sets the URL of the C<mod_status> output. This needs to be the output generated
+by C<ExtendedStatus on> and it needs to be the machine readable output
+generated by appending the C<?auto> argument.
+
+=item B<User> I<Username>
+
+Optional user name needed for authentication.
+
+=item B<Password> I<Password>
+
+Optional password needed for authentication.
+
+=back
+
 =head2 Plugin C<hddtemp>
 
 =over 4
@@ -150,6 +170,10 @@ option for what this plugin does.
 Host to ping periodically. This option may be repeated several times to ping
 multiple hosts.
 
+=item B<TTL> I<0-255>
+
+Sets the Time-To-Live of generated ICMP packets.
+
 =back
 
 =head1 SEE ALSO
index 0221a59..9781bdc 100644 (file)
 #define MODE_LOCAL  0x04
 #define MODE_LOG    0x08
 
+#ifndef COLLECTD_STEP
+#  define COLLECTD_STEP "10"
+#endif
+
+#ifndef COLLECTD_HEARTBEAT
+#  define COLLECTD_HEARTBEAT "25"
+#endif
+
+#ifndef COLLECTD_ROWS
+#  define COLLECTD_ROWS "1200"
+#endif
+
+#ifndef COLLECTD_XFF
+#  define COLLECTD_XFF 0.1
+#endif
+
 extern time_t curtime;
 
 #ifdef HAVE_LIBRRD
index 6d57200..1eef525 100644 (file)
@@ -82,6 +82,10 @@ Network traffic (I<traffic>)
 
 Number of users logged into the system (I<users>)
 
+=item
+
+System ressources used by VServers (I<vserver>)
+
 =back
 
 =head1 OPTIONS
@@ -133,12 +137,29 @@ values.
 
 =head1 SPECIAL PLUGINS
 
+=head2 apache
+
+This module connects to an Apache webserver and expects the output produced by
+B<mod_status.c>. If requires B<libcurl> to set up the HTTP connection and issue
+the request(s). The following is a sample config for the Apache webserver. The
+use of C<ExtendedStatus on> is mandatory.
+
+  ExtendedStatus on
+  <IfModule mod_status.c>
+    <Location /mod_status>
+      SetHandler server-status
+    </Location>
+  </IfModule>
+
+This plugin requires further configuration. Please read L<collectd.conf(5)>.
+
 =head2 cpufreq
 
 This module reads F</sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq> (for
 the first CPU installed) to get the current CPU frequency. If this file does
 not exist make sure B<cpufreqd> (L<http://cpufreqd.sourceforge.net/>) or a
-similar tool is installed.
+similar tool is installed and an "cpu governor" (that's kernel module) is
+loaded.
 
 =head2 mysql
 
@@ -175,28 +196,45 @@ which may interfere with other statistics..
 The B<hddtemp> homepage can be found at
 L<http://www.guzu.net/linux/hddtemp.php>.
 
-=head1 RRD FILES
+=head2 vserver
 
-The RRD files are created automatically with the following RRAs:
+B<VServer> support is only available for Linux. It cannot yet be found in a 
+vanilla kernel, though. To make use of this plugin you need a kernel that has 
+B<VServer> support built in, i.e. you need to apply the patches and compile 
+your own kernel, which will then provide the /proc/virtual filesystem that is
+required by this plugin.
 
-  RRA:AVERAGE:0.2:6:1500
-  RRA:AVERAGE:0.1:180:1680
-  RRA:AVERAGE:0.1:2160:1520
-  RRA:MIN:0.2:6:1500
-  RRA:MIN:0.1:180:1680
-  RRA:MIN:0.1:2160:1520
-  RRA:MAX:0.2:6:1500
-  RRA:MAX:0.1:180:1680
-  RRA:MAX:0.1:2160:1520
+The B<VServer> homepage can be found at L<http://linux-vserver.org/>.
 
-Since collectd uses a 10 second I<step> the RRAs contain the following
-timespans:
+=head1 RRD FILES
 
-  Resolution | Data points |  Timespan
-  -----------+-------------+----------
-  60 seconds |        1500 |  25 hours
-  30 minutes |        1680 |  35 days
-   6 hours   |        1520 | 380 days
+The RRD files are created automatically. The size of the RRAs depend on the
+compile time settings of I<step> and I<width>. With the default values (I<step>
+= B<10>, I<width> = B<1200>) the following RRAs are created:
+
+  RRA:AVERAGE:0.1:1:8640
+  RRA:AVERAGE:0.1:50:1210
+  RRA:AVERAGE:0.1:223:1202
+  RRA:AVERAGE:0.1:2635:1201
+  RRA:MIN:0.1:1:8640
+  RRA:MIN:0.1:50:1210
+  RRA:MIN:0.1:223:1202
+  RRA:MIN:0.1:2635:1201
+  RRA:MAX:0.1:1:8640
+  RRA:MAX:0.1:50:1210
+  RRA:MAX:0.1:223:1202
+  RRA:MAX:0.1:2635:1201
+
+By default collectd uses a 10 second I<step>. Thus the RRAs contain the
+following timespans. If you've changed the I<step> at compile time you will
+have calculate resolution and timespan yourself.
+
+  PDP per CDP |  Resolution  | Data points | Timespan
+  ------------+--------------+-------------+---------
+            1 | 10.0 seconds !        8640 ! 1 day
+           50 |  8.3 minutes |        1210 | 1 week
+          223 | 37.2 minutes |        1202 | 1 month
+         2635 |  7.3 hours   |        1201 | 1 year
 
 The DS'es depend on the module creating the RRD files:
 
@@ -376,6 +414,36 @@ The DS'es depend on the module creating the RRD files:
 
   DS:users:GAUGE:25:0:65535
 
+=item VServer load (F<vserver-I<E<lt>xidE<gt>>/load.rrd>)
+
+  DS:shortterm:GAUGE:25:0:100
+  DS:midterm:GAUGE:25:0:100
+  DS:longterm:GAUGE:25:0:100
+
+=item VServer threads (F<vserver-I<E<lt>xidE<gt>>/threads.rrd>)
+
+  DS:total:GAUGE:25:0:65535
+  DS:running:GAUGE:25:0:65535
+  DS:uninterruptible:GAUGE:25:0:65535
+  DS:onhold:GAUGE:25:0:65535
+
+=item VServer network traffic (F<vserver-I<E<lt>xidE<gt>>/traffic-I<E<lt>nameE<gt>>.rrd>)
+
+  DS:incoming:COUNTER:25:0:9223372036854775807
+  DS:outgoing:COUNTER:25:0:9223372036854775807
+  DS:failed:COUNTER:25:0:9223372036854775807
+
+=item VServer processes (F<vserver-I<E<lt>xidE<gt>>/vs_processes.rrd>)
+
+  DS:total:GAUGE:25:0:65535
+
+=item VServer memory usage (F<vserver-I<E<lt>xidE<gt>>/vs_memory.rrd>)
+
+  DS:vm:GAUGE:25:0:9223372036854775807
+  DS:vml:GAUGE:25:0:9223372036854775807
+  DS:rss:GAUGE:25:0:9223372036854775807
+  DS:anon:GAUGE:25:0:9223372036854775807
+
 =back
 
 =head1 SEE ALSO
index 56ae326..a4b718c 100644 (file)
 #include "common.h"
 #include "utils_debug.h"
 
+#ifdef HAVE_MATH_H
+#  include <math.h>
+#endif
+
 extern int operating_mode;
 
 #ifdef HAVE_LIBKSTAT
@@ -32,20 +36,45 @@ extern kstat_ctl_t *kc;
 #endif
 
 #ifdef HAVE_LIBRRD
+#if 0
 static char *rra_def[] =
 {
+               "RRA:AVERAGE:0.0:1:1500",
                "RRA:AVERAGE:0.2:6:1500",
                "RRA:AVERAGE:0.1:180:1680",
                "RRA:AVERAGE:0.1:2160:1520",
+               "RRA:MIN:0.0:1:1500",
                "RRA:MIN:0.2:6:1500",
                "RRA:MIN:0.1:180:1680",
                "RRA:MIN:0.1:2160:1520",
+               "RRA:MAX:0.0:1:1500",
                "RRA:MAX:0.2:6:1500",
                "RRA:MAX:0.1:180:1680",
                "RRA:MAX:0.1:2160:1520",
                NULL
 };
-static int rra_num = 9;
+static int rra_num = 12;
+#endif
+
+static int rra_timespans[] =
+{
+       3600,
+       86400,
+       604800,
+       2678400,
+       31622400,
+       0
+};
+static int rra_timespans_num = 5;
+
+static char *rra_types[] =
+{
+       "AVERAGE",
+       "MIN",
+       "MAX",
+       NULL
+};
+static int rra_types_num = 3;
 #endif /* HAVE_LIBRRD */
 
 void sstrncpy (char *d, const char *s, int len)
@@ -204,6 +233,29 @@ int escape_slashes (char *buf, int buf_len)
        return (0);
 }
 
+int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret)
+{
+       if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL))
+               return (-2);
+
+       if ((tv0->tv_sec < tv1->tv_sec)
+                       || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec)))
+               return (-1);
+
+       ret->tv_sec  = tv0->tv_sec - tv1->tv_sec;
+       ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec));
+
+       if (ret->tv_nsec < 0)
+       {
+               assert (ret->tv_sec > 0);
+
+               ret->tv_nsec += 1000000000;
+               ret->tv_sec  -= 1;
+       }
+
+       return (0);
+}
+
 static int check_create_dir (const char *file_orig)
 {
        struct stat statbuf;
@@ -308,6 +360,87 @@ static int check_create_dir (const char *file_orig)
        return (0);
 }
 
+/* * * * *
+ * Magic *
+ * * * * */
+int rra_get (char ***ret)
+{
+       static char **rra_def = NULL;
+       static int rra_num = 0;
+
+       int rra_max = rra_timespans_num * rra_types_num;
+
+       int step;
+       int rows;
+       int span;
+
+       int cdp_num;
+       int cdp_len;
+       int i, j;
+
+       char buffer[64];
+
+       if ((rra_num != 0) && (rra_def != NULL))
+       {
+               *ret = rra_def;
+               return (rra_num);
+       }
+
+       if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+               return (-1);
+       memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+
+       step = atoi (COLLECTD_STEP);
+       rows = atoi (COLLECTD_ROWS);
+
+       if ((step <= 0) || (rows <= 0))
+       {
+               *ret = NULL;
+               return (-1);
+       }
+
+       cdp_len = 0;
+       for (i = 0; i < rra_timespans_num; i++)
+       {
+               span = rra_timespans[i];
+
+               if ((span / step) < rows)
+                       continue;
+
+               if (cdp_len == 0)
+                       cdp_len = 1;
+               else
+                       cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
+
+               cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
+
+               for (j = 0; j < rra_types_num; j++)
+               {
+                       if (rra_num >= rra_max)
+                               break;
+
+                       if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
+                                               rra_types[j], COLLECTD_XFF,
+                                               cdp_len, cdp_num) >= sizeof (buffer))
+                       {
+                               syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
+                               continue;
+                       }
+
+                       rra_def[rra_num++] = sstrdup (buffer);
+               }
+       }
+
+#if COLLECT_DEBUG
+       DBG ("rra_num = %i", rra_num);
+       for (i = 0; i < rra_num; i++)
+               DBG ("  %s", rra_def[i]);
+#endif
+
+       *ret = rra_def;
+       return (rra_num);
+}
+
 static int log_create_file (char *filename, char **ds_def, int ds_num)
 {
        FILE *log;
@@ -443,12 +576,20 @@ static int rrd_create_file (char *filename, char **ds_def, int ds_num)
 {
        char **argv;
        int argc;
+       char **rra_def;
+       int rra_num;
        int i, j;
        int status = 0;
 
        if (check_create_dir (filename))
                return (-1);
 
+       if ((rra_num = rra_get (&rra_def)) < 1)
+       {
+               syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs");
+               return (-1);
+       }
+
        argc = ds_num + rra_num + 4;
 
        if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
@@ -460,7 +601,7 @@ static int rrd_create_file (char *filename, char **ds_def, int ds_num)
        argv[0] = "create";
        argv[1] = filename;
        argv[2] = "-s";
-       argv[3] = "10";
+       argv[3] = COLLECTD_STEP;
 
        j = 4;
        for (i = 0; i < ds_num; i++)
index ae93635..bbc182b 100644 (file)
@@ -103,6 +103,9 @@ int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const
  */
 int escape_slashes (char *buf, int buf_len);
 
+/* FIXME: `timeval_sub_timespec' needs a description */
+int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret);
+
 int rrd_update_file (char *host, char *file, char *values,
                char **ds_def, int ds_num);
 
index 45fe684..91bef48 100644 (file)
@@ -106,7 +106,7 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value
 
        if ((cf_cb = cf_search (type)) == NULL)
        {
-               syslog (LOG_WARNING, "Plugin `%s' did not register a callback.\n", type);
+               syslog (LOG_WARNING, "Plugin `%s' did not register a callback.", type);
                return (-1);
        }
 
@@ -130,11 +130,13 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value
        }
 
        if (i >= cf_cb->keys_num)
-               syslog (LOG_WARNING, "Plugin `%s' did not register for value `%s'.\n", type, key);
+               syslog (LOG_WARNING, "Plugin `%s' did not register for value `%s'.", type, key);
 
        free (key);
        free (value);
 
+       DBG ("return (%i)", ret);
+
        return (ret);
 }
 
index 28e6233..eacc590 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
+#include "utils_debug.h"
 
 #define MODULE_NAME "cpu"
 
+#ifdef HAVE_MACH_KERN_RETURN_H
+# include <mach/kern_return.h>
+#endif
+#ifdef HAVE_MACH_MACH_INIT_H
+# include <mach/mach_init.h>
+#endif
+#ifdef HAVE_MACH_HOST_PRIV_H
+# include <mach/host_priv.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#ifdef HAVE_MACH_PROCESSOR_INFO_H
+# include <mach/processor_info.h>
+#endif
+#ifdef HAVE_MACH_PROCESSOR_H
+# include <mach/processor.h>
+#endif
+#ifdef HAVE_MACH_VM_MAP_H
+# include <mach/vm_map.h>
+#endif
+
 #ifdef HAVE_LIBKSTAT
 # include <sys/sysinfo.h>
 #endif /* HAVE_LIBKSTAT */
 # endif
 #endif /* HAVE_SYSCTLBYNAME */
 
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME)
+#if defined(PROCESSOR_CPU_LOAD_INFO) || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME)
 # define CPU_HAVE_READ 1
 #else
 # define CPU_HAVE_READ 0
 #endif
 
-#ifdef HAVE_LIBKSTAT
+#ifdef PROCESSOR_CPU_LOAD_INFO
+static mach_port_t port_host;
+static processor_port_array_t cpu_list;
+static mach_msg_type_number_t cpu_list_len;
+/* #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(KERNEL_LINUX)
+/* no variables needed */
+/* #endif KERNEL_LINUX */
+
+#elif defined(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 */
+/* #endif HAVE_LIBKSTAT */
 
-#ifdef HAVE_SYSCTLBYNAME
+#elif defined(HAVE_SYSCTLBYNAME)
 static int numcpu;
 #endif /* HAVE_SYSCTLBYNAME */
 
@@ -71,18 +104,35 @@ static char *cpu_filename = "cpu-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:user:COUNTER:25:0:U",
-       "DS:nice:COUNTER:25:0:U",
-       "DS:syst:COUNTER:25:0:U",
-       "DS:idle:COUNTER:25:0:U",
-       "DS:wait:COUNTER:25:0:U",
+       "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:nice:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:idle:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wait:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num = 5;
 
 static void cpu_init (void)
 {
-#ifdef HAVE_LIBKSTAT
+#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
+       kern_return_t status;
+
+       port_host = mach_host_self ();
+
+       /* FIXME: Free `cpu_list' if it's not NULL */
+       if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
+       {
+               syslog (LOG_ERR, "cpu-plugin: host_processors returned %i\n", (int) status);
+               cpu_list_len = 0;
+               return;
+       }
+
+       DBG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
+       syslog (LOG_INFO, "cpu-plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
+/* #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(HAVE_LIBKSTAT)
        kstat_t *ksp_chain;
 
        numcpu = 0;
@@ -150,8 +200,76 @@ static void cpu_submit (int cpu_num, unsigned long long user,
 
 static void cpu_read (void)
 {
-#ifdef KERNEL_LINUX
-#define BUFSIZE 1024
+#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
+       int cpu;
+
+       kern_return_t status;
+       
+#if PROCESSOR_CPU_LOAD_INFO
+       processor_cpu_load_info_data_t cpu_info;
+       mach_msg_type_number_t         cpu_info_len;
+#endif
+#if PROCESSOR_TEMPERATURE
+       processor_info_data_t          cpu_temp;
+       mach_msg_type_number_t         cpu_temp_len;
+#endif
+
+       host_t cpu_host;
+
+       for (cpu = 0; cpu < cpu_list_len; cpu++)
+       {
+#if PROCESSOR_CPU_LOAD_INFO
+               cpu_host = 0;
+               cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
+
+               if ((status = processor_info (cpu_list[cpu],
+                                               PROCESSOR_CPU_LOAD_INFO, &cpu_host,
+                                               (processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "processor_info failed with status %i\n", (int) status);
+                       continue;
+               }
+
+               if (cpu_info_len < CPU_STATE_MAX)
+               {
+                       syslog (LOG_ERR, "processor_info returned only %i elements..\n", cpu_info_len);
+                       continue;
+               }
+
+               cpu_submit (cpu, cpu_info.cpu_ticks[CPU_STATE_USER],
+                               cpu_info.cpu_ticks[CPU_STATE_NICE],
+                               cpu_info.cpu_ticks[CPU_STATE_SYSTEM],
+                               cpu_info.cpu_ticks[CPU_STATE_IDLE],
+                               0ULL);
+#endif /* PROCESSOR_CPU_LOAD_INFO */
+#if PROCESSOR_TEMPERATURE
+               cpu_temp_len = PROCESSOR_INFO_MAX;
+
+               status = processor_info (cpu_list[cpu],
+                               PROCESSOR_TEMPERATURE,
+                               &cpu_host,
+                               cpu_temp, &cpu_temp_len);
+               if (status != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "processor_info failed: %s",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               if (cpu_temp_len != 1)
+               {
+                       DBG ("processor_info (PROCESSOR_TEMPERATURE) returned %i elements..?",
+                                       (int) cpu_temp_len);
+                       continue;
+               }
+
+               DBG ("cpu_temp = %i", (int) cpu_temp);
+#endif /* PROCESSOR_TEMPERATURE */
+       }
+/* #endif PROCESSOR_CPU_LOAD_INFO */
+
+#elif defined(KERNEL_LINUX)
+# define BUFSIZE 1024
        int cpu;
        unsigned long long user, nice, syst, idle;
        unsigned long long wait, intr, sitr; /* sitr == soft interrupt */
diff --git a/src/cpu.h b/src/cpu.h
deleted file mode 100644 (file)
index fa5a710..0000000
--- a/src/cpu.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * collectd - src/cpu.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#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 */
index 22877b4..797bee7 100644 (file)
@@ -36,7 +36,7 @@ static char *cpufreq_file = "cpufreq-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:value:GAUGE:25:0:U",
+       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num = 1;
diff --git a/src/cpufreq.h b/src/cpufreq.h
deleted file mode 100644 (file)
index 9c0d41e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/cpufreq.c
- * Copyright (C) 2005  Peter Holik
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Peter Holik <peter at holik.at>
- **/
-
-#ifndef CPUFREQ_H
-#define CPUFREQ_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_CPUFREQ
-#if defined(KERNEL_LINUX)
-#define COLLECT_CPUFREQ 1
-#else
-#define COLLECT_CPUFREQ 0
-#endif
-#endif /* !defined(COLLECT_CPUFREQ) */
-
-#endif /* CPUFREQ_H */
index 6b7df31..51dff31 100644 (file)
--- a/src/df.c
+++ b/src/df.c
@@ -51,8 +51,8 @@ static char *filename_template = "df-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:used:GAUGE:25:0:U",
-       "DS:free:GAUGE:25:0:U",
+       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num = 2;
@@ -110,10 +110,7 @@ static void df_read (void)
 
        mnt_list = NULL;
        if (cu_mount_getlist (&mnt_list) == NULL)
-       {
-               syslog (LOG_WARNING, "cu_mount_getlist returned `NULL'");
                return;
-       }
 
        for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
        {
index ea49717..992c2d2 100644 (file)
@@ -38,24 +38,24 @@ static char *part_filename_template = "partition-%s.rrd";
 /* 104857600 == 100 MB */
 static char *disk_ds_def[] =
 {
-       "DS:rcount:COUNTER:25:0:U",
-       "DS:rmerged:COUNTER:25:0:U",
-       "DS:rbytes:COUNTER:25:0:104857600",
-       "DS:rtime:COUNTER:25:0:U",
-       "DS:wcount:COUNTER:25:0:U",
-       "DS:wmerged:COUNTER:25:0:U",
-       "DS:wbytes:COUNTER:25:0:104857600",
-       "DS:wtime:COUNTER:25:0:U",
+       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
+       "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
+       "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int disk_ds_num = 8;
 
 static char *part_ds_def[] =
 {
-       "DS:rcount:COUNTER:25:0:U",
-       "DS:rbytes:COUNTER:25:0:104857600",
-       "DS:wcount:COUNTER:25:0:U",
-       "DS:wbytes:COUNTER:25:0:104857600",
+       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
+       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
        NULL
 };
 static int part_ds_num = 4;
diff --git a/src/disk.h b/src/disk.h
deleted file mode 100644 (file)
index f946963..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/disk.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef DISKSTATS_H
-#define DISKSTATS_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_DISK
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT)
-#define COLLECT_DISK 1
-#else
-#define COLLECT_DISK 0
-#endif
-#endif /* !defined(COLLECT_DISK) */
-
-#endif /* DISKSTATS_H */
index bfb2621..d3772b8 100644 (file)
@@ -55,7 +55,7 @@ static char *filename_format = "hddtemp-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:value:GAUGE:25:U:U",
+       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
        NULL
 };
 static int ds_num = 1;
@@ -233,7 +233,7 @@ static int hddtemp_config (char *key, char *value)
  * operating-systems, it's not done at all. */
 static void hddtemp_init (void)
 {
-#if defined(KERNEL_LINUX)
+#if KERNEL_LINUX
        FILE *fh;
        char buf[BUFFER_SIZE];
        int buflen;
diff --git a/src/hddtemp.h b/src/hddtemp.h
deleted file mode 100644 (file)
index aaf0191..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * collectd - src/hddtemp.c
- * Copyright (C) 2005  Vincent StehlĂ©
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Vincent StehlĂ© <vincent.stehle at free.fr>
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef HDDTEMP_H
-#define HDDTEMP_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_HDDTEMP
-#define COLLECT_HDDTEMP 1
-#endif
-
-#endif /* HDDTEMP_H */
index 9ad4d66..14bd3ed 100644 (file)
@@ -1,5 +1,9 @@
 AUTOMAKE_OPTIONS = foreign no-dependencies
 
+if COMPILER_IS_GCC
+AM_CFLAGS = -Wall -Werror
+endif
+
 noinst_LTLIBRARIES = liboping.la
 
 #liboping_la_CFLAGS = 
index b57f8e2..43d5fd5 100644 (file)
 /*
  * private (static) functions
  */
+static int ping_timeval_add (struct timeval *tv1, struct timeval *tv2,
+               struct timeval *res)
+{
+       res->tv_sec  = tv1->tv_sec  + tv2->tv_sec;
+       res->tv_usec = tv1->tv_usec + tv2->tv_usec;
+
+       while (res->tv_usec > 1000000)
+       {
+               res->tv_usec -= 1000000;
+               res->tv_sec++;
+       }
+
+       return (0);
+}
+
 static int ping_timeval_sub (struct timeval *tv1, struct timeval *tv2,
                struct timeval *res)
 {
@@ -350,12 +365,13 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now)
        return (0);
 }
 
-static int ping_receive_all (pinghost_t *ph)
+static int ping_receive_all (pingobj_t *obj)
 {
        fd_set readfds;
        int num_readfds;
        int max_readfds;
 
+       pinghost_t *ph;
        pinghost_t *ptr;
 
        struct timeval endtime;
@@ -365,14 +381,24 @@ static int ping_receive_all (pinghost_t *ph)
 
        int ret;
 
+       ph = obj->head;
        ret = 0;
 
        for (ptr = ph; ptr != NULL; ptr = ptr->next)
                ptr->latency = -1.0;
 
-       if (gettimeofday (&endtime, NULL) == -1)
+       if (gettimeofday (&nowtime, NULL) == -1)
                return (-1);
-       endtime.tv_sec += 1;
+
+       /* Set up timeout */
+       timeout.tv_sec = (time_t) obj->timeout;
+       timeout.tv_usec = (suseconds_t) (1000000 * (obj->timeout - ((double) timeout.tv_sec)));
+
+       dprintf ("Set timeout to %i.%06i seconds\n",
+                       (int) timeout.tv_sec,
+                       (int) timeout.tv_usec);
+
+       ping_timeval_add (&nowtime, &timeout, &endtime);
 
        while (1)
        {
@@ -598,6 +624,25 @@ static int ping_send_all (pinghost_t *ph)
        return (0);
 }
 
+/*
+ * Set the TTL of a socket protocol independently.
+ */
+static int ping_set_ttl (pinghost_t *ph, int ttl)
+{
+       int ret = -2;
+
+       if (ph->addrfamily == AF_INET)
+       {
+               ret = setsockopt (ph->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl));
+       }
+       else if (ph->addrfamily == AF_INET6)
+       {
+               ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl));
+       }
+
+       return (ret);
+}
+
 static int ping_get_ident (void)
 {
        int fd;
@@ -751,7 +796,7 @@ int ping_send (pingobj_t *obj)
        if (ping_send_all (obj->head) < 0)
                return (-1);
 
-       if ((ret = ping_receive_all (obj->head)) < 0)
+       if ((ret = ping_receive_all (obj)) < 0)
                return (-2);
 
        return (ret);
@@ -791,7 +836,7 @@ int ping_host_add (pingobj_t *obj, const char *host)
 #ifdef AI_ADDRCONFIG
        ai_hints.ai_flags    |= AI_ADDRCONFIG;
 #endif
-       ai_hints.ai_family    = PF_UNSPEC;
+       ai_hints.ai_family    = obj->addrfamily;
        ai_hints.ai_socktype  = SOCK_RAW;
 
        if ((ph = ping_alloc ()) == NULL)
@@ -885,6 +930,8 @@ int ping_host_add (pingobj_t *obj, const char *host)
        ph->next  = obj->head;
        obj->head = ph;
 
+       ping_set_ttl (ph, obj->ttl);
+
        return (0);
 }
 
index 913eb53..fbe6c4d 100644 (file)
@@ -48,9 +48,9 @@ static char *load_file = "load.rrd";
 
 static char *ds_def[] =
 {
-       "DS:shortterm:GAUGE:25:0:100",
-       "DS:midterm:GAUGE:25:0:100",
-       "DS:longterm:GAUGE:25:0:100",
+       "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
        NULL
 };
 static int ds_num = 3;
diff --git a/src/load.h b/src/load.h
deleted file mode 100644 (file)
index 651d1d6..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/load.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef LOAD_H
-#define LOAD_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_LOAD
-#if defined(HAVE_GETLOADAVG) || defined(KERNEL_LINUX) || defined(HAVE_LIBSTATGRAB)
-#define COLLECT_LOAD 1
-#else
-#define COLLECT_LOAD 0
-#endif
-#endif /* !defined(COLLECT_LOAD) */
-
-#endif /* LOAD_H */
index 3ab19e6..77a6dac 100644 (file)
 #include "common.h"
 #include "plugin.h"
 
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT)
+#ifdef HAVE_MACH_KERN_RETURN_H
+# include <mach/kern_return.h>
+#endif
+#ifdef HAVE_MACH_MACH_INIT_H
+# include <mach/mach_init.h>
+#endif
+#ifdef HAVE_MACH_MACH_HOST_H
+# include <mach/mach_host.h>
+#endif
+#ifdef HAVE_MACH_HOST_PRIV_H
+# include <mach/host_priv.h>
+#endif
+#ifdef MACH_VM_STATISTICS_H
+# include <mach/vm_statistics.h>
+#endif
+
+#if defined (HOST_VM_INFO) || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT)
 # define MEMORY_HAVE_READ 1
 #else
 # define MEMORY_HAVE_READ 0
@@ -37,22 +53,41 @@ static char *memory_file = "memory.rrd";
 /* 9223372036854775807 == LLONG_MAX */
 static char *ds_def[] =
 {
-       "DS:used:GAUGE:25:0:9223372036854775807",
-       "DS:free:GAUGE:25:0:9223372036854775807",
-       "DS:buffers:GAUGE:25:0:9223372036854775807",
-       "DS:cached:GAUGE:25:0:9223372036854775807",
+       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:buffers:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
        NULL
 };
 static int ds_num = 4;
 
-#ifdef HAVE_LIBKSTAT
+/* vm_statistics_data_t */
+#if defined(HOST_VM_INFO)
+static mach_port_t port_host;
+static vm_size_t pagesize;
+/* #endif HOST_VM_INFO */
+
+#elif defined(KERNEL_LINUX)
+/* no global variables */
+/* #endif KERNEL_LINUX */
+
+#elif defined(HAVE_LIBKSTAT)
 static int pagesize;
 static kstat_t *ksp;
 #endif /* HAVE_LIBKSTAT */
 
 static void memory_init (void)
 {
-#ifdef HAVE_LIBKSTAT
+#if defined(HOST_VM_INFO)
+       port_host = mach_host_self ();
+       host_page_size (port_host, &pagesize);
+/* #endif HOST_VM_INFO */
+
+#elif defined(KERNEL_LINUX)
+/* no init stuff */
+/* #endif KERNEL_LINUX */
+
+#elif defined(HAVE_LIBKSTAT)
        /* getpagesize(3C) tells me this does not fail.. */
        pagesize = getpagesize ();
        if (get_kstat (&ksp, "unix", 0, "system_pages"))
@@ -85,7 +120,57 @@ static void memory_submit (long long mem_used, long long mem_buffered,
 
 static void memory_read (void)
 {
-#ifdef KERNEL_LINUX
+#if defined(HOST_VM_INFO)
+       kern_return_t status;
+       vm_statistics_data_t   vm_data;
+       mach_msg_type_number_t vm_data_len;
+
+       long long wired;
+       long long active;
+       long long inactive;
+       long long free;
+
+       if (!port_host || !pagesize)
+               return;
+
+       vm_data_len = sizeof (vm_data) / sizeof (natural_t);
+       if ((status = host_statistics (port_host, HOST_VM_INFO,
+                                       (host_info_t) &vm_data,
+                                       &vm_data_len)) != KERN_SUCCESS)
+       {
+               syslog (LOG_ERR, "memory-plugin: host_statistics failed and returned the value %i", (int) status);
+               return;
+       }
+
+       /*
+        * From <http://docs.info.apple.com/article.html?artnum=107918>:
+        *
+        * Wired memory
+        *   This information can't be cached to disk, so it must stay in RAM.
+        *   The amount depends on what applications you are using.
+        *
+        * Active memory
+        *   This information is currently in RAM and actively being used.
+        *
+        * Inactive memory
+        *   This information is no longer being used and has been cached to
+        *   disk, but it will remain in RAM until another application needs
+        *   the space. Leaving this information in RAM is to your advantage if
+        *   you (or a client of your computer) come back to it later.
+        *
+        * Free memory
+        *   This memory is not being used.
+        */
+
+       wired    = vm_data.wire_count     * pagesize;
+       active   = vm_data.active_count   * pagesize;
+       inactive = vm_data.inactive_count * pagesize;
+       free     = vm_data.free_count     * pagesize;
+
+       memory_submit (wired + active, -1, inactive, free);
+/* #endif HOST_VM_INFO */
+
+#elif defined(KERNEL_LINUX)
        FILE *fh;
        char buffer[1024];
        
diff --git a/src/memory.h b/src/memory.h
deleted file mode 100644 (file)
index c457110..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/memory.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef MEMINFO_H
-#define MEMINFO_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_MEMORY
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
-#define COLLECT_MEMORY 1
-#else
-#define COLLECT_MEMORY 0
-#endif
-#endif /* !defined(COLLECT_MEMORY) */
-
-#endif /* MEMINFO_H */
index 4342dea..822c6cc 100644 (file)
@@ -60,43 +60,43 @@ static char *traffic_file  = "traffic-mysql.rrd";
 
 static char *commands_ds_def[] =
 {
-       "DS:value:COUNTER:25:0:U",
+       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int commands_ds_num = 1;
 
 static char *handler_ds_def[] =
 {
-       "DS:value:COUNTER:25:0:U",
+       "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int handler_ds_num = 1;
 
 static char *qcache_ds_def[] =
 {
-       "DS:hits:COUNTER:25:0:U",
-       "DS:inserts:COUNTER:25:0:U",
-       "DS:not_cached:COUNTER:25:0:U",
-       "DS:lowmem_prunes:COUNTER:25:0:U",
-       "DS:queries_in_cache:GAUGE:25:0:U",
+       "DS:hits:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:inserts:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:not_cached:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:lowmem_prunes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:queries_in_cache:GAUGE:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int qcache_ds_num = 5;
 
 static char *threads_ds_def[] =
 {
-       "DS:running:GAUGE:25:0:U",
-       "DS:connected:GAUGE:25:0:U",
-       "DS:cached:GAUGE:25:0:U",
-       "DS:created:COUNTER:25:0:U",
+       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "DS:connected:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "DS:created:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int threads_ds_num = 4;
 
 static char *traffic_ds_def[] =
 {
-       "DS:incoming:COUNTER:25:0:U",
-       "DS:outgoing:COUNTER:25:0:U",
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int traffic_ds_num = 2;
index f6bb6e8..a2cb6f5 100644 (file)
@@ -512,8 +512,6 @@ int network_send (char *type, char *inst, char *value)
                if (se->mode != operating_mode)
                        continue;
 
-               DBG ("fd = %i", se->fd);
-
                while (1)
                {
                        status = sendto (se->fd, buf, buflen, 0,
index 1592c91..3c7b8cf 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
@@ -83,52 +83,52 @@ Number      Procedures  Procedures
 
 static char *nfs2_procedures_ds_def[] =
 {
-       "DS:null:COUNTER:25:0:U",
-       "DS:getattr:COUNTER:25:0:U",
-       "DS:setattr:COUNTER:25:0:U",
-       "DS:root:COUNTER:25:0:U",
-       "DS:lookup:COUNTER:25:0:U",
-       "DS:readlink:COUNTER:25:0:U",
-       "DS:read:COUNTER:25:0:U",
-       "DS:wrcache:COUNTER:25:0:U",
-       "DS:write:COUNTER:25:0:U",
-       "DS:create:COUNTER:25:0:U",
-       "DS:remove:COUNTER:25:0:U",
-       "DS:rename:COUNTER:25:0:U",
-       "DS:link:COUNTER:25:0:U",
-       "DS:symlink:COUNTER:25:0:U",
-       "DS:mkdir:COUNTER:25:0:U",
-       "DS:rmdir:COUNTER:25:0:U",
-       "DS:readdir:COUNTER:25:0:U",
-       "DS:fsstat:COUNTER:25:0:U",
+       "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int nfs2_procedures_ds_num = 18;
 
 static char *nfs3_procedures_ds_def[] =
 {
-       "DS:null:COUNTER:25:0:U",
-       "DS:getattr:COUNTER:25:0:U",
-       "DS:setattr:COUNTER:25:0:U",
-       "DS:lookup:COUNTER:25:0:U",
-       "DS:access:COUNTER:25:0:U",
-       "DS:readlink:COUNTER:25:0:U",
-       "DS:read:COUNTER:25:0:U",
-       "DS:write:COUNTER:25:0:U",
-       "DS:create:COUNTER:25:0:U",
-       "DS:mkdir:COUNTER:25:0:U",
-       "DS:symlink:COUNTER:25:0:U",
-       "DS:mknod:COUNTER:25:0:U",
-       "DS:remove:COUNTER:25:0:U",
-       "DS:rmdir:COUNTER:25:0:U",
-       "DS:rename:COUNTER:25:0:U",
-       "DS:link:COUNTER:25:0:U",
-       "DS:readdir:COUNTER:25:0:U",
-       "DS:readdirplus:COUNTER:25:0:U",
-       "DS:fsstat:COUNTER:25:0:U",
-       "DS:fsinfo:COUNTER:25:0:U",
-       "DS:pathconf:COUNTER:25:0:U",
-       "DS:commit:COUNTER:25:0:U",
+       "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int nfs3_procedures_ds_num = 22;
diff --git a/src/nfs.h b/src/nfs.h
deleted file mode 100644 (file)
index ae752be..0000000
--- a/src/nfs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/nfs.h
- * Copyright (C) 2005  Jason Pepas
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Jason Pepas <cell at ices.utexas.edu>
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef NFS_H
-#define NFS_H
-
-#include "collectd.h"
-
-#ifndef COLLECT_NFS
-#if defined(KERNEL_LINUX)
-#define COLLECT_NFS 1
-#else
-#define COLLECT_NFS 0
-#endif
-#endif /* !defined(COLLECT_NFS) */
-
-#endif /* NFS_H */
index fb2f8c1..6966170 100644 (file)
@@ -37,7 +37,7 @@ static char *file_template = "ping-%s.rrd";
 
 static char *ds_def[] = 
 {
-       "DS:ping:GAUGE:25:0:65535",
+       "DS:ping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
        NULL
 };
 static int ds_num = 1;
@@ -45,9 +45,10 @@ static int ds_num = 1;
 static char *config_keys[] =
 {
        "Host",
+       "TTL",
        NULL
 };
-static int config_keys_num = 1;
+static int config_keys_num = 2;
 
 static void ping_init (void)
 {
@@ -56,23 +57,34 @@ static void ping_init (void)
 
 static int ping_config (char *key, char *value)
 {
-       if (strcasecmp (key, "host"))
-       {
-               return (-1);
-       }
-
        if (pingobj == NULL)
        {
                if ((pingobj = ping_construct ()) == NULL)
                {
                        syslog (LOG_ERR, "ping: `ping_construct' failed.\n");
-                       return (-1);
+                       return (1);
                }
        }
 
-       if (ping_host_add (pingobj, value) < 0)
+       if (strcasecmp (key, "host") == 0)
+       {
+               if (ping_host_add (pingobj, value) < 0)
+               {
+                       syslog (LOG_WARNING, "ping: `ping_host_add' failed.");
+                       return (1);
+               }
+       }
+       else if (strcasecmp (key, "ttl") == 0)
+       {
+               int ttl = atoi (value);
+               if (ping_setopt (pingobj, PING_DEF_TIMEOUT, (void *) &ttl))
+               {
+                       syslog (LOG_WARNING, "ping: liboping did not accept the TTL value %i", ttl);
+                       return (1);
+               }
+       }
+       else
        {
-               syslog (LOG_ERR, "ping: `ping_host_add' failed.\n");
                return (-1);
        }
 
diff --git a/src/ping.h b/src/ping.h
deleted file mode 100644 (file)
index c5f26c4..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * collectd - src/ping.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef COLLECTD_PING_H
-#define COLLECTD_PING_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_PING
-#if defined(HAVE_NETINET_IN_H)
-#define COLLECT_PING 1
-#else
-#define COLLECT_PING 0
-#endif /* defined(HAVE_NETINET_IN_H) */
-#endif /* !defined(COLLECT_PING) */
-
-#if COLLECT_PING
-
-#define MAX_PINGHOSTS 32
-
-#endif /* COLLECT_PING */
-#endif
index 54f57af..e991c78 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "plugin.h"
 #include "network.h"
+#include "utils_debug.h"
 
 typedef struct plugin
 {
@@ -114,11 +115,19 @@ int plugin_load_file (char *file)
        lt_dlhandle dlh;
        void (*reg_handle) (void);
 
+       DBG ("file = %s", file);
+
        lt_dlinit ();
        lt_dlerror (); /* clear errors */
 
        if ((dlh = lt_dlopen (file)) == NULL)
+       {
+               const char *error = lt_dlerror ();
+
+               syslog (LOG_ERR, "lt_dlopen failed: %s", error);
+               DBG ("lt_dlopen failed: %s", error);
                return (1);
+       }
 
        if ((reg_handle = lt_dlsym (dlh, "module_register")) == NULL)
        {
@@ -145,6 +154,8 @@ int plugin_load (const char *type)
        struct stat    statbuf;
        struct dirent *de;
 
+       DBG ("type = %s", type);
+
        dir = plugin_get_dir ();
        ret = 1;
 
index 3a73189..fae1c2d 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/processes.c
  * Copyright (C) 2005  Lyonel Vincent
+ * Copyright (C) 2006  Florian Forster (Mach code)
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
 #include "collectd.h"
 #include "common.h"
 #include "plugin.h"
+#include "utils_debug.h"
+
+/* Include header files for the mach system, if they exist.. */
+#if HAVE_MACH_MACH_INIT_H
+#  include <mach/mach_init.h>
+#endif
+#if HAVE_MACH_HOST_PRIV_H
+#  include <mach/host_priv.h>
+#endif
+#if HAVE_MACH_MACH_ERROR_H
+#  include <mach/mach_error.h>
+#endif
+#if HAVE_MACH_MACH_HOST_H
+#  include <mach/mach_host.h>
+#endif
+#if HAVE_MACH_MACH_PORT_H
+#  include <mach/mach_port.h>
+#endif
+#if HAVE_MACH_MACH_TYPES_H
+#  include <mach/mach_types.h>
+#endif
+#if HAVE_MACH_MESSAGE_H
+#  include <mach/message.h>
+#endif
+#if HAVE_MACH_PROCESSOR_SET_H
+#  include <mach/processor_set.h>
+#endif
+#if HAVE_MACH_TASK_H
+#  include <mach/task.h>
+#endif
+#if HAVE_MACH_THREAD_ACT_H
+#  include <mach/thread_act.h>
+#endif
+#if HAVE_MACH_VM_REGION_H
+#  include <mach/vm_region.h>
+#endif
+#if HAVE_MACH_VM_MAP_H
+#  include <mach/vm_map.h>
+#endif
+#if HAVE_MACH_VM_PROT_H
+#  include <mach/vm_prot.h>
+#endif
 
 #define MODULE_NAME "processes"
 
-#ifdef KERNEL_LINUX
+#if HAVE_THREAD_INFO || KERNEL_LINUX
 # define PROCESSES_HAVE_READ 1
 #else
 # define PROCESSES_HAVE_READ 0
@@ -39,18 +82,62 @@ static char *ps_file = "processes.rrd";
 
 static char *ds_def[] =
 {
-       "DS:running:GAUGE:25:0:65535",
-       "DS:sleeping:GAUGE:25:0:65535",
-       "DS:zombies:GAUGE:25:0:65535",
-       "DS:stopped:GAUGE:25:0:65535",
-       "DS:paging:GAUGE:25:0:65535",
-       "DS:blocked:GAUGE:25:0:65535",
+       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
        NULL
 };
 static int ds_num = 6;
 
+#if HAVE_THREAD_INFO
+static mach_port_t port_host_self;
+static mach_port_t port_task_self;
+
+static processor_set_name_array_t pset_list;
+static mach_msg_type_number_t     pset_list_len;
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+/* No global variables */
+#endif /* KERNEL_LINUX */
+
 static void ps_init (void)
 {
+#if HAVE_THREAD_INFO
+       kern_return_t status;
+
+       port_host_self = mach_host_self ();
+       port_task_self = mach_task_self ();
+
+       if (pset_list != NULL)
+       {
+               vm_deallocate (port_task_self,
+                               (vm_address_t) pset_list,
+                               pset_list_len * sizeof (processor_set_t));
+               pset_list = NULL;
+               pset_list_len = 0;
+       }
+
+       if ((status = host_processor_sets (port_host_self,
+                                       &pset_list,
+                                       &pset_list_len)) != KERN_SUCCESS)
+       {
+               syslog (LOG_ERR, "host_processor_sets failed: %s\n",
+                               mach_error_string (status));
+               pset_list = NULL;
+               pset_list_len = 0;
+               return;
+       }
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+       /* No init */
+#endif /* KERNEL_LINUX */
+
+       return;
 }
 
 static void ps_write (char *host, char *inst, char *val)
@@ -59,16 +146,16 @@ static void ps_write (char *host, char *inst, char *val)
 }
 
 #if PROCESSES_HAVE_READ
-static void ps_submit (unsigned int running,
-               unsigned int sleeping,
-               unsigned int zombies,
-               unsigned int stopped,
-               unsigned int paging,
-               unsigned int blocked)
+static void ps_submit (int running,
+               int sleeping,
+               int zombies,
+               int stopped,
+               int paging,
+               int blocked)
 {
        char buf[BUFSIZE];
 
-       if (snprintf (buf, BUFSIZE, "%u:%u:%u:%u:%u:%u:%u",
+       if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i",
                                (unsigned int) curtime,
                                running, sleeping, zombies, stopped, paging,
                                blocked) >= BUFSIZE)
@@ -79,8 +166,182 @@ static void ps_submit (unsigned int running,
 
 static void ps_read (void)
 {
-#ifdef KERNEL_LINUX
-       unsigned int running, sleeping, zombies, stopped, paging, blocked;
+#if HAVE_THREAD_INFO
+       kern_return_t            status;
+
+       int                      pset;
+       processor_set_t          port_pset_priv;
+
+       int                      task;
+       task_array_t             task_list;
+       mach_msg_type_number_t   task_list_len;
+
+       int                      thread;
+       thread_act_array_t       thread_list;
+       mach_msg_type_number_t   thread_list_len;
+       thread_basic_info_data_t thread_data;
+       mach_msg_type_number_t   thread_data_len;
+
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int blocked  = 0;
+
+       /*
+        * The Mach-concept is a little different from the traditional UNIX
+        * concept: All the work is done in threads. Threads are contained in
+        * `tasks'. Therefore, `task status' doesn't make much sense, since
+        * it's actually a `thread status'.
+        * Tasks are assigned to sets of processors, so that's where you go to
+        * get a list.
+        */
+       for (pset = 0; pset < pset_list_len; pset++)
+       {
+               if ((status = host_processor_set_priv (port_host_self,
+                                               pset_list[pset],
+                                               &port_pset_priv)) != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "host_processor_set_priv failed: %s\n",
+                                       mach_error_string (status));
+                       continue;
+               }
+
+               if ((status = processor_set_tasks (port_pset_priv,
+                                               &task_list,
+                                               &task_list_len)) != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "processor_set_tasks failed: %s\n",
+                                       mach_error_string (status));
+                       mach_port_deallocate (port_task_self, port_pset_priv);
+                       continue;
+               }
+
+               for (task = 0; task < task_list_len; task++)
+               {
+                       status = task_threads (task_list[task], &thread_list,
+                                       &thread_list_len);
+                       if (status != KERN_SUCCESS)
+                       {
+                               /* Apple's `top' treats this case a zombie. It
+                                * makes sense to some extend: A `zombie'
+                                * thread is nonsense, since the task/process
+                                * is dead. */
+                               zombies++;
+                               DBG ("task_threads failed: %s",
+                                               mach_error_string (status));
+                               if (task_list[task] != port_task_self)
+                                       mach_port_deallocate (port_task_self,
+                                                       task_list[task]);
+                               continue; /* with next task_list */
+                       }
+
+                       for (thread = 0; thread < thread_list_len; thread++)
+                       {
+                               thread_data_len = THREAD_BASIC_INFO_COUNT;
+                               status = thread_info (thread_list[thread],
+                                               THREAD_BASIC_INFO,
+                                               (thread_info_t) &thread_data,
+                                               &thread_data_len);
+                               if (status != KERN_SUCCESS)
+                               {
+                                       syslog (LOG_ERR, "thread_info failed: %s\n",
+                                                       mach_error_string (status));
+                                       if (task_list[task] != port_task_self)
+                                               mach_port_deallocate (port_task_self,
+                                                               thread_list[thread]);
+                                       continue; /* with next thread_list */
+                               }
+
+                               switch (thread_data.run_state)
+                               {
+                                       case TH_STATE_RUNNING:
+                                               running++;
+                                               break;
+                                       case TH_STATE_STOPPED:
+                                       /* What exactly is `halted'? */
+                                       case TH_STATE_HALTED:
+                                               stopped++;
+                                               break;
+                                       case TH_STATE_WAITING:
+                                               sleeping++;
+                                               break;
+                                       case TH_STATE_UNINTERRUPTIBLE:
+                                               blocked++;
+                                               break;
+                                       /* There is no `zombie' case here,
+                                        * since there are no zombie-threads.
+                                        * There's only zombie tasks, which are
+                                        * handled above. */
+                                       default:
+                                               syslog (LOG_WARNING,
+                                                               "Unknown thread status: %s",
+                                                               thread_data.run_state);
+                                               break;
+                               } /* switch (thread_data.run_state) */
+
+                               if (task_list[task] != port_task_self)
+                               {
+                                       status = mach_port_deallocate (port_task_self,
+                                                       thread_list[thread]);
+                                       if (status != KERN_SUCCESS)
+                                               syslog (LOG_ERR, "mach_port_deallocate failed: %s",
+                                                               mach_error_string (status));
+                               }
+                       } /* for (thread_list) */
+
+                       if ((status = vm_deallocate (port_task_self,
+                                                       (vm_address_t) thread_list,
+                                                       thread_list_len * sizeof (thread_act_t)))
+                                       != KERN_SUCCESS)
+                       {
+                               syslog (LOG_ERR, "vm_deallocate failed: %s",
+                                               mach_error_string (status));
+                       }
+                       thread_list = NULL;
+                       thread_list_len = 0;
+
+                       /* Only deallocate the task port, if it isn't our own.
+                        * Don't know what would happen in that case, but this
+                        * is what Apple's top does.. ;) */
+                       if (task_list[task] != port_task_self)
+                       {
+                               status = mach_port_deallocate (port_task_self,
+                                               task_list[task]);
+                               if (status != KERN_SUCCESS)
+                                       syslog (LOG_ERR, "mach_port_deallocate failed: %s",
+                                                       mach_error_string (status));
+                       }
+               } /* for (task_list) */
+
+               if ((status = vm_deallocate (port_task_self,
+                               (vm_address_t) task_list,
+                               task_list_len * sizeof (task_t))) != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "vm_deallocate failed: %s",
+                                       mach_error_string (status));
+               }
+               task_list = NULL;
+               task_list_len = 0;
+
+               if ((status = mach_port_deallocate (port_task_self, port_pset_priv))
+                               != KERN_SUCCESS)
+               {
+                       syslog (LOG_ERR, "mach_port_deallocate failed: %s",
+                                       mach_error_string (status));
+               }
+       } /* for (pset_list) */
+
+       ps_submit (running, sleeping, zombies, stopped, -1, blocked);
+/* #endif HAVE_THREAD_INFO */
+
+#elif KERNEL_LINUX
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int paging   = 0;
+       int blocked  = 0;
 
        char buf[BUFSIZE];
        char filename[20]; /* need 17 bytes */
@@ -137,7 +398,7 @@ static void ps_read (void)
        closedir(proc);
 
        ps_submit (running, sleeping, zombies, stopped, paging, blocked);
-#endif /* defined(KERNEL_LINUX) */
+#endif /* KERNEL_LINUX */
 }
 #else
 # define ps_read NULL
diff --git a/src/processes.h b/src/processes.h
deleted file mode 100644 (file)
index db8446a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * collectd - src/processes.h
- * Copyright (C) 2005  Lyonel Vincent
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Lyonel Vincent <lyonel at ezix.org>
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef PROCESSES_H
-#define PROCESSES_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_PROCESSES
-#if defined(KERNEL_LINUX)
-#define COLLECT_PROCESSES 1
-#else
-#define COLLECT_PROCESSES 0
-#endif
-#endif /* !defined(COLLECT_PROCESSES) */
-
-#endif /* PROCESSES_H */
index 75981e8..05973ba 100644 (file)
@@ -44,7 +44,7 @@ static char *filename_format = "sensors-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:value:GAUGE:25:U:U",
+       "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
        NULL
 };
 static int ds_num = 1;
diff --git a/src/sensors.h b/src/sensors.h
deleted file mode 100644 (file)
index 9fb1767..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * collectd - src/sensors.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef SENSORS_H
-#define SENSORS_H
-
-#include "collectd.h"
-#include "common.h"
-
-/* Won't compile without header file */
-#ifndef HAVE_SENSORS_SENSORS_H
-#undef HAVE_LIBSENSORS
-#endif
-
-#ifndef COLLECT_SENSORS
-#ifdef HAVE_LIBSENSORS
-#define COLLECT_SENSORS 1
-#else
-#define COLLECT_SENSORS 0
-#endif
-#endif /* !defined(COLLECT_SENSORS) */
-
-#endif /* SENSORS_H */
index 31b6148..a95eb2d 100644 (file)
@@ -37,8 +37,8 @@ static char *serial_filename_template = "serial-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:incoming:COUNTER:25:0:U",
-       "DS:outgoing:COUNTER:25:0:U",
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num = 2;
diff --git a/src/serial.h b/src/serial.h
deleted file mode 100644 (file)
index 8337280..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * collectd - src/serial.h
- * Copyright (C) 2005  David Bacher
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   David Bacher <drbacher at gmail.com>
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef SERIAL_H
-#define SERIAL_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_SERIAL
-#if defined(KERNEL_LINUX)
-#define COLLECT_SERIAL 1
-#else
-#define COLLECT_SERIAL 0
-#endif
-#endif /* !defined(COLLECT_SERIAL) */
-
-#endif /* SERIAL_H */
-
-
-
-
index 8ffa453..a6a4e36 100644 (file)
@@ -44,10 +44,10 @@ static char *swap_file = "swap.rrd";
 /* 1099511627776 == 1TB ought to be enough for anyone ;) */
 static char *ds_def[] =
 {
-       "DS:used:GAUGE:25:0:1099511627776",
-       "DS:free:GAUGE:25:0:1099511627776",
-       "DS:cached:GAUGE:25:0:1099511627776",
-       "DS:resv:GAUGE:25:0:1099511627776",
+       "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
+       "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
+       "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
+       "DS:resv:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
        NULL
 };
 static int ds_num = 4;
diff --git a/src/swap.h b/src/swap.h
deleted file mode 100644 (file)
index dfe5d36..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/swap.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef SWAP_H
-#define SWAP_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_SWAP
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
-#define COLLECT_SWAP 1
-#else
-#define COLLECT_SWAP 0
-#endif
-#endif /* !defined(COLLECT_SWAP) */
-
-#endif /* SWAP_H */
index 4671ed4..f6aeb93 100644 (file)
@@ -37,14 +37,14 @@ static char *tape_filename_template = "tape-%s.rrd";
 /* 104857600 == 100 MB */
 static char *tape_ds_def[] =
 {
-       "DS:rcount:COUNTER:25:0:U",
-       "DS:rmerged:COUNTER:25:0:U",
-       "DS:rbytes:COUNTER:25:0:U",
-       "DS:rtime:COUNTER:25:0:U",
-       "DS:wcount:COUNTER:25:0:U",
-       "DS:wmerged:COUNTER:25:0:U",
-       "DS:wbytes:COUNTER:25:0:U",
-       "DS:wtime:COUNTER:25:0:U",
+       "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int tape_ds_num = 8;
diff --git a/src/tape.h b/src/tape.h
deleted file mode 100644 (file)
index acf03a3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/tape.h
- * Copyright (C) 2005  Scott Garrett
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Scott Garrett <sgarrett at technomancer.com>
- **/
-
-#ifndef TAPESTATS_H
-#define TAPESTATS_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_TAPE
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT)
-#define COLLECT_TAPE 1
-#else
-#define COLLECT_TAPE 0
-#endif
-#endif /* !defined(COLLECT_TAPE) */
-
-#endif /* TAPESTATS_H */
index f7a9f8f..b5e7887 100644 (file)
 #include "common.h"
 #include "plugin.h"
 
+#if HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#endif
+
+/* One cannot include both. This sucks. */
+#if HAVE_LINUX_IF_H
+#  include <linux/if.h>
+#elif HAVE_NET_IF_H
+#  include <net/if.h>
+#endif
+
+#if HAVE_LINUX_NETDEVICE_H
+#  include <linux/netdevice.h>
+#endif
+#if HAVE_IFADDRS_H
+#  include <ifaddrs.h>
+#endif
+
 #define MODULE_NAME "traffic"
 
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
+#if HAVE_GETIFADDRS || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
 # define TRAFFIC_HAVE_READ 1
 #else
 # define TRAFFIC_HAVE_READ 0
@@ -38,8 +59,8 @@ static char *traffic_filename_template = "traffic-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:incoming:COUNTER:25:0:U",
-       "DS:outgoing:COUNTER:25:0:U",
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
        NULL
 };
 static int ds_num = 2;
@@ -53,7 +74,15 @@ static int numif = 0;
 
 static void traffic_init (void)
 {
-#ifdef HAVE_LIBKSTAT
+#if HAVE_GETIFADDRS
+       /* nothing */
+/* #endif HAVE_GETIFADDRS */
+
+#elif KERNEL_LINUX
+       /* nothing */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_LIBKSTAT
        kstat_t *ksp_chain;
        unsigned long long val;
 
@@ -76,7 +105,13 @@ static void traffic_init (void)
                        continue;
                ksp[numif++] = ksp_chain;
        }
-#endif /* HAVE_LIBKSTAT */
+/* #endif HAVE_LIBKSTAT */
+
+#elif HAVE_LIBSTATG
+       /* nothing */
+#endif /* HAVE_LIBSTATG */
+
+       return;
 }
 
 static void traffic_write (char *host, char *inst, char *val)
@@ -108,7 +143,41 @@ static void traffic_submit (char *device,
 
 static void traffic_read (void)
 {
-#ifdef KERNEL_LINUX
+#if HAVE_GETIFADDRS
+       struct ifaddrs *if_list;
+       struct ifaddrs *if_ptr;
+
+#if HAVE_STRUCT_IF_DATA
+#  define IFA_DATA if_data
+#  define IFA_INCOMING ifi_ibytes
+#  define IFA_OUTGOING ifi_obytes
+#elif HAVE_STRUCT_NET_DEVICE_STATS
+#  define IFA_DATA net_device_stats
+#  define IFA_INCOMING rx_bytes
+#  define IFA_OUTGOING tx_bytes
+#else
+#  error "No suitable type for `struct ifaddrs->ifa_data' found."
+#endif
+
+       struct IFA_DATA *if_data;
+
+       if (getifaddrs (&if_list) != 0)
+               return;
+
+       for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
+       {
+               if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL)
+                       continue;
+
+               traffic_submit (if_ptr->ifa_name,
+                               if_data->IFA_INCOMING,
+                               if_data->IFA_OUTGOING);
+       }
+
+       freeifaddrs (if_list);
+/* #endif HAVE_GETIFADDRS */
+
+#elif KERNEL_LINUX
        FILE *fh;
        char buffer[1024];
        unsigned long long incoming, outgoing;
diff --git a/src/traffic.h b/src/traffic.h
deleted file mode 100644 (file)
index 3b95927..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- * collectd - src/traffic.h
- * Copyright (C) 2005  Florian octo Forster
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Florian octo Forster <octo at verplant.org>
- **/
-
-#ifndef TRAFFIC_H
-#define TRAFFIC_H
-
-#include "collectd.h"
-#include "common.h"
-
-#ifndef COLLECT_TRAFFIC
-#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB)
-#define COLLECT_TRAFFIC 1
-#else
-#define COLLECT_TRAFFIC 0
-#endif
-#endif /* !defined(COLLECT_TRAFFIC) */
-
-#endif /* TRAFFIC_H */
index 5fe1b71..4041a1c 100644 (file)
@@ -43,7 +43,7 @@
 static char *rrd_file = "users.rrd";
 static char *ds_def[] =
 {
-       "DS:users:GAUGE:25:0:65535",
+       "DS:users:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
        NULL
 };
 static int ds_num = 1;
diff --git a/src/users.h b/src/users.h
deleted file mode 100644 (file)
index c514094..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * collectd - src/users.h
- * Copyright (C) 2005  Sebastian Harl
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- *
- * Authors:
- *   Sebastian Harl <sh at tokkee.org>
- **/
-
-#if !COLLECTD_USERS_H
-#define COLLECTD_USERS_H 1
-
-void module_register(void);
-
-#endif /* !COLLECTD_USERS_H */
-
index 176040a..30a155f 100644 (file)
@@ -429,15 +429,21 @@ static cu_mount_t *cu_mount_getfsstat (void)
 
        /* Get the number of mounted file systems */
        if ((bufsize = getfsstat (NULL, 0, MNT_NOWAIT)) < 1)
+       {
+               DBG ("getfsstat failed: %s", strerror (errno));
                return (NULL);
+       }
 
-       if ((buf = (struct statfs *) malloc (bufsize * sizeof (struct statfs))) == NULL)
+       if ((buf = (struct statfs *) malloc (bufsize * sizeof (struct statfs)))
+                       == NULL)
                return (NULL);
        memset (buf, '\0', bufsize * sizeof (struct statfs));
 
-       /* FIXME: If `bufsize' in bytes or structures? */
-       if ((num = getfsstat (buf, bufsize, MNT_NOWAIT)) < 1)
+       /* The bufsize needs to be passed in bytes. Really. This is not in the
+        * manpage.. -octo */
+       if ((num = getfsstat (buf, bufsize * sizeof (struct statfs), MNT_NOWAIT)) < 1)
        {
+               DBG ("getfsstat failed: %s", strerror (errno));
                free (buf);
                return (NULL);
        }
diff --git a/src/vserver.c b/src/vserver.c
new file mode 100644 (file)
index 0000000..694b6d0
--- /dev/null
@@ -0,0 +1,528 @@
+/**
+ * collectd - src/vserver.c
+ * Copyright (C) 2006  Sebastian Harl
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define BUFSIZE 512
+
+#define MODULE_NAME "vserver"
+#define PROCDIR "/proc/virtual"
+
+#if defined(KERNEL_LINUX)
+# define VSERVER_HAVE_READ 1
+#else
+# define VSERVER_HAVE_READ 0
+#endif /* defined(KERNEL_LINUX) */
+
+static char *rrd_unix  = "vserver-%s/traffic-unix.rrd";
+static char *rrd_inet  = "vserver-%s/traffic-inet.rrd";
+static char *rrd_inet6 = "vserver-%s/traffic-inet6.rrd";
+static char *rrd_other = "vserver-%s/traffic-other.rrd";
+static char *rrd_unspec        = "vserver-%s/traffic-unspec.rrd";
+
+static char *rrd_thread        = "vserver-%s/vs_threads.rrd";
+
+static char *rrd_load  = "vserver-%s/load.rrd";
+
+static char *rrd_procs = "vserver-%s/vs_processes.rrd";
+static char *rrd_memory        = "vserver-%s/vs_memory.rrd";
+
+/* 9223372036854775807 == LLONG_MAX */
+/* bytes transferred */
+static char *ds_def_unix[] =
+{
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_unix = 3;
+
+static char *ds_def_inet[] =
+{
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_inet = 3;
+
+static char *ds_def_inet6[] =
+{
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_inet6 = 3;
+
+static char *ds_def_other[] =
+{
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_other = 3;
+
+static char *ds_def_unspec[] =
+{
+       "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_unspec = 3;
+
+static char *ds_def_threads[] =
+{
+       "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:uninterruptible:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       "DS:onhold:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       NULL
+};
+static int ds_num_threads = 4;
+
+static char *ds_def_load[] =
+{
+       "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+       NULL
+};
+static int ds_num_load = 3;
+
+static char *ds_def_procs[] =
+{
+       "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
+       NULL
+};
+static int ds_num_procs = 1;
+
+/* 9223372036854775807 == LLONG_MAX */
+/* bytes */
+static char *ds_def_memory[] =
+{
+       "DS:vm:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:vml:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:rss:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       "DS:anon:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
+       NULL
+};
+static int ds_num_memory = 4;
+
+static int pagesize = 0;
+
+static void vserver_init (void)
+{
+       /* XXX Should we check for getpagesize () in configure?
+        * What's the right thing to do, if there is no getpagesize ()? */
+       pagesize = getpagesize ();
+       return;
+} /* static void vserver_init(void) */
+
+static void vserver_unix_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_unix, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_unix, ds_num_unix);
+       return;
+} /* static void vserver_unix_write(char *host, char *inst, char *val) */
+
+static void vserver_inet_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_inet, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_inet, ds_num_inet);
+       return;
+} /* static void vserver_inet_write(char *host, char *inst, char *val) */
+
+static void vserver_inet6_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_inet6, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_inet6, ds_num_inet6);
+       return;
+} /* static void vserver_inet6_write(char *host, char *inst, char *val) */
+
+static void vserver_other_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_other, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_other, ds_num_other);
+       return;
+} /* static void vserver_other_write(char *host, char *inst, char *val) */
+
+static void vserver_unspec_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_unspec, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_unspec, ds_num_unspec);
+       return;
+} /* static void vserver_unspec_write(char *host, char *inst, char *val) */
+
+static void vserver_threads_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_thread, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_threads, ds_num_threads);
+       return;
+} /* static void vserver_threads_write(char *host, char *inst, char *val) */
+
+static void vserver_load_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_load, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_load, ds_num_load);
+       return;
+} /* static void vserver_load_write(char *host, char *inst, char *val) */
+
+static void vserver_procs_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_procs, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_procs, ds_num_procs);
+       return;
+} /* static void vserver_procs_write(char *host, char *inst, char *val) */
+
+static void vserver_memory_write (char *host, char *inst, char *val)
+{
+       int  len;
+       char filename[BUFSIZE];
+
+       len = snprintf (filename, BUFSIZE, rrd_memory, inst);
+       if ((len > 0) && (len < BUFSIZE))
+               rrd_update_file (host, filename, val, ds_def_memory, ds_num_memory);
+       return;
+} /* static void vserver_memory_write(char *host, char *inst, char *val) */
+
+#if VSERVER_HAVE_READ
+static void vserver_submit (char *inst, long long unix_in, long long unix_out, 
+               long long unix_failed, long long inet_in, long long inet_out, 
+               long long inet_failed, long long inet6_in, long long inet6_out, 
+               long long inet6_failed, long long other_in, long long other_out,
+               long long other_failed, long long unspec_in, long long unspec_out, 
+               long long unspec_failed, int t_total, int t_running, 
+               int t_uninterruptible, int t_onhold, double avg1, double avg5, 
+               double avg15, int p_total, long long vm, long long vml, long long rss, 
+               long long anon)
+{
+       int  len;
+       char buffer[BUFSIZE];
+
+       len = snprintf (buffer, BUFSIZE, 
+                       "N:%lld:%lld:%lld", unix_in, unix_out, unix_failed);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_unix", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, 
+                       "N:%lld:%lld:%lld", inet_in, inet_out, inet_failed);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_inet", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, 
+                       "N:%lld:%lld:%lld", inet6_in, inet6_out, inet6_failed);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_inet6", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, 
+                       "N:%lld:%lld:%lld", other_in, other_out, other_failed);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_other", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, 
+                       "N:%lld:%lld:%lld", unspec_in, unspec_out, unspec_failed);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_unspec", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, "N:%d:%d:%d:%d",
+                       t_total, t_running, t_uninterruptible, t_onhold);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_threads", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, "N:%.2f:%.2f:%.2f",
+                       avg1, avg5, avg15);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_load", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, "N:%d",
+                       p_total);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_procs", inst, buffer);
+
+
+       len = snprintf (buffer, BUFSIZE, "N:%lld:%lld:%lld:%lld",
+                       vm, vml, rss, anon);
+
+       if ((len > 0) && (len < BUFSIZE))
+               plugin_submit ("vserver_memory", inst, buffer);
+       return;
+} /* static void vserver_submit() */
+
+static inline long long __get_sock_bytes(const char *s)
+{
+       while (s[0] != '/')
+               ++s;
+
+       /* Remove '/' */
+       ++s;
+       return atoll(s);
+}
+
+static void vserver_read (void)
+{
+       DIR                     *proc;
+       struct dirent   *dent; /* 42 */
+
+       errno = 0;
+       if (NULL == (proc = opendir (PROCDIR))) {
+               syslog (LOG_ERR, "Cannot open '%s': %s", PROCDIR, strerror (errno));
+               return;
+       }
+
+       while (NULL != (dent = readdir (proc))) {
+               int  len;
+               char file[BUFSIZE];
+
+               FILE *fh;
+               char buffer[BUFSIZE];
+
+               char *cols[4];
+
+               long long       unix_s[3]       = {-1, -1, -1};
+               long long       inet[3]         = {-1, -1, -1};
+               long long       inet6[3]        = {-1, -1, -1};
+               long long       other[3]        = {-1, -1, -1};
+               long long       unspec[3]       = {-1, -1, -1};
+               int                     threads[4]      = {-1, -1, -1, -1};
+               double          load[3]         = {-1, -1, -1};
+               /* Just to be consistent ;-) */
+               int                     procs[1]        = {-1};
+               long long       memory[4]       = {-1, -1, -1, -1};
+
+               if (dent->d_name[0] == '.')
+                       continue;
+
+               /* XXX This check is just the result of a trial-and-error test.
+                * I did not find any documentation describing the d_type field. */
+               if (!(dent->d_type & 0x4))
+                       /* This is not a directory */
+                       continue;
+
+               /* socket message accounting */
+               len = snprintf (file, BUFSIZE, PROCDIR "/%s/cacct", dent->d_name);
+               if ((len < 0) || (len >= BUFSIZE))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r"))) {
+                       syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
+                       continue;
+               }
+
+               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+                       if (strsplit (buffer, cols, 4) < 4)
+                               continue;
+
+                       if (0 == strcmp (cols[0], "UNIX:")) {
+                               unix_s[0] = __get_sock_bytes (cols[1]);
+                               unix_s[1] = __get_sock_bytes (cols[2]);
+                               unix_s[2] = __get_sock_bytes (cols[3]);
+                       }
+                       else if (0 == strcmp (cols[0], "INET:")) {
+                               inet[0] = __get_sock_bytes (cols[1]);
+                               inet[1] = __get_sock_bytes (cols[2]);
+                               inet[2] = __get_sock_bytes (cols[3]);
+                       }
+                       else if (0 == strcmp (cols[0], "INET6:")) {
+                               inet6[0] = __get_sock_bytes (cols[1]);
+                               inet6[1] = __get_sock_bytes (cols[2]);
+                               inet6[2] = __get_sock_bytes (cols[3]);
+                       }
+                       else if (0 == strcmp (cols[0], "OTHER:")) {
+                               other[0] = __get_sock_bytes (cols[1]);
+                               other[1] = __get_sock_bytes (cols[2]);
+                               other[2] = __get_sock_bytes (cols[3]);
+                       }
+                       else if (0 == strcmp (cols[0], "UNSPEC:")) {
+                               unspec[0] = __get_sock_bytes (cols[1]);
+                               unspec[1] = __get_sock_bytes (cols[2]);
+                               unspec[2] = __get_sock_bytes (cols[3]);
+                       }
+               }
+
+               fclose (fh);
+
+               /* thread information and load */
+               len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name);
+               if ((len < 0) || (len >= BUFSIZE))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r"))) {
+                       syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
+                       continue;
+               }
+
+               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+                       int n = strsplit (buffer, cols, 4);
+
+                       if (2 == n) {
+                               if (0 == strcmp (cols[0], "nr_threads:")) {
+                                       threads[0] = atoi (cols[1]);
+                               }
+                               else if (0 == strcmp (cols[0], "nr_running:")) {
+                                       threads[1] = atoi (cols[1]);
+                               }
+                               else if (0 == strcmp (cols[0], "nr_unintr:")) {
+                                       threads[2] = atoi (cols[1]);
+                               }
+                               else if (0 == strcmp (cols[0], "nr_onhold:")) {
+                                       threads[3] = atoi (cols[1]);
+                               }
+                       }
+                       else if (4 == n) {
+                               if (0 == strcmp (cols[0], "loadavg:")) {
+                                       load[0] = atof (cols[1]);
+                                       load[1] = atof (cols[2]);
+                                       load[2] = atof (cols[3]);
+                               }
+                       }
+               }
+
+               fclose (fh);
+
+               /* processes and memory usage */
+               len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name);
+               if ((len < 0) || (len >= BUFSIZE))
+                       continue;
+
+               if (NULL == (fh = fopen (file, "r"))) {
+                       syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno));
+                       continue;
+               }
+
+               while (NULL != fgets (buffer, BUFSIZE, fh)) {
+                       if (strsplit (buffer, cols, 2) < 2)
+                               continue;
+
+                       if (0 == strcmp (cols[0], "PROC:")) {
+                               procs[0] = atoi (cols[1]);
+                       }
+                       else if (0 == strcmp (cols[0], "VM:")) {
+                               memory[0] = atoll (cols[1]) * pagesize;
+                       }
+                       else if (0 == strcmp (cols[0], "VML:")) {
+                               memory[1] = atoll (cols[1]) * pagesize;
+                       }
+                       else if (0 == strcmp (cols[0], "RSS:")) {
+                               memory[2] = atoll (cols[1]) * pagesize;
+                       }
+                       else if (0 == strcmp (cols[0], "ANON:")) {
+                               memory[3] = atoll (cols[1]) * pagesize;
+                       }
+               }
+
+               fclose (fh);
+
+               /* XXX What to do in case of an error (i.e. some value is
+                * still -1)? */
+
+               vserver_submit (dent->d_name, unix_s[0], unix_s[1], unix_s[2], 
+                               inet[0], inet[1], inet[2], inet6[0], inet6[1], inet6[2], 
+                               other[0], other[1], other[2], unspec[0], unspec[1], unspec[2],
+                               threads[0], threads[1], threads[2], threads[3], load[0], 
+                               load[1], load[2], procs[0], memory[0], memory[1], memory[2], 
+                               memory[3]);
+       }
+
+       closedir (proc);
+       return;
+} /* static void vserver_read(void) */
+#else
+# define vserver_read NULL
+#endif /* VSERVER_HAVE_READ */
+
+void module_register (void)
+{
+       plugin_register (MODULE_NAME, vserver_init, vserver_read, NULL);
+       plugin_register ("vserver_unix", NULL, NULL, vserver_unix_write);
+       plugin_register ("vserver_inet", NULL, NULL, vserver_inet_write);
+       plugin_register ("vserver_inet6", NULL, NULL, vserver_inet6_write);
+       plugin_register ("vserver_other", NULL, NULL, vserver_other_write);
+       plugin_register ("vserver_unspec", NULL, NULL, vserver_unspec_write);
+       plugin_register ("vserver_threads", NULL, NULL, vserver_threads_write);
+       plugin_register ("vserver_load", NULL, NULL, vserver_load_write);
+       plugin_register ("vserver_procs", NULL, NULL, vserver_procs_write);
+       plugin_register ("vserver_memory", NULL, NULL, vserver_memory_write);
+       return;
+} /* void module_register(void) */
+
+/* vim: set ts=4 sw=4 noexpandtab : */
index be366c4..f0b9b01 100644 (file)
@@ -24,8 +24,6 @@
 #include "common.h"
 #include "plugin.h"
 
-#include <math.h>
-
 #define MODULE_NAME "wireless"
 #define BUFSIZE 1024
 
@@ -41,9 +39,9 @@ static char *filename_template = "wireless-%s.rrd";
 
 static char *ds_def[] =
 {
-       "DS:quality:GAUGE:25:0:U",
-       "DS:power:GAUGE:25:0:U",
-       "DS:noise:GAUGE:25:0:U",
+       "DS:quality:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+       "DS:power:GAUGE:"COLLECTD_HEARTBEAT":U:0",
+       "DS:noise:GAUGE:"COLLECTD_HEARTBEAT":U:0",
        NULL
 };
 static int ds_num = 3;
@@ -79,6 +77,7 @@ static void wireless_write (char *host, char *inst, char *val)
 }
 
 #if WIRELESS_HAVE_READ
+#if 0
 static double wireless_dbm_to_watt (double dbm)
 {
        double watt;
@@ -92,6 +91,7 @@ static double wireless_dbm_to_watt (double dbm)
 
        return (watt);
 }
+#endif
 
 static void wireless_submit (char *device,
                double quality, double power, double noise)
@@ -154,18 +154,15 @@ static void wireless_read (void)
                power   = atof (fields[3]);
                noise   = atof (fields[4]);
 
+               /* Fill in invalid values when conversion failed.. */
                if (quality == 0.0)
-                       quality = -1.0;
+                       quality = -1.0; /* quality >= 0 */
 
-               if (power >= 0.0)
-                       power = -1.0;
-               else
-                       power = wireless_dbm_to_watt (power);
+               if (power == 0.0)
+                       power = 1.0; /* power <= 0 */
 
-               if (noise >= 0.0)
-                       noise = -1.0;
-               else
-                       noise = wireless_dbm_to_watt (noise);
+               if (noise == 0.0)
+                       noise = 1.0; /* noise <= 0 */
 
                wireless_submit (device, quality, power, noise);
        }
@@ -179,7 +176,7 @@ static void wireless_read (void)
 
 void module_register (void)
 {
-   plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write);
+       plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write);
 }
 
 #undef BUFSIZE