Kevin Bowling <kbowling at llnw.com>
- write_tsdb plugin for http://opentsdb.net/
+Kimo Rosenbaum <kimor79 at yahoo.com>
+ - openldap plugin.
+
Kris Nielander <nielander at fox-it.com>
- tail_csv plugin.
- RPM specfile update.
- libmnl support in the netlink plugin.
- linux support in the zfs_arc plugin.
+ - openldap plugin.
Marco Chiappero <marco at absence.it>
- uptime plugin.
- python plugin.
Tim Laszlo <tim.laszlo at gmail.com>
- - drbd plugin
+ - drbd plugin.
Thomas Meson <zllak at hycik.org>
- Graphite support for the AMQP plugin.
Tommie Gannert <d00-tga at d.kth.se>
- PID-file patch.
+Vincent Bernat <vincent at bernat.im>
+ - smart plugin.
+
Vincent Stehlé <vincent.stehle at free.fr>
- hddtemp plugin.
Read onewire sensors using the owcapu library of the owfs project.
Please read in collectd.conf(5) why this plugin is experimental.
+ - openldap
+ Read monitoring information from OpenLDAP's cn=Monitor subtree.
+
- openvpn
RX and TX of each client in openvpn-status.log (status-version 2).
<http://openvpn.net/index.php/documentation/howto.html>
to have its measurements fed to collectd. This includes multimeters,
sound level meters, thermometers, and much more.
+ - smart
+ Collect SMART statistics, notably load cycle count, temperature
+ and bad sectors.
+
- snmp
Read values from SNMP (Simple Network Management Protocol) enabled
network devices such as switches, routers, thermometers, rack monitoring
particular.
<http://developer.apple.com/corefoundation/>
+ * libatasmart (optional)
+ Used by the `smart' plugin.
+ <http://git.0pointer.de/?p=libatasmart.git>
+
* libclntsh (optional)
Used by the `oracle' plugin.
libjvm” below.
<http://openjdk.java.net/> (and others)
+ * libldap (optional)
+ Used by the `openldap' plugin.
+ <http://www.openldap.org/>
+
* liblvm2 (optional)
Used by the `lvm' plugin.
<ftp://sources.redhat.com/pub/lvm2/>
#endif
])
-AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h kvm.h wordexp.h locale.h)
+AC_CHECK_HEADERS(pwd.h grp.h sys/un.h ctype.h limits.h xfs/xqm.h fs_info.h fshelp.h paths.h mntent.h mnttab.h sys/fstyp.h sys/fs_types.h sys/mntent.h sys/mnttab.h sys/statfs.h sys/statvfs.h sys/vfs.h sys/vfstab.h sys/vmmeter.h kvm.h wordexp.h locale.h)
# For the dns plugin
AC_CHECK_HEADERS(arpa/nameser.h)
AM_CONDITIONAL(BUILD_WITH_JAVA, test "x$with_java" = "xyes")
# }}}
+# --with-libldap {{{
+AC_ARG_WITH(libldap, [AS_HELP_STRING([--with-libldap@<:@=PREFIX@:>@], [Path to libldap.])],
+[
+ if test "x$withval" = "xyes"
+ then
+ with_libldap="yes"
+ else if test "x$withval" = "xno"
+ then
+ with_libldap="no"
+ else
+ with_libldap="yes"
+ LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS -I$withval/include"
+ LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS -L$withval/lib"
+ fi; fi
+],
+[with_libldap="yes"])
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+
+CPPFLAGS="$CPPFLAGS $LIBLDAP_CPPFLAGS"
+LDFLAGS="$LDFLAGS $LIBLDAP_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+ if test "x$LIBLDAP_CPPFLAGS" != "x"
+ then
+ AC_MSG_NOTICE([libldap CPPFLAGS: $LIBLDAP_CPPFLAGS])
+ fi
+ AC_CHECK_HEADERS(ldap.h,
+ [with_libldap="yes"],
+ [with_libldap="no ('ldap.h' not found)"])
+fi
+if test "x$with_libldap" = "xyes"
+then
+ if test "x$LIBLDAP_LDFLAGS" != "x"
+ then
+ AC_MSG_NOTICE([libldap LDFLAGS: $LIBLDAP_LDFLAGS])
+ fi
+ AC_CHECK_LIB(ldap, ldap_initialize,
+ [with_libldap="yes"],
+ [with_libldap="no (symbol 'ldap_initialize' not found)"])
+
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libldap" = "xyes"
+then
+ BUILD_WITH_LIBLDAP_CPPFLAGS="$LIBLDAP_CPPFLAGS"
+ BUILD_WITH_LIBLDAP_LDFLAGS="$LIBLDAP_LDFLAGS"
+ AC_SUBST(BUILD_WITH_LIBLDAP_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBLDAP_LDFLAGS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBLDAP, test "x$with_libldap" = "xyes")
+# }}}
+
# --with-liblvm2app {{{
with_liblvm2app_cppflags=""
with_liblvm2app_ldflags=""
LDFLAGS="$SAVE_LDFLAGS"
fi
+if test "x$with_libstatgrab" = "xyes"
+then
+ SAVE_CFLAGS="$CFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+
+ CFLAGS="$CFLAGS $with_libstatgrab_cflags"
+ LDFLAGS="$LDFLAGS $with_libstatgrab_ldflags"
+
+ AC_CACHE_CHECK([if libstatgrab >= 0.90],
+ [c_cv_have_libstatgrab_0_90],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[[
+#include <stdio.h>
+#include <statgrab.h>
+]]],
+[[[
+ if (sg_init()) return 0;
+]]]
+ )],
+ [c_cv_have_libstatgrab_0_90="no"],
+ [c_cv_have_libstatgrab_0_90="yes"]
+ )
+ )
+
+ CFLAGS="$SAVE_CFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+
AM_CONDITIONAL(BUILD_WITH_LIBSTATGRAB, test "x$with_libstatgrab" = "xyes")
if test "x$with_libstatgrab" = "xyes"
then
BUILD_WITH_LIBSTATGRAB_LDFLAGS="$with_libstatgrab_ldflags"
AC_SUBST(BUILD_WITH_LIBSTATGRAB_CFLAGS)
AC_SUBST(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
+ if test "x$c_cv_have_libstatgrab_0_90" = "xyes"
+ then
+ AC_DEFINE(HAVE_LIBSTATGRAB_0_90, 1, [Define to 1 if libstatgrab version >= 0.90])
+ fi
fi
# }}}
fi
# }}}
+# --with-libatasmart {{{
+with_libatasmart_cppflags=""
+with_libatasmart_ldflags=""
+AC_ARG_WITH(libatasmart, [AS_HELP_STRING([--with-libatasmart@<:@=PREFIX@:>@], [Path to libatasmart.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libatasmart_cppflags="-I$withval/include"
+ with_libatasmart_ldflags="-L$withval/lib"
+ with_libatasmart="yes"
+ else
+ with_libatasmart="$withval"
+ fi
+],
+[
+ if test "x$ac_system" = "xLinux"
+ then
+ with_libatasmart="yes"
+ else
+ with_libatasmart="no (Linux only library)"
+ fi
+])
+if test "x$with_libatasmart" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+
+ AC_CHECK_HEADERS(atasmart.h, [with_libatasmart="yes"], [with_libatasmart="no (atasmart.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libatasmart_cppflags"
+ LDFLAGS="$LDFLAGS $with_libatasmart_ldflags"
+
+ AC_CHECK_LIB(atasmart, sk_disk_open, [with_libatasmart="yes"], [with_libatasmart="no (Symbol 'sk_disk_open' not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libatasmart" = "xyes"
+then
+ BUILD_WITH_LIBATASMART_CPPFLAGS="$with_libatasmart_cppflags"
+ BUILD_WITH_LIBATASMART_LDFLAGS="$with_libatasmart_ldflags"
+ BUILD_WITH_LIBATASMART_LIBS="-latasmart"
+ AC_SUBST(BUILD_WITH_LIBATASMART_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBATASMART_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBATASMART_LIBS)
+ AC_DEFINE(HAVE_LIBATASMART, 1, [Define if libatasmart is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBATASMART, test "x$with_libatasmart" = "xyes")
+# }}}
+
PKG_CHECK_MODULES([LIBNOTIFY], [libnotify],
[with_libnotify="yes"],
[if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
AC_PLUGIN([olsrd], [yes], [olsrd statistics])
AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
+AC_PLUGIN([openldap], [$with_libldap], [OpenLDAP statistics])
AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics])
AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin])
AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter])
AC_PLUGIN([sensors], [$with_libsensors], [lm_sensors statistics])
AC_PLUGIN([serial], [$plugin_serial], [serial port traffic])
AC_PLUGIN([sigrok], [$with_libsigrok], [sigrok acquisition sources])
+AC_PLUGIN([smart], [$with_libatasmart], [SMART statistics])
AC_PLUGIN([snmp], [$with_libnetsnmp], [SNMP querying plugin])
AC_PLUGIN([statsd], [yes], [StatsD plugin])
AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
Libraries:
intel mic . . . . . . $with_mic
libaquaero5 . . . . . $with_libaquaero5
+ libatasmart . . . . . $with_libatasmart
libcurl . . . . . . . $with_libcurl
libdbi . . . . . . . $with_libdbi
libhiredis . . . . . $with_libhiredis
libjvm . . . . . . . $with_java
libkstat . . . . . . $with_kstat
libkvm . . . . . . . $with_libkvm
+ libldap . . . . . . . $with_libldap
liblvm2app . . . . . $with_liblvm2app
libmemcached . . . . $with_libmemcached
libmnl . . . . . . . $with_libmnl
nut . . . . . . . . . $enable_nut
olsrd . . . . . . . . $enable_olsrd
onewire . . . . . . . $enable_onewire
+ openldap . . . . . . $enable_openldap
openvpn . . . . . . . $enable_openvpn
oracle . . . . . . . $enable_oracle
perl . . . . . . . . $enable_perl
sensors . . . . . . . $enable_sensors
serial . . . . . . . $enable_serial
sigrok . . . . . . . $enable_sigrok
+ smart . . . . . . . . $enable_smart
snmp . . . . . . . . $enable_snmp
statsd . . . . . . . $enable_statsd
swap . . . . . . . . $enable_swap
%{?el6:%global _has_libmodbus 1}
%{?el6:%global _has_libudev 1}
%{?el6:%global _has_iproute 1}
+%{?el6:%global _has_atasmart 1}
%{?el7:%global _has_libyajl 1}
%{?el7:%global _has_recent_libpcap 1}
%{?el7:%global _has_varnish4 1}
%{?el7:%global _has_broken_libmemcached 1}
%{?el7:%global _has_iproute 1}
+%{?el7:%global _has_atasmart 1}
# plugins enabled by default
%define with_aggregation 0%{!?_without_aggregation:1}
%define with_numa 0%{!?_without_numa:1}
%define with_nut 0%{!?_without_nut:1}
%define with_olsrd 0%{!?_without_olsrd:1}
+%define with_openldap 0%{!?_without_openldap:1}
%define with_openvpn 0%{!?_without_openvpn:1}
%define with_perl 0%{!?_without_perl:1}
%define with_pinba 0%{!?_without_pinba:1}
%define with_rrdtool 0%{!?_without_rrdtool:1}
%define with_sensors 0%{!?_without_sensors:1}
%define with_serial 0%{!?_without_serial:1}
+%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
%define with_snmp 0%{!?_without_snmp:1}
%define with_statsd 0%{!?_without_statsd:1}
%define with_swap 0%{!?_without_swap:1}
This plugin for collectd provides Network UPS Tools support.
%endif
+%if %{with_openldap}
+%package openldap
+Summary: Openldap plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: openldap-devel
+%description openldap
+This plugin reads monitoring information from OpenLDAP's cn=Monitor subtree.
+%endif
+
%if %{with_perl}
%package perl
Summary: Perl plugin for collectd
thermometers, and much more.
%endif
+%if %{with_smart}
+%package smart
+Summary: SMART plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: libatasmart-devel
+%description smart
+Collect SMART statistics, notably load cycle count, temperature and bad
+sectors.
+%endif
+
%if %{with_snmp}
%package snmp
Summary: SNMP plugin for collectd
%define _with_onewire --disable-onewire
%endif
+%if %{with_openldap}
+%define _with_openldap --enable-openldap
+%else
+%define _with_openldap --disable-openldap
+%endif
+
%if %{with_openvpn}
%define _with_openvpn --enable-openvpn
%else
%define _with_sigrok --disable-sigrok
%endif
+%if %{with_smart}
+%define _with_smart --enable-smart
+%else
+%define _with_smart --disable-smart
+%endif
+
%if %{with_snmp}
%define _with_snmp --enable-snmp
%else
%{?_with_notify_email} \
%{?_with_nut} \
%{?_with_onewire} \
+ %{?_with_openldap} \
%{?_with_oracle} \
%{?_with_perl} \
%{?_with_pf} \
%{?_with_rrdtool} \
%{?_with_sensors} \
%{?_with_sigrok} \
+ %{?_with_smart} \
%{?_with_snmp} \
%{?_with_tape} \
%{?_with_tokyotyrant} \
%{_libdir}/%{name}/nut.so
%endif
+%if %{with_openldap}
+%files openldap
+%{_libdir}/%{name}/openldap.so
+%endif
+
%if %{with_perl}
%files perl
%doc perl-examples/*
%{_libdir}/%{name}/sigrok.so
%endif
+%if %{with_smart}
+%files smart
+%{_libdir}/%{name}/smart.so
+%endif
+
%if %{with_snmp}
%files snmp
%{_mandir}/man5/collectd-snmp.5*
%changelog
# * TODO 5.5.0-1
# - New upstream version
-# - New plugins enabled by default: drbd, log_logstash, write_tsdb
+# - New plugins enabled by default: drbd, log_logstash, write_tsdb, smart, openldap
# - New plugins disabled by default: barometer, write_kafka
# - Enable zfs_arc, now supported on Linux
# - Install disk plugin in an dedicated package, as it depends on libudev
--- /dev/null
+[Unit]
+Description=Collectd
+After=local-fs.target network.target
+Requires=local-fs.target network.target
+
+[Service]
+ExecStart=/usr/sbin/collectd
+
+# Tell systemd it will receive a notification from collectd over it's control
+# socket once the daemon is ready. See systemd.service(5) for more details.
+Type=notify
+NotifyAccess=main
+
+# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
+Restart=always
+RestartSec=10
+
+# Send all console messages to syslog.
+StandardOutput=syslog
+StandardError=syslog
+
+[Install]
+WantedBy=multi-user.target
# these cannot be started at boot time by the system without
# arcane trickery. Also a root user will not see these tasks/jobs
# by default. set*id is a reasonable and secure compromise.
+# These options are not supported on early upstart versions.
#setuid nobody
#setgid nobody
# shell commands via `sh -e`.
env DAEMON=/usr/sbin/collectd
-# Tell upstart to watch for forking when tracking the pid for us.
-expect fork
+# Tell upstart to wait for collectd to SIGSTOP itself, signaling it is ready
+# to run.
+expect stop
# prevent thrashing - 10 restarts in 5 seconds
respawn
respawn limit 10 5
-# Make a log available in /var/log/upstart/collectd.log
-console log
+# Uncomment to make a log available in /var/log/upstart/collectd.log
+# (not supported on early upstart versions).
+#console log
# The daemon will not start if the configuration is invalid.
pre-start exec $DAEMON -t
collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
collectd_nagios_SOURCES = collectd-nagios.c
-collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
collectd_nagios_LDADD =
if BUILD_WITH_LIBSOCKET
collectd_nagios_LDADD += -lsocket
collectdctl_SOURCES = collectdctl.c
-collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
collectdctl_LDADD =
if BUILD_WITH_LIBSOCKET
collectdctl_LDADD += -lsocket
collectd_tg_SOURCES = collectd-tg.c \
daemon/utils_heap.c daemon/utils_heap.h
-collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
collectd_tg_LDADD =
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
aggregation_la_SOURCES = aggregation.c \
utils_vl_lookup.c utils_vl_lookup.h
aggregation_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-aggregation_la_LIBADD =
+aggregation_la_LIBADD = -lm
endif
if BUILD_PLUGIN_AMQP
onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
+if BUILD_PLUGIN_OPENLDAP
+pkglib_LTLIBRARIES += openldap.la
+openldap_la_SOURCES = openldap.c
+openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
+openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LIBADD = -lldap
+endif
+
if BUILD_PLUGIN_OPENVPN
pkglib_LTLIBRARIES += openvpn.la
openvpn_la_SOURCES = openvpn.c
sigrok_la_LIBADD = -lsigrok
endif
+if BUILD_PLUGIN_SMART
+if BUILD_WITH_LIBUDEV
+pkglib_LTLIBRARIES += smart.la
+smart_la_SOURCES = smart.c \
+ utils_ignorelist.c utils_ignorelist.h
+smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
+smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
+smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
+endif
+endif
+
if BUILD_PLUGIN_SNMP
pkglib_LTLIBRARIES += snmp.la
snmp_la_SOURCES = snmp.c
battery_submit ("0", "current", current);
if (!isnan (voltage))
battery_submit ("0", "voltage", voltage);
+
+ return (0);
} /* }}} int battery_read */
/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
#@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
#@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
+#@BUILD_PLUGIN_OPENLDAP_TRUE@LoadPlugin openldap
#@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
#@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
#@BUILD_PLUGIN_PERL_TRUE@<LoadPlugin perl>
#@BUILD_PLUGIN_SENSORS_TRUE@LoadPlugin sensors
#@BUILD_PLUGIN_SERIAL_TRUE@LoadPlugin serial
#@BUILD_PLUGIN_SIGROK_TRUE@LoadPlugin sigrok
+#@BUILD_PLUGIN_SMART_TRUE@LoadPlugin smart
#@BUILD_PLUGIN_SNMP_TRUE@LoadPlugin snmp
#@BUILD_PLUGIN_STATSD_TRUE@LoadPlugin statsd
#@BUILD_PLUGIN_SWAP_TRUE@LoadPlugin swap
# IgnoreSelected false
#</Plugin>
+#<Plugin openldap>
+# <Instance "localhost">
+# URL "ldap://localhost:389"
+# StartTLS false
+# VerifyHost true
+# CACert "/path/to/ca.crt"
+# Timeout -1
+# Version 3
+# </Instance>
+#</Plugin>
+
#<Plugin openvpn>
# StatusFile "/etc/openvpn/openvpn-status.log"
# ImprovedNamingSchema false
# </Device>
#</Plugin>
+#<Plugin smart>
+# Disk "/^[hs]d[a-f][0-9]?$/"
+# IgnoreSelected false
+#</Plugin>
+
#<Plugin snmp>
# <Data "powerplus_voltge_input">
# Type "voltage"
BaseDir "/var/lib/collectd"
PIDFile "/run/collectd.pid"
Interval 10.0
-
+
LoadPlugin cpu
LoadPlugin load
-
+
<LoadPlugin df>
Interval 3600
</LoadPlugin>
<Plugin df>
ValuesPercentage true
</Plugin>
-
+
LoadPlugin ping
<Plugin ping>
Host "example.org"
change, though this is unlikely. Oh, and if you want to help improving this
plugin, just send a short notice to the mailing list. ThanksE<nbsp>:)
+=head2 Plugin C<openldap>
+
+To use the C<openldap> plugin you first need to configure the I<OpenLDAP>
+server correctly. The backend database C<monitor> needs to be loaded and
+working. See slapd-monitor(5) for the details.
+
+The configuration of the C<openldap> plugin consists of one or more B<Instance>
+blocks. Each block requires one string argument as the instance name. For
+example:
+
+ <Plugin "openldap">
+ <Instance "foo">
+ URL "ldap://localhost/"
+ </Instance>
+ <Instance "bar">
+ URL "ldaps://localhost/"
+ </Instance>
+ </Plugin>
+
+The instance name will be used as the I<plugin instance>. To emulate the old
+(versionE<nbsp>4) behavior, you can use an empty string (""). In order for the
+plugin to work correctly, each instance name must be unique. This is not
+enforced by the plugin and it is your responsibility to ensure it is.
+
+The following options are accepted within each B<Instance> block:
+
+=over 4
+
+=item B<URL> I<ldap://host/binddn>
+
+Sets the URL to use to connect to the I<OpenLDAP> server. This option is
+I<mandatory>.
+
+=item B<StartTLS> B<true|false>
+
+Defines whether TLS must be used when connecting to the I<OpenLDAP> server.
+Disabled by default.
+
+=item B<VerifyHost> B<true|false>
+
+Enables or disables peer host name verification. If enabled, the plugin checks
+if the C<Common Name> or a C<Subject Alternate Name> field of the SSL
+certificate matches the host name provided by the B<URL> option. If this
+identity check fails, the connection is aborted. Enabled by default.
+
+=item B<CACert> I<File>
+
+File that holds one or more SSL certificates. If you want to use TLS/SSL you
+may possibly need this option. What CA certificates are checked by default
+depends on the distribution you use and can be changed with the usual ldap
+client configuration mechanisms. See ldap.conf(5) for the details.
+
+=item B<Timeout> I<Seconds>
+
+Sets the timeout value for ldap operations. Defaults to B<-1> which results in
+an infinite timeout.
+
+=item B<Version> I<Version>
+
+An integer which sets the LDAP protocol version number to use when connecting
+to the I<OpenLDAP> server. Defaults to B<3> for using I<LDAPv3>.
+
+=back
+
=head2 Plugin C<openvpn>
The OpenVPN plugin reads a status file maintained by OpenVPN and gathers
=back
+=head2 Plugin C<smart>
+
+The C<smart> plugin collects SMART information from physical
+disks. Values collectd include temperature, power cycle count, poweron
+time and bad sectors. Also, all SMART attributes are collected along
+with the normalized current value, the worst value, the threshold and
+a human readable value.
+
+Using the following two options you can ignore some disks or configure the
+collection only of specific disks.
+
+=over 4
+
+=item B<Disk> I<Name>
+
+Select the disk I<Name>. Whether it is collected or ignored depends on the
+B<IgnoreSelected> setting, see below. As with other plugins that use the
+daemon's ignorelist functionality, a string that starts and ends with a slash
+is interpreted as a regular expression. Examples:
+
+ Disk "sdd"
+ Disk "/hda[34]/"
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Sets whether selected disks, i.E<nbsp>e. the ones matches by any of the B<Disk>
+statements, are ignored or if all other disks are ignored. The behavior
+(hopefully) is intuitive: If no B<Disk> option is configured, all disks are
+collected. If at least one B<Disk> option is given and no B<IgnoreSelected> or
+set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
+is set to B<true>, all disks are collected B<except> the ones matched.
+
+=back
+
=head2 Plugin C<snmp>
Since the configuration of the C<snmp plugin> is a little more complicated than
Specify the protocol to use when communicating with I<Riemann>. Defaults to
B<UDP>.
+=item B<Batch> B<true>|B<false>
+
+If set to B<true> and B<Protocol> is set to B<TCP>,
+events will be batched in memory and flushed at
+regular intervals or when B<BatchMaxSize> is exceeded.
+
+Notifications are not batched and sent as soon as possible.
+
+Defaults to false
+
+=item B<BatchMaxSize> I<size>
+
+Maximum payload size for a riemann packet. Defaults to 8192
+
=item B<StoreRates> B<true>|B<false>
If set to B<true> (the default), convert counter values to rates. If set to
Don't fork to the background. I<collectd> will also B<not> close standard file
descriptors, detach from the session nor write a pid file. This is mainly
-thought for 'supervising' init replacements such as I<runit>.
+thought for 'supervising' init replacements such as I<runit>. If using
+I<upstart> or I<systemd> though, starting with version 5.5.0 I<collectd> is
+able to notify these two init replacements, and B<does> require forking to the
+background for process supervision. The F<contrib/> directory has sample
+I<upstart> and I<systemd> configuration files.
=item B<-h>
/* Legacy behavior: Dispatches the raw derive values without any aggregation. */
static void cpu_commit_without_aggregation (void) /* {{{ */
{
- size_t cpu_num;
+ int state;
- for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ for (state = 0; state < CPU_STATE_ACTIVE; state++)
{
- int state;
-
- for (state = 0; state < CPU_STATE_ACTIVE; state++)
- {
- cpu_state_t *s = get_cpu_state (cpu_num, state);
+ size_t cpu_num;
+ if (report_by_cpu) {
+ for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ {
+ cpu_state_t *s = get_cpu_state (cpu_num, state);
- if (!s->has_value)
- continue;
+ if (!s->has_value)
+ continue;
- submit_derive ((int) cpu_num, (int) state, s->conv.last_value.derive);
+ submit_derive ((int) cpu_num, (int) state, s->conv.last_value.derive);
+ }
+ } else {
+ derive_t derive_total = 0;
+ for (cpu_num = 0; cpu_num < global_cpu_num; cpu_num++)
+ {
+ cpu_state_t *s = get_cpu_state (cpu_num, state);
+
+ if (!s->has_value)
+ continue;
+
+ derive_total += s->conv.last_value.derive;
+
+ }
+ submit_derive (-1, (int) state, derive_total);
}
}
} /* }}} void cpu_commit_without_aggregation */
};
size_t cpu_num;
- if (report_by_cpu && report_by_state && !report_percent)
+ if (report_by_state && !report_percent)
{
cpu_commit_without_aggregation ();
return;
AM_CFLAGS = -Wall -Werror
endif
-AM_CPPFLAGS = -DPREFIX='"${prefix}"'
+AM_CPPFLAGS = -I$(top_srcdir)/src
+AM_CPPFLAGS += -DPREFIX='"${prefix}"'
AM_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
AM_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
#include <netdb.h>
#include <pthread.h>
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
-
+
dirlen = strlen (dir);
while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
dir[--dirlen] = '\0';
static void exit_usage (int status)
{
printf ("Usage: "PACKAGE" [OPTIONS]\n\n"
-
+
"Available options:\n"
" General:\n"
" -C <file> Configuration file.\n"
#endif
#if HAVE_LIBSTATGRAB
- if (sg_init ())
+ if (sg_init (
+# if HAVE_LIBSTATGRAB_0_90
+ 0
+# endif
+ ))
{
ERROR ("sg_init: %s", sg_str_error (sg_get_error ()));
return (-1);
} /* static int pidfile_remove (const char *file) */
#endif /* COLLECT_DAEMON */
+#ifdef KERNEL_LINUX
+int notify_upstart (void)
+{
+ const char *upstart_job = getenv("UPSTART_JOB");
+
+ if (upstart_job == NULL)
+ return 0;
+
+ if (strcmp(upstart_job, "collectd") != 0)
+ return 0;
+
+ WARNING ("supervised by upstart, will stop to signal readyness");
+ raise(SIGSTOP);
+ unsetenv("UPSTART_JOB");
+
+ return 1;
+}
+
+int notify_systemd (void)
+{
+ int fd = -1;
+ const char *notifysocket = getenv("NOTIFY_SOCKET");
+ struct sockaddr_un su;
+ struct iovec iov;
+ struct msghdr hdr;
+
+ if (notifysocket == NULL)
+ return 0;
+
+ if ((strchr("@/", notifysocket[0])) == NULL ||
+ strlen(notifysocket) < 2)
+ return 0;
+
+ WARNING ("supervised by systemd, will signal readyness");
+ if ((fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
+ WARNING ("cannot contact systemd socket %s", notifysocket);
+ return 0;
+ }
+
+ bzero(&su, sizeof(su));
+ su.sun_family = AF_UNIX;
+ sstrncpy (su.sun_path, notifysocket, sizeof(su.sun_path));
+
+ if (notifysocket[0] == '@')
+ su.sun_path[0] = 0;
+
+ bzero(&iov, sizeof(iov));
+ iov.iov_base = "READY=1";
+ iov.iov_len = strlen("READY=1");
+
+ bzero(&hdr, sizeof(hdr));
+ hdr.msg_name = &su;
+ hdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) +
+ strlen(notifysocket);
+ hdr.msg_iov = &iov;
+ hdr.msg_iovlen = 1;
+
+ unsetenv("NOTIFY_SOCKET");
+ if (sendmsg(fd, &hdr, MSG_NOSIGNAL) < 0) {
+ WARNING ("cannot send notification to systemd");
+ close(fd);
+ return 0;
+ }
+ close(fd);
+ return 1;
+}
+#endif /* KERNEL_LINUX */
+
int main (int argc, char **argv)
{
struct sigaction sig_int_action;
sig_chld_action.sa_handler = SIG_IGN;
sigaction (SIGCHLD, &sig_chld_action, NULL);
- if (daemonize)
+ /*
+ * Only daemonize if we're not being supervised
+ * by upstart or systemd (when using Linux).
+ */
+ if (daemonize
+#ifdef KERNEL_LINUX
+ && notify_upstart() == 0 && notify_systemd() == 0
+#endif
+ )
{
if ((pid = fork ()) == -1)
{
#elif defined(HAVE_LIBSTATGRAB)
sg_disk_io_stats *ds;
- int disks, counter;
+# if HAVE_LIBSTATGRAB_0_90
+ size_t disks;
+# else
+ int disks;
+#endif
+ int counter;
char name[DATA_MAX_NAME_LEN];
if ((ds = sg_get_disk_io_stats(&disks)) == NULL)
BUILT_SOURCES = collectd/lcc_features.h
libcollectdclient_la_SOURCES = client.c network.c network_buffer.c
-libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd -I$(top_srcdir)/src/daemon
+libcollectdclient_la_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd \
+ -I$(top_srcdir)/src/daemon
libcollectdclient_la_LDFLAGS = -version-info 1:0:0
libcollectdclient_la_LIBADD =
if BUILD_WITH_LIBGCRYPT
/* Re enable deprecation warnings */
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
#endif
#include "collectd/network_buffer.h"
need_init = 0;
#if HAVE_LIBGCRYPT
+# if GCRYPT_VERSION_NUMBER < 0x010600
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
if (!gcry_check_version (GCRYPT_VERSION))
return (0);
#ifdef HAVE_SYS_SYSCTL_H
# include <sys/sysctl.h>
#endif
+#ifdef HAVE_SYS_VMMETER_H
+# include <sys/vmmeter.h>
+#endif
#ifdef HAVE_MACH_KERN_RETURN_H
# include <mach/kern_return.h>
/* Re enable deprecation warnings */
# pragma GCC diagnostic warning "-Wdeprecated-declarations"
# endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
#endif
#ifndef IPV6_ADD_MEMBERSHIP
* above doesn't count, as it doesn't implicitly initalize Libgcrypt.
*
* tl;dr: keep all these gry_* statements in this exact order please. */
+# if GCRYPT_VERSION_NUMBER < 0x010600
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
gcry_check_version (NULL);
gcry_control (GCRYCTL_INIT_SECMEM, 32768);
gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
--- /dev/null
+/**
+ * collectd - src/openldap.c
+ * Copyright (C) 2011 Kimo Rosenbaum
+ * Copyright (C) 2014 Marc Fournier
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Kimo Rosenbaum <kimor79 at yahoo.com>
+ * Marc Fournier <marc.fournier at camptocamp.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <lber.h>
+#include <ldap.h>
+
+struct ldap_s /* {{{ */
+{
+ char *name;
+
+ char *cacert;
+ char *host;
+ int state;
+ _Bool starttls;
+ int timeout;
+ char *url;
+ _Bool verifyhost;
+ int version;
+
+ LDAP *ld;
+};
+typedef struct ldap_s ldap_t; /* }}} */
+
+static void ldap_free (ldap_t *st) /* {{{ */
+{
+ if (st == NULL)
+ return;
+
+ sfree (st->cacert);
+ sfree (st->host);
+ sfree (st->name);
+ sfree (st->url);
+ if (st->ld)
+ ldap_memfree (st->ld);
+ sfree (st);
+} /* }}} void ldap_free */
+
+/* initialize ldap for each host */
+static int ldap_init_host (ldap_t *st) /* {{{ */
+{
+ LDAP *ld;
+ int rc;
+ rc = ldap_initialize (&ld, st->url);
+ if (rc != LDAP_SUCCESS)
+ {
+ ERROR ("openldap plugin: ldap_initialize failed: %s",
+ ldap_err2string (rc));
+ st->state = 0;
+ ldap_unbind_ext_s (ld, NULL, NULL);
+ return (-1);
+ }
+
+ st->ld = ld;
+
+ ldap_set_option (st->ld, LDAP_OPT_PROTOCOL_VERSION, &st->version);
+
+ ldap_set_option (st->ld, LDAP_OPT_TIMEOUT,
+ &(const struct timeval){st->timeout, 0});
+
+ if (st->cacert != NULL)
+ ldap_set_option (st->ld, LDAP_OPT_X_TLS_CACERTFILE, st->cacert);
+
+ if (st->verifyhost == 0)
+ {
+ int never = LDAP_OPT_X_TLS_NEVER;
+ ldap_set_option (st->ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &never);
+ }
+
+ if (st->starttls != 0)
+ {
+ rc = ldap_start_tls_s (ld, NULL, NULL);
+ if (rc != LDAP_SUCCESS)
+ {
+ ERROR ("openldap plugin: Failed to start tls on %s: %s",
+ st->url, ldap_err2string (rc));
+ st->state = 0;
+ ldap_unbind_ext_s (st->ld, NULL, NULL);
+ return (-1);
+ }
+ }
+
+ struct berval cred;
+ cred.bv_val = "";
+ cred.bv_len = 0;
+
+ rc = ldap_sasl_bind_s (st->ld, NULL, NULL, &cred, NULL, NULL, NULL);
+ if (rc != LDAP_SUCCESS)
+ {
+ ERROR ("openldap plugin: Failed to bind to %s: %s",
+ st->url, ldap_err2string (rc));
+ st->state = 0;
+ ldap_unbind_ext_s (st->ld, NULL, NULL);
+ return (-1);
+ }
+ else
+ {
+ DEBUG ("openldap plugin: Successfully connected to %s",
+ st->url);
+ st->state = 1;
+ return (0);
+ }
+} /* }}} static ldap_init_host */
+
+static void ldap_submit_value (const char *type, const char *type_instance, /* {{{ */
+ value_t value, ldap_t *st)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = &value;
+ vl.values_len = 1;
+
+ if ((st->host == NULL)
+ || (strcmp ("", st->host) == 0)
+ || (strcmp ("localhost", st->host) == 0))
+ {
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ }
+ else
+ {
+ sstrncpy (vl.host, st->host, sizeof (vl.host));
+ }
+
+ sstrncpy (vl.plugin, "openldap", sizeof (vl.plugin));
+ if (st->name != NULL)
+ sstrncpy (vl.plugin_instance, st->name,
+ sizeof (vl.plugin_instance));
+
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ if (type_instance != NULL)
+ sstrncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+} /* }}} void ldap_submit_value */
+
+static void ldap_submit_derive (const char *type, const char *type_instance, /* {{{ */
+ derive_t d, ldap_t *st)
+{
+ value_t v;
+ v.derive = d;
+ ldap_submit_value (type, type_instance, v, st);
+} /* }}} void ldap_submit_derive */
+
+static void ldap_submit_gauge (const char *type, const char *type_instance, /* {{{ */
+ gauge_t g, ldap_t *st)
+{
+ value_t v;
+ v.gauge = g;
+ ldap_submit_value (type, type_instance, v, st);
+} /* }}} void ldap_submit_gauge */
+
+static int ldap_read_host (user_data_t *ud) /* {{{ */
+{
+ ldap_t *st;
+ LDAPMessage *e, *result;
+ char *dn;
+ int rc;
+ int status;
+
+ char *attrs[9] = { "monitorCounter",
+ "monitorOpCompleted",
+ "monitorOpInitiated",
+ "monitoredInfo",
+ "olmBDBEntryCache",
+ "olmBDBDNCache",
+ "olmBDBIDLCache",
+ "namingContexts",
+ NULL };
+
+ if ((ud == NULL) || (ud->data == NULL))
+ {
+ ERROR ("openldap plugin: ldap_read_host: Invalid user data.");
+ return (-1);
+ }
+
+ st = (ldap_t *) ud->data;
+
+ status = ldap_init_host (st);
+ if (status != 0)
+ return (-1);
+
+ rc = ldap_search_ext_s (st->ld, "cn=Monitor", LDAP_SCOPE_SUBTREE,
+ "(|(!(cn=* *))(cn=Database*))", attrs, 0,
+ NULL, NULL, NULL, 0, &result);
+
+ if (rc != LDAP_SUCCESS)
+ {
+ ERROR ("openldap plugin: Failed to execute search: %s",
+ ldap_err2string (rc));
+ ldap_msgfree (result);
+ ldap_unbind_ext_s (st->ld, NULL, NULL);
+ return (-1);
+ }
+
+ for (e = ldap_first_entry (st->ld, result); e != NULL;
+ e = ldap_next_entry (st->ld, e))
+ {
+ if ((dn = ldap_get_dn (st->ld, e)) != NULL)
+ {
+ unsigned long long counter = 0;
+ unsigned long long opc = 0;
+ unsigned long long opi = 0;
+ unsigned long long info = 0;
+
+ struct berval counter_data;
+ struct berval opc_data;
+ struct berval opi_data;
+ struct berval info_data;
+ struct berval olmbdb_data;
+ struct berval nc_data;
+
+ struct berval **counter_list;
+ struct berval **opc_list;
+ struct berval **opi_list;
+ struct berval **info_list;
+ struct berval **olmbdb_list;
+ struct berval **nc_list;
+
+ if ((counter_list = ldap_get_values_len (st->ld, e,
+ "monitorCounter")) != NULL)
+ {
+ counter_data = *counter_list[0];
+ counter = atoll (counter_data.bv_val);
+ }
+
+ if ((opc_list = ldap_get_values_len (st->ld, e,
+ "monitorOpCompleted")) != NULL)
+ {
+ opc_data = *opc_list[0];
+ opc = atoll (opc_data.bv_val);
+ }
+
+ if ((opi_list = ldap_get_values_len (st->ld, e,
+ "monitorOpInitiated")) != NULL)
+ {
+ opi_data = *opi_list[0];
+ opi = atoll (opi_data.bv_val);
+ }
+
+ if ((info_list = ldap_get_values_len (st->ld, e,
+ "monitoredInfo")) != NULL)
+ {
+ info_data = *info_list[0];
+ info = atoll (info_data.bv_val);
+ }
+
+ if (strcmp (dn, "cn=Total,cn=Connections,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("total_connections", NULL,
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Current,cn=Connections,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("current_connections", NULL,
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Operations,cn=Monitor") == 0)
+ {
+ ldap_submit_derive ("operations",
+ "completed", opc, st);
+ ldap_submit_derive ("operations",
+ "initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Bind,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "bind-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "bind-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=UnBind,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "unbind-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "unbind-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Search,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "search-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "search-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Compare,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "compare-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "compare-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Modify,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "modify-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "modify-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Modrdn,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "modrdn-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "modrdn-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Add,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "add-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "add-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Delete,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "delete-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "delete-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Abandon,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "abandon-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "abandon-initiated", opi, st);
+ }
+ else if (strcmp (dn,
+ "cn=Extended,cn=Operations,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("operations",
+ "extended-completed", opc, st);
+ ldap_submit_derive ("operations",
+ "extended-initiated", opi, st);
+ }
+ else if ((strncmp (dn, "cn=Database", 11) == 0)
+ && ((nc_list = ldap_get_values_len
+ (st->ld, e, "namingContexts")) != NULL))
+ {
+ nc_data = *nc_list[0];
+ char typeinst[DATA_MAX_NAME_LEN];
+
+ if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+ "olmBDBEntryCache")) != NULL)
+ {
+ olmbdb_data = *olmbdb_list[0];
+ ssnprintf (typeinst, sizeof (typeinst),
+ "bdbentrycache-%s", nc_data.bv_val);
+ ldap_submit_gauge ("cache_size", typeinst,
+ atoll (olmbdb_data.bv_val), st);
+ ldap_value_free_len (olmbdb_list);
+ }
+
+ if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+ "olmBDBDNCache")) != NULL)
+ {
+ olmbdb_data = *olmbdb_list[0];
+ ssnprintf (typeinst, sizeof (typeinst),
+ "bdbdncache-%s", nc_data.bv_val);
+ ldap_submit_gauge ("cache_size", typeinst,
+ atoll (olmbdb_data.bv_val), st);
+ ldap_value_free_len (olmbdb_list);
+ }
+
+ if ((olmbdb_list = ldap_get_values_len (st->ld, e,
+ "olmBDBIDLCache")) != NULL)
+ {
+ olmbdb_data = *olmbdb_list[0];
+ ssnprintf (typeinst, sizeof (typeinst),
+ "bdbidlcache-%s", nc_data.bv_val);
+ ldap_submit_gauge ("cache_size", typeinst,
+ atoll (olmbdb_data.bv_val), st);
+ ldap_value_free_len (olmbdb_list);
+ }
+
+ ldap_value_free_len (nc_list);
+ }
+ else if (strcmp (dn,
+ "cn=Bytes,cn=Statistics,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "statistics-bytes",
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=PDU,cn=Statistics,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "statistics-pdu",
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Entries,cn=Statistics,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "statistics-entries",
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Referrals,cn=Statistics,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "statistics-referrals",
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Open,cn=Threads,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("threads", "threads-open",
+ info, st);
+ }
+ else if (strcmp (dn,
+ "cn=Starting,cn=Threads,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("threads", "threads-starting",
+ info, st);
+ }
+ else if (strcmp (dn,
+ "cn=Active,cn=Threads,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("threads", "threads-active",
+ info, st);
+ }
+ else if (strcmp (dn,
+ "cn=Pending,cn=Threads,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("threads", "threads-pending",
+ info, st);
+ }
+ else if (strcmp (dn,
+ "cn=Backload,cn=Threads,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_gauge ("threads", "threads-backload",
+ info, st);
+ }
+ else if (strcmp (dn,
+ "cn=Read,cn=Waiters,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "waiters-read",
+ counter, st);
+ }
+ else if (strcmp (dn,
+ "cn=Write,cn=Waiters,cn=Monitor")
+ == 0)
+ {
+ ldap_submit_derive ("derive", "waiters-write",
+ counter, st);
+ }
+
+ ldap_value_free_len (counter_list);
+ ldap_value_free_len (opc_list);
+ ldap_value_free_len (opi_list);
+ ldap_value_free_len (info_list);
+ }
+
+ ldap_memfree (dn);
+ }
+
+ ldap_msgfree (result);
+ ldap_unbind_ext_s (st->ld, NULL, NULL);
+ return (0);
+} /* }}} int ldap_read_host */
+
+/* Configuration handling functions {{{
+ *
+ * <Plugin ldap>
+ * <Instance "plugin_instance1">
+ * URL "ldap://localhost"
+ * ...
+ * </Instance>
+ * </Plugin>
+ */
+
+static int ldap_config_add (oconfig_item_t *ci) /* {{{ */
+{
+ ldap_t *st;
+ int i;
+ int status;
+
+ st = malloc (sizeof (*st));
+ if (st == NULL)
+ {
+ ERROR ("openldap plugin: malloc failed.");
+ return (-1);
+ }
+ memset (st, 0, sizeof (*st));
+
+ status = cf_util_get_string (ci, &st->name);
+ if (status != 0)
+ {
+ sfree (st);
+ return (status);
+ }
+
+ st->starttls = 0;
+ st->timeout = -1;
+ st->verifyhost = 1;
+ st->version = LDAP_VERSION3;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("CACert", child->key) == 0)
+ status = cf_util_get_string (child, &st->cacert);
+ else if (strcasecmp ("StartTLS", child->key) == 0)
+ status = cf_util_get_boolean (child, &st->starttls);
+ else if (strcasecmp ("Timeout", child->key) == 0)
+ status = cf_util_get_int (child, &st->timeout);
+ else if (strcasecmp ("URL", child->key) == 0)
+ status = cf_util_get_string (child, &st->url);
+ else if (strcasecmp ("VerifyHost", child->key) == 0)
+ status = cf_util_get_boolean (child, &st->verifyhost);
+ else if (strcasecmp ("Version", child->key) == 0)
+ status = cf_util_get_int (child, &st->version);
+ else
+ {
+ WARNING ("openldap plugin: Option `%s' not allowed here.",
+ child->key);
+ status = -1;
+ }
+
+ if (status != 0)
+ break;
+ }
+
+ /* Check if struct is complete.. */
+ if ((status == 0) && (st->url == NULL))
+ {
+ ERROR ("openldap plugin: Instance `%s': "
+ "No URL has been configured.",
+ st->name);
+ status = -1;
+ }
+
+ /* Check if URL is valid */
+ if ((status == 0) && (st->url != NULL))
+ {
+ LDAPURLDesc *ludpp;
+ int rc;
+
+ if ((rc = ldap_url_parse (st->url, &ludpp)) != 0)
+ {
+ ERROR ("openldap plugin: Instance `%s': "
+ "Invalid URL: `%s'",
+ st->name, st->url);
+ status = -1;
+ }
+ else
+ {
+ st->host = strdup (ludpp->lud_host);
+ }
+
+ ldap_free_urldesc (ludpp);
+ }
+
+ if (status == 0)
+ {
+ user_data_t ud;
+ char callback_name[3*DATA_MAX_NAME_LEN];
+
+ memset (&ud, 0, sizeof (ud));
+ ud.data = st;
+
+ memset (callback_name, 0, sizeof (callback_name));
+ ssnprintf (callback_name, sizeof (callback_name),
+ "openldap/%s/%s",
+ (st->host != NULL) ? st->host : hostname_g,
+ (st->name != NULL) ? st->name : "default"),
+
+ status = plugin_register_complex_read (/* group = */ NULL,
+ /* name = */ callback_name,
+ /* callback = */ ldap_read_host,
+ /* interval = */ NULL,
+ /* user_data = */ &ud);
+ }
+
+ if (status != 0)
+ {
+ ldap_free (st);
+ return (-1);
+ }
+
+ return (0);
+} /* }}} int ldap_config_add */
+
+static int ldap_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+ int status = 0;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Instance", child->key) == 0)
+ ldap_config_add (child);
+ else
+ WARNING ("openldap plugin: The configuration option "
+ "\"%s\" is not allowed here. Did you "
+ "forget to add an <Instance /> block "
+ "around the configuration?",
+ child->key);
+ } /* for (ci->children) */
+
+ return (status);
+} /* }}} int ldap_config */
+
+/* }}} End of configuration handling functions */
+
+static int ldap_init (void) /* {{{ */
+{
+ /* Initialize LDAP library while still single-threaded as recommended in
+ * ldap_initialize(3) */
+ int debug_level;
+ ldap_get_option (NULL, LDAP_OPT_DEBUG_LEVEL, &debug_level);
+ return (0);
+} /* }}} int ldap_init */
+
+void module_register (void) /* {{{ */
+{
+ plugin_register_complex_config ("openldap", ldap_config);
+ plugin_register_init ("openldap", ldap_init);
+} /* }}} void module_register */
--- /dev/null
+/**
+ * collectd - src/smart.c
+ * Copyright (C) 2014 Vincent Bernat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Vincent Bernat <vbe at exoscale.ch>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+#include <atasmart.h>
+#include <libudev.h>
+
+static const char *config_keys[] =
+{
+ "Disk",
+ "IgnoreSelected"
+};
+
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *ignorelist = NULL;
+
+static int smart_config (const char *key, const char *value)
+{
+ if (ignorelist == NULL)
+ ignorelist = ignorelist_create (/* invert = */ 1);
+ if (ignorelist == NULL)
+ return (1);
+
+ if (strcasecmp ("Disk", key) == 0)
+ {
+ ignorelist_add (ignorelist, value);
+ }
+ else if (strcasecmp ("IgnoreSelected", key) == 0)
+ {
+ int invert = 1;
+ if (IS_TRUE (value))
+ invert = 0;
+ ignorelist_set_invert (ignorelist, invert);
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+} /* int smart_config */
+
+static void smart_submit (const char *dev, char *type, char *type_inst, double value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedData *a,
+ void* userdata)
+{
+ const char *dev = userdata;
+ value_t values[4];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ if (!a->current_value_valid || !a->worst_value_valid) return;
+ values[0].gauge = a->current_value;
+ values[1].gauge = a->worst_value;
+ values[2].gauge = a->threshold_valid?a->threshold:0;
+ values[3].gauge = a->pretty_value;
+
+ vl.values = values;
+ vl.values_len = 4;
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "smart", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "smart_attribute", sizeof (vl.type));
+ sstrncpy (vl.type_instance, a->name, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+
+ if (a->threshold_valid && a->current_value <= a->threshold)
+ {
+ notification_t notif = { NOTIF_WARNING,
+ cdtime (),
+ "",
+ "",
+ "smart", "",
+ "smart_attribute",
+ "",
+ NULL };
+ sstrncpy (notif.host, hostname_g, sizeof (notif.host));
+ sstrncpy (notif.plugin_instance, dev, sizeof (notif.plugin_instance));
+ sstrncpy (notif.type_instance, a->name, sizeof (notif.type_instance));
+ ssnprintf (notif.message, sizeof (notif.message),
+ "attribute %s is below allowed threshold (%d < %d)",
+ a->name, a->current_value, a->threshold);
+ plugin_dispatch_notification (¬if);
+ }
+}
+
+static void smart_handle_disk (const char *dev)
+{
+ SkDisk *d = NULL;
+ SkBool awake = FALSE;
+ SkBool available = FALSE;
+ const char *shortname;
+ const SkSmartParsedData *spd;
+ uint64_t poweron, powercycles, badsectors, temperature;
+
+ shortname = strrchr(dev, '/');
+ if (!shortname) return;
+ shortname++;
+ if (ignorelist_match (ignorelist, shortname) != 0) {
+ DEBUG ("smart plugin: ignoring %s.", dev);
+ return;
+ }
+
+ DEBUG ("smart plugin: checking SMART status of %s.",
+ dev);
+
+ if (sk_disk_open (dev, &d) < 0)
+ {
+ ERROR ("smart plugin: unable to open %s.", dev);
+ return;
+ }
+ if (sk_disk_identify_is_available (d, &available) < 0 || !available)
+ {
+ DEBUG ("smart plugin: disk %s cannot be identified.", dev);
+ goto end;
+ }
+ if (sk_disk_smart_is_available (d, &available) < 0 || !available)
+ {
+ DEBUG ("smart plugin: disk %s has no SMART support.", dev);
+ goto end;
+ }
+ if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+ {
+ DEBUG ("smart plugin: disk %s is sleeping.", dev);
+ goto end;
+ }
+ if (sk_disk_smart_read_data (d) < 0)
+ {
+ ERROR ("smart plugin: unable to get SMART data for disk %s.", dev);
+ goto end;
+ }
+ if (sk_disk_smart_parse (d, &spd) < 0)
+ {
+ ERROR ("smart plugin: unable to parse SMART data for disk %s.", dev);
+ goto end;
+ }
+
+ /* Get some specific values */
+ if (sk_disk_smart_get_power_on (d, &poweron) < 0)
+ {
+ WARNING ("smart plugin: unable to get milliseconds since power on for %s.",
+ dev);
+ }
+ else
+ smart_submit (shortname, "smart_poweron", "", poweron / 1000.);
+
+ if (sk_disk_smart_get_power_cycle (d, &powercycles) < 0)
+ {
+ WARNING ("smart plugin: unable to get number of power cycles for %s.",
+ dev);
+ }
+ else
+ smart_submit (shortname, "smart_powercycles", "", powercycles);
+
+ if (sk_disk_smart_get_bad (d, &badsectors) < 0)
+ {
+ WARNING ("smart plugin: unable to get number of bad sectors for %s.",
+ dev);
+ }
+ else
+ smart_submit (shortname, "smart_badsectors", "", badsectors);
+
+ if (sk_disk_smart_get_temperature (d, &temperature) < 0)
+ {
+ WARNING ("smart plugin: unable to get temperature for %s.",
+ dev);
+ }
+ else
+ smart_submit (shortname, "smart_temperature", "", temperature / 1000. - 273.15);
+
+ /* Grab all attributes */
+ if (sk_disk_smart_parse_attributes(d, smart_handle_disk_attribute,
+ (char *)shortname) < 0)
+ {
+ ERROR ("smart plugin: unable to handle SMART attributes for %s.",
+ dev);
+ }
+
+end:
+ sk_disk_free(d);
+}
+
+static int smart_read (void)
+{
+ struct udev *handle_udev;
+ struct udev_enumerate *enumerate;
+ struct udev_list_entry *devices, *dev_list_entry;
+ struct udev_device *dev;
+
+ /* Use udev to get a list of disks */
+ handle_udev = udev_new();
+ if (!handle_udev)
+ {
+ ERROR ("smart plugin: unable to initialize udev.");
+ return (-1);
+ }
+ enumerate = udev_enumerate_new (handle_udev);
+ udev_enumerate_add_match_subsystem (enumerate, "block");
+ udev_enumerate_add_match_property (enumerate, "DEVTYPE", "disk");
+ udev_enumerate_scan_devices (enumerate);
+ devices = udev_enumerate_get_list_entry (enumerate);
+ udev_list_entry_foreach (dev_list_entry, devices)
+ {
+ const char *path, *devpath;
+ path = udev_list_entry_get_name (dev_list_entry);
+ dev = udev_device_new_from_syspath (handle_udev, path);
+ devpath = udev_device_get_devnode (dev);
+
+ /* Query status with libatasmart */
+ smart_handle_disk (devpath);
+ }
+
+ udev_enumerate_unref (enumerate);
+ udev_unref (handle_udev);
+
+ return (0);
+} /* int smart_read */
+
+void module_register (void)
+{
+ plugin_register_config ("smart", smart_config,
+ config_keys, config_keys_num);
+ plugin_register_read ("smart", smart_read);
+} /* void module_register */
{
ERROR("snmp plugin: Can't allocate memory");
strarray_free(dd->ignores, dd->ignores_len);
- return (ENOMEM);
+ return (ENOMEM);
}
}
return 0;
snmp_free_pdu (res);
res = NULL;
+ /* snmp_synch_response already freed our PDU */
+ req = NULL;
sfree (errstr);
csnmp_host_close_session (host);
static int conn_read (void)
{
struct inpcbtable table;
-#ifdef __OpenBSD__ || __NetBSD_Version__ > 699002700
+#if !defined(__OpenBSD__) && (defined(__NetBSD_Version__) && __NetBSD_Version__ <= 699002700)
struct inpcb *head;
#endif
struct inpcb *next;
if (status != 0)
return (-1);
-#ifdef __OpenBSD__ || __NetBSD_Version__ > 699002700
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
/* inpt_queue is a TAILQ on OpenBSD */
/* Get the first pcb */
next = (struct inpcb *)TAILQ_FIRST (&table.inpt_queue);
kread ((u_long) next, &inpcb, sizeof (inpcb));
/* Advance `next' */
-#ifdef __OpenBSD__ || __NetBSD_Version__ > 699002700
+#if defined(__OpenBSD__) || (defined(__NetBSD_Version__) && __NetBSD_Version__ > 699002700)
/* inpt_queue is a TAILQ on OpenBSD */
next = (struct inpcb *)TAILQ_NEXT (&inpcb, inp_queue);
#else
signal_noise value:GAUGE:U:0
signal_power value:GAUGE:U:0
signal_quality value:GAUGE:0:U
+smart_poweron value:GAUGE:0:U
+smart_powercycles value:GAUGE:0:U
+smart_badsectors value:GAUGE:0:U
+smart_temperature value:GAUGE:-300:300
+smart_attribute current:GAUGE:0:255, worst:GAUGE:0:255, threshold:GAUGE:0:255, pretty:GAUGE:0:U
snr value:GAUGE:0:U
spam_check value:GAUGE:0:U
spam_score value:GAUGE:U:U
#elif HAVE_LIBSTATGRAB
sg_user_stats *us;
+# if HAVE_LIBSTATGRAB_0_90
+ size_t num_entries;
+ us = sg_get_user_stats (&num_entries);
+# else
us = sg_get_user_stats ();
+# endif
if (us == NULL)
return (-1);
- users_submit ((gauge_t) us->num_entries);
+ users_submit ((gauge_t)
+# if HAVE_LIBSTATGRAB_0_90
+ num_entries);
+# else
+ us->num_entries);
+# endif
/* #endif HAVE_LIBSTATGRAB */
#else
#define RIEMANN_HOST "localhost"
#define RIEMANN_PORT "5555"
#define RIEMANN_TTL_FACTOR 2.0
+#define RIEMANN_BATCH_MAX 8192
int write_riemann_threshold_check(const data_set_t *, const value_list_t *, int *);
struct riemann_host {
char *name;
char *event_service_prefix;
-#define F_CONNECT 0x01
+#define F_CONNECT 0x01
uint8_t flags;
- pthread_mutex_t lock;
- _Bool notifications;
- _Bool check_thresholds;
+ pthread_mutex_t lock;
+ _Bool batch_mode;
+ _Bool notifications;
+ _Bool check_thresholds;
_Bool store_rates;
_Bool always_append_ds;
char *node;
char *service;
_Bool use_tcp;
- int s;
+ int s;
double ttl_factor;
-
- int reference_count;
+ Msg *batch_msg;
+ cdtime_t batch_init;
+ int batch_max;
+ int reference_count;
};
static char **riemann_tags;
return (msg);
} /* }}} Msg *riemann_value_list_to_protobuf */
+
+/*
+ * Always call while holding host->lock !
+ */
+static int riemann_batch_flush_nolock (cdtime_t timeout,
+ struct riemann_host *host)
+{
+ cdtime_t now;
+ int status = 0;
+
+ if (timeout > 0) {
+ now = cdtime ();
+ if ((host->batch_init + timeout) > now)
+ return status;
+ }
+ riemann_send_msg(host, host->batch_msg);
+ riemann_msg_protobuf_free(host->batch_msg);
+
+ if (host->use_tcp && ((status = riemann_recv_ack(host)) != 0))
+ riemann_disconnect (host);
+
+ host->batch_init = cdtime();
+ host->batch_msg = NULL;
+ return status;
+}
+
+static int riemann_batch_flush (cdtime_t timeout,
+ const char *identifier __attribute__((unused)),
+ user_data_t *user_data)
+{
+ struct riemann_host *host;
+ int status;
+
+ if (user_data == NULL)
+ return (-EINVAL);
+
+ host = user_data->data;
+ pthread_mutex_lock (&host->lock);
+ status = riemann_batch_flush_nolock (timeout, host);
+ if (status != 0)
+ ERROR ("write_riemann plugin: riemann_send failed with status %i",
+ status);
+
+ pthread_mutex_unlock(&host->lock);
+ return status;
+}
+
+static int riemann_batch_add_value_list (struct riemann_host *host, /* {{{ */
+ data_set_t const *ds,
+ value_list_t const *vl,
+ int *statuses)
+{
+ size_t i;
+ Event **events;
+ Msg *msg;
+ size_t len;
+ int ret;
+
+ msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+ if (msg == NULL)
+ return -1;
+
+ pthread_mutex_lock(&host->lock);
+
+ if (host->batch_msg == NULL) {
+ host->batch_msg = msg;
+ } else {
+ len = msg->n_events + host->batch_msg->n_events;
+ events = realloc(host->batch_msg->events,
+ (len * sizeof(*host->batch_msg->events)));
+ if (events == NULL) {
+ pthread_mutex_unlock(&host->lock);
+ ERROR ("write_riemann plugin: out of memory");
+ riemann_msg_protobuf_free (msg);
+ return -1;
+ }
+ host->batch_msg->events = events;
+
+ for (i = host->batch_msg->n_events; i < len; i++)
+ host->batch_msg->events[i] = msg->events[i - host->batch_msg->n_events];
+
+ host->batch_msg->n_events = len;
+ sfree (msg->events);
+ msg->n_events = 0;
+ sfree (msg);
+ }
+
+ len = msg__get_packed_size(host->batch_msg);
+ ret = 0;
+ if (len >= host->batch_max) {
+ ret = riemann_batch_flush_nolock(0, host);
+ }
+
+ pthread_mutex_unlock(&host->lock);
+ return ret;
+} /* }}} Msg *riemann_batch_add_value_list */
+
static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
{
int status;
if (!host->notifications)
return 0;
+ /*
+ * Never batch for notifications, send them ASAP
+ */
msg = riemann_notification_to_protobuf (host, n);
if (msg == NULL)
return (-1);
const value_list_t *vl,
user_data_t *ud)
{
- int status;
+ int status = 0;
int statuses[vl->values_len];
struct riemann_host *host = ud->data;
Msg *msg;
if (host->check_thresholds)
write_riemann_threshold_check(ds, vl, statuses);
- msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
- if (msg == NULL)
- return (-1);
- status = riemann_send (host, msg);
- if (status != 0)
- ERROR ("write_riemann plugin: riemann_send failed with status %i",
- status);
+ if (host->use_tcp == 1 && host->batch_mode) {
- riemann_msg_protobuf_free (msg);
+ riemann_batch_add_value_list (host, ds, vl, statuses);
+
+
+ } else {
+
+ msg = riemann_value_list_to_protobuf (host, ds, vl, statuses);
+ if (msg == NULL)
+ return (-1);
+
+ status = riemann_send (host, msg);
+ if (status != 0)
+ ERROR ("write_riemann plugin: riemann_send failed with status %i",
+ status);
+
+ riemann_msg_protobuf_free (msg);
+ }
return status;
} /* }}} int riemann_write */
host->store_rates = 1;
host->always_append_ds = 0;
host->use_tcp = 0;
+ host->batch_mode = 0;
+ host->batch_max = RIEMANN_BATCH_MAX; /* typical MSS */
+ host->batch_init = cdtime();
host->ttl_factor = RIEMANN_TTL_FACTOR;
status = cf_util_get_string (ci, &host->name);
status = cf_util_get_boolean(child, &host->check_thresholds);
if (status != 0)
break;
+ } else if (strcasecmp ("Batch", child->key) == 0) {
+ status = cf_util_get_boolean(child, &host->batch_mode);
+ if (status != 0)
+ break;
+ } else if (strcasecmp("BatchMaxSize", child->key) == 0) {
+ status = cf_util_get_int(child, &host->batch_max);
+ if (status != 0)
+ break;
} else if (strcasecmp ("Port", child->key) == 0) {
status = cf_util_get_service (child, &host->service);
if (status != 0) {
pthread_mutex_lock (&host->lock);
status = plugin_register_write (callback_name, riemann_write, &ud);
+
+ if (host->use_tcp == 1 && host->batch_mode) {
+ ud.free_func = NULL;
+ plugin_register_flush(callback_name, riemann_batch_flush, &ud);
+ }
if (status != 0)
WARNING ("write_riemann plugin: plugin_register_write (\"%s\") "
"failed with status %i.",