+ 2014-01-26, Version 5.4.1
+ * amqp plugin: Add support for RabbitMQ 0.4.x to avoid compiler
+ warnings. Thanks to Sebastian Harl for implementing this.
+ * apache / network plugins: Improved initialization order hopefully
+ resolved gcrypt initialization problems.
+ * aquaero plugin: The type used to submit fan utilization was fixed.
+ Thanks to Alex Deymo for the patch.
+ * cgroups plugin: A small memory leak was fixed. Checking the existence
+ of a mount option without a value was fixed. More permissive parsing
+ of the cpuacct.stats file fixes support for some versions of Linux.
+ Thanks to Marc Fournier for bug reports and patches.
+ * curl plugin: Fix <Match> blocks without an instance. Thanks to
+ Alexander Golovko for reporting and Sebastian Harl for fixing this.
+ * curl_json plugin: Potentially invalid memory access has been
+ sanitized. Thanks to Jim Radford for his patch.
+ * interface plugin: Fix behavior under FreeBSD 10: Reporting of
+ per-address statistics caused duplicate updates to the same metric.
+ Thanks to demon / @trtrmitya for the patch.
+ * write_graphite plugin: Use TCP to connect to Graphite by default. The
+ default changed from TCP to UDP between 5.3.1 and 5.4.0, which is a
+ regression. Thanks to Marc Fournier for fixing this. Reconnect
+ behavior was improved. Thanks to Michael Hart for his patch.
+ * zfs_arc plugin: Collect "allocated" and "stolen" on FreeBSD only.
+
2013-08-18, Version 5.4.0
* collectd: The "LoadPlugin" config option no longer attempts to load
plugins twice. If more than one "LoadPlugin" statement or block is
2008-07-15, Version 4.4.2
* build system: Use pkg-config to detect the upsclient library.
- * collectd: Try even harder to determine the endianess of the
+ * collectd: Try even harder to determine the endianness of the
architecture collectd is being built on.
* disk plugin: Fix for Linux 2.4: A wrong field was used as the name
of disks.
2008-08-30, Version 4.3.4
* Build system: Improved detection of and linking with the statgrab
library.
- * collectd: Portability fixes, especially to determine endianess more
+ * collectd: Portability fixes, especially to determine endianness more
reliable.
* Various plugins: Fix format strings.
* disk plugin: A fix for giving disks under Linux 2.4 the right names
# 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
uint8_t c[8];
double d;
- d = 8.642135e130;
+ d = 8.642135e130;
memcpy ((void *) &i0, (void *) &d, 8);
i1 = i0;
uint8_t c[8];
double d;
- d = 8.642135e130;
+ d = 8.642135e130;
memcpy ((void *) &i0, (void *) &d, 8);
i1 = endianflip (i0);
uint8_t c[8];
double d;
- d = 8.642135e130;
+ d = 8.642135e130;
memcpy ((void *) &i0, (void *) &d, 8);
i1 = intswap (i0);
AC_MSG_ERROR([Didn't find out how doubles are stored in memory. Sorry.])
fi; fi; fi
+# --with-useragent {{{
+AC_ARG_WITH(useragent, [AS_HELP_STRING([--with-useragent@<:@=AGENT@:>@], [User agent to use on http requests])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ AC_DEFINE_UNQUOTED(COLLECTD_USERAGENT, ["$withval"], [User agent for http requests])
+ fi
+])
+
+# }}}
+
have_getfsstat="no"
AC_CHECK_FUNCS(getfsstat, [have_getfsstat="yes"])
have_getvfsstat="no"
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],
#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], [],
[],
[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
AM_CONDITIONAL([BUILD_FREEBSD],[test "x$x$ac_system" = "xFreeBSD"])
-AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"])
+AM_CONDITIONAL([BUILD_AIX],[test "x$x$ac_system" = "xAIX"])
if test "x$ac_system" = "xAIX"
then
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")
# }}}
# --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
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"
fi
if test "x$with_libmnl" = "xyes"
then
+ AC_CHECK_MEMBERS([struct rtnl_link_stats64.tx_window_errors],
+ [AC_DEFINE(HAVE_RTNL_LINK_STATS64, 1, [Define if struct rtnl_link_stats64 exists and is usable.])],
+ [],
+ [
+ #include <linux/if_link.h>
+ ])
+fi
+if test "x$with_libmnl" = "xyes"
+then
AC_CHECK_LIB(mnl, mnl_nlmsg_get_payload,
[with_libmnl="yes"],
[with_libmnl="no (symbol 'mnl_nlmsg_get_payload' not found)"],
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"
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"
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"
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 {{{
AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])],
[
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
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
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=""
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"
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"
dependency_error="no"
plugin_ascent="no"
+plugin_barometer="no"
plugin_battery="no"
plugin_bind="no"
plugin_cgroups="no"
plugin_curl_xml="no"
plugin_df="no"
plugin_disk="no"
+plugin_drbd="no"
plugin_entropy="no"
plugin_ethstat="no"
plugin_fscache="no"
plugin_irq="no"
plugin_libvirt="no"
plugin_load="no"
+plugin_log_logstash="no"
plugin_memory="no"
plugin_multimeter="no"
plugin_nfs="no"
plugin_cpu="yes"
plugin_cpufreq="yes"
plugin_disk="yes"
+ plugin_drbd="yes"
plugin_entropy="yes"
plugin_fscache="yes"
plugin_interface="yes"
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_load="yes"
fi
+if test "x$with_libyajl" = "xyes"
+then
+ plugin_log_logstash="yes"
+fi
+
if test "x$c_cv_have_libperl$c_cv_have_perl_ithreads" = "xyesyes"
then
plugin_perl="yes"
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
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([conntrack], [$plugin_conntrack], [nf_conntrack statistics])
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])
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])
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_mongodb], [$with_libmongoc], [MongoDB output plugin])
AC_PLUGIN([write_redis], [$with_libcredis], [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])
# 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"
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
+ 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
conntrack . . . . . . $enable_conntrack
df . . . . . . . . . $enable_df
disk . . . . . . . . $enable_disk
dns . . . . . . . . . $enable_dns
+ drbd . . . . . . . . $enable_drbd
email . . . . . . . . $enable_email
entropy . . . . . . . $enable_entropy
ethstat . . . . . . . $enable_ethstat
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
wireless . . . . . . $enable_wireless
write_graphite . . . $enable_write_graphite
write_http . . . . . $enable_write_http
+ write_kafka . . . . . $enable_write_kafka
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
%{?el6:%global _has_ip_vs_h 1}
%{?el6:%global _has_lvm2app_h 1}
%{?el6:%global _has_perl_extutils_embed 1}
+ %{?el6:%global _has_libmodbus 1}
# plugins enabled by default
%define with_aggregation 0%{!?_without_aggregation:1}
%define with_memcached 0%{!?_without_memcached:1}
%define with_memory 0%{!?_without_memory:1}
%define with_multimeter 0%{!?_without_multimeter:1}
+ %define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
%define with_mysql 0%{!?_without_mysql:1}
%define with_netlink 0%{!?_without_netlink:1}
%define with_network 0%{!?_without_network:1}
consumption from Intel Many Integrated Core (MIC) CPUs.
%endif
+ %if %{with_modbus}
+ %package modbus
+ Summary: modbus plugin for collectd
+ Group: System Environment/Daemons
+ Requires: %{name}%{?_isa} = %{version}-%{release}
+ BuildRequires: libmodbus-devel
+ %description modbus
+ The modbus plugin collects values from Modbus/TCP enabled devices
+ %endif
+
%if %{with_mysql}
%package mysql
Summary: MySQL plugin for collectd
%define _with_multimeter --disable-multimeter
%endif
+ %if %{with_modbus}
+ %define _with_modbus --enable-modbus
+ %else
+ %define _with_modbus --disable-modbus
+ %endif
+
%if %{with_mysql}
%define _with_mysql --enable-mysql
%else
- Enable cgroups, lvm and statsd plugins
- Enable (but don't build by default) mic, aquaero and sigrok plugins
+ * Wed Aug 06 2014 Marc Fournier <marc.fournier@camptocamp.com> 5.3.1-2
+ - Enabled modbus plugin
+
* Tue Aug 06 2013 Marc Fournier <marc.fournier@camptocamp.com> 5.3.1-1
- New upstream version
- Added RHEL5 support:
* Sat Nov 17 2012 Ruben Kerkhof <ruben@tilaa.nl> 5.1.0-2
- Move perl stuff to perl_vendorlib
- Replace hardcoded paths with macros
-- Remove unneccesary Requires
+- Remove unnecessary Requires
- Removed .a and .la files
- Some other small cleanups
- New upstream version
- Changes to support 5.1.0
- Enabled all buildable plugins based on libraries available on EL6 + EPEL
-- All plugins requiring external libraries are now shipped in seperate
+- All plugins requiring external libraries are now shipped in separate
packages.
- No longer treat Java plugin as an exception, correctly set $JAVA_HOME during
the build process + ensure build deps are installed.
AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
+AUTOMAKE_OPTIONS = subdir-objects
+
sbin_PROGRAMS = collectd collectdmon
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
utils_subst.c utils_subst.h \
utils_tail.c utils_tail.h \
utils_time.c utils_time.h \
- types_list.c types_list.h
+ types_list.c types_list.h \
+ utils_threshold.c utils_threshold.h
+
collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
collectd_CFLAGS = $(AM_CFLAGS)
collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
-pkglib_LTLIBRARIES =
+pkglib_LTLIBRARIES =
-BUILT_SOURCES =
+BUILT_SOURCES =
CLEANFILES =
if BUILD_PLUGIN_AGGREGATION
collectd_DEPENDENCIES += ascent.la
endif
+if BUILD_PLUGIN_BAROMETER
+pkglib_LTLIBRARIES += barometer.la
+barometer_la_SOURCES = barometer.c
+barometer_la_LDFLAGS = -module -avoid-version
+barometer_la_LIBADD = -lm
+collectd_LDADD += "-dlopen" barometer.la
+collectd_DEPENDENCIES += barometer.la
+endif
+
if BUILD_PLUGIN_BATTERY
pkglib_LTLIBRARIES += battery.la
battery_la_SOURCES = battery.c
cpu_la_SOURCES = cpu.c
cpu_la_CFLAGS = $(AM_CFLAGS)
cpu_la_LDFLAGS = -module -avoid-version
-cpu_la_LIBADD =
+cpu_la_LIBADD =
if BUILD_WITH_LIBKSTAT
cpu_la_LIBADD += -lkstat
endif
disk_la_SOURCES = disk.c
disk_la_CFLAGS = $(AM_CFLAGS)
disk_la_LDFLAGS = -module -avoid-version
-disk_la_LIBADD =
+disk_la_LIBADD =
if BUILD_WITH_LIBKSTAT
disk_la_LIBADD += -lkstat
endif
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_DEPENDENCIES += dns.la
endif
+if BUILD_PLUGIN_DRBD
+pkglib_LTLIBRARIES += drbd.la
+drbd_la_SOURCES = drbd.c
+drbd_la_LDFLAGS = -module -avoid-version
+drbd_la_LIBADD = -lpthread
+collectd_LDADD += "-dlopen" drbd.la
+collectd_DEPENDENCIES += drbd.la
+endif
+
if BUILD_PLUGIN_EMAIL
pkglib_LTLIBRARIES += email.la
email_la_SOURCES = email.c
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
+ iptables_la_LDFLAGS = -module -avoid-version
+ iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS)
collectd_LDADD += "-dlopen" iptables.la
collectd_DEPENDENCIES += iptables.la
endif
collectd_DEPENDENCIES += logfile.la
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 = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS)
+log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+collectd_LDADD += "-dlopen" log_logstash.la
+collectd_DEPENDENCIES += log_logstash.la
+endif
+
if BUILD_PLUGIN_LPAR
pkglib_LTLIBRARIES += lpar.la
lpar_la_SOURCES = lpar.c
pkglib_LTLIBRARIES += olsrd.la
olsrd_la_SOURCES = olsrd.c
olsrd_la_LDFLAGS = -module -avoid-version
-olsrd_la_LIBADD =
+olsrd_la_LIBADD =
if BUILD_WITH_LIBSOCKET
olsrd_la_LIBADD += -lsocket
endif
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
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 = -module -avoid-version $(BUILD_WITH_LIBRDKAFKA_LDFLAGS)
+write_kafka_la_LIBADD = $(BUILD_WITH_LIBRDKAFKA_LIBS)
+collectd_LDADD += "-dlopen" write_kafka.la
+collectd_DEPENDENCIES += write_kafka.la
+endif
+
if BUILD_PLUGIN_WRITE_MONGODB
pkglib_LTLIBRARIES += write_mongodb.la
write_mongodb_la_SOURCES = write_mongodb.c
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_LIBADD = -lprotobuf-c
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 = -module -avoid-version
+collectd_LDADD += "-dlopen" write_tsdb.la
+collectd_DEPENDENCIES += write_tsdb.la
+endif
+
if BUILD_PLUGIN_XMMS
pkglib_LTLIBRARIES += xmms.la
xmms_la_SOURCES = xmms.c
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 \
+ common.h 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 \
+ utils_avltree.c utils_avltree.h
+test_utils_avltree_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
+test_utils_avltree_LDFLAGS = -export-dynamic
+test_utils_avltree_LDADD =
+
+test_utils_heap_SOURCES = tests/test_utils_heap.c \
+ utils_heap.c utils_heap.h
+test_utils_heap_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
+test_utils_heap_LDFLAGS = -export-dynamic
+test_utils_heap_LDADD =
+
+test_utils_mount_SOURCES = tests/test_utils_mount.c \
+ utils_mount.c utils_mount.h \
+ common.c common.h \
+ 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
+ common.c 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
*
* Authors:
* Sebastien Pahl <sebastien.pahl at dotcloud.com>
- * Florian Forster <octo at verplant.org>
+ * Florian Forster <octo at collectd.org>
**/
#include "collectd.h"
#include <amqp.h>
#include <amqp_framing.h>
+ #ifdef HAVE_AMQP_TCP_SOCKET_H
+ # include <amqp_tcp_socket.h>
+ #endif
+ #ifdef HAVE_AMQP_SOCKET_H
+ # include <amqp_socket.h>
+ #endif
+ #ifdef HAVE_AMQP_TCP_SOCKET
+ #if defined HAVE_DECL_AMQP_SOCKET_CLOSE && !HAVE_DECL_AMQP_SOCKET_CLOSE
+ /* rabbitmq-c does not currently ship amqp_socket.h
+ * and, thus, does not define this function. */
+ int amqp_socket_close(amqp_socket_t *);
+ #endif
+ #endif
+
/* Defines for the delivery mode. I have no idea why they're not defined by the
* library.. */
#define CAMQP_DM_VOLATILE 1
/* subscribe only */
char *exchange_type;
char *queue;
+ _Bool queue_durable;
+ _Bool queue_auto_delete;
amqp_connection_state_t connection;
pthread_mutex_t lock;
? amqp_cstring_bytes (conf->queue)
: AMQP_EMPTY_BYTES,
/* passive = */ 0,
- /* durable = */ 0,
+ /* durable = */ conf->queue_durable,
/* exclusive = */ 0,
- /* auto_delete = */ 1,
+ /* auto_delete = */ conf->queue_auto_delete,
/* arguments = */ AMQP_EMPTY_TABLE);
if (qd_ret == NULL)
{
static int camqp_connect (camqp_config_t *conf) /* {{{ */
{
amqp_rpc_reply_t reply;
- int sockfd;
int status;
+ #ifdef HAVE_AMQP_TCP_SOCKET
+ amqp_socket_t *socket;
+ #else
+ int sockfd;
+ #endif
if (conf->connection != NULL)
return (0);
return (ENOMEM);
}
+ #ifdef HAVE_AMQP_TCP_SOCKET
+ # define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us */
+ /* TODO: add support for SSL using amqp_ssl_socket_new
+ * and related functions */
+ socket = amqp_tcp_socket_new (conf->connection);
+ if (! socket)
+ {
+ ERROR ("amqp plugin: amqp_tcp_socket_new failed.");
+ amqp_destroy_connection (conf->connection);
+ conf->connection = NULL;
+ return (ENOMEM);
+ }
+
+ status = amqp_socket_open (socket, CONF(conf, host), conf->port);
+ if (status < 0)
+ {
+ char errbuf[1024];
+ status *= -1;
+ ERROR ("amqp plugin: amqp_socket_open failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ amqp_destroy_connection (conf->connection);
+ conf->connection = NULL;
+ return (status);
+ }
+ #else /* HAVE_AMQP_TCP_SOCKET */
+ # define CLOSE_SOCKET() close(sockfd)
+ /* this interface is deprecated as of rabbitmq-c 0.4 */
sockfd = amqp_open_socket (CONF(conf, host), conf->port);
if (sockfd < 0)
{
return (status);
}
amqp_set_sockfd (conf->connection, sockfd);
+ #endif
reply = amqp_login (conf->connection, CONF(conf, vhost),
/* channel max = */ 0,
ERROR ("amqp plugin: amqp_login (vhost = %s, user = %s) failed.",
CONF(conf, vhost), CONF(conf, user));
amqp_destroy_connection (conf->connection);
- close (sockfd);
+ CLOSE_SOCKET ();
conf->connection = NULL;
return (1);
}
ERROR ("amqp plugin: amqp_channel_open failed.");
amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS);
amqp_destroy_connection (conf->connection);
- close(sockfd);
+ CLOSE_SOCKET ();
conf->connection = NULL;
return (1);
}
{
camqp_config_t *conf = user_data->data;
char routing_key[6 * DATA_MAX_NAME_LEN];
- char buffer[4096];
+ char buffer[8192];
int status;
if ((ds == NULL) || (vl == NULL) || (conf == NULL))
/* subscribe only */
conf->exchange_type = NULL;
conf->queue = NULL;
+ conf->queue_durable = 0;
+ conf->queue_auto_delete = 1;
/* general */
conf->connection = NULL;
pthread_mutex_init (&conf->lock, /* attr = */ NULL);
status = cf_util_get_string (child, &conf->exchange_type);
else if ((strcasecmp ("Queue", child->key) == 0) && !publish)
status = cf_util_get_string (child, &conf->queue);
+ else if ((strcasecmp ("QueueDurable", child->key) == 0) && !publish)
+ status = cf_util_get_boolean (child, &conf->queue_durable);
+ else if ((strcasecmp ("QueueAutoDelete", child->key) == 0) && !publish)
+ status = cf_util_get_boolean (child, &conf->queue_auto_delete);
else if (strcasecmp ("RoutingKey", child->key) == 0)
status = cf_util_get_string (child, &conf->routing_key);
else if ((strcasecmp ("Persistent", child->key) == 0) && publish)
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Florent EppO Monbillard <eppo at darox.net>
* - connections/lighttpd extension
* Amit Gupta <amit.gupta221 at gmail.com>
curl_easy_setopt (st->curl, CURLOPT_WRITEHEADER, st);
}
- curl_easy_setopt (st->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (st->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (st->curl, CURLOPT_ERRORBUFFER, st->apache_curl_error);
if (st->user != NULL)
return (0);
} /* }}} int apache_read_host */
+ static int apache_init (void) /* {{{ */
+ {
+ /* Call this while collectd is still single-threaded to avoid
+ * initialization issues in libgcrypt. */
+ curl_global_init (CURL_GLOBAL_SSL);
+ return (0);
+ } /* }}} int apache_init */
+
void module_register (void)
{
plugin_register_complex_config ("apache", config);
+ plugin_register_init ("apache", apache_init);
} /* void module_register */
/* vim: set sw=8 noet fdm=marker : */
SocketFile "/path/to/socket"
SocketGroup "collectd"
SocketPerms "0770"
+ DeleteSocket false
</Plugin>
=head1 DESCRIPTION
or B<type_instance> without B<type> doesn't make much sense and should be
avoided.
-Please note that this is the same format as used in the B<exec plugin>, see
-L<collectd-exec(5)>.
+=item B<type:key=>I<value>
+
+Sets user defined meta information. The B<type> key is a single character
+defining the type of the meta information.
+
+The current supported types are:
+
+=over 8
+
+=item B<s> A string passed as-is.
=back
+=back
+
+Please note that this is the same format as used in the B<exec plugin>, see
+L<collectd-exec(5)>.
+
Example:
-> | PUTNOTIF type=temperature severity=warning time=1201094702 message=The roof is on fire!
<- | 0 Success
=head1 AUTHOR
-Florian Forster E<lt>octo@verplant.orgE<gt>
+Florian Forster E<lt>octo@collectd.orgE<gt>
=cut
@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_CONNTRACK_TRUE@LoadPlugin conntrack
#@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_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_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
# 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 "bind">
# URL "http://localhost:8053/"
# ParseTime false
# </View>
#</Plugin>
- #<Plugin cgroup>
+ #<Plugin cgroups>
# CGroup "libvirt"
# IgnoreSelected false
#</Plugin>
+#<Plugin cpu>
+# ReportActive false
+# ReportByCpu true
+# ValuesPercentage false
+#</Plugin>
+#
#<Plugin csv>
# DataDir "@localstatedir@/lib/@PACKAGE_NAME@/csv"
# StoreRates false
# </URL>
#</Plugin>
-#<Plugin "curl_xml">
+#<Plugin curl_xml>
# <URL "http://localhost/stats.xml">
# Host "my_host"
# Instance "some_instance"
#<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"
#
# IgnoreSelected false
# HostnameFormat name
# InterfaceFormat name
+# PluginInstanceFormat name
+#</Plugin>
+
+#<Plugin load>
+# ReportRelative true
#</Plugin>
#<Plugin lpar>
# </Instance>
#</Plugin>
+#<Plugin memory>
+# ValuesAbsolute true
+# ValuesPercentage false
+#</Plugin>
+
#<Plugin modbus>
# <Data "data_name">
# RegisterBase 1234
# 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
# TimerPercentile 90.0
#</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
# <Match>
# Regex "S=([1-9][0-9]*)"
# DSType "CounterAdd"
# </File>
#</Plugin>
-#<Plugin "tail_csv">
+#<Plugin tail_csv>
# <Metric "dropped">
# Type "percent"
# Instance "dropped"
# 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>
#</Plugin>
+#<Plugin write_kafka>
+# Property "metadata.broker.list" "localhost:9092"
+# <Topic "collectd">
+# Format JSON
+# </Topic>
+#</Plugin>
+
#<Plugin write_mongodb>
# <Node "example">
# Host "localhost"
# TTLFactor 2.0
# </Node>
# Tag "foobar"
+# Attribute "foo" "bar"
+#</Plugin>
+
+#<Plugin write_tsdb>
+# <Node>
+# Host "localhost"
+# Port "4242"
+# HostTags "status=production"
+# StoreRates false
+# AlwaysAppendDS false
+# </Node>
#</Plugin>
##############################################################################
##############################################################################
#@BUILD_PLUGIN_THRESHOLD_TRUE@LoadPlugin "threshold"
-#<Plugin "threshold">
+#<Plugin threshold>
# <Type "foo">
# WarningMin 0.00
# WarningMax 1000.00
BaseDir "/path/to/data/"
PIDFile "/path/to/pidfile/collectd.pid"
Server "123.123.123.123" 12345
-
+
LoadPlugin cpu
LoadPlugin load
-
+
<LoadPlugin df>
Interval 3600
</LoadPlugin>
-
+
LoadPlugin ping
<Plugin ping>
Host "example.org"
<Aggregation>
Plugin "cpu"
Type "cpu"
-
+
GroupBy "Host"
GroupBy "TypeInstance"
-
+
CalculateSum true
CalculateAverage true
</Aggregation>
Plugin "cpu"
PluginInstance "/[0,2,4,6,8]$/"
Type "cpu"
-
+
SetPlugin "cpu"
SetPluginInstance "even-%{aggregation}"
-
+
GroupBy "Host"
GroupBy "TypeInstance"
-
+
CalculateAverage true
</Aggregation>
</Plugin>
# StoreRates false
# GraphitePrefix "collectd."
# GraphiteEscapeChar "_"
+ # GraphiteSeparateInstances false
+ # GraphiteAlwaysAppendDS false
</Publish>
-
+
# Receive values from an AMQP broker
<Subscribe "some_name">
Host "localhost"
Exchange "amq.fanout"
# ExchangeType "fanout"
# Queue "queue_name"
+ # QueueDurable false
+ # QueueAutoDelete true
# RoutingKey "collectd.#"
</Subscribe>
</Plugin>
=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
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>
=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<bind>
Starting with BIND 9.5.0, the most widely used DNS server software provides
ParseTime false
OpCodes true
QTypes true
-
+
ServerStats true
ZoneMaintStats true
ResolverStats false
MemoryStats true
-
+
<View "_default">
QTypes true
ResolverStats true
CacheRRSets true
-
+
Zone "127.in-addr.arpa/IN"
</View>
</Plugin>
=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 following configuration options are available:
+
+=over 4
+
+=item B<ReportActive> B<false>|B<true>
+
+Reports non-idle CPU usage as the "active" value. Defaults to false.
+
+=item B<ReportByCpu> B<false>|B<true>
+
+When true reports usage for all cores. When false, reports cpu usage
+aggregated over all cores.
+Defaults to true.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+When true report percentage usage instead of tick values. Defaults to false.
+
+=back
+
+
=head2 Plugin C<cpufreq>
This plugin doesn't have any options. It reads
Password to use if authorization is required to read the page.
+=item B<Digest> B<true>|B<false>
+
+Enable HTTP digest authentication.
+
=item B<VerifyPeer> B<true>|B<false>
Enable or disable peer SSL certificate verification. See
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>
+
+=item B<Digest> B<true>|B<false>
+
=item B<VerifyPeer> B<true>|B<false>
+
=item B<VerifyHost> B<true>|B<false>
+
=item B<CACert> I<file>
+
=item B<Header> I<Header>
+
=item B<Post> I<Body>
These options behave exactly equivalent to the appropriate options of the
=item B<Password> I<Password>
+=item B<Digest> B<true>|B<false>
+
=item B<VerifyPeer> B<true>|B<false>
=item B<VerifyHost> B<true>|B<false>
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
=item B<ValuesAbsolute> B<true>|B<false>
-Enables or disables reporting of free, used and used disk space in 1K-blocks.
-Defaults to true.
+Enables or disables reporting of free and used disk space in 1K-blocks.
+Defaults to B<true>.
-=item B<ValuesPercentage> B<true>|B<false>
+=item B<ValuesPercentage> B<false>|B<true>
-Enables or disables reporting of free, used and used disk space in percentage.
-Defaults to false.
+Enables or disables reporting of free and used disk space in percentage.
+Defaults to B<false>.
-This is useful for deploying collectd on the cloud, where machines with
-different disk size may exist. Then it is more practical to configure thresholds
-based on relative disk size.
+This is useful for deploying I<collectd> on the cloud, where machines with
+different disk size may exist. Then it is more practical to configure
+thresholds based on relative disk size.
=back
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>
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 libvirt 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<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
+runnable tasks in the run-queue and is provided by many operating systems as a
+one, five or fifteen minute average.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<ReportRelative> B<false>|B<true>
+
+When enabled, system load divided by number of available CPU cores is reported
+for intervals 1 min, 5 min and 15 min. Defaults to false.
+
+=back
+
+
=head2 Plugin C<logfile>
=over 4
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
ShowCPU true
ShowCPUCores true
ShowMemory true
-
+
ShowTemperatures true
Temperature vddg
Temperature vddq
ShowPower true
Power total0
Power total1
- IgnoreSelectedPower true
+ IgnoreSelectedPower true
</Plugin>
The following options are valid inside the B<PluginE<nbsp>mic> block:
=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>
=item fout
-Fan Out
+Fan Out
=item vccp
=item total0
-Total power utilization averaged over Time Window 0 (uWatts).
+Total power utilization averaged over Time Window 0 (uWatts).
=item total1
-Total power utilization averaged over Time Window 0 (uWatts).
+Total power utilization averaged over Time Window 0 (uWatts).
=item inst
=item imax
-Max instantaneous power (uWatts).
+Max instantaneous power (uWatts).
=item pcie
-PCI-E connector power (uWatts).
+PCI-E connector power (uWatts).
=item c2x3
-2x3 connector power (uWatts).
+2x3 connector power (uWatts).
=item c2x4
-2x4 connector power (uWatts).
+2x4 connector power (uWatts).
=item vccp
-Core rail (uVolts).
+Core rail (uVolts).
=item vddg
-Uncore rail (uVolts).
+Uncore rail (uVolts).
=item vddq
-Memory subsystem rail (uVolts).
+Memory subsystem rail (uVolts).
+
+=back
=back
+=head2 Plugin C<memory>
+
+The I<memory plugin> provides the following configuration options:
+
+=over 4
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of physical memory usage in absolute numbers,
+i.e. bytes. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of physical memory usage in percentages, e.g.
+percent of physical memory used. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment in
+which the sizes of physical memory vary.
+
=back
=head2 Plugin C<modbus>
Type voltage
Instance "input-1"
</Data>
-
+
<Data "voltage-input-2">
RegisterBase 2
RegisterType float
Type voltage
Instance "input-2"
</Data>
-
+
<Host "modbus.example.com">
Address "192.168.0.42"
Port "502"
Interval 60
-
+
<Slave 1>
Instance "power-supply"
Collect "voltage-input-1"
Password "password"
Port "3306"
MasterStats true
+ ConnectTimeout 10
</Database>
<Database bar>
+ Alias "squeeze"
Host "localhost"
Socket "/var/run/mysql/mysqld.sock"
SlaveStats true
=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>.
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>
If enabled, the plugin sends a notification if the replication slave I/O and /
or SQL threads are not running.
+=item B<ConnectTimeout> I<Seconds>
+
+Sets the connect timeout for the MySQL client.
+
=back
=head2 Plugin C<netapp>
User "username"
Password "aef4Aebe"
Interval 30
-
+
<WAFL>
Interval 30
GetNameCache true
GetBufferCache true
GetInodeCache true
</WAFL>
-
+
<Disks>
Interval 30
GetBusy true
</Disks>
-
+
<VolumePerf>
Interval 30
GetIO "volume0"
GetLatency "volume0"
IgnoreSelectedLatency false
</VolumePerf>
-
+
<VolumeUsage>
Interval 30
GetCapacity "vol0"
GetSnapshot "vol3"
IgnoreSelectedSnapshot false
</VolumeUsage>
-
+
<Quota>
Interval 60
</Quota>
-
+
<Snapvault>
Interval 30
</Snapvault>
-
+
<System>
Interval 30
GetCPULoad true
# Export to an internal server
# (demonstrates usage without additional options)
Server "collectd.internal.tld"
-
+
# Export to an external server
# (demonstrates usage with signature options)
<Server "collectd.external.tld">
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>
=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
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
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>
=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
When enabled, the I<swap I/O> is reported in bytes. When disabled, the default,
I<swap I/O> is reported in pages. This option is available under Linux only.
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of absolute swap metrics, i.e. number of I<bytes>
+available and used. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of relative swap metrics, i.e. I<percent>
+available and free. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment, where
+swap sizes differ and you want to specify generic thresholds or similar.
+
=back
=head2 Plugin C<syslog>
<Plugin "tail">
<File "/var/log/exim4/mainlog">
Instance "exim"
+ Interval 60
<Match>
Regex "S=([1-9][0-9]*)"
DSType "CounterAdd"
next B<Instance> option. This way you can extract several plugin instances from
one logfile, handy when parsing syslog and the like.
+The B<Interval> option allows you to define the length of time between reads. If
+this is not set, the default Interval will be used.
+
Each B<Match> block has the following options to describe how the match should
be performed:
=item B<AlwaysAppendDS> B<false>|B<true>
- If set the B<true>, append the name of the I<Data Source> (DS) to the "metric"
+ 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.
+
+=back
+
=head2 Plugin C<write_mongodb>
The I<write_mongodb plugin> will send values to I<MongoDB>, a schema-less
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
=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
+"<metric> <value> <timestamp>\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 "<prefix><host><postfix><plugin><type><name>"
+
+=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 "<prefix><host><postfix><plugin><type><name>"
+
+=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 "_" (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_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.
TTLFactor 2.0
</Node>
Tag "foobar"
+ Attribute "foo" "bar"
</Plugin>
The following options are understood by the I<write_riemann plugin>:
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>.
+
=back
=item B<Tag> I<String>
Add the given string as an additional tag to the metric being sent to
I<Riemann>.
+=item B<Attribute> I<String> I<String>
+
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to I<Riemann>.
+
=back
=head1 THRESHOLD CONFIGURATION
=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
Max 100
Satisfy "All"
</Match>
-
+
# Match if the value of any data source is outside the range of 0 - 100.
<Match "value">
Min 0
<Target "replace">
# Replace "example.net" with "example.com"
Host "\\<example.net\\>" "example.com"
-
+
# Strip "www." from hostnames
Host "\\<www\\." ""
</Target>
=head1 AUTHOR
-Florian Forster E<lt>octo@verplant.orgE<gt>
+Florian Forster E<lt>octo@collectd.orgE<gt>
=cut
/**
* collectd - src/common.c
- * Copyright (C) 2005-2010 Florian octo Forster
+ * Copyright (C) 2005-2014 Florian octo Forster
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 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
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* Authors:
* Florian octo Forster <octo at collectd.org>
if (buf[i] != '\\')
continue;
- if ((i >= buf_len) || (buf[i + 1] == '\0')) {
+ if (((i + 1) >= buf_len) || (buf[i + 1] == 0)) {
ERROR ("string unescape: backslash found at end of string.");
+ /* Ensure null-byte at the end of the buffer. */
+ buf[i] = 0;
return (-1);
}
break;
}
+ /* Move everything after the position one position to the left.
+ * Add a null-byte as last character in the buffer. */
memmove (buf + i + 1, buf + i + 2, buf_len - i - 2);
+ buf[buf_len - 1] = 0;
}
return (0);
} /* int strunescape */
return (buffer_len);
} /* size_t strstripnewline */
-int escape_slashes (char *buf, int buf_len)
+int escape_slashes (char *buffer, size_t buffer_size)
{
int i;
+ size_t buffer_len;
- if (strcmp (buf, "/") == 0)
- {
- if (buf_len < 5)
- return (-1);
+ buffer_len = strlen (buffer);
- strncpy (buf, "root", buf_len);
+ if (buffer_len <= 1)
+ {
+ if (strcmp ("/", buffer) == 0)
+ {
+ if (buffer_size < 5)
+ return (-1);
+ sstrncpy (buffer, "root", buffer_size);
+ }
return (0);
}
- if (buf_len <= 1)
- return (0);
-
/* Move one to the left */
- if (buf[0] == '/')
- memmove (buf, buf + 1, buf_len - 1);
+ if (buffer[0] == '/')
+ {
+ memmove (buffer, buffer + 1, buffer_len);
+ buffer_len--;
+ }
- for (i = 0; i < buf_len - 1; i++)
+ for (i = 0; i < buffer_len - 1; i++)
{
- if (buf[i] == '\0')
- break;
- else if (buf[i] == '/')
- buf[i] = '_';
+ if (buffer[i] == '/')
+ buffer[i] = '_';
}
- buf[i] = '\0';
return (0);
} /* int escape_slashes */
char ident[128];
*ksp_ptr = NULL;
-
+
if (kc == NULL)
return (-1);
}
if (value == endptr) {
- sfree (value);
ERROR ("parse_value: Failed to parse string as %s: %s.",
DS_TYPE_TO_STRING (ds_type), value);
+ sfree (value);
return -1;
}
else if ((NULL != endptr) && ('\0' != *endptr))
while ((ent = readdir (dh)) != NULL)
{
int status;
-
+
if (include_hidden)
{
if ((strcmp (".", ent->d_name) == 0)
return (0);
} /* }}} value_t rate_to_value */
+int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
+ value_to_rate_state_t *state,
+ int ds_type, cdtime_t t)
+{
+ double interval;
+
+ /* Another invalid state: The time is not increasing. */
+ if (t <= state->last_time)
+ {
+ memset (state, 0, sizeof (*state));
+ return (EINVAL);
+ }
+
+ interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
+
+ /* Previous value is invalid. */
+ if (state->last_time == 0) /* {{{ */
+ {
+ if (ds_type == DS_TYPE_DERIVE)
+ {
+ state->last_value.derive = value;
+ }
+ else if (ds_type == DS_TYPE_COUNTER)
+ {
+ state->last_value.counter = (counter_t) value;
+ }
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ {
+ state->last_value.absolute = (absolute_t) value;
+ }
+ else
+ {
+ assert (23 == 42);
+ }
+
+ state->last_time = t;
+ return (EAGAIN);
+ } /* }}} */
+
+ if (ds_type == DS_TYPE_DERIVE)
+ {
+ ret_rate->gauge = (value - state->last_value.derive) / interval;
+ state->last_value.derive = value;
+ }
+ else if (ds_type == DS_TYPE_COUNTER)
+ {
+ ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
+ state->last_value.counter = (counter_t) value;
+ }
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ {
+ ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
+ state->last_value.absolute = (absolute_t) value;
+ }
+ else
+ {
+ assert (23 == 42);
+ }
+
+ state->last_time = t;
+ return (0);
+} /* }}} value_t rate_to_value */
+
int service_name_to_port_number (const char *service_name)
{
struct addrinfo *ai_list;
* collectd - src/configfile.c
* Copyright (C) 2005-2011 Florian octo Forster
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 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
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* Authors:
* Florian octo Forster <octo at collectd.org>
/* Resize the memory containing the children to be big enough to hold
* all children. */
+ if (dst->children_num + src->children_num - 1 == 0)
+ {
+ dst->children_num = 0;
+ return (0);
+ }
+
temp = (oconfig_item_t *) realloc (dst->children,
sizeof (oconfig_item_t)
* (dst->children_num + src->children_num - 1));
return (-1);
/* Now replace the i'th child in `root' with `new'. */
- cf_ci_replace_child (root, new, i);
+ if (cf_ci_replace_child (root, new, i) < 0)
+ return (-1);
/* ... and go back to the new i'th child. */
--i;
if (i >= cf_global_options_num)
return (-1);
+ if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1)
+ {
+ DEBUG ("Configfile: Ignoring `PIDFILE' option because "
+ "command-line option `-P' take precedence.");
+ return (0);
+ }
+
sfree (cf_global_options[i].value);
if (value != NULL)
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Aman Gupta <aman at tmm1.net>
**/
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
curl_easy_setopt (wp->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (wp->curl, CURLOPT_WRITEFUNCTION, cc_curl_callback);
curl_easy_setopt (wp->curl, CURLOPT_WRITEDATA, wp);
- curl_easy_setopt (wp->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (wp->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
curl_easy_setopt (wp->curl, CURLOPT_URL, wp->url);
curl_easy_setopt (wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
ssnprintf (wp->credentials, credentials_size, "%s:%s",
wp->user, (wp->pass == NULL) ? "" : wp->pass);
curl_easy_setopt (wp->curl, CURLOPT_USERPWD, wp->credentials);
+
+ if (wp->digest)
+ {
+ curl_easy_setopt (wp->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (wp->curl, CURLOPT_USERNAME, wp->user);
+ curl_easy_setopt (wp->curl, CURLOPT_PASSWORD, wp->pass);
+ }
}
curl_easy_setopt (wp->curl, CURLOPT_SSL_VERIFYPEER, (long) wp->verify_peer);
page->url = NULL;
page->user = NULL;
page->pass = NULL;
+ page->digest = 0;
page->verify_peer = 1;
page->verify_host = 1;
page->response_time = 0;
status = cf_util_get_string (child, &page->user);
else if (strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &page->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &page->digest);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &page->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
INFO ("curl plugin: No pages have been defined.");
return (-1);
}
+ curl_global_init (CURL_GLOBAL_SSL);
return (0);
} /* }}} int cc_init */
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
struct curl_slist *headers;
char *post_body;
+ cdtime_t interval;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
- curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
ssnprintf (db->credentials, credentials_size, "%s:%s",
db->user, (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+
+ if (db->digest)
+ {
+ curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+ curl_easy_setopt (db->curl, CURLOPT_PASSWORD, db->pass);
+ }
}
curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, (long) db->verify_peer);
status = cf_util_get_string (child, &db->user);
else if (db->url && strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &db->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &db->digest);
else if (db->url && strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &db->verify_peer);
else if (db->url && strcasecmp ("VerifyHost", child->key) == 0)
status = cf_util_get_string (child, &db->post_body);
else if (strcasecmp ("Key", child->key) == 0)
status = cj_config_add_key (db, child);
+ else if (strcasecmp ("Interval", child->key) == 0)
+ status = cf_util_get_cdtime(child, &db->interval);
else
{
WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
if (status == 0)
{
user_data_t ud;
- char cb_name[DATA_MAX_NAME_LEN];
+ char *cb_name;
+ struct timespec interval = { 0, 0 };
+
+ CDTIME_T_TO_TIMESPEC (db->interval, &interval);
if (db->instance == NULL)
db->instance = strdup("default");
ud.data = (void *) db;
ud.free_func = cj_free;
- ssnprintf (cb_name, sizeof (cb_name), "curl_json-%s-%s",
+ cb_name = ssnprintf_alloc ("curl_json-%s-%s",
db->instance, db->url ? db->url : db->sock);
- plugin_register_complex_read (/* group = */ "curl_json", cb_name, cj_read,
- /* interval = */ NULL, &ud);
+ plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
+ /* interval = */ (db->interval > 0) ? &interval : NULL,
+ &ud);
+ sfree (cb_name);
}
else
{
if (key->instance == NULL)
{
- if ((db->depth == 0) || (strcmp ("", db->state[db->depth-1].name) == 0))
- sstrncpy (vl.type_instance, db->state[db->depth].name, sizeof (vl.type_instance));
- else
- ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
- db->state[db->depth-1].name, db->state[db->depth].name);
+ int i, len = 0;
+ for (i = 0; i < db->depth; i++)
+ len += ssnprintf(vl.type_instance+len, sizeof(vl.type_instance)-len,
+ i ? "-%s" : "%s", db->state[i+1].name);
}
else
sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
sstrncpy (vl.type, key->type, sizeof (vl.type));
+ if (db->interval > 0)
+ vl.interval = db->interval;
+
plugin_dispatch_values (&vl);
} /* }}} int cj_submit */
return cj_perform (db);
} /* }}} int cj_read */
+ static int cj_init (void) /* {{{ */
+ {
+ /* Call this while collectd is still single-threaded to avoid
+ * initialization issues in libgcrypt. */
+ curl_global_init (CURL_GLOBAL_SSL);
+ return (0);
+ } /* }}} int cj_init */
+
void module_register (void)
{
plugin_register_complex_config ("curl_json", cj_config);
+ plugin_register_init ("curl_json", cj_init);
} /* void module_register */
/* vim: set sw=2 sts=2 et fdm=marker : */
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
/* If the base xpath returns more than one block, the result is assumed to be
* a table. The `Instance' option is not optional in this case. Check for the
* condition and inform the user. */
- if (is_table && (vl->type_instance == NULL))
+ if (is_table)
{
WARNING ("curl_xml plugin: "
"Base-XPath %s is a table (more than one result was returned), "
curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
- curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
ssnprintf (db->credentials, credentials_size, "%s:%s",
db->user, (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+
+ if (db->digest)
+ {
+ curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+ curl_easy_setopt (db->curl, CURLOPT_PASSWORD, db->pass);
+ }
}
curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, db->verify_peer ? 1L : 0L);
status = cf_util_get_string (child, &db->user);
else if (strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &db->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &db->digest);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &db->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
return (0);
} /* }}} int cx_config */
+ static int cx_init (void) /* {{{ */
+ {
+ /* Call this while collectd is still single-threaded to avoid
+ * initialization issues in libgcrypt. */
+ curl_global_init (CURL_GLOBAL_SSL);
+ return (0);
+ } /* }}} int cx_init */
+
void module_register (void)
{
plugin_register_complex_config ("curl_xml", cx_config);
+ plugin_register_init ("curl_xml", cx_init);
} /* void module_register */
/* vim: set sw=2 sts=2 et fdm=marker : */
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Sebastian Harl <sh at tokkee.org>
* Peter Holik <peter at holik.at>
**/
fprintf (fh,
"Severity: %s\n"
- "Time: %.3f\n",
- severity, CDTIME_T_TO_DOUBLE (n->time));
+ "Time: %u\n",
+ severity, (unsigned int)CDTIME_T_TO_TIME_T(n->time));
/* Print the optional fields */
if (strlen (n->host) > 0)
/**
* collectd - src/lvm.c
* Copyright (C) 2013 Chad Malfait
+ * Copyright (C) 2014 Carnegie Mellon University
*
* 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
*
* Authors:
* Chad Malfait <malfaitc at yahoo.com>
+ * Benjamin Gilbert <bgilbert at cs.cmu.edu>
**/
#include <lvm2app.h>
#include "common.h"
#include "plugin.h"
+#define NO_VALUE UINT64_MAX
+#define PERCENT_SCALE_FACTOR 1e-8
+
+static uint64_t get_lv_property_int(lv_t lv, char const *property)
+{
+ lvm_property_value_t v;
+
+ v = lvm_lv_get_property(lv, property);
+ if (!v.is_valid || !v.is_integer)
+ return NO_VALUE;
+ /* May be NO_VALUE if @property does not apply to this LV */
+ return v.value.integer;
+}
+
+static char const *get_lv_property_string(lv_t lv, char const *property)
+{
+ lvm_property_value_t v;
+
+ v = lvm_lv_get_property(lv, property);
+ if (!v.is_valid || !v.is_string)
+ return NULL;
+ return v.value.string;
+}
+
static void lvm_submit (char const *plugin_instance, char const *type_instance,
uint64_t ivalue)
{
plugin_dispatch_values (&vl);
}
-static int vg_read(vg_t vg, char const *vg_name)
+static void report_lv_utilization(lv_t lv, char const *vg_name,
+ char const *lv_name, uint64_t lv_size,
+ char const *used_percent_property)
+{
+ uint64_t used_percent_unscaled;
+ uint64_t used_bytes;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
+ used_percent_unscaled = get_lv_property_int(lv, used_percent_property);
+ if (used_percent_unscaled == NO_VALUE)
+ return;
+ used_bytes = lv_size * (used_percent_unscaled * PERCENT_SCALE_FACTOR);
+
+ ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-%s",
+ vg_name, lv_name);
+ lvm_submit(plugin_instance, "used", used_bytes);
+ lvm_submit(plugin_instance, "free", lv_size - used_bytes);
+}
+
+static void report_thin_pool_utilization(lv_t lv, char const *vg_name,
+ uint64_t lv_size)
+{
+ char const *data_lv;
+ char const *metadata_lv;
+ uint64_t metadata_size;
+
+ data_lv = get_lv_property_string(lv, "data_lv");
+ metadata_lv = get_lv_property_string(lv, "metadata_lv");
+ metadata_size = get_lv_property_int(lv, "lv_metadata_size");
+ if (data_lv == NULL || metadata_lv == NULL || metadata_size == NO_VALUE)
+ return;
+
+ report_lv_utilization(lv, vg_name, data_lv, lv_size, "data_percent");
+ report_lv_utilization(lv, vg_name, metadata_lv, metadata_size,
+ "metadata_percent");
+}
+
+static void vg_read(vg_t vg, char const *vg_name)
{
struct dm_list *lvs;
struct lvm_lv_list *lvl;
+ char const *name;
+ char const *attrs;
+ uint64_t size;
lvm_submit (vg_name, "free", lvm_vg_get_free_size(vg));
lvs = lvm_vg_list_lvs(vg);
if (!lvs) {
/* no VGs are defined, which is not an error per se */
- return (0);
+ return;
}
dm_list_iterate_items(lvl, lvs) {
- return (0);
+ lvm_submit(vg_name, lvm_lv_get_name(lvl->lv), lvm_lv_get_size(lvl->lv));
+ }
+
++ dm_list_iterate_items(lvl, lvs) {
+ name = lvm_lv_get_name(lvl->lv);
+ attrs = get_lv_property_string(lvl->lv, "lv_attr");
+ size = lvm_lv_get_size(lvl->lv);
+ if (name == NULL || attrs == NULL || size == NO_VALUE)
+ continue;
+
+ /* Condition on volume type. We want the reported sizes in the
+ volume group to sum to the size of the volume group, so we ignore
+ virtual volumes. */
+ switch (attrs[0]) {
+ case 's':
+ case 'S':
+ /* Snapshot. Also report used/free space. */
+ report_lv_utilization(lvl->lv, vg_name, name, size,
+ "data_percent");
+ break;
+ case 't':
+ /* Thin pool virtual volume. We report the underlying data
+ and metadata volumes, not this one. Report used/free
+ space, then ignore. */
+ report_thin_pool_utilization(lvl->lv, vg_name, size);
+ continue;
+ case 'v':
+ /* Virtual volume. Ignore. */
+ continue;
+ case 'V':
+ /* Thin volume or thin snapshot. Ignore. */
+ continue;
+ }
+ lvm_submit(vg_name, name, size);
+ }
}
static int lvm_read(void)
if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P))
return;
- gcry_check_version (NULL); /* before calling any other functions */
+ /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
+ * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS
+ * *before* initalizing Libgcrypt with gcry_check_version(), which itself must
+ * be called before any other gcry_* function. GCRYCTL_ANY_INITIALIZATION_P
+ * above doesn't count, as it doesn't implicitly initalize Libgcrypt.
+ *
+ * tl;dr: keep all these gry_* statements in this exact order please. */
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ gcry_check_version (NULL);
gcry_control (GCRYCTL_INIT_SECMEM, 32768);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
} /* }}} void network_init_gcrypt */
tmp = (int) ci->values[0].value.number;
if ((tmp > 0) && (tmp <= 255))
network_config_ttl = tmp;
+ else {
+ WARNING ("network plugin: The `TimeToLive' must be between 1 and 255.");
+ return (-1);
+ }
return (0);
} /* }}} int network_config_set_ttl */
{
int i;
+ /* The options need to be applied first */
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("TimeToLive", child->key) == 0)
+ network_config_set_ttl (child);
+ }
+
for (i = 0; i < ci->children_num; i++)
{
oconfig_item_t *child = ci->children + i;
network_config_add_listen (child);
else if (strcasecmp ("Server", child->key) == 0)
network_config_add_server (child);
- else if (strcasecmp ("TimeToLive", child->key) == 0)
- network_config_set_ttl (child);
+ else if (strcasecmp ("TimeToLive", child->key) == 0) {
+ /* Handled earlier */
+ }
else if (strcasecmp ("MaxPacketSize", child->key) == 0)
network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)
*
* Authors:
* Lyonel Vincent <lyonel at ezix.org>
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Oleg King <king2 at kaluga.ru>
* Sebastian Harl <sh at tokkee.org>
* Andrés J. DÃaz <ajdiaz at connectical.com>
int getprocs64 (void *procsinfo, int sizproc, void *fdsinfo, int sizfd, pid_t *index, int count);
int getthrds64( pid_t, void *, int, tid64_t *, int );
#endif
- int getargs (struct procentry64 *processBuffer, int bufferLen, char *argsBuffer, int argsLen);
+ int getargs (void *processBuffer, int bufferLen, char *argsBuffer, int argsLen);
#endif /* HAVE_PROCINFO_H */
/* put name of process from config to list_head_g tree
* collectd - src/snmp.c
* Copyright (C) 2007-2012 Florian octo Forster
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; only version 2 of the License is applicable.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
*
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * 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
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* Authors:
* Florian octo Forster <octo at collectd.org>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
+#include <fnmatch.h>
+
/*
* Private data structes
*/
{
char *name; /* used to reference this from the `Collect' option */
char *type; /* used to find the data_set */
- int is_table;
+ _Bool is_table;
instance_t instance;
char *instance_prefix;
oid_t *values;
double scale;
double shift;
struct data_definition_s *next;
+ char **ignores;
+ size_t ignores_len;
+ int invert_match;
};
typedef struct data_definition_s data_definition_t;
{
char *name;
char *address;
- char *community;
int version;
+
+ /* snmpv1/2 options */
+ char *community;
+
+ /* snmpv3 security options */
+ char *username;
+ oid *auth_protocol;
+ size_t auth_protocol_len;
+ char *auth_passphrase;
+ oid *priv_protocol;
+ size_t priv_protocol_len;
+ char *priv_passphrase;
+ int security_level;
+ char *context;
+
void *sess_handle;
c_complain_t complaint;
cdtime_t interval;
sfree (hd->name);
sfree (hd->address);
sfree (hd->community);
+ sfree (hd->username);
+ sfree (hd->auth_passphrase);
+ sfree (hd->priv_passphrase);
+ sfree (hd->context);
sfree (hd->data_list);
sfree (hd);
* csnmp_config
* +-> call_snmp_init_once
* +-> csnmp_config_add_data
- * ! +-> csnmp_config_add_data_type
- * ! +-> csnmp_config_add_data_table
* ! +-> csnmp_config_add_data_instance
* ! +-> csnmp_config_add_data_instance_prefix
* ! +-> csnmp_config_add_data_values
* +-> csnmp_config_add_host
- * +-> csnmp_config_add_host_address
- * +-> csnmp_config_add_host_community
* +-> csnmp_config_add_host_version
* +-> csnmp_config_add_host_collect
+ * +-> csnmp_config_add_host_auth_protocol
+ * +-> csnmp_config_add_host_priv_protocol
+ * +-> csnmp_config_add_host_security_level
*/
static void call_snmp_init_once (void)
{
have_init = 1;
} /* void call_snmp_init_once */
-static int csnmp_config_add_data_type (data_definition_t *dd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Type' needs exactly one string argument.");
- return (-1);
- }
-
- sfree (dd->type);
- dd->type = strdup (ci->values[0].value.string);
- if (dd->type == NULL)
- return (-1);
-
- return (0);
-} /* int csnmp_config_add_data_type */
-
-static int csnmp_config_add_data_table (data_definition_t *dd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("snmp plugin: `Table' needs exactly one boolean argument.");
- return (-1);
- }
-
- dd->is_table = ci->values[0].value.boolean ? 1 : 0;
-
- return (0);
-} /* int csnmp_config_add_data_table */
-
static int csnmp_config_add_data_instance (data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Instance' needs exactly one string argument.");
- return (-1);
- }
+ char buffer[DATA_MAX_NAME_LEN];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
if (dd->is_table)
{
/* Instance is an OID */
dd->instance.oid.oid_len = MAX_OID_LEN;
- if (!read_objid (ci->values[0].value.string,
+ if (!read_objid (buffer,
dd->instance.oid.oid, &dd->instance.oid.oid_len))
{
- ERROR ("snmp plugin: read_objid (%s) failed.",
- ci->values[0].value.string);
+ ERROR ("snmp plugin: read_objid (%s) failed.", buffer);
return (-1);
}
}
else
{
/* Instance is a simple string */
- sstrncpy (dd->instance.string, ci->values[0].value.string,
+ sstrncpy (dd->instance.string, buffer,
sizeof (dd->instance.string));
}
static int csnmp_config_add_data_instance_prefix (data_definition_t *dd,
oconfig_item_t *ci)
{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `InstancePrefix' needs exactly one string argument.");
- return (-1);
- }
+ int status;
if (!dd->is_table)
{
return (-1);
}
- sfree (dd->instance_prefix);
- dd->instance_prefix = strdup (ci->values[0].value.string);
- if (dd->instance_prefix == NULL)
- return (-1);
-
- return (0);
+ status = cf_util_get_string(ci, &dd->instance_prefix);
+ return status;
} /* int csnmp_config_add_data_instance_prefix */
static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci)
return (0);
} /* int csnmp_config_add_data_instance */
-static int csnmp_config_add_data_shift (data_definition_t *dd, oconfig_item_t *ci)
+static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ int i;
+
+ if (ci->values_num < 1)
+ return (0);
+
+ for (i = 0; i < ci->values_num; i++)
{
- WARNING ("snmp plugin: The `Shift' config option needs exactly one number argument.");
- return (-1);
+ if (ci->values[i].type != OCONFIG_TYPE_STRING)
+ {
+ WARNING ("snmp plugin: `Ignore' needs only string argument.");
+ return (-1);
+ }
}
- dd->shift = ci->values[0].value.number;
+ dd->ignores_len = 0;
+ dd->ignores = NULL;
- return (0);
-} /* int csnmp_config_add_data_shift */
+ for (i = 0; i < ci->values_num; ++i)
+ {
+ if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0)
+ {
+ ERROR("snmp plugin: Can't allocate memory");
+ strarray_free(dd->ignores, dd->ignores_len);
+ return (ENOMEM);
+ }
+ }
+ return 0;
+} /* int csnmp_config_add_data_blacklist */
-static int csnmp_config_add_data_scale (data_definition_t *dd, oconfig_item_t *ci)
+static int csnmp_config_add_data_blacklist_match_inverted(data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
{
- WARNING ("snmp plugin: The `Scale' config option needs exactly one number argument.");
+ WARNING ("snmp plugin: `InvertMatch' needs exactly one boolean argument.");
return (-1);
}
- dd->scale = ci->values[0].value.number;
+ dd->invert_match = ci->values[0].value.boolean ? 1 : 0;
return (0);
-} /* int csnmp_config_add_data_scale */
+} /* int csnmp_config_add_data_blacklist_match_inverted */
static int csnmp_config_add_data (oconfig_item_t *ci)
{
int status = 0;
int i;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Data' config option needs exactly one string argument.");
- return (-1);
- }
-
dd = (data_definition_t *) malloc (sizeof (data_definition_t));
if (dd == NULL)
return (-1);
memset (dd, '\0', sizeof (data_definition_t));
- dd->name = strdup (ci->values[0].value.string);
- if (dd->name == NULL)
+ status = cf_util_get_string(ci, &dd->name);
+ if (status != 0)
{
free (dd);
return (-1);
}
+
dd->scale = 1.0;
dd->shift = 0.0;
status = 0;
if (strcasecmp ("Type", option->key) == 0)
- status = csnmp_config_add_data_type (dd, option);
+ status = cf_util_get_string(option, &dd->type);
else if (strcasecmp ("Table", option->key) == 0)
- status = csnmp_config_add_data_table (dd, option);
+ status = cf_util_get_boolean(option, &dd->is_table);
else if (strcasecmp ("Instance", option->key) == 0)
status = csnmp_config_add_data_instance (dd, option);
else if (strcasecmp ("InstancePrefix", option->key) == 0)
else if (strcasecmp ("Values", option->key) == 0)
status = csnmp_config_add_data_values (dd, option);
else if (strcasecmp ("Shift", option->key) == 0)
- status = csnmp_config_add_data_shift (dd, option);
+ status = cf_util_get_double(option, &dd->shift);
else if (strcasecmp ("Scale", option->key) == 0)
- status = csnmp_config_add_data_scale (dd, option);
+ status = cf_util_get_double(option, &dd->scale);
+ else if (strcasecmp ("Ignore", option->key) == 0)
+ status = csnmp_config_add_data_blacklist(dd, option);
+ else if (strcasecmp ("InvertMatch", option->key) == 0)
+ status = csnmp_config_add_data_blacklist_match_inverted(dd, option);
else
{
WARNING ("snmp plugin: Option `%s' not allowed here.", option->key);
sfree (dd->name);
sfree (dd->instance_prefix);
sfree (dd->values);
+ sfree (dd->ignores);
sfree (dd);
return (-1);
}
return (0);
} /* int csnmp_config_add_data */
-static int csnmp_config_add_host_address (host_definition_t *hd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Address' config option needs exactly one string argument.");
- return (-1);
- }
-
- if (hd->address == NULL)
- free (hd->address);
-
- hd->address = strdup (ci->values[0].value.string);
- if (hd->address == NULL)
- return (-1);
-
- DEBUG ("snmp plugin: host = %s; host->address = %s;",
- hd->name, hd->address);
-
- return (0);
-} /* int csnmp_config_add_host_address */
-
-static int csnmp_config_add_host_community (host_definition_t *hd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Community' config option needs exactly one string argument.");
- return (-1);
- }
-
- if (hd->community == NULL)
- free (hd->community);
-
- hd->community = strdup (ci->values[0].value.string);
- if (hd->community == NULL)
- return (-1);
-
- DEBUG ("snmp plugin: host = %s; host->community = %s;",
- hd->name, hd->community);
-
- return (0);
-} /* int csnmp_config_add_host_community */
-
static int csnmp_config_add_host_version (host_definition_t *hd, oconfig_item_t *ci)
{
int version;
}
version = (int) ci->values[0].value.number;
- if ((version != 1) && (version != 2))
+ if ((version < 1) || (version > 3))
{
- WARNING ("snmp plugin: `Version' must either be `1' or `2'.");
+ WARNING ("snmp plugin: `Version' must either be `1', `2', or `3'.");
return (-1);
}
return (0);
} /* int csnmp_config_add_host_collect */
+static int csnmp_config_add_host_auth_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[4];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("MD5", buffer) == 0) {
+ hd->auth_protocol = usmHMACMD5AuthProtocol;
+ hd->auth_protocol_len = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
+ }
+ else if (strcasecmp("SHA", buffer) == 0) {
+ hd->auth_protocol = usmHMACSHA1AuthProtocol;
+ hd->auth_protocol_len = sizeof(usmHMACSHA1AuthProtocol)/sizeof(oid);
+ }
+ else
+ {
+ WARNING ("snmp plugin: The `AuthProtocol' config option must be `MD5' or `SHA'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->auth_protocol = %s;",
+ hd->name, hd->auth_protocol == usmHMACMD5AuthProtocol ? "MD5" : "SHA");
+
+ return (0);
+} /* int csnmp_config_add_host_auth_protocol */
+
+static int csnmp_config_add_host_priv_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[4];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("AES", buffer) == 0)
+ {
+ hd->priv_protocol = usmAESPrivProtocol;
+ hd->priv_protocol_len = sizeof(usmAESPrivProtocol)/sizeof(oid);
+ }
+ else if (strcasecmp("DES", buffer) == 0) {
+ hd->priv_protocol = usmDESPrivProtocol;
+ hd->priv_protocol_len = sizeof(usmDESPrivProtocol)/sizeof(oid);
+ }
+ else
+ {
+ WARNING ("snmp plugin: The `PrivProtocol' config option must be `AES' or `DES'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->priv_protocol = %s;",
+ hd->name, hd->priv_protocol == usmAESPrivProtocol ? "AES" : "DES");
+
+ return (0);
+} /* int csnmp_config_add_host_priv_protocol */
+
+static int csnmp_config_add_host_security_level (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[16];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("noAuthNoPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp("authNoPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp("authPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_AUTHPRIV;
+ else
+ {
+ WARNING ("snmp plugin: The `SecurityLevel' config option must be `noAuthNoPriv', `authNoPriv', or `authPriv'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->security_level = %d;",
+ hd->name, hd->security_level);
+
+ return (0);
+} /* int csnmp_config_add_host_security_level */
+
static int csnmp_config_add_host (oconfig_item_t *ci)
{
host_definition_t *hd;
user_data_t cb_data;
struct timespec cb_interval;
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Host' needs exactly one string argument.");
- return (-1);
- }
-
hd = (host_definition_t *) malloc (sizeof (host_definition_t));
if (hd == NULL)
return (-1);
hd->version = 2;
C_COMPLAIN_INIT (&hd->complaint);
- hd->name = strdup (ci->values[0].value.string);
- if (hd->name == NULL)
- {
- free (hd);
- return (-1);
- }
+ status = cf_util_get_string(ci, &hd->name);
+ if (status != 0)
+ return status;
hd->sess_handle = NULL;
hd->interval = 0;
status = 0;
if (strcasecmp ("Address", option->key) == 0)
- status = csnmp_config_add_host_address (hd, option);
+ status = cf_util_get_string(option, &hd->address);
else if (strcasecmp ("Community", option->key) == 0)
- status = csnmp_config_add_host_community (hd, option);
+ status = cf_util_get_string(option, &hd->community);
else if (strcasecmp ("Version", option->key) == 0)
status = csnmp_config_add_host_version (hd, option);
else if (strcasecmp ("Collect", option->key) == 0)
csnmp_config_add_host_collect (hd, option);
else if (strcasecmp ("Interval", option->key) == 0)
cf_util_get_cdtime (option, &hd->interval);
+ else if (strcasecmp ("Username", option->key) == 0)
+ status = cf_util_get_string(option, &hd->username);
+ else if (strcasecmp ("AuthProtocol", option->key) == 0)
+ status = csnmp_config_add_host_auth_protocol (hd, option);
+ else if (strcasecmp ("PrivacyProtocol", option->key) == 0)
+ status = csnmp_config_add_host_priv_protocol (hd, option);
+ else if (strcasecmp ("AuthPassphrase", option->key) == 0)
+ status = cf_util_get_string(option, &hd->auth_passphrase);
+ else if (strcasecmp ("PrivacyPassphrase", option->key) == 0)
+ status = cf_util_get_string(option, &hd->priv_passphrase);
+ else if (strcasecmp ("SecurityLevel", option->key) == 0)
+ status = csnmp_config_add_host_security_level (hd, option);
+ else if (strcasecmp ("Context", option->key) == 0)
+ status = cf_util_get_string(option, &hd->context);
else
{
WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key);
status = -1;
break;
}
- if (hd->community == NULL)
+ if (hd->community == NULL && hd->version < 3)
{
WARNING ("snmp plugin: `Community' not given for host `%s'", hd->name);
status = -1;
break;
}
+ if (hd->version == 3)
+ {
+ if (hd->username == NULL)
+ {
+ WARNING ("snmp plugin: `Username' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->security_level == 0)
+ {
+ WARNING ("snmp plugin: `SecurityLevel' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->security_level == SNMP_SEC_LEVEL_AUTHNOPRIV || hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ if (hd->auth_protocol == NULL)
+ {
+ WARNING ("snmp plugin: `AuthProtocol' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->auth_passphrase == NULL)
+ {
+ WARNING ("snmp plugin: `AuthPassphrase' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ }
+ if (hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ if (hd->priv_protocol == NULL)
+ {
+ WARNING ("snmp plugin: `PrivacyProtocol' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->priv_passphrase == NULL)
+ {
+ WARNING ("snmp plugin: `PrivacyPassphrase' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ }
+ }
break;
} /* while (status == 0) */
static void csnmp_host_open_session (host_definition_t *host)
{
struct snmp_session sess;
+ int error;
if (host->sess_handle != NULL)
csnmp_host_close_session (host);
snmp_sess_init (&sess);
sess.peername = host->address;
- sess.community = (u_char *) host->community;
- sess.community_len = strlen (host->community);
- sess.version = (host->version == 1) ? SNMP_VERSION_1 : SNMP_VERSION_2c;
+ switch (host->version)
+ {
+ case 1:
+ sess.version = SNMP_VERSION_1;
+ break;
+ case 3:
+ sess.version = SNMP_VERSION_3;
+ break;
+ default:
+ sess.version = SNMP_VERSION_2c;
+ break;
+ }
+
+ if (host->version == 3)
+ {
+ sess.securityName = host->username;
+ sess.securityNameLen = strlen (host->username);
+ sess.securityLevel = host->security_level;
+
+ if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ sess.securityAuthProto = host->auth_protocol;
+ sess.securityAuthProtoLen = host->auth_protocol_len;
+ sess.securityAuthKeyLen = USM_AUTH_KU_LEN;
+ error = generate_Ku (sess.securityAuthProto,
+ sess.securityAuthProtoLen,
+ (u_char *) host->auth_passphrase,
+ strlen(host->auth_passphrase),
+ sess.securityAuthKey,
+ &sess.securityAuthKeyLen);
+ if (error != SNMPERR_SUCCESS) {
+ ERROR ("snmp plugin: host %s: Error generating Ku from auth_passphrase. (Error %d)", host->name, error);
+ }
+ }
+
+ if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ sess.securityPrivProto = host->priv_protocol;
+ sess.securityPrivProtoLen = host->priv_protocol_len;
+ sess.securityPrivKeyLen = USM_PRIV_KU_LEN;
+ error = generate_Ku (sess.securityAuthProto,
+ sess.securityAuthProtoLen,
+ (u_char *) host->priv_passphrase,
+ strlen(host->priv_passphrase),
+ sess.securityPrivKey,
+ &sess.securityPrivKeyLen);
+ if (error != SNMPERR_SUCCESS) {
+ ERROR ("snmp plugin: host %s: Error generating Ku from priv_passphrase. (Error %d)", host->name, error);
+ }
+ }
+
+ if (host->context != NULL)
+ {
+ sess.contextName = host->context;
+ sess.contextNameLen = strlen (host->context);
+ }
+ }
+ else /* SNMPv1/2 "authenticates" with community string */
+ {
+ sess.community = (u_char *) host->community;
+ sess.community_len = strlen (host->community);
+ }
/* snmp_sess_open will copy the `struct snmp_session *'. */
host->sess_handle = snmp_sess_open (&sess);
struct variable_list *vb;
oid_t vb_name;
int status;
+ uint32_t i;
+ uint32_t is_matched;
/* Set vb on the last variable */
for (vb = res->variables;
char *ptr;
csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
-
+ is_matched = 0;
+ for (i = 0; i < dd->ignores_len; i++)
+ {
+ status = fnmatch(dd->ignores[i], il->instance, 0);
+ if (status == 0)
+ {
+ if (dd->invert_match == 0)
+ {
+ sfree(il);
+ return 0;
+ }
+ else
+ {
+ is_matched = 1;
+ break;
+ }
+ }
+ }
+ if (dd->invert_match != 0 && is_matched == 0)
+ {
+ sfree(il);
+ return 0;
+ }
for (ptr = il->instance; *ptr != '\0'; ptr++)
{
if ((*ptr > 0) && (*ptr < 32))
snmp_free_pdu (res);
res = NULL;
+ if (req != NULL)
+ snmp_free_pdu (req);
+ req = NULL;
+
if (status == 0)
csnmp_dispatch_table (host, data, instance_list_head, value_list_head);
sfree (data_this->name);
sfree (data_this->type);
sfree (data_this->values);
+ sfree (data_this->ignores);
sfree (data_this);
data_this = data_next;
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Author:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Michael Stapelberg <michael+git at stapelberg.de>
**/
/* sys/socket.h is necessary to compile when using netlink on older systems. */
# include <sys/socket.h>
# include <linux/netlink.h>
+ #if HAVE_LINUX_INET_DIAG_H
# include <linux/inet_diag.h>
+ #endif
# include <sys/socket.h>
# include <arpa/inet.h>
/* #endif KERNEL_LINUX */
#endif /* KERNEL_AIX */
#if KERNEL_LINUX
+ #if HAVE_STRUCT_LINUX_INET_DIAG_REQ
struct nlreq {
struct nlmsghdr nlh;
struct inet_diag_req r;
};
+ #endif
static const char *tcp_state[] =
{
"CLOSED",
"LISTEN",
"SYN_SENT",
- "SYN_RCVD",
+ "SYN_RECV",
"ESTABLISHED",
"CLOSE_WAIT",
- "FIN_WAIT_1",
+ "FIN_WAIT1",
"CLOSING",
"LAST_ACK",
- "FIN_WAIT_2",
+ "FIN_WAIT2",
"TIME_WAIT"
};
static port_entry_t *port_list_head = NULL;
#if KERNEL_LINUX
+ #if HAVE_STRUCT_LINUX_INET_DIAG_REQ
+ /* This depends on linux inet_diag_req because if this structure is missing,
+ * sequence_number is useless and we get a compilation warning.
+ */
static uint32_t sequence_number = 0;
+ #endif
enum
{
* zero on other errors. */
static int conn_read_netlink (void)
{
+ #if HAVE_STRUCT_LINUX_INET_DIAG_REQ
int fd;
struct sockaddr_nl nladdr;
struct nlreq req;
/* Not reached because the while() loop above handles the exit condition. */
return (0);
+ #else
+ return (1);
+ #endif /* HAVE_STRUCT_LINUX_INET_DIAG_REQ */
} /* int conn_read_netlink */
static int conn_handle_line (char *buffer)
/**
* collectd - src/utils_vl_lookup.c
- * Copyright (C) 2012 Florian Forster
+ * Copyright (C) 2012 Florian Forster
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
#include "collectd.h"
+ #include <pthread.h>
#include <regex.h>
#include "common.h"
struct user_class_s
{
+ pthread_mutex_t lock;
void *user_class;
identifier_match_t match;
user_obj_t *user_obj_list; /* list of user_obj */
return (0);
} /* }}} int lu_copy_ident_to_match */
+ /* user_class->lock must be held when calling this function */
static void *lu_create_user_obj (lookup_t *obj, /* {{{ */
data_set_t const *ds, value_list_t const *vl,
user_class_t *user_class)
return (user_obj);
} /* }}} void *lu_create_user_obj */
+ /* user_class->lock must be held when calling this function */
static user_obj_t *lu_find_user_obj (user_class_t *user_class, /* {{{ */
value_list_t const *vl)
{
|| !lu_part_matches (&user_class->match.host, vl->host))
return (1);
+ pthread_mutex_lock (&user_class->lock);
user_obj = lu_find_user_obj (user_class, vl);
if (user_obj == NULL)
{
/* call lookup_class_callback_t() and insert into the list of user objects. */
user_obj = lu_create_user_obj (obj, ds, vl, user_class);
+ pthread_mutex_unlock (&user_class->lock);
if (user_obj == NULL)
return (-1);
}
+ pthread_mutex_unlock (&user_class->lock);
status = obj->cb_user_obj (ds, vl,
user_class->user_class, user_obj->user_obj);
identifier_match_t const *match = &user_class_list->entry.match;
/* Lookup user_class_list from the per-plugin structure. If this is the first
- * user_class to be added, the blocks return immediately. Otherwise they will
+ * user_class to be added, the block returns immediately. Otherwise they will
* set "ptr" to non-NULL. */
if (match->plugin.is_regex)
{
lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list);
user_class_list->entry.user_obj_list = NULL;
+ pthread_mutex_destroy (&user_class_list->entry.lock);
sfree (user_class_list);
user_class_list = next;
return (ENOMEM);
}
memset (user_class_obj, 0, sizeof (*user_class_obj));
+ pthread_mutex_init (&user_class_obj->entry.lock, /* attr = */ NULL);
user_class_obj->entry.user_class = user_class;
lu_copy_ident_to_match (&user_class_obj->entry.match, ident, group_by);
user_class_obj->entry.user_obj_list = NULL;
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
* Doug MacEachern <dougm@hyperic.com>
* Paul Sadauskas <psadauskas@gmail.com>
**/
char *user;
char *pass;
char *credentials;
- int verify_peer;
- int verify_host;
+ _Bool verify_peer;
+ _Bool verify_host;
char *cacert;
- int store_rates;
+ char *capath;
+ char *clientkey;
+ char *clientcert;
+ char *clientkeypass;
+ long sslversion;
+ _Bool store_rates;
#define WH_FORMAT_COMMAND 0
#define WH_FORMAT_JSON 1
}
curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
headers = NULL;
headers = curl_slist_append (headers, "Accept: */*");
curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYPEER, (long) cb->verify_peer);
curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYHOST,
cb->verify_host ? 2L : 0L);
+ curl_easy_setopt (cb->curl, CURLOPT_SSLVERSION, cb->sslversion);
if (cb->cacert != NULL)
curl_easy_setopt (cb->curl, CURLOPT_CAINFO, cb->cacert);
+ if (cb->capath != NULL)
+ curl_easy_setopt (cb->curl, CURLOPT_CAPATH, cb->capath);
+
+ if (cb->clientkey != NULL && cb->clientcert != NULL)
+ {
+ curl_easy_setopt (cb->curl, CURLOPT_SSLKEY, cb->clientkey);
+ curl_easy_setopt (cb->curl, CURLOPT_SSLCERT, cb->clientcert);
+
+ if (cb->clientkeypass != NULL)
+ curl_easy_setopt (cb->curl, CURLOPT_SSLKEYPASSWD, cb->clientkeypass);
+ }
wh_reset_buffer (cb);
sfree (cb->pass);
sfree (cb->credentials);
sfree (cb->cacert);
+ sfree (cb->capath);
+ sfree (cb->clientkey);
+ sfree (cb->clientcert);
+ sfree (cb->clientkeypass);
sfree (cb);
} /* }}} void wh_callback_free */
return (status);
} /* }}} int wh_write */
-static int config_set_string (char **ret_string, /* {{{ */
- oconfig_item_t *ci)
-{
- char *string;
-
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("write_http plugin: The `%s' config option "
- "needs exactly one string argument.", ci->key);
- return (-1);
- }
-
- string = strdup (ci->values[0].value.string);
- if (string == NULL)
- {
- ERROR ("write_http plugin: strdup failed.");
- return (-1);
- }
-
- if (*ret_string != NULL)
- free (*ret_string);
- *ret_string = string;
-
- return (0);
-} /* }}} int config_set_string */
-
-static int config_set_boolean (int *dest, oconfig_item_t *ci) /* {{{ */
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("write_http plugin: The `%s' config option "
- "needs exactly one boolean argument.", ci->key);
- return (-1);
- }
-
- *dest = ci->values[0].value.boolean ? 1 : 0;
-
- return (0);
-} /* }}} int config_set_boolean */
-
static int config_set_format (wh_callback_t *cb, /* {{{ */
oconfig_item_t *ci)
{
}
return (0);
-} /* }}} int config_set_string */
+} /* }}} int config_set_format */
static int wh_config_url (oconfig_item_t *ci) /* {{{ */
{
return (-1);
}
memset (cb, 0, sizeof (*cb));
- cb->location = NULL;
- cb->user = NULL;
- cb->pass = NULL;
- cb->credentials = NULL;
cb->verify_peer = 1;
cb->verify_host = 1;
- cb->cacert = NULL;
cb->format = WH_FORMAT_COMMAND;
- cb->curl = NULL;
+ cb->sslversion = CURL_SSLVERSION_DEFAULT;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
- config_set_string (&cb->location, ci);
+ cf_util_get_string (ci, &cb->location);
if (cb->location == NULL)
return (-1);
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("User", child->key) == 0)
- config_set_string (&cb->user, child);
+ cf_util_get_string (child, &cb->user);
else if (strcasecmp ("Password", child->key) == 0)
- config_set_string (&cb->pass, child);
+ cf_util_get_string (child, &cb->pass);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
- config_set_boolean (&cb->verify_peer, child);
+ cf_util_get_boolean (child, &cb->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
- config_set_boolean (&cb->verify_host, child);
+ cf_util_get_boolean (child, &cb->verify_host);
else if (strcasecmp ("CACert", child->key) == 0)
- config_set_string (&cb->cacert, child);
+ cf_util_get_string (child, &cb->cacert);
+ else if (strcasecmp ("CAPath", child->key) == 0)
+ cf_util_get_string (child, &cb->capath);
+ else if (strcasecmp ("ClientKey", child->key) == 0)
+ cf_util_get_string (child, &cb->clientkey);
+ else if (strcasecmp ("ClientCert", child->key) == 0)
+ cf_util_get_string (child, &cb->clientcert);
+ else if (strcasecmp ("ClientKeyPass", child->key) == 0)
+ cf_util_get_string (child, &cb->clientkeypass);
+ else if (strcasecmp ("SSLVersion", child->key) == 0)
+ {
+ char *value = NULL;
+
+ cf_util_get_string (child, &value);
+
+ if (value == NULL || strcasecmp ("default", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_DEFAULT;
+ else if (strcasecmp ("SSLv2", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_SSLv2;
+ else if (strcasecmp ("SSLv3", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_SSLv3;
+ else if (strcasecmp ("TLSv1", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1;
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 34)
+ else if (strcasecmp ("TLSv1_0", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_0;
+ else if (strcasecmp ("TLSv1_1", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_1;
+ else if (strcasecmp ("TLSv1_2", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_2;
+#endif
+ else
+ ERROR ("write_http plugin: Invalid SSLVersion "
+ "option: %s.", value);
+
+ sfree(value);
+ }
else if (strcasecmp ("Format", child->key) == 0)
config_set_format (cb, child);
else if (strcasecmp ("StoreRates", child->key) == 0)
- config_set_boolean (&cb->store_rates, child);
+ cf_util_get_boolean (child, &cb->store_rates);
else
{
ERROR ("write_http plugin: Invalid configuration "
return (0);
} /* }}} int wh_config */
+ static int wh_init (void) /* {{{ */
+ {
+ /* Call this while collectd is still single-threaded to avoid
+ * initialization issues in libgcrypt. */
+ curl_global_init (CURL_GLOBAL_SSL);
+ return (0);
+ } /* }}} int wh_init */
+
void module_register (void) /* {{{ */
{
plugin_register_complex_config ("write_http", wh_config);
+ plugin_register_init ("write_http", wh_init);
} /* }}} void module_register */
/* vim: set fdm=marker sw=8 ts=8 tw=78 et : */
/**
* collectd - src/write_riemann.c
- *
* Copyright (C) 2012,2013 Pierre-Yves Ritschard
* Copyright (C) 2013 Florian octo Forster
*
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
- * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
* Authors:
* Pierre-Yves Ritschard <pyr at spootnik.org>
#define RIEMANN_PORT "5555"
#define RIEMANN_TTL_FACTOR 2.0
+int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
+
struct riemann_host {
char *name;
#define F_CONNECT 0x01
uint8_t flags;
pthread_mutex_t lock;
- _Bool notifications;
- _Bool check_thresholds;
++ _Bool notifications;
++ _Bool check_thresholds;
_Bool store_rates;
_Bool always_append_ds;
char *node;
static char **riemann_tags;
static size_t riemann_tags_num;
+static char **riemann_attrs;
+static size_t riemann_attrs_num;
static void riemann_event_protobuf_free (Event *event) /* {{{ */
{
sfree (event);
} /* }}} void riemann_event_protobuf_free */
- static void riemann_msg_protobuf_free (Msg *msg) /* {{{ */
+ static void riemann_msg_protobuf_free(Msg *msg) /* {{{ */
{
size_t i;
}
host->flags |= F_CONNECT;
- DEBUG("write_riemann plugin: got a succesful connection for: %s:%s",
+ DEBUG("write_riemann plugin: got a successful connection for: %s:%s",
node, service);
break;
}
return (strarray_add (&event->tags, &event->n_tags, tag));
} /* }}} int riemann_event_add_tag */
- static int riemann_event_add_attribute (Event *event, /* {{{ */
+ static int riemann_event_add_attribute(Event *event, /* {{{ */
char const *key, char const *value)
{
Attribute **new_attributes;
return (0);
} /* }}} int riemann_event_add_attribute */
- static Msg *riemann_notification_to_protobuf (struct riemann_host *host, /* {{{ */
+ static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ */
notification_t const *n)
{
Msg *msg;
riemann_event_add_attribute (event, "type_instance",
n->type_instance);
+ for (i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_add_attribute(event,
+ riemann_attrs[i],
+ riemann_attrs[i +1]);
+
for (i = 0; i < riemann_tags_num; i++)
riemann_event_add_tag (event, riemann_tags[i]);
n->type, n->type_instance);
event->service = strdup (&service_buffer[1]);
- /* Pull in values from threshold */
+ if (n->message[0] != 0)
+ riemann_event_add_attribute (event, "description", n->message);
+
+ /* Pull in values from threshold and add extra attributes */
for (meta = n->meta; meta != NULL; meta = meta->next)
{
- if (strcasecmp ("CurrentValue", meta->name) != 0)
+ if (strcasecmp ("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE)
+ {
+ event->metric_d = meta->nm_value.nm_double;
+ event->has_metric_d = 1;
continue;
+ }
- event->metric_d = meta->nm_value.nm_double;
- event->has_metric_d = 1;
- break;
+ if (meta->type == NM_TYPE_STRING) {
+ riemann_event_add_attribute (event, meta->name, meta->nm_value.nm_string);
+ continue;
+ }
}
DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
return (msg);
} /* }}} Msg *riemann_notification_to_protobuf */
- static Event *riemann_value_to_protobuf (struct riemann_host const *host, /* {{{ */
+ static Event *riemann_value_to_protobuf(struct riemann_host const *host, /* {{{ */
data_set_t const *ds,
value_list_t const *vl, size_t index,
- gauge_t const *rates)
+ gauge_t const *rates,
+ int status)
{
Event *event;
char name_buffer[5 * DATA_MAX_NAME_LEN];
event->time = CDTIME_T_TO_TIME_T (vl->time);
event->has_time = 1;
- if (host->check_thresholds) {
- switch (status) {
- case STATE_OKAY:
- event->state = strdup("ok");
- break;
- case STATE_ERROR:
- event->state = strdup("critical");
- break;
- case STATE_WARNING:
- event->state = strdup("warning");
- break;
- case STATE_MISSING:
- event->state = strdup("unknown");
- break;
- }
- }
++ if (host->check_thresholds) {
++ switch (status) {
++ case STATE_OKAY:
++ event->state = strdup("ok");
++ break;
++ case STATE_ERROR:
++ event->state = strdup("critical");
++ break;
++ case STATE_WARNING:
++ event->state = strdup("warning");
++ break;
++ case STATE_MISSING:
++ event->state = strdup("unknown");
++ break;
++ }
++ }
+
ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor;
event->ttl = (float) ttl;
event->has_ttl = 1;
riemann_event_add_attribute (event, "ds_index", ds_index);
}
+ for (i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_add_attribute(event,
+ riemann_attrs[i],
+ riemann_attrs[i +1]);
+
for (i = 0; i < riemann_tags_num; i++)
riemann_event_add_tag (event, riemann_tags[i]);
return (event);
} /* }}} Event *riemann_value_to_protobuf */
-static Msg *riemann_value_list_to_protobuf(struct riemann_host const *host, /* {{{ */
- data_set_t const *ds,
- value_list_t const *vl)
+static Msg *riemann_value_list_to_protobuf (struct riemann_host const *host, /* {{{ */
+ data_set_t const *ds,
+ value_list_t const *vl,
+ int *statuses)
{
Msg *msg;
size_t i;
for (i = 0; i < msg->n_events; i++)
{
msg->events[i] = riemann_value_to_protobuf (host, ds, vl,
- (int) i, rates);
+ (int) i, rates, statuses[i]);
if (msg->events[i] == NULL)
{
riemann_msg_protobuf_free (msg);
struct riemann_host *host = ud->data;
Msg *msg;
- if (!host->notifications)
- return 0;
++ if (!host->notifications)
++ return 0;
+
msg = riemann_notification_to_protobuf (host, n);
if (msg == NULL)
return (-1);
user_data_t *ud)
{
int status;
+ int statuses[vl->values_len];
struct riemann_host *host = ud->data;
Msg *msg;
- if (host->check_thresholds)
- write_riemann_threshold_check(ds, vl, statuses);
- msg = riemann_value_list_to_protobuf (host, ds, vl);
++ if (host->check_thresholds)
++ write_riemann_threshold_check(ds, vl, statuses);
+ msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
if (msg == NULL)
return (-1);
host->reference_count = 1;
host->node = NULL;
host->service = NULL;
- host->notifications = 1;
- host->check_thresholds = 0;
++ host->notifications = 1;
++ host->check_thresholds = 0;
host->store_rates = 1;
host->always_append_ds = 0;
host->use_tcp = 0;
status = cf_util_get_string (child, &host->node);
if (status != 0)
break;
- } else if (strcasecmp ("Notifications", child->key) == 0) {
- status = cf_util_get_boolean(child, &host->notifications);
- if (status != 0)
- break;
- } else if (strcasecmp ("CheckThresholds", child->key) == 0) {
- status = cf_util_get_boolean(child, &host->check_thresholds);
- if (status != 0)
- break;
++ } else if (strcasecmp ("Notifications", child->key) == 0) {
++ status = cf_util_get_boolean(child, &host->notifications);
++ if (status != 0)
++ break;
++ } else if (strcasecmp ("CheckThresholds", child->key) == 0) {
++ status = cf_util_get_boolean(child, &host->check_thresholds);
++ if (status != 0)
++ break;
} else if (strcasecmp ("Port", child->key) == 0) {
status = cf_util_get_service (child, &host->service);
if (status != 0) {
if (strcasecmp("Node", child->key) == 0) {
riemann_config_node (child);
+ } else if (strcasecmp(child->key, "attribute") == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("riemann attributes need both a key and a value.");
+ return (-1);
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("riemann attribute needs string arguments.");
+ return (-1);
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ return (-1);
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ return (-1);
+ }
+ strarray_add(&riemann_attrs, &riemann_attrs_num, key);
+ strarray_add(&riemann_attrs, &riemann_attrs_num, val);
+ DEBUG("write_riemann: got attr: %s => %s", key, val);
+ sfree(key);
+ sfree(val);
} else if (strcasecmp(child->key, "tag") == 0) {
char *tmp = NULL;
status = cf_util_get_string(child, &tmp);
child->key);
}
}
- return 0;
+ return (0);
} /* }}} int riemann_config */
void module_register(void)
#!/usr/bin/env bash
- DEFAULT_VERSION="5.4.0.git"
+ DEFAULT_VERSION="5.4.1.git"
-VERSION="`git describe 2> /dev/null | sed -e 's/^collectd-//'`"
+VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
if test -z "$VERSION"; then
VERSION="$DEFAULT_VERSION"