Merge pull request #759 from mschenck/add-linux-io-time
authorMarc Fournier <marc.fournier@camptocamp.com>
Thu, 20 Nov 2014 07:58:38 +0000 (08:58 +0100)
committerMarc Fournier <marc.fournier@camptocamp.com>
Thu, 20 Nov 2014 07:58:38 +0000 (08:58 +0100)
Add linux I/O time

45 files changed:
.gitignore
AUTHORS
README
configure.ac
contrib/redhat/collectd.spec
contrib/systemd.collectd.service [new file with mode: 0644]
contrib/upstart.collectd.conf
src/Makefile.am
src/battery.c
src/collectd-python.pod
src/collectd.conf.in
src/collectd.conf.pod
src/collectd.pod
src/cpu.c
src/daemon/Makefile.am
src/daemon/collectd.c
src/daemon/plugin.c
src/daemon/plugin.h
src/disk.c
src/dns.c
src/exec.c
src/libcollectdclient/Makefile.am
src/libcollectdclient/network_buffer.c
src/liboconfig/scanner.l
src/load.c
src/lvm.c
src/memory.c
src/mysql.c
src/network.c
src/ntpd.c
src/openldap.c [new file with mode: 0644]
src/processes.c
src/python.c
src/redis.c
src/smart.c [new file with mode: 0644]
src/snmp.c
src/tcpconns.c
src/types.db
src/users.c
src/utils_dns.c
src/varnish.c
src/write_kafka.c
src/write_redis.c
src/write_riemann.c
src/write_tsdb.c

index 1929b28..f005edd 100644 (file)
@@ -82,3 +82,8 @@ src/tags
 # tests stuff
 src/tests/.deps/
 src/tests/mock/.deps/
+
+# new daemon repo
+src/daemon/.deps/
+src/daemon/.dirstamp
+src/daemon/collectd
diff --git a/AUTHORS b/AUTHORS
index d821d9e..b1ebbf2 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -121,6 +121,9 @@ Jérôme Renard <jerome.renard at gmail.com>
 Kevin Bowling <kbowling at llnw.com>
  - write_tsdb plugin for http://opentsdb.net/
 
+Kimo Rosenbaum <kimor79 at yahoo.com>
+ - openldap plugin.
+
 Kris Nielander <nielander at fox-it.com>
  - tail_csv plugin.
 
@@ -151,6 +154,7 @@ Marc Fournier <marc.fournier at camptocamp.com>
  - RPM specfile update.
  - libmnl support in the netlink plugin.
  - linux support in the zfs_arc plugin.
+ - openldap plugin.
 
 Marco Chiappero <marco at absence.it>
  - uptime plugin.
@@ -217,7 +221,7 @@ Piotr Hosowicz <the55 at wp.pl>
  - SMF manifest for collectd.
 
 Richard W. M. Jones <rjones at redhat.com>
- - libvirt plugin.
+ - virt plugin.
  - uuid plugin.
 
 Roman Klesel <roman.klesel at noris.de>
@@ -249,7 +253,7 @@ Sven Trenkel <collectd at semidefinite.de>
  - python plugin.
 
 Tim Laszlo <tim.laszlo at gmail.com>
- - drbd plugin
+ - drbd plugin.
 
 Thomas Meson <zllak at hycik.org>
  - Graphite support for the AMQP plugin.
@@ -260,6 +264,9 @@ Tomasz Pala <gotar at pld-linux.org>
 Tommie Gannert <d00-tga at d.kth.se>
  - PID-file patch.
 
+Vincent Bernat <vincent at bernat.im>
+ - smart plugin.
+
 Vincent Stehlé <vincent.stehle at free.fr>
  - hddtemp plugin.
 
diff --git a/README b/README
index 1956609..8a34781 100644 (file)
--- a/README
+++ b/README
@@ -146,9 +146,6 @@ Features
       Detailed CPU statistics of the “Logical Partitions” virtualization
       technique built into IBM's POWER processors.
 
-    - libvirt
-      CPU, memory, disk and network I/O statistics from virtual machines.
-
     - lvm
       Size of “Logical Volumes” (LV) and “Volume Groups” (VG) of Linux'
       “Logical Volume Manager” (LVM).
@@ -232,6 +229,9 @@ Features
       Read onewire sensors using the owcapu library of the owfs project.
       Please read in collectd.conf(5) why this plugin is experimental.
 
+    - openldap
+      Read monitoring information from OpenLDAP's cn=Monitor subtree.
+
     - openvpn
       RX and TX of each client in openvpn-status.log (status-version 2).
       <http://openvpn.net/index.php/documentation/howto.html>
@@ -296,6 +296,10 @@ Features
       to have its measurements fed to collectd. This includes multimeters,
       sound level meters, thermometers, and much more.
 
+    - smart
+      Collect SMART statistics, notably load cycle count, temperature
+      and bad sectors.
+
     - snmp
       Read values from SNMP (Simple Network Management Protocol) enabled
       network devices such as switches, routers, thermometers, rack monitoring
@@ -347,6 +351,9 @@ Features
     - varnish
       Various statistics from Varnish, an HTTP accelerator.
 
+    - virt
+      CPU, memory, disk and network I/O statistics from virtual machines.
+
     - vmem
       Virtual memory statistics, e. g. the number of page-ins/-outs or the
       number of pagefaults.
@@ -604,12 +611,16 @@ Prerequisites
     particular.
     <http://developer.apple.com/corefoundation/>
 
+  * libatasmart (optional)
+    Used by the `smart' plugin.
+    <http://git.0pointer.de/?p=libatasmart.git>
+
   * libclntsh (optional)
     Used by the `oracle' plugin.
 
-  * libcredis (optional)
-    Used by the `redis' plugin. Please note that you require a 0.2.2 version
-    or higher. <http://code.google.com/p/credis/>
+  * libhiredis (optional)
+    Used by the redis plugin. Please note that you require a 0.10.0 version
+    or higher. <https://github.com/redis/hiredis>
 
   * libcurl (optional)
     If you want to use the `apache', `ascent', `bind', `curl', `curl_json',
@@ -650,6 +661,10 @@ Prerequisites
     libjvm” below.
     <http://openjdk.java.net/> (and others)
 
+  * libldap (optional)
+    Used by the `openldap' plugin.
+    <http://www.openldap.org/>
+
   * liblvm2 (optional)
     Used by the `lvm' plugin.
     <ftp://sources.redhat.com/pub/lvm2/>
@@ -775,7 +790,7 @@ Prerequisites
 
   * libxml2 (optional)
     Parse XML data. This is needed for the `ascent', `bind', `curl_xml' and
-    `libvirt' plugins.
+    `virt' plugins.
     <http://xmlsoft.org/>
 
   * libxmms (optional)
index 9dd30c7..332ed52 100644 (file)
@@ -527,7 +527,7 @@ AC_CHECK_HEADERS(linux/un.h, [], [],
 #endif
 ])
 
-AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h kvm.h wordexp.h locale.h)
+AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h sys/vmmeter.h kvm.h wordexp.h locale.h)
 
 # For the dns plugin
 AC_CHECK_HEADERS(arpa/nameser.h)
@@ -809,7 +809,9 @@ if test "x$have_swapctl" = "xyes"; then
 #  undef _LARGEFILE64_SOURCE
 #endif
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <sys/swap.h>
+#include <unistd.h>
 ]]],
 [[[
 int num = swapctl(0, NULL);
@@ -829,7 +831,9 @@ int num = swapctl(0, NULL);
 #  undef _LARGEFILE64_SOURCE
 #endif
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <sys/swap.h>
+#include <unistd.h>
 ]]],
 [[[
 int num = swapctl(0, NULL, 0);
@@ -1311,7 +1315,7 @@ AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct
 #include <sys/user.h>
        ])
 
-AC_CHECK_MEMBERS([struct kinfo_proc.kp_proc, struct kinfo_proc.kp_eproc],
+AC_CHECK_MEMBERS([struct kinfo_proc.p_pid, struct kinfo_proc.p_vm_rssize],
        [
                AC_DEFINE(HAVE_STRUCT_KINFO_PROC_OPENBSD, 1,
                        [Define if struct kinfo_proc exists in the OpenBSD variant.])
@@ -1328,6 +1332,7 @@ AC_CHECK_MEMBERS([struct kinfo_proc.kp_proc, struct kinfo_proc.kp_eproc],
 
 AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
 [#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
 #if HAVE_STDINT_H
 # include <stdint.h>
 #endif
@@ -1349,6 +1354,7 @@ AC_CHECK_MEMBERS([struct udphdr.uh_dport, struct udphdr.uh_sport], [], [],
 ])
 AC_CHECK_MEMBERS([struct udphdr.dest, struct udphdr.source], [], [],
 [#define _BSD_SOURCE
+#define _DEFAULT_SOURCE
 #if HAVE_STDINT_H
 # include <stdint.h>
 #endif
@@ -1573,62 +1579,63 @@ fi
 AM_CONDITIONAL(BUILD_WITH_LIBAQUAERO5, test "x$with_libaquaero5" = "xyes")
 # }}}
 
-# --with-libcredis {{{
-AC_ARG_WITH(libcredis, [AS_HELP_STRING([--with-libcredis@<:@=PREFIX@:>@], [Path to libcredis.])],
+# --with-libhiredis {{{
+AC_ARG_WITH(libhiredis, [AS_HELP_STRING([--with-libhiredis@<:@=PREFIX@:>@],
+      [Path to libhiredis.])],
 [
  if test "x$withval" = "xyes"
  then
-        with_libcredis="yes"
+        with_libhiredis="yes"
  else if test "x$withval" = "xno"
  then
-        with_libcredis="no"
+        with_libhiredis="no"
  else
-        with_libcredis="yes"
-        LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS -I$withval/include"
-        LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS -L$withval/lib"
+        with_libhiredis="yes"
+        LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS -I$withval/include"
+        LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS -L$withval/lib"
  fi; fi
 ],
-[with_libcredis="yes"])
+[with_libhiredis="yes"])
 
 SAVE_CPPFLAGS="$CPPFLAGS"
 SAVE_LDFLAGS="$LDFLAGS"
 
-CPPFLAGS="$CPPFLAGS $LIBCREDIS_CPPFLAGS"
-LDFLAGS="$LDFLAGS $LIBCREDIS_LDFLAGS"
+CPPFLAGS="$CPPFLAGS $LIBHIREDIS_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBHIREDIS_LDFLAGS"
 
-if test "x$with_libcredis" = "xyes"
+if test "x$with_libhiredis" = "xyes"
 then
-       if test "x$LIBCREDIS_CPPFLAGS" != "x"
+       if test "x$LIBHIREDIS_CPPFLAGS" != "x"
        then
-               AC_MSG_NOTICE([libcredis CPPFLAGS: $LIBCREDIS_CPPFLAGS])
+               AC_MSG_NOTICE([libhiredis CPPFLAGS: $LIBHIREDIS_CPPFLAGS])
        fi
-       AC_CHECK_HEADERS(credis.h,
-       [with_libcredis="yes"],
-       [with_libcredis="no (credis.h not found)"])
+       AC_CHECK_HEADERS(hiredis/hiredis.h,
+       [with_libhiredis="yes"],
+       [with_libhiredis="no (hiredis.h not found)"])
 fi
-if test "x$with_libcredis" = "xyes"
+if test "x$with_libhiredis" = "xyes"
 then
-       if test "x$LIBCREDIS_LDFLAGS" != "x"
+       if test "x$LIBHIREDIS_LDFLAGS" != "x"
        then
-               AC_MSG_NOTICE([libcredis LDFLAGS: $LIBCREDIS_LDFLAGS])
+               AC_MSG_NOTICE([libhiredis LDFLAGS: $LIBHIREDIS_LDFLAGS])
        fi
-       AC_CHECK_LIB(credis, credis_info,
-       [with_libcredis="yes"],
-       [with_libcredis="no (symbol 'credis_info' not found)"])
+       AC_CHECK_LIB(hiredis, redisCommand,
+       [with_libhiredis="yes"],
+       [with_libhiredis="no (symbol 'redisCommand' not found)"])
 
 fi
 
 CPPFLAGS="$SAVE_CPPFLAGS"
 LDFLAGS="$SAVE_LDFLAGS"
 
-if test "x$with_libcredis" = "xyes"
+if test "x$with_libhiredis" = "xyes"
 then
-       BUILD_WITH_LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS"
-       BUILD_WITH_LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS"
-       AC_SUBST(BUILD_WITH_LIBCREDIS_CPPFLAGS)
-       AC_SUBST(BUILD_WITH_LIBCREDIS_LDFLAGS)
+       BUILD_WITH_LIBHIREDIS_CPPFLAGS="$LIBHIREDIS_CPPFLAGS"
+       BUILD_WITH_LIBHIREDIS_LDFLAGS="$LIBHIREDIS_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBHIREDIS_LDFLAGS)
 fi
-AM_CONDITIONAL(BUILD_WITH_LIBCREDIS, test "x$with_libcredis" = "xyes")
+AM_CONDITIONAL(BUILD_WITH_LIBHIREDIS, test "x$with_libhiredis" = "xyes")
 # }}}
 
 # --with-libcurl {{{
@@ -2241,6 +2248,64 @@ AC_SUBST(JAVA_LIBS)
 AM_CONDITIONAL(BUILD_WITH_JAVA, test "x$with_java" = "xyes")
 # }}}
 
+# --with-libldap {{{
+AC_ARG_WITH(libldap, [AS_HELP_STRING([--with-libldap@<:@=PREFIX@:>@], [Path to libldap.])],
+[
+ if test "x$withval" = "xyes"
+ then
+        with_libldap="yes"
+ else if test "x$withval" = "xno"
+ then
+        with_libldap="no"
+ else
+        with_libldap="yes"
+        LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS -I$withval/include"
+        LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_libldap="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBLDAP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBLDAP_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_CPPFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libldap CPPFLAGS: $LIBLDAP_CPPFLAGS])
+       fi
+       AC_CHECK_HEADERS(ldap.h,
+       [with_libldap="yes"],
+       [with_libldap="no ('ldap.h' not found)"])
+fi
+if test "x$with_libldap" = "xyes"
+then
+       if test "x$LIBLDAP_LDFLAGS" != "x"
+       then
+               AC_MSG_NOTICE([libldap LDFLAGS: $LIBLDAP_LDFLAGS])
+       fi
+       AC_CHECK_LIB(ldap, ldap_initialize,
+       [with_libldap="yes"],
+       [with_libldap="no (symbol 'ldap_initialize' not found)"])
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+       BUILD_WITH_LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS"
+       BUILD_WITH_LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS"
+       AC_SUBST(BUILD_WITH_LIBLDAP_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBLDAP_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBLDAP, test "x$with_libldap" = "xyes")
+# }}}
+
 # --with-liblvm2app {{{
 with_liblvm2app_cppflags=""
 with_liblvm2app_ldflags=""
@@ -4071,6 +4136,34 @@ then
   LDFLAGS="$SAVE_LDFLAGS"
 fi
 
+if test "x$with_libstatgrab" = "xyes"
+then
+  SAVE_CFLAGS="$CFLAGS"
+  SAVE_LDFLAGS="$LDFLAGS"
+
+  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+
+  AC_CACHE_CHECK([if libstatgrab >= 0.90],
+          [c_cv_have_libstatgrab_0_90],
+          AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdio.h>
+#include <statgrab.h>
+]]],
+[[[
+      if (sg_init()) return 0;
+]]]
+    )],
+    [c_cv_have_libstatgrab_0_90="no"],
+    [c_cv_have_libstatgrab_0_90="yes"]
+          )
+  )
+
+  CFLAGS="$SAVE_CFLAGS"
+  LDFLAGS="$SAVE_LDFLAGS"
+fi
+
 AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
 if test "x$with_libstatgrab" = "xyes"
 then
@@ -4079,6 +4172,10 @@ then
   BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
   AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS)
   AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+  if test "x$c_cv_have_libstatgrab_0_90" = "xyes"
+  then
+        AC_DEFINE(HAVE_LIBSTATGRAB_0_90, 1, [Define to 1 if libstatgrab version >= 0.90])
+  fi
 fi
 # }}}
 
@@ -4590,25 +4687,18 @@ fi
 if test "x$with_libvarnish" = "xyes"
 then
        SAVE_CPPFLAGS="$CPPFLAGS"
-       CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
-       AC_CHECK_HEADERS(varnish/varnishapi.h, [], [with_libvarnish="no (varnish/varnishapi.h not found)"])
-
-       CPPFLAGS="$SAVE_CPPFLAGS"
-fi
-if test "x$with_libvarnish" = "xyes"
-then
-       SAVE_CPPFLAGS="$CPPFLAGS"
-       #SAVE_LDFLAGS="$LDFLAGS"
 
        CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
-       #LDFLAGS="$LDFLAGS $with_libvarnish_libs"
 
-    AC_CHECK_HEADERS(varnish/vsc.h,
-        [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])],
-        [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])])
+       AC_CHECK_HEADERS(varnish/vapi/vsc.h,
+               [AC_DEFINE([HAVE_VARNISH_V4], [1], [Varnish 4 API support])],
+               [AC_CHECK_HEADERS(varnish/vsc.h,
+                       [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])],
+                       [AC_CHECK_HEADERS(varnish/varnishapi.h,
+                               [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])],
+                               [with_libvarnish="no (found none of the varnish header files)"])])])
 
        CPPFLAGS="$SAVE_CPPFLAGS"
-       #LDFLAGS="$SAVE_LDFLAGS"
 fi
 if test "x$with_libvarnish" = "xyes"
 then
@@ -4817,6 +4907,62 @@ then
 fi
 # }}}
 
+# --with-libatasmart {{{
+with_libatasmart_cppflags=""
+with_libatasmart_ldflags=""
+AC_ARG_WITH(libatasmart, [AS_HELP_STRING([--with-libatasmart@<:@=PREFIX@:>@], [Path to libatasmart.])],
+[
+       if test "x$withval" != "xno" && test "x$withval" != "xyes"
+       then
+               with_libatasmart_cppflags="-I$withval/include"
+               with_libatasmart_ldflags="-L$withval/lib"
+               with_libatasmart="yes"
+       else
+               with_libatasmart="$withval"
+       fi
+],
+[
+       if test "x$ac_system" = "xLinux"
+       then
+               with_libatasmart="yes"
+       else
+               with_libatasmart="no (Linux only library)"
+       fi
+])
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+
+       AC_CHECK_HEADERS(atasmart.h, [with_libatasmart="yes"], [with_libatasmart="no (atasmart.h not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       SAVE_CPPFLAGS="$CPPFLAGS"
+       SAVE_LDFLAGS="$LDFLAGS"
+       CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+       LDFLAGS="$LDFLAGS $with_libatasmart_ldflags"
+
+       AC_CHECK_LIB(atasmart, sk_disk_open, [with_libatasmart="yes"], [with_libatasmart="no (Symbol 'sk_disk_open' not found)"])
+
+       CPPFLAGS="$SAVE_CPPFLAGS"
+       LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+       BUILD_WITH_LIBATASMART_CPPFLAGS="$with_libatasmart_cppflags"
+       BUILD_WITH_LIBATASMART_LDFLAGS="$with_libatasmart_ldflags"
+       BUILD_WITH_LIBATASMART_LIBS="-latasmart"
+       AC_SUBST(BUILD_WITH_LIBATASMART_CPPFLAGS)
+       AC_SUBST(BUILD_WITH_LIBATASMART_LDFLAGS)
+       AC_SUBST(BUILD_WITH_LIBATASMART_LIBS)
+       AC_DEFINE(HAVE_LIBATASMART, 1, [Define if libatasmart is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBATASMART, test "x$with_libatasmart" = "xyes")
+# }}}
+
 PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
                [with_libnotify="yes"],
                [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
@@ -5254,6 +5400,11 @@ then
        plugin_processes="yes"
 fi
 
+if test "x$with_kvm_getprocs" = "xyes" && test "x$have_struct_kinfo_proc_openbsd" = "xyes"
+then
+       plugin_processes="yes"
+fi
+
 if test "x$with_kvm_getswapinfo" = "xyes"
 then
        plugin_swap="yes"
@@ -5374,6 +5525,7 @@ AC_PLUGIN([numa],        [$plugin_numa],       [NUMA virtual memory statistics])
 AC_PLUGIN([nut],         [$with_libupsclient], [Network UPS tools statistics])
 AC_PLUGIN([olsrd],       [yes],                [olsrd statistics])
 AC_PLUGIN([onewire],     [$with_libowcapi],    [OneWire sensor statistics])
+AC_PLUGIN([openldap],    [$with_libldap],      [OpenLDAP statistics])
 AC_PLUGIN([openvpn],     [yes],                [OpenVPN client statistics])
 AC_PLUGIN([oracle],      [$with_oracle],       [Oracle plugin])
 AC_PLUGIN([perl],        [$plugin_perl],       [Embed a Perl interpreter])
@@ -5386,13 +5538,14 @@ AC_PLUGIN([powerdns],    [yes],                [PowerDNS statistics])
 AC_PLUGIN([processes],   [$plugin_processes],  [Process statistics])
 AC_PLUGIN([protocols],   [$plugin_protocols],  [Protocol (IP, TCP, ...) statistics])
 AC_PLUGIN([python],      [$with_python],       [Embed a Python interpreter])
-AC_PLUGIN([redis],       [$with_libcredis],    [Redis plugin])
+AC_PLUGIN([redis],       [$with_libhiredis],    [Redis plugin])
 AC_PLUGIN([routeros],    [$with_librouteros],  [RouterOS plugin])
 AC_PLUGIN([rrdcached],   [$librrd_rrdc_update], [RRDTool output plugin])
 AC_PLUGIN([rrdtool],     [$with_librrd],       [RRDTool output plugin])
 AC_PLUGIN([sensors],     [$with_libsensors],   [lm_sensors statistics])
 AC_PLUGIN([serial],      [$plugin_serial],     [serial port traffic])
 AC_PLUGIN([sigrok],      [$with_libsigrok],    [sigrok acquisition sources])
+AC_PLUGIN([smart],       [$with_libatasmart],  [SMART statistics])
 AC_PLUGIN([snmp],        [$with_libnetsnmp],   [SNMP querying plugin])
 AC_PLUGIN([statsd],      [yes],                [StatsD plugin])
 AC_PLUGIN([swap],        [$plugin_swap],       [Swap usage statistics])
@@ -5425,7 +5578,7 @@ AC_PLUGIN([write_graphite], [yes],             [Graphite / Carbon output plugin]
 AC_PLUGIN([write_http],  [$with_libcurl],      [HTTP output plugin])
 AC_PLUGIN([write_kafka],  [$with_librdkafka],  [Kafka output plugin])
 AC_PLUGIN([write_mongodb], [$with_libmongoc],  [MongoDB output plugin])
-AC_PLUGIN([write_redis], [$with_libcredis],    [Redis output plugin])
+AC_PLUGIN([write_redis], [$with_libhiredis],    [Redis output plugin])
 AC_PLUGIN([write_riemann], [$have_protoc_c],   [Riemann output plugin])
 AC_PLUGIN([write_tsdb],  [yes],                [TSDB output plugin])
 AC_PLUGIN([xmms],        [$with_libxmms],      [XMMS statistics])
@@ -5613,9 +5766,10 @@ Configuration:
   Libraries:
     intel mic . . . . . . $with_mic
     libaquaero5 . . . . . $with_libaquaero5
+    libatasmart . . . . . $with_libatasmart
     libcurl . . . . . . . $with_libcurl
     libdbi  . . . . . . . $with_libdbi
-    libcredis . . . . . . $with_libcredis
+    libhiredis  . . . . . $with_libhiredis
     libesmtp  . . . . . . $with_libesmtp
     libganglia  . . . . . $with_libganglia
     libgcrypt . . . . . . $with_libgcrypt
@@ -5625,6 +5779,7 @@ Configuration:
     libjvm  . . . . . . . $with_java
     libkstat  . . . . . . $with_kstat
     libkvm  . . . . . . . $with_libkvm
+    libldap . . . . . . . $with_libldap
     liblvm2app  . . . . . $with_liblvm2app
     libmemcached  . . . . $with_libmemcached
     libmnl  . . . . . . . $with_libmnl
@@ -5739,6 +5894,7 @@ Configuration:
     nut . . . . . . . . . $enable_nut
     olsrd . . . . . . . . $enable_olsrd
     onewire . . . . . . . $enable_onewire
+    openldap  . . . . . . $enable_openldap
     openvpn . . . . . . . $enable_openvpn
     oracle  . . . . . . . $enable_oracle
     perl  . . . . . . . . $enable_perl
@@ -5757,6 +5913,7 @@ Configuration:
     sensors . . . . . . . $enable_sensors
     serial  . . . . . . . $enable_serial
     sigrok  . . . . . . . $enable_sigrok
+    smart . . . . . . . . $enable_smart
     snmp  . . . . . . . . $enable_snmp
     statsd  . . . . . . . $enable_statsd
     swap  . . . . . . . . $enable_swap
index 9d63e3a..23fbae2 100644 (file)
@@ -47,6 +47,7 @@
 %{?el6:%global _has_libmodbus 1}
 %{?el6:%global _has_libudev 1}
 %{?el6:%global _has_iproute 1}
+%{?el6:%global _has_atasmart 1}
 
 %{?el7:%global _has_libyajl 1}
 %{?el7:%global _has_recent_libpcap 1}
@@ -59,6 +60,7 @@
 %{?el7:%global _has_varnish4 1}
 %{?el7:%global _has_broken_libmemcached 1}
 %{?el7:%global _has_iproute 1}
+%{?el7:%global _has_atasmart 1}
 
 # plugins enabled by default
 %define with_aggregation 0%{!?_without_aggregation:1}
@@ -96,7 +98,7 @@
 %define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}}
 %define with_irq 0%{!?_without_irq:1}
 %define with_java 0%{!?_without_java:1}
-%define with_libvirt 0%{!?_without_libvirt:1}
+%define with_virt 0%{!?_without_virt:1}
 %define with_load 0%{!?_without_load:1}
 %define with_logfile 0%{!?_without_logfile:1}
 %define with_log_logstash 0%{!?_without_log_logstash:0%{?_has_libyajl}}
 %define with_numa 0%{!?_without_numa:1}
 %define with_nut 0%{!?_without_nut:1}
 %define with_olsrd 0%{!?_without_olsrd:1}
+%define with_openldap 0%{!?_without_openldap:1}
 %define with_openvpn 0%{!?_without_openvpn:1}
 %define with_perl 0%{!?_without_perl:1}
 %define with_pinba 0%{!?_without_pinba:1}
 %define with_rrdtool 0%{!?_without_rrdtool:1}
 %define with_sensors 0%{!?_without_sensors:1}
 %define with_serial 0%{!?_without_serial:1}
+%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
 %define with_snmp 0%{!?_without_snmp:1}
 %define with_statsd 0%{!?_without_statsd:1}
 %define with_swap 0%{!?_without_swap:1}
@@ -417,16 +421,6 @@ This plugin for collectd allows plugins to be written in Java and executed
 in an embedded JVM.
 %endif
 
-%if %{with_libvirt}
-%package libvirt
-Summary:       Libvirt plugin for collectd
-Group:         System Environment/Daemons
-Requires:      %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: libvirt-devel
-%description libvirt
-This plugin collects information from virtualized guests.
-%endif
-
 %if %{with_log_logstash}
 %package log_logstash
 Summary:       log_logstash plugin for collectd
@@ -543,6 +537,16 @@ BuildRequires:     nut-devel
 This plugin for collectd provides Network UPS Tools support.
 %endif
 
+%if %{with_openldap}
+%package openldap
+Summary:       Openldap plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: openldap-devel
+%description openldap
+This plugin reads monitoring information from OpenLDAP's cn=Monitor subtree.
+%endif
+
 %if %{with_perl}
 %package perl
 Summary:       Perl plugin for collectd
@@ -660,6 +664,17 @@ measurements fed to collectd. This includes multimeters, sound level meters,
 thermometers, and much more.
 %endif
 
+%if %{with_smart}
+%package smart
+Summary:       SMART plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libatasmart-devel
+%description smart
+Collect SMART statistics, notably load cycle count, temperature and bad
+sectors.
+%endif
+
 %if %{with_snmp}
 %package snmp
 Summary:       SNMP plugin for collectd
@@ -680,6 +695,16 @@ BuildRequires:     varnish-libs-devel
 The Varnish plugin collects information about Varnish, an HTTP accelerator.
 %endif
 
+%if %{with_virt}
+%package virt
+Summary:       Virt plugin for collectd
+Group:         System Environment/Daemons
+Requires:      %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libvirt-devel
+%description virt
+This plugin collects information from virtualized guests.
+%endif
+
 %if %{with_write_http}
 %package write_http
 Summary:       Write-HTTP plugin for collectd
@@ -996,10 +1021,10 @@ Development files for libcollectdclient
 %define _with_java --disable-java
 %endif
 
-%if %{with_libvirt}
-%define _with_libvirt --enable-libvirt
+%if %{with_virt}
+%define _with_virt --enable-virt
 %else
-%define _with_libvirt --disable-libvirt
+%define _with_virt --disable-virt
 %endif
 
 %if %{with_load}
@@ -1164,6 +1189,12 @@ Development files for libcollectdclient
 %define _with_onewire --disable-onewire
 %endif
 
+%if %{with_openldap}
+%define _with_openldap --enable-openldap
+%else
+%define _with_openldap --disable-openldap
+%endif
+
 %if %{with_openvpn}
 %define _with_openvpn --enable-openvpn
 %else
@@ -1276,6 +1307,12 @@ Development files for libcollectdclient
 %define _with_sigrok --disable-sigrok
 %endif
 
+%if %{with_smart}
+%define _with_smart --enable-smart
+%else
+%define _with_smart --disable-smart
+%endif
+
 %if %{with_snmp}
 %define _with_snmp --enable-snmp
 %else
@@ -1513,7 +1550,7 @@ Development files for libcollectdclient
        %{?_with_iptables} \
        %{?_with_ipvs} \
        %{?_with_java} \
-       %{?_with_libvirt} \
+       %{?_with_virt} \
        %{?_with_log_logstash} \
        %{?_with_lpar} \
        %{?_with_lvm} \
@@ -1529,6 +1566,7 @@ Development files for libcollectdclient
        %{?_with_notify_email} \
        %{?_with_nut} \
        %{?_with_onewire} \
+       %{?_with_openldap} \
        %{?_with_oracle} \
        %{?_with_perl} \
        %{?_with_pf} \
@@ -1542,6 +1580,7 @@ Development files for libcollectdclient
        %{?_with_rrdtool} \
        %{?_with_sensors} \
        %{?_with_sigrok} \
+       %{?_with_smart} \
        %{?_with_snmp} \
        %{?_with_tape} \
        %{?_with_tokyotyrant} \
@@ -1983,9 +2022,9 @@ fi
 %{_mandir}/man5/collectd-java.5*
 %endif
 
-%if %{with_libvirt}
-%files libvirt
-%{_libdir}/%{name}/libvirt.so
+%if %{with_virt}
+%files virt
+%{_libdir}/%{name}/virt.so
 %endif
 
 %if %{with_log_logstash}
@@ -2043,6 +2082,11 @@ fi
 %{_libdir}/%{name}/nut.so
 %endif
 
+%if %{with_openldap}
+%files openldap
+%{_libdir}/%{name}/openldap.so
+%endif
+
 %if %{with_perl}
 %files perl
 %doc perl-examples/*
@@ -2100,6 +2144,11 @@ fi
 %{_libdir}/%{name}/sigrok.so
 %endif
 
+%if %{with_smart}
+%files smart
+%{_libdir}/%{name}/smart.so
+%endif
+
 %if %{with_snmp}
 %files snmp
 %{_mandir}/man5/collectd-snmp.5*
@@ -2145,7 +2194,7 @@ fi
 %changelog
 # * TODO 5.5.0-1
 # - New upstream version
-# - New plugins enabled by default: drbd, log_logstash, write_tsdb
+# - New plugins enabled by default: drbd, log_logstash, write_tsdb, smart, openldap
 # - New plugins disabled by default: barometer, write_kafka
 # - Enable zfs_arc, now supported on Linux
 # - Install disk plugin in an dedicated package, as it depends on libudev
diff --git a/contrib/systemd.collectd.service b/contrib/systemd.collectd.service
new file mode 100644 (file)
index 0000000..b046192
--- /dev/null
@@ -0,0 +1,23 @@
+[Unit]
+Description=Collectd
+After=local-fs.target network.target
+Requires=local-fs.target network.target
+
+[Service]
+ExecStart=/usr/sbin/collectd
+
+# Tell systemd it will receive a notification from collectd over it's control
+# socket once the daemon is ready. See systemd.service(5) for more details.
+Type=notify
+NotifyAccess=main
+
+# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
+Restart=always
+RestartSec=10
+
+# Send all console messages to syslog.
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
index 1c7fd9c..69032a5 100644 (file)
@@ -20,6 +20,7 @@ stop on runlevel [!2345]
 # these cannot be started at boot time by the system without
 # arcane trickery. Also a root user will not see these tasks/jobs
 # by default. set*id is a reasonable and secure compromise.
+# These options are not supported on early upstart versions.
 #setuid nobody
 #setgid nobody
 
@@ -31,15 +32,17 @@ stop on runlevel [!2345]
 # shell commands via `sh -e`.
 env DAEMON=/usr/sbin/collectd
 
-# Tell upstart to watch for forking when tracking the pid for us.
-expect fork
+# Tell upstart to wait for collectd to SIGSTOP itself, signaling it is ready
+# to run.
+expect stop
 
 # prevent thrashing - 10 restarts in 5 seconds
 respawn
 respawn limit 10 5
 
-# Make a log available in /var/log/upstart/collectd.log
-console log
+# Uncomment to make a log available in /var/log/upstart/collectd.log
+# (not supported on early upstart versions).
+#console log
 
 # The daemon will not start if the configuration is invalid.
 pre-start exec $DAEMON -t
index 5c6adfe..e942869 100644 (file)
@@ -30,7 +30,7 @@ collectdmon_SOURCES = collectdmon.c
 collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
 
 collectd_nagios_SOURCES = collectd-nagios.c
-collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
 collectd_nagios_LDADD =
 if BUILD_WITH_LIBSOCKET
 collectd_nagios_LDADD += -lsocket
@@ -44,7 +44,7 @@ collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
 
 
 collectdctl_SOURCES = collectdctl.c
-collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
 collectdctl_LDADD =
 if BUILD_WITH_LIBSOCKET
 collectdctl_LDADD += -lsocket
@@ -57,7 +57,7 @@ collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
 
 collectd_tg_SOURCES = collectd-tg.c \
                      daemon/utils_heap.c daemon/utils_heap.h
-collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
 collectd_tg_LDADD =
 if BUILD_WITH_LIBSOCKET
 collectd_tg_LDADD += -lsocket
@@ -68,6 +68,9 @@ endif
 if BUILD_AIX
 collectd_tg_LDADD += -lm
 endif
+if BUILD_WITH_LIBPTHREAD
+collectd_tg_LDADD += -lpthread
+endif
 collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
 collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
 
@@ -82,7 +85,7 @@ pkglib_LTLIBRARIES += aggregation.la
 aggregation_la_SOURCES = aggregation.c \
                          utils_vl_lookup.c utils_vl_lookup.h
 aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-aggregation_la_LIBADD =
+aggregation_la_LIBADD = -lm
 endif
 
 if BUILD_PLUGIN_AMQP
@@ -725,6 +728,14 @@ onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
 onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 endif
 
+if BUILD_PLUGIN_OPENLDAP
+pkglib_LTLIBRARIES += openldap.la
+openldap_la_SOURCES = openldap.c
+openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
+openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LIBADD = -lldap
+endif
+
 if BUILD_PLUGIN_OPENVPN
 pkglib_LTLIBRARIES += openvpn.la
 openvpn_la_SOURCES = openvpn.c
@@ -830,9 +841,9 @@ endif
 if BUILD_PLUGIN_REDIS
 pkglib_LTLIBRARIES += redis.la
 redis_la_SOURCES = redis.c
-redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBCREDIS_LDFLAGS)
-redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
-redis_la_LIBADD = -lcredis
+redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+redis_la_LIBADD = -lhiredis
 endif
 
 if BUILD_PLUGIN_ROUTEROS
@@ -882,6 +893,17 @@ sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
 sigrok_la_LIBADD = -lsigrok
 endif
 
+if BUILD_PLUGIN_SMART
+if BUILD_WITH_LIBUDEV
+pkglib_LTLIBRARIES += smart.la
+smart_la_SOURCES = smart.c \
+                  utils_ignorelist.c utils_ignorelist.h
+smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
+smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
+smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
+endif
+endif
+
 if BUILD_PLUGIN_SNMP
 pkglib_LTLIBRARIES += snmp.la
 snmp_la_SOURCES = snmp.c
@@ -1164,9 +1186,9 @@ endif
 if BUILD_PLUGIN_WRITE_REDIS
 pkglib_LTLIBRARIES += write_redis.la
 write_redis_la_SOURCES = write_redis.c
-write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBCREDIS_LDFLAGS)
-write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
-write_redis_la_LIBADD = -lcredis
+write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
+write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+write_redis_la_LIBADD = -lhiredis
 endif
 
 if BUILD_PLUGIN_WRITE_RIEMANN
@@ -1305,7 +1327,7 @@ uninstall-hook:
 check_PROGRAMS = test_common test_utils_avltree test_utils_heap test_utils_mount test_utils_vl_lookup
 
 test_common_SOURCES = tests/test_common.c \
-                      common.h common.c \
+                      daemon/common.h daemon/common.c \
                       tests/mock/plugin.c \
                       tests/mock/utils_cache.c \
                       tests/mock/utils_time.c
@@ -1314,20 +1336,20 @@ test_common_LDFLAGS = -export-dynamic
 test_common_LDADD =
 
 test_utils_avltree_SOURCES = tests/test_utils_avltree.c \
-                             utils_avltree.c utils_avltree.h
+                             daemon/utils_avltree.c daemon/utils_avltree.h
 test_utils_avltree_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
 test_utils_avltree_LDFLAGS = -export-dynamic
 test_utils_avltree_LDADD =
 
 test_utils_heap_SOURCES = tests/test_utils_heap.c \
-                          utils_heap.c utils_heap.h
+                          daemon/utils_heap.c daemon/utils_heap.h
 test_utils_heap_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
 test_utils_heap_LDFLAGS = -export-dynamic
 test_utils_heap_LDADD =
 
 test_utils_mount_SOURCES = tests/test_utils_mount.c \
                            utils_mount.c utils_mount.h \
-                           common.c common.h \
+                           daemon/common.c daemon/common.h \
                            tests/mock/plugin.c \
                            tests/mock/utils_cache.c \
                            tests/mock/utils_time.c
@@ -1337,8 +1359,8 @@ test_utils_mount_LDADD =
 
 test_utils_vl_lookup_SOURCES = tests/test_utils_vl_lookup.c \
                                utils_vl_lookup.h utils_vl_lookup.c \
-                               utils_avltree.c utils_avltree.h \
-                               common.c common.h \
+                               daemon/utils_avltree.c daemon/utils_avltree.h \
+                               daemon/common.c daemon/common.h \
                                tests/mock/plugin.c \
                                tests/mock/utils_cache.c \
                                tests/mock/utils_time.c
index 62c2964..185442c 100644 (file)
@@ -376,6 +376,8 @@ static int battery_read (void) /* {{{ */
                battery_submit ("0", "current", current);
        if (!isnan (voltage))
                battery_submit ("0", "voltage", voltage);
+
+       return (0);
 } /* }}} int battery_read */
 /* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
 
index ff1cb31..d04d0f0 100644 (file)
@@ -562,7 +562,7 @@ receive blocks where your callback identifier matches B<python.>I<blockname>.
 
 The callback will be called without arguments.
 
-=item register_read(callback[, interval][, data][, name]) -> identifier
+=item register_read(callback[, interval][, data][, name]) -> I<identifier>
 
 This function takes an additional parameter: I<interval>. It specifies the
 time between calls to the callback function.
@@ -616,7 +616,33 @@ I<identifier> is either the string that was returned by the register function
 or a callback function. The identifier will be constructed in the same way as
 for the register functions.
 
-=item B<flush>(I<plugin[, I<timeout>][, I<identifier>]) -> None
+=item B<get_dataset>(I<name>) -> I<definition>
+
+Returns the definition of a dataset specified by I<name>. I<definition> is a list
+of tuples, each representing one data source. Each tuple has 4 values:
+
+=over 4
+
+=item name
+
+A string, the name of the data source.
+
+=item type
+
+A string that is equal to either of the variables B<DS_TYPE_COUNTER>,
+B<DS_TYPE_GAUGE>, B<DS_TYPE_DERIVE> or B<DS_TYPE_ABSOLUTE>.
+
+=item min
+
+A float or None, the minimum value.
+
+=item max
+
+A float or None, the maximum value.
+
+=back
+
+=item B<flush>(I<plugin>[, I<timeout>][, I<identifier>]) -> None
 
 Flush one or all plugins. I<timeout> and the specified I<identifiers> are
 passed on to the registered flush-callbacks. If omitted, the timeout defaults
index 80e1d5c..5196979 100644 (file)
 #@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
 #@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
 #@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
+#@BUILD_PLUGIN_OPENLDAP_TRUE@LoadPlugin openldap
 #@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
 #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
 #@BUILD_PLUGIN_PERL_TRUE@<LoadPlugin perl>
 #@BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors
 #@BUILD_PLUGIN_SERIAL_TRUE@LoadPlugin serial
 #@BUILD_PLUGIN_SIGROK_TRUE@LoadPlugin sigrok
+#@BUILD_PLUGIN_SMART_TRUE@LoadPlugin smart
 #@BUILD_PLUGIN_SNMP_TRUE@LoadPlugin snmp
 #@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd
 #@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap
 #      IgnoreSelected false
 #</Plugin>
 
+#<Plugin openldap>
+#  <Instance "localhost">
+#    URL "ldap://localhost:389"
+#    StartTLS false
+#    VerifyHost true
+#    CACert "/path/to/ca.crt"
+#    Timeout -1
+#    Version 3
+#  </Instance>
+#</Plugin>
+
 #<Plugin openvpn>
 #      StatusFile "/etc/openvpn/openvpn-status.log"
 #      ImprovedNamingSchema false
 #  </Device>
 #</Plugin>
 
+#<Plugin smart>
+#  Disk "/^[hs]d[a-f][0-9]?$/"
+#  IgnoreSelected false
+#</Plugin>
+
 #<Plugin snmp>
 #   <Data "powerplus_voltge_input">
 #       Type "voltage"
 
 #<Plugin tcpconns>
 #      ListeningPorts false
+#      AllPortsSummary false
 #      LocalPort "25"
 #      RemotePort "25"
 #</Plugin>
 #   If you prefer defining another instance you can do
 #   so by using <Instance "myinstance">
 #   <Instance>
-#      CollectCache true
 #      CollectBackend true
-#      CollectBan false           # Varnish 3 only
+#      CollectBan false           # Varnish 3 and above
+#      CollectCache true
 #      CollectConnections true
 #      CollectDirectorDNS false   # Varnish 3 only
-#      CollectSHM true
 #      CollectESI false
 #      CollectFetch false
 #      CollectHCB false
 #      CollectObjects false
 #      CollectPurge false         # Varnish 2 only
 #      CollectSession false
+#      CollectSHM true
 #      CollectSMA false           # Varnish 2 only
 #      CollectSMS false
 #      CollectSM false            # Varnish 2 only
 #      CollectStruct false
 #      CollectTotals false
-#      CollectUptime false
+#      CollectUptime false        # Varnish 3 and above
 #      CollectVCL false
+#      CollectVSM false           # Varnish 4 only
 #      CollectWorkers false
 #   </Instance>
 #</Plugin>
index ac0ff2a..03871a4 100644 (file)
@@ -9,17 +9,17 @@ collectd.conf - Configuration for the system statistics collection daemon B<coll
   BaseDir "/var/lib/collectd"
   PIDFile "/run/collectd.pid"
   Interval 10.0
-  
+
   LoadPlugin cpu
   LoadPlugin load
-  
+
   <LoadPlugin df>
     Interval 3600
   </LoadPlugin>
   <Plugin df>
     ValuesPercentage true
   </Plugin>
-  
+
   LoadPlugin ping
   <Plugin ping>
     Host "example.org"
@@ -4245,6 +4245,70 @@ short: If it works for you: Great! But keep in mind that the config I<might>
 change, though this is unlikely. Oh, and if you want to help improving this
 plugin, just send a short notice to the mailing list. ThanksE<nbsp>:)
 
+=head2 Plugin C<openldap>
+
+To use the C<openldap> plugin you first need to configure the I<OpenLDAP>
+server correctly. The backend database C<monitor> needs to be loaded and
+working. See slapd-monitor(5) for the details.
+
+The configuration of the C<openldap> plugin consists of one or more B<Instance>
+blocks. Each block requires one string argument as the instance name. For
+example:
+
+ <Plugin "openldap">
+   <Instance "foo">
+     URL "ldap://localhost/"
+   </Instance>
+   <Instance "bar">
+     URL "ldaps://localhost/"
+   </Instance>
+ </Plugin>
+
+The instance name will be used as the I<plugin instance>. To emulate the old
+(versionE<nbsp>4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it is.
+
+The following options are accepted within each B<Instance> block:
+
+=over 4
+
+=item B<URL> I<ldap://host/binddn>
+
+Sets the URL to use to connect to the I<OpenLDAP> server. This option is
+I<mandatory>.
+
+=item B<StartTLS> B<true|false>
+
+Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
+Disabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enables or disables peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use TLS/SSL you
+may possibly need this option. What CA certificates are checked by default
+depends on the distribution you use and can be changed with the usual ldap
+client configuration mechanisms. See ldap.conf(5) for the details.
+
+=item B<Timeout> I<Seconds>
+
+Sets the timeout value for ldap operations. Defaults to B<-1> which results in
+an infinite timeout.
+
+=item B<Version> I<Version>
+
+An integer which sets the LDAP protocol version number to use when connecting
+to the I<OpenLDAP> server. Defaults to B<3> for using I<LDAPv3>.
+
+=back
+
 =head2 Plugin C<openvpn>
 
 The OpenVPN plugin reads a status file maintained by OpenVPN and gathers
@@ -5639,6 +5703,40 @@ measurements are discarded.
 
 =back
 
+=head2 Plugin C<smart>
+
+The C<smart> plugin collects SMART information from physical
+disks. Values collectd include temperature, power cycle count, poweron
+time and bad sectors. Also, all SMART attributes are collected along
+with the normalized current value, the worst value, the threshold and
+a human readable value.
+
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+
+=over 4
+
+=item B<Disk> I<Name>
+
+Select the disk I<Name>. Whether it is collected or ignored depends on the
+B<IgnoreSelected> setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+
+  Disk "sdd"
+  Disk "/hda[34]/"
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no B<Disk> option is configured, all disks are
+collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
+set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
+is set to B<true>, all disks are collected B<except> the ones matched.
+
+=back
+
 =head2 Plugin C<snmp>
 
 Since the configuration of the C<snmp plugin> is a little more complicated than
@@ -6176,6 +6274,11 @@ connections a mail server or news server has to other mail or news servers, or
 how many connections a web proxy holds to web servers. You have to give the
 port in numeric form.
 
+=item B<AllPortsSummary> I<true>|I<false>
+
+If this option is set to I<true> a summary of statistics from all connections
+are collectd. This option defaults to I<false>.
+
 =back
 
 =head2 Plugin C<thermal>
@@ -6305,22 +6408,35 @@ Take the UUID from the given file (default I</etc/uuid>).
 =head2 Plugin C<varnish>
 
 The I<varnish plugin> collects information about Varnish, an HTTP accelerator.
+It collects a subset of the values displayed by L<varnishstat(1)>, and
+organizes them in categories which can be enabled or disabled. Currently only
+metrics shown in L<varnishstat(1)>'s I<MAIN> section are collected. The exact
+meaning of each metric can be found in L<varnish-counters(7)>.
 
 Synopsis:
 
  <Plugin "varnish">
    <Instance "example">
+     CollectBackend     true
+     CollectBan         false
      CollectCache       true
      CollectConnections true
-     CollectBackend     true
-     CollectSHM         true
+     CollectDirectorDNS false
      CollectESI         false
      CollectFetch       false
      CollectHCB         false
+     CollectObjects     false
+     CollectPurge       false
+     CollectSession     false
+     CollectSHM         true
      CollectSMA         false
      CollectSMS         false
      CollectSM          false
+     CollectStruct      false
      CollectTotals      false
+     CollectUptime      false
+     CollectVCL         false
+     CollectVSM         false
      CollectWorkers     false
    </Instance>
  </Plugin>
@@ -6334,29 +6450,24 @@ Inside each E<lt>B<Instance>E<gt> blocks, the following options are recognized:
 
 =over 4
 
-=item B<CollectCache> B<true>|B<false>
-
-Cache hits and misses. True by default.
-
-=item B<CollectConnections> B<true>|B<false>
-
-Number of client connections received, accepted and dropped. True by default.
-
 =item B<CollectBackend> B<true>|B<false>
 
 Back-end connection statistics, such as successful, reused,
 and closed connections. True by default.
 
-=item B<CollectSHM> B<true>|B<false>
-
-Statistics about the shared memory log, a memory region to store
-log messages which is flushed to disk when full. True by default.
-
 =item B<CollectBan> B<true>|B<false>
 
 Statistics about ban operations, such as number of bans added, retired, and
 number of objects tested against ban operations. Only available with Varnish
-3.x. False by default.
+3.x and above. False by default.
+
+=item B<CollectCache> B<true>|B<false>
+
+Cache hits and misses. True by default.
+
+=item B<CollectConnections> B<true>|B<false>
+
+Number of client connections received, accepted and dropped. True by default.
 
 =item B<CollectDirectorDNS> B<true>|B<false>
 
@@ -6390,7 +6501,14 @@ number of objects tested against purge operations. Only available with Varnish
 =item B<CollectSession> B<true>|B<false>
 
 Client session statistics. Number of past and current sessions, session herd and
-linger counters, etc. False by default.
+linger counters, etc. False by default. Note that if using Varnish 4.x, some
+metrics found in the Connections and Threads sections with previous versions of
+Varnish have been moved here.
+
+=item B<CollectSHM> B<true>|B<false>
+
+Statistics about the shared memory log, a memory region to store
+log messages which is flushed to disk when full. True by default.
 
 =item B<CollectSMA> B<true>|B<false>
 
@@ -6421,12 +6539,17 @@ the number of requests and bytes transferred. False by default.
 
 =item B<CollectUptime> B<true>|B<false>
 
-Varnish uptime. False by default.
+Varnish uptime. Only available with Varnish 3.x and above. False by default.
 
 =item B<CollectVCL> B<true>|B<false>
 
 Number of total (available + discarded) VCL (config files). False by default.
 
+=item B<CollectVSM> B<true>|B<false>
+
+Collect statistics about Varnish's shared memory usage (used by the logging and
+statistics subsystems). Only available with Varnish 4.x. False by default.
+
 =item B<CollectWorkers> B<true>|B<false>
 
 Collect statistics about worker threads. False by default.
@@ -6494,7 +6617,7 @@ will be collected.
 
 =item B<HostnameFormat> B<name|uuid|hostname|...>
 
-When the libvirt plugin logs data, it sets the hostname of the collected data
+When the virt plugin logs data, it sets the hostname of the collected data
 according to this setting. The default is to use the guest name as provided by
 the hypervisor, which is equal to setting B<name>.
 
@@ -6510,7 +6633,7 @@ between, thus I<"foo:1234-1234-1234-1234">).
 
 =item B<InterfaceFormat> B<name>|B<address>
 
-When the libvirt plugin logs interface data, it sets the name of the collected
+When the virt plugin logs interface data, it sets the name of the collected
 data according to this setting. The default is to use the path as provided by
 the hypervisor (the "dev" property of the target node), which is equal to
 setting B<name>.
@@ -6520,7 +6643,7 @@ interface path might change between reboots of a guest or across migrations.
 
 =item B<PluginInstanceFormat> B<name|uuid>
 
-When the libvirt plugin logs data, it sets the plugin_instance of the collected
+When the virt plugin logs data, it sets the plugin_instance of the collected
 data according to this setting. The default is to use the guest name as provided
 by the hypervisor, which is equal to setting B<name>.
 
@@ -7005,6 +7128,20 @@ Service name or port number to connect to. Defaults to C<5555>.
 Specify the protocol to use when communicating with I<Riemann>. Defaults to
 B<UDP>.
 
+=item B<Batch> B<true>|B<false>
+
+If set to B<true> and B<Protocol> is set to B<TCP>,
+events will be batched in memory and flushed at
+regular intervals or when B<BatchMaxSize> is exceeded.
+
+Notifications are not batched and sent as soon as possible.
+
+Defaults to false
+
+=item B<BatchMaxSize> I<size>
+
+Maximum payload size for a riemann packet. Defaults to 8192
+
 =item B<StoreRates> B<true>|B<false>
 
 If set to B<true> (the default), convert counter values to rates. If set to
index 8fccdb3..fb0403b 100644 (file)
@@ -49,7 +49,11 @@ config-option.
 
 Don't fork to the background. I<collectd> will also B<not> close standard file
 descriptors, detach from the session nor write a pid file. This is mainly
-thought for 'supervising' init replacements such as I<runit>.
+thought for 'supervising' init replacements such as I<runit>. If using
+I<upstart> or I<systemd> though, starting with version 5.5.0 I<collectd> is
+able to notify these two init replacements, and B<does> require forking to the
+background for process supervision. The F<contrib/> directory has sample
+I<upstart> and I<systemd> configuration files.
 
 =item B<-h>
 
index fae7ab9..d1978f9 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -472,20 +472,34 @@ static void cpu_reset (void) /* {{{ */
 /* Legacy behavior: Dispatches the raw derive values without any aggregation. */
 static void cpu_commit_without_aggregation (void) /* {{{ */
 {
-       size_t cpu_num;
+       int state;
 
-       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+       for (state = 0; state < CPU_STATE_ACTIVE; state++)
        {
-               int state;
-
-               for (state = 0; state < CPU_STATE_ACTIVE; state++)
-               {
-                       cpu_state_t *s = get_cpu_state (cpu_num, state);
+               size_t cpu_num;
+               if (report_by_cpu) {
+                       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+                       {
+                               cpu_state_t *s = get_cpu_state (cpu_num, state);
 
-                       if (!s->has_value)
-                               continue;
+                               if (!s->has_value)
+                                       continue;
 
-                       submit_derive ((int) cpu_num, (int) state, s->conv.last_value.derive);
+                               submit_derive ((int) cpu_num, (int) state, s->conv.last_value.derive);
+                       }
+               } else {
+                       derive_t derive_total = 0;
+                       for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+                               {
+                                       cpu_state_t *s = get_cpu_state (cpu_num, state);
+
+                                       if (!s->has_value)
+                                               continue;
+
+                                       derive_total += s->conv.last_value.derive;
+                       
+                               }
+                       submit_derive (-1, (int) state, derive_total);
                }
        }
 } /* }}} void cpu_commit_without_aggregation */
@@ -498,7 +512,7 @@ static void cpu_commit (void) /* {{{ */
        };
        size_t cpu_num;
 
-       if (report_by_cpu && report_by_state && !report_percent)
+       if (report_by_state && !report_percent)
        {
                cpu_commit_without_aggregation ();
                return;
@@ -772,11 +786,11 @@ static int cpu_read (void)
        }
 
        for (i = 0; i < numcpu; i++) {
-               cpu_state (i, CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER]);
-               cpu_state (i, CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE]);
-               cpu_state (i, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS]);
-               cpu_state (i, CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE]);
-               cpu_state (i, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR]);
+               cpu_stage (i, CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
+               cpu_stage (i, CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
+               cpu_stage (i, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
+               cpu_stage (i, CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE], now);
+               cpu_stage (i, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR], now);
        }
 /* }}} #endif CAN_USE_SYSCTL */
 
@@ -797,11 +811,11 @@ static int cpu_read (void)
        }
 
        for (i = 0; i < numcpu; i++) {
-               cpu_state (i, CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER]);
-               cpu_state (i, CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE]);
-               cpu_state (i, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS]);
-               cpu_state (i, CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE]);
-               cpu_state (i, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR]);
+               cpu_stage (i, CPU_STATE_USER,      (derive_t) cpuinfo[i][CP_USER], now);
+               cpu_stage (i, CPU_STATE_NICE,      (derive_t) cpuinfo[i][CP_NICE], now);
+               cpu_stage (i, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[i][CP_SYS], now);
+               cpu_stage (i, CPU_STATE_IDLE,      (derive_t) cpuinfo[i][CP_IDLE], now);
+               cpu_stage (i, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[i][CP_INTR], now);
        }
 /* }}} #endif HAVE_SYSCTL_KERN_CP_TIMES */
 
@@ -819,11 +833,11 @@ static int cpu_read (void)
                return (-1);
        }
 
-       cpu_state (0, CPU_STATE_USER,      (derive_t) cpuinfo[CP_USER]);
-       cpu_state (0, CPU_STATE_NICE,      (derive_t) cpuinfo[CP_NICE]);
-       cpu_state (0, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[CP_SYS]);
-       cpu_state (0, CPU_STATE_IDLE,      (derive_t) cpuinfo[CP_IDLE]);
-       cpu_state (0, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[CP_INTR]);
+       cpu_stage (0, CPU_STATE_USER,      (derive_t) cpuinfo[CP_USER], now);
+       cpu_stage (0, CPU_STATE_NICE,      (derive_t) cpuinfo[CP_NICE], now);
+       cpu_stage (0, CPU_STATE_SYSTEM,    (derive_t) cpuinfo[CP_SYS], now);
+       cpu_stage (0, CPU_STATE_IDLE,      (derive_t) cpuinfo[CP_IDLE], now);
+       cpu_stage (0, CPU_STATE_INTERRUPT, (derive_t) cpuinfo[CP_INTR], now);
 /* }}} #endif HAVE_SYSCTLBYNAME */
 
 #elif defined(HAVE_LIBSTATGRAB) /* {{{ */
index d6067d7..fc81554 100644 (file)
@@ -2,7 +2,8 @@ if COMPILER_IS_GCC
 AM_CFLAGS = -Wall -Werror
 endif
 
-AM_CPPFLAGS = -DPREFIX='"${prefix}"'
+AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CPPFLAGS += -DPREFIX='"${prefix}"'
 AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
 AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
 AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
index 2e2d821..1b9c374 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <netdb.h>
 
 #include <pthread.h>
@@ -191,7 +192,7 @@ static int change_basedir (const char *orig_dir)
                                sstrerror (errno, errbuf, sizeof (errbuf)));
                return (-1);
        }
-       
+
        dirlen = strlen (dir);
        while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
                dir[--dirlen] = '\0';
@@ -270,7 +271,7 @@ static void update_kstat (void)
 static void exit_usage (int status)
 {
        printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
-                       
+
                        "Available options:\n"
                        "  General:\n"
                        "    -C <file>       Configuration file.\n"
@@ -307,7 +308,11 @@ static int do_init (void)
 #endif
 
 #if HAVE_LIBSTATGRAB
-       if (sg_init ())
+       if (sg_init (
+# if HAVE_LIBSTATGRAB_0_90
+                   0
+# endif
+                   ))
        {
                ERROR ("sg_init: %s", sg_str_error (sg_get_error ()));
                return (-1);
@@ -409,6 +414,74 @@ static int pidfile_remove (void)
 } /* static int pidfile_remove (const char *file) */
 #endif /* COLLECT_DAEMON */
 
+#ifdef KERNEL_LINUX
+int notify_upstart (void)
+{
+    const char  *upstart_job = getenv("UPSTART_JOB");
+
+    if (upstart_job == NULL)
+        return 0;
+
+    if (strcmp(upstart_job, "collectd") != 0)
+        return 0;
+
+    WARNING ("supervised by upstart, will stop to signal readyness");
+    raise(SIGSTOP);
+    unsetenv("UPSTART_JOB");
+
+    return 1;
+}
+
+int notify_systemd (void)
+{
+    int                  fd = -1;
+    const char          *notifysocket = getenv("NOTIFY_SOCKET");
+    struct sockaddr_un   su;
+    struct iovec         iov;
+    struct msghdr        hdr;
+
+    if (notifysocket == NULL)
+        return 0;
+
+    if ((strchr("@/", notifysocket[0])) == NULL ||
+        strlen(notifysocket) < 2)
+        return 0;
+
+    WARNING ("supervised by systemd, will signal readyness");
+    if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+        WARNING ("cannot contact systemd socket %s", notifysocket);
+        return 0;
+    }
+
+    bzero(&su, sizeof(su));
+    su.sun_family = AF_UNIX;
+    sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
+
+    if (notifysocket[0] == '@')
+        su.sun_path[0] = 0;
+
+    bzero(&iov, sizeof(iov));
+    iov.iov_base = "READY=1";
+    iov.iov_len = strlen("READY=1");
+
+    bzero(&hdr, sizeof(hdr));
+    hdr.msg_name = &su;
+    hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
+        strlen(notifysocket);
+    hdr.msg_iov = &iov;
+    hdr.msg_iovlen = 1;
+
+    unsetenv("NOTIFY_SOCKET");
+    if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
+        WARNING ("cannot send notification to systemd");
+        close(fd);
+        return 0;
+    }
+    close(fd);
+    return 1;
+}
+#endif /* KERNEL_LINUX */
+
 int main (int argc, char **argv)
 {
        struct sigaction sig_int_action;
@@ -525,7 +598,15 @@ int main (int argc, char **argv)
        sig_chld_action.sa_handler = SIG_IGN;
        sigaction (SIGCHLD, &sig_chld_action, NULL);
 
-       if (daemonize)
+    /*
+     * Only daemonize if we're not being supervised
+     * by upstart or systemd (when using Linux).
+     */
+       if (daemonize
+#ifdef KERNEL_LINUX
+           && notify_upstart() == 0 && notify_systemd() == 0
+#endif
+       )
        {
                if ((pid = fork ()) == -1)
                {
index cd99204..97b794f 100644 (file)
 #include "utils_time.h"
 #include "utils_random.h"
 
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
 #include <ltdl.h>
 
 /*
index dfc608e..d773e09 100644 (file)
 #include "meta_data.h"
 #include "utils_time.h"
 
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+
 #define PLUGIN_FLAGS_GLOBAL 0x0001
 
 #define DATA_MAX_NAME_LEN 64
index f702311..8830403 100644 (file)
@@ -859,7 +859,12 @@ static int disk_read (void)
 
 #elif defined(HAVE_LIBSTATGRAB)
        sg_disk_io_stats *ds;
-       int disks, counter;
+# if HAVE_LIBSTATGRAB_0_90
+       size_t disks;
+# else
+       int disks;
+#endif
+       int counter;
        char name[DATA_MAX_NAME_LEN];
        
        if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
index 00fcff1..fd75dc9 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
@@ -21,6 +21,7 @@
  *   Mirko Buffoni <briareos at eswat.org>
  **/
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE
 
 #include "collectd.h"
index cb6844b..a2b0915 100644 (file)
@@ -23,6 +23,7 @@
  *   Peter Holik <peter at holik.at>
  **/
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE /* For setgroups */
 
 #include "collectd.h"
index 2fc3152..5abee2f 100644 (file)
@@ -11,7 +11,10 @@ nodist_pkgconfig_DATA = libcollectdclient.pc
 BUILT_SOURCES = collectd/lcc_features.h
 
 libcollectdclient_la_SOURCES = client.c network.c network_buffer.c
-libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd -I$(top_srcdir)/src/daemon
+libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) \
+                               -I$(top_srcdir)/src/libcollectdclient/collectd \
+                               -I$(top_builddir)/src/libcollectdclient/collectd \
+                               -I$(top_srcdir)/src/daemon
 libcollectdclient_la_LDFLAGS = -version-info 1:0:0
 libcollectdclient_la_LIBADD = 
 if BUILD_WITH_LIBGCRYPT
index 7b06620..61c7c22 100644 (file)
@@ -54,7 +54,9 @@
 /* Re enable deprecation warnings */
 #  pragma GCC diagnostic warning "-Wdeprecated-declarations"
 # endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
 #endif
 
 #include "collectd/network_buffer.h"
@@ -131,7 +133,9 @@ static _Bool have_gcrypt (void) /* {{{ */
   need_init = 0;
 
 #if HAVE_LIBGCRYPT
+# if GCRYPT_VERSION_NUMBER < 0x010600
   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
 
   if (!gcry_check_version (GCRYPT_VERSION))
     return (0);
index b6d757e..cb3754d 100644 (file)
@@ -65,9 +65,20 @@ BOOL_TRUE (true|yes|on)
 BOOL_FALSE (false|no|off)
 COMMENT #.*
 PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
+
 IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
 IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
 
+/* IPv6 address according to http://www.ietf.org/rfc/rfc2373.txt
+ * This supports embedded IPv4 addresses as well but does not strictly check
+ * for the right prefix (::0:<v4> or ::FFFF:<v4>) because there are too many
+ * ways to correctly represent the zero bytes. It's up to the user to check
+ * for valid addresses. */
+HEX16 ([0-9A-Fa-f]{1,4})
+V6_PART ({HEX16}:{HEX16}|{IPV4_ADDR})
+IPV6_BASE ({HEX16}:){6}{V6_PART}|::({HEX16}:){5}{V6_PART}|({HEX16})?::({HEX16}:){4}{V6_PART}|(({HEX16}:){0,1}{HEX16})?::({HEX16}:){3}{V6_PART}|(({HEX16}:){0,2}{HEX16})?::({HEX16}:){2}{V6_PART}|(({HEX16}:){0,3}{HEX16})?::{HEX16}:{V6_PART}|(({HEX16}:){0,4}{HEX16})?::{V6_PART}|(({HEX16}:){0,5}{HEX16})?::{HEX16}|(({HEX16}:){0,6}{HEX16})?::
+IPV6_ADDR ({IPV6_BASE})|(\[{IPV6_BASE}\](:{PORT})?)
+
 %%
 {WHITE_SPACE}          |
 {COMMENT}              {/* ignore */}
@@ -82,6 +93,7 @@ IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
 {BOOL_FALSE}           {yylval.boolean = 0; return (BFALSE);}
 
 {IPV4_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
+{IPV6_ADDR}            {yylval.string = yytext; return (UNQUOTED_STRING);}
 
 {NUMBER}               {yylval.number = strtod (yytext, NULL); return (NUMBER);}
 
index f631476..18b5f8e 100644 (file)
@@ -23,6 +23,7 @@
  *   Vedran Bartonicek <vbartoni at gmail.com>
  **/
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE
 
 #include "collectd.h"
index 82d7f6f..9e24542 100644 (file)
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -125,10 +125,6 @@ static void vg_read(vg_t vg, char const *vg_name)
     }
 
     dm_list_iterate_items(lvl, lvs) {
-         lvm_submit(vg_name, lvm_lv_get_name(lvl->lv), lvm_lv_get_size(lvl->lv));
-    }
-
-    dm_list_iterate_items(lvl, lvs) {
         name = lvm_lv_get_name(lvl->lv);
         attrs = get_lv_property_string(lvl->lv, "lv_attr");
         size = lvm_lv_get_size(lvl->lv);
index 0f5e1a0..7e7fd8e 100644 (file)
@@ -30,6 +30,9 @@
 #ifdef HAVE_SYS_SYSCTL_H
 # include <sys/sysctl.h>
 #endif
+#ifdef HAVE_SYS_VMMETER_H
+# include <sys/vmmeter.h>
+#endif
 
 #ifdef HAVE_MACH_KERN_RETURN_H
 # include <mach/kern_return.h>
index 7d5eddd..f5ae1ad 100644 (file)
@@ -688,7 +688,7 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Innodb_buffer_pool_pages_dirty") == 0)
                                gauge_submit ("mysql_bpool_pages", "dirty", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_flushed") == 0)
-                               counter_submit ("mysql_bpool_counters", "flushed", val, db);
+                               counter_submit ("mysql_bpool_pages", "flushed", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_free") == 0)
                                gauge_submit ("mysql_bpool_pages", "free", val, db);
                        else if (strcmp (key, "Innodb_buffer_pool_pages_misc") == 0)
@@ -716,7 +716,7 @@ static int mysql_read (user_data_t *ud)
                        else if (strcmp (key, "Innodb_data_reads") == 0)
                                counter_submit ("mysql_innodb_data", "reads", val, db);
                        else if (strcmp (key, "Innodb_data_writes") == 0)
-                               counter_submit ("mysql_bpool_counters", "writes", val, db);
+                               counter_submit ("mysql_innodb_data", "writes", val, db);
                        else if (strcmp (key, "Innodb_data_written") == 0)
                                counter_submit ("mysql_innodb_data", "written", val, db);
 
index bf0b2bc..551bd5c 100644 (file)
@@ -22,6 +22,7 @@
  *   Aman Gupta <aman at tmm1.net>
  **/
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE /* For struct ip_mreq */
 
 #include "collectd.h"
@@ -76,7 +77,9 @@
 /* Re enable deprecation warnings */
 #  pragma GCC diagnostic warning "-Wdeprecated-declarations"
 # endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
 #endif
 
 #ifndef IPV6_ADD_MEMBERSHIP
@@ -510,7 +513,9 @@ static void network_init_gcrypt (void) /* {{{ */
   * above doesn't count, as it doesn't implicitly initalize Libgcrypt.
   *
   * tl;dr: keep all these gry_* statements in this exact order please. */
+# if GCRYPT_VERSION_NUMBER < 0x010600
   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
   gcry_check_version (NULL);
   gcry_control (GCRYCTL_INIT_SECMEM, 32768);
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
@@ -3002,7 +3007,7 @@ static int network_config_set_ttl (const oconfig_item_t *ci) /* {{{ */
     network_config_ttl = tmp;
   else {
     WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
-    return (-1);    
+    return (-1);
   }
 
   return (0);
index 6bed82c..15b12f9 100644 (file)
@@ -24,6 +24,7 @@
  *   Florian octo Forster <octo at collectd.org>
  **/
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE /* For NI_MAXHOST */
 
 #include "collectd.h"
@@ -486,7 +487,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
                poll_s.fd      = sd;
                poll_s.events  = POLLIN | POLLPRI;
                poll_s.revents = 0;
-               
+
                DEBUG ("Polling for %ims", timeout);
                status = poll (&poll_s, 1, timeout);
 
@@ -526,7 +527,7 @@ static int ntpd_receive_response (int *res_items, int *res_size,
 
                DEBUG ("recv'd %i bytes", status);
 
-               /* 
+               /*
                 * Do some sanity checks first
                 */
                if (status < RESP_HEADER_SIZE)
@@ -736,7 +737,7 @@ static int ntpd_send_request (int req_code, int req_items, int req_size, char *r
 
        req.err_nitems   = ERR_NITEMS (0, req_items);
        req.mbz_itemsize = MBZ_ITEMSIZE (req_size);
-       
+
        if (req_data != NULL)
                memcpy ((void *) req.data, (const void *) req_data, req_data_len);
 
diff --git a/src/openldap.c b/src/openldap.c
new file mode 100644 (file)
index 0000000..212310b
--- /dev/null
@@ -0,0 +1,682 @@
+/**
+ * collectd - src/openldap.c
+ * Copyright (C) 2011       Kimo Rosenbaum
+ * Copyright (C) 2014       Marc Fournier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Kimo Rosenbaum <kimor79 at yahoo.com>
+ *   Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <lber.h>
+#include <ldap.h>
+
+struct ldap_s /* {{{ */
+{
+       char *name;
+
+       char *cacert;
+       char *host;
+       int   state;
+       _Bool starttls;
+       int   timeout;
+       char *url;
+       _Bool verifyhost;
+       int   version;
+
+       LDAP *ld;
+};
+typedef struct ldap_s ldap_t; /* }}} */
+
+static void ldap_free (ldap_t *st) /* {{{ */
+{
+       if (st == NULL)
+               return;
+
+       sfree (st->cacert);
+       sfree (st->host);
+       sfree (st->name);
+       sfree (st->url);
+       if (st->ld)
+               ldap_memfree (st->ld);
+       sfree (st);
+} /* }}} void ldap_free */
+
+/* initialize ldap for each host */
+static int ldap_init_host (ldap_t *st) /* {{{ */
+{
+       LDAP *ld;
+       int rc;
+       rc = ldap_initialize (&ld, st->url);
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: ldap_initialize failed: %s",
+                       ldap_err2string (rc));
+               st->state = 0;
+               ldap_unbind_ext_s (ld, NULL, NULL);
+               return (-1);
+       }
+
+       st->ld = ld;
+
+       ldap_set_option (st->ld, LDAP_OPT_PROTOCOL_VERSION, &st->version);
+
+       ldap_set_option (st->ld, LDAP_OPT_TIMEOUT,
+               &(const struct timeval){st->timeout, 0});
+
+       if (st->cacert != NULL)
+               ldap_set_option (st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert);
+
+       if (st->verifyhost == 0)
+       {
+               int never = LDAP_OPT_X_TLS_NEVER;
+               ldap_set_option (st->ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &never);
+       }
+
+       if (st->starttls != 0)
+       {
+               rc = ldap_start_tls_s (ld, NULL, NULL);
+               if (rc != LDAP_SUCCESS)
+               {
+                       ERROR ("openldap plugin: Failed to start tls on %s: %s",
+                                       st->url, ldap_err2string (rc));
+                       st->state = 0;
+                       ldap_unbind_ext_s (st->ld, NULL, NULL);
+                       return (-1);
+               }
+       }
+
+       struct berval cred;
+       cred.bv_val = "";
+       cred.bv_len = 0;
+
+       rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: Failed to bind to %s: %s",
+                               st->url, ldap_err2string (rc));
+               st->state = 0;
+               ldap_unbind_ext_s (st->ld, NULL, NULL);
+               return (-1);
+       }
+       else
+       {
+               DEBUG ("openldap plugin: Successfully connected to %s",
+                               st->url);
+               st->state = 1;
+               return (0);
+       }
+} /* }}} static ldap_init_host */
+
+static void ldap_submit_value (const char *type, const char *type_instance, /* {{{ */
+               value_t value, ldap_t *st)
+{
+       value_list_t vl = VALUE_LIST_INIT;
+
+       vl.values     = &value;
+       vl.values_len = 1;
+
+       if ((st->host == NULL)
+                       || (strcmp ("", st->host) == 0)
+                       || (strcmp ("localhost", st->host) == 0))
+       {
+               sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       }
+       else
+       {
+               sstrncpy (vl.host, st->host, sizeof (vl.host));
+       }
+
+       sstrncpy (vl.plugin, "openldap", sizeof (vl.plugin));
+       if (st->name != NULL)
+               sstrncpy (vl.plugin_instance, st->name,
+                               sizeof (vl.plugin_instance));
+
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       if (type_instance != NULL)
+               sstrncpy (vl.type_instance, type_instance,
+                               sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+} /* }}} void ldap_submit_value */
+
+static void ldap_submit_derive (const char *type, const char *type_instance, /* {{{ */
+               derive_t d, ldap_t *st)
+{
+       value_t v;
+       v.derive = d;
+       ldap_submit_value (type, type_instance, v, st);
+} /* }}} void ldap_submit_derive */
+
+static void ldap_submit_gauge (const char *type, const char *type_instance, /* {{{ */
+               gauge_t g, ldap_t *st)
+{
+       value_t v;
+       v.gauge = g;
+       ldap_submit_value (type, type_instance, v, st);
+} /* }}} void ldap_submit_gauge */
+
+static int ldap_read_host (user_data_t *ud) /* {{{ */
+{
+       ldap_t *st;
+       LDAPMessage *e, *result;
+       char *dn;
+       int rc;
+       int status;
+
+       char *attrs[9] = { "monitorCounter",
+                               "monitorOpCompleted",
+                               "monitorOpInitiated",
+                               "monitoredInfo",
+                               "olmBDBEntryCache",
+                               "olmBDBDNCache",
+                               "olmBDBIDLCache",
+                               "namingContexts",
+                               NULL };
+
+       if ((ud == NULL) || (ud->data == NULL))
+       {
+               ERROR ("openldap plugin: ldap_read_host: Invalid user data.");
+               return (-1);
+       }
+
+       st = (ldap_t *) ud->data;
+
+       status = ldap_init_host (st);
+       if (status != 0)
+               return (-1);
+
+       rc = ldap_search_ext_s (st->ld, "cn=Monitor", LDAP_SCOPE_SUBTREE,
+               "(|(!(cn=* *))(cn=Database*))", attrs, 0,
+               NULL, NULL, NULL, 0, &result);
+
+       if (rc != LDAP_SUCCESS)
+       {
+               ERROR ("openldap plugin: Failed to execute search: %s",
+                               ldap_err2string (rc));
+               ldap_msgfree (result);
+               ldap_unbind_ext_s (st->ld, NULL, NULL);
+               return (-1);
+       }
+
+       for (e = ldap_first_entry (st->ld, result); e != NULL;
+               e = ldap_next_entry (st->ld, e))
+       {
+               if ((dn = ldap_get_dn (st->ld, e)) != NULL)
+               {
+                       unsigned long long counter = 0;
+                       unsigned long long opc = 0;
+                       unsigned long long opi = 0;
+                       unsigned long long info = 0;
+
+                       struct berval counter_data;
+                       struct berval opc_data;
+                       struct berval opi_data;
+                       struct berval info_data;
+                       struct berval olmbdb_data;
+                       struct berval nc_data;
+
+                       struct berval **counter_list;
+                       struct berval **opc_list;
+                       struct berval **opi_list;
+                       struct berval **info_list;
+                       struct berval **olmbdb_list;
+                       struct berval **nc_list;
+
+                       if ((counter_list = ldap_get_values_len (st->ld, e,
+                               "monitorCounter")) != NULL)
+                       {
+                               counter_data = *counter_list[0];
+                               counter = atoll (counter_data.bv_val);
+                       }
+
+                       if ((opc_list = ldap_get_values_len (st->ld, e,
+                               "monitorOpCompleted")) != NULL)
+                       {
+                               opc_data = *opc_list[0];
+                               opc = atoll (opc_data.bv_val);
+                       }
+
+                       if ((opi_list = ldap_get_values_len (st->ld, e,
+                               "monitorOpInitiated")) != NULL)
+                       {
+                               opi_data = *opi_list[0];
+                               opi = atoll (opi_data.bv_val);
+                       }
+
+                       if ((info_list = ldap_get_values_len (st->ld, e,
+                               "monitoredInfo")) != NULL)
+                       {
+                               info_data = *info_list[0];
+                               info = atoll (info_data.bv_val);
+                       }
+
+                       if (strcmp (dn, "cn=Total,cn=Connections,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("total_connections", NULL,
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Current,cn=Connections,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("current_connections", NULL,
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Operations,cn=Monitor") == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Bind,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "bind-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "bind-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=UnBind,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "unbind-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "unbind-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Search,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "search-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "search-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Compare,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "compare-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "compare-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Modify,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "modify-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "modify-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Modrdn,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "modrdn-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "modrdn-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Add,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "add-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "add-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Delete,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "delete-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "delete-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Abandon,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "abandon-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "abandon-initiated", opi, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Extended,cn=Operations,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("operations",
+                                       "extended-completed", opc, st);
+                               ldap_submit_derive ("operations",
+                                       "extended-initiated", opi, st);
+                       }
+                       else if ((strncmp (dn, "cn=Database", 11) == 0)
+                               && ((nc_list = ldap_get_values_len
+                                               (st->ld, e, "namingContexts")) != NULL))
+                       {
+                               nc_data = *nc_list[0];
+                               char typeinst[DATA_MAX_NAME_LEN];
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBEntryCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       ssnprintf (typeinst, sizeof (typeinst),
+                                               "bdbentrycache-%s", nc_data.bv_val);
+                                       ldap_submit_gauge ("cache_size", typeinst,
+                                               atoll (olmbdb_data.bv_val), st);
+                                       ldap_value_free_len (olmbdb_list);
+                               }
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBDNCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       ssnprintf (typeinst, sizeof (typeinst),
+                                               "bdbdncache-%s", nc_data.bv_val);
+                                       ldap_submit_gauge ("cache_size", typeinst,
+                                               atoll (olmbdb_data.bv_val), st);
+                                       ldap_value_free_len (olmbdb_list);
+                               }
+
+                               if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+                                       "olmBDBIDLCache")) != NULL)
+                               {
+                                       olmbdb_data = *olmbdb_list[0];
+                                       ssnprintf (typeinst, sizeof (typeinst),
+                                               "bdbidlcache-%s", nc_data.bv_val);
+                                       ldap_submit_gauge ("cache_size", typeinst,
+                                               atoll (olmbdb_data.bv_val), st);
+                                       ldap_value_free_len (olmbdb_list);
+                               }
+
+                               ldap_value_free_len (nc_list);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Bytes,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "statistics-bytes",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=PDU,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "statistics-pdu",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Entries,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "statistics-entries",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Referrals,cn=Statistics,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "statistics-referrals",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Open,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("threads", "threads-open",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Starting,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("threads", "threads-starting",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Active,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("threads", "threads-active",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Pending,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("threads", "threads-pending",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Backload,cn=Threads,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_gauge ("threads", "threads-backload",
+                                       info, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Read,cn=Waiters,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "waiters-read",
+                                       counter, st);
+                       }
+                       else if (strcmp (dn,
+                                       "cn=Write,cn=Waiters,cn=Monitor")
+                                       == 0)
+                       {
+                               ldap_submit_derive ("derive", "waiters-write",
+                                       counter, st);
+                       }
+
+                       ldap_value_free_len (counter_list);
+                       ldap_value_free_len (opc_list);
+                       ldap_value_free_len (opi_list);
+                       ldap_value_free_len (info_list);
+               }
+
+               ldap_memfree (dn);
+       }
+
+       ldap_msgfree (result);
+       ldap_unbind_ext_s (st->ld, NULL, NULL);
+       return (0);
+} /* }}} int ldap_read_host */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin ldap>
+ *   <Instance "plugin_instance1">
+ *     URL "ldap://localhost"
+ *     ...
+ *   </Instance>
+ * </Plugin>
+ */
+
+static int ldap_config_add (oconfig_item_t *ci) /* {{{ */
+{
+       ldap_t *st;
+       int i;
+       int status;
+
+       st = malloc (sizeof (*st));
+       if (st == NULL)
+       {
+               ERROR ("openldap plugin: malloc failed.");
+               return (-1);
+       }
+       memset (st, 0, sizeof (*st));
+
+       status = cf_util_get_string (ci, &st->name);
+       if (status != 0)
+       {
+               sfree (st);
+               return (status);
+       }
+
+       st->starttls = 0;
+       st->timeout = -1;
+       st->verifyhost = 1;
+       st->version = LDAP_VERSION3;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("CACert", child->key) == 0)
+                       status = cf_util_get_string (child, &st->cacert);
+               else if (strcasecmp ("StartTLS", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->starttls);
+               else if (strcasecmp ("Timeout", child->key) == 0)
+                       status = cf_util_get_int (child, &st->timeout);
+               else if (strcasecmp ("URL", child->key) == 0)
+                       status = cf_util_get_string (child, &st->url);
+               else if (strcasecmp ("VerifyHost", child->key) == 0)
+                       status = cf_util_get_boolean (child, &st->verifyhost);
+               else if (strcasecmp ("Version", child->key) == 0)
+                       status = cf_util_get_int (child, &st->version);
+               else
+               {
+                       WARNING ("openldap plugin: Option `%s' not allowed here.",
+                                       child->key);
+                       status = -1;
+               }
+
+               if (status != 0)
+                       break;
+       }
+
+       /* Check if struct is complete.. */
+       if ((status == 0) && (st->url == NULL))
+       {
+               ERROR ("openldap plugin: Instance `%s': "
+                               "No URL has been configured.",
+                               st->name);
+               status = -1;
+       }
+
+       /* Check if URL is valid */
+       if ((status == 0) && (st->url != NULL))
+       {
+               LDAPURLDesc *ludpp;
+               int rc;
+
+               if ((rc = ldap_url_parse (st->url, &ludpp)) != 0)
+               {
+                       ERROR ("openldap plugin: Instance `%s': "
+                               "Invalid URL: `%s'",
+                               st->name, st->url);
+                       status = -1;
+               }
+               else
+               {
+                       st->host = strdup (ludpp->lud_host);
+               }
+
+               ldap_free_urldesc (ludpp);
+       }
+
+       if (status == 0)
+       {
+               user_data_t ud;
+               char callback_name[3*DATA_MAX_NAME_LEN];
+
+               memset (&ud, 0, sizeof (ud));
+               ud.data = st;
+
+               memset (callback_name, 0, sizeof (callback_name));
+               ssnprintf (callback_name, sizeof (callback_name),
+                               "openldap/%s/%s",
+                               (st->host != NULL) ? st->host : hostname_g,
+                               (st->name != NULL) ? st->name : "default"),
+
+               status = plugin_register_complex_read (/* group = */ NULL,
+                               /* name      = */ callback_name,
+                               /* callback  = */ ldap_read_host,
+                               /* interval  = */ NULL,
+                               /* user_data = */ &ud);
+       }
+
+       if (status != 0)
+       {
+               ldap_free (st);
+               return (-1);
+       }
+
+       return (0);
+} /* }}} int ldap_config_add */
+
+static int ldap_config (oconfig_item_t *ci) /* {{{ */
+{
+       int i;
+       int status = 0;
+
+       for (i = 0; i < ci->children_num; i++)
+       {
+               oconfig_item_t *child = ci->children + i;
+
+               if (strcasecmp ("Instance", child->key) == 0)
+                       ldap_config_add (child);
+               else
+                       WARNING ("openldap plugin: The configuration option "
+                                       "\"%s\" is not allowed here. Did you "
+                                       "forget to add an <Instance /> block "
+                                       "around the configuration?",
+                                       child->key);
+       } /* for (ci->children) */
+
+       return (status);
+} /* }}} int ldap_config */
+
+/* }}} End of configuration handling functions */
+
+static int ldap_init (void) /* {{{ */
+{
+       /* Initialize LDAP library while still single-threaded as recommended in
+        * ldap_initialize(3) */
+       int debug_level;
+       ldap_get_option (NULL, LDAP_OPT_DEBUG_LEVEL, &debug_level);
+       return (0);
+} /* }}} int ldap_init */
+
+void module_register (void) /* {{{ */
+{
+       plugin_register_complex_config ("openldap", ldap_config);
+       plugin_register_init ("openldap", ldap_init);
+} /* }}} void module_register */
index aa47f33..68f30a5 100644 (file)
 #  endif
 /* #endif KERNEL_LINUX */
 
-#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
+#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
 #  include <kvm.h>
 #  include <sys/param.h>
 #  include <sys/sysctl.h>
 #  include <sys/user.h>
 #  include <sys/proc.h>
-/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
+/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD) */
 
 #elif HAVE_PROCINFO_H
 #  include <procinfo.h>
@@ -214,9 +214,9 @@ static mach_msg_type_number_t     pset_list_len;
 static long pagesize_g;
 /* #endif KERNEL_LINUX */
 
-#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
+#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
 static int pagesize;
-/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
+/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD) */
 
 #elif HAVE_PROCINFO_H
 static  struct procentry64 procentry[MAXPROCENTRY];
@@ -623,9 +623,9 @@ static int ps_init (void)
                        pagesize_g, CONFIG_HZ);
 /* #endif KERNEL_LINUX */
 
-#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
+#elif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD)
        pagesize = getpagesize();
-/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
+/* #endif HAVE_LIBKVM_GETPROCS && (HAVE_STRUCT_KINFO_PROC_FREEBSD || HAVE_STRUCT_KINFO_PROC_OPENBSD) */
 
 #elif HAVE_PROCINFO_H
        pagesize = getpagesize();
@@ -1925,6 +1925,138 @@ static int ps_read (void)
                ps_submit_proc_list (ps_ptr);
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
+#elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD
+       int running  = 0;
+       int sleeping = 0;
+       int zombies  = 0;
+       int stopped  = 0;
+       int onproc   = 0;
+       int idle     = 0;
+       int dead     = 0;
+
+       kvm_t *kd;
+       char errbuf[1024];
+       struct kinfo_proc *procs;          /* array of processes */
+       struct kinfo_proc *proc_ptr = NULL;
+       int count;                         /* returns number of processes */
+       int i;
+
+       procstat_t *ps_ptr;
+       procstat_entry_t pse;
+
+       ps_list_reset ();
+
+       /* Open the kvm interface, get a descriptor */
+       kd = kvm_open (NULL, NULL, NULL, 0, errbuf);
+       if (kd == NULL)
+       {
+               ERROR ("processes plugin: Cannot open kvm interface: %s",
+                               errbuf);
+               return (0);
+       }
+
+       /* Get the list of processes. */
+       procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count);
+       if (procs == NULL)
+       {
+               ERROR ("processes plugin: Cannot get kvm processes list: %s",
+                               kvm_geterr(kd));
+               kvm_close (kd);
+               return (0);
+       }
+
+       /* Iterate through the processes in kinfo_proc */
+       for (i = 0; i < count; i++)
+       {
+               /* Create only one process list entry per _process_, i.e.
+                * filter out threads (duplicate PID entries). */
+               if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid))
+               {
+                       char cmdline[CMDLINE_BUFFER_SIZE] = "";
+                       _Bool have_cmdline = 0;
+
+                       proc_ptr = &(procs[i]);
+                       /* Don't probe zombie processes  */
+                       if (!P_ZOMBIE(proc_ptr))
+                       {
+                               char **argv;
+                               int argc;
+                               int status;
+
+                               /* retrieve the arguments */
+                               argv = kvm_getargv (kd, proc_ptr, /* nchr = */ 0);
+                               argc = 0;
+                               if ((argv != NULL) && (argv[0] != NULL))
+                               {
+                                       while (argv[argc] != NULL)
+                                               argc++;
+
+                                       status = strjoin (cmdline, sizeof (cmdline), argv, argc, " ");
+                                       if (status < 0)
+                                               WARNING ("processes plugin: Command line did not fit into buffer.");
+                                       else
+                                               have_cmdline = 1;
+                               }
+                       } /* if (process has argument list) */
+
+                       pse.id       = procs[i].p_pid;
+                       pse.age      = 0;
+
+                       pse.num_proc = 1;
+                       pse.num_lwp  = 1; /* XXX: accumulate p_tid values for a single p_pid ? */
+
+                       pse.vmem_rss = procs[i].p_vm_rssize * pagesize;
+                       pse.vmem_data = procs[i].p_vm_dsize * pagesize;
+                       pse.vmem_code = procs[i].p_vm_tsize * pagesize;
+                       pse.stack_size = procs[i].p_vm_ssize * pagesize;
+                       pse.vmem_size = pse.stack_size + pse.vmem_code + pse.vmem_data;
+                       pse.vmem_minflt = 0;
+                       pse.vmem_minflt_counter = procs[i].p_uru_minflt;
+                       pse.vmem_majflt = 0;
+                       pse.vmem_majflt_counter = procs[i].p_uru_majflt;
+
+                       pse.cpu_user = 0;
+                       pse.cpu_system = 0;
+                       pse.cpu_user_counter = procs[i].p_uutime_usec +
+                                               (1000000lu * procs[i].p_uutime_sec);
+                       pse.cpu_system_counter = procs[i].p_ustime_usec +
+                                               (1000000lu * procs[i].p_ustime_sec);
+
+                       /* no I/O data */
+                       pse.io_rchar = -1;
+                       pse.io_wchar = -1;
+                       pse.io_syscr = -1;
+                       pse.io_syscw = -1;
+
+                       ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
+               } /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
+
+               switch (procs[i].p_stat)
+               {
+                       case SSTOP:     stopped++;      break;
+                       case SSLEEP:    sleeping++;     break;
+                       case SRUN:      running++;      break;
+                       case SIDL:      idle++;         break;
+                       case SONPROC:   onproc++;       break;
+                       case SDEAD:     dead++;         break;
+                       case SZOMB:     zombies++;      break;
+               }
+       }
+
+       kvm_close(kd);
+
+       ps_submit_state ("running",  running);
+       ps_submit_state ("sleeping", sleeping);
+       ps_submit_state ("zombies",  zombies);
+       ps_submit_state ("stopped",  stopped);
+       ps_submit_state ("onproc",   onproc);
+       ps_submit_state ("idle",     idle);
+       ps_submit_state ("dead",     dead);
+
+       for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
+               ps_submit_proc_list (ps_ptr);
+/* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_OPENBSD */
+
 #elif HAVE_PROCINFO_H
        /* AIX */
        int running  = 0;
index 81724c0..0fad6fa 100644 (file)
@@ -46,6 +46,19 @@ typedef struct cpy_callback_s {
 
 static char log_doc[] = "This function sends a string to all logging plugins.";
 
+static char get_ds_doc[] = "get_dataset(name) -> definition\n"
+               "\n"
+               "Returns the definition of a dataset specified by name.\n"
+               "\n"
+               "'name' is a string specifying the dataset to query.\n"
+               "'definition' is a list of 4-tuples. Every tuple represents a \n"
+               "    data source within the data set and its 4 values are the \n"
+               "    name, type, min and max value.\n"
+               "    'name' is a string.\n"
+               "    'type' is a string that is equal to either DS_TYPE_COUNTER,\n"
+               "        DS_TYPE_GAUGE, DS_TYPE_DERIVE or DS_TYPE_ABSOLUTE.\n"
+               "    'min' and 'max' are either a float or None.";
+
 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
                "\n"
                "Flushes the cache of another plugin.";
@@ -548,7 +561,39 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args
        return cpy_string_to_unicode_or_bytes(buf);
 }
 
-static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
+static PyObject *float_or_none(float number) {
+       if (isnan(number)) {
+               Py_RETURN_NONE;
+       }
+       return PyFloat_FromDouble(number);
+}
+
+static PyObject *cpy_get_dataset(PyObject *self, PyObject *args) {
+       int i;
+       char *name;
+       const data_set_t *ds;
+       PyObject *list, *tuple;
+
+       if (PyArg_ParseTuple(args, "et", NULL, &name) == 0) return NULL;
+       ds = plugin_get_ds(name);
+       PyMem_Free(name);
+       if (ds == NULL) {
+               PyErr_Format(PyExc_TypeError, "Dataset %s not found", name);
+               return NULL;
+       }
+       list = PyList_New(ds->ds_num); /* New reference. */
+       for (i = 0; i < ds->ds_num; ++i) {
+               tuple = PyTuple_New(4);
+               PyTuple_SET_ITEM(tuple, 0, cpy_string_to_unicode_or_bytes(ds->ds[i].name));
+               PyTuple_SET_ITEM(tuple, 1, cpy_string_to_unicode_or_bytes(DS_TYPE_TO_STRING(ds->ds[i].type)));
+               PyTuple_SET_ITEM(tuple, 2, float_or_none(ds->ds[i].min));
+               PyTuple_SET_ITEM(tuple, 3, float_or_none(ds->ds[i].max));
+               PyList_SET_ITEM(list, i, tuple);
+       }
+       return list;
+}
+
+static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
        int timeout = -1;
        char *plugin = NULL, *identifier = NULL;
        static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
@@ -817,6 +862,7 @@ static PyMethodDef cpy_methods[] = {
        {"notice", cpy_notice, METH_VARARGS, log_doc},
        {"warning", cpy_warning, METH_VARARGS, log_doc},
        {"error", cpy_error, METH_VARARGS, log_doc},
+       {"get_dataset", (PyCFunction) cpy_get_dataset, METH_VARARGS, get_ds_doc},
        {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
        {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
        {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
@@ -1041,6 +1087,10 @@ static int cpy_init_python() {
        PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
        PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
        PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
+       PyModule_AddStringConstant(module, "DS_TYPE_COUNTER", DS_TYPE_TO_STRING(DS_TYPE_COUNTER));
+       PyModule_AddStringConstant(module, "DS_TYPE_GAUGE", DS_TYPE_TO_STRING(DS_TYPE_GAUGE));
+       PyModule_AddStringConstant(module, "DS_TYPE_DERIVE", DS_TYPE_TO_STRING(DS_TYPE_DERIVE));
+       PyModule_AddStringConstant(module, "DS_TYPE_ABSOLUTE", DS_TYPE_TO_STRING(DS_TYPE_ABSOLUTE));
        return 0;
 }
 
index 92be18f..f5bb304 100644 (file)
@@ -26,7 +26,8 @@
 #include "configfile.h"
 
 #include <pthread.h>
-#include <credis.h>
+#include <sys/time.h>
+#include <hiredis/hiredis.h>
 
 #ifndef HOST_NAME_MAX
 # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
@@ -38,6 +39,7 @@
 #define REDIS_DEF_TIMEOUT 2000
 #define MAX_REDIS_NODE_NAME 64
 #define MAX_REDIS_PASSWD_LENGTH 512
+#define MAX_REDIS_VAL_SIZE 256
 
 /* Redis plugin configuration example:
  *
@@ -45,7 +47,8 @@
  *   <Node "mynode">
  *     Host "localhost"
  *     Port "6379"
- *     Timeout 2000
+ *     Timeout 2
+ *     Password "foobar"
  *   </Node>
  * </Plugin>
  */
@@ -58,7 +61,7 @@ struct redis_node_s
   char host[HOST_NAME_MAX];
   char passwd[MAX_REDIS_PASSWD_LENGTH];
   int port;
-  int timeout;
+  struct timeval timeout;
 
   redis_node_t *next;
 };
@@ -107,16 +110,18 @@ static int redis_node_add (const redis_node_t *rn) /* {{{ */
   return (0);
 } /* }}} */
 
+
 static int redis_config_node (oconfig_item_t *ci) /* {{{ */
 {
   redis_node_t rn;
   int i;
   int status;
+  int timeout;
 
   memset (&rn, 0, sizeof (rn));
   sstrncpy (rn.host, REDIS_DEF_HOST, sizeof (rn.host));
   rn.port = REDIS_DEF_PORT;
-  rn.timeout = REDIS_DEF_TIMEOUT;
+  rn.timeout.tv_usec = REDIS_DEF_TIMEOUT;
 
   status = cf_util_get_string_buffer (ci, rn.name, sizeof (rn.name));
   if (status != 0)
@@ -138,7 +143,10 @@ static int redis_config_node (oconfig_item_t *ci) /* {{{ */
       }
     }
     else if (strcasecmp ("Timeout", option->key) == 0)
-      status = cf_util_get_int (option, &rn.timeout);
+    {
+      status = cf_util_get_int (option, &timeout);
+      if (status == 0) rn.timeout.tv_usec = timeout;
+    }
     else if (strcasecmp ("Password", option->key) == 0)
       status = cf_util_get_string_buffer (option, rn.passwd, sizeof (rn.passwd));
     else
@@ -180,39 +188,14 @@ static int redis_config (oconfig_item_t *ci) /* {{{ */
 } /* }}} */
 
   __attribute__ ((nonnull(2)))
-static void redis_submit_g (char *plugin_instance,
-    const char *type, const char *type_instance,
-    gauge_t value) /* {{{ */
-{
-  value_t values[1];
-  value_list_t vl = VALUE_LIST_INIT;
-
-  values[0].gauge = value;
-
-  vl.values = values;
-  vl.values_len = 1;
-  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
-  sstrncpy (vl.plugin, "redis", sizeof (vl.plugin));
-  if (plugin_instance != NULL)
-    sstrncpy (vl.plugin_instance, plugin_instance,
-        sizeof (vl.plugin_instance));
-  sstrncpy (vl.type, type, sizeof (vl.type));
-  if (type_instance != NULL)
-    sstrncpy (vl.type_instance, type_instance,
-        sizeof (vl.type_instance));
-
-  plugin_dispatch_values (&vl);
-} /* }}} */
-
-  __attribute__ ((nonnull(2)))
-static void redis_submit_d (char *plugin_instance,
+static void redis_submit (char *plugin_instance,
     const char *type, const char *type_instance,
-    derive_t value) /* {{{ */
+    value_t value) /* {{{ */
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
 
-  values[0].derive = value;
+  values[0] = value;
 
   vl.values = values;
   vl.values_len = 1;
@@ -231,8 +214,14 @@ static void redis_submit_d (char *plugin_instance,
 
 static int redis_init (void) /* {{{ */
 {
-  redis_node_t rn = { "default", REDIS_DEF_HOST, REDIS_DEF_PASSWD,
-    REDIS_DEF_PORT, REDIS_DEF_TIMEOUT, /* next = */ NULL };
+  redis_node_t rn = {
+    .name = "default",
+    .host = REDIS_DEF_HOST,
+    .port = REDIS_DEF_PORT,
+    .timeout.tv_sec = 0,
+    .timeout.tv_usec = REDIS_DEF_TIMEOUT,
+    .next = NULL
+};
 
   if (nodes_head == NULL)
     redis_node_add (&rn);
@@ -240,20 +229,45 @@ static int redis_init (void) /* {{{ */
   return (0);
 } /* }}} int redis_init */
 
+int redis_handle_info (char *node, char const *info_line, char const *type, char const *type_instance, char const *field_name, int ds_type) /* {{{ */
+{
+  char *str = strstr (info_line, field_name);
+  static char buf[MAX_REDIS_VAL_SIZE];
+  value_t val;
+  if (str)
+  {
+    int i;
+
+    str += strlen (field_name) + 1; /* also skip the ':' */
+    for(i=0;(*str && (isdigit(*str) || *str == '.'));i++,str++)
+      buf[i] = *str;
+    buf[i] ='\0';
+
+    if(parse_value (buf, &val, ds_type) == -1)
+    {
+      WARNING ("redis plugin: Unable to parse field `%s'.", field_name);
+      return (-1);
+    }
+
+    redis_submit (node, type, type_instance, val);
+    return (0);
+  }
+  return (-1);
+
+} /* }}} int redis_handle_info */
+
 static int redis_read (void) /* {{{ */
 {
   redis_node_t *rn;
 
   for (rn = nodes_head; rn != NULL; rn = rn->next)
   {
-    REDIS rh;
-    REDIS_INFO info;
-
-    int status;
+    redisContext *rh;
+    redisReply   *rr;
 
     DEBUG ("redis plugin: querying info from node `%s' (%s:%d).", rn->name, rn->host, rn->port);
 
-    rh = credis_connect (rn->host, rn->port, rn->timeout);
+    rh = redisConnectWithTimeout ((char *)rn->host, rn->port, rn->timeout);
     if (rh == NULL)
     {
       ERROR ("redis plugin: unable to connect to node `%s' (%s:%d).", rn->name, rn->host, rn->port);
@@ -263,56 +277,42 @@ static int redis_read (void) /* {{{ */
     if (strlen (rn->passwd) > 0)
     {
       DEBUG ("redis plugin: authenticanting node `%s' passwd(%s).", rn->name, rn->passwd);
-      status = credis_auth(rh, rn->passwd);
-      if (status != 0)
+      rr = redisCommand (rh, "AUTH %s", rn->passwd);
+
+      if (rr == NULL || rr->type != REDIS_REPLY_STATUS)
       {
         WARNING ("redis plugin: unable to authenticate on node `%s'.", rn->name);
-        credis_close (rh);
+        if (rr != NULL)
+          freeReplyObject (rr);
+
+        redisFree (rh);
         continue;
       }
     }
 
-    memset (&info, 0, sizeof (info));
-    status = credis_info (rh, &info);
-    if (status != 0)
+    if ((rr = redisCommand(rh, "INFO")) == NULL)
     {
-      WARNING ("redis plugin: unable to get info from node `%s'.", rn->name);
-      credis_close (rh);
+      WARNING ("redis plugin: unable to connect to node `%s'.", rn->name);
+      redisFree (rh);
       continue;
     }
 
-    /* typedef struct _cr_info {
-     *   char redis_version[CREDIS_VERSION_STRING_SIZE];
-     *   int bgsave_in_progress;
-     *   int connected_clients;
-     *   int connected_slaves;
-     *   unsigned int used_memory;
-     *   long long changes_since_last_save;
-     *   int last_save_time;
-     *   long long total_connections_received;
-     *   long long total_commands_processed;
-     *   int uptime_in_seconds;
-     *   int uptime_in_days;
-     *   int role;
-     * } REDIS_INFO; */
-
-    DEBUG ("redis plugin: received info from node `%s': connected_clients = %d; "
-        "connected_slaves = %d; used_memory = %lu; changes_since_last_save = %lld; "
-        "bgsave_in_progress = %d; total_connections_received = %lld; "
-        "total_commands_processed = %lld; uptime_in_seconds = %ld", rn->name,
-        info.connected_clients, info.connected_slaves, info.used_memory,
-        info.changes_since_last_save, info.bgsave_in_progress,
-        info.total_connections_received, info.total_commands_processed,
-        info.uptime_in_seconds);
-
-    redis_submit_g (rn->name, "current_connections", "clients", info.connected_clients);
-    redis_submit_g (rn->name, "current_connections", "slaves", info.connected_slaves);
-    redis_submit_g (rn->name, "memory", "used", info.used_memory);
-    redis_submit_g (rn->name, "volatile_changes", NULL, info.changes_since_last_save);
-    redis_submit_d (rn->name, "total_connections", NULL, info.total_connections_received);
-    redis_submit_d (rn->name, "total_operations", NULL, info.total_commands_processed);
-
-    credis_close (rh);
+    redis_handle_info (rn->name, rr->str, "uptime", NULL, "uptime_in_seconds", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "current_connections", "clients", "connected_clients", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "blocked_clients", NULL, "blocked_clients", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "memory", NULL, "used_memory", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "memory_lua", NULL, "used_memory_lua", DS_TYPE_GAUGE);
+    /* changes_since_last_save: Deprecated in redis version 2.6 and above */
+    redis_handle_info (rn->name, rr->str, "volatile_changes", NULL, "changes_since_last_save", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "total_connections", NULL, "total_connections_received", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "total_operations", NULL, "total_commands_processed", DS_TYPE_DERIVE);
+    redis_handle_info (rn->name, rr->str, "expired_keys", NULL, "expired_keys", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "pubsub", "channels", "pubsub_channels", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "pubsub", "patterns", "pubsub_patterns", DS_TYPE_GAUGE);
+    redis_handle_info (rn->name, rr->str, "current_connections", "slaves", "connected_slaves", DS_TYPE_GAUGE);
+
+    freeReplyObject (rr);
+    redisFree (rh);
   }
 
   return 0;
diff --git a/src/smart.c b/src/smart.c
new file mode 100644 (file)
index 0000000..3b113bd
--- /dev/null
@@ -0,0 +1,269 @@
+/**
+ * collectd - src/smart.c
+ * Copyright (C) 2014       Vincent Bernat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Vincent Bernat <vbe at exoscale.ch>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <atasmart.h>
+#include <libudev.h>
+
+static const char *config_keys[] =
+{
+  "Disk",
+  "IgnoreSelected"
+};
+
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int smart_config (const char *key, const char *value)
+{
+  if (ignorelist == NULL)
+    ignorelist = ignorelist_create (/* invert = */ 1);
+  if (ignorelist == NULL)
+    return (1);
+
+  if (strcasecmp ("Disk", key) == 0)
+  {
+    ignorelist_add (ignorelist, value);
+  }
+  else if (strcasecmp ("IgnoreSelected", key) == 0)
+  {
+    int invert = 1;
+    if (IS_TRUE (value))
+      invert = 0;
+    ignorelist_set_invert (ignorelist, invert);
+  }
+  else
+  {
+    return (-1);
+  }
+
+  return (0);
+} /* int smart_config */
+
+static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = value;
+
+       vl.values = values;
+       vl.values_len = 1;
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+       sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+       sstrncpy (vl.type, type, sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+       plugin_dispatch_values (&vl);
+}
+
+static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedData *a,
+                                        void* userdata)
+{
+  const char *dev = userdata;
+  value_t values[4];
+  value_list_t vl = VALUE_LIST_INIT;
+
+  if (!a->current_value_valid || !a->worst_value_valid) return;
+  values[0].gauge = a->current_value;
+  values[1].gauge = a->worst_value;
+  values[2].gauge = a->threshold_valid?a->threshold:0;
+  values[3].gauge = a->pretty_value;
+
+  vl.values = values;
+  vl.values_len = 4;
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, "smart_attribute", sizeof (vl.type));
+  sstrncpy (vl.type_instance, a->name, sizeof (vl.type_instance));
+
+  plugin_dispatch_values (&vl);
+
+  if (a->threshold_valid && a->current_value <= a->threshold)
+  {
+    notification_t notif = { NOTIF_WARNING,
+                             cdtime (),
+                             "",
+                             "",
+                             "smart", "",
+                             "smart_attribute",
+                             "",
+                             NULL };
+    sstrncpy (notif.host, hostname_g, sizeof (notif.host));
+    sstrncpy (notif.plugin_instance, dev, sizeof (notif.plugin_instance));
+    sstrncpy (notif.type_instance, a->name, sizeof (notif.type_instance));
+    ssnprintf (notif.message, sizeof (notif.message),
+               "attribute %s is below allowed threshold (%d < %d)",
+               a->name, a->current_value, a->threshold);
+    plugin_dispatch_notification (&notif);
+  }
+}
+
+static void smart_handle_disk (const char *dev)
+{
+  SkDisk *d = NULL;
+  SkBool awake = FALSE;
+  SkBool available = FALSE;
+  const char *shortname;
+  const SkSmartParsedData *spd;
+  uint64_t poweron, powercycles, badsectors, temperature;
+
+  shortname = strrchr(dev, '/');
+  if (!shortname) return;
+  shortname++;
+  if (ignorelist_match (ignorelist, shortname) != 0) {
+    DEBUG ("smart plugin: ignoring %s.", dev);
+    return;
+  }
+
+  DEBUG ("smart plugin: checking SMART status of %s.",
+         dev);
+
+  if (sk_disk_open (dev, &d) < 0)
+  {
+    ERROR ("smart plugin: unable to open %s.", dev);
+    return;
+  }
+  if (sk_disk_identify_is_available (d, &available) < 0 || !available)
+  {
+    DEBUG ("smart plugin: disk %s cannot be identified.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_is_available (d, &available) < 0 || !available)
+  {
+    DEBUG ("smart plugin: disk %s has no SMART support.", dev);
+    goto end;
+  }
+  if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+  {
+    DEBUG ("smart plugin: disk %s is sleeping.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_read_data (d) < 0)
+  {
+    ERROR ("smart plugin: unable to get SMART data for disk %s.", dev);
+    goto end;
+  }
+  if (sk_disk_smart_parse (d, &spd) < 0)
+  {
+    ERROR ("smart plugin: unable to parse SMART data for disk %s.", dev);
+    goto end;
+  }
+
+  /* Get some specific values */
+  if (sk_disk_smart_get_power_on (d, &poweron) < 0)
+  {
+    WARNING ("smart plugin: unable to get milliseconds since power on for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_poweron", "", poweron / 1000.);
+
+  if (sk_disk_smart_get_power_cycle (d, &powercycles) < 0)
+  {
+    WARNING ("smart plugin: unable to get number of power cycles for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_powercycles", "", powercycles);
+
+  if (sk_disk_smart_get_bad (d, &badsectors) < 0)
+  {
+    WARNING ("smart plugin: unable to get number of bad sectors for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_badsectors", "", badsectors);
+
+  if (sk_disk_smart_get_temperature (d, &temperature) < 0)
+  {
+    WARNING ("smart plugin: unable to get temperature for %s.",
+             dev);
+  }
+  else
+    smart_submit (shortname, "smart_temperature", "", temperature / 1000. - 273.15);
+
+  /* Grab all attributes */
+  if (sk_disk_smart_parse_attributes(d, smart_handle_disk_attribute,
+                                     (char *)shortname) < 0)
+  {
+    ERROR ("smart plugin: unable to handle SMART attributes for %s.",
+           dev);
+  }
+
+end:
+  sk_disk_free(d);
+}
+
+static int smart_read (void)
+{
+  struct udev *handle_udev;
+  struct udev_enumerate *enumerate;
+  struct udev_list_entry *devices, *dev_list_entry;
+  struct udev_device *dev;
+
+  /* Use udev to get a list of disks */
+  handle_udev = udev_new();
+  if (!handle_udev)
+  {
+    ERROR ("smart plugin: unable to initialize udev.");
+    return (-1);
+  }
+  enumerate = udev_enumerate_new (handle_udev);
+  udev_enumerate_add_match_subsystem (enumerate, "block");
+  udev_enumerate_add_match_property (enumerate, "DEVTYPE", "disk");
+  udev_enumerate_scan_devices (enumerate);
+  devices = udev_enumerate_get_list_entry (enumerate);
+  udev_list_entry_foreach (dev_list_entry, devices)
+  {
+    const char *path, *devpath;
+    path = udev_list_entry_get_name (dev_list_entry);
+    dev = udev_device_new_from_syspath (handle_udev, path);
+    devpath = udev_device_get_devnode (dev);
+
+    /* Query status with libatasmart */
+    smart_handle_disk (devpath);
+  }
+
+  udev_enumerate_unref (enumerate);
+  udev_unref (handle_udev);
+
+  return (0);
+} /* int smart_read */
+
+void module_register (void)
+{
+  plugin_register_config ("smart", smart_config,
+                          config_keys, config_keys_num);
+  plugin_register_read ("smart", smart_read);
+} /* void module_register */
index 7d6e0a1..ab59638 100644 (file)
@@ -359,7 +359,7 @@ static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t
     {
       ERROR("snmp plugin: Can't allocate memory");
       strarray_free(dd->ignores, dd->ignores_len);
-      return (ENOMEM); 
+      return (ENOMEM);
     }
   }
   return 0;
@@ -1497,6 +1497,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
         snmp_free_pdu (res);
       res = NULL;
 
+      /* snmp_synch_response already freed our PDU */
+      req = NULL;
       sfree (errstr);
       csnmp_host_close_session (host);
 
index 5a04231..0236c9d 100644 (file)
@@ -272,12 +272,15 @@ static const char *config_keys[] =
 {
   "ListeningPorts",
   "LocalPort",
-  "RemotePort"
+  "RemotePort",
+  "AllPortsSummary"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
 static int port_collect_listening = 0;
+static int port_collect_total = 0;
 static port_entry_t *port_list_head = NULL;
+static uint32_t count_total[TCP_STATE_MAX + 1];
 
 #if KERNEL_LINUX
 #if HAVE_STRUCT_LINUX_INET_DIAG_REQ
@@ -295,17 +298,22 @@ enum
 } linux_source = SRC_DUNNO;
 #endif
 
+static void conn_prepare_vl (value_list_t *vl, value_t *values)
+{
+  vl->values = values;
+  vl->values_len = 1;
+  sstrncpy (vl->host, hostname_g, sizeof (vl->host));
+  sstrncpy (vl->plugin, "tcpconns", sizeof (vl->plugin));
+  sstrncpy (vl->type, "tcp_connections", sizeof (vl->type));
+}
+
 static void conn_submit_port_entry (port_entry_t *pe)
 {
   value_t values[1];
   value_list_t vl = VALUE_LIST_INIT;
   int i;
 
-  vl.values = values;
-  vl.values_len = 1;
-  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
-  sstrncpy (vl.plugin, "tcpconns", sizeof (vl.plugin));
-  sstrncpy (vl.type, "tcp_connections", sizeof (vl.type));
+  conn_prepare_vl (&vl, values);
 
   if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING))
       || (pe->flags & PORT_COLLECT_LOCAL))
@@ -339,10 +347,33 @@ static void conn_submit_port_entry (port_entry_t *pe)
   }
 } /* void conn_submit */
 
+static void conn_submit_port_total (void)
+{
+  value_t values[1];
+  value_list_t vl = VALUE_LIST_INIT;
+  int i;
+
+  conn_prepare_vl (&vl, values);
+
+  sstrncpy (vl.plugin_instance, "all", sizeof (vl.plugin_instance));
+
+  for (i = 1; i <= TCP_STATE_MAX; i++)
+  {
+    vl.values[0].gauge = count_total[i];
+
+    sstrncpy (vl.type_instance, tcp_state[i], sizeof (vl.type_instance));
+
+    plugin_dispatch_values (&vl);
+  }
+}
+
 static void conn_submit_all (void)
 {
   port_entry_t *pe;
 
+  if (port_collect_total)
+    conn_submit_port_total ();
+
   for (pe = port_list_head; pe != NULL; pe = pe->next)
     conn_submit_port_entry (pe);
 } /* void conn_submit_all */
@@ -381,6 +412,8 @@ static void conn_reset_port_entry (void)
   port_entry_t *prev = NULL;
   port_entry_t *pe = port_list_head;
 
+  memset (&count_total, '\0', sizeof(count_total));
+
   while (pe != NULL)
   {
     /* If this entry was created while reading the files (ant not when handling
@@ -428,6 +461,8 @@ static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t
     return (-1);
   }
 
+  count_total[state]++;
+
   /* Listening sockets */
   if ((state == TCP_STATE_LISTEN) && (port_collect_listening != 0))
   {
@@ -704,6 +739,13 @@ static int conn_config (const char *key, const char *value)
       else
        pe->flags |= PORT_COLLECT_REMOTE;
   }
+  else if (strcasecmp (key, "AllPortsSummary") == 0)
+  {
+    if (IS_TRUE (value))
+      port_collect_total = 1;
+    else
+      port_collect_total = 0;
+  }
   else
   {
     return (-1);
@@ -715,7 +757,7 @@ static int conn_config (const char *key, const char *value)
 #if KERNEL_LINUX
 static int conn_init (void)
 {
-  if (port_list_head == NULL)
+  if (port_collect_total == 0 && port_list_head == NULL)
     port_collect_listening = 1;
 
   return (0);
@@ -909,7 +951,9 @@ static int conn_init (void)
 static int conn_read (void)
 {
   struct inpcbtable table;
+#if !defined(__OpenBSD__) && (defined(__NetBSD_Version__) && __NetBSD_Version__ <= 699002700)
   struct inpcb *head;
+#endif
   struct inpcb *next;
   struct inpcb inpcb;
   struct tcpcb tcpcb;
@@ -922,18 +966,30 @@ static int conn_read (void)
   if (status != 0)
     return (-1);
 
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+  /* inpt_queue is a TAILQ on OpenBSD */
+  /* Get the first pcb */
+  next = (struct inpcb *)TAILQ_FIRST (&table.inpt_queue);
+  while (next)
+#else
   /* Get the `head' pcb */
   head = (struct inpcb *) &(inpcbtable_ptr->inpt_queue);
   /* Get the first pcb */
   next = (struct inpcb *)CIRCLEQ_FIRST (&table.inpt_queue);
 
   while (next != head)
+#endif
   {
     /* Read the pcb pointed to by `next' into `inpcb' */
     kread ((u_long) next, &inpcb, sizeof (inpcb));
 
     /* Advance `next' */
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
+    /* inpt_queue is a TAILQ on OpenBSD */
+    next = (struct inpcb *)TAILQ_NEXT (&inpcb, inp_queue);
+#else
     next = (struct inpcb *)CIRCLEQ_NEXT (&inpcb, inp_queue);
+#endif
 
     /* Ignore sockets, that are not connected. */
 #ifdef __NetBSD__
index fc75153..8916379 100644 (file)
@@ -8,12 +8,14 @@ ath_nodes             value:GAUGE:0:65535
 ath_stat               value:DERIVE:0:U
 backends               value:GAUGE:0:65535
 bitrate                        value:GAUGE:0:4294967295
+blocked_clients value:GAUGE:0:U
 bytes                  value:GAUGE:0:U
 cache_eviction         value:DERIVE:0:U
 cache_operation                value:DERIVE:0:U
 cache_ratio            value:GAUGE:0:100
 cache_result           value:DERIVE:0:U
 cache_size             value:GAUGE:0:U
+changes_since_last_save   value:GAUGE:0:U
 charge                 value:GAUGE:0:U
 compression_ratio      value:GAUGE:0:2
 compression            uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
@@ -60,6 +62,7 @@ email_check           value:GAUGE:0:U
 email_count            value:GAUGE:0:U
 email_size             value:GAUGE:0:U
 entropy                        value:GAUGE:0:4294967295
+expired_keys    value:GAUGE:0:U
 fanspeed               value:GAUGE:0:U
 file_size              value:GAUGE:0:U
 files                  value:GAUGE:0:U
@@ -100,6 +103,7 @@ memcached_items             value:GAUGE:0:U
 memcached_octets       rx:DERIVE:0:U, tx:DERIVE:0:U
 memcached_ops          value:DERIVE:0:U
 memory                 value:GAUGE:0:281474976710656
+memory_lua             value:GAUGE:0:281474976710656
 multimeter             value:GAUGE:U:U
 mutex_operations       value:DERIVE:0:U
 mysql_commands         value:DERIVE:0:U
@@ -157,6 +161,7 @@ ps_rss                      value:GAUGE:0:9223372036854775807
 ps_stacksize           value:GAUGE:0:9223372036854775807
 ps_state               value:GAUGE:0:65535
 ps_vm                  value:GAUGE:0:9223372036854775807
+pubsub        value:GAUGE:0:U
 queue_length           value:GAUGE:0:U
 records                        value:GAUGE:0:U
 requests               value:GAUGE:0:U
@@ -169,6 +174,11 @@ serial_octets              rx:DERIVE:0:U, tx:DERIVE:0:U
 signal_noise           value:GAUGE:U:0
 signal_power           value:GAUGE:U:0
 signal_quality         value:GAUGE:0:U
+smart_poweron          value:GAUGE:0:U
+smart_powercycles      value:GAUGE:0:U
+smart_badsectors       value:GAUGE:0:U
+smart_temperature      value:GAUGE:-300:300
+smart_attribute         current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
 snr                    value:GAUGE:0:U
 spam_check             value:GAUGE:0:U
 spam_score             value:GAUGE:U:U
index 781e778..10f34ee 100644 (file)
@@ -102,11 +102,21 @@ static int users_read (void)
 #elif HAVE_LIBSTATGRAB
        sg_user_stats *us;
 
+# if HAVE_LIBSTATGRAB_0_90
+       size_t num_entries;
+       us = sg_get_user_stats (&num_entries);
+# else
        us = sg_get_user_stats ();
+# endif
        if (us == NULL)
                return (-1);   
 
-       users_submit ((gauge_t) us->num_entries);
+       users_submit ((gauge_t)
+# if HAVE_LIBSTATGRAB_0_90
+                     num_entries);
+# else
+                     us->num_entries);
+# endif
 /* #endif HAVE_LIBSTATGRAB */
 
 #else
index 712b1ae..eefde96 100644 (file)
@@ -3,10 +3,10 @@
  * Copyright (C) 2006       Florian octo Forster
  * Copyright (C) 2002       The Measurement Factory, Inc.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
- * 
+ *
  * 1. Redistributions of source code must retain the above copyright notice,
  *    this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright notice,
@@ -33,6 +33,7 @@
  *   Florian octo Forster <octo at collectd.org>
  */
 
+#define _DEFAULT_SOURCE
 #define _BSD_SOURCE
 
 #include "collectd.h"
index 3a8dddd..8e6d95e 100644 (file)
 #include "plugin.h"
 #include "configfile.h"
 
-#include <varnish/varnishapi.h>
+#if HAVE_VARNISH_V4
+#include <varnish/vapi/vsm.h>
+#include <varnish/vapi/vsc.h>
+typedef struct VSC_C_main c_varnish_stats_t;
+#endif
 
 #if HAVE_VARNISH_V3
-# include <varnish/vsc.h>
+#include <varnish/varnishapi.h>
+#include <varnish/vsc.h>
 typedef struct VSC_C_main c_varnish_stats_t;
 #endif
 
 #if HAVE_VARNISH_V2
+#include <varnish/varnishapi.h>
 typedef struct varnish_stats c_varnish_stats_t;
 #endif
 
@@ -67,11 +73,14 @@ struct user_config_s {
 #endif
        _Bool collect_struct;
        _Bool collect_totals;
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
        _Bool collect_uptime;
 #endif
        _Bool collect_vcl;
        _Bool collect_workers;
+#if HAVE_VARNISH_V4
+       _Bool collect_vsm;
+#endif
 };
 typedef struct user_config_s user_config_t; /* }}} */
 
@@ -141,10 +150,12 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
 
        if (conf->collect_connections)
        {
+#ifndef HAVE_VARNISH_V4
                /* Client connections accepted */
                varnish_submit_derive (conf->instance, "connections", "connections", "accepted", stats->client_conn);
                /* Connection dropped, no sess */
                varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , stats->client_drop);
+#endif
                /* Client requests received    */
                varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
        }
@@ -225,7 +236,7 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , stats->fetch_zero);
                /* Fetch failed              */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , stats->fetch_failed);
-#if HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                /* Fetch no body (1xx)       */
                varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", stats->fetch_1xx);
                /* Fetch no body (204)       */
@@ -263,12 +274,17 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
 #endif
                /* HTTP header overflows         */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow",    stats->losthdr);
+#if HAVE_VARNISH_V4
+               /* N purged objects              */
+               varnish_submit_derive (conf->instance, "objects", "total_objects", "purged",             stats->n_obj_purged);
+#else
                /* Objects sent with sendfile    */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile",      stats->n_objsendfile);
                /* Objects sent with write       */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write",         stats->n_objwrite);
                /* Objects overflowing workspace */
                varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", stats->n_objoverflow);
+#endif
        }
 
 #if HAVE_VARNISH_V2
@@ -287,7 +303,8 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* N duplicate purges removed */
                varnish_submit_derive (conf->instance, "purge", "total_operations", "duplicate",        stats->n_purge_dups);
        }
-#else
+#endif
+#if HAVE_VARNISH_V3
        if (conf->collect_ban)
        {
                /* N total active bans      */
@@ -304,6 +321,27 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->n_ban_dups);
        }
 #endif
+#if HAVE_VARNISH_V4
+       if (conf->collect_ban)
+       {
+               /* N total active bans      */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "total",          stats->bans);
+               /* N new bans added         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "added",          stats->bans_added);
+               /* N bans using obj */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "obj",            stats->bans_obj);
+               /* N bans using req */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "req",            stats->bans_req);
+               /* N new bans completed     */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "completed",      stats->bans_completed);
+               /* N old bans deleted       */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted",        stats->bans_deleted);
+               /* N objects tested         */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "tested",         stats->bans_tested);
+               /* N duplicate bans removed */
+               varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate",      stats->bans_dups);
+       }
+#endif
 
        if (conf->collect_session)
        {
@@ -313,8 +351,21 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline",  stats->sess_pipeline);
                /* Session Read Ahead */
                varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", stats->sess_readahead);
+#if HAVE_VARNISH_V4
+               /* Sessions accepted */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "accepted",  stats->sess_conn);
+               /* Sessions dropped for thread */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "dropped",   stats->sess_drop);
+               /* Sessions accept failure */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "failed",    stats->sess_fail);
+               /* Sessions pipe overflow */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "overflow",  stats->sess_pipe_overflow);
+               /* Sessions queued for thread */
+               varnish_submit_derive (conf->instance, "session", "total_operations", "queued",    stats->sess_queued);
+#else
                /* Session Linger     */
                varnish_submit_derive (conf->instance, "session", "total_operations", "linger",    stats->sess_linger);
+#endif
                /* Session herd       */
                varnish_submit_derive (conf->instance, "session", "total_operations", "herd",      stats->sess_herd);
        }
@@ -377,17 +428,21 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
 
        if (conf->collect_struct)
        {
+#if !HAVE_VARNISH_V4
                /* N struct sess_mem       */
                varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem",  stats->n_sess_mem);
                /* N struct sess           */
                varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess",      stats->n_sess);
+#endif
                /* N struct object         */
                varnish_submit_gauge (conf->instance, "struct", "objects", "object",             stats->n_object);
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                /* N unresurrected objects */
                varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject",      stats->n_vampireobject);
                /* N struct objectcore     */
                varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore",         stats->n_objectcore);
+               /* N struct waitinglist    */
+               varnish_submit_gauge (conf->instance, "struct", "objects", "waitinglist",        stats->n_waitinglist);
 #endif
                /* N struct objecthead     */
                varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead",         stats->n_objecthead);
@@ -415,13 +470,40 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    stats->s_pass);
                /* Total fetch */
                varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", stats->s_fetch);
+#if HAVE_VARNISH_V4
+               /* Total synth */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "synth",       stats->s_synth);
+               /* Request header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_header",  stats->s_req_hdrbytes);
+               /* Request body byte */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "req_body",    stats->s_req_bodybytes);
+               /* Response header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_header", stats->s_resp_hdrbytes);
+               /* Response body byte */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "resp_body",   stats->s_resp_bodybytes);
+               /* Pipe request header bytes */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_header", stats->s_pipe_hdrbytes);
+               /* Piped bytes from client */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_in",     stats->s_pipe_in);
+               /* Piped bytes to client */
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "pipe_out",    stats->s_pipe_out);
+               /* Number of purge operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "purges", stats->n_purges);
+#else
                /* Total header bytes */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", stats->s_hdrbytes);
                /* Total body byte */
                varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
+#endif
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* Gzip operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "gzip",    stats->n_gzip);
+               /* Gunzip operations */
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "gunzip",  stats->n_gunzip);
+#endif
        }
 
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
        if (conf->collect_uptime)
        {
                /* Client uptime */
@@ -437,10 +519,28 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl",     stats->n_vcl_avail);
                /* N vcl discarded */
                varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", stats->n_vcl_discard);
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
+               /* Loaded VMODs */
+               varnish_submit_gauge (conf->instance, "vcl", "objects", "vmod",      stats->vmods);
+#endif
        }
 
        if (conf->collect_workers)
        {
+#ifdef HAVE_VARNISH_V4
+               /* total number of threads */
+               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->threads);
+               /* threads created */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     stats->threads_created);
+               /* thread creation failed */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      stats->threads_failed);
+               /* threads hit max */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->threads_limited);
+               /* threads destroyed */
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->threads_destroyed);
+               /* length of session queue */
+               varnish_submit_derive (conf->instance, "workers", "queue_length",  "threads",     stats->thread_queue_len);
+#else
                /* worker threads */
                varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->n_wrk);
                /* worker threads created */
@@ -450,22 +550,40 @@ static void varnish_monitor (const user_config_t *conf, /* {{{ */
                /* worker threads limited */
                varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->n_wrk_max);
                /* dropped work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped",    stats->n_wrk_drop);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "dropped",     stats->n_wrk_drop);
 #ifdef HAVE_VARNISH_V2
                /* queued work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     stats->n_wrk_queue);
                /* overflowed work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", stats->n_wrk_overflow);
-#else
+#else /* HAVE_VARNISH_V3 */
                /* queued work requests */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",       stats->n_wrk_queued);
                /* work request queue length */
                varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", stats->n_wrk_lqueue);
 #endif
+#endif
+       }
+
+#if HAVE_VARNISH_V4
+       if (conf->collect_vsm)
+       {
+               /* Free VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "free",              stats->vsm_free);
+               /* Used VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "used",              stats->vsm_used);
+               /* Cooling VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "cooling",           stats->vsm_cooling);
+               /* Overflow VSM space */
+               varnish_submit_gauge (conf->instance, "vsm", "bytes", "overflow",          stats->vsm_overflow);
+               /* Total overflowed VSM space */
+               varnish_submit_derive (conf->instance, "vsm", "total_bytes", "overflowed", stats->vsm_overflowed);
        }
+#endif
+
 } /* }}} void varnish_monitor */
 
-#if HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
 static int varnish_read (user_data_t *ud) /* {{{ */
 {
        struct VSM_data *vd;
@@ -479,7 +597,9 @@ static int varnish_read (user_data_t *ud) /* {{{ */
        conf = ud->data;
 
        vd = VSM_New();
+#if HAVE_VARNISH_V3
        VSC_Setup(vd);
+#endif
 
        if (conf->instance != NULL)
        {
@@ -495,14 +615,22 @@ static int varnish_read (user_data_t *ud) /* {{{ */
                }
        }
 
+#if HAVE_VARNISH_V3
        if (VSC_Open (vd, /* diag = */ 1))
+#else /* if HAVE_VARNISH_V4 */
+       if (VSM_Open (vd))
+#endif
        {
                ERROR ("varnish plugin: Unable to load statistics.");
 
                return (-1);
        }
 
+#if HAVE_VARNISH_V3
        stats = VSC_Main(vd);
+#else /* if HAVE_VARNISH_V4 */
+       stats = VSC_Main(vd, NULL);
+#endif
 
        varnish_monitor (conf, stats);
        VSM_Close (vd);
@@ -575,11 +703,14 @@ static int varnish_config_apply_default (user_config_t *conf) /* {{{ */
        conf->collect_sms         = 0;
        conf->collect_struct      = 0;
        conf->collect_totals      = 0;
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
        conf->collect_uptime      = 0;
 #endif
        conf->collect_vcl         = 0;
        conf->collect_workers     = 0;
+#if HAVE_VARNISH_V4
+       conf->collect_vsm         = 0;
+#endif
 
        return (0);
 } /* }}} int varnish_config_apply_default */
@@ -699,7 +830,7 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_struct);
                else if (strcasecmp ("CollectTotals", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_totals);
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                else if (strcasecmp ("CollectUptime", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_uptime);
 #endif
@@ -707,6 +838,10 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_vcl);
                else if (strcasecmp ("CollectWorkers", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_workers);
+#if HAVE_VARNISH_V4
+               else if (strcasecmp ("CollectVSM", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_vsm);
+#endif
                else
                {
                        WARNING ("Varnish plugin: Ignoring unknown "
@@ -741,11 +876,15 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
 #endif
                        && !conf->collect_struct
                        && !conf->collect_totals
-#ifdef HAVE_VARNISH_V3
+#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
                        && !conf->collect_uptime
 #endif
                        && !conf->collect_vcl
-                       && !conf->collect_workers)
+                       && !conf->collect_workers
+#if HAVE_VARNISH_V4
+                       && !conf->collect_vsm
+#endif
+       )
        {
                WARNING ("Varnish plugin: No metric has been configured for "
                                "instance \"%s\". Disabling this instance.",
index 3e683c8..ba76d71 100644 (file)
@@ -61,7 +61,7 @@ static int kafka_write(const data_set_t *, const value_list_t *, user_data_t *);
 static int32_t kafka_partition(const rd_kafka_topic_t *, const void *, size_t,
                                int32_t, void *, void *);
 
-#ifdef HAVE_LIBRDKAFKA_LOGGER
+#if defined HAVE_LIBRDKAFKA_LOGGER || defined HAVE_LIBRDKAFKA_LOG_CB
 static void kafka_log(const rd_kafka_t *, int, const char *, const char *);
 
 static void kafka_log(const rd_kafka_t *rkt, int level,
index 3defaca..b47650d 100644 (file)
@@ -30,7 +30,8 @@
 #include "configfile.h"
 
 #include <pthread.h>
-#include <credis.h>
+#include <sys/time.h>
+#include <hiredis/hiredis.h>
 
 struct wr_node_s
 {
@@ -38,9 +39,9 @@ struct wr_node_s
 
   char *host;
   int port;
-  int timeout;
+  struct timeval timeout;
 
-  REDIS conn;
+  redisContext *conn;
   pthread_mutex_t lock;
 };
 typedef struct wr_node_s wr_node_t;
@@ -56,15 +57,18 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   char ident[512];
   char key[512];
   char value[512];
+  char time[24];
   size_t value_size;
   char *value_ptr;
   int status;
+  redisReply   *rr;
   int i;
 
   status = FORMAT_VL (ident, sizeof (ident), vl);
   if (status != 0)
     return (status);
   ssnprintf (key, sizeof (key), "collectd/%s", ident);
+  ssnprintf (time, sizeof (time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
 
   memset (value, 0, sizeof (value));
   value_size = sizeof (value);
@@ -84,7 +88,9 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   }                                                                  \
 } while (0)
 
-  APPEND ("%lu", (unsigned long) vl->time);
+  APPEND (time);
+  APPEND (":");
+
   for (i = 0; i < ds->ds_num; i++)
   {
     if (ds->ds[i].type == DS_TYPE_COUNTER)
@@ -105,7 +111,7 @@ static int wr_write (const data_set_t *ds, /* {{{ */
 
   if (node->conn == NULL)
   {
-    node->conn = credis_connect (node->host, node->port, node->timeout);
+    node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
     if (node->conn == NULL)
     {
       ERROR ("write_redis plugin: Connecting to host \"%s\" (port %i) failed.",
@@ -116,12 +122,14 @@ static int wr_write (const data_set_t *ds, /* {{{ */
     }
   }
 
-  /* "credis_zadd" doesn't handle a NULL pointer gracefully, so I'd rather
-   * have a meaningful assertion message than a normal segmentation fault. */
   assert (node->conn != NULL);
-  status = credis_zadd (node->conn, key, (double) vl->time, value);
+  rr = redisCommand (node->conn, "ZADD %s %s %s", key, time, value);
+  if (rr==NULL)
+    WARNING("ZADD command error. key:%s", key);
 
-  credis_sadd (node->conn, "collectd/values", ident);
+  rr = redisCommand (node->conn, "SADD collectd/values %s", ident);
+  if (rr==NULL)
+    WARNING("SADD command error. ident:%s", ident);
 
   pthread_mutex_unlock (&node->lock);
 
@@ -137,7 +145,7 @@ static void wr_config_free (void *ptr) /* {{{ */
 
   if (node->conn != NULL)
   {
-    credis_close (node->conn);
+    redisFree (node->conn);
     node->conn = NULL;
   }
 
@@ -148,6 +156,7 @@ static void wr_config_free (void *ptr) /* {{{ */
 static int wr_config_node (oconfig_item_t *ci) /* {{{ */
 {
   wr_node_t *node;
+  int timeout;
   int status;
   int i;
 
@@ -157,7 +166,8 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
   memset (node, 0, sizeof (*node));
   node->host = NULL;
   node->port = 0;
-  node->timeout = 1000;
+  node->timeout.tv_sec = 0;
+  node->timeout.tv_usec = 1000;
   node->conn = NULL;
   pthread_mutex_init (&node->lock, /* attr = */ NULL);
 
@@ -183,8 +193,10 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */
         status = 0;
       }
     }
-    else if (strcasecmp ("Timeout", child->key) == 0)
-      status = cf_util_get_int (child, &node->timeout);
+    else if (strcasecmp ("Timeout", child->key) == 0) {
+      status = cf_util_get_int (child, &timeout);
+      if (status == 0) node->timeout.tv_usec = timeout;
+    }
     else
       WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
           child->key);
index c3740e1..0a8df6f 100644 (file)
 #define RIEMANN_HOST           "localhost"
 #define RIEMANN_PORT           "5555"
 #define RIEMANN_TTL_FACTOR      2.0
+#define RIEMANN_BATCH_MAX      8192
 
 int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
 
 struct riemann_host {
        char                    *name;
        char                    *event_service_prefix;
-#define F_CONNECT               0x01
+#define F_CONNECT       0x01
        uint8_t                  flags;
-       pthread_mutex_t          lock;
-       _Bool                    notifications;
-       _Bool                    check_thresholds;
+       pthread_mutex_t  lock;
+    _Bool            batch_mode;
+       _Bool            notifications;
+       _Bool            check_thresholds;
        _Bool                    store_rates;
        _Bool                    always_append_ds;
        char                    *node;
        char                    *service;
        _Bool                    use_tcp;
-       int                      s;
+       int                          s;
        double                   ttl_factor;
-
-       int                      reference_count;
+    Msg             *batch_msg;
+    cdtime_t         batch_init;
+    int              batch_max;
+       int                          reference_count;
 };
 
 static char    **riemann_tags;
@@ -651,6 +655,103 @@ static Msg *riemann_value_list_to_protobuf (struct riemann_host const *host, /*
        return (msg);
 } /* }}} Msg *riemann_value_list_to_protobuf */
 
+
+/*
+ * Always call while holding host->lock !
+ */
+static int riemann_batch_flush_nolock (cdtime_t timeout,
+                                       struct riemann_host *host)
+{
+    cdtime_t    now;
+    int         status = 0;
+
+    if (timeout > 0) {
+        now = cdtime ();
+        if ((host->batch_init + timeout) > now)
+            return status;
+    }
+    riemann_send_msg(host, host->batch_msg);
+    riemann_msg_protobuf_free(host->batch_msg);
+
+       if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
+        riemann_disconnect (host);
+
+    host->batch_init = cdtime();
+    host->batch_msg = NULL;
+    return status;
+}
+
+static int riemann_batch_flush (cdtime_t timeout,
+        const char *identifier __attribute__((unused)),
+        user_data_t *user_data)
+{
+    struct riemann_host *host;
+    int status;
+
+    if (user_data == NULL)
+        return (-EINVAL);
+
+    host = user_data->data;
+    pthread_mutex_lock (&host->lock);
+    status = riemann_batch_flush_nolock (timeout, host);
+    if (status != 0)
+        ERROR ("write_riemann plugin: riemann_send failed with status %i",
+               status);
+
+    pthread_mutex_unlock(&host->lock);
+    return status;
+}
+
+static int riemann_batch_add_value_list (struct riemann_host *host, /* {{{ */
+                                         data_set_t const *ds,
+                                         value_list_t const *vl,
+                                         int *statuses)
+{
+       size_t i;
+    Event **events;
+    Msg *msg;
+    size_t len;
+    int ret;
+
+    msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+    if (msg == NULL)
+        return -1;
+
+    pthread_mutex_lock(&host->lock);
+
+    if (host->batch_msg == NULL) {
+        host->batch_msg = msg;
+    } else {
+        len = msg->n_events + host->batch_msg->n_events;
+        events = realloc(host->batch_msg->events,
+                         (len * sizeof(*host->batch_msg->events)));
+        if (events == NULL) {
+            pthread_mutex_unlock(&host->lock);
+            ERROR ("write_riemann plugin: out of memory");
+            riemann_msg_protobuf_free (msg);
+            return -1;
+        }
+        host->batch_msg->events = events;
+
+        for (i = host->batch_msg->n_events; i < len; i++)
+            host->batch_msg->events[i] = msg->events[i - host->batch_msg->n_events];
+
+        host->batch_msg->n_events = len;
+        sfree (msg->events);
+        msg->n_events = 0;
+        sfree (msg);
+    }
+
+       len = msg__get_packed_size(host->batch_msg);
+    ret = 0;
+    if (len >= host->batch_max) {
+        ret = riemann_batch_flush_nolock(0, host);
+    }
+
+    pthread_mutex_unlock(&host->lock);
+    return ret;
+} /* }}} Msg *riemann_batch_add_value_list */
+
 static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
 {
        int                      status;
@@ -660,6 +761,9 @@ static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{
        if (!host->notifications)
                return 0;
 
+    /*
+     * Never batch for notifications, send them ASAP
+     */
        msg = riemann_notification_to_protobuf (host, n);
        if (msg == NULL)
                return (-1);
@@ -677,23 +781,32 @@ static int riemann_write(const data_set_t *ds, /* {{{ */
              const value_list_t *vl,
              user_data_t *ud)
 {
-       int                      status;
+       int                      status = 0;
        int                      statuses[vl->values_len];
        struct riemann_host     *host = ud->data;
        Msg                     *msg;
 
        if (host->check_thresholds)
                write_riemann_threshold_check(ds, vl, statuses);
-       msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
-       if (msg == NULL)
-               return (-1);
 
-       status = riemann_send (host, msg);
-       if (status != 0)
-               ERROR ("write_riemann plugin: riemann_send failed with status %i",
-                               status);
+    if (host->use_tcp == 1 && host->batch_mode) {
 
-       riemann_msg_protobuf_free (msg);
+        riemann_batch_add_value_list (host, ds, vl, statuses);
+
+
+    } else {
+
+        msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+        if (msg == NULL)
+            return (-1);
+
+        status = riemann_send (host, msg);
+        if (status != 0)
+            ERROR ("write_riemann plugin: riemann_send failed with status %i",
+                   status);
+
+        riemann_msg_protobuf_free (msg);
+    }
        return status;
 } /* }}} int riemann_write */
 
@@ -742,6 +855,9 @@ static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
        host->store_rates = 1;
        host->always_append_ds = 0;
        host->use_tcp = 0;
+    host->batch_mode = 0;
+    host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
+    host->batch_init = cdtime();
        host->ttl_factor = RIEMANN_TTL_FACTOR;
 
        status = cf_util_get_string (ci, &host->name);
@@ -775,6 +891,14 @@ static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
                        status = cf_util_get_boolean(child, &host->check_thresholds);
                        if (status != 0)
                                break;
+        } else if (strcasecmp ("Batch", child->key) == 0) {
+            status = cf_util_get_boolean(child, &host->batch_mode);
+            if (status != 0)
+                break;
+        } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
+            status = cf_util_get_int(child, &host->batch_max);
+            if (status != 0)
+                break;
                } else if (strcasecmp ("Port", child->key) == 0) {
                        status = cf_util_get_service (child, &host->service);
                        if (status != 0) {
@@ -859,6 +983,11 @@ static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
        pthread_mutex_lock (&host->lock);
 
        status = plugin_register_write (callback_name, riemann_write, &ud);
+
+    if (host->use_tcp == 1 && host->batch_mode) {
+        ud.free_func = NULL;
+        plugin_register_flush(callback_name, riemann_batch_flush, &ud);
+    }
        if (status != 0)
                WARNING ("write_riemann plugin: plugin_register_write (\"%s\") "
                                "failed with status %i.",
index aeed635..efc7146 100644 (file)
@@ -387,8 +387,8 @@ static int wt_format_name(char *ret, int ret_len,
         ssnprintf(ret, ret_len, "%s%s.%s.%s",
                   prefix, vl->plugin, vl->plugin_instance, vl->type);
     } else {
-        ssnprintf(ret, ret_len, "%s%s.%s.%s",
-                  prefix, vl->plugin, vl->plugin_instance, vl->type_instance);
+        ssnprintf(ret, ret_len, "%s%s.%s.%s.%s",
+                  prefix, vl->plugin, vl->plugin_instance, vl->type, vl->type_instance);
     }
 
     sfree(temp);