Merge remote-tracking branch 'origin/pr/598'
authorMarc Fournier <marc.fournier@camptocamp.com>
Tue, 3 Mar 2015 20:36:21 +0000 (21:36 +0100)
committerMarc Fournier <marc.fournier@camptocamp.com>
Tue, 3 Mar 2015 20:36:21 +0000 (21:36 +0100)
Conflicts:
src/collectd.conf.in
src/types.db

1  2 
configure.ac
src/Makefile.am
src/ceph.c
src/collectd.conf.in
src/collectd.conf.pod
src/types.db

diff --combined configure.ac
@@@ -1,6 -1,6 +1,6 @@@
  dnl Process this file with autoconf to produce a configure script.
  AC_INIT([collectd],[m4_esyscmd(./version-gen.sh)])
 -AC_CONFIG_SRCDIR(src/collectd.c)
 +AC_CONFIG_SRCDIR(src/)
  AC_CONFIG_HEADERS(src/config.h)
  AC_CONFIG_AUX_DIR([libltdl/config])
  
@@@ -70,11 -70,9 +70,11 @@@ case $host_os i
        ac_system="Solaris"
        ;;
        *darwin*)
 +      AC_DEFINE([KERNEL_DARWIN], 1, [True if program is to be compiled for a Darwin kernel])
        ac_system="Darwin"
        ;;
        *openbsd*)
 +      AC_DEFINE([KERNEL_OPENBSD], 1, [True if program is to be compiled for an OpenBSD kernel])
        ac_system="OpenBSD"
        ;;
        *aix*)
  esac
  AC_MSG_RESULT([$ac_system])
  
 +AM_CONDITIONAL([BUILD_LINUX],[test "x$x$ac_system" = "xLinux"])
 +AM_CONDITIONAL([BUILD_SOLARIS],[test "x$x$ac_system" = "xSolaris"])
 +AM_CONDITIONAL([BUILD_DARWIN],[test "x$x$ac_system" = "xDarwin"])
 +AM_CONDITIONAL([BUILD_OPENBSD],[test "x$x$ac_system" = "xOpenBSD"])
 +AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"])
 +AM_CONDITIONAL([BUILD_FREEBSD],[test "x$x$ac_system" = "xFreeBSD"])
 +
  if test "x$ac_system" = "xLinux"
  then
        AC_ARG_VAR([KERNEL_DIR], [path to Linux kernel sources])
@@@ -413,18 -404,6 +413,18 @@@ AC_CHECK_HEADERS(linux/if.h, [], []
  #  include <sys/socket.h>
  #endif
  ])
 +AC_CHECK_HEADERS(linux/inet_diag.h, [], [],
 +[
 +#if HAVE_SYS_TYPES_H
 +#  include <sys/types.h>
 +#endif
 +#if HAVE_SYS_SOCKET_H
 +#  include <sys/socket.h>
 +#endif
 +#if HAVE_LINUX_INET_DIAG_H
 +# include <linux/inet_diag.h>
 +#endif
 +])
  AC_CHECK_HEADERS(linux/netdevice.h, [], [],
  [
  #if HAVE_SYS_TYPES_H
@@@ -527,7 -506,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)
 +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)
@@@ -602,7 -581,7 +602,7 @@@ AC_HEADER_TIM
  # Checks for library functions.
  #
  AC_PROG_GCC_TRADITIONAL
 -AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname)
 +AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale)
  
  AC_FUNC_STRERROR_R
  
@@@ -809,9 -788,7 +809,9 @@@ if test "x$have_swapctl" = "xyes"; the
  #  undef _LARGEFILE64_SOURCE
  #endif
  #include <sys/stat.h>
 +#include <sys/param.h>
  #include <sys/swap.h>
 +#include <unistd.h>
  ]]],
  [[[
  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);
@@@ -1006,7 -981,7 +1006,7 @@@ if test "x$fp_layout_type" = "xunknown"
        uint8_t c[8];
        double d;
  
 -      d = 8.642135e130; 
 +      d = 8.642135e130;
        memcpy ((void *) &i0, (void *) &d, 8);
  
        i1 = i0;
@@@ -1061,7 -1036,7 +1061,7 @@@ if test "x$fp_layout_type" = "xunknown"
        uint8_t c[8];
        double d;
  
 -      d = 8.642135e130; 
 +      d = 8.642135e130;
        memcpy ((void *) &i0, (void *) &d, 8);
  
        i1 = endianflip (i0);
@@@ -1110,7 -1085,7 +1110,7 @@@ if test "x$fp_layout_type" = "xunknown"
        uint8_t c[8];
        double d;
  
 -      d = 8.642135e130; 
 +      d = 8.642135e130;
        memcpy ((void *) &i0, (void *) &d, 8);
  
        i1 = intswap (i0);
@@@ -1243,9 -1218,10 +1243,9 @@@ if test "x$have_getmntent" = "xgen"; th
  fi
  
  # Check for htonll
 -AC_MSG_CHECKING([if have htonll defined])
 -
 -    have_htonll="no"
 -    AC_LINK_IFELSE([AC_LANG_PROGRAM(
 +AC_CACHE_CHECK([if have htonll defined],
 +                  [c_cv_have_htonll],
 +                  AC_LINK_IFELSE([AC_LANG_PROGRAM(
  [[[
  #include <sys/types.h>
  #include <netinet/in.h>
            return htonll(0);
  ]]]
      )],
 -    [
 -      have_htonll="yes"
 -      AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.])
 -    ])
 - 
 -AC_MSG_RESULT([$have_htonll])
 +    [c_cv_have_htonll="yes"],
 +    [c_cv_have_htonll="no"]
 +  )
 +)
 +if test "x$c_cv_have_htonll" = "xyes"
 +then
 +    AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.])
 +fi
  
  # Check for structures
  AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_opackets, struct if_data.ifi_ierrors],
@@@ -1284,13 -1258,6 +1284,13 @@@ AC_CHECK_MEMBERS([struct net_device_sta
        #include <linux/if.h>
        #include <linux/netdevice.h>
        ])
 +AC_CHECK_MEMBERS([struct inet_diag_req.id, struct inet_diag_req.idiag_states],
 +      [AC_DEFINE(HAVE_STRUCT_LINUX_INET_DIAG_REQ, 1, [Define if struct inet_diag_req exists and is usable.])],
 +      [],
 +      [
 +      #include <linux/inet_diag.h>
 +      ])
 +
  
  AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [],
        [],
@@@ -1315,7 -1282,7 +1315,7 @@@ AC_CHECK_MEMBERS([struct kinfo_proc.ki_
  #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.])
  
  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
  ])
  AC_CHECK_MEMBERS([struct udphdr.dest, struct udphdr.source], [], [],
  [#define _BSD_SOURCE
 +#define _DEFAULT_SOURCE
  #if HAVE_STDINT_H
  # include <stdint.h>
  #endif
@@@ -1403,8 -1368,8 +1403,8 @@@ AC_CHECK_LIB(hal,libhal_device_property
             [with_libhal="no"])
  if test "x$with_libhal" = "xyes"; then
        if test "x$PKG_CONFIG" != "x"; then
 -              BUILD_WITH_LIBHAL_CFLAGS="`pkg-config --cflags hal`"
 -              BUILD_WITH_LIBHAL_LIBS="`pkg-config --libs hal`"
 +              BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`"
 +              BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`"
                AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS)
                AC_SUBST(BUILD_WITH_LIBHAL_LIBS)
        fi
  m4_divert_once([HELP_WITH], [
  collectd additional packages:])
  
 -AM_CONDITIONAL([BUILD_FREEBSD],[test "x$x$ac_system" = "xFreeBSD"])
 -
 -AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"]) 
 -
  if test "x$ac_system" = "xAIX"
  then
        with_perfstat="yes"
  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 {{{
                 [with_libcurl="yes"],
                 [with_libcurl="no (symbol 'curl_easy_init' not found)"],
                 [$with_curl_libs])
 +              AC_CHECK_DECL(CURLOPT_USERNAME,
 +               [have_curlopt_username="yes"],
 +               [have_curlopt_username="no"],
 +               [[#include <curl/curl.h>]])
        fi
  fi
  if test "x$with_libcurl" = "xyes"
        BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
        AC_SUBST(BUILD_WITH_LIBCURL_CFLAGS)
        AC_SUBST(BUILD_WITH_LIBCURL_LIBS)
 +
 +      if test "x$have_curlopt_username" = "xyes"
 +      then
 +              AC_DEFINE(HAVE_CURLOPT_USERNAME, 1, [Define if libcurl supports CURLOPT_USERNAME option.])
 +      fi
  fi
  AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
  # }}}
@@@ -1751,7 -1710,6 +1751,7 @@@ the
        LDFLAGS="$LDFLAGS $with_libdbi_ldflags"
  
        AC_CHECK_LIB(dbi, dbi_initialize, [with_libdbi="yes"], [with_libdbi="no (Symbol 'dbi_initialize' not found)"])
 +      AC_CHECK_LIB(dbi, dbi_driver_open_r, [with_libdbi_r="yes"], [with_libdbi_r="no"])
  
        CPPFLAGS="$SAVE_CPPFLAGS"
        LDFLAGS="$SAVE_LDFLAGS"
        AC_SUBST(BUILD_WITH_LIBDBI_CPPFLAGS)
        AC_SUBST(BUILD_WITH_LIBDBI_LDFLAGS)
        AC_SUBST(BUILD_WITH_LIBDBI_LIBS)
 +
 +  if test "x$with_libdbi_r" = "xyes"
 +  then
 +              AC_DEFINE(HAVE_LIBDBI_R, 1, [Define if reentrant dbi facility is present and usable.])
 +  fi
  fi
  AM_CONDITIONAL(BUILD_WITH_LIBDBI, test "x$with_libdbi" = "xyes")
  # }}}
@@@ -1964,7 -1917,7 +1964,7 @@@ the
                [with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
  
        if test "$with_libgcrypt" != "no"; then
 -              AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")
 +              m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
                GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
                GCRYPT_LIBS="$LIBGCRYPT_LIBS"
        fi
@@@ -1987,7 -1940,10 +1987,7 @@@ AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, te
  # --with-libiptc {{{
  AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
  [
 -      if test "x$withval" = "xshipped"
 -      then
 -              with_libiptc="own"
 -      else if test "x$withval" = "xyes"
 +      if test "x$withval" = "xyes"
        then
                with_libiptc="pkgconfig"
        else if test "x$withval" = "xno"
                with_libiptc="yes"
                with_libiptc_cflags="-I$withval/include"
                with_libiptc_libs="-L$withval/lib"
 -      fi; fi; fi
 +      fi; fi
  ],
  [
        if test "x$ac_system" = "xLinux"
  
  CPPFLAGS="$SAVE_CPPFLAGS"
  
 -if test "x$with_libiptc" = "xown"
 -then
 -      with_libiptc_cflags=""
 -      with_libiptc_libs=""
 -fi
 -if test "x$with_libiptc" = "xown"
 -then
 -      AC_CHECK_HEADERS(linux/netfilter_ipv4/ip_tables.h linux/netfilter_ipv6/ip6_tables.h linux/netfilter/x_tables.h, [],
 -      [
 -              with_libiptc="no (Linux iptables headers not found)"
 -      ],
 -      [
 -#include "$srcdir/src/owniptc/ipt_kernel_headers.h"
 -      ])
 -fi
 -AM_CONDITIONAL(BUILD_WITH_OWN_LIBIPTC, test "x$with_libiptc" = "xown")
 -if test "x$with_libiptc" = "xown"
 -then
 -      AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
 -      with_libiptc="yes"
 -fi
 -
  AM_CONDITIONAL(BUILD_WITH_LIBIPTC, test "x$with_libiptc" = "xyes")
  if test "x$with_libiptc" = "xyes"
  then
@@@ -2248,64 -2226,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=""
@@@ -2340,7 -2260,7 +2340,7 @@@ the
          CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
          LDFLAGS="$LDFLAGS $with_liblvm2app_ldflags"
  
 -        AC_CHECK_LIB(lvm2app, lvm_init, [with_liblvm2app="yes"], [with_liblvm2app="no (Symbol 'lvm_init' not found)"])
 +        AC_CHECK_LIB(lvm2app, lvm_lv_get_property, [with_liblvm2app="yes"], [with_liblvm2app="no (Symbol 'lvm_lv_get_property' not found)"])
  
          CPPFLAGS="$SAVE_CPPFLAGS"
          LDFLAGS="$SAVE_LDFLAGS"
@@@ -2874,7 -2794,7 +2874,7 @@@ the
        else
                SAVE_CPPFLAGS="$CPPFLAGS"
                CPPFLAGS="$CPPFLAGS $with_snmp_cflags"
 -              
 +
                AC_CHECK_HEADERS(net-snmp/net-snmp-config.h, [], [with_libnetsnmp="no (net-snmp/net-snmp-config.h not found)"])
  
                CPPFLAGS="$SAVE_CPPFLAGS"
  if test "x$with_oracle" = "xyes"
  then
        SAVE_CPPFLAGS="$CPPFLAGS"
 -      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
        CPPFLAGS="$CPPFLAGS $with_oracle_cppflags"
 -      LDFLAGS="$LDFLAGS $with_oracle_libs"
 +      LIBS="$LIBS $with_oracle_libs"
  
        AC_CHECK_FUNC(OCIEnvCreate, [with_oracle="yes"], [with_oracle="no (Symbol 'OCIEnvCreate' not found)"])
  
        CPPFLAGS="$SAVE_CPPFLAGS"
 -      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
  fi
  if test "x$with_oracle" = "xyes"
  then
@@@ -3101,7 -3021,7 +3101,7 @@@ if test "x$with_libowcapi" = "xyes
  then
        SAVE_CPPFLAGS="$CPPFLAGS"
        CPPFLAGS="$with_libowcapi_cppflags"
 -      
 +
        AC_CHECK_HEADERS(owcapi.h, [with_libowcapi="yes"], [with_libowcapi="no (owcapi.h not found)"])
  
        CPPFLAGS="$SAVE_CPPFLAGS"
@@@ -3112,7 -3032,7 +3112,7 @@@ the
        SAVE_CPPFLAGS="$CPPFLAGS"
        LDFLAGS="$with_libowcapi_libs"
        CPPFLAGS="$with_libowcapi_cppflags"
 -      
 +
        AC_CHECK_LIB(owcapi, OW_get, [with_libowcapi="yes"], [with_libowcapi="no (libowcapi not found)"])
  
        LDFLAGS="$SAVE_LDFLAGS"
@@@ -3219,12 -3139,12 +3219,12 @@@ if test "x$with_libperl" = "xyes" 
        && test -n "$perl_interpreter"
  then
    SAVE_CFLAGS="$CFLAGS"
 -  SAVE_LDFLAGS="$LDFLAGS"
 +  SAVE_LIBS="$LIBS"
  dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string)
    PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts`
 -  PERL_LDFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
 +  PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts`
    CFLAGS="$CFLAGS $PERL_CFLAGS"
 -  LDFLAGS="$LDFLAGS $PERL_LDFLAGS"
 +  LIBS="$LIBS $PERL_LIBS"
  
    AC_CACHE_CHECK([for libperl],
      [c_cv_have_libperl],
    then
          AC_DEFINE(HAVE_LIBPERL, 1, [Define if libperl is present and usable.])
          AC_SUBST(PERL_CFLAGS)
 -        AC_SUBST(PERL_LDFLAGS)
 +        AC_SUBST(PERL_LIBS)
    else
          with_libperl="no"
    fi
  
    CFLAGS="$SAVE_CFLAGS"
 -  LDFLAGS="$SAVE_LDFLAGS"
 +  LIBS="$SAVE_LIBS"
  else if test -z "$perl_interpreter"; then
    with_libperl="no (no perl interpreter found)"
    c_cv_have_libperl="no"
@@@ -3267,9 -3187,9 +3267,9 @@@ AM_CONDITIONAL(BUILD_WITH_LIBPERL, tes
  if test "x$with_libperl" = "xyes"
  then
        SAVE_CFLAGS="$CFLAGS"
 -      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
        CFLAGS="$CFLAGS $PERL_CFLAGS"
 -      LDFLAGS="$LDFLAGS $PERL_LDFLAGS"
 +      LIBS="$LIBS $PERL_LIBS"
  
        AC_CACHE_CHECK([if perl supports ithreads],
                [c_cv_have_perl_ithreads],
        fi
  
        CFLAGS="$SAVE_CFLAGS"
 -      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
  fi
  
  if test "x$with_libperl" = "xyes"
  then
        SAVE_CFLAGS="$CFLAGS"
 -      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
        # trigger an error if Perl_load_module*() uses __attribute__nonnull__(3)
        # (see issues #41 and #42)
        CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror"
 -      LDFLAGS="$LDFLAGS $PERL_LDFLAGS"
 +      LIBS="$LIBS $PERL_LIBS"
  
        AC_CACHE_CHECK([for broken Perl_load_module()],
                [c_cv_have_broken_perl_load_module],
        )
  
        CFLAGS="$SAVE_CFLAGS"
 -      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
  fi
  AM_CONDITIONAL(HAVE_BROKEN_PERL_LOAD_MODULE,
                test "x$c_cv_have_broken_perl_load_module" = "xyes")
  if test "x$with_libperl" = "xyes"
  then
        SAVE_CFLAGS="$CFLAGS"
 -      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
        CFLAGS="$CFLAGS $PERL_CFLAGS"
 -      LDFLAGS="$LDFLAGS $PERL_LDFLAGS"
 +      LIBS="$LIBS $PERL_LIBS"
  
        AC_CHECK_MEMBER(
                [struct mgvtbl.svt_local],
        fi
  
        CFLAGS="$SAVE_CFLAGS"
 -      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
  fi
  # }}}
  
  CPPFLAGS="$SAVE_CPPFLAGS"
  LDFLAGS="$SAVE_LDFLAGS"
  AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes")
 +
 +with_amqp_tcp_socket="no"
 +if test "x$with_librabbitmq" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      SAVE_LIBS="$LIBS"
 +      CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags"
 +      LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags"
 +      LIBS="-lrabbitmq"
 +
 +      AC_CHECK_HEADERS(amqp_tcp_socket.h amqp_socket.h)
 +      AC_CHECK_FUNC(amqp_tcp_socket_new, [with_amqp_tcp_socket="yes"], [with_amqp_tcp_socket="no"])
 +      if test "x$with_amqp_tcp_socket" = "xyes"
 +      then
 +              AC_DEFINE(HAVE_AMQP_TCP_SOCKET, 1,
 +                              [Define if librabbitmq provides the new TCP socket interface.])
 +      fi
 +
 +      AC_CHECK_DECLS(amqp_socket_close,
 +                              [amqp_socket_close_decl="yes"], [amqp_socket_close_decl="no"],
 +                              [[
 +#include <amqp.h>
 +#ifdef HAVE_AMQP_TCP_SOCKET_H
 +# include <amqp_tcp_socket.h>
 +#endif
 +#ifdef HAVE_AMQP_SOCKET_H
 +# include <amqp_socket.h>
 +#endif
 +                              ]])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      LDFLAGS="$SAVE_LDFLAGS"
 +      LIBS="$SAVE_LIBS"
 +fi
 +# }}}
 +
 +# --with-librdkafka {{{
 +AC_ARG_WITH(librdkafka, [AS_HELP_STRING([--with-librdkafka@<:@=PREFIX@:>@], [Path to librdkafka.])],
 +[
 +  if test "x$withval" = "xno" && test "x$withval" != "xyes"
 +  then
 +    with_librdkafka_cppflags="-I$withval/include"
 +    with_librdkafka_ldflags="-L$withval/lib"
 +    with_librdkafka="yes"
 +  else
 +    with_librdkafka="$withval"
 +  fi
 +],
 +[
 +  with_librdkafka="yes"
 +])
 +SAVE_CPPFLAGS="$CPPFLAGS"
 +SAVE_LDFLAGS="$LDFLAGS"
 +
 +if test "x$with_librdkafka" = "xyes"
 +then
 +      AC_CHECK_HEADERS(librdkafka/rdkafka.h, [with_librdkafka="yes"], [with_librdkafka="no (librdkafka/rdkafka.h not found)"])
 +fi
 +
 +if test "x$with_librdkafka" = "xyes"
 +then
 +      AC_CHECK_LIB(rdkafka, rd_kafka_new, [with_librdkafka="yes"], [with_librdkafka="no (Symbol 'rd_kafka_new' not found)"])
 +  AC_CHECK_LIB(rdkafka, rd_kafka_conf_set_log_cb, [with_librdkafka_log_cb="yes"], [with_librdkafka_log_cb="no"])
 +  AC_CHECK_LIB(rdkafka, rd_kafka_conf_set_logger, [with_librdkafka_logger="yes"], [with_librdkafka_logger="no"])
 +fi
 +if test "x$with_librdkafka" = "xyes"
 +then
 +      BUILD_WITH_LIBRDKAFKA_CPPFLAGS="$with_librdkafka_cppflags"
 +      BUILD_WITH_LIBRDKAFKA_LDFLAGS="$with_librdkafka_ldflags"
 +      BUILD_WITH_LIBRDKAFKA_LIBS="-lrdkafka"
 +      AC_SUBST(BUILD_WITH_LIBRDKAFKA_CPPFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBRDKAFKA_LIBS)
 +      AC_DEFINE(HAVE_LIBRDKAFKA, 1, [Define if librdkafka is present and usable.])
 +  if test "x$with_librdkafka_log_cb" = "xyes"
 +  then
 +        AC_DEFINE(HAVE_LIBRDKAFKA_LOG_CB, 1, [Define if librdkafka log facility is present and usable.])
 +  fi
 +  if test "x$with_librdkafka_logger" = "xyes"
 +  then
 +        AC_DEFINE(HAVE_LIBRDKAFKA_LOGGER, 1, [Define if librdkafka log facility is present and usable.])
 +  fi
 +fi
 +CPPFLAGS="$SAVE_CPPFLAGS"
 +LDFLAGS="$SAVE_LDFLAGS"
 +AM_CONDITIONAL(BUILD_WITH_LIBRDKAFKA, test "x$with_librdkafka" = "xyes")
 +
  # }}}
  
  # --with-librouteros {{{
@@@ -3978,20 -3810,18 +3978,20 @@@ AC_ARG_WITH(libsigrok, [AS_HELP_STRING(
                        with_libsigrok_ldflags="-L$withval/lib"
                fi
        fi
 -],[])
 +],[with_libsigrok="yes"])
  
  # libsigrok has a glib dependency
  if test "x$with_libsigrok" = "xyes"
  then
 -      if test -z "m4_ifdef([AM_PATH_GLIB_2_0], [yes], [])"
 -      then
 -              with_libsigrok="no (glib not available)"
 -      else
 -              AM_PATH_GLIB_2_0([2.28.0],
 -                      [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"])
 -      fi
 +m4_ifdef([AM_PATH_GLIB_2_0],
 +      [
 +       AM_PATH_GLIB_2_0([2.28.0],
 +              [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"])
 +      ],
 +      [
 +       with_libsigrok="no (glib not available)"
 +      ]
 +)
  fi
  
  # libsigrok headers
    LDFLAGS="$SAVE_LDFLAGS"
  fi
  
 +if test "x$with_libstatgrab" = "xyes"
 +then
 +  SAVE_CFLAGS="$CFLAGS"
 +  SAVE_LIBS="$LIBS"
 +
 +  CFLAGS="$CFLAGS $with_libstatgrab_cflags"
 +  LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
 +  LIBS="-lstatgrab $LIBS"
 +
 +  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"
 +  LIBS="$SAVE_LIBS"
 +fi
 +
  AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
  if test "x$with_libstatgrab" = "xyes"
  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
  # }}}
  
@@@ -4209,8 -4005,8 +4209,8 @@@ the
    if $PKG_CONFIG --exists tokyotyrant
    then
      with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`"
 -    with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `pkg-config --libs-only-L tokyotyrant`"
 -    with_libtokyotyrant_libs="$with_libtokyotyrant_libs `pkg-config --libs-only-l tokyotyrant`"
 +    with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `$PKG_CONFIG --libs-only-L tokyotyrant`"
 +    with_libtokyotyrant_libs="$with_libtokyotyrant_libs `$PKG_CONFIG --libs-only-l tokyotyrant`"
    fi
  fi
  
@@@ -4243,7 -4039,7 +4243,7 @@@ CPPFLAGS="$SAVE_CPPFLAGS
  LDFLAGS="$SAVE_LDFLAGS"
  
  if test "x$with_libtokyotyrant" = "xyes"
 -then 
 +then
    BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS="$with_libtokyotyrant_cppflags"
    BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS="$with_libtokyotyrant_ldflags"
    BUILD_WITH_LIBTOKYOTYRANT_LIBS="$with_libtokyotyrant_libs"
  AM_CONDITIONAL(BUILD_WITH_LIBTOKYOTYRANT, test "x$with_libtokyotyrant" = "xyes")
  # }}}
  
 +# --with-libudev {{{
 +with_libudev_cflags=""
 +with_libudev_ldflags=""
 +AC_ARG_WITH(libudev, [AS_HELP_STRING([--with-libudev@<:@=PREFIX@:>@], [Path to libudev.])],
 +[
 +      if test "x$withval" = "xno"
 +      then
 +              with_libudev="no"
 +      else
 +              with_libudev="yes"
 +              if test "x$withval" != "xyes"
 +              then
 +                      with_libudev_cflags="-I$withval/include"
 +                      with_libudev_ldflags="-L$withval/lib"
 +                      with_libudev="yes"
 +              fi
 +      fi
 +],
 +[
 +      if test "x$ac_system" = "xLinux"
 +      then
 +              with_libudev="yes"
 +      else
 +              with_libudev="no (Linux only library)"
 +      fi
 +])
 +if test "x$with_libudev" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
 +
 +      AC_CHECK_HEADERS(libudev.h, [], [with_libudev="no (libudev.h not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +fi
 +if test "x$with_libudev" = "xyes"
 +then
 +      SAVE_CPPFLAGS="$CPPFLAGS"
 +      SAVE_LDFLAGS="$LDFLAGS"
 +      CPPFLAGS="$CPPFLAGS $with_libudev_cflags"
 +      LDFLAGS="$LDFLAGS $with_libudev_ldflags"
 +
 +      AC_CHECK_LIB(udev, udev_new,
 +      [
 +              AC_DEFINE(HAVE_LIBUDEV, 1, [Define to 1 if you have the udev library (-ludev).])
 +      ],
 +      [with_libudev="no (libudev not found)"])
 +
 +      CPPFLAGS="$SAVE_CPPFLAGS"
 +      LDFLAGS="$SAVE_LDFLAGS"
 +fi
 +if test "x$with_libudev" = "xyes"
 +then
 +      BUILD_WITH_LIBUDEV_CFLAGS="$with_libudev_cflags"
 +      BUILD_WITH_LIBUDEV_LDFLAGS="$with_libudev_ldflags"
 +      AC_SUBST(BUILD_WITH_LIBUDEV_CFLAGS)
 +      AC_SUBST(BUILD_WITH_LIBUDEV_LDFLAGS)
 +fi
 +AM_CONDITIONAL(BUILD_WITH_LIBUDEV, test "x$with_libudev" = "xyes")
 +# }}}
 +
  # --with-libupsclient {{{
  with_libupsclient_config=""
  with_libupsclient_cflags=""
  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
@@@ -4720,7 -4462,7 +4720,7 @@@ with_libvirt_cflags="
  with_libvirt_ldflags=""
  if test "x$PKG_CONFIG" != "x"
  then
 -      pkg-config --exists 'libxml-2.0' 2>/dev/null
 +      $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null
        if test "$?" = "0"
        then
                with_libxml2="yes"
                with_libxml2="no (pkg-config doesn't know libxml-2.0)"
        fi
  
 -      pkg-config --exists libvirt 2>/dev/null
 +      $PKG_CONFIG --exists libvirt 2>/dev/null
        if test "$?" = "0"
        then
                with_libvirt="yes"
  fi
  if test "x$with_libxml2" = "xyes"
  then
 -      with_libxml2_cflags="`pkg-config --cflags libxml-2.0`"
 +      with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`"
        if test $? -ne 0
        then
                with_libxml2="no"
        fi
 -      with_libxml2_ldflags="`pkg-config --libs libxml-2.0`"
 +      with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`"
        if test $? -ne 0
        then
                with_libxml2="no"
@@@ -4783,12 -4525,12 +4783,12 @@@ if test "x$with_libxml2" = "xyes"; the
  fi
  if test "x$with_libvirt" = "xyes"
  then
 -      with_libvirt_cflags="`pkg-config --cflags libvirt`"
 +      with_libvirt_cflags="`$PKG_CONFIG --cflags libvirt`"
        if test $? -ne 0
        then
                with_libvirt="no"
        fi
 -      with_libvirt_ldflags="`pkg-config --libs libvirt`"
 +      with_libvirt_ldflags="`$PKG_CONFIG --libs libvirt`"
        if test $? -ne 0
        then
                with_libvirt="no"
  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
@@@ -5100,9 -4786,9 +5100,10 @@@ dependency_warning="no
  dependency_error="no"
  
  plugin_ascent="no"
 +plugin_barometer="no"
  plugin_battery="no"
  plugin_bind="no"
+ plugin_ceph="no"
  plugin_cgroups="no"
  plugin_conntrack="no"
  plugin_contextswitch="no"
@@@ -5112,7 -4798,6 +5113,7 @@@ plugin_curl_json="no
  plugin_curl_xml="no"
  plugin_df="no"
  plugin_disk="no"
 +plugin_drbd="no"
  plugin_entropy="no"
  plugin_ethstat="no"
  plugin_fscache="no"
@@@ -5120,8 -4805,8 +5121,8 @@@ plugin_interface="no
  plugin_ipmi="no"
  plugin_ipvs="no"
  plugin_irq="no"
 -plugin_libvirt="no"
  plugin_load="no"
 +plugin_log_logstash="no"
  plugin_memory="no"
  plugin_multimeter="no"
  plugin_nfs="no"
@@@ -5135,14 -4820,12 +5136,14 @@@ plugin_tape="no
  plugin_tcpconns="no"
  plugin_ted="no"
  plugin_thermal="no"
 -plugin_users="no"
  plugin_uptime="no"
 +plugin_users="no"
 +plugin_virt="no"
  plugin_vmem="no"
  plugin_vserver="no"
  plugin_wireless="no"
  plugin_zfs_arc="no"
 +plugin_zookeeper="no"
  
  # Linux
  if test "x$ac_system" = "xLinux"
@@@ -5154,7 -4837,6 +5155,7 @@@ the
        plugin_cpu="yes"
        plugin_cpufreq="yes"
        plugin_disk="yes"
 +      plugin_drbd="yes"
        plugin_entropy="yes"
        plugin_fscache="yes"
        plugin_interface="yes"
        plugin_vmem="yes"
        plugin_vserver="yes"
        plugin_wireless="yes"
 +      plugin_zfs_arc="yes"
  
        if test "x$have_linux_ip_vs_h" = "xyes" || test "x$have_net_ip_vs_h" = "xyes" || test "x$have_ip_vs_h" = "xyes"
        then
        plugin_tape="yes"
  fi
  
 +# libi2c-dev
 +with_libi2c="no"
 +if test "x$ac_system" = "xLinux"
 +then
 +AC_CHECK_DECL(i2c_smbus_read_i2c_block_data,
 +      [with_libi2c="yes"],
 +      [with_libi2c="no (symbol i2c_smbus_read_i2c_block_data not found - have you installed libi2c-dev ?)"],
 +      [[#include <stdlib.h>
 +      #include <linux/i2c-dev.h>]])
 +fi
 +
 +if test "x$with_libi2c" = "xyes"
 +then
 +      plugin_barometer="yes"
 +fi
 +
 +
  # libstatgrab
  if test "x$with_libstatgrab" = "xyes"
  then
        plugin_curl_xml="yes"
  fi
  
+ if test "x$with_libyajl" = "xyes"
+ then
+       plugin_ceph="yes"
+ fi
  if test "x$have_processor_info" = "xyes"
  then
        plugin_cpu="yes"
        plugin_interface="yes"
  fi
  
 -if test "x$with_libxml2" = "xyes" && test "x$with_libvirt" = "xyes"
 +if test "x$have_getloadavg" = "xyes"
  then
 -      plugin_libvirt="yes"
 +      plugin_load="yes"
  fi
  
 -if test "x$have_getloadavg" = "xyes"
 +if test "x$with_libyajl" = "xyes"
  then
 -      plugin_load="yes"
 +      plugin_log_logstash="yes"
  fi
  
  if test "x$c_cv_have_libperl$c_cv_have_perl_ithreads" = "xyesyes"
  
  if test "x$have_termios_h" = "xyes"
  then
 -      plugin_multimeter="yes"
 +      if test "x$ac_system" != "xAIX"
 +      then
 +              plugin_multimeter="yes"
 +      fi
        plugin_ted="yes"
  fi
  
        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"
        plugin_users="yes"
  fi
  
 +if test "x$with_libxml2" = "xyes" && test "x$with_libvirt" = "xyes"
 +then
 +      plugin_virt="yes"
 +fi
 +
 +
  m4_divert_once([HELP_ENABLE], [
  collectd plugins:])
  
@@@ -5465,9 -5120,9 +5471,10 @@@ AC_PLUGIN([apcups],      [yes]
  AC_PLUGIN([apple_sensors], [$with_libiokit],   [Apple's hardware sensors])
  AC_PLUGIN([aquaero],     [$with_libaquaero5],  [Aquaero's hardware sensors])
  AC_PLUGIN([ascent],      [$plugin_ascent],     [AscentEmu player statistics])
 +AC_PLUGIN([barometer],   [$plugin_barometer],  [Barometer sensor on I2C])
  AC_PLUGIN([battery],     [$plugin_battery],    [Battery statistics])
  AC_PLUGIN([bind],        [$plugin_bind],       [ISC Bind nameserver statistics])
+ AC_PLUGIN([ceph],        [$plugin_ceph],       [Ceph daemon statistics])
  AC_PLUGIN([conntrack],   [$plugin_conntrack],  [nf_conntrack statistics])
  AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
  AC_PLUGIN([cpufreq],     [$plugin_cpufreq],    [CPU frequency statistics])
@@@ -5480,7 -5135,6 +5487,7 @@@ AC_PLUGIN([cgroups],     [$plugin_cgrou
  AC_PLUGIN([dbi],         [$with_libdbi],       [General database statistics])
  AC_PLUGIN([df],          [$plugin_df],         [Filesystem usage statistics])
  AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
 +AC_PLUGIN([drbd],        [$plugin_drbd],       [DRBD statistics])
  AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
  AC_PLUGIN([email],       [yes],                [EMail statistics])
  AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
@@@ -5496,9 -5150,9 +5503,9 @@@ AC_PLUGIN([iptables],    [$with_libiptc
  AC_PLUGIN([ipvs],        [$plugin_ipvs],       [IPVS connection statistics])
  AC_PLUGIN([irq],         [$plugin_irq],        [IRQ statistics])
  AC_PLUGIN([java],        [$with_java],         [Embed the Java Virtual Machine])
 -AC_PLUGIN([libvirt],     [$plugin_libvirt],    [Virtual machine statistics])
  AC_PLUGIN([load],        [$plugin_load],       [System load])
  AC_PLUGIN([logfile],     [yes],                [File logging plugin])
 +AC_PLUGIN([log_logstash], [$plugin_log_logstash], [Logstash json_event compatible logging])
  AC_PLUGIN([lpar],        [$with_perfstat],     [AIX logical partitions statistics])
  AC_PLUGIN([lvm],         [$with_liblvm2app],   [LVM statistics])
  AC_PLUGIN([madwifi],     [$have_linux_wireless_h], [Madwifi wireless statistics])
@@@ -5528,7 -5182,6 +5535,7 @@@ AC_PLUGIN([numa],        [$plugin_numa]
  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])
@@@ -5541,14 -5194,13 +5548,14 @@@ AC_PLUGIN([powerdns],    [yes]
  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])
@@@ -5573,27 -5225,21 +5580,27 @@@ AC_PLUGIN([uptime],      [$plugin_uptim
  AC_PLUGIN([users],       [$plugin_users],      [User statistics])
  AC_PLUGIN([uuid],        [yes],                [UUID as hostname plugin])
  AC_PLUGIN([varnish],     [$with_libvarnish],   [Varnish cache statistics])
 +AC_PLUGIN([virt],        [$plugin_virt],       [Virtual machine statistics])
  AC_PLUGIN([vmem],        [$plugin_vmem],       [Virtual memory statistics])
  AC_PLUGIN([vserver],     [$plugin_vserver],    [Linux VServer statistics])
  AC_PLUGIN([wireless],    [$plugin_wireless],   [Wireless statistics])
  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_log], [yes],                  [Log 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])
  AC_PLUGIN([zfs_arc],     [$plugin_zfs_arc],    [ZFS ARC statistics])
 +AC_PLUGIN([zookeeper],   [yes],              [Zookeeper statistics])
  
  dnl Default configuration file
  # Load either syslog or logfile
  LOAD_PLUGIN_SYSLOG=""
  LOAD_PLUGIN_LOGFILE=""
 +LOAD_PLUGIN_LOG_LOGSTASH=""
  
  AC_MSG_CHECKING([which default log plugin to load])
  default_log_plugin="none"
  else
        LOAD_PLUGIN_LOGFILE="##"
  fi
 +
 +if test "x$enable_log_logstash" = "xyes"
 +then
 +  LOAD_PLUGIN_LOG_LOGSTASH="#"
 +else
 +  LOAD_PLUGIN_LOG_LOGSTASH="##"
 +fi
 +
 +
  AC_MSG_RESULT([$default_log_plugin])
  
  AC_SUBST(LOAD_PLUGIN_SYSLOG)
  AC_SUBST(LOAD_PLUGIN_LOGFILE)
 +AC_SUBST(LOAD_PLUGIN_LOG_LOGSTASH)
  
  DEFAULT_LOG_LEVEL="info"
  if test "x$enable_debug" = "xyes"
@@@ -5738,7 -5374,7 +5745,7 @@@ AC_SUBST(LCC_VERSION_STRING
  
  AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
  
 -AC_CONFIG_FILES([Makefile src/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
 +AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
  AC_OUTPUT
  
  if test "x$with_librrd" = "xyes" \
@@@ -5771,21 -5407,17 +5778,21 @@@ 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
 +    libi2c-dev  . . . . . $with_libi2c
      libiokit  . . . . . . $with_libiokit
      libiptc . . . . . . . $with_libiptc
      libjvm  . . . . . . . $with_java
      libkstat  . . . . . . $with_kstat
      libkvm  . . . . . . . $with_libkvm
 +    libldap . . . . . . . $with_libldap
 +    liblvm2app  . . . . . $with_liblvm2app
      libmemcached  . . . . $with_libmemcached
      libmnl  . . . . . . . $with_libmnl
      libmodbus . . . . . . $with_libmodbus
      libpq . . . . . . . . $with_libpq
      libpthread  . . . . . $with_libpthread
      librabbitmq . . . . . $with_librabbitmq
 +    librdkafka  . . . . . $with_librdkafka
      librouteros . . . . . $with_librouteros
      librrd  . . . . . . . $with_librrd
      libsensors  . . . . . $with_libsensors
      libsigrok   . . . . . $with_libsigrok
      libstatgrab . . . . . $with_libstatgrab
      libtokyotyrant  . . . $with_libtokyotyrant
 +    libudev . . . . . . . $with_libudev
      libupsclient  . . . . $with_libupsclient
      libvarnish  . . . . . $with_libvarnish
      libvirt . . . . . . . $with_libvirt
      aquaero . . . . . . . $enable_aquaero
      apple_sensors . . . . $enable_apple_sensors
      ascent  . . . . . . . $enable_ascent
 +    barometer . . . . . . $enable_barometer
      battery . . . . . . . $enable_battery
      bind  . . . . . . . . $enable_bind
+     ceph  . . . . . . . . $enable_ceph
      conntrack . . . . . . $enable_conntrack
      contextswitch . . . . $enable_contextswitch
      cgroups . . . . . . . $enable_cgroups
      df  . . . . . . . . . $enable_df
      disk  . . . . . . . . $enable_disk
      dns . . . . . . . . . $enable_dns
 +    drbd  . . . . . . . . $enable_drbd
      email . . . . . . . . $enable_email
      entropy . . . . . . . $enable_entropy
      ethstat . . . . . . . $enable_ethstat
      ipvs  . . . . . . . . $enable_ipvs
      irq . . . . . . . . . $enable_irq
      java  . . . . . . . . $enable_java
 -    libvirt . . . . . . . $enable_libvirt
      load  . . . . . . . . $enable_load
      logfile . . . . . . . $enable_logfile
      lpar  . . . . . . . . $enable_lpar
 +    log_logstash  . . . . $enable_log_logstash
      lvm . . . . . . . . . $enable_lvm
      madwifi . . . . . . . $enable_madwifi
      match_empty_counter . $enable_match_empty_counter
      nut . . . . . . . . . $enable_nut
      olsrd . . . . . . . . $enable_olsrd
      onewire . . . . . . . $enable_onewire
 +    openldap  . . . . . . $enable_openldap
      openvpn . . . . . . . $enable_openvpn
      oracle  . . . . . . . $enable_oracle
      perl  . . . . . . . . $enable_perl
      sensors . . . . . . . $enable_sensors
      serial  . . . . . . . $enable_serial
      sigrok  . . . . . . . $enable_sigrok
 +    smart . . . . . . . . $enable_smart
      snmp  . . . . . . . . $enable_snmp
      statsd  . . . . . . . $enable_statsd
      swap  . . . . . . . . $enable_swap
      users . . . . . . . . $enable_users
      uuid  . . . . . . . . $enable_uuid
      varnish . . . . . . . $enable_varnish
 +    virt  . . . . . . . . $enable_virt
      vmem  . . . . . . . . $enable_vmem
      vserver . . . . . . . $enable_vserver
      wireless  . . . . . . $enable_wireless
      write_graphite  . . . $enable_write_graphite
      write_http  . . . . . $enable_write_http
 +    write_kafka . . . . . $enable_write_kafka
 +    write_log . . . . . . $enable_write_log
      write_mongodb . . . . $enable_write_mongodb
      write_redis . . . . . $enable_write_redis
      write_riemann . . . . $enable_write_riemann
 +    write_tsdb  . . . . . $enable_write_tsdb
      xmms  . . . . . . . . $enable_xmms
      zfs_arc . . . . . . . $enable_zfs_arc
 +    zookeeper . . . . . . $enable_zookeeper
  
  EOF
  
diff --combined src/Makefile.am
@@@ -2,16 -2,12 +2,16 @@@ SUBDIRS = libcollectdclien
  if BUILD_WITH_OWN_LIBOCONFIG
  SUBDIRS += liboconfig
  endif
 +SUBDIRS += daemon
 +
 +PLUGIN_LDFLAGS = -module -avoid-version -export-symbols-regex '\<module_register\>'
  
  if COMPILER_IS_GCC
  AM_CFLAGS = -Wall -Werror
  endif
  
 -AM_CPPFLAGS = -DPREFIX='"${prefix}"'
 +AM_CPPFLAGS = -I$(srcdir)/daemon
 +AM_CPPFLAGS += -DPREFIX='"${prefix}"'
  AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
  AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
  AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
@@@ -21,16 -17,81 +21,16 @@@ endi
  AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
  AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
  
 -sbin_PROGRAMS = collectd collectdmon
 -bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
 -
 -collectd_SOURCES = collectd.c collectd.h \
 -                 common.c common.h \
 -                 configfile.c configfile.h \
 -                 filter_chain.c filter_chain.h \
 -                 meta_data.c meta_data.h \
 -                 plugin.c plugin.h \
 -                 utils_avltree.c utils_avltree.h \
 -                 utils_cache.c utils_cache.h \
 -                 utils_complain.c utils_complain.h \
 -                 utils_heap.c utils_heap.h \
 -                 utils_ignorelist.c utils_ignorelist.h \
 -                 utils_llist.c utils_llist.h \
 -                 utils_parse_option.c utils_parse_option.h \
 -                 utils_random.c utils_random.h \
 -                 utils_tail_match.c utils_tail_match.h \
 -                 utils_match.c utils_match.h \
 -                 utils_subst.c utils_subst.h \
 -                 utils_tail.c utils_tail.h \
 -                 utils_time.c utils_time.h \
 -                 types_list.c types_list.h
 -
 -collectd_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL)
 -collectd_CFLAGS = $(AM_CFLAGS)
 -collectd_LDFLAGS = -export-dynamic
 -collectd_LDADD = -lm
 -collectd_DEPENDENCIES =
 -
 -# Link to these libraries..
 -if BUILD_WITH_LIBRT
 -collectd_LDADD += -lrt
 -endif
 -if BUILD_WITH_LIBPOSIX4
 -collectd_LDADD += -lposix4
 -endif
 -if BUILD_WITH_LIBSOCKET
 -collectd_LDADD += -lsocket
 -endif
 -if BUILD_WITH_LIBRESOLV
 -collectd_LDADD += -lresolv
 -endif
 -if BUILD_WITH_LIBPTHREAD
 -collectd_LDADD += -lpthread
 -endif
 -if BUILD_WITH_LIBKSTAT
 -collectd_LDADD += -lkstat
 -endif
 -if BUILD_WITH_LIBDEVINFO
 -collectd_LDADD += -ldevinfo
 -endif
 -if BUILD_AIX
 -collectd_LDFLAGS += -Wl,-bexpall,-brtllib
 -endif
 -
 -# The daemon needs to call sg_init, so we need to link it against libstatgrab,
 -# too. -octo
 -if BUILD_WITH_LIBSTATGRAB
 -collectd_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
 -collectd_LDADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
 -endif
 +AUTOMAKE_OPTIONS = subdir-objects
  
 -if BUILD_WITH_OWN_LIBOCONFIG
 -collectd_LDADD += $(LIBLTDL) liboconfig/liboconfig.la
 -collectd_DEPENDENCIES += liboconfig/liboconfig.la
 -else
 -collectd_LDADD += -loconfig
 -endif
 +sbin_PROGRAMS = collectdmon
 +bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
  
  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 -105,7 +44,7 @@@ collectd_nagios_DEPENDENCIES = libcolle
  
  
  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
@@@ -56,8 -117,8 +56,8 @@@ collectdctl_LDADD += libcollectdclient/
  collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
  
  collectd_tg_SOURCES = collectd-tg.c \
 -                    utils_heap.c utils_heap.h
 -collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
 +                    daemon/utils_heap.c daemon/utils_heap.h
 +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,24 -129,23 +68,24 @@@ endi
  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
  
  
 -pkglib_LTLIBRARIES = 
 +pkglib_LTLIBRARIES =
  
 -BUILT_SOURCES = 
 +BUILT_SOURCES =
  CLEANFILES =
  
  if BUILD_PLUGIN_AGGREGATION
  pkglib_LTLIBRARIES += aggregation.la
  aggregation_la_SOURCES = aggregation.c \
                           utils_vl_lookup.c utils_vl_lookup.h
 -aggregation_la_LDFLAGS = -module -avoid-version
 -aggregation_la_LIBADD =
 -collectd_LDADD += "-dlopen" aggregation.la
 -collectd_DEPENDENCIES += aggregation.la
 +aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +aggregation_la_LIBADD = -lm
  endif
  
  if BUILD_PLUGIN_AMQP
@@@ -94,113 -154,135 +94,122 @@@ amqp_la_SOURCES = amqp.c 
                  utils_cmd_putval.c utils_cmd_putval.h \
                  utils_format_graphite.c utils_format_graphite.h \
                  utils_format_json.c utils_format_json.h
 -amqp_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
 +amqp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
  amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
  amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS)
 -collectd_LDADD += "-dlopen" amqp.la
 -collectd_DEPENDENCIES += amqp.la
  endif
  
  if BUILD_PLUGIN_APACHE
  pkglib_LTLIBRARIES += apache.la
  apache_la_SOURCES = apache.c
 -apache_la_LDFLAGS = -module -avoid-version
 +apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  apache_la_CFLAGS = $(AM_CFLAGS)
  apache_la_LIBADD =
 -collectd_LDADD += "-dlopen" apache.la
  if BUILD_WITH_LIBCURL
  apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
  apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
  endif
 -collectd_DEPENDENCIES += apache.la
  endif
  
  if BUILD_PLUGIN_APCUPS
  pkglib_LTLIBRARIES += apcups.la
  apcups_la_SOURCES = apcups.c
 -apcups_la_LDFLAGS = -module -avoid-version
 +apcups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  apcups_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  apcups_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" apcups.la
 -collectd_DEPENDENCIES += apcups.la
  endif
  
  if BUILD_PLUGIN_APPLE_SENSORS
  pkglib_LTLIBRARIES += apple_sensors.la
  apple_sensors_la_SOURCES = apple_sensors.c
 -apple_sensors_la_LDFLAGS = -module -avoid-version
 +apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  apple_sensors_la_LDFLAGS += -framework IOKit
 -collectd_LDADD += "-dlopen" apple_sensors.la
 -collectd_DEPENDENCIES += apple_sensors.la
  endif
  
  if BUILD_PLUGIN_AQUAERO
  pkglib_LTLIBRARIES += aquaero.la
  aquaero_la_SOURCES = aquaero.c
 -aquaero_la_LDFLAGS = -module -avoid-version
 +aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
  aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
 -collectd_LDADD += "-dlopen" aquaero.la
 -collectd_DEPENDENCIES += aquaero.la
  endif
  
  if BUILD_PLUGIN_ASCENT
  pkglib_LTLIBRARIES += ascent.la
  ascent_la_SOURCES = ascent.c
 -ascent_la_LDFLAGS = -module -avoid-version
 +ascent_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  ascent_la_CFLAGS = $(AM_CFLAGS) \
                $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  ascent_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
 -collectd_LDADD += "-dlopen" ascent.la
 -collectd_DEPENDENCIES += ascent.la
 +endif
 +
 +if BUILD_PLUGIN_BAROMETER
 +pkglib_LTLIBRARIES += barometer.la
 +barometer_la_SOURCES = barometer.c
 +barometer_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +barometer_la_LIBADD = -lm
  endif
  
  if BUILD_PLUGIN_BATTERY
  pkglib_LTLIBRARIES += battery.la
  battery_la_SOURCES = battery.c
 -battery_la_LDFLAGS = -module -avoid-version
 +battery_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  battery_la_LIBADD =
  if BUILD_WITH_LIBIOKIT
  battery_la_LDFLAGS += -framework IOKit
  endif
 -collectd_LDADD += "-dlopen" battery.la
 -collectd_DEPENDENCIES += battery.la
  endif
  
  if BUILD_PLUGIN_BIND
  pkglib_LTLIBRARIES += bind.la
  bind_la_SOURCES = bind.c
 -bind_la_LDFLAGS = -module -avoid-version
 +bind_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  bind_la_CFLAGS = $(AM_CFLAGS) \
 -              $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
 +               $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  bind_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
 -collectd_LDADD += "-dlopen" bind.la
 -collectd_DEPENDENCIES += bind.la
  endif
  
+ if BUILD_PLUGIN_CEPH
+ pkglib_LTLIBRARIES += ceph.la
+ ceph_la_SOURCES = ceph.c
+ ceph_la_CFLAGS = $(AM_CFLAGS)
+ ceph_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+ ceph_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+ ceph_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+ endif
  if BUILD_PLUGIN_CGROUPS
  pkglib_LTLIBRARIES += cgroups.la
 -cgroups_la_SOURCES = cgroups.c utils_mount.c utils_mount.h
 -cgroups_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" cgroups.la
 -collectd_DEPENDENCIES += cgroups.la
 +cgroups_la_SOURCES = cgroups.c \
 +                   utils_ignorelist.c utils_ignorelist.h \
 +                   utils_mount.c utils_mount.h
 +cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_CONNTRACK
  pkglib_LTLIBRARIES += conntrack.la
  conntrack_la_SOURCES = conntrack.c
 -conntrack_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" conntrack.la
 -collectd_DEPENDENCIES += conntrack.la
 +conntrack_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_CONTEXTSWITCH
  pkglib_LTLIBRARIES += contextswitch.la
  contextswitch_la_SOURCES = contextswitch.c
 -contextswitch_la_LDFLAGS = -module -avoid-version
 +contextswitch_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  contextswitch_la_LIBADD =
  if BUILD_WITH_PERFSTAT
  contextswitch_la_LIBADD += -lperfstat
  endif
 -collectd_LDADD += "-dlopen" contextswitch.la
 -collectd_DEPENDENCIES += contextswitch.la
  endif
  
  if BUILD_PLUGIN_CPU
  pkglib_LTLIBRARIES += cpu.la
  cpu_la_SOURCES = cpu.c
  cpu_la_CFLAGS = $(AM_CFLAGS)
 -cpu_la_LDFLAGS = -module -avoid-version
 -cpu_la_LIBADD = 
 +cpu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +cpu_la_LIBADD =
  if BUILD_WITH_LIBKSTAT
  cpu_la_LIBADD += -lkstat
  endif
@@@ -214,52 -296,64 +223,52 @@@ endi
  if BUILD_WITH_PERFSTAT
  cpu_la_LIBADD += -lperfstat
  endif
 -collectd_LDADD += "-dlopen" cpu.la
 -collectd_DEPENDENCIES += cpu.la
  endif
  
  if BUILD_PLUGIN_CPUFREQ
  pkglib_LTLIBRARIES += cpufreq.la
  cpufreq_la_SOURCES = cpufreq.c
 -cpufreq_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" cpufreq.la
 -collectd_DEPENDENCIES += cpufreq.la
 +cpufreq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_CSV
  pkglib_LTLIBRARIES += csv.la
  csv_la_SOURCES = csv.c
 -csv_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" csv.la
 -collectd_DEPENDENCIES += csv.la
 +csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_CURL
  pkglib_LTLIBRARIES += curl.la
  curl_la_SOURCES = curl.c
 -curl_la_LDFLAGS = -module -avoid-version
 +curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  curl_la_CFLAGS = $(AM_CFLAGS)
  curl_la_LIBADD =
 -collectd_LDADD += "-dlopen" curl.la
  if BUILD_WITH_LIBCURL
  curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
  curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
  endif
 -collectd_DEPENDENCIES += curl.la
  endif
  
  if BUILD_PLUGIN_CURL_JSON
  pkglib_LTLIBRARIES += curl_json.la
  curl_json_la_SOURCES = curl_json.c
  curl_json_la_CFLAGS = $(AM_CFLAGS)
 -curl_json_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS)
 -curl_json_la_CPPFLAGS = $(BUILD_WITH_LIBYAJL_CPPFLAGS)
 +curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
 +curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
  curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
  if BUILD_WITH_LIBCURL
  curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
  curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
  endif
 -collectd_LDADD += "-dlopen" curl_json.la
 -collectd_DEPENDENCIES += curl_json.la
  endif
  
  if BUILD_PLUGIN_CURL_XML
  pkglib_LTLIBRARIES += curl_xml.la
  curl_xml_la_SOURCES = curl_xml.c
 -curl_xml_la_LDFLAGS = -module -avoid-version
 +curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  curl_xml_la_CFLAGS = $(AM_CFLAGS) \
                $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
  curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
 -collectd_LDADD += "-dlopen" curl_xml.la
 -collectd_DEPENDENCIES += curl_xml.la
  endif
  
  if BUILD_PLUGIN_DBI
@@@ -267,25 -361,26 +276,25 @@@ pkglib_LTLIBRARIES += dbi.l
  dbi_la_SOURCES = dbi.c \
                 utils_db_query.c utils_db_query.h
  dbi_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBDBI_CPPFLAGS)
 -dbi_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBDBI_LDFLAGS)
 +dbi_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBDBI_LDFLAGS)
  dbi_la_LIBADD = $(BUILD_WITH_LIBDBI_LIBS)
 -collectd_LDADD += "-dlopen" dbi.la
 -collectd_DEPENDENCIES += dbi.la
  endif
  
  if BUILD_PLUGIN_DF
  pkglib_LTLIBRARIES += df.la
 -df_la_SOURCES = df.c utils_mount.c utils_mount.h
 -df_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" df.la
 -collectd_DEPENDENCIES += df.la
 +df_la_SOURCES = df.c \
 +              utils_ignorelist.c utils_ignorelist.h \
 +              utils_mount.c utils_mount.h
 +df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_DISK
  pkglib_LTLIBRARIES += disk.la
 -disk_la_SOURCES = disk.c
 +disk_la_SOURCES = disk.c \
 +                utils_ignorelist.c utils_ignorelist.h
  disk_la_CFLAGS = $(AM_CFLAGS)
 -disk_la_LDFLAGS = -module -avoid-version
 -disk_la_LIBADD = 
 +disk_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +disk_la_LIBADD =
  if BUILD_WITH_LIBKSTAT
  disk_la_LIBADD += -lkstat
  endif
@@@ -296,91 -391,99 +305,91 @@@ if BUILD_WITH_LIBIOKI
  disk_la_LDFLAGS += -framework IOKit
  endif
  if BUILD_WITH_LIBSTATGRAB
 -disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)  
 +disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
  disk_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
  endif
 +if BUILD_WITH_LIBUDEV
 +disk_la_LIBADD += -ludev
 +endif
  if BUILD_WITH_PERFSTAT
  disk_la_LIBADD += -lperfstat
  endif
 -collectd_LDADD += "-dlopen" disk.la
 -collectd_DEPENDENCIES += disk.la
  endif
  
  if BUILD_PLUGIN_DNS
  pkglib_LTLIBRARIES += dns.la
  dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
 -dns_la_LDFLAGS = -module -avoid-version
 +dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  dns_la_LIBADD = -lpcap -lpthread
 -collectd_LDADD += "-dlopen" dns.la
 -collectd_DEPENDENCIES += dns.la
 +endif
 +
 +if BUILD_PLUGIN_DRBD
 +pkglib_LTLIBRARIES += drbd.la
 +drbd_la_SOURCES = drbd.c
 +drbd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +drbd_la_LIBADD = -lpthread
  endif
  
  if BUILD_PLUGIN_EMAIL
  pkglib_LTLIBRARIES += email.la
  email_la_SOURCES = email.c
 -email_la_LDFLAGS = -module -avoid-version
 +email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  email_la_LIBADD = -lpthread
 -collectd_LDADD += "-dlopen" email.la
 -collectd_DEPENDENCIES += email.la
  endif
  
  if BUILD_PLUGIN_ENTROPY
  pkglib_LTLIBRARIES += entropy.la
  entropy_la_SOURCES = entropy.c
 -entropy_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" entropy.la
 -collectd_DEPENDENCIES += entropy.la
 +entropy_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_EXEC
  pkglib_LTLIBRARIES += exec.la
  exec_la_SOURCES = exec.c \
                  utils_cmd_putnotif.c utils_cmd_putnotif.h \
 -                utils_cmd_putval.c utils_cmd_putval.h
 -exec_la_LDFLAGS = -module -avoid-version
 +                utils_cmd_putval.c utils_cmd_putval.h \
 +                utils_parse_option.h utils_parse_option.c
 +exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  exec_la_LIBADD = -lpthread
 -collectd_LDADD += "-dlopen" exec.la
 -collectd_DEPENDENCIES += exec.la
  endif
  
  if BUILD_PLUGIN_ETHSTAT
  pkglib_LTLIBRARIES += ethstat.la
  ethstat_la_SOURCES = ethstat.c
 -ethstat_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" ethstat.la
 -collectd_DEPENDENCIES += ethstat.la
 +ethstat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_FILECOUNT
  pkglib_LTLIBRARIES += filecount.la
  filecount_la_SOURCES = filecount.c
 -filecount_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" filecount.la
 -collectd_DEPENDENCIES += filecount.la
 +filecount_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_GMOND
  pkglib_LTLIBRARIES += gmond.la
  gmond_la_SOURCES = gmond.c
  gmond_la_CPPFLAGS = $(AM_CPPFLAGS) $(GANGLIA_CPPFLAGS)
 -gmond_la_LDFLAGS = -module -avoid-version $(GANGLIA_LDFLAGS)
 +gmond_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(GANGLIA_LDFLAGS)
  gmond_la_LIBADD = $(GANGLIA_LIBS)
 -collectd_LDADD += "-dlopen" gmond.la
 -collectd_DEPENDENCIES += gmond.la
  endif
  
  if BUILD_PLUGIN_HDDTEMP
  pkglib_LTLIBRARIES += hddtemp.la
  hddtemp_la_SOURCES = hddtemp.c
 -hddtemp_la_LDFLAGS = -module -avoid-version
 +hddtemp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  hddtemp_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  hddtemp_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" hddtemp.la
 -collectd_DEPENDENCIES += hddtemp.la
  endif
  
  if BUILD_PLUGIN_INTERFACE
  pkglib_LTLIBRARIES += interface.la
 -interface_la_SOURCES = interface.c
 +interface_la_SOURCES = interface.c \
 +                     utils_ignorelist.c utils_ignorelist.h
  interface_la_CFLAGS = $(AM_CFLAGS)
 -interface_la_LDFLAGS = -module -avoid-version
 +interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  interface_la_LIBADD =
 -collectd_LDADD += "-dlopen" interface.la
 -collectd_DEPENDENCIES += interface.la
  if BUILD_WITH_LIBSTATGRAB
  interface_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
  interface_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
@@@ -401,17 -504,20 +410,17 @@@ if BUILD_PLUGIN_IPTABLE
  pkglib_LTLIBRARIES += iptables.la
  iptables_la_SOURCES = iptables.c
  iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS)
 -iptables_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBIPTC_LDFLAGS)
 -iptables_la_LIBADD = -liptc
 -collectd_LDADD += "-dlopen" iptables.la
 -collectd_DEPENDENCIES += iptables.la
 +iptables_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_IPMI
  pkglib_LTLIBRARIES += ipmi.la
 -ipmi_la_SOURCES = ipmi.c
 +ipmi_la_SOURCES = ipmi.c \
 +                utils_ignorelist.c utils_ignorelist.h
  ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
 -ipmi_la_LDFLAGS = -module -avoid-version
 +ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
 -collectd_LDADD += "-dlopen" ipmi.la
 -collectd_DEPENDENCIES += ipmi.la
  endif
  
  if BUILD_PLUGIN_IPVS
@@@ -420,14 -526,17 +429,14 @@@ ipvs_la_SOURCES = ipvs.
  if IP_VS_H_NEEDS_KERNEL_CFLAGS
  ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
  endif
 -ipvs_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" ipvs.la
 -collectd_DEPENDENCIES += ipvs.la
 +ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_IRQ
  pkglib_LTLIBRARIES += irq.la
 -irq_la_SOURCES = irq.c
 -irq_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" irq.la
 -collectd_DEPENDENCIES += irq.la
 +irq_la_SOURCES = irq.c \
 +               utils_ignorelist.c utils_ignorelist.h
 +irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_JAVA
@@@ -435,16 -544,31 +444,16 @@@ pkglib_LTLIBRARIES += java.l
  java_la_SOURCES = java.c
  java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS)
  java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS)
 -java_la_LDFLAGS = -module -avoid-version $(JAVA_LDFLAGS)
 +java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS)
  java_la_LIBADD = $(JAVA_LIBS)
 -collectd_LDADD += "-dlopen" java.la
 -collectd_DEPENDENCIES += java.la
 -endif
 -
 -if BUILD_PLUGIN_LIBVIRT
 -pkglib_LTLIBRARIES += libvirt.la
 -libvirt_la_SOURCES = libvirt.c
 -libvirt_la_CFLAGS = $(AM_CFLAGS) \
 -              $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
 -libvirt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
 -libvirt_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" libvirt.la
 -collectd_DEPENDENCIES += libvirt.la
  endif
  
  if BUILD_PLUGIN_LOAD
  pkglib_LTLIBRARIES += load.la
  load_la_SOURCES = load.c
  load_la_CFLAGS = $(AM_CFLAGS)
 -load_la_LDFLAGS = -module -avoid-version
 +load_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  load_la_LIBADD =
 -collectd_LDADD += "-dlopen" load.la
 -collectd_DEPENDENCIES += load.la
  if BUILD_WITH_LIBSTATGRAB
  load_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
  load_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
@@@ -457,110 -581,127 +466,110 @@@ endif # BUILD_PLUGIN_LOA
  if BUILD_PLUGIN_LOGFILE
  pkglib_LTLIBRARIES += logfile.la
  logfile_la_SOURCES = logfile.c
 -logfile_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" logfile.la
 -collectd_DEPENDENCIES += logfile.la
 +logfile_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +endif
 +
 +if BUILD_PLUGIN_LOG_LOGSTASH
 +pkglib_LTLIBRARIES += log_logstash.la
 +log_logstash_la_SOURCES = log_logstash.c
 +log_logstash_la_CFLAGS = $(AM_CFLAGS)
 +log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
 +log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
 +log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
  endif
  
  if BUILD_PLUGIN_LPAR
  pkglib_LTLIBRARIES += lpar.la
  lpar_la_SOURCES = lpar.c
 -lpar_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" lpar.la
 -collectd_DEPENDENCIES += lpar.la
 +lpar_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  lpar_la_LIBADD = -lperfstat
  endif
  
  if BUILD_PLUGIN_LVM
  pkglib_LTLIBRARIES += lvm.la
  lvm_la_SOURCES = lvm.c
 -lvm_la_LDFLAGS = -module -avoid-version
 +lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
 -collectd_LDADD += "-dlopen" lvm.la
 -collectd_DEPENDENCIES += lvm.la
  endif
  
  if BUILD_PLUGIN_MADWIFI
  pkglib_LTLIBRARIES += madwifi.la
 -madwifi_la_SOURCES = madwifi.c madwifi.h
 -madwifi_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" madwifi.la
 -collectd_DEPENDENCIES += madwifi.la
 +madwifi_la_SOURCES = madwifi.c madwifi.h \
 +                   utils_ignorelist.c utils_ignorelist.h
 +madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MATCH_EMPTY_COUNTER
  pkglib_LTLIBRARIES += match_empty_counter.la
  match_empty_counter_la_SOURCES = match_empty_counter.c
 -match_empty_counter_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" match_empty_counter.la
 -collectd_DEPENDENCIES += match_empty_counter.la
 +match_empty_counter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MATCH_HASHED
  pkglib_LTLIBRARIES += match_hashed.la
  match_hashed_la_SOURCES = match_hashed.c
 -match_hashed_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" match_hashed.la
 -collectd_DEPENDENCIES += match_hashed.la
 +match_hashed_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MATCH_REGEX
  pkglib_LTLIBRARIES += match_regex.la
  match_regex_la_SOURCES = match_regex.c
 -match_regex_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" match_regex.la
 -collectd_DEPENDENCIES += match_regex.la
 +match_regex_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MATCH_TIMEDIFF
  pkglib_LTLIBRARIES += match_timediff.la
  match_timediff_la_SOURCES = match_timediff.c
 -match_timediff_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" match_timediff.la
 -collectd_DEPENDENCIES += match_timediff.la
 +match_timediff_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MATCH_VALUE
  pkglib_LTLIBRARIES += match_value.la
  match_value_la_SOURCES = match_value.c
 -match_value_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" match_value.la
 -collectd_DEPENDENCIES += match_value.la
 +match_value_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MBMON
  pkglib_LTLIBRARIES += mbmon.la
  mbmon_la_SOURCES = mbmon.c
 -mbmon_la_LDFLAGS = -module -avoid-version
 +mbmon_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  mbmon_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  mbmon_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" mbmon.la
 -collectd_DEPENDENCIES += mbmon.la
  endif
  
  if BUILD_PLUGIN_MD
  pkglib_LTLIBRARIES += md.la
 -md_la_SOURCES = md.c
 -md_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" md.la
 -collectd_DEPENDENCIES += md.la
 +md_la_SOURCES = md.c \
 +              utils_ignorelist.c utils_ignorelist.h
 +md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MEMCACHEC
  pkglib_LTLIBRARIES += memcachec.la
  memcachec_la_SOURCES = memcachec.c
 -memcachec_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
 -memcachec_la_CPPFLAGS = $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
 +memcachec_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMEMCACHED_LDFLAGS)
 +memcachec_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMEMCACHED_CPPFLAGS)
  memcachec_la_LIBADD = $(BUILD_WITH_LIBMEMCACHED_LIBS)
 -collectd_LDADD += "-dlopen" memcachec.la
 -collectd_DEPENDENCIES += memcachec.la
  endif
  
  if BUILD_PLUGIN_MEMCACHED
  pkglib_LTLIBRARIES += memcached.la
  memcached_la_SOURCES = memcached.c
 -memcached_la_LDFLAGS = -module -avoid-version
 +memcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  memcached_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  memcached_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" memcached.la
 -collectd_DEPENDENCIES += memcached.la
  endif
  
  if BUILD_PLUGIN_MEMORY
  pkglib_LTLIBRARIES += memory.la
  memory_la_SOURCES = memory.c
  memory_la_CFLAGS = $(AM_CFLAGS)
 -memory_la_LDFLAGS = -module -avoid-version
 +memory_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  memory_la_LIBADD =
 -collectd_LDADD += "-dlopen" memory.la
 -collectd_DEPENDENCIES += memory.la
  if BUILD_WITH_LIBKSTAT
  memory_la_LIBADD += -lkstat
  endif
@@@ -576,56 -717,56 +585,56 @@@ memory_la_LIBADD += -lperfsta
  endif
  endif
  
 +if BUILD_PLUGIN_MIC
 +pkglib_LTLIBRARIES += mic.la
 +mic_la_SOURCES = mic.c \
 +               utils_ignorelist.c utils_ignorelist.h
 +mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH)
 +mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
 +mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
 +endif
 +
  if BUILD_PLUGIN_MODBUS
  pkglib_LTLIBRARIES += modbus.la
  modbus_la_SOURCES = modbus.c
 -modbus_la_LDFLAGS = -module -avoid-version
 +modbus_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS)
  modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS)
 -collectd_LDADD += "-dlopen" modbus.la
 -collectd_DEPENDENCIES += modbus.la
  endif
  
  if BUILD_PLUGIN_MULTIMETER
  pkglib_LTLIBRARIES += multimeter.la
  multimeter_la_SOURCES = multimeter.c
 -multimeter_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" multimeter.la
 -collectd_DEPENDENCIES += multimeter.la
 +multimeter_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_MYSQL
  pkglib_LTLIBRARIES += mysql.la
  mysql_la_SOURCES = mysql.c
 -mysql_la_LDFLAGS = -module -avoid-version
 +mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  mysql_la_CFLAGS = $(AM_CFLAGS)
  mysql_la_LIBADD =
 -collectd_LDADD += "-dlopen" mysql.la
  if BUILD_WITH_LIBMYSQL
  mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS)
  mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS)
  endif
 -collectd_DEPENDENCIES += mysql.la
  endif
  
  if BUILD_PLUGIN_NETAPP
  pkglib_LTLIBRARIES += netapp.la
 -netapp_la_SOURCES = netapp.c
 +netapp_la_SOURCES = netapp.c \
 +                  utils_ignorelist.c utils_ignorelist.h
  netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
 -netapp_la_LDFLAGS = -module -avoid-version $(LIBNETAPP_LDFLAGS)
 +netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
  netapp_la_LIBADD = $(LIBNETAPP_LIBS)
 -collectd_LDADD += "-dlopen" netapp.la
 -collectd_DEPENDENCIES += netapp.la
  endif
  
  if BUILD_PLUGIN_NETLINK
  pkglib_LTLIBRARIES += netlink.la
  netlink_la_SOURCES = netlink.c
 -netlink_la_LDFLAGS = -module -avoid-version
 +netlink_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  netlink_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMNL_CFLAGS)
  netlink_la_LIBADD = $(BUILD_WITH_LIBMNL_LIBS)
 -collectd_LDADD += "-dlopen" netlink.la
 -collectd_DEPENDENCIES += netlink.la
  endif
  
  if BUILD_PLUGIN_NETWORK
@@@ -633,7 -774,7 +642,7 @@@ pkglib_LTLIBRARIES += network.l
  network_la_SOURCES = network.c network.h \
                     utils_fbhash.c utils_fbhash.h
  network_la_CPPFLAGS = $(AM_CPPFLAGS)
 -network_la_LDFLAGS = -module -avoid-version
 +network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  network_la_LIBADD = -lpthread
  if BUILD_WITH_LIBSOCKET
  network_la_LIBADD += -lsocket
@@@ -643,18 -784,24 +652,18 @@@ network_la_CPPFLAGS += $(GCRYPT_CPPFLAG
  network_la_LDFLAGS += $(GCRYPT_LDFLAGS)
  network_la_LIBADD += $(GCRYPT_LIBS)
  endif
 -collectd_LDADD += "-dlopen" network.la
 -collectd_DEPENDENCIES += network.la
  endif
  
  if BUILD_PLUGIN_NFS
  pkglib_LTLIBRARIES += nfs.la
  nfs_la_SOURCES = nfs.c
 -nfs_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" nfs.la
 -collectd_DEPENDENCIES += nfs.la
 +nfs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_FSCACHE
  pkglib_LTLIBRARIES += fscache.la
  fscache_la_SOURCES = fscache.c
 -fscache_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" fscache.la
 -collectd_DEPENDENCIES += fscache.la
 +fscache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_NGINX
@@@ -662,85 -809,94 +671,85 @@@ pkglib_LTLIBRARIES += nginx.l
  nginx_la_SOURCES = nginx.c
  nginx_la_CFLAGS = $(AM_CFLAGS)
  nginx_la_LIBADD =
 -nginx_la_LDFLAGS = -module -avoid-version
 +nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  if BUILD_WITH_LIBCURL
  nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
  nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
  endif
 -collectd_LDADD += "-dlopen" nginx.la
 -collectd_DEPENDENCIES += nginx.la
  endif
  
  if BUILD_PLUGIN_NOTIFY_DESKTOP
  pkglib_LTLIBRARIES += notify_desktop.la
  notify_desktop_la_SOURCES = notify_desktop.c
  notify_desktop_la_CFLAGS = $(AM_CFLAGS) $(LIBNOTIFY_CFLAGS)
 -notify_desktop_la_LDFLAGS = -module -avoid-version
 +notify_desktop_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  notify_desktop_la_LIBADD = $(LIBNOTIFY_LIBS)
 -collectd_LDADD += "-dlopen" notify_desktop.la
 -collectd_DEPENDENCIES += notify_desktop.la
  endif
  
  if BUILD_PLUGIN_NOTIFY_EMAIL
  pkglib_LTLIBRARIES += notify_email.la
  notify_email_la_SOURCES = notify_email.c
 -notify_email_la_LDFLAGS = -module -avoid-version
 +notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread -ldl
 -collectd_LDADD += "-dlopen" notify_email.la
 -collectd_DEPENDENCIES += notify_email.la
  endif
  
  if BUILD_PLUGIN_NTPD
  pkglib_LTLIBRARIES += ntpd.la
  ntpd_la_SOURCES = ntpd.c
 -ntpd_la_LDFLAGS = -module -avoid-version
 +ntpd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  ntpd_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  ntpd_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" ntpd.la
 -collectd_DEPENDENCIES += ntpd.la
  endif
  
  if BUILD_PLUGIN_NUMA
  pkglib_LTLIBRARIES += numa.la
  numa_la_SOURCES = numa.c
 -numa_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" numa.la
 -collectd_DEPENDENCIES += numa.la
 +numa_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_NUT
  pkglib_LTLIBRARIES += nut.la
  nut_la_SOURCES = nut.c
  nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
 -nut_la_LDFLAGS = -module -avoid-version
 +nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  nut_la_LIBADD = -lpthread $(BUILD_WITH_LIBUPSCLIENT_LIBS)
 -collectd_LDADD += "-dlopen" nut.la
 -collectd_DEPENDENCIES += nut.la
  endif
  
  if BUILD_PLUGIN_OLSRD
  pkglib_LTLIBRARIES += olsrd.la
  olsrd_la_SOURCES = olsrd.c
 -olsrd_la_LDFLAGS = -module -avoid-version
 -olsrd_la_LIBADD = 
 +olsrd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
 +olsrd_la_LIBADD =
  if BUILD_WITH_LIBSOCKET
  olsrd_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" olsrd.la
 -collectd_DEPENDENCIES += olsrd.la
  endif
  
  if BUILD_PLUGIN_ONEWIRE
  pkglib_LTLIBRARIES += onewire.la
 -onewire_la_SOURCES = onewire.c
 +onewire_la_SOURCES = onewire.c \
 +                   utils_ignorelist.c utils_ignorelist.h
  onewire_la_CFLAGS = $(AM_CFLAGS)
 -onewire_la_CPPFLAGS = $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
 +onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
  onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
 -onewire_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" onewire.la
 -collectd_DEPENDENCIES += onewire.la
 +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
  openvpn_la_CFLAGS = $(AM_CFLAGS)
 -openvpn_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" openvpn.la
 -collectd_DEPENDENCIES += openvpn.la
 +openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_ORACLE
@@@ -748,9 -904,11 +757,9 @@@ pkglib_LTLIBRARIES += oracle.l
  oracle_la_SOURCES = oracle.c \
        utils_db_query.c utils_db_query.h
  oracle_la_CFLAGS = $(AM_CFLAGS)
 -oracle_la_CPPFLAGS = $(BUILD_WITH_ORACLE_CFLAGS)
 +oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
  oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
 -oracle_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" oracle.la
 -collectd_DEPENDENCIES += oracle.la
 +oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_PERL
@@@ -767,31 -925,38 +776,31 @@@ perl_la_CFLAGS  = $(AM_CFLAGS) 
  if HAVE_BROKEN_PERL_LOAD_MODULE
  perl_la_CFLAGS += -Wno-nonnull
  endif
 -perl_la_LDFLAGS = -module -avoid-version \
 +perl_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
                $(PERL_LDFLAGS)
 -collectd_LDADD += "-dlopen" perl.la
 -collectd_DEPENDENCIES += perl.la
 +perl_la_LIBADD = $(PERL_LIBS)
  endif
  
  if BUILD_PLUGIN_PF
  pkglib_LTLIBRARIES += pf.la
  pf_la_SOURCES = pf.c
 -pf_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" pf.la
 -collectd_DEPENDENCIES += pf.la
 +pf_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_PINBA
  pkglib_LTLIBRARIES += pinba.la
  pinba_la_SOURCES = pinba.c
  nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h
 -pinba_la_LDFLAGS = -module -avoid-version
 +pinba_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  pinba_la_LIBADD = -lprotobuf-c
 -collectd_LDADD += "-dlopen" pinba.la
 -collectd_DEPENDENCIES += pinba.la
  endif
  
  if BUILD_PLUGIN_PING
  pkglib_LTLIBRARIES += ping.la
  ping_la_SOURCES = ping.c
  ping_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOPING_CPPFLAGS)
 -ping_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBOPING_LDFLAGS)
 +ping_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOPING_LDFLAGS)
  ping_la_LIBADD = -loping -lm
 -collectd_LDADD += "-dlopen" ping.la
 -collectd_DEPENDENCIES += ping.la
  endif
  
  if BUILD_PLUGIN_POSTGRESQL
@@@ -799,15 -964,19 +808,15 @@@ pkglib_LTLIBRARIES += postgresql.l
  postgresql_la_SOURCES = postgresql.c \
                 utils_db_query.c utils_db_query.h
  postgresql_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBPQ_CPPFLAGS)
 -postgresql_la_LDFLAGS = -module -avoid-version \
 +postgresql_la_LDFLAGS = $(PLUGIN_LDFLAGS) \
                $(BUILD_WITH_LIBPQ_LDFLAGS)
  postgresql_la_LIBADD = -lpq
 -collectd_LDADD += "-dlopen" postgresql.la
 -collectd_DEPENDENCIES += postgresql.la
  endif
  
  if BUILD_PLUGIN_POWERDNS
  pkglib_LTLIBRARIES += powerdns.la
  powerdns_la_SOURCES = powerdns.c
 -powerdns_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" powerdns.la
 -collectd_DEPENDENCIES += powerdns.la
 +powerdns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_PYTHON
@@@ -818,15 -987,19 +827,15 @@@ python_la_CFLAGS = $(AM_CFLAGS
  if COMPILER_IS_GCC
  python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing
  endif
 -python_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_PYTHON_LDFLAGS)
 +python_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_PYTHON_LDFLAGS)
  python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS)
 -collectd_LDADD += "-dlopen" python.la
 -collectd_DEPENDENCIES += python.la
  endif
  
  if BUILD_PLUGIN_PROCESSES
  pkglib_LTLIBRARIES += processes.la
  processes_la_SOURCES = processes.c
 -processes_la_LDFLAGS = -module -avoid-version
 +processes_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  processes_la_LIBADD =
 -collectd_LDADD += "-dlopen" processes.la
 -collectd_DEPENDENCIES += processes.la
  if BUILD_WITH_LIBKVM_GETPROCS
  processes_la_LIBADD += -lkvm
  endif
@@@ -834,81 -1007,84 +843,81 @@@ endi
  
  if BUILD_PLUGIN_PROTOCOLS
  pkglib_LTLIBRARIES += protocols.la
 -protocols_la_SOURCES = protocols.c
 -protocols_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" protocols.la
 -collectd_DEPENDENCIES += protocols.la
 +protocols_la_SOURCES = protocols.c \
 +                     utils_ignorelist.c utils_ignorelist.h
 +protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_REDIS
  pkglib_LTLIBRARIES += redis.la
  redis_la_SOURCES = redis.c
 -redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS)
 -redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
 -redis_la_LIBADD = -lcredis
 -collectd_LDADD += "-dlopen" redis.la
 -collectd_DEPENDENCIES += redis.la
 +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
  pkglib_LTLIBRARIES += routeros.la
  routeros_la_SOURCES = routeros.c
 -routeros_la_CPPFLAGS = $(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
 -routeros_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBROUTEROS_LDFLAGS)
 +routeros_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBROUTEROS_CPPFLAGS)
 +routeros_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBROUTEROS_LDFLAGS)
  routeros_la_LIBADD = -lrouteros
 -collectd_LDADD += "-dlopen" routeros.la
 -collectd_DEPENDENCIES += routeros.la
  endif
  
  if BUILD_PLUGIN_RRDCACHED
  pkglib_LTLIBRARIES += rrdcached.la
  rrdcached_la_SOURCES = rrdcached.c utils_rrdcreate.c utils_rrdcreate.h
 -rrdcached_la_LDFLAGS = -module -avoid-version
 +rrdcached_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  rrdcached_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
  rrdcached_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
 -collectd_LDADD += "-dlopen" rrdcached.la
 -collectd_DEPENDENCIES += rrdcached.la
  endif
  
  if BUILD_PLUGIN_RRDTOOL
  pkglib_LTLIBRARIES += rrdtool.la
  rrdtool_la_SOURCES = rrdtool.c utils_rrdcreate.c utils_rrdcreate.h
 -rrdtool_la_LDFLAGS = -module -avoid-version
 +rrdtool_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  rrdtool_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBRRD_CFLAGS)
  rrdtool_la_LIBADD = $(BUILD_WITH_LIBRRD_LDFLAGS)
 -collectd_LDADD += "-dlopen" rrdtool.la
 -collectd_DEPENDENCIES += rrdtool.la
  endif
  
  if BUILD_PLUGIN_SENSORS
  pkglib_LTLIBRARIES += sensors.la
 -sensors_la_SOURCES = sensors.c
 +sensors_la_SOURCES = sensors.c \
 +                   utils_ignorelist.c utils_ignorelist.h
  sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
 -sensors_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSENSORS_LDFLAGS)
 +sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
  sensors_la_LIBADD = -lsensors
 -collectd_LDADD += "-dlopen" sensors.la
 -collectd_DEPENDENCIES += sensors.la
  endif
  
  if BUILD_PLUGIN_SERIAL
  pkglib_LTLIBRARIES += serial.la
  serial_la_SOURCES = serial.c
 -serial_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" serial.la
 -collectd_DEPENDENCIES += serial.la
 +serial_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_SIGROK
  pkglib_LTLIBRARIES += sigrok.la
  sigrok_la_SOURCES = sigrok.c
  sigrok_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSIGROK_CFLAGS)
 -sigrok_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSIGROK_LDFLAGS)
 +sigrok_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSIGROK_LDFLAGS)
  sigrok_la_LIBADD = -lsigrok
 -collectd_LDADD += "-dlopen" sigrok.la
 -collectd_DEPENDENCIES += sigrok.la
 +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
 -snmp_la_LDFLAGS = -module -avoid-version
 +snmp_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  snmp_la_CFLAGS = $(AM_CFLAGS)
  snmp_la_LIBADD =
  if BUILD_WITH_LIBNETSNMP
@@@ -918,22 -1094,28 +927,22 @@@ endi
  if BUILD_WITH_LIBPTHREAD
  snmp_la_LIBADD += -lpthread
  endif
 -collectd_LDADD += "-dlopen" snmp.la
 -collectd_DEPENDENCIES += snmp.la
  endif
  
  if BUILD_PLUGIN_STATSD
  pkglib_LTLIBRARIES += statsd.la
  statsd_la_SOURCES = statsd.c \
                      utils_latency.h utils_latency.c
 -statsd_la_LDFLAGS = -module -avoid-version
 +statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  statsd_la_LIBADD = -lpthread
 -collectd_LDADD += "-dlopen" statsd.la
 -collectd_DEPENDENCIES += statsd.la
  endif
  
  if BUILD_PLUGIN_SWAP
  pkglib_LTLIBRARIES += swap.la
  swap_la_SOURCES = swap.c
  swap_la_CFLAGS = $(AM_CFLAGS)
 -swap_la_LDFLAGS = -module -avoid-version
 +swap_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  swap_la_LIBADD =
 -collectd_LDADD += "-dlopen" swap.la
 -collectd_DEPENDENCIES += swap.la
  if BUILD_WITH_LIBKSTAT
  swap_la_LIBADD += -lkstat
  endif
@@@ -956,69 -1138,91 +965,69 @@@ endi
  if BUILD_PLUGIN_SYSLOG
  pkglib_LTLIBRARIES += syslog.la
  syslog_la_SOURCES = syslog.c
 -syslog_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" syslog.la
 -collectd_DEPENDENCIES += syslog.la
 +syslog_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TABLE
  pkglib_LTLIBRARIES += table.la
  table_la_SOURCES = table.c
 -table_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" table.la
 -collectd_DEPENDENCIES += table.la
 +table_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TAIL
  pkglib_LTLIBRARIES += tail.la
  tail_la_SOURCES = tail.c
 -tail_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" tail.la
 -collectd_DEPENDENCIES += tail.la
 +tail_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TAIL_CSV
  pkglib_LTLIBRARIES += tail_csv.la
  tail_csv_la_SOURCES = tail_csv.c
 -tail_csv_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" tail_csv.la
 -collectd_DEPENDENCIES += tail_csv.la
 +tail_csv_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TAPE
  pkglib_LTLIBRARIES += tape.la
  tape_la_SOURCES = tape.c
 -tape_la_LDFLAGS = -module -avoid-version
 +tape_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  tape_la_LIBADD = -lkstat -ldevinfo
 -collectd_LDADD += "-dlopen" tape.la
 -collectd_DEPENDENCIES += tape.la
  endif
  
  if BUILD_PLUGIN_TARGET_NOTIFICATION
  pkglib_LTLIBRARIES += target_notification.la
  target_notification_la_SOURCES = target_notification.c
 -target_notification_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" target_notification.la
 -collectd_DEPENDENCIES += target_notification.la
 +target_notification_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TARGET_REPLACE
  pkglib_LTLIBRARIES += target_replace.la
  target_replace_la_SOURCES = target_replace.c
 -target_replace_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" target_replace.la
 -collectd_DEPENDENCIES += target_replace.la
 +target_replace_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TARGET_SCALE
  pkglib_LTLIBRARIES += target_scale.la
  target_scale_la_SOURCES = target_scale.c
 -target_scale_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" target_scale.la
 -collectd_DEPENDENCIES += target_scale.la
 +target_scale_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TARGET_SET
  pkglib_LTLIBRARIES += target_set.la
  target_set_la_SOURCES = target_set.c
 -target_set_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" target_set.la
 -collectd_DEPENDENCIES += target_set.la
 +target_set_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TARGET_V5UPGRADE
  pkglib_LTLIBRARIES += target_v5upgrade.la
  target_v5upgrade_la_SOURCES = target_v5upgrade.c
 -target_v5upgrade_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" target_v5upgrade.la
 -collectd_DEPENDENCIES += target_v5upgrade.la
 +target_v5upgrade_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TCPCONNS
  pkglib_LTLIBRARIES += tcpconns.la
  tcpconns_la_SOURCES = tcpconns.c
 -tcpconns_la_LDFLAGS = -module -avoid-version
 +tcpconns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  tcpconns_la_LIBADD =
 -collectd_LDADD += "-dlopen" tcpconns.la
 -collectd_DEPENDENCIES += tcpconns.la
  if BUILD_WITH_LIBKVM_NLIST
  tcpconns_la_LIBADD += -lkvm
  endif
@@@ -1027,37 -1231,46 +1036,37 @@@ endi
  if BUILD_PLUGIN_TEAMSPEAK2
  pkglib_LTLIBRARIES += teamspeak2.la
  teamspeak2_la_SOURCES = teamspeak2.c
 -teamspeak2_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" teamspeak2.la
 -collectd_DEPENDENCIES += teamspeak2.la
 +teamspeak2_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TED
  pkglib_LTLIBRARIES += ted.la
  ted_la_SOURCES = ted.c
 -ted_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" ted.la
 -collectd_DEPENDENCIES += ted.la
 +ted_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_THERMAL
  pkglib_LTLIBRARIES += thermal.la
 -thermal_la_SOURCES = thermal.c
 -thermal_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" thermal.la
 -collectd_DEPENDENCIES += thermal.la
 +thermal_la_SOURCES = thermal.c \
 +                   utils_ignorelist.c utils_ignorelist.h
 +thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_THRESHOLD
  pkglib_LTLIBRARIES += threshold.la
  threshold_la_SOURCES = threshold.c
 -threshold_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" threshold.la
 -collectd_DEPENDENCIES += threshold.la
 +threshold_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_TOKYOTYRANT
  pkglib_LTLIBRARIES += tokyotyrant.la
  tokyotyrant_la_SOURCES = tokyotyrant.c
  tokyotyrant_la_CPPFLAGS  = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
 -tokyotyrant_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
 +tokyotyrant_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
  tokyotyrant_la_LIBADD  = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
  if BUILD_WITH_LIBSOCKET
  tokyotyrant_la_LIBADD += -lsocket
  endif
 -collectd_LDADD += "-dlopen" tokyotyrant.la
 -collectd_DEPENDENCIES += tokyotyrant.la
  endif
  
  if BUILD_PLUGIN_UNIXSOCK
@@@ -1065,20 -1278,20 +1074,20 @@@ pkglib_LTLIBRARIES += unixsock.l
  unixsock_la_SOURCES = unixsock.c \
                      utils_cmd_flush.h utils_cmd_flush.c \
                      utils_cmd_getval.h utils_cmd_getval.c \
 +                    utils_cmd_getthreshold.h utils_cmd_getthreshold.c \
                      utils_cmd_listval.h utils_cmd_listval.c \
                      utils_cmd_putval.h utils_cmd_putval.c \
 -                    utils_cmd_putnotif.h utils_cmd_putnotif.c
 -unixsock_la_LDFLAGS = -module -avoid-version
 +                    utils_cmd_putnotif.h utils_cmd_putnotif.c \
 +                    utils_parse_option.h utils_parse_option.c
 +unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  unixsock_la_LIBADD = -lpthread
 -collectd_LDADD += "-dlopen" unixsock.la
 -collectd_DEPENDENCIES += unixsock.la
  endif
  
  if BUILD_PLUGIN_UPTIME
  pkglib_LTLIBRARIES += uptime.la
  uptime_la_SOURCES = uptime.c
  uptime_la_CFLAGS = $(AM_CFLAGS)
 -uptime_la_LDFLAGS = -module -avoid-version
 +uptime_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  uptime_la_LIBADD =
  if BUILD_WITH_LIBKSTAT
  uptime_la_LIBADD += -lkstat
@@@ -1086,18 -1299,22 +1095,18 @@@ endi
  if BUILD_WITH_PERFSTAT
  uptime_la_LIBADD += -lperfstat
  endif
 -collectd_LDADD += "-dlopen" uptime.la
 -collectd_DEPENDENCIES += uptime.la
  endif
  
  if BUILD_PLUGIN_USERS
  pkglib_LTLIBRARIES += users.la
  users_la_SOURCES = users.c
  users_la_CFLAGS = $(AM_CFLAGS)
 -users_la_LDFLAGS = -module -avoid-version
 +users_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  users_la_LIBADD =
  if BUILD_WITH_LIBSTATGRAB
  users_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
  users_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
  endif
 -collectd_LDADD += "-dlopen" users.la
 -collectd_DEPENDENCIES += users.la
  endif
  
  if BUILD_PLUGIN_UUID
@@@ -1105,43 -1322,53 +1114,43 @@@ pkglib_LTLIBRARIES += uuid.l
  uuid_la_SOURCES = uuid.c
  uuid_la_CFLAGS  = $(AM_CFLAGS) $(BUILD_WITH_LIBHAL_CFLAGS)
  uuid_la_LIBADD  = $(BUILD_WITH_LIBHAL_LIBS)
 -uuid_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" uuid.la
 -collectd_DEPENDENCIES += uuid.la
 -endif
 -
 -if BUILD_PLUGIN_MIC
 -pkglib_LTLIBRARIES += mic.la
 -mic_la_SOURCES = mic.c
 -mic_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_MIC_LIBPATH)
 -mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
 -mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
 -collectd_LDADD += "-dlopen" mic.la
 -collectd_DEPENDENCIES += mic.la
 +uuid_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_VARNISH
  pkglib_LTLIBRARIES += varnish.la
  varnish_la_SOURCES = varnish.c
 -varnish_la_LDFLAGS = -module -avoid-version
 +varnish_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS)
  varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS)
 -collectd_LDADD += "-dlopen" varnish.la
 -collectd_DEPENDENCIES += varnish.la
 +endif
 +
 +if BUILD_PLUGIN_VIRT
 +pkglib_LTLIBRARIES += virt.la
 +virt_la_SOURCES = virt.c \
 +                utils_ignorelist.c utils_ignorelist.h
 +virt_la_CFLAGS = $(AM_CFLAGS) \
 +              $(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
 +virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
 +virt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_VMEM
  pkglib_LTLIBRARIES += vmem.la
  vmem_la_SOURCES = vmem.c
 -vmem_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" vmem.la
 -collectd_DEPENDENCIES += vmem.la
 +vmem_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_VSERVER
  pkglib_LTLIBRARIES += vserver.la
  vserver_la_SOURCES = vserver.c
 -vserver_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" vserver.la
 -collectd_DEPENDENCIES += vserver.la
 +vserver_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_WIRELESS
  pkglib_LTLIBRARIES += wireless.la
  wireless_la_SOURCES = wireless.c
 -wireless_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" wireless.la
 -collectd_DEPENDENCIES += wireless.la
 +wireless_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_WRITE_GRAPHITE
@@@ -1149,99 -1376,78 +1158,99 @@@ pkglib_LTLIBRARIES += write_graphite.l
  write_graphite_la_SOURCES = write_graphite.c \
                          utils_format_graphite.c utils_format_graphite.h \
                          utils_format_json.c utils_format_json.h
 -write_graphite_la_LDFLAGS = -module -avoid-version
 -collectd_LDADD += "-dlopen" write_graphite.la
 -collectd_DEPENDENCIES += write_graphite.la
 +write_graphite_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_WRITE_HTTP
  pkglib_LTLIBRARIES += write_http.la
  write_http_la_SOURCES = write_http.c \
                        utils_format_json.c utils_format_json.h
 -write_http_la_LDFLAGS = -module -avoid-version
 +write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  write_http_la_CFLAGS = $(AM_CFLAGS)
  write_http_la_LIBADD =
 -collectd_LDADD += "-dlopen" write_http.la
  if BUILD_WITH_LIBCURL
  write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
  write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
  endif
 -collectd_DEPENDENCIES += write_http.la
 +endif
 +
 +if BUILD_PLUGIN_WRITE_KAFKA
 +pkglib_LTLIBRARIES += write_kafka.la
 +write_kafka_la_SOURCES = write_kafka.c \
 +                        utils_format_graphite.c utils_format_graphite.h \
 +                        utils_format_json.c utils_format_json.h \
 +                        utils_cmd_putval.c utils_cmd_putval.h \
 +                        utils_crc32.c utils_crc32.h
 +write_kafka_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
 +write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
 +endif
 +
 +if BUILD_PLUGIN_WRITE_LOG
 +pkglib_LTLIBRARIES += write_log.la
 +write_log_la_SOURCES = write_log.c \
 +                        utils_format_graphite.c utils_format_graphite.h
 +write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_WRITE_MONGODB
  pkglib_LTLIBRARIES += write_mongodb.la
  write_mongodb_la_SOURCES = write_mongodb.c
  write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS)
 -write_mongodb_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBMONGOC_LDFLAGS)
 +write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS)
  write_mongodb_la_LIBADD = -lmongoc
 -collectd_LDADD += "-dlopen" write_mongodb.la
 -collectd_DEPENDENCIES += write_mongodb.la
  endif
  
  if BUILD_PLUGIN_WRITE_REDIS
  pkglib_LTLIBRARIES += write_redis.la
  write_redis_la_SOURCES = write_redis.c
 -write_redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS)
 -write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS)
 -write_redis_la_LIBADD = -lcredis
 -collectd_LDADD += "-dlopen" write_redis.la
 -collectd_DEPENDENCIES += write_redis.la
 +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
  pkglib_LTLIBRARIES += write_riemann.la
 -write_riemann_la_SOURCES = write_riemann.c
 +write_riemann_la_SOURCES = write_riemann.c write_riemann_threshold.c
  nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h
 -write_riemann_la_LDFLAGS = -module -avoid-version
 +write_riemann_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  write_riemann_la_LIBADD = -lprotobuf-c
 -collectd_LDADD += "-dlopen" write_riemann.la
 -collectd_DEPENDENCIES += write_riemann.la
 +endif
 +
 +if BUILD_PLUGIN_WRITE_TSDB
 +pkglib_LTLIBRARIES += write_tsdb.la
 +write_tsdb_la_SOURCES = write_tsdb.c
 +write_tsdb_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  if BUILD_PLUGIN_XMMS
  pkglib_LTLIBRARIES += xmms.la
  xmms_la_SOURCES = xmms.c
  xmms_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBXMMS_CFLAGS)
 -xmms_la_LDFLAGS = -module -avoid-version
 +xmms_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  xmms_la_LIBADD = $(BUILD_WITH_LIBXMMS_LIBS)
 -collectd_LDADD += "-dlopen" xmms.la
 -collectd_DEPENDENCIES += xmms.la
  endif
  
  if BUILD_PLUGIN_ZFS_ARC
  pkglib_LTLIBRARIES += zfs_arc.la
  zfs_arc_la_SOURCES = zfs_arc.c
  zfs_arc_la_CFLAGS = $(AM_CFLAGS)
 -zfs_arc_la_LDFLAGS = -module -avoid-version
 +zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  if BUILD_FREEBSD
  zfs_arc_la_LIBADD = -lm
  else
 +if BUILD_LINUX
 +# zfs_arc requires no library on linux
 +else
 +# solaris
  zfs_arc_la_LIBADD = -lkstat
  endif
 -collectd_LDADD += "-dlopen" zfs_arc.la
 -collectd_DEPENDENCIES += zfs_arc.la
 +endif
 +endif
 +
 +if BUILD_PLUGIN_ZOOKEEPER
 +pkglib_LTLIBRARIES += zookeeper.la
 +zookeeper_la_SOURCES = zookeeper.c
 +zookeeper_la_LDFLAGS = $(PLUGIN_LDFLAGS)
  endif
  
  BUILT_SOURCES += $(dist_man_MANS)
@@@ -1338,48 -1544,15 +1347,48 @@@ uninstall-hook
        rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
        rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
  
 -if BUILD_FEATURE_DEBUG
 -bin_PROGRAMS += utils_vl_lookup_test
 -utils_vl_lookup_test_SOURCES = utils_vl_lookup_test.c \
 +check_PROGRAMS = test_common test_utils_avltree test_utils_heap test_utils_mount test_utils_vl_lookup
 +
 +test_common_SOURCES = tests/test_common.c \
 +                      daemon/common.h daemon/common.c \
 +                      tests/mock/plugin.c \
 +                      tests/mock/utils_cache.c \
 +                      tests/mock/utils_time.c
 +test_common_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
 +test_common_LDFLAGS = -export-dynamic
 +test_common_LDADD =
 +
 +test_utils_avltree_SOURCES = tests/test_utils_avltree.c \
 +                             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 \
 +                          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 \
 +                           daemon/common.c daemon/common.h \
 +                           tests/mock/plugin.c \
 +                           tests/mock/utils_cache.c \
 +                           tests/mock/utils_time.c
 +test_utils_mount_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
 +test_utils_mount_LDFLAGS = -export-dynamic
 +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.h
 -
 -utils_vl_lookup_test_CPPFLAGS =  $(AM_CPPFLAGS) $(LTDLINCL) -DBUILD_TEST=1
 -utils_vl_lookup_test_CFLAGS = $(AM_CFLAGS)
 -utils_vl_lookup_test_LDFLAGS = -export-dynamic
 -utils_vl_lookup_test_LDADD =
 -endif
 +                               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
 +test_utils_vl_lookup_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
 +test_utils_vl_lookup_LDFLAGS = -export-dynamic
 +test_utils_vl_lookup_LDADD =
 +
 +TESTS = test_common test_utils_avltree test_utils_heap test_utils_mount test_utils_vl_lookup
diff --combined src/ceph.c
index 0000000,4ae6e54..1b1f40b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1579 +1,1579 @@@
 -    
+ /**
+  * collectd - src/ceph.c
+  * Copyright (C) 2011  New Dream Network
+  *
+  * This program is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU General Public License as published by the
+  * Free Software Foundation; only version 2 of the License is applicable.
+  *
+  * This program is distributed in the hope that it will be useful, but
+  * WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * General Public License for more details.
+  *
+  * You should have received a copy of the GNU General Public License along
+  * with this program; if not, write to the Free Software Foundation, Inc.,
+  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+  *
+  * Authors:
+  *   Colin McCabe <cmccabe@alumni.cmu.edu>
+  *   Dennis Zou <yunzou@cisco.com>
+  *   Dan Ryder <daryder@cisco.com>
+  **/
+ #define _BSD_SOURCE
+ #include "collectd.h"
+ #include "common.h"
+ #include "plugin.h"
+ #include <arpa/inet.h>
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <yajl/yajl_parse.h>
+ #if HAVE_YAJL_YAJL_VERSION_H
+ #include <yajl/yajl_version.h>
+ #endif
+ #include <limits.h>
+ #include <poll.h>
+ #include <stdint.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <strings.h>
+ #include <sys/socket.h>
+ #include <sys/time.h>
+ #include <sys/types.h>
+ #include <sys/un.h>
+ #include <unistd.h>
+ #include <math.h>
+ #include <inttypes.h>
+ #define RETRY_AVGCOUNT -1
+ #if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+ # define HAVE_YAJL_V2 1
+ #endif
+ #define RETRY_ON_EINTR(ret, expr) \
+     while(1) { \
+         ret = expr; \
+         if(ret >= 0) \
+             break; \
+         ret = -errno; \
+         if(ret != -EINTR) \
+             break; \
+     }
+ /** Timeout interval in seconds */
+ #define CEPH_TIMEOUT_INTERVAL 1
+ /** Maximum path length for a UNIX domain socket on this system */
+ #define UNIX_DOMAIN_SOCK_PATH_MAX (sizeof(((struct sockaddr_un*)0)->sun_path))
+ /** Yajl callback returns */
+ #define CEPH_CB_CONTINUE 1
+ #define CEPH_CB_ABORT 0
+ #if HAVE_YAJL_V2
+ typedef size_t yajl_len_t;
+ #else
+ typedef unsigned int yajl_len_t;
+ #endif
+ /** Number of types for ceph defined in types.db */
+ #define CEPH_DSET_TYPES_NUM 3
+ /** ceph types enum */
+ enum ceph_dset_type_d
+ {
+     DSET_LATENCY = 0,
+     DSET_BYTES = 1,
+     DSET_RATE = 2,
+     DSET_TYPE_UNFOUND = 1000
+ };
+ /** Valid types for ceph defined in types.db */
+ const char * ceph_dset_types [CEPH_DSET_TYPES_NUM] =
+                                    {"ceph_latency", "ceph_bytes", "ceph_rate"};
+ /******* ceph_daemon *******/
+ struct ceph_daemon
+ {
+     /** Version of the admin_socket interface */
+     uint32_t version;
+     /** daemon name **/
+     char name[DATA_MAX_NAME_LEN];
+     /** Path to the socket that we use to talk to the ceph daemon */
+     char asok_path[UNIX_DOMAIN_SOCK_PATH_MAX];
+     /** Number of counters */
+     int ds_num;
+     /** Track ds types */
+     uint32_t *ds_types;
+     /** Track ds names to match with types */
+     char **ds_names;
 -static int 
++
+     /**
+      * Keep track of last data for latency values so we can calculate rate
+      * since last poll.
+      */
+     struct last_data **last_poll_data;
+     /** index of last poll data */
+     int last_idx;
+ };
+ /******* JSON parsing *******/
+ typedef int (*node_handler_t)(void *, const char*, const char*);
+ /** Track state and handler while parsing JSON */
+ struct yajl_struct
+ {
+     node_handler_t handler;
+     void * handler_arg;
+     struct {
+       char key[DATA_MAX_NAME_LEN];
+       int key_len;
+     } state[YAJL_MAX_DEPTH];
+     int depth;
+ };
+ typedef struct yajl_struct yajl_struct;
+ enum perfcounter_type_d
+ {
+     PERFCOUNTER_LATENCY = 0x4, PERFCOUNTER_DERIVE = 0x8,
+ };
+ /** Give user option to use default (long run = since daemon started) avg */
+ static int long_run_latency_avg = 0;
+ /**
+  * Give user option to use default type for special cases -
+  * filestore.journal_wr_bytes is currently only metric here. Ceph reports the
+  * type as a sum/count pair and will calculate it the same as a latency value.
+  * All other "bytes" metrics (excluding the used/capacity bytes for the OSD)
+  * use the DERIVE type. Unless user specifies to use given type, convert this
+  * metric to use DERIVE.
+  */
+ static int convert_special_metrics = 1;
+ /** Array of daemons to monitor */
+ static struct ceph_daemon **g_daemons = NULL;
+ /** Number of elements in g_daemons */
+ static int g_num_daemons = 0;
+ /**
+  * A set of data that we build up in memory while parsing the JSON.
+  */
+ struct values_tmp
+ {
+     /** ceph daemon we are processing data for*/
+     struct ceph_daemon *d;
+     /** track avgcount across counters for avgcount/sum latency pairs */
+     uint64_t avgcount;
+     /** current index of counters - used to get type of counter */
+     int index;
+     /** do we already have an avgcount for latency pair */
+     int avgcount_exists;
+     /**
+      * similar to index, but current index of latency type counters -
+      * used to get last poll data of counter
+      */
+     int latency_index;
+     /**
+      * values list - maintain across counters since
+      * host/plugin/plugin instance are always the same
+      */
+     value_list_t vlist;
+ };
+ /**
+  * A set of count/sum pairs to keep track of latency types and get difference
+  * between this poll data and last poll data.
+  */
+ struct last_data
+ {
+     char ds_name[DATA_MAX_NAME_LEN];
+     double last_sum;
+     uint64_t last_count;
+ };
+ /******* network I/O *******/
+ enum cstate_t
+ {
+     CSTATE_UNCONNECTED = 0,
+     CSTATE_WRITE_REQUEST,
+     CSTATE_READ_VERSION,
+     CSTATE_READ_AMT,
+     CSTATE_READ_JSON,
+ };
+ enum request_type_t
+ {
+     ASOK_REQ_VERSION = 0,
+     ASOK_REQ_DATA = 1,
+     ASOK_REQ_SCHEMA = 2,
+     ASOK_REQ_NONE = 1000,
+ };
+ struct cconn
+ {
+     /** The Ceph daemon that we're talking to */
+     struct ceph_daemon *d;
+     /** Request type */
+     uint32_t request_type;
+     /** The connection state */
+     enum cstate_t state;
+     /** The socket we use to talk to this daemon */
+     int asok;
+     /** The amount of data remaining to read / write. */
+     uint32_t amt;
+     /** Length of the JSON to read */
+     uint32_t json_len;
+     /** Buffer containing JSON data */
+     unsigned char *json;
+     /** Keep data important to yajl processing */
+     struct yajl_struct yajl;
+ };
+ static int ceph_cb_null(void *ctx)
+ {
+     return CEPH_CB_CONTINUE;
+ }
+ static int ceph_cb_boolean(void *ctx, int bool_val)
+ {
+     return CEPH_CB_CONTINUE;
+ }
 -static int ceph_cb_string(void *ctx, const unsigned char *string_val, 
++static int
+ ceph_cb_number(void *ctx, const char *number_val, yajl_len_t number_len)
+ {
+     yajl_struct *yajl = (yajl_struct*)ctx;
+     char buffer[number_len+1];
+     int i, latency_type = 0, result;
+     char key[128];
+     memcpy(buffer, number_val, number_len);
+     buffer[sizeof(buffer) - 1] = 0;
+     ssnprintf(key, yajl->state[0].key_len, "%s", yajl->state[0].key);
+     for(i = 1; i < yajl->depth; i++)
+     {
+         if((i == yajl->depth-1) && ((strcmp(yajl->state[i].key,"avgcount") == 0)
+                 || (strcmp(yajl->state[i].key,"sum") == 0)))
+         {
+             if(convert_special_metrics)
+             {
+                 /**
+                  * Special case for filestore:JournalWrBytes. For some reason,
+                  * Ceph schema encodes this as a count/sum pair while all
+                  * other "Bytes" data (excluding used/capacity bytes for OSD
+                  * space) uses a single "Derive" type. To spare further
+                  * confusion, keep this KPI as the same type of other "Bytes".
+                  * Instead of keeping an "average" or "rate", use the "sum" in
+                  * the pair and assign that to the derive value.
+                  */
+                 if((strcmp(yajl->state[i-1].key, "journal_wr_bytes") == 0) &&
+                         (strcmp(yajl->state[i-2].key,"filestore") == 0) &&
+                         (strcmp(yajl->state[i].key,"avgcount") == 0))
+                 {
+                     DEBUG("ceph plugin: Skipping avgcount for filestore.JournalWrBytes");
+                     yajl->depth = (yajl->depth - 1);
+                     return CEPH_CB_CONTINUE;
+                 }
+             }
+             //probably a avgcount/sum pair. if not - we'll try full key later
+             latency_type = 1;
+             break;
+         }
+         strncat(key, ".", 1);
+         strncat(key, yajl->state[i].key, yajl->state[i].key_len+1);
+     }
+     result = yajl->handler(yajl->handler_arg, buffer, key);
+     if((result == RETRY_AVGCOUNT) && latency_type)
+     {
+         strncat(key, ".", 1);
+         strncat(key, yajl->state[yajl->depth-1].key,
+                 yajl->state[yajl->depth-1].key_len+1);
+         result = yajl->handler(yajl->handler_arg, buffer, key);
+     }
+     if(result == -ENOMEM)
+     {
+         ERROR("ceph plugin: memory allocation failed");
+         return CEPH_CB_ABORT;
+     }
+     yajl->depth = (yajl->depth - 1);
+     return CEPH_CB_CONTINUE;
+ }
 -    if(ds_name == NULL || key_str == NULL ||  key_str[0] == '\0' || 
++static int ceph_cb_string(void *ctx, const unsigned char *string_val,
+         yajl_len_t string_len)
+ {
+     return CEPH_CB_CONTINUE;
+ }
+ static int ceph_cb_start_map(void *ctx)
+ {
+     return CEPH_CB_CONTINUE;
+ }
+ static int
+ ceph_cb_map_key(void *ctx, const unsigned char *key, yajl_len_t string_len)
+ {
+     yajl_struct *yajl = (yajl_struct*)ctx;
+     if((yajl->depth+1)  >= YAJL_MAX_DEPTH)
+     {
+         ERROR("ceph plugin: depth exceeds max, aborting.");
+         return CEPH_CB_ABORT;
+     }
+     char buffer[string_len+1];
+     memcpy(buffer, key, string_len);
+     buffer[sizeof(buffer) - 1] = 0;
+     snprintf(yajl->state[yajl->depth].key, sizeof(buffer), "%s", buffer);
+     yajl->state[yajl->depth].key_len = sizeof(buffer);
+     yajl->depth = (yajl->depth + 1);
+     return CEPH_CB_CONTINUE;
+ }
+ static int ceph_cb_end_map(void *ctx)
+ {
+     yajl_struct *yajl = (yajl_struct*)ctx;
+     yajl->depth = (yajl->depth - 1);
+     return CEPH_CB_CONTINUE;
+ }
+ static int ceph_cb_start_array(void *ctx)
+ {
+     return CEPH_CB_CONTINUE;
+ }
+ static int ceph_cb_end_array(void *ctx)
+ {
+     return CEPH_CB_CONTINUE;
+ }
+ static yajl_callbacks callbacks = {
+         ceph_cb_null,
+         ceph_cb_boolean,
+         NULL,
+         NULL,
+         ceph_cb_number,
+         ceph_cb_string,
+         ceph_cb_start_map,
+         ceph_cb_map_key,
+         ceph_cb_end_map,
+         ceph_cb_start_array,
+         ceph_cb_end_array
+ };
+ static void ceph_daemon_print(const struct ceph_daemon *d)
+ {
+     DEBUG("ceph plugin: name=%s, asok_path=%s", d->name, d->asok_path);
+ }
+ static void ceph_daemons_print(void)
+ {
+     int i;
+     for(i = 0; i < g_num_daemons; ++i)
+     {
+         ceph_daemon_print(g_daemons[i]);
+     }
+ }
+ static void ceph_daemon_free(struct ceph_daemon *d)
+ {
+     int i = 0;
+     for(; i < d->last_idx; i++)
+     {
+         sfree(d->last_poll_data[i]);
+     }
+     sfree(d->last_poll_data);
+     d->last_poll_data = NULL;
+     d->last_idx = 0;
+     for(i = 0; i < d->ds_num; i++)
+     {
+         sfree(d->ds_names[i]);
+     }
+     sfree(d->ds_types);
+     sfree(d->ds_names);
+     sfree(d);
+ }
+ /**
+  * Compact ds name by removing special characters and trimming length to
+  * DATA_MAX_NAME_LEN if necessary
+  */
+ static void compact_ds_name(char *source, char *dest)
+ {
+     int keys_num = 0, i;
+     char *save_ptr = NULL, *tmp_ptr = source;
+     char *keys[16];
+     char len_str[3];
+     char tmp[DATA_MAX_NAME_LEN];
+     size_t key_chars_remaining = (DATA_MAX_NAME_LEN-1);
+     int reserved = 0;
+     int offset = 0;
+     memset(tmp, 0, sizeof(tmp));
+     if(source == NULL || dest == NULL || source[0] == '\0' || dest[0] != '\0')
+     {
+         return;
+     }
+     size_t src_len = strlen(source);
+     snprintf(len_str, sizeof(len_str), "%zu", src_len);
+     unsigned char append_status = 0x0;
+     append_status |= (source[src_len - 1] == '-') ? 0x1 : 0x0;
+     append_status |= (source[src_len - 1] == '+') ? 0x2 : 0x0;
+     while ((keys[keys_num] = strtok_r(tmp_ptr, ":_-+", &save_ptr)) != NULL)
+     {
+         tmp_ptr = NULL;
+         /** capitalize 1st char **/
+         keys[keys_num][0] = toupper(keys[keys_num][0]);
+         keys_num++;
+         if(keys_num >= 16)
+         {
+             break;
+         }
+     }
+     /** concatenate each part of source string **/
+     for(i = 0; i < keys_num; i++)
+     {
+         strncat(tmp, keys[i], key_chars_remaining);
+         key_chars_remaining -= strlen(keys[i]);
+     }
+     tmp[DATA_MAX_NAME_LEN - 1] = '\0';
+     /** to coordinate limitation of length of type_instance
+      *  we will truncate ds_name
+      *  when the its length is more than
+      *  DATA_MAX_NAME_LEN
+      */
+     if(strlen(tmp) > DATA_MAX_NAME_LEN - 1)
+     {
+         append_status |= 0x4;
+         /** we should reserve space for
+          * len_str
+          */
+         reserved += 2;
+     }
+     if(append_status & 0x1)
+     {
+         /** we should reserve space for
+          * "Minus"
+          */
+         reserved += 5;
+     }
+     if(append_status & 0x2)
+     {
+         /** we should reserve space for
+          * "Plus"
+          */
+         reserved += 4;
+     }
+     snprintf(dest, DATA_MAX_NAME_LEN - reserved, "%s", tmp);
+     offset = strlen(dest);
+     switch (append_status)
+     {
+         case 0x1:
+             memcpy(dest + offset, "Minus", 5);
+             break;
+         case 0x2:
+             memcpy(dest + offset, "Plus", 5);
+             break;
+         case 0x4:
+             memcpy(dest + offset, len_str, 2);
+             break;
+         case 0x5:
+             memcpy(dest + offset, "Minus", 5);
+             memcpy(dest + offset + 5, len_str, 2);
+             break;
+         case 0x6:
+             memcpy(dest + offset, "Plus", 4);
+             memcpy(dest + offset + 4, len_str, 2);
+             break;
+         default:
+             break;
+     }
+ }
+ /**
+  * Parse key to remove "type" if this is for schema and initiate compaction
+  */
+ static int parse_keys(const char *key_str, char *ds_name)
+ {
+     char *ptr, *rptr;
+     size_t ds_name_len = 0;
+     /**
+      * allow up to 100 characters before compaction - compact_ds_name will not
+      * allow more than DATA_MAX_NAME_LEN chars
+      */
+     int max_str_len = 100;
+     char tmp_ds_name[max_str_len];
+     memset(tmp_ds_name, 0, sizeof(tmp_ds_name));
 -    
++    if(ds_name == NULL || key_str == NULL ||  key_str[0] == '\0' ||
+                                                             ds_name[0] != '\0')
+     {
+         return -1;
+     }
+     if((ptr = strchr(key_str, '.')) == NULL
+             || (rptr = strrchr(key_str, '.')) == NULL)
+     {
+         memcpy(tmp_ds_name, key_str, max_str_len - 1);
+         goto compact;
+     }
 -    
++
+     ds_name_len = (rptr - ptr) > max_str_len ? max_str_len : (rptr - ptr);
+     if((ds_name_len == 0) || strncmp(rptr + 1, "type", 4))
+     { /** copy whole key **/
+         memcpy(tmp_ds_name, key_str, max_str_len - 1);
+     }
+     else
+     {/** more than two keys **/
+         memcpy(tmp_ds_name, key_str, ((rptr - key_str) > (max_str_len - 1) ?
+                 (max_str_len - 1) : (rptr - key_str)));
+     }
 -    
++
+     compact: compact_ds_name(tmp_ds_name, ds_name);
+     return 0;
+ }
+ /**
+  * while parsing ceph admin socket schema, save counter name and type for later
+  * data processing
+  */
+ static int ceph_daemon_add_ds_entry(struct ceph_daemon *d, const char *name,
+         int pc_type)
+ {
+     uint32_t type;
+     char ds_name[DATA_MAX_NAME_LEN];
+     memset(ds_name, 0, sizeof(ds_name));
 -    
++
+     if(convert_special_metrics)
+     {
+         /**
+          * Special case for filestore:JournalWrBytes. For some reason, Ceph
+          * schema encodes this as a count/sum pair while all other "Bytes" data
+          * (excluding used/capacity bytes for OSD space) uses a single "Derive"
+          * type. To spare further confusion, keep this KPI as the same type of
+          * other "Bytes". Instead of keeping an "average" or "rate", use the
+          * "sum" in the pair and assign that to the derive value.
+          */
+         if((strcmp(name,"filestore.journal_wr_bytes.type") == 0))
+         {
+             pc_type = 10;
+         }
+     }
+     d->ds_names = realloc(d->ds_names, sizeof(char *) * (d->ds_num + 1));
+     if(!d->ds_names)
+     {
+         return -ENOMEM;
+     }
+     d->ds_types = realloc(d->ds_types, sizeof(uint32_t) * (d->ds_num + 1));
+     if(!d->ds_types)
+     {
+         return -ENOMEM;
+     }
+     d->ds_names[d->ds_num] = malloc(sizeof(char) * DATA_MAX_NAME_LEN);
+     if(!d->ds_names[d->ds_num])
+     {
+         return -ENOMEM;
+     }
+     type = (pc_type & PERFCOUNTER_DERIVE) ? DSET_RATE :
+             ((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES);
+     d->ds_types[d->ds_num] = type;
+     if(parse_keys(name, ds_name))
+     {
+         return 1;
+     }
+     sstrncpy(d->ds_names[d->ds_num], ds_name, DATA_MAX_NAME_LEN -1);
+     d->ds_num = (d->ds_num + 1);
 -    
++
+     return 0;
+ }
+ /******* ceph_config *******/
+ static int cc_handle_str(struct oconfig_item_s *item, char *dest, int dest_len)
+ {
+     const char *val;
+     if(item->values_num != 1)
+     {
+         return -ENOTSUP;
+     }
+     if(item->values[0].type != OCONFIG_TYPE_STRING)
+     {
+         return -ENOTSUP;
+     }
+     val = item->values[0].value.string;
+     if(snprintf(dest, dest_len, "%s", val) > (dest_len - 1))
+     {
+         ERROR("ceph plugin: configuration parameter '%s' is too long.\n",
+                 item->key);
+         return -ENAMETOOLONG;
+     }
+     return 0;
+ }
+ static int cc_handle_bool(struct oconfig_item_s *item, int *dest)
+ {
+     if(item->values_num != 1)
+     {
+         return -ENOTSUP;
+     }
+     if(item->values[0].type != OCONFIG_TYPE_BOOLEAN)
+     {
+         return -ENOTSUP;
+     }
+     *dest = (item->values[0].value.boolean) ? 1 : 0;
+     return 0;
+ }
+ static int cc_add_daemon_config(oconfig_item_t *ci)
+ {
+     int ret, i;
+     struct ceph_daemon *array, *nd, cd;
+     memset(&cd, 0, sizeof(struct ceph_daemon));
+     if((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+     {
+         WARNING("ceph plugin: `Daemon' blocks need exactly one string "
+                 "argument.");
+         return (-1);
+     }
+     ret = cc_handle_str(ci, cd.name, DATA_MAX_NAME_LEN);
+     if(ret)
+     {
+         return ret;
+     }
+     for(i=0; i < ci->children_num; i++)
+     {
+         oconfig_item_t *child = ci->children + i;
+         if(strcasecmp("SocketPath", child->key) == 0)
+         {
+             ret = cc_handle_str(child, cd.asok_path, sizeof(cd.asok_path));
+             if(ret)
+             {
+                 return ret;
+             }
+         }
+         else
+         {
+             WARNING("ceph plugin: ignoring unknown option %s", child->key);
+         }
+     }
+     if(cd.name[0] == '\0')
+     {
+         ERROR("ceph plugin: you must configure a daemon name.\n");
+         return -EINVAL;
+     }
+     else if(cd.asok_path[0] == '\0')
+     {
+         ERROR("ceph plugin(name=%s): you must configure an administrative "
+         "socket path.\n", cd.name);
+         return -EINVAL;
+     }
+     else if(!((cd.asok_path[0] == '/') ||
+             (cd.asok_path[0] == '.' && cd.asok_path[1] == '/')))
+     {
+         ERROR("ceph plugin(name=%s): administrative socket paths must begin "
+                 "with '/' or './' Can't parse: '%s'\n", cd.name, cd.asok_path);
+         return -EINVAL;
+     }
 -static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum, 
++
+     array = realloc(g_daemons,
+                     sizeof(struct ceph_daemon *) * (g_num_daemons + 1));
+     if(array == NULL)
+     {
+         /* The positive return value here indicates that this is a
+          * runtime error, not a configuration error.  */
+         return ENOMEM;
+     }
+     g_daemons = (struct ceph_daemon**) array;
+     nd = malloc(sizeof(struct ceph_daemon));
+     if(!nd)
+     {
+         return ENOMEM;
+     }
+     memcpy(nd, &cd, sizeof(struct ceph_daemon));
+     g_daemons[g_num_daemons++] = nd;
+     return 0;
+ }
+ static int ceph_config(oconfig_item_t *ci)
+ {
+     int ret, i;
+     for(i = 0; i < ci->children_num; ++i)
+     {
+         oconfig_item_t *child = ci->children + i;
+         if(strcasecmp("Daemon", child->key) == 0)
+         {
+             ret = cc_add_daemon_config(child);
+             if(ret == ENOMEM)
+             {
+                 ERROR("ceph plugin: Couldn't allocate memory");
+                 return ret;
+             }
+             else if(ret)
+             {
+                 //process other daemons and ignore this one
+                 continue;
+             }
+         }
+         else if(strcasecmp("LongRunAvgLatency", child->key) == 0)
+         {
+             ret = cc_handle_bool(child, &long_run_latency_avg);
+             if(ret)
+             {
+                 return ret;
+             }
+         }
+         else if(strcasecmp("ConvertSpecialMetricTypes", child->key) == 0)
+         {
+             ret = cc_handle_bool(child, &convert_special_metrics);
+             if(ret)
+             {
+                 return ret;
+             }
+         }
+         else
+         {
+             WARNING("ceph plugin: ignoring unknown option %s", child->key);
+         }
+     }
+     return 0;
+ }
+ /**
+  * Parse JSON and get error message if present
+  */
+ static int
+ traverse_json(const unsigned char *json, uint32_t json_len, yajl_handle hand)
+ {
+     yajl_status status = yajl_parse(hand, json, json_len);
+     unsigned char *msg;
+     switch(status)
+     {
+         case yajl_status_error:
+             msg = yajl_get_error(hand, /* verbose = */ 1,
+                                        /* jsonText = */ (unsigned char *) json,
+                                                       (unsigned int) json_len);
+             ERROR ("ceph plugin: yajl_parse failed: %s", msg);
+             yajl_free_error(hand, msg);
+             return 1;
+         case yajl_status_client_canceled:
+             return 1;
+         default:
+             return 0;
+     }
+ }
+ /**
+  * Add entry for each counter while parsing schema
+  */
+ static int
+ node_handler_define_schema(void *arg, const char *val, const char *key)
+ {
+     struct ceph_daemon *d = (struct ceph_daemon *) arg;
+     int pc_type;
+     pc_type = atoi(val);
+     return ceph_daemon_add_ds_entry(d, key, pc_type);
+ }
+ /**
+  * Latency counter does not yet have an entry in last poll data - add it.
+  */
 -    
++static int add_last(struct ceph_daemon *d, const char *ds_n, double cur_sum,
+         uint64_t cur_count)
+ {
+     d->last_poll_data[d->last_idx] = malloc(1 * sizeof(struct last_data));
+     if(!d->last_poll_data[d->last_idx])
+     {
+         return -ENOMEM;
+     }
+     sstrncpy(d->last_poll_data[d->last_idx]->ds_name,ds_n,
+             sizeof(d->last_poll_data[d->last_idx]->ds_name));
+     d->last_poll_data[d->last_idx]->last_sum = cur_sum;
+     d->last_poll_data[d->last_idx]->last_count = cur_count;
+     d->last_idx = (d->last_idx + 1);
+     return 0;
+ }
+ /**
+  * Update latency counter or add new entry if it doesn't exist
+  */
+ static int update_last(struct ceph_daemon *d, const char *ds_n, int index,
+         double cur_sum, uint64_t cur_count)
+ {
+     if((d->last_idx > index) && (strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0))
+     {
+         d->last_poll_data[index]->last_sum = cur_sum;
+         d->last_poll_data[index]->last_count = cur_count;
+         return 0;
+     }
+     if(!d->last_poll_data)
+     {
+         d->last_poll_data = malloc(1 * sizeof(struct last_data *));
+         if(!d->last_poll_data)
+         {
+             return -ENOMEM;
+         }
+     }
+     else
+     {
+         struct last_data **tmp_last = realloc(d->last_poll_data,
+                 ((d->last_idx+1) * sizeof(struct last_data *)));
+         if(!tmp_last)
+         {
+             return -ENOMEM;
+         }
+         d->last_poll_data = tmp_last;
+     }
+     return add_last(d, ds_n, cur_sum, cur_count);
+ }
+ /**
+  * If using index guess failed (shouldn't happen, but possible if counters
+  * get rearranged), resort to searching for counter name
+  */
+ static int backup_search_for_last_avg(struct ceph_daemon *d, const char *ds_n)
+ {
+     int i = 0;
+     for(; i < d->last_idx; i++)
+     {
+         if(strcmp(d->last_poll_data[i]->ds_name, ds_n) == 0)
+         {
+             return i;
+         }
+     }
+     return -1;
+ }
+ /**
+  * Calculate average b/t current data and last poll data
+  * if last poll data exists
+  */
+ static double get_last_avg(struct ceph_daemon *d, const char *ds_n, int index,
+         double cur_sum, uint64_t cur_count)
+ {
+     double result = -1.1, sum_delt = 0.0;
+     uint64_t count_delt = 0;
+     int tmp_index = 0;
+     if(d->last_idx > index)
+     {
+         if(strcmp(d->last_poll_data[index]->ds_name, ds_n) == 0)
+         {
+             tmp_index = index;
+         }
+         //test previous index
+         else if((index > 0) && (strcmp(d->last_poll_data[index-1]->ds_name, ds_n) == 0))
+         {
+             tmp_index = (index - 1);
+         }
+         else
+         {
+             tmp_index = backup_search_for_last_avg(d, ds_n);
+         }
+         if((tmp_index > -1) && (cur_count > d->last_poll_data[tmp_index]->last_count))
+         {
+             sum_delt = (cur_sum - d->last_poll_data[tmp_index]->last_sum);
+             count_delt = (cur_count - d->last_poll_data[tmp_index]->last_count);
+             result = (sum_delt / count_delt);
+         }
+     }
+     if(result == -1.1)
+     {
+         result = NAN;
+     }
+     if(update_last(d, ds_n, tmp_index, cur_sum, cur_count) == -ENOMEM)
+     {
+         return -ENOMEM;
+     }
+     return result;
+ }
+ /**
+  * If using index guess failed, resort to searching for counter name
+  */
+ static uint32_t backup_search_for_type(struct ceph_daemon *d, char *ds_name)
+ {
+     int idx = 0;
+     for(; idx < d->ds_num; idx++)
+     {
+         if(strcmp(d->ds_names[idx], ds_name) == 0)
+         {
+             return d->ds_types[idx];
+         }
+     }
+     return DSET_TYPE_UNFOUND;
+ }
+ /**
+  * Process counter data and dispatch values
+  */
+ static int node_handler_fetch_data(void *arg, const char *val, const char *key)
+ {
+     value_t uv;
+     double tmp_d;
+     uint64_t tmp_u;
+     struct values_tmp *vtmp = (struct values_tmp*) arg;
+     uint32_t type = DSET_TYPE_UNFOUND;
+     int index = vtmp->index;
+     char ds_name[DATA_MAX_NAME_LEN];
+     memset(ds_name, 0, sizeof(ds_name));
+     if(parse_keys(key, ds_name))
+     {
+         return 1;
+     }
+     if(index >= vtmp->d->ds_num)
+     {
+         //don't overflow bounds of array
+         index = (vtmp->d->ds_num - 1);
+     }
 -                
++
+     /**
+      * counters should remain in same order we parsed schema... we maintain the
+      * index variable to keep track of current point in list of counters. first
+      * use index to guess point in array for retrieving type. if that doesn't
+      * work, use the old way to get the counter type
+      */
+     if(strcmp(ds_name, vtmp->d->ds_names[index]) == 0)
+     {
+         //found match
+         type = vtmp->d->ds_types[index];
+     }
+     else if((index > 0) && (strcmp(ds_name, vtmp->d->ds_names[index-1]) == 0))
+     {
+         //try previous key
+         type = vtmp->d->ds_types[index-1];
+     }
+     if(type == DSET_TYPE_UNFOUND)
+     {
+         //couldn't find right type by guessing, check the old way
+         type = backup_search_for_type(vtmp->d, ds_name);
+     }
+     switch(type)
+     {
+         case DSET_LATENCY:
+             if(vtmp->avgcount_exists == -1)
+             {
+                 sscanf(val, "%" PRIu64, &vtmp->avgcount);
+                 vtmp->avgcount_exists = 0;
+                 //return after saving avgcount - don't dispatch value
+                 //until latency calculation
+                 return 0;
+             }
+             else
+             {
+                 double sum, result;
+                 sscanf(val, "%lf", &sum);
+                 if(vtmp->avgcount == 0)
+                 {
+                     vtmp->avgcount = 1;
+                 }
++
+                 /** User wants latency values as long run avg */
+                 if(long_run_latency_avg)
+                 {
+                     result = (sum / vtmp->avgcount);
+                 }
+                 else
+                 {
+                     result = get_last_avg(vtmp->d, ds_name, vtmp->latency_index, sum, vtmp->avgcount);
+                     if(result == -ENOMEM)
+                     {
+                         return -ENOMEM;
+                     }
+                 }
+                 uv.gauge = result;
+                 vtmp->avgcount_exists = -1;
+                 vtmp->latency_index = (vtmp->latency_index + 1);
+             }
+             break;
+         case DSET_BYTES:
+             sscanf(val, "%lf", &tmp_d);
+             uv.gauge = tmp_d;
+             break;
+         case DSET_RATE:
+             sscanf(val, "%" PRIu64, &tmp_u);
+             uv.derive = tmp_u;
+             break;
+         case DSET_TYPE_UNFOUND:
+         default:
+             ERROR("ceph plugin: ds %s was not properly initialized.", ds_name);
+             return -1;
+     }
+     sstrncpy(vtmp->vlist.type, ceph_dset_types[type], sizeof(vtmp->vlist.type));
+     sstrncpy(vtmp->vlist.type_instance, ds_name, sizeof(vtmp->vlist.type_instance));
+     vtmp->vlist.values = &uv;
+     vtmp->vlist.values_len = 1;
+     vtmp->index = (vtmp->index + 1);
+     plugin_dispatch_values(&vtmp->vlist);
+     return 0;
+ }
+ static int cconn_connect(struct cconn *io)
+ {
+     struct sockaddr_un address;
+     int flags, fd, err;
+     if(io->state != CSTATE_UNCONNECTED)
+     {
+         ERROR("ceph plugin: cconn_connect: io->state != CSTATE_UNCONNECTED");
+         return -EDOM;
+     }
+     fd = socket(PF_UNIX, SOCK_STREAM, 0);
+     if(fd < 0)
+     {
+         int err = -errno;
+         ERROR("ceph plugin: cconn_connect: socket(PF_UNIX, SOCK_STREAM, 0) "
+             "failed: error %d", err);
+         return err;
+     }
+     memset(&address, 0, sizeof(struct sockaddr_un));
+     address.sun_family = AF_UNIX;
+     snprintf(address.sun_path, sizeof(address.sun_path), "%s",
+             io->d->asok_path);
+     RETRY_ON_EINTR(err,
+         connect(fd, (struct sockaddr *) &address, sizeof(struct sockaddr_un)));
+     if(err < 0)
+     {
+         ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d",
+             fd, err);
+         return err;
+     }
+     flags = fcntl(fd, F_GETFL, 0);
+     if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0)
+     {
+         err = -errno;
+         ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d",
+             fd, err);
+         return err;
+     }
+     io->asok = fd;
+     io->state = CSTATE_WRITE_REQUEST;
+     io->amt = 0;
+     io->json_len = 0;
+     io->json = NULL;
+     return 0;
+ }
+ static void cconn_close(struct cconn *io)
+ {
+     io->state = CSTATE_UNCONNECTED;
+     if(io->asok != -1)
+     {
+         int res;
+         RETRY_ON_EINTR(res, close(io->asok));
+     }
+     io->asok = -1;
+     io->amt = 0;
+     io->json_len = 0;
+     sfree(io->json);
+     io->json = NULL;
+ }
+ /* Process incoming JSON counter data */
+ static int
+ cconn_process_data(struct cconn *io, yajl_struct *yajl, yajl_handle hand)
+ {
+     int ret;
+     struct values_tmp *vtmp = calloc(1, sizeof(struct values_tmp) * 1);
+     if(!vtmp)
+     {
+         return -ENOMEM;
+     }
+     vtmp->vlist = (value_list_t)VALUE_LIST_INIT;
+     sstrncpy(vtmp->vlist.host, hostname_g, sizeof(vtmp->vlist.host));
+     sstrncpy(vtmp->vlist.plugin, "ceph", sizeof(vtmp->vlist.plugin));
+     sstrncpy(vtmp->vlist.plugin_instance, io->d->name, sizeof(vtmp->vlist.plugin_instance));
+     vtmp->d = io->d;
+     vtmp->avgcount_exists = -1;
+     vtmp->latency_index = 0;
+     vtmp->index = 0;
+     yajl->handler_arg = vtmp;
+     ret = traverse_json(io->json, io->json_len, hand);
+     sfree(vtmp);
+     return ret;
+ }
+ /**
+  * Initiate JSON parsing and print error if one occurs
+  */
+ static int cconn_process_json(struct cconn *io)
+ {
+     if((io->request_type != ASOK_REQ_DATA) &&
+             (io->request_type != ASOK_REQ_SCHEMA))
+     {
+         return -EDOM;
+     }
+     int result = 1;
+     yajl_handle hand;
+     yajl_status status;
+     hand = yajl_alloc(&callbacks,
+ #if HAVE_YAJL_V2
+       /* alloc funcs = */ NULL,
+ #else
+       /* alloc funcs = */ NULL, NULL,
+ #endif
+       /* context = */ (void *)(&io->yajl));
+     if(!hand)
+     {
+         ERROR ("ceph plugin: yajl_alloc failed.");
+         return ENOMEM;
+     }
+     io->yajl.depth = 0;
+     switch(io->request_type)
+     {
+         case ASOK_REQ_DATA:
+             io->yajl.handler = node_handler_fetch_data;
+             result = cconn_process_data(io, &io->yajl, hand);
+             break;
+         case ASOK_REQ_SCHEMA:
+             //init daemon specific variables
+             io->d->ds_num = 0;
+             io->d->last_idx = 0;
+             io->d->last_poll_data = NULL;
+             io->yajl.handler = node_handler_define_schema;
+             io->yajl.handler_arg = io->d;
+             result = traverse_json(io->json, io->json_len, hand);
+             break;
+     }
+     if(result)
+     {
+         goto done;
+     }
+ #if HAVE_YAJL_V2
+     status = yajl_complete_parse(hand);
+ #else
+     status = yajl_parse_complete(hand);
+ #endif
+     if (status != yajl_status_ok)
+     {
+       unsigned char *errmsg = yajl_get_error (hand, /* verbose = */ 0,
+           /* jsonText = */ NULL, /* jsonTextLen = */ 0);
+       ERROR ("ceph plugin: yajl_parse_complete failed: %s",
+           (char *) errmsg);
+       yajl_free_error (hand, errmsg);
+       yajl_free (hand);
+       return 1;
+     }
+     done:
+     yajl_free (hand);
+     return result;
+ }
+ static int cconn_validate_revents(struct cconn *io, int revents)
+ {
+     if(revents & POLLERR)
+     {
+         ERROR("ceph plugin: cconn_validate_revents(name=%s): got POLLERR",
+             io->d->name);
+         return -EIO;
+     }
+     switch (io->state)
+     {
+         case CSTATE_WRITE_REQUEST:
+             return (revents & POLLOUT) ? 0 : -EINVAL;
+         case CSTATE_READ_VERSION:
+         case CSTATE_READ_AMT:
+         case CSTATE_READ_JSON:
+             return (revents & POLLIN) ? 0 : -EINVAL;
+         default:
+             ERROR("ceph plugin: cconn_validate_revents(name=%s) got to "
+                 "illegal state on line %d", io->d->name, __LINE__);
+             return -EDOM;
+     }
+ }
+ /** Handle a network event for a connection */
+ static int cconn_handle_event(struct cconn *io)
+ {
+     int ret;
+     switch (io->state)
+     {
+         case CSTATE_UNCONNECTED:
+             ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal "
+                 "state on line %d", io->d->name, __LINE__);
+             return -EDOM;
+         case CSTATE_WRITE_REQUEST:
+         {
+             char cmd[32];
+             snprintf(cmd, sizeof(cmd), "%s%d%s", "{ \"prefix\": \"",
+                     io->request_type, "\" }\n");
+             size_t cmd_len = strlen(cmd);
+             RETRY_ON_EINTR(ret,
+                   write(io->asok, ((char*)&cmd) + io->amt, cmd_len - io->amt));
+             DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,amt=%d,ret=%d)",
+                     io->d->name, io->state, io->amt, ret);
+             if(ret < 0)
+             {
+                 return ret;
+             }
+             io->amt += ret;
+             if(io->amt >= cmd_len)
+             {
+                 io->amt = 0;
+                 switch (io->request_type)
+                 {
+                     case ASOK_REQ_VERSION:
+                         io->state = CSTATE_READ_VERSION;
+                         break;
+                     default:
+                         io->state = CSTATE_READ_AMT;
+                         break;
+                 }
+             }
+             return 0;
+         }
+         case CSTATE_READ_VERSION:
+         {
+             RETRY_ON_EINTR(ret,
+                     read(io->asok, ((char*)(&io->d->version)) + io->amt,
+                             sizeof(io->d->version) - io->amt));
+             DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                     io->d->name, io->state, ret);
+             if(ret < 0)
+             {
+                 return ret;
+             }
+             io->amt += ret;
+             if(io->amt >= sizeof(io->d->version))
+             {
+                 io->d->version = ntohl(io->d->version);
+                 if(io->d->version != 1)
+                 {
+                     ERROR("ceph plugin: cconn_handle_event(name=%s) not "
+                         "expecting version %d!", io->d->name, io->d->version);
+                     return -ENOTSUP;
+                 }
+                 DEBUG("ceph plugin: cconn_handle_event(name=%s): identified as "
+                         "version %d", io->d->name, io->d->version);
+                 io->amt = 0;
+                 cconn_close(io);
+                 io->request_type = ASOK_REQ_SCHEMA;
+             }
+             return 0;
+         }
+         case CSTATE_READ_AMT:
+         {
+             RETRY_ON_EINTR(ret,
+                     read(io->asok, ((char*)(&io->json_len)) + io->amt,
+                             sizeof(io->json_len) - io->amt));
+             DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                     io->d->name, io->state, ret);
+             if(ret < 0)
+             {
+                 return ret;
+             }
+             io->amt += ret;
+             if(io->amt >= sizeof(io->json_len))
+             {
+                 io->json_len = ntohl(io->json_len);
+                 io->amt = 0;
+                 io->state = CSTATE_READ_JSON;
+                 io->json = calloc(1, io->json_len + 1);
+                 if(!io->json)
+                 {
+                     ERROR("ceph plugin: error callocing io->json");
+                     return -ENOMEM;
+                 }
+             }
+             return 0;
+         }
+         case CSTATE_READ_JSON:
+         {
+             RETRY_ON_EINTR(ret,
+                    read(io->asok, io->json + io->amt, io->json_len - io->amt));
+             DEBUG("ceph plugin: cconn_handle_event(name=%s,state=%d,ret=%d)",
+                     io->d->name, io->state, ret);
+             if(ret < 0)
+             {
+                 return ret;
+             }
+             io->amt += ret;
+             if(io->amt >= io->json_len)
+             {
+                 ret = cconn_process_json(io);
+                 if(ret)
+                 {
+                     return ret;
+                 }
+                 cconn_close(io);
+                 io->request_type = ASOK_REQ_NONE;
+             }
+             return 0;
+         }
+         default:
+             ERROR("ceph plugin: cconn_handle_event(name=%s) got to illegal "
+                 "state on line %d", io->d->name, __LINE__);
+             return -EDOM;
+     }
+ }
+ static int cconn_prepare(struct cconn *io, struct pollfd* fds)
+ {
+     int ret;
+     if(io->request_type == ASOK_REQ_NONE)
+     {
+         /* The request has already been serviced. */
+         return 0;
+     }
+     else if((io->request_type == ASOK_REQ_DATA) && (io->d->ds_num == 0))
+     {
+         /* If there are no counters to report on, don't bother
+          * connecting */
+         return 0;
+     }
+     switch (io->state)
+     {
+         case CSTATE_UNCONNECTED:
+             ret = cconn_connect(io);
+             if(ret > 0)
+             {
+                 return -ret;
+             }
+             else if(ret < 0)
+             {
+                 return ret;
+             }
+             fds->fd = io->asok;
+             fds->events = POLLOUT;
+             return 1;
+         case CSTATE_WRITE_REQUEST:
+             fds->fd = io->asok;
+             fds->events = POLLOUT;
+             return 1;
+         case CSTATE_READ_VERSION:
+         case CSTATE_READ_AMT:
+         case CSTATE_READ_JSON:
+             fds->fd = io->asok;
+             fds->events = POLLIN;
+             return 1;
+         default:
+             ERROR("ceph plugin: cconn_prepare(name=%s) got to illegal state "
+                 "on line %d", io->d->name, __LINE__);
+             return -EDOM;
+     }
+ }
+ /** Returns the difference between two struct timevals in milliseconds.
+  * On overflow, we return max/min int.
+  */
+ static int milli_diff(const struct timeval *t1, const struct timeval *t2)
+ {
+     int64_t ret;
+     int sec_diff = t1->tv_sec - t2->tv_sec;
+     int usec_diff = t1->tv_usec - t2->tv_usec;
+     ret = usec_diff / 1000;
+     ret += (sec_diff * 1000);
+     return (ret > INT_MAX) ? INT_MAX : ((ret < INT_MIN) ? INT_MIN : (int)ret);
+ }
+ /** This handles the actual network I/O to talk to the Ceph daemons.
+  */
+ static int cconn_main_loop(uint32_t request_type)
+ {
+     int i, ret, some_unreachable = 0;
+     struct timeval end_tv;
+     struct cconn io_array[g_num_daemons];
+     DEBUG("ceph plugin: entering cconn_main_loop(request_type = %d)", request_type);
+     /* create cconn array */
+     memset(io_array, 0, sizeof(io_array));
+     for(i = 0; i < g_num_daemons; ++i)
+     {
+         io_array[i].d = g_daemons[i];
+         io_array[i].request_type = request_type;
+         io_array[i].state = CSTATE_UNCONNECTED;
+     }
+     /** Calculate the time at which we should give up */
+     gettimeofday(&end_tv, NULL);
+     end_tv.tv_sec += CEPH_TIMEOUT_INTERVAL;
+     while (1)
+     {
+         int nfds, diff;
+         struct timeval tv;
+         struct cconn *polled_io_array[g_num_daemons];
+         struct pollfd fds[g_num_daemons];
+         memset(fds, 0, sizeof(fds));
+         nfds = 0;
+         for(i = 0; i < g_num_daemons; ++i)
+         {
+             struct cconn *io = io_array + i;
+             ret = cconn_prepare(io, fds + nfds);
+             if(ret < 0)
+             {
+                 WARNING("ceph plugin: cconn_prepare(name=%s,i=%d,st=%d)=%d",
+                         io->d->name, i, io->state, ret);
+                 cconn_close(io);
+                 io->request_type = ASOK_REQ_NONE;
+                 some_unreachable = 1;
+             }
+             else if(ret == 1)
+             {
+                 polled_io_array[nfds++] = io_array + i;
+             }
+         }
+         if(nfds == 0)
+         {
+             /* finished */
+             ret = 0;
+             goto done;
+         }
+         gettimeofday(&tv, NULL);
+         diff = milli_diff(&end_tv, &tv);
+         if(diff <= 0)
+         {
+             /* Timed out */
+             ret = -ETIMEDOUT;
+             WARNING("ceph plugin: cconn_main_loop: timed out.");
+             goto done;
+         }
+         RETRY_ON_EINTR(ret, poll(fds, nfds, diff));
+         if(ret < 0)
+         {
+             ERROR("ceph plugin: poll(2) error: %d", ret);
+             goto done;
+         }
+         for(i = 0; i < nfds; ++i)
+         {
+             struct cconn *io = polled_io_array[i];
+             int revents = fds[i].revents;
+             if(revents == 0)
+             {
+                 /* do nothing */
+             }
+             else if(cconn_validate_revents(io, revents))
+             {
+                 WARNING("ceph plugin: cconn(name=%s,i=%d,st=%d): "
+                 "revents validation error: "
+                 "revents=0x%08x", io->d->name, i, io->state, revents);
+                 cconn_close(io);
+                 io->request_type = ASOK_REQ_NONE;
+                 some_unreachable = 1;
+             }
+             else
+             {
+                 int ret = cconn_handle_event(io);
+                 if(ret)
+                 {
+                     WARNING("ceph plugin: cconn_handle_event(name=%s,"
+                     "i=%d,st=%d): error %d", io->d->name, i, io->state, ret);
+                     cconn_close(io);
+                     io->request_type = ASOK_REQ_NONE;
+                     some_unreachable = 1;
+                 }
+             }
+         }
+     }
+     done: for(i = 0; i < g_num_daemons; ++i)
+     {
+         cconn_close(io_array + i);
+     }
+     if(some_unreachable)
+     {
+         DEBUG("ceph plugin: cconn_main_loop: some Ceph daemons were unreachable.");
+     }
+     else
+     {
+         DEBUG("ceph plugin: cconn_main_loop: reached all Ceph daemons :)");
+     }
+     return ret;
+ }
+ static int ceph_read(void)
+ {
+     return cconn_main_loop(ASOK_REQ_DATA);
+ }
+ /******* lifecycle *******/
+ static int ceph_init(void)
+ {
+     int ret;
+     ceph_daemons_print();
+     ret = cconn_main_loop(ASOK_REQ_VERSION);
+     return (ret) ? ret : 0;
+ }
+ static int ceph_shutdown(void)
+ {
+     int i;
+     for(i = 0; i < g_num_daemons; ++i)
+     {
+         ceph_daemon_free(g_daemons[i]);
+     }
+     sfree(g_daemons);
+     g_daemons = NULL;
+     g_num_daemons = 0;
+     DEBUG("ceph plugin: finished ceph_shutdown");
+     return 0;
+ }
+ void module_register(void)
+ {
+     plugin_register_complex_config("ceph", ceph_config);
+     plugin_register_init("ceph", ceph_init);
+     plugin_register_read("ceph", ceph_read);
+     plugin_register_shutdown("ceph", ceph_shutdown);
+ }
diff --combined src/collectd.conf.in
  #AutoLoadPlugin false
  
  #----------------------------------------------------------------------------#
 +# When enabled, internal statistics are collected, using "collectd" as the   #
 +# plugin name.                                                               #
 +# Disabled by default.                                                       #
 +#----------------------------------------------------------------------------#
 +#CollectInternalStats false
 +
 +#----------------------------------------------------------------------------#
  # Interval at which to query values. This may be overwritten on a per-plugin #
  # base by using the 'Interval' option of the LoadPlugin block:               #
  #   <LoadPlugin foo>                                                         #
  #----------------------------------------------------------------------------#
  #Interval     10
  
 -#Timeout      2
 -#ReadThreads  5
 -#WriteThreads 5
 +#MaxReadInterval 86400
 +#Timeout         2
 +#ReadThreads     5
 +#WriteThreads    5
  
  # Limit the size of the write queue. Default is no limit. Setting up a limit is
  # recommended for servers handling a high volume of traffic.
@@@ -60,7 -52,6 +60,7 @@@
  
  @LOAD_PLUGIN_SYSLOG@LoadPlugin syslog
  @LOAD_PLUGIN_LOGFILE@LoadPlugin logfile
 +@LOAD_PLUGIN_LOG_LOGSTASH@LoadPlugin log_logstash
  
  #<Plugin logfile>
  #     LogLevel @DEFAULT_LOG_LEVEL@
  #     PrintSeverity false
  #</Plugin>
  
 +#<Plugin log_logstash>
 +#     LogLevel @DEFAULT_LOG_LEVEL@
 +#     File "@localstatedir@/log/@PACKAGE_NAME@.json.log"
 +#</Plugin>
 +
  #<Plugin syslog>
  #     LogLevel @DEFAULT_LOG_LEVEL@
  #</Plugin>
  #@BUILD_PLUGIN_APPLE_SENSORS_TRUE@LoadPlugin apple_sensors
  #@BUILD_PLUGIN_AQUAERO_TRUE@LoadPlugin aquaero
  #@BUILD_PLUGIN_ASCENT_TRUE@LoadPlugin ascent
 +#@BUILD_PLUGIN_BAROMETER_TRUE@LoadPlugin barometer
  #@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
  #@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
+ #@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
  #@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
  #@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
  #@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
  #@BUILD_PLUGIN_DF_TRUE@LoadPlugin df
  #@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk
  #@BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns
 +#@BUILD_PLUGIN_DRBD_TRUE@LoadPlugin drbd
  #@BUILD_PLUGIN_EMAIL_TRUE@LoadPlugin email
  #@BUILD_PLUGIN_ENTROPY_TRUE@LoadPlugin entropy
  #@BUILD_PLUGIN_ETHSTAT_TRUE@LoadPlugin ethstat
  #@BUILD_PLUGIN_IPVS_TRUE@LoadPlugin ipvs
  #@BUILD_PLUGIN_IRQ_TRUE@LoadPlugin irq
  #@BUILD_PLUGIN_JAVA_TRUE@LoadPlugin java
 -#@BUILD_PLUGIN_LIBVIRT_TRUE@LoadPlugin libvirt
  @BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
  #@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
  #@BUILD_PLUGIN_LVM_TRUE@LoadPlugin lvm
  #@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
  #@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
  #@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
  #@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
 +#@BUILD_PLUGIN_VIRT_TRUE@LoadPlugin virt
  #@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
  #@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
  #@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
  #@BUILD_PLUGIN_WRITE_GRAPHITE_TRUE@LoadPlugin write_graphite
  #@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
 +#@BUILD_PLUGIN_WRITE_KAFKA_TRUE@LoadPlugin write_kafka
 +#@BUILD_PLUGIN_WRITE_LOG_TRUE@LoadPlugin write_log
  #@BUILD_PLUGIN_WRITE_MONGODB_TRUE@LoadPlugin write_mongodb
  #@BUILD_PLUGIN_WRITE_REDIS_TRUE@LoadPlugin write_redis
  #@BUILD_PLUGIN_WRITE_RIEMANN_TRUE@LoadPlugin write_riemann
 +#@BUILD_PLUGIN_WRITE_TSDB_TRUE@LoadPlugin write_tsdb
  #@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
  #@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
 +#@BUILD_PLUGIN_ZOOKEEPER_TRUE@LoadPlugin zookeeper
  
  ##############################################################################
  # Plugin configuration                                                       #
  # ription of those options is available in the collectd.conf(5) manual page. #
  ##############################################################################
  
 -#<Plugin "aggregation">
 +#<Plugin aggregation>
  #  <Aggregation>
  #    #Host "unspecified"
  #    Plugin "cpu"
  #  </Aggregation>
  #</Plugin>
  
 -#<Plugin "amqp">
 +#<Plugin amqp>
  #  <Publish "name">
  #    Host "localhost"
  #    Port "5672"
  #     CACert "/etc/ssl/ca.crt"
  #</Plugin>
  
 +#<Plugin "barometer">
 +#   Device            "/dev/i2c-0";
 +#   Oversampling      512
 +#   PressureOffset    0.0
 +#   TemperatureOffset 0.0
 +#   Normalization     2
 +#   Altitude          238.0
 +#   TemperatureSensor "myserver/onewire-F10FCA000800/temperature"
 +#</Plugin>
 +
 +#<Plugin "battery">
 +#  ValuesPercentage false
 +#  ReportDegraded
 +#</Plugin>
 +
  #<Plugin "bind">
  #  URL "http://localhost:8053/"
  #  ParseTime       false
  #  </View>
  #</Plugin>
  
 -
 -#<Plugin cgroup>
+ #<Plugin ceph>
+ #  LongRunAvgLatency false
+ #  ConvertSpecialMetricTypes true
+ #  <Daemon "osd.0">
+ #    SocketPath "/var/run/ceph/ceph-osd.0.asok"
+ #  </Daemon>
+ #  <Daemon "osd.1">
+ #    SocketPath "/var/run/ceph/ceph-osd.1.asok"
+ #  </Daemon>
+ #  <Daemon "mon.a">
+ #    SocketPath "/var/run/ceph/ceph-mon.ceph1.asok"
+ #  </Daemon>
+ #  <Daemon "mds.a">
+ #    SocketPath "/var/run/ceph/ceph-mds.ceph1.asok"
+ #  </Daemon>
+ #</Plugin>
 +#<Plugin cgroups>
  #  CGroup "libvirt"
  #  IgnoreSelected false
  #</Plugin>
  
 +#<Plugin cpu>
 +#  ReportByCpu true
 +#  ReportByState true
 +#  ValuesPercentage false
 +#</Plugin>
 +#
  #<Plugin csv>
  #     DataDir "@localstatedir@/lib/@PACKAGE_NAME@/csv"
  #     StoreRates false
  #    URL "http://finance.google.com/finance?q=NYSE%3AAMD"
  #    User "foo"
  #    Password "bar"
 +#    Digest false
 +#    VerifyPeer true
 +#    VerifyHost true
 +#    CACert "/path/to/ca.crt"
 +#    Header "X-Custom-Header: foobar"
 +#    Post "foo=bar"
 +#
  #    MeasureResponseTime false
 +#    MeasureResponseCode false
  #    <Match>
  #      Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
  #      DSType "GaugeAverage"
  #</Plugin>
  
  #<Plugin curl_json>
 +#  <URL "http://localhost:80/test.json">
 +#    Instance "test_http_json"
 +#    <Key "testArray/0">
 +#      Type "gauge"
 +#      # Expect: 1
 +#    </Key>
 +#    <Key "testArray/1">
 +#      Type "gauge"
 +#      # Expect: 2
 +#    </Key>
 +#    <Key "testArrayInbetween/0/blarg">
 +#      Type "gauge"
 +#      # Expect: 3
 +#    </Key>
 +#    <Key "testArrayInbetween/1/blub">
 +#      Type "gauge"
 +#      # Expect: 4
 +#    </Key>
 +#    <Key "testDirectHit">
 +#      Type "gauge"
 +#      # Expect: 5
 +#    </Key>
 +#    <Key "testSubLevelHit/oneMoreLevel">
 +#      Type "gauge"
 +#      # Expect: 6
 +#    </Key>
 +#  </URL>
 +# put this as test.json on your webserver, the above config demonstraces
 +# how to match them.
 +# {
 +#  "testArray":[1,2],
 +#  "testArrayInbetween":[{"blarg":3},{"blub":4}],
 +#  "testDirectHit":5,
 +#  "testSubLevelHit":{"oneMoreLevel":6}
 +# }
  ## See: http://wiki.apache.org/couchdb/Runtime_Statistics
  #  <URL "http://localhost:5984/_stats">
  #    Instance "httpd"
  #  </URL>
  #</Plugin>
  
 -#<Plugin "curl_xml">
 +#<Plugin curl_xml>
  #  <URL "http://localhost/stats.xml">
  #    Host "my_host"
  #    Instance "some_instance"
  #    User "collectd"
  #    Password "thaiNg0I"
 +#    Digest false
  #    VerifyPeer true
  #    VerifyHost true
  #    CACert "/path/to/ca.crt"
 +#    Header "X-Custom-Header: foobar"
 +#    Post "foo=bar"
  #
  #    <XPath "table[@id=\"magic_level\"]/tr">
  #      Type "magic_level"
  #<Plugin disk>
  #     Disk "/^[hs]d[a-f][0-9]?$/"
  #     IgnoreSelected false
 +#     UseBSDName false
 +#     UdevNameAttr "DEVNAME"
  #</Plugin>
  
  #<Plugin dns>
  #     </Directory>
  #</Plugin>
  
 -#<Plugin "gmond">
 +#<Plugin gmond>
  #  MCReceiveFrom "239.2.11.71" "8649"
  #  <Metric "swap_total">
  #    Type "swap"
  #     IgnoreSelected true
  #</Plugin>
  
 -#<Plugin "java">
 +#<Plugin java>
  #     JVMArg "-verbose:jni"
  #     JVMArg "-Djava.class.path=@prefix@/share/collectd/java/collectd-api.jar"
  #
  #     </Plugin>
  #</Plugin>
  
 -#<Plugin libvirt>
 -#     Connection "xen:///"
 -#     RefreshInterval 60
 -#     Domain "name"
 -#     BlockDevice "name:device"
 -#     InterfaceDevice "name:device"
 -#     IgnoreSelected false
 -#     HostnameFormat name
 -#     InterfaceFormat name
 -#</Plugin>
 -
  #<Plugin load>
  #        ReportRelative true
  #</Plugin>
  #<Plugin modbus>
  #     <Data "data_name">
  #             RegisterBase 1234
 +#             RegisterCmd ReadHolding
  #             RegisterType float
  #             Type gauge
  #             Instance "..."
  #             Password "secret"
  #             Database "db_name"
  #             MasterStats true
 +#             ConnectTimeout 10
 +#             InnodbStats true
  #     </Database>
  #
  #     <Database db_name2>
 +#             Alias "squeeze"
  #             Host "localhost"
  #             Socket "/var/run/mysql/mysqld.sock"
  #             SlaveStats true
  #             Username "user"
  #             Password "secret"
  #             Interface "eth0"
 +#             ResolveInterval 14400
  @LOAD_PLUGIN_NETWORK@ </Server>
 -#     TimeToLive "128"
 +#     TimeToLive 128
  #
  #     # server setup:
  #     Listen "ff18::efc0:4a42" "25826"
  #             AuthFile "/etc/collectd/passwd"
  #             Interface "eth0"
  #     </Listen>
 -#     MaxPacketSize 1024
 +#     MaxPacketSize 1452
  #
  #     # proxy setup (client and server as above):
  #     Forward true
  #     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"
  #  DeleteGauges   false
  #  DeleteSets     false
  #  TimerPercentile 90.0
 +#  TimerPercentile 95.0
 +#  TimerPercentile 99.0
 +#  TimerLower     false
 +#  TimerUpper     false
 +#  TimerSum       false
 +#  TimerCount     false
  #</Plugin>
  
 -#<Plugin "swap">
 +#<Plugin swap>
  #     ReportByDevice false
  #     ReportBytes true
  #     ValuesAbsolute true
  #     ValuesPercentage false
  #</Plugin>
  
 -#<Plugin "table">
 +#<Plugin table>
  #     <Table "/proc/slabinfo">
  #             Instance "slabinfo"
  #             Separator " "
  #     </Table>
  #</Plugin>
  
 -#<Plugin "tail">
 +#<Plugin tail>
  #  <File "/var/log/exim4/mainlog">
  #    Instance "exim"
  #    Interval 60
  #  </File>
  #</Plugin>
  
 -#<Plugin "tail_csv">
 +#<Plugin tail_csv>
  #   <Metric "dropped">
  #       Type "percent"
  #       Instance "dropped"
  
  #<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>
  
 +#<Plugin virt>
 +#     Connection "xen:///"
 +#     RefreshInterval 60
 +#     Domain "name"
 +#     BlockDevice "name:device"
 +#     InterfaceDevice "name:device"
 +#     IgnoreSelected false
 +#     HostnameFormat name
 +#     InterfaceFormat name
 +#     PluginInstanceFormat name
 +#</Plugin>
 +
  #<Plugin vmem>
  #     Verbose false
  #</Plugin>
  #</Plugin>
  
  #<Plugin write_http>
 -#     <URL "http://example.com/collectd-post">
 +#     <Node "example">
 +#             URL "http://example.com/collectd-post"
  #             User "collectd"
  #             Password "weCh3ik0"
  #             VerifyPeer true
  #             VerifyHost true
  #             CACert "/etc/ssl/ca.crt"
 +#             CAPath "/etc/ssl/certs/"
 +#             ClientKey "/etc/ssl/client.pem"
 +#             ClientCert "/etc/ssl/client.crt"
 +#             ClientKeyPass "secret"
 +#             SSLVersion "TLSv1"
  #             Format "Command"
  #             StoreRates false
 -#     </URL>
 +#             BufferSize 4096
 +#     </Node>
 +#</Plugin>
 +
 +#<Plugin write_kafka>
 +#  Property "metadata.broker.list" "localhost:9092"
 +#  <Topic "collectd">
 +#    Format JSON
 +#  </Topic>
  #</Plugin>
  
  #<Plugin write_mongodb>
  #     <Node "example">
  #             Host "localhost"
  #             Port 5555
 -#             Protocol UDP
 +#             Protocol TCP
 +#             Batch true
 +#             BatchMaxSize 8192
  #             StoreRates true
  #             AlwaysAppendDS false
  #             TTLFactor 2.0
 +#             Notifications true
 +#             CheckThresholds false
 +#             EventServicePrefix ""
  #     </Node>
  #     Tag "foobar"
 -#       Attribute "foo" "bar"
 +#     Attribute "foo" "bar"
 +#</Plugin>
 +
 +#<Plugin write_tsdb>
 +#     <Node>
 +#             Host "localhost"
 +#             Port "4242"
 +#             HostTags "status=production"
 +#             StoreRates false
 +#             AlwaysAppendDS false
 +#     </Node>
 +#</Plugin>
 +
 +#<Plugin zookeeper>
 +#    Host "localhost"
 +#    Port "2181"
  #</Plugin>
  
  ##############################################################################
  ##############################################################################
  
  #@BUILD_PLUGIN_THRESHOLD_TRUE@LoadPlugin "threshold"
 -#<Plugin "threshold">
 +#<Plugin threshold>
  #  <Type "foo">
  #    WarningMin    0.00
  #    WarningMax 1000.00
diff --combined src/collectd.conf.pod
@@@ -6,9 -6,9 +6,9 @@@ collectd.conf - Configuration for the s
  
  =head1 SYNOPSIS
  
 -  BaseDir "/path/to/data/"
 -  PIDFile "/path/to/pidfile/collectd.pid"
 -  Server  "123.123.123.123" 12345
 +  BaseDir "/var/lib/collectd"
 +  PIDFile "/run/collectd.pid"
 +  Interval 10.0
  
    LoadPlugin cpu
    LoadPlugin load
@@@ -16,9 -16,6 +16,9 @@@
    <LoadPlugin df>
      Interval 3600
    </LoadPlugin>
 +  <Plugin df>
 +    ValuesPercentage true
 +  </Plugin>
  
    LoadPlugin ping
    <Plugin ping>
@@@ -31,9 -28,7 +31,9 @@@
  This config file controls how the system statistics collection daemon
  B<collectd> behaves. The most significant option is B<LoadPlugin>, which
  controls which plugins to load. These plugins ultimately define collectd's
 -behavior.
 +behavior. If the B<AutoLoadPlugin> option has been enabled, the explicit
 +B<LoadPlugin> lines may be omitted for all plugins with a configuration block,
 +i.e. a C<E<lt>PluginE<nbsp>...E<gt>> block.
  
  The syntax of this config file is similar to the config file of the famous
  I<Apache> webserver. Each line contains either an option (a key and a list of
@@@ -60,9 -55,8 +60,9 @@@ indenting the wrapped lines
  The configuration is read and processed in order, i.e. from top to bottom. So
  the plugins are loaded in the order listed in this config file. It is a good
  idea to load any logging plugins first in order to catch messages from plugins
 -during configuration. Also, the C<LoadPlugin> option B<must> occur B<before>
 -the appropriate C<E<lt>Plugin ...E<gt>> block.
 +during configuration. Also, unless B<AutoLoadPlugin> is enabled, the
 +B<LoadPlugin> option I<must> occur I<before> the appropriate
 +C<E<lt>B<Plugin> ...E<gt>> block.
  
  =head1 GLOBAL OPTIONS
  
@@@ -146,18 -140,6 +146,18 @@@ B<E<lt>PluginE<nbsp>...E<gt>> block act
  B<LoadPlugin> statement. B<LoadPlugin> statements are still required for
  plugins that don't provide any configuration, e.g. the I<Load plugin>.
  
 +=item B<CollectInternalStats> B<false>|B<true>
 +
 +When set to B<true>, various statistics about the I<collectd> daemon will be
 +collected, with "collectd" as the I<plugin name>. Defaults to B<false>.
 +
 +The "write_queue" I<plugin instance> reports the number of elements currently
 +queued and the number of elements dropped off the queue by the
 +B<WriteQueueLimitLow>/B<WriteQueueLimitHigh> mechanism.
 +
 +The "cache" I<plugin instance> reports the number of elements in the value list
 +cache (the cache you can interact with using L<collectd-unixsock(5)>).
 +
  =item B<Include> I<Path> [I<pattern>]
  
  If I<Path> points to a file, includes that file. If I<Path> points to a
@@@ -230,14 -212,6 +230,14 @@@ B<Warning:> You should set this once an
  I<you will have to delete all your RRD files> or know some serious RRDtool
  magic! (Assuming you're using the I<RRDtool> or I<RRDCacheD> plugin.)
  
 +=item B<MaxReadInterval> I<Seconds>
 +
 +Read plugin doubles interval between queries after each failed attempt
 +to get data.
 +
 +This options limits the maximum value of the interval. The default value is
 +B<86400>.
 +
  =item B<Timeout> I<Iterations>
  
  Consider a value list "missing" when no update has been read or received for
@@@ -288,11 -262,8 +288,11 @@@ If B<WriteQueueLimitHigh> is set to non
  unset, the latter will default to half of B<WriteQueueLimitHigh>.
  
  If you do not want to randomly drop values when the queue size is between
 -I<LowNum> and I<HighNum>, set If B<WriteQueueLimitHigh> and
 -B<WriteQueueLimitLow> to same value.
 +I<LowNum> and I<HighNum>, set B<WriteQueueLimitHigh> and B<WriteQueueLimitLow>
 +to the same value.
 +
 +Enabling the B<CollectInternalStats> option is of great help to figure out the
 +values to set B<WriteQueueLimitHigh> and B<WriteQueueLimitLow> to.
  
  =item B<Hostname> I<Name>
  
@@@ -523,8 -494,6 +523,8 @@@ possibly filtering or messages
   #   StoreRates false
   #   GraphitePrefix "collectd."
   #   GraphiteEscapeChar "_"
 + #   GraphiteSeparateInstances false
 + #   GraphiteAlwaysAppendDS false
     </Publish>
  
     # Receive values from an AMQP broker
       Exchange "amq.fanout"
   #   ExchangeType "fanout"
   #   Queue "queue_name"
 + #   QueueDurable false
 + #   QueueAutoDelete true
   #   RoutingKey "collectd.#"
     </Subscribe>
   </Plugin>
@@@ -591,23 -558,9 +591,23 @@@ be bound to this exchange
  
  =item B<Queue> I<Queue> (Subscribe only)
  
 -Configures the I<queue> name to subscribe to. If no queue name was configures
 +Configures the I<queue> name to subscribe to. If no queue name was configured
  explicitly, a unique queue name will be created by the broker.
  
 +=item B<QueueDurable> B<true>|B<false> (Subscribe only)
 +
 +Defines if the I<queue> subscribed to is durable (saved to persistent storage)
 +or transient (will disappear if the AMQP broker is restarted). Defaults to
 +"false".
 +
 +This option should be used in conjunction with the I<Persistent> option on the
 +publish side.
 +
 +=item B<QueueAutoDelete> B<true>|B<false> (Subscribe only)
 +
 +Defines if the I<queue> subscribed to will be deleted once the last consumer
 +unsubscribes. Defaults to "true".
 +
  =item B<RoutingKey> I<Key>
  
  In I<Publish> blocks, this configures the routing key to set on all outgoing
@@@ -678,19 -631,6 +678,19 @@@ In I<Graphite> metric name, dots are us
  metric parts (host, plugin, type).
  Default is "_" (I<Underscore>).
  
 +=item B<GraphiteSeparateInstances> B<true>|B<false>
 +
 +If set to B<true>, the plugin instance and type instance will be in their own
 +path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
 +default), the plugin and plugin instance (and likewise the type and type
 +instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
 +
 +=item B<GraphiteAlwaysAppendDS> B<true>|B<false>
 +
 +If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
 +identifier. If set to B<false> (the default), this is only done when there is
 +more than one DS.
 +
  =back
  
  =head2 Plugin C<apache>
@@@ -856,165 -796,6 +856,165 @@@ and are checked by default depends on t
  
  =back
  
 +=head2 Plugin C<barometer>
 +
 +This plugin reads absolute air pressure using digital barometer sensor MPL115A2
 +or MPL3115 from Freescale (sensor attached to any I2C bus available in
 +the computer, for HW details see
 +I<http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL115A> or
 +I<http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPL3115A2>).
 +The sensor type - one fo these two - is detected automatically by the plugin
 +and indicated in the plugin_instance (typically you will see subdirectory
 +"barometer-mpl115" or "barometer-mpl3115").
 +
 +The plugin provides absolute barometric pressure, air pressure reduced to sea
 +level (several possible approximations) and as an auxiliary value also internal
 +sensor temperature. It uses (expects/provides) typical metric units - pressure
 +in [hPa], temperature in [C], altitude in [m].
 +
 +It was developed and tested under Linux only. The only platform dependency is
 +the standard Linux i2c-dev interface (the particular bus driver has to
 +support the SM Bus command subset).
 +
 +The reduction or normalization to mean sea level pressure requires (depedning on
 +selected method/approximation) also altitude and reference to temperature sensor(s).
 +When multiple temperature sensors are configured the minumum of their values is
 +always used (expecting that the warmer ones are affected by e.g. direct sun light
 +at that moment).
 +
 +Synopsis:
 +
 +  <Plugin "barometer">
 +     Device            "/dev/i2c-0";
 +     Oversampling      512
 +     PressureOffset    0.0
 +     TemperatureOffset 0.0
 +     Normalization     2
 +     Altitude          238.0
 +     TemperatureSensor "myserver/onewire-F10FCA000800/temperature"
 +  </Plugin>
 +
 +=over 4
 +
 +=item B<Device> I<device>
 +
 +Device name of the I2C bus to which the sensor is connected. Note that typically
 +you need to have loaded the i2c-dev module.
 +Using i2c-tools you can check/list i2c buses available on your system by:
 +
 +  i2cdetect -l
 +
 +Then you can scan for devices on given bus. E.g. to scan the whole bus 0 use:
 +
 +  i2cdetect -y -a 0
 +
 +This way you should be able to verify that the pressure sensor (either type) is
 +connected and detected on address 0x60.
 +
 +=item B<Oversampling> I<value>
 +
 +For MPL115 this is the size of the averaging window. To filter out sensor noise
 +a simple averaging using floating window of configurable size is used. The plugin
 +will use average of the last C<value> measurements (value of 1 means no averaging).
 +Minimal size is 1, maximal 1024.
 +
 +For MPL3115 this is the oversampling value. The actual oversampling is performed
 +by the sensor and the higher value the higher accuracy and longer conversion time
 +(although nothing to worry about in the collectd context). Supported values are:
 +1, 2, 4, 8, 16, 32, 64 and 128. Any other value is adjusted by the plugin to
 +the closest supported one. Default is 128.
 +
 +=item B<PressureOffset> I<offset>
 +
 +You can further calibrate the sensor by supplying pressure and/or temperature offsets.
 +This is added to the measured/caclulated value (i.e. if the measured value is too high
 +then use negative offset).
 +In hPa, default is 0.0.
 +
 +=item B<TemperatureOffset> I<offset>
 +
 +You can further calibrate the sensor by supplying pressure and/or temperature offsets.
 +This is added to the measured/caclulated value (i.e. if the measured value is too high
 +then use negative offset).
 +In C, default is 0.0.
 +
 +=item B<Normalization> I<method>
 +
 +Normalization method - what approximation/model is used to compute mean sea
 +level pressure from the air absolute pressure.
 +
 +Supported values of the C<method> (integer between from 0 to 2) are:
 +
 +=over 5
 +
 +=item B<0> - no conversion, absolute pressrure is simply copied over. For this method you
 +       do not need to configure C<Altitude> or C<TemperatureSensor>.
 +
 +=item B<1> - international formula for conversion ,
 +See I<http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation>.
 +For this method you have to configure C<Altitude> but do not need C<TemperatureSensor>
 +(uses fixed global temperature average instead).
 +
 +=item B<2> - formula as recommended by the Deutsche Wetterdienst (German
 +Meteorological Service).
 +See I<http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie>
 +For this method you have to configure both  C<Altitude> and C<TemperatureSensor>.
 +
 +=back
 +
 +
 +=item B<Altitude> I<altitude>
 +
 +The altitude (in meters) of the location where you meassure the pressure.
 +
 +=item B<TemperatureSensor> I<reference>
 +
 +Temperature sensor which should be used as a reference when normalizing the pressure.
 +When specified more sensors a minumum is found and uses each time.
 +The temperature reading directly from this pressure sensor/plugin
 +is typically not suitable as the pressure sensor
 +will be probably inside while we want outside temperature.
 +The collectd reference name is something like
 +<hostname>/<plugin_name>-<plugin_instance>/<type>-<type_instance>
 +(<type_instance> is usually omitted when there is just single value type).
 +Or you can figure it out from the path of the output data files.
 +
 +=back
 +
 +=head2 Plugin C<battery>
 +
 +The I<battery plugin> reports the remaining capacity, power and voltage of
 +laptop batteries.
 +
 +=over 4
 +
 +=item B<ValuesPercentage> B<false>|B<true>
 +
 +When enabled, remaining capacity is reported as a percentage, e.g. "42%
 +capacity remaining". Otherwise the capacity is stored as reported by the
 +battery, most likely in "Wh". This option does not work with all input methods,
 +in particular when only C</proc/pmu> is available on an old Linux system.
 +Defaults to B<false>.
 +
 +=item B<ReportDegraded> B<false>|B<true>
 +
 +Typical laptop batteries degrade over time, meaning the capacity decreases with
 +recharge cycles. The maximum charge of the previous charge cycle is tracked as
 +"last full capacity" and used to determine that a battery is "fully charged".
 +
 +When this option is set to B<false>, the default, the I<battery plugin> will
 +only report the remaining capacity. If the B<ValuesPercentage> option is
 +enabled, the relative remaining capacity is calculated as the ratio of the
 +"remaining capacity" and the "last full capacity". This is what most tools,
 +such as the status bar of desktop environments, also do.
 +
 +When set to B<true>, the battery plugin will report three values: B<charged>
 +(remaining capacity), B<discharged> (difference between "last full capacity"
 +and "remaining capacity") and B<degraded> (difference between "design capacity"
 +and "last full capacity").
 +
 +=back
 +
  =head2 Plugin C<bind>
  
  Starting with BIND 9.5.0, the most widely used DNS server software provides
@@@ -1169,6 -950,74 +1169,74 @@@ By default no detailed zone informatio
  
  =back
  
 -The ceph plugin collects values from JSON data to be parsed by B<libyajl> 
+ =head2 Plugin C<ceph>
 -A separate B<Daemon> block must be configured for each ceph daemon to be 
 -monitored. The following example will read daemon statistics from four 
++The ceph plugin collects values from JSON data to be parsed by B<libyajl>
+ (L<https://lloyd.github.io/yajl/>) retrieved from ceph daemon admin sockets.
 -If enabled, latency values(sum,count pairs) are calculated as the long run 
++A separate B<Daemon> block must be configured for each ceph daemon to be
++monitored. The following example will read daemon statistics from four
+ separate ceph daemons running on the same device (two OSDs, one MON, one MDS) :
+   <Plugin ceph>
+     LongRunAvgLatency false
+     ConvertSpecialMetricTypes true
+     <Daemon "osd.0">
+       SocketPath "/var/run/ceph/ceph-osd.0.asok"
+     </Daemon>
+     <Daemon "osd.1">
+       SocketPath "/var/run/ceph/ceph-osd.1.asok"
+     </Daemon>
+     <Daemon "mon.a">
+       SocketPath "/var/run/ceph/ceph-mon.ceph1.asok"
+     </Daemon>
+     <Daemon "mds.a">
+       SocketPath "/var/run/ceph/ceph-mds.ceph1.asok"
+     </Daemon>
+   </Plugin>
+ The ceph plugin accepts the following configuration options:
+ =over 4
+ =item B<LongRunAvgLatency> B<true>|B<false>
 -When disabled, latency values are calculated as the average since the last 
++If enabled, latency values(sum,count pairs) are calculated as the long run
+ average - average since the ceph daemon was started = (sum / count).
 -are converted to the type of those similar counters. This currently only 
 -applies to filestore.journal_wr_bytes which is a counter for OSD daemons. The 
++When disabled, latency values are calculated as the average since the last
+ collection = (sum_now - sum_last) / (count_now - count_last).
+ Default: Disabled
+ =item B<ConvertSpecialMetricTypes> B<true>|B<false>
+ If enabled, special metrics (metrics that differ in type from similar counters)
 -are treated as derive types. When converted, the sum is used as the counter 
++are converted to the type of those similar counters. This currently only
++applies to filestore.journal_wr_bytes which is a counter for OSD daemons. The
+ ceph schema reports this metric type as a sum,count pair while similar counters
++are treated as derive types. When converted, the sum is used as the counter
+ value and is treated as a derive type.
+ When disabled, all metrics are treated as the types received from the ceph schema.
+ Default: Enabled
+ =back
+ Each B<Daemon> block must have a string argument for the plugin instance name.
+ A B<SocketPath> is also required for each B<Daemon> block:
+ =over 4
+ =item B<Daemon> I<DaemonName>
+ Name to be used as the instance name for this daemon.
+ =item B<SocketPath> I<SocketPath>
+ Specifies the path to the UNIX admin socket of the ceph daemon.
+ =back
  =head2 Plugin C<cgroups>
  
  This plugin collects the CPU user/system time for each I<cgroup> by reading the
@@@ -1192,68 -1041,31 +1260,68 @@@ at all, B<all> cgroups are selected
  
  =back
  
 +=head2 Plugin C<conntrack>
 +
 +This plugin collects IP conntrack statistics.
 +
 +=over 4
 +
 +=item B<OldFiles>
 +
 +Assume the B<conntrack_count> and B<conntrack_max> files to be found in
 +F</proc/sys/net/ipv4/netfilter> instead of F</proc/sys/net/netfilter/>.
 +
 +=back
 +
  =head2 Plugin C<cpu>
  
 -The I<CPU plugin> collects CPU usage metrics.
 +The I<CPU plugin> collects CPU usage metrics. By default, CPU usage is reported
 +as Jiffies, using the C<cpu> type. Two aggregations are available:
 +
 +=over 4
 +
 +=item
 +
 +Sum, per-state, over all CPUs installed in the system; and
 +
 +=item
 +
 +Sum, per-CPU, over all non-idle states of a CPU, creating an "active" state.
 +
 +=back
 +
 +The two aggregations can be combined, leading to I<collectd> only emitting a
 +single "active" metric for the entire system. As soon as one of these
 +aggregations (or both) is enabled, the I<cpu plugin> will report a percentage,
 +rather than Jiffies. In addition, you can request individual, per-state,
 +per-CPU metrics to be reported as percentage.
  
  The following configuration options are available:
  
  =over 4
  
 -=item B<ReportActive> B<false>|B<true>
 +=item B<ReportByState> B<true>|B<false>
  
 -Reports non-idle CPU usage as the "active" value. Defaults to false.
 +When set to B<true>, the default, reports per-state metrics, e.g. "system",
 +"user" and "idle".
 +When set to B<false>, aggregates (sums) all I<non-idle> states into one
 +"active" metric.
  
 -=item B<ReportByCpu> B<false>|B<true>
 +=item B<ReportByCpu> B<true>|B<false>
  
 -When true reports usage for all cores. When false, reports cpu usage
 -aggregated over all cores. Implies ValuesPercentage when false.
 -Defaults to true.
 +When set to B<true>, the default, reports per-CPU (per-core) metrics.
 +When set to B<false>, instead of reporting metrics for individual CPUs, only a
 +global sum of CPU states is emitted.
  
  =item B<ValuesPercentage> B<false>|B<true>
  
 -When true report percentage usage instead of tick values. Defaults to false.
 +This option is only considered when both, B<ReportByCpu> and B<ReportByState>
 +are set to B<true>. In this case, by default, metrics will be reported as
 +Jiffies. By setting this option to B<true>, you can request percentage values
 +in the un-aggregated (per-CPU, per-state) mode as well.
  
  =back
  
 -
  =head2 Plugin C<cpufreq>
  
  This plugin doesn't have any options. It reads
@@@ -1296,16 -1108,6 +1364,16 @@@ finance page and dispatch the value to 
        URL "http://finance.google.com/finance?q=NYSE%3AAMD"
        User "foo"
        Password "bar"
 +      Digest false
 +      VerifyPeer true
 +      VerifyHost true
 +      CACert "/path/to/ca.crt"
 +      Header "X-Custom-Header: foobar"
 +      Post "foo=bar"
 +
 +      MeasureResponseTime false
 +      MeasureResponseCode false
 +
        <Match>
          Regex "<span +class=\"pr\"[^>]*> *([0-9]*\\.[0-9]+) *</span>"
          DSType "GaugeAverage"
@@@ -1378,19 -1180,13 +1446,19 @@@ C<application/x-www-form-urlencoded>)
  Measure response time for the request. If this setting is enabled, B<Match>
  blocks (see below) are optional. Disabled by default.
  
 +=item B<MeasureResponseCode> B<true>|B<false>
 +
 +Measure response code for the request. If this setting is enabled, B<Match>
 +blocks (see below) are optional. Disabled by default.
 +
  =item B<E<lt>MatchE<gt>>
  
  One or more B<Match> blocks that define how to match information in the data
  returned by C<libcurl>. The C<curl> plugin uses the same infrastructure that's
  used by the C<tail> plugin, so please see the documentation of the C<tail>
 -plugin below on how matches are defined. If the B<MeasureResponseTime> option
 -is set to B<true>, B<Match> blocks are optional.
 +plugin below on how matches are defined. If the B<MeasureResponseTime> or
 +B<MeasureResponseCode> options are set to B<true>, B<Match> blocks are
 +optional.
  
  =back
  
@@@ -1457,11 -1253,6 +1525,11 @@@ The following options are valid within 
  
  Sets the plugin instance to I<Instance>.
  
 +=item B<Interval> I<Interval>
 +
 +Sets the interval (in seconds) in which the values will be collected from this
 +URL. By default the global B<Interval> setting will be used.
 +
  =item B<User> I<Name>
  
  =item B<Password> I<Password>
@@@ -1513,8 -1304,6 +1581,8 @@@ The B<curl_xml plugin> uses B<libcurl> 
       VerifyPeer true
       VerifyHost true
       CACert "/path/to/ca.crt"
 +     Header "X-Custom-Header: foobar"
 +     Post "foo=bar"
  
       <XPath "table[@id=\"magic_level\"]/tr">
         Type "magic_level"
@@@ -1807,16 -1596,6 +1875,16 @@@ it should be able to handle integer an 
  
  There must be at least one B<ValuesFrom> option inside each B<Result> block.
  
 +=item B<MetadataFrom> [I<column0> I<column1> ...]
 +
 +Names the columns whose content is used as metadata for the data sets
 +that are dispatched to the daemon.
 +
 +The actual data type in the columns is not that important. The plugin will
 +automatically cast the values to the right type if it know how to do that. So
 +it should be able to handle integer an floating point types, as well as strings
 +(if they include a number at the beginning).
 +
  =back
  
  =head3 B<Database> blocks
@@@ -1977,20 -1756,6 +2045,20 @@@ collected. If at least one B<Disk> opti
  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.
  
 +=item B<UseBSDName> B<true>|B<false>
 +
 +Whether to use the device's "BSD Name", on MacE<nbsp>OSE<nbsp>X, instead of the
 +default major/minor numbers. Requires collectd to be built with Apple's
 +IOKitLib support.
 +
 +=item B<UdevNameAttr> I<Attribute>
 +
 +Attempt to override disk instance name with the value of a specified udev
 +attribute when built with B<libudev>.  If the attribute is not defined for the
 +given device, the default name is used. Example:
 +
 +  UdevNameAttr "DM_NAME"
 +
  =back
  
  =head2 Plugin C<dns>
@@@ -2454,7 -2219,94 +2522,7 @@@ independent from the I<JavaClass> argum
  
  =back
  
 -=head2 Plugin C<libvirt>
 -
 -This plugin allows CPU, disk and network load to be collected for virtualized
 -guests on the machine. This means that these characteristics can be collected
 -for guest systems without installing any software on them - collectd only runs
 -on the hosting system. The statistics are collected through libvirt
 -(L<http://libvirt.org/>).
 -
 -Only I<Connection> is required.
 -
 -=over 4
 -
 -=item B<Connection> I<uri>
 -
 -Connect to the hypervisor given by I<uri>. For example if using Xen use:
 -
 - Connection "xen:///"
 -
 -Details which URIs allowed are given at L<http://libvirt.org/uri.html>.
 -
 -=item B<RefreshInterval> I<seconds>
 -
 -Refresh the list of domains and devices every I<seconds>. The default is 60
 -seconds. Setting this to be the same or smaller than the I<Interval> will cause
 -the list of domains and devices to be refreshed on every iteration.
 -
 -Refreshing the devices in particular is quite a costly operation, so if your
 -virtualization setup is static you might consider increasing this. If this
 -option is set to 0, refreshing is disabled completely.
 -
 -=item B<Domain> I<name>
 -
 -=item B<BlockDevice> I<name:dev>
 -
 -=item B<InterfaceDevice> I<name:dev>
 -
 -=item B<IgnoreSelected> I<true>|I<false>
 -
 -Select which domains and devices are collected.
 -
 -If I<IgnoreSelected> is not given or I<false> then only the listed domains and
 -disk/network devices are collected.
 -
 -If I<IgnoreSelected> is I<true> then the test is reversed and the listed
 -domains and disk/network devices are ignored, while the rest are collected.
 -
 -The domain name and device names may use a regular expression, if the name is
 -surrounded by I</.../> and collectd was compiled with support for regexps.
 -
 -The default is to collect statistics for all domains and all their devices.
 -
 -Example:
 -
 - BlockDevice "/:hdb/"
 - IgnoreSelected "true"
 -
 -Ignore all I<hdb> devices on any domain, but other block devices (eg. I<hda>)
 -will be collected.
 -
 -=item B<HostnameFormat> B<name|uuid|hostname|...>
 -
 -When the libvirt 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>.
 -
 -B<uuid> means use the guest's UUID. This is useful if you want to track the
 -same guest across migrations.
 -
 -B<hostname> means to use the global B<Hostname> setting, which is probably not
 -useful on its own because all guests will appear to have the same name.
 -
 -You can also specify combinations of these fields. For example B<name uuid>
 -means to concatenate the guest name and UUID (with a literal colon character
 -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
 -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>.
 -
 -B<address> means use the interface's mac address. This is useful since the
 -interface path might change between reboots of a guest or across migrations.
 -
 -=back
 -
 -+=head2 Plugin C<load>
 +=head2 Plugin C<load>
  
  The I<Load plugin> collects the system load. These numbers give a rough overview
  over the utilization of a machine. The system load is defined as the number of
@@@ -2507,34 -2359,6 +2575,34 @@@ B<Note>: There is no need to notify th
  log file (e.E<nbsp>g. when rotating the logs). The plugin reopens the file
  for each line it writes.
  
 +=head2 Plugin C<log_logstash>
 +
 +The I<log logstash plugin> behaves like the logfile plugin but formats
 +messages as JSON events for logstash to parse and input.
 +
 +=over 4
 +
 +=item B<LogLevel> B<debug|info|notice|warning|err>
 +
 +Sets the log-level. If, for example, set to B<notice>, then all events with
 +severity B<notice>, B<warning>, or B<err> will be written to the logfile.
 +
 +Please note that B<debug> is only available if collectd has been compiled with
 +debugging support.
 +
 +=item B<File> I<File>
 +
 +Sets the file to write log messages to. The special strings B<stdout> and
 +B<stderr> can be used to write to the standard output and standard error
 +channels, respectively. This, of course, only makes much sense when I<collectd>
 +is running in foreground- or non-daemon-mode.
 +
 +=back
 +
 +B<Note>: There is no need to notify the daemon after moving or removing the
 +log file (e.E<nbsp>g. when rotating the logs). The plugin reopens the file
 +for each line it writes.
 +
  =head2 Plugin C<lpar>
  
  The I<LPAR plugin> reads CPU statistics of I<Logical Partitions>, a
@@@ -2726,7 -2550,7 +2794,7 @@@ The following options are valid inside 
  
  =item B<ShowCPU> B<true>|B<false>
  
 -If enabled (the default) a sum of the CPU usage accross all cores is reported.
 +If enabled (the default) a sum of the CPU usage across all cores is reported.
  
  =item B<ShowCPUCores> B<true>|B<false>
  
@@@ -2880,8 -2704,8 +2948,8 @@@ which the sizes of physical memory vary
  
  =head2 Plugin C<modbus>
  
 -The B<modbus plugin> connects to a Modbus "slave" via Modbus/TCP and reads
 -register values. It supports reading single registers (unsigned 16E<nbsp>bit
 +The B<modbus plugin> connects to a Modbus "slave" via Modbus/TCP or Modbus/RTU and
 +reads register values. It supports reading single registers (unsigned 16E<nbsp>bit
  values), large integer values (unsigned 32E<nbsp>bit values) and floating point
  values (two registers interpreted as IEEE floats in big endian notation).
  
@@@ -2890,7 -2714,6 +2958,7 @@@ B<Synopsis:
   <Data "voltage-input-1">
     RegisterBase 0
     RegisterType float
 +   RegisterCmd ReadHolding
     Type voltage
     Instance "input-1"
   </Data>
   <Data "voltage-input-2">
     RegisterBase 2
     RegisterType float
 +   RegisterCmd ReadHolding
     Type voltage
     Instance "input-2"
   </Data>
  
 + <Data "supply-temperature-1">
 +   RegisterBase 0
 +   RegisterType Int16
 +   RegisterCmd ReadHolding
 +   Type temperature
 +   Instance "temp-1"
 + </Data>
 +
   <Host "modbus.example.com">
     Address "192.168.0.42"
     Port    "502"
     </Slave>
   </Host>
  
 + <Host "localhost">
 +   Device "/dev/ttyUSB0"
 +   Baudrate 38400
 +   Interval 20
 +
 +   <Slave 1>
 +     Instance "temperature"
 +     Collect  "supply-temperature-1"
 +   </Slave>
 + </Host>
 +
  =over 4
  
  =item E<lt>B<Data> I<Name>E<gt> blocks
@@@ -2957,11 -2760,6 +3025,11 @@@ Specifies what kind of data is returne
  B<Uint32> or B<Float>, two 16E<nbsp>bit registers will be read and the data is
  combined into one value. Defaults to B<Uint16>.
  
 +=item B<RegisterCmd> B<ReadHolding>|B<ReadInput>
 +
 +Specifies register type to be collected from device. Works only with libmodbus
 +2.9.2 or higher. Defaults to B<ReadHolding>.
 +
  =item B<Type> I<Type>
  
  Specifies the "type" (data set) to use when dispatching the value to
@@@ -2987,25 -2785,15 +3055,25 @@@ Within E<lt>HostE<nbsp>/E<gt> blocks, t
  
  =item B<Address> I<Hostname>
  
 -Specifies the node name (the actual network address) used to connect to the
 -host. This may be an IP address or a hostname. Please note that the used
 -I<libmodbus> library only supports IPv4 at the moment.
 +For Modbus/TCP, specifies the node name (the actual network address) used to
 +connect to the host. This may be an IP address or a hostname. Please note that
 +the used I<libmodbus> library only supports IPv4 at the moment.
  
  =item B<Port> I<Service>
  
 -Specifies the port used to connect to the host. The port can either be given as
 -a number or as a service name. Please note that the I<Service> argument must be
 -a string, even if ports are given in their numerical form. Defaults to "502".
 +for Modbus/TCP, specifies the port used to connect to the host. The port can
 +either be given as a number or as a service name. Please note that the
 +I<Service> argument must be a string, even if ports are given in their numerical
 +form. Defaults to "502".
 +
 +=item B<Device> I<Devicenode>
 +
 +For Modbus/RTU, specifies the path to the serial device being used.
 +
 +=item B<Baudrate> I<Baudrate>
 +
 +For Modbus/RTU, specifies the baud rate of the serial device.
 +Note, connections currently support only 8/N/1.
  
  =item B<Interval> I<Interval>
  
@@@ -3014,7 -2802,7 +3082,7 @@@ host. By default the global B<Interval
  
  =item E<lt>B<Slave> I<ID>E<gt>
  
 -Over each TCP connection, multiple Modbus devices may be reached. The slave ID
 +Over each connection, multiple Modbus devices may be reached. The slave ID
  is used to specify which device should be addressed. For each device you want
  to query, one B<Slave> block must be given.
  
@@@ -3072,11 -2860,9 +3140,11 @@@ Synopsis
        Password "password"
        Port "3306"
        MasterStats true
 +      ConnectTimeout 10
      </Database>
  
      <Database bar>
 +      Alias "squeeze"
        Host "localhost"
        Socket "/var/run/mysql/mysqld.sock"
        SlaveStats true
@@@ -3091,11 -2877,6 +3159,11 @@@ section "mysql_real_connect()" in the B
  
  =over 4
  
 +=item B<Alias> I<Alias>
 +
 +Alias to use as sender instead of hostname when reporting. This may be useful
 +when having cryptic hostnames.
 +
  =item B<Host> I<Hostname>
  
  Hostname of the database server. Defaults to B<localhost>.
@@@ -3134,27 -2915,18 +3202,27 @@@ only has any effect, if B<Host> is set 
  Otherwise, use the B<Port> option above. See the documentation for the
  C<mysql_real_connect> function for details.
  
 +=item B<InnodbStats> I<true|false>
 +
 +If enabled, metrics about the InnoDB storage engine are collected.
 +Disabled by default.
 +
  =item B<MasterStats> I<true|false>
  
  =item B<SlaveStats> I<true|false>
  
  Enable the collection of master / slave statistics in a replication setup. In
  order to be able to get access to these statistics, the user needs special
 -privileges. See the B<User> documentation above.
 +privileges. See the B<User> documentation above. Defaults to B<false>.
  
  =item B<SlaveNotifications> I<true|false>
  
  If enabled, the plugin sends a notification if the replication slave I/O and /
 -or SQL threads are not running.
 +or SQL threads are not running. Defaults to B<false>.
 +
 +=item B<ConnectTimeout> I<Seconds>
 +
 +Sets the connect timeout for the MySQL client.
  
  =back
  
@@@ -3855,12 -3627,6 +3923,12 @@@ behavior is to let the kernel choose th
  that the manual selection of an interface for unicast traffic is only
  necessary in rare cases.
  
 +=item B<ResolveInterval> I<Seconds>
 +
 +Sets the interval at which to re-resolve the DNS for the I<Host>. This is
 +useful to force a regular DNS lookup to support a high availability setup. If
 +not specified, re-resolves are never attempted.
 +
  =back
  
  =item B<E<lt>Listen> I<Host> [I<Port>]B<E<gt>>
@@@ -4187,36 -3953,13 +4255,36 @@@ B<EXPERIMENTAL!> See notes below
  The C<onewire> plugin uses the B<owcapi> library from the B<owfs> project
  L<http://owfs.org/> to read sensors connected via the onewire bus.
  
 -Currently only temperature sensors (sensors with the family code C<10>,
 -e.E<nbsp>g. DS1820, DS18S20, DS1920) can be read. If you have other sensors you
 -would like to have included, please send a sort request to the mailing list.
 +It can be used in two possible modes - standard or advanced.
 +
 +In the standard mode only temperature sensors (sensors with the family code
 +C<10>, C<22> and C<28> - e.g. DS1820, DS18S20, DS1920) can be read. If you have
 +other sensors you would like to have included, please send a sort request to
 +the mailing list. You can select sensors to be read or to be ignored depending
 +on the option B<IgnoreSelected>). When no list is provided the whole bus is
 +walked and all sensors are read.
  
  Hubs (the DS2409 chips) are working, but read the note, why this plugin is
  experimental, below.
  
 +In the advanced mode you can configure any sensor to be read (only numerical
 +value) using full OWFS path (e.g. "/uncached/10.F10FCA000800/temperature").
 +In this mode you have to list all the sensors. Neither default bus walk nor
 +B<IgnoreSelected> are used here. Address and type (file) is extracted from
 +the path automatically and should produce compatible structure with the "standard"
 +mode (basically the path is expected as for example
 +"/uncached/10.F10FCA000800/temperature" where it would extract address part
 +"F10FCA000800" and the rest after the slash is considered the type - here
 +"temperature").
 +There are two advantages to this mode - you can access virtually any sensor
 +(not just temperature), select whether to use cached or directly read values
 +and it is slighlty faster. The downside is more complex configuration.
 +
 +The two modes are distinguished automatically by the format of the address.
 +It is not possible to mix the two modes. Once a full path is detected in any
 +B<Sensor> then the whole addressing (all sensors) is considered to be this way
 +(and as standard addresses will fail parsing they will be ignored).
 +
  =over 4
  
  =item B<Device> I<Device>
@@@ -4237,23 -3980,14 +4305,23 @@@ This directive is B<required> and does 
  
  =item B<Sensor> I<Sensor>
  
 -Selects sensors to collect or to ignore, depending on B<IgnoreSelected>, see
 -below. Sensors are specified without the family byte at the beginning, to you'd
 -use C<F10FCA000800>, and B<not> include the leading C<10.> family byte and
 -point.
 +In the standard mode selects sensors to collect or to ignore
 +(depending on B<IgnoreSelected>, see below). Sensors are specified without
 +the family byte at the beginning, so you have to use for example C<F10FCA000800>,
 +and B<not> include the leading C<10.> family byte and point.
 +When no B<Sensor> is configured the whole Onewire bus is walked and all supported
 +sensors (see above) are read.
 +
 +In the advanced mode the B<Sensor> specifies full OWFS path - e.g.
 +C</uncached/10.F10FCA000800/temperature> (or when cached values are OK
 +C</10.F10FCA000800/temperature>). B<IgnoreSelected> is not used.
 +
 +As there can be multiple devices on the bus you can list multiple sensor (use
 +multiple B<Sensor> elements).
  
  =item B<IgnoreSelected> I<true>|I<false>
  
 -If no configuration if given, the B<onewire> plugin will collect data from all
 +If no configuration is given, the B<onewire> plugin will collect data from all
  sensors found. This may not be practical, especially if sensors are added and
  removed regularly. Sometimes, however, it's easier/preferred to collect only
  specific sensors or all sensors I<except> a few specified ones. This option
@@@ -4261,8 -3995,6 +4329,8 @@@ enables you to do that: By setting B<Ig
  B<Sensor> is inverted: All selected interfaces are ignored and all other
  interfaces are collected.
  
 +Used only in the standard mode - see above.
 +
  =item B<Interval> I<Seconds>
  
  Sets the interval in which all sensors should be read. If not specified, the
@@@ -4281,77 -4013,13 +4349,77 @@@ short: If it works for you: Great! But 
  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<openvpn>
 +=head2 Plugin C<openldap>
  
 -The OpenVPN plugin reads a status file maintained by OpenVPN and gathers
 -traffic statistics about connected clients.
 +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.
  
 -To set up OpenVPN to write to the status file periodically, use the
 -B<--status> option of OpenVPN. Since OpenVPN can write two different formats,
 +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
 +traffic statistics about connected clients.
 +
 +To set up OpenVPN to write to the status file periodically, use the
 +B<--status> option of OpenVPN. Since OpenVPN can write two different formats,
  you need to set the required format, too. This is done by setting
  B<--status-version> to B<2>.
  
@@@ -4998,15 -4666,18 +5066,15 @@@ Specify the username to be used when co
  
  Specify the password to be used when connecting to the server.
  
 +=item B<ExpireDelay> I<delay>
 +
 +Skip expired values in query output.
 +
  =item B<SSLMode> I<disable>|I<allow>|I<prefer>|I<require>
  
  Specify whether to use an SSL connection when contacting the server. The
  following modes are supported:
  
 -=item B<Instance> I<name>
 -
 -Specify the plugin instance name that should be used instead of the database
 -name (which is the default, if this option has not been specified). This
 -allows to query multiple databases of the same name on the same host (e.g.
 -when running multiple database server versions in parallel).
 -
  =over 4
  
  =item I<disable>
@@@ -5027,13 -4698,6 +5095,13 @@@ Use SSL only
  
  =back
  
 +=item B<Instance> I<name>
 +
 +Specify the plugin instance name that should be used instead of the database
 +name (which is the default, if this option has not been specified). This
 +allows to query multiple databases of the same name on the same host (e.g.
 +when running multiple database server versions in parallel).
 +
  =item B<KRBSrvName> I<kerberos_service_name>
  
  Specify the Kerberos service name to use when authenticating with Kerberos 5
@@@ -5373,10 -5037,6 +5441,10 @@@ which configures the connection paramet
          Host "localhost"
          Port "6379"
          Timeout 2000
 +        <Query "LLEN myqueue">
 +          Type "queue_length"
 +          Instance "myqueue"
 +        <Query>
      </Node>
    </Plugin>
  
@@@ -5414,22 -5074,6 +5482,22 @@@ read function is blocking, you should k
  in mind that the sum of all B<Timeout> values for all B<Nodes> should be lower
  than B<Interval> defined globally.
  
 +=item B<Query> I<Querystring>
 +
 +The B<Query> block identifies a query to execute against the redis server.
 +There may be an arbitrary number of queries to execute.
 +
 +=item B<Type> I<Collectd type>
 +
 +Within a query definition, a valid collectd type to use as when submitting
 +the result of the query. When not supplied, will default to B<gauge>.
 +
 +=item B<Instance> I<Type instance>
 +
 +Within a query definition, an optional type instance to use when submitting
 +the result of the query. When not supplied will default to the escaped
 +command, up to 64 chars.
 +
  =back
  
  =head2 Plugin C<rrdcached>
@@@ -5534,14 -5178,6 +5602,14 @@@ Set the "XFiles Factor". The default i
  I<Factor> must be in the range C<[0.0-1.0)>, i.e. between zero (inclusive) and
  one (exclusive).
  
 +=item B<CollectStatistics> B<false>|B<true>
 +
 +When set to B<true>, various statistics about the I<rrdcached> daemon will be
 +collected, with "rrdcached" as the I<plugin name>. Defaults to B<false>.
 +
 +Statistics are read via I<rrdcached>s socket using the STATS command.
 +See L<rrdcached(1)> for details.
 +
  =back
  
  =head2 Plugin C<rrdtool>
@@@ -5771,40 -5407,6 +5839,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
@@@ -5856,20 -5458,7 +5924,20 @@@ that I<Percent> of all reported timers 
  computed latency. This is useful for cutting off the long tail latency, as it's
  often done in I<Service Level Agreements> (SLAs).
  
 -If not specified, no percentile is calculated / dispatched.
 +Different percentiles can be calculated by setting this option several times.
 +If none are specified, no percentiles are calculated / dispatched.
 +
 +=item B<TimerLower> B<false>|B<true>
 +
 +=item B<TimerUpper> B<false>|B<true>
 +
 +=item B<TimerSum> B<false>|B<true>
 +
 +=item B<TimerCount> B<false>|B<true>
 +
 +Calculate and dispatch various values out of I<Timer> metrics received during
 +an interval. If set to B<False>, the default, these values aren't calculated /
 +dispatched.
  
  =back
  
@@@ -6128,8 -5717,6 +6196,8 @@@ Use the last number found
  The matched number is a counter. Simply I<sets> the internal counter to this
  value. Variants exist for C<COUNTER>, C<DERIVE>, and C<ABSOLUTE> data sources.
  
 +=item B<GaugeAdd>
 +
  =item B<CounterAdd>
  
  =item B<DeriveAdd>
@@@ -6138,8 -5725,6 +6206,8 @@@ Add the matched value to the internal c
  matched number may be negative, which will effectively subtract from the
  internal counter.
  
 +=item B<GaugeInc>
 +
  =item B<CounterInc>
  
  =item B<DeriveInc>
@@@ -6359,11 -5944,6 +6427,11 @@@ connections a mail server or news serve
  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>
@@@ -6493,35 -6073,22 +6561,35 @@@ Take the UUID from the given file (defa
  =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>
@@@ -6535,24 -6102,29 +6603,24 @@@ Inside each E<lt>B<Instance>E<gt> block
  
  =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>
  
@@@ -6586,14 -6158,7 +6654,14 @@@ number of objects tested against purge 
  =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>
  
@@@ -6624,118 -6189,18 +6692,118 @@@ the number of requests and bytes transf
  
  =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.
  
  =back
  
 +=head2 Plugin C<virt>
 +
 +This plugin allows CPU, disk and network load to be collected for virtualized
 +guests on the machine. This means that these metrics can be collected for guest
 +systems without installing any software on them - I<collectd> only runs on the
 +host system. The statistics are collected through libvirt
 +(L<http://libvirt.org/>).
 +
 +Only I<Connection> is required.
 +
 +=over 4
 +
 +=item B<Connection> I<uri>
 +
 +Connect to the hypervisor given by I<uri>. For example if using Xen use:
 +
 + Connection "xen:///"
 +
 +Details which URIs allowed are given at L<http://libvirt.org/uri.html>.
 +
 +=item B<RefreshInterval> I<seconds>
 +
 +Refresh the list of domains and devices every I<seconds>. The default is 60
 +seconds. Setting this to be the same or smaller than the I<Interval> will cause
 +the list of domains and devices to be refreshed on every iteration.
 +
 +Refreshing the devices in particular is quite a costly operation, so if your
 +virtualization setup is static you might consider increasing this. If this
 +option is set to 0, refreshing is disabled completely.
 +
 +=item B<Domain> I<name>
 +
 +=item B<BlockDevice> I<name:dev>
 +
 +=item B<InterfaceDevice> I<name:dev>
 +
 +=item B<IgnoreSelected> B<true>|B<false>
 +
 +Select which domains and devices are collected.
 +
 +If I<IgnoreSelected> is not given or B<false> then only the listed domains and
 +disk/network devices are collected.
 +
 +If I<IgnoreSelected> is B<true> then the test is reversed and the listed
 +domains and disk/network devices are ignored, while the rest are collected.
 +
 +The domain name and device names may use a regular expression, if the name is
 +surrounded by I</.../> and collectd was compiled with support for regexps.
 +
 +The default is to collect statistics for all domains and all their devices.
 +
 +Example:
 +
 + BlockDevice "/:hdb/"
 + IgnoreSelected "true"
 +
 +Ignore all I<hdb> devices on any domain, but other block devices (eg. I<hda>)
 +will be collected.
 +
 +=item B<HostnameFormat> B<name|uuid|hostname|...>
 +
 +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>.
 +
 +B<uuid> means use the guest's UUID. This is useful if you want to track the
 +same guest across migrations.
 +
 +B<hostname> means to use the global B<Hostname> setting, which is probably not
 +useful on its own because all guests will appear to have the same name.
 +
 +You can also specify combinations of these fields. For example B<name uuid>
 +means to concatenate the guest name and UUID (with a literal colon character
 +between, thus I<"foo:1234-1234-1234-1234">).
 +
 +=item B<InterfaceFormat> B<name>|B<address>
 +
 +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>.
 +
 +B<address> means use the interface's mac address. This is useful since the
 +interface path might change between reboots of a guest or across migrations.
 +
 +=item B<PluginInstanceFormat> B<name|uuid>
 +
 +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>.
 +
 +B<uuid> means use the guest's UUID.
 +
 +=back
 +
  =head2 Plugin C<vmem>
  
  The C<vmem> plugin collects information about the usage of virtual memory.
@@@ -6846,59 -6311,6 +6914,59 @@@ instance) are put into one component, f
  
  =item B<AlwaysAppendDS> B<false>|B<true>
  
 +If set to B<true>, append the name of the I<Data Source> (DS) to the "metric"
 +identifier. If set to B<false> (the default), this is only done when there is
 +more than one DS.
 +
 +=back
 +
 +=head2 Plugin C<write_tsdb>
 +
 +The C<write_tsdb> plugin writes data to I<OpenTSDB>, a scalable open-source
 +time series database. The plugin connects to a I<TSD>, a masterless, no shared
 +state daemon that ingests metrics and stores them in HBase. The plugin uses
 +I<TCP> over the "line based" protocol with a default port 4242. The data will
 +be sent in blocks of at most 1428 bytes to minimize the number of network
 +packets.
 +
 +Synopsis:
 +
 + <Plugin write_tsdb>
 +   <Node "example">
 +     Host "tsd-1.my.domain"
 +     Port "4242"
 +     HostTags "status=production"
 +   </Node>
 + </Plugin>
 +
 +The configuration consists of one or more E<lt>B<Node>E<nbsp>I<Name>E<gt>
 +blocks. Inside the B<Node> blocks, the following options are recognized:
 +
 +=over 4
 +
 +=item B<Host> I<Address>
 +
 +Hostname or address to connect to. Defaults to C<localhost>.
 +
 +=item B<Port> I<Service>
 +
 +Service name or port number to connect to. Defaults to C<4242>.
 +
 +
 +=item B<HostTags> I<String>
 +
 +When set, I<HostTags> is added to the end of the metric. It is intended to be
 +used for name=value pairs that the TSD will tag the metric with. Dots and
 +whitespace are I<not> escaped in this string.
 +
 +=item B<StoreRates> B<false>|B<true>
 +
 +If set to B<true>, convert counter values to rates. If set to B<false>
 +(the default) counter values are stored as is, as an increasing
 +integer number.
 +
 +=item B<AlwaysAppendDS> B<false>|B<true>
 +
  If set the B<true>, append the name of the I<Data Source> (DS) to the "metric"
  identifier. If set to B<false> (the default), this is only done when there is
  more than one DS.
@@@ -6960,31 -6372,25 +7028,31 @@@ want to use authentication all three fi
  
  =head2 Plugin C<write_http>
  
 -This output plugin submits values to an http server by POST them using the
 -PUTVAL plain-text protocol. Each destination you want to post data to needs to
 -have one B<URL> block, within which the destination can be configured further,
 -for example by specifying authentication data.
 +This output plugin submits values to an HTTP server using POST requests and
 +encoding metrics with JSON or using the C<PUTVAL> command described in
 +L<collectd-unixsock(5)>.
  
  Synopsis:
  
   <Plugin "write_http">
 -   <URL "http://example.com/post-collectd">
 +   <Node "example">
 +     URL "http://example.com/post-collectd"
       User "collectd"
       Password "weCh3ik0"
 -   </URL>
 +     Format JSON
 +   </Node>
   </Plugin>
  
 -B<URL> blocks need one string argument which is used as the URL to which data
 -is posted. The following options are understood within B<URL> blocks.
 +The plugin can send values to multiple HTTP servers by specifying one
 +E<lt>B<Node>E<nbsp>I<Name>E<gt> block for each server. Within each B<Node>
 +block, the following options are available:
  
  =over 4
  
 +=item B<URL> I<URL>
 +
 +URL to which the values are submitted to. Mandatory.
 +
  =item B<User> I<Username>
  
  Optional user name needed for authentication.
@@@ -7012,33 -6418,6 +7080,33 @@@ File that holds one or more SSL certifi
  possibly need this option. What CA certificates come bundled with C<libcurl>
  and are checked by default depends on the distribution you use.
  
 +=item B<CAPath> I<Directory>
 +
 +Directory holding one or more CA certificate files. You can use this if for
 +some reason all the needed CA certificates aren't in the same file and can't be
 +pointed to using the B<CACert> option. Requires C<libcurl> to be built against
 +OpenSSL.
 +
 +=item B<ClientKey> I<File>
 +
 +File that holds the private key in PEM format to be used for certificate-based
 +authentication.
 +
 +=item B<ClientCert> I<File>
 +
 +File that holds the SSL certificate to be used for certificate-based
 +authentication.
 +
 +=item B<ClientKeyPass> I<Password>
 +
 +Password required to load the private key in B<ClientKey>.
 +
 +=item B<SSLVersion> B<SSLv2>|B<SSLv3>|B<TLSv1>|B<TLSv1_0>|B<TLSv1_1>|B<TLSv1_2>
 +
 +Define which SSL protocol version must be used. By default C<libcurl> will
 +attempt to figure out the remote SSL protocol version. See
 +L<curl_easy_setopt(3)> for more details.
 +
  =item B<Format> B<Command>|B<JSON>
  
  Format of the output to generate. If set to B<Command>, will create output that
@@@ -7050,184 -6429,14 +7118,184 @@@ Defaults to B<Command>
  =item B<StoreRates> B<true|false>
  
  If set to B<true>, convert counter values to rates. If set to B<false> (the
 -default) counter values are stored as is, i.E<nbsp>e. as an increasing integer
 -number.
 +default) counter values are stored as is, i.e. as an increasing integer number.
 +
 +=item B<BufferSize> I<Bytes>
 +
 +Sets the send buffer size to I<Bytes>. By increasing this buffer, less HTTP
 +requests will be generated, but more metrics will be batched / metrics are
 +cached for longer before being sent, introducing additional delay until they
 +are available on the server side. I<Bytes> must be at least 1024 and cannot
 +exceed the size of an C<int>, i.e. 2E<nbsp>GByte.
 +Defaults to C<4096>.
 +
 +=back
 +
 +=head2 Plugin C<write_kafka>
 +
 +The I<write_kafka plugin> will send values to a I<Kafka> topic, a distributed
 +queue.
 +Synopsis:
 +
 + <Plugin "write_kafka">
 +   Property "metadata.broker.list" "broker1:9092,broker2:9092"
 +   <Topic "collectd">
 +     Format JSON
 +   </Topic>
 + </Plugin>
 +
 +The following options are understood by the I<write_kafka plugin>:
 +
 +=over 4
 +
 +=item E<lt>B<Topic> I<Name>E<gt>
 +
 +The plugin's configuration consists of one or more B<Topic> blocks. Each block
 +is given a unique I<Name> and specifies one kafka producer.
 +Inside the B<Topic> block, the following per-topic options are
 +understood:
 +
 +=over 4
 +
 +=item B<Property> I<String> I<String>
 +
 +Configure the named property for the current topic. Properties are
 +forwarded to the kafka producer library B<librdkafka>.
 +
 +=item B<Key> I<String>
 +
 +Use the specified string as a partioning key for the topic. Kafka breaks
 +topic into partitions and guarantees that for a given topology, the same
 +consumer will be used for a specific key. The special (case insensitive)
 +string B<Random> can be used to specify that an arbitrary partition should
 +be used.
 +
 +=item B<Format> B<Command>|B<JSON>|B<Graphite>
 +
 +Selects the format in which messages are sent to the broker. If set to
 +B<Command> (the default), values are sent as C<PUTVAL> commands which are
 +identical to the syntax used by the I<Exec> and I<UnixSock plugins>.
 +
 +If set to B<JSON>, the values are encoded in the I<JavaScript Object Notation>,
 +an easy and straight forward exchange format.
 +
 +If set to B<Graphite>, values are encoded in the I<Graphite> format, which is
 +C<E<lt>metricE<gt> E<lt>valueE<gt> E<lt>timestampE<gt>\n>.
 +
 +=item B<StoreRates> B<true>|B<false>
 +
 +Determines whether or not C<COUNTER>, C<DERIVE> and C<ABSOLUTE> data sources
 +are converted to a I<rate> (i.e. a C<GAUGE> value). If set to B<false> (the
 +default), no conversion is performed. Otherwise the conversion is performed
 +using the internal value cache.
 +
 +Please note that currently this option is only used if the B<Format> option has
 +been set to B<JSON>.
 +
 +=item B<GraphitePrefix> (B<Format>=I<Graphite> only)
 +
 +A prefix can be added in the metric name when outputting in the I<Graphite>
 +format. It's added before the I<Host> name.
 +Metric name will be
 +C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
 +
 +=item B<GraphitePostfix> (B<Format>=I<Graphite> only)
 +
 +A postfix can be added in the metric name when outputting in the I<Graphite>
 +format. It's added after the I<Host> name.
 +Metric name will be
 +C<E<lt>prefixE<gt>E<lt>hostE<gt>E<lt>postfixE<gt>E<lt>pluginE<gt>E<lt>typeE<gt>E<lt>nameE<gt>>
 +
 +=item B<GraphiteEscapeChar> (B<Format>=I<Graphite> only)
 +
 +Specify a character to replace dots (.) in the host part of the metric name.
 +In I<Graphite> metric name, dots are used as separators between different
 +metric parts (host, plugin, type).
 +Default is C<_> (I<Underscore>).
 +
 +=item B<GraphiteSeparateInstances> B<false>|B<true>
 +
 +If set to B<true>, the plugin instance and type instance will be in their own
 +path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
 +default), the plugin and plugin instance (and likewise the type and type
 +instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
 +
 +=item B<StoreRates> B<true>|B<false>
 +
 +If set to B<true> (the default), convert counter values to rates. If set to
 +B<false> counter values are stored as is, i.e. as an increasing integer number.
 +
 +This will be reflected in the C<ds_type> tag: If B<StoreRates> is enabled,
 +converted values will have "rate" appended to the data source type, e.g.
 +C<ds_type:derive:rate>.
 +
 +=back
 +
 +=item B<Property> I<String> I<String>
 +
 +Configure the kafka producer through properties, you almost always will
 +want to set B<metadata.broker.list> to your Kafka broker list.
 +
 +=back
 +
 +=head2 Plugin C<write_redis>
 +
 +The I<write_redis plugin> submits values to I<Redis>, a data structure server.
 +
 +Synopsis:
 +
 +  <Plugin "write_redis">
 +    <Node "example">
 +        Host "localhost"
 +        Port "6379"
 +        Timeout 1000
 +    </Node>
 +  </Plugin>
 +
 +Values are submitted to I<Sorted Sets>, using the metric name as the key, and
 +the timestamp as the score. Retrieving a date range can then be done using the
 +C<ZRANGEBYSCORE> I<Redis> command. Additionnally, all the identifiers of these
 +I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
 +retrieved using the C<SMEMBERS> I<Redis> command. See
 +L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
 +details.
 +
 +The information shown in the synopsis above is the I<default configuration>
 +which is used by the plugin if no configuration is present.
 +
 +The plugin can send values to multiple instances of I<Redis> by specifying
 +one B<Node> block for each instance. Within the B<Node> blocks, the following
 +options are available:
 +
 +=over 4
 +
 +=item B<Node> I<Nodename>
 +
 +The B<Node> block identifies a new I<Redis> node, that is a new I<Redis>
 +instance running in an specified host and port. The name for node is a
 +canonical identifier which is used as I<plugin instance>. It is limited to
 +64E<nbsp>characters in length.
 +
 +=item B<Host> I<Hostname>
 +
 +The B<Host> option is the hostname or IP-address where the I<Redis> instance is
 +running on.
 +
 +=item B<Port> I<Port>
 +
 +The B<Port> option is the TCP port on which the Redis instance accepts
 +connections. Either a service name of a port number may be given. Please note
 +that numerical port numbers must be given as a string, too.
 +
 +=item B<Timeout> I<Timeout in miliseconds>
 +
 +The B<Timeout> option sets the socket connection timeout, in milliseconds.
  
  =back
  
  =head2 Plugin C<write_riemann>
  
 -The I<write_riemann plugin> will send values to I<Riemann>, a powerfull stream
 +The I<write_riemann plugin> will send values to I<Riemann>, a powerful stream
  aggregation and monitoring system. The plugin sends I<Protobuf> encoded data to
  I<Riemann> using UDP packets.
  
@@@ -7270,26 -6479,7 +7338,26 @@@ Service name or port number to connect 
  =item B<Protocol> B<UDP>|B<TCP>
  
  Specify the protocol to use when communicating with I<Riemann>. Defaults to
 -B<UDP>.
 +B<TCP>.
 +
 +=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.
 +
 +When enabled, it can occur that events get processed by the Riemann server
 +close to or after their expiration time. Tune the B<TTLFactor> and
 +B<BatchMaxSize> settings according to the amount of values collected, if this
 +is an issue.
 +
 +Defaults to true
 +
 +=item B<BatchMaxSize> I<size>
 +
 +Maximum payload size for a riemann packet. Defaults to 8192
  
  =item B<StoreRates> B<true>|B<false>
  
@@@ -7316,23 -6506,6 +7384,23 @@@ interval is multiplied to set the TTL. 
  know exactly what you're doing, you should only increase this setting from its
  default value.
  
 +=item B<Notifications> B<false>|B<true>
 +
 +If set to B<true>, create riemann events for notifications. This is B<true>
 +by default. When processing thresholds from write_riemann, it might prove
 +useful to avoid getting notification events.
 +
 +=item B<CheckThresholds> B<false>|B<true>
 +
 +If set to B<true>, attach state to events based on thresholds defined
 +in the B<Threshold> plugin. Defaults to B<false>.
 +
 +=item B<EventServicePrefix> I<String>
 +
 +Add the given string as a prefix to the event service name.
 +If B<EventServicePrefix> not set or set to an empty string (""),
 +no prefix will be used.
 +
  =back
  
  =item B<Tag> I<String>
@@@ -7347,31 -6520,6 +7415,31 @@@ attribute for each metric being sent ou
  
  =back
  
 +=head2 Plugin C<zookeeper>
 +
 +The I<zookeeper plugin> will collect statistics from a I<Zookeeper> server
 +using the mntr command.  It requires Zookeeper 3.4.0+ and access to the
 +client port.
 +
 +B<Synopsis:>
 +
 + <Plugin "zookeeper">
 +   Host "127.0.0.1"
 +   Port "2181"
 + </Plugin>
 +
 +=over 4
 +
 +=item B<Host> I<Address>
 +
 +Hostname or address to connect to. Defaults to C<localhost>.
 +
 +=item B<Port> I<Service>
 +
 +Service name or port number to connect to. Defaults to C<2181>.
 +
 +=back
 +
  =head1 THRESHOLD CONFIGURATION
  
  Starting with version C<4.3.0> collectd has support for B<monitoring>. By that
@@@ -7842,36 -6990,19 +7910,36 @@@ Available options
  =item B<Plugin> I<Name>
  
  Name of the write plugin to which the data should be sent. This option may be
 -given multiple times to send the data to more than one write plugin.
 +given multiple times to send the data to more than one write plugin. If the
 +plugin supports multiple instances, the plugin's instance(s) must also be
 +specified.
  
  =back
  
  If no plugin is explicitly specified, the values will be sent to all available
  write plugins.
  
 -Example:
 +Single-instance plugin example:
  
   <Target "write">
     Plugin "rrdtool"
   </Target>
  
 +Multi-instance plugin example:
 +
 + <Plugin "write_graphite">
 +   <Node "foo">
 +   ...
 +   </Node>
 +   <Node "bar">
 +   ...
 +   </Node>
 + </Plugin>
 +  ...
 + <Target "write">
 +   Plugin "write_graphite/foo"
 + </Target>
 +
  =item B<jump>
  
  Starts processing the rules of another chain, see L<"Flow control"> above. If
@@@ -8306,6 -7437,6 +8374,6 @@@ L<sensors(1)
  
  =head1 AUTHOR
  
 -Florian Forster E<lt>octo@verplant.orgE<gt>
 +Florian Forster E<lt>octo@collectd.orgE<gt>
  
  =cut
diff --combined src/types.db
@@@ -8,21 -8,21 +8,24 @@@ ath_nodes             value:GAUGE:0:6553
  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
 -ceph_bytes              value:GAUGE:U:U
 -ceph_latency            value:GAUGE:U:U
 -ceph_rate               value:DERIVE:0:U
++ceph_bytes            value:GAUGE:U:U
++ceph_latency  value:GAUGE:U:U
++ceph_rate                     value:DERIVE: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
  connections           value:DERIVE:0:U
  conntrack             value:GAUGE:0:4294967295
  contextswitch         value:DERIVE:0:U
 +count                 value:GAUGE:0:U
  counter                       value:COUNTER:U:U
  cpufreq                       value:GAUGE:0:U
  cpu                   value:DERIVE:0:U
@@@ -40,7 -40,6 +43,7 @@@ disk_octets           read:DERIVE:0:U, write:DER
  disk_ops_complex      value:DERIVE:0:U
  disk_ops              read:DERIVE:0:U, write:DERIVE:0:U
  disk_time             read:DERIVE:0:U, write:DERIVE:0:U
 +disk_io_time          io_time:DERIVE:0:U, weighted_io_time:DERIVE:0:U
  dns_answer            value:DERIVE:0:U
  dns_notify            value:DERIVE:0:U
  dns_octets            queries:DERIVE:0:U, responses:DERIVE:0:U
@@@ -57,13 -56,11 +60,13 @@@ dns_response               value:DERIVE:0:
  dns_transfer          value:DERIVE:0:U
  dns_update            value:DERIVE:0:U
  dns_zops              value:DERIVE:0:U
 +drbd_resource value:DERIVE:0:U
  duration              seconds:GAUGE:0:U
  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
@@@ -104,7 -101,6 +107,7 @@@ memcached_items            value:GAUGE:0:
  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
@@@ -112,17 -108,6 +115,17 @@@ mysql_handler            value:DERIVE:0:
  mysql_locks           value:DERIVE:0:U
  mysql_log_position    value:DERIVE:0:U
  mysql_octets          rx:DERIVE:0:U, tx:DERIVE:0:U
 +mysql_bpool_pages     value:GAUGE:0:U
 +mysql_bpool_bytes     value:GAUGE:0:U
 +mysql_bpool_counters  value:DERIVE:0:U
 +mysql_innodb_data     value:DERIVE:0:U
 +mysql_innodb_dblwr    value:DERIVE:0:U
 +mysql_innodb_log      value:DERIVE:0:U
 +mysql_innodb_pages    value:DERIVE:0:U
 +mysql_innodb_row_lock value:DERIVE:0:U
 +mysql_innodb_rows     value:DERIVE:0:U
 +mysql_select          value:DERIVE:0:U
 +mysql_sort            value:DERIVE:0:U
  nfs_procedure         value:DERIVE:0:U
  nginx_connections     value:GAUGE:0:U
  nginx_requests                value:DERIVE:0:U
@@@ -132,8 -117,6 +135,8 @@@ node_stat          value:DERIVE:0:
  node_tx_rate          value:GAUGE:0:127
  objects                       value:GAUGE:0:U
  operations            value:DERIVE:0:U
 +packets                       value:DERIVE:0:U
 +pending_operations    value:GAUGE:0:U
  percent                       value:GAUGE:0:100.1
  percent_bytes         value:GAUGE:0:100.1
  percent_inodes                value:GAUGE:0:100.1
@@@ -154,7 -137,6 +157,7 @@@ ping_stddev                value:GAUGE:0:6553
  ping                  value:GAUGE:0:65535
  players                       value:GAUGE:0:1000000
  power                 value:GAUGE:0:U
 +pressure                      value:GAUGE:0:U
  protocol_counter      value:DERIVE:0:U
  ps_code                       value:GAUGE:0:9223372036854775807
  ps_count              processes:GAUGE:0:1000000, threads:GAUGE:0:1000000
@@@ -167,7 -149,6 +170,7 @@@ ps_rss                     value:GAUGE:0:9223372036854775
  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
@@@ -180,11 -161,6 +183,11 @@@ serial_octets            rx:DERIVE:0:U, tx:DERIVE
  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