+2009-09-13, Version 4.8.0
+
+ * collectd: Two new data source types, “DERIVE” and “ABSOLUTE”, have
+ been added. “DERIVE” can be used for counters that are reset
+ occasionally. Thanks to Mariusz Gronczewski for implementing this.
+ * thresholds: The advanced threshold options “Percentage”, “Hits”, and
+ “Hysteresis” have been added. Thanks to Andrés J. Díaz for hit
+ patches.
+ * curl_json plugin: The new cURL-JSON plugin reads JSON files using
+ the cURL library and parses the contents according to user
+ specification. Among other things, this allows to read statistics
+ from a CouchDB instance. Thanks to Doug MacEachern for the patch.
+ * df plugin: Using the new “ReportByDevice” option the device rather
+ than the mount point can be used to identify partitions. Thanks to
+ Paul Sadauskas for the patch.
+ * dns plugin: The possibility to ignore numeric QTypes has been added.
+ Thanks to Mirko Buffoni for the patch.
+ * GenericJMX plugin: The new, Java-based GenericJMX plugin allows to
+ query arbitrary data from a Java process using the “Java Management
+ Extensions” (JMX).
+ * madwifi plugin: The new MadWifi plugin collects information about
+ Atheros wireless LAN chipsets from the MadWifi driver. Thanks to
+ Ondrej Zajicek for his patches.
+ * network plugin: The receive- and send-buffer-sizes have been made
+ configurable, allowing for bigger and smaller packets. Thanks to
+ Aman Gupta for the patch.
+ * olsrd plugin: The new OLSRd plugin queries routing information from
+ the “Optimized Link State Routing” daemon.
+ * rrdtool plugin: A new configuration option allows to define a random
+ write delay when writing RRD files. This spreads the load created by
+ writing RRD files more evenly. Thanks to Mariusz Gronczewski for the
+ patch.
+ * swap plugin: The possibility to collect swapped in/out pages has
+ been added to the Swap plugin. Thanks to Stefan Völkel for the
+ patch.
+ * tokyotyrant plugin: The new TokyoTyrant plugin reads the number of
+ records and file size from a running Tokyo Tyrant server. Thanks to
+ Paul Sadauskas for the patch.
+ * write_http plugin: The new Write HTTP plugin sends the values
+ collected by collectd to a web-server using HTTP POST requests.
+ Thanks to Paul Sadauskas for the patch.
+ * zfs_arc plugin: The new ZFS ARC plugin collects information about
+ the “Adaptive Replacement Cache” (ARC) of the “Zeta File-System”
+ (ZFS). Thanks to Anthony Dewhurst for the patch.
+ * empty_counter match: The new Empty Counter match matches value
+ lists, where at least one data source is of type COUNTER and the
+ counter value of all counter data sources is zero.
+
+ 2009-09-13, Version 4.7.3
+ * collectd: Fix a possible but very rare invalid “free” in the caching
+ code. Thanks to Sebastian Harl for the patch.
+ * collectd: Remove old values when a cache entry is marked as missing.
+ This way the “GETVAL” command of the UnixSock plugin doesn't return
+ old, no longer valid values when this happens. Thanks to Andrés J.
+ Díaz for the patch.
+ * collectd: The “plugin_unregister_read” function has been fixed.
+ * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+ to follow redirects. Thanks to Joey Hess for reporting this bug.
+ * df plugin: Check the ignorelist before stating the file system,
+ possibly reducing the number of stats considerably. Thanks to Joey
+ Hess for reporting this bug.
+ * iptables plugin: Support for the new libiptc API has been added.
+ Thanks to Sebastian Harl for the patch. The build system has been
+ updated to the plugin only includes the shipped header files when it
+ is linked with the shipped library, too.
+ * java plugin: Delay creating the JVM until after the daemon has
+ forked. The JVM internally creates threads that are lost when
+ forking. This means that Java-based plugins are now configured
+ during the init-phase, i. e. later than other plugins.
+ * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+ to Alan Pevec for the patch.
+ * network plugin: Fix the handling of the “CacheFlush” option: The
+ value was assigned to a wrong variable. The initialization of the
+ gcrypt library, which is used for signing / encrypting traffic, has
+ been fixed. Thanks to Luke Heberling for the patch.
+ * powerdns plugin: Set a timeout when reading data from the datagram
+ socket. Handling of the “LocalSocket” option has been fixed. An
+ incorrectly used “type” has been corrected. Thanks to Luke Heberling
+ for his patches.
+
2009-07-19, Version 4.7.2
* Build system: Support for `DESTDIR' has been fixed in the Java
bindings.
* uptime plugin: The new uptime plugin can collect the server's
uptime. Thanks to Marco Chiappero for the patch.
+ 2009-09-10, Version 4.6.5
+ * collectd: Remove old values when a cache entry is marked as missing.
+ This way the “GETVAL” command of the UnixSock plugin doesn't return
+ old, no longer valid values when this happens. Thanks to Andrés J.
+ Díaz for the patch.
+ * apache, ascent, bind, curl, nginx plugins: Advise the cURL library
+ to follow redirects. Thanks to Joey Hess for reporting this bug.
+ * df plugin: Check the ignorelist before stating the file system,
+ possibly reducing the number of stats considerably. Thanks to Joey
+ Hess for reporting this bug.
+ * iptables plugin: Support for the new libiptc API has been added.
+ Thanks to Sebastian Harl for the patch. The build system has been
+ updated to the plugin only includes the shipped header files when it
+ is linked with the shipped library, too.
+ * libvirt plugin: Re-connect to libvirtd if connecting fails. Thanks
+ to Alan Pevec for the patch.
+ * powerdns plugin: Set a timeout when reading data from the datagram
+ socket. Handling of the “LocalSocket” option has been fixed. An
+ incorrectly used “type” has been corrected. Thanks to Luke Heberling
+ for his patches.
+
2009-07-18, Version 4.6.4
* collectd: Okay-notifications have been fixed. Thanks to Andrés J.
Díaz for fixing this bug.
2005-07-08, Version 1.3: CPU stats
* Collecting CPU statistics now
- 2004-07-12, Version 1.2: Using syslog
+ 2005-07-12, Version 1.2: Using syslog
* collectd is now using the syslog facility to report errors, warnings
and the like..
* The default directory is now /var/db/collectd
- 2004-07-10, Version 1.1: Minor changes
+ 2005-07-10, Version 1.1: Minor changes
* Nothing really useful to say ;)
- 2004-07-09, Version 1.0: Initial Version
+ 2005-07-09, Version 1.0: Initial Version
* The following modules are provided:
* Load average
* Ping time
- conntrack
Number of nf_conntrack entries.
+ - curl_json
+ Retrieves JSON data via cURL and parses it according to user
+ configuration.
+
- cpu
CPU utilization: Time spent in the system, user, nice, idle, and related
states.
- libvirt
CPU, disk and network I/O statistics from virtual machines.
+ - madwifi
+ Queries very detailed usage statistics from wireless LAN adapters and
+ interfaces that use the Atheros chipset and the MadWifi driver.
+
- mbmon
Motherboard sensors: temperature, fanspeed and voltage information,
using mbmon(1).
Network UPS tools: UPS current, voltage, power, charge, utilisation,
temperature, etc. See upsd(8).
+ - olsr
+ Queries routing information from the “Optimized Link State Routing”
+ daemon.
+
- onewire (EXPERIMENTAL!)
Read onewire sensors using the owcapu library of the owfs project.
Please read in collectd.conf(5) why this plugin is experimental.
- thermal
Linux ACPI thermal zone information.
+ - tokyotyrant
+ Reads the number of records and file size from a running Tokyo Tyrant
+ server.
+
- uptime
System uptime statistics.
- xmms
Bitrate and frequency of music played with XMMS.
+ - zfs_arc
+ Statistics for ZFS' “Adaptive Replacement Cache” (ARC).
+
* Output can be written or send to various destinations by the following
plugins:
needed. Please read collectd-unixsock(5) for a description on how that's
done.
+ - write_http
+ Sends the values collected by collectd to a web-server using HTTP POST
+ requests. The transmitted data is either in a form understood by the
+ Exec plugin or formatted in JSON.
+
* Logging is, as everything in collectd, provided by plugins. The following
plugins keep up informed about what's going on:
* Value processing can be controlled using the "filter chain" infrastructure
and "matches" and "targets". The following plugins are available:
+ - match_empty_counter
+ Match counter values which are currently zero.
+
- match_regex
Match values by their identifier based on regular expressions.
Used by the `oracle' plugin.
* libcurl (optional)
- If you want to use the `apache', `ascent', `curl' or `nginx' plugin.
+ If you want to use the `apache', `ascent', `curl', `nginx', or `write_http'
+ plugin.
<http://curl.haxx.se/>
* libdbi (optional)
For the `notify_desktop' plugin.
<http://www.galago-project.org/>
- * liboping (optional, if not found a version shipped with this distribution
- can be used)
+ * liboping (optional)
Used by the `ping' plugin to send and receive ICMP packets.
<http://verplant.org/liboping/>
* libxmms (optional)
<http://www.xmms.org/>
+ * libyajl (optional)
+ Parse JSON data. This is needed for the `curl_json' plugin.
+ <http://www.lloydforge.org/projects/yajl/>
Configuring / Compiling / Installing
------------------------------------
])
# For the swap module
+have_linux_wireless_h="no"
+if test "x$ac_system" = "xLinux"
+then
+ AC_CHECK_HEADERS(linux/wireless.h,
+ [have_linux_wireless_h="yes"],
+ [have_linux_wireless_h="no"],
+[
+#include <dirent.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+])
+fi
+
+# For the swap module
have_sys_swap_h="yes"
AC_CHECK_HEADERS(sys/swap.h vm/anon.h, [], [have_sys_swap_h="no"],
[
with_own_libiptc="no"
],
[
- #include "$srcdir/src/libiptc/ipt_kernel_headers.h"
+ #include "$srcdir/src/owniptc/ipt_kernel_headers.h"
])
CFLAGS=$SAVE_CFLAGS
then
AC_DEFINE(OWN_LIBIPTC, 1, [Define to 1 if we use the shipped iptc library.])
fi
+ if test "x$with_libiptc" = "xyes"
+ then
+ SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS $KERNEL_CFLAGS"
+
+ AC_CHECK_TYPES([iptc_handle_t, ip6tc_handle_t], [], [],
+ [
+ #if OWN_LIBIPTC
+ # include "$srcdir/src/owniptc/libiptc.h"
+ # include "$srcdir/src/owniptc/libip6tc.h"
+ #else
+ # include <libiptc/libiptc.h>
+ # include <libiptc/libip6tc.h>
+ #endif
+ ])
+
+ CFLAGS=$SAVE_CFLAGS
+ fi
# }}}
# --with-java {{{
fi
# }}}
+# --with-libtokyotyrant {{{
+with_libtokyotyrant_cppflags=""
+with_libtokyotyrant_ldflags=""
+with_libtokyotyrant_libs=""
+AC_ARG_WITH(libtokyotyrant, [AS_HELP_STRING([--with-libtokyotyrant@<:@=PREFIX@:>@], [Path to libtokyotyrant.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_libtokyotyrant="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libtokyotyrant="yes"
+ else
+ with_libtokyotyrant_cppflags="-I$withval/include"
+ with_libtokyotyrant_ldflags="-L$withval/include"
+ with_libtokyotyrant_libs="-ltokyotyrant"
+ with_libtokyotyrant="yes"
+ fi; fi
+],
+[
+ with_libtokyotyrant="yes"
+])
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+ 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`"
+ fi
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+CPPFLAGS="$CPPFLAGS $with_libtokyotyrant_cppflags"
+LDFLAGS="$LDFLAGS $with_libtokyotyrant_ldflags"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+ AC_CHECK_HEADERS(tcrdb.h,
+ [
+ AC_DEFINE(HAVE_TCRDB_H, 1,
+ [Define to 1 if you have the <tcrdb.h> header file.])
+ ], [with_libtokyotyrant="no (tcrdb.h not found)"])
+fi
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+ AC_CHECK_LIB(tokyotyrant, tcrdbrnum,
+ [
+ AC_DEFINE(HAVE_LIBTOKYOTYRANT, 1,
+ [Define to 1 if you have the tokyotyrant library (-ltokyotyrant).])
+ ],
+ [with_libtokyotyrant="no (symbol tcrdbrnum not found)"],
+ [$with_libtokyotyrant_libs])
+fi
+
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+
+if test "x$with_libtokyotyrant" = "xyes"
+then
+ BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS="$with_libtokyotyrant_cppflags"
+ BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS="$with_libtokyotyrant_ldflags"
+ BUILD_WITH_LIBTOKYOTYRANT_LIBS="$with_libtokyotyrant_libs"
+ AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBTOKYOTYRANT, test "x$with_libtokyotyrant" = "xyes")
+# }}}
+
# --with-libupsclient {{{
with_libupsclient_config=""
with_libupsclient_cflags=""
AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
# }}}
+# --with-libyajl {{{
+with_libyajl_cppflags=""
+with_libyajl_ldflags=""
+AC_ARG_WITH(libyajl, [AS_HELP_STRING([--with-libyajl@<:@=PREFIX@:>@], [Path to libyajl.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libyajl_cppflags="-I$withval/include"
+ with_libyajl_ldflags="-L$withval/lib"
+ with_libyajl="yes"
+ else
+ with_libyajl="$withval"
+ fi
+],
+[
+ with_libyajl="yes"
+])
+if test "x$with_libyajl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+
+ AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+ LDFLAGS="$LDFLAGS $with_libyajl_ldflags"
+
+ AC_CHECK_LIB(yajl, yajl_alloc, [with_libyajl="yes"], [with_libyajl="no (Symbol 'yajl_alloc' not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+ BUILD_WITH_LIBYAJL_CPPFLAGS="$with_libyajl_cppflags"
+ BUILD_WITH_LIBYAJL_LDFLAGS="$with_libyajl_ldflags"
+ BUILD_WITH_LIBYAJL_LIBS="-lyajl"
+ AC_SUBST(BUILD_WITH_LIBYAJL_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBYAJL_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBYAJL_LIBS)
+ AC_DEFINE(HAVE_LIBYAJL, 1, [Define if libyajl is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
+# }}}
+
# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
with_libxml2="no (pkg-config isn't available)"
with_libxml2_cflags=""
plugin_conntrack="no"
plugin_cpu="no"
plugin_cpufreq="no"
+plugin_curl_json="no"
plugin_df="no"
plugin_disk="no"
plugin_entropy="no"
plugin_vmem="no"
plugin_vserver="no"
plugin_wireless="no"
+plugin_zfs_arc="no"
# Linux
if test "x$ac_system" = "xLinux"
if test "x$with_kstat" = "xyes"
then
plugin_uptime="yes"
+ plugin_zfs_arc="yes"
fi
if test "x$with_devinfo$with_kstat" = "xyesyes"
plugin_ipmi="yes"
fi
+if test "x$with_libcurl" = "xyes" && test "x$with_libyajl" = "xyes"
+then
+ plugin_curl_json="yes"
+fi
+
if test "x$have_processor_info" = "xyes"
then
plugin_cpu="yes"
AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
AC_PLUGIN([csv], [yes], [CSV output plugin])
AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics])
+AC_PLUGIN([curl_json], [$plugin_curl_json], [CouchDB 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([libvirt], [$plugin_libvirt], [Virtual machine statistics])
AC_PLUGIN([load], [$plugin_load], [System load])
AC_PLUGIN([logfile], [yes], [File logging plugin])
+AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics])
+AC_PLUGIN([match_empty_counter], [yes], [The empty counter match])
AC_PLUGIN([match_regex], [yes], [The regex match])
AC_PLUGIN([match_timediff], [yes], [The timediff match])
AC_PLUGIN([match_value], [yes], [The value match])
AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
AC_PLUGIN([ntpd], [yes], [NTPd statistics])
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
+AC_PLUGIN([olsrd], [yes], [olsrd statistics])
AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics])
AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin])
AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values])
AC_PLUGIN([thermal], [$plugin_thermal], [Linux ACPI thermal zone statistics])
+AC_PLUGIN([tokyotyrant], [$with_libtokyotyrant], [TokyoTyrant database statistics])
AC_PLUGIN([unixsock], [yes], [Unixsock communication plugin])
AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics])
AC_PLUGIN([users], [$plugin_users], [User statistics])
AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics])
AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
+AC_PLUGIN([write_http], [$with_libcurl], [HTTP output plugin])
AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics])
+AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics])
dnl Default configuration file
# Load either syslog or logfile
AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h)
- AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libiptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
+ AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/owniptc/Makefile src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile)
if test "x$with_librrd" = "xyes" \
&& test "x$librrd_threadsafe" != "xyes"
librrd . . . . . . . $with_librrd
libsensors . . . . . $with_libsensors
libstatgrab . . . . . $with_libstatgrab
+ libtokyotyrant . . . $with_libtokyotyrant
libupsclient . . . . $with_libupsclient
libvirt . . . . . . . $with_libvirt
libxml2 . . . . . . . $with_libxml2
libxmms . . . . . . . $with_libxmms
+ libyajl . . . . . . . $with_libyajl
oracle . . . . . . . $with_oracle
Features:
cpufreq . . . . . . . $enable_cpufreq
csv . . . . . . . . . $enable_csv
curl . . . . . . . . $enable_curl
+ curl_json . . . . . . $enable_curl_json
dbi . . . . . . . . . $enable_dbi
df . . . . . . . . . $enable_df
disk . . . . . . . . $enable_disk
libvirt . . . . . . . $enable_libvirt
load . . . . . . . . $enable_load
logfile . . . . . . . $enable_logfile
+ madwifi . . . . . . . $enable_madwifi
+ match_empty_counter . $enable_match_empty_counter
match_regex . . . . . $enable_match_regex
match_timediff . . . $enable_match_timediff
match_value . . . . . $enable_match_value
notify_email . . . . $enable_notify_email
ntpd . . . . . . . . $enable_ntpd
nut . . . . . . . . . $enable_nut
+ olsrd . . . . . . . . $enable_olsrd
onewire . . . . . . . $enable_onewire
openvpn . . . . . . . $enable_openvpn
oracle . . . . . . . $enable_oracle
teamspeak2 . . . . . $enable_teamspeak2
ted . . . . . . . . . $enable_ted
thermal . . . . . . . $enable_thermal
+ tokyotyrant . . . . . $enable_tokyotyrant
unixsock . . . . . . $enable_unixsock
uptime . . . . . . . $enable_uptime
users . . . . . . . . $enable_users
vmem . . . . . . . . $enable_vmem
vserver . . . . . . . $enable_vserver
wireless . . . . . . $enable_wireless
+ write_http . . . . . $enable_write_http
xmms . . . . . . . . $enable_xmms
+ zfs_arc . . . . . . . $enable_zfs_arc
EOF
Color starting ff00ff
Color waiting ffb000
</Type>
+<Type arc_counts>
+ Module ArcCounts
+ RRDTitle "ARC {type_instance} on {hostname}"
+# RRDOptions ...
+</Type>
+<Type arc_l2_bytes>
+ Module GenericIO
+ DataSources read write
+ DSName "read Read "
+ DSName "write Written"
+ RRDTitle "L2ARC traffic"
+ RRDVerticalLabel "Bytes per second"
+# RRDOptions ...
+ RRDFormat "%5.1lf%s"
+</Type>
+<Type arc_l2_size>
+ RRDTitle "L2ARC size on {hostname}"
+ RRDVerticalLabel "Size"
+ RRDFormat "%4.0lf%s"
+ RRDOptions -b 1024
+ DSName "value Current size"
+ Color value 00e000
+</Type>
+<Type arc_size>
+ DataSources "current target minlimit maxlimit"
+ RRDTitle "ARC size on {hostname}"
+ RRDVerticalLabel "Size"
+ RRDFormat "%4.0lf%s"
+ RRDOptions -b 1024
+ DSName "current Current size"
+ DSName "target Target size "
+ DSName "maxlimit Max size "
+ DSName "minlimit Min size "
+ Color current 00e000
+ Color target 0000ff
+ Color minlimit ff0000
+ Color maxlimit ff00ff
+</Type>
+<Type arc_ratio>
+ DataSources value
+ RRDTitle "{type_instance}ARC ratio on {hostname}"
+ RRDVerticalLabel "Ratio"
+ RRDFormat "%4.1lf"
+ RRDOptions -l 0
+ DSName "value Hit ratio"
+</Type>
+ <Type cache_ratio>
+ DataSources value
+ DSName value Percent
+ RRDTitle "Cache hit ratio for {plugin_instance} {type_instance}"
+ RRDVerticalLabel "Percent"
+ RRDFormat "%5.1lf %%"
+ </Type>
<Type cpu>
Module GenericStacked
DataSources value
Module Df
DataSources free used
</Type>
+ <Type df_complex>
+ Module GenericStacked
+ DataSources value
+ RRDTitle "disk usage on {plugin_instance}"
+ RRDVerticalLabel "Byte"
+ RRDFormat "%6.2lf%s"
+ DSName "snap_used used for snapshots"
+ DSName "snap_reserved snapshot reserve "
+ DSName "used in use "
+ DSName "free free "
+ DSName "sis_saved sis_saved "
+ Order free snap_used snap_reserved sis_saved used
+ Color snap_reverse ff8000
+ Color used ff0000
+ Color snap_used 000080
+ Color snap_reserved ff8000
+ Color free 00ff00
+ Color sis_saved 00e0e0
+ </Type>
+ <Type disk_latency>
+ Module GenericIO
+ DataSources read write
+ DSName "read Read "
+ DSName write Write
+ RRDTitle "Disk Latency for {plugin_instance}"
+ RRDVerticalLabel "microseconds"
+ Scale 0.000001
+ RRDFormat "%5.1lf %ss"
+ </Type>
<Type disk_octets>
Module GenericIO
DataSources read write
# RRDOptions ...
RRDFormat "%5.1lf"
</Type>
+ <Type disk_ops_complex>
+ Module GenericStacked
+ DataSources value
+ RRDTitle "Netapp disc ops on {plugin_instance}"
+ RRDVerticalLabel "Ops"
+ RRDFormat "%6.2lf"
+ DSName fcp_ops FCP-Ops
+ DSName nfs_ops NFS-Ops
+ DSName http_ops HTTP-Ops
+ DSName cifs_ops CIFS-Ops
+ DSName dafs_ops DAFS-Ops
+ DSName iscsi_ops iSCSI-Ops
+ Order fcp_ops nfs_ops http_ops cifs_ops dafs_ops iscsi_ops
+ Color fcp_ops 000080
+ Color nfs_ops ff0000
+ Color http_ops ffb000
+ Color cifs_ops 00e0a0
+ Color dafs_ops 00e000
+ Color iscsi_ops 00e0ff
+ </Type>
<Type disk_merged>
Module GenericIO
DataSources read write
<Type load>
Module Load
</Type>
+ <Type java_memory>
+ Module JavaMemory
+ DataSources value
+ </Type>
<Type memory>
Module GenericStacked
DataSources value
RRDVerticalLabel "°Celsius"
RRDFormat "%4.1lf°C"
</Type>
+ <Type total_time_in_ms>
+ DataSources value
+ DSName "value Time"
+ RRDTitle "Time {instance}"
+ RRDVerticalLabel "Seconds"
+ RRDFormat "%6.2lf %ss"
+ Scale 0.001
+ </Type>
<Type users>
DataSources users
DSName users Users
HELP => \&cmd_help,
PUTVAL => \&putval,
GETVAL => \&getval,
+ GETTHRESHOLD => \&getthreshold,
FLUSH => \&flush,
LISTVAL => \&listval,
PUTNOTIF => \&putnotif,
=cut
sub cmd_help {
- print <<HELP;
+ my $sock = shift;
+ my $line = shift || '';
+
+ my @line = tokenize($line);
+ my $cmd = shift (@line);
+
+ my %text = (
+ help => <<HELP,
Available commands:
HELP
PUTVAL
GETVAL
+ GETTHRESHOLD
FLUSH
LISTVAL
PUTNOTIF
See the embedded Perldoc documentation for details. To do that, run:
perldoc $0
HELP
+ putval => <<HELP,
+ PUTVAL <id> <value0> [<value1> ...]
+
+ Submits a value to the daemon.
+ HELP
+ getval => <<HELP,
+ GETVAL <id>
+
+ Retrieves the current value or values from the daemon.
+ HELP
+ flush => <<HELP,
+ FLUSH [plugin=<plugin>] [timeout=<timeout>] [identifier=<id>] [...]
+
+ Sends a FLUSH command to the daemon.
+ HELP
+ listval => <<HELP,
+ LISTVAL
+
+ Prints a list of available values.
+ HELP
+ putnotif => <<HELP
+ PUTNOTIF severity=<severity> [...] message=<message>
+
+ Sends a notifications message to the daemon.
+ HELP
+ );
+
+ if (!$cmd)
+ {
+ $cmd = 'help';
+ }
+ if (!exists ($text{$cmd}))
+ {
+ print STDOUT "Unknown command: " . uc ($cmd) . "\n\n";
+ $cmd = 'help';
+ }
+
+ print STDOUT $text{$cmd};
+
return 1;
} # cmd_help
return 1;
}
+=item B<GETTHRESHOLD> I<Identifier>
+
+=cut
+
+sub getthreshold {
+ my $sock = shift || return;
+ my $line = shift || return;
+
+ my @line = tokenize($line);
+
+ my $id;
+ my $vals;
+
+ if (! @line) {
+ return;
+ }
+
+ if (scalar(@line) < 1) {
+ print STDERR "Synopsis: GETTHRESHOLD <id>" . $/;
+ return;
+ }
+
+ $id = getid($line[0]);
+
+ if (! $id) {
+ print STDERR "Invalid id \"$line[0]\"." . $/;
+ return;
+ }
+
+ $vals = $sock->getthreshold(%$id);
+
+ if (! $vals) {
+ print STDERR "socket error: " . $sock->{'error'} . $/;
+ return;
+ }
+
+ foreach my $key (keys %$vals) {
+ print "\t$key: $vals->{$key}\n";
+ }
+ return 1;
+}
+
=item B<FLUSH> [B<timeout>=I<$timeout>] [B<plugin>=I<$plugin>[ ...]]
=cut
$args{"timeout"} = $value;
}
elsif ($option eq "identifier") {
- my $id = getid (\$value);
+ my $id = getid ($value);
if (!$id)
{
print STDERR "Not a valid identifier: \"$value\"\n";
SUBDIRS = libcollectdclient
if BUILD_WITH_OWN_LIBIPTC
- SUBDIRS += libiptc
+ SUBDIRS += owniptc
endif
if BUILD_WITH_OWN_LIBOCONFIG
SUBDIRS += liboconfig
collectd_DEPENDENCIES += curl.la
endif
+if BUILD_PLUGIN_CURL_JSON
+pkglib_LTLIBRARIES += curl_json.la
+curl_json_la_SOURCES = curl_json.c
+curl_json_la_CFLAGS = $(AM_CFLAGS)
+curl_json_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_CPPFLAGS = $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+if BUILD_WITH_LIBCURL
+curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+collectd_LDADD += "-dlopen" curl_json.la
+collectd_DEPENDENCIES += curl_json.la
+endif
+
if BUILD_PLUGIN_DBI
pkglib_LTLIBRARIES += dbi.la
dbi_la_SOURCES = dbi.c \
iptables_la_SOURCES = iptables.c
iptables_la_LDFLAGS = -module -avoid-version
if BUILD_WITH_OWN_LIBIPTC
- iptables_la_LIBADD = libiptc/libiptc.la
- iptables_la_DEPENDENCIES = libiptc/libiptc.la
+ iptables_la_LIBADD = owniptc/libiptc.la
+ iptables_la_DEPENDENCIES = owniptc/libiptc.la
else
iptables_la_LIBADD = -liptc
endif
collectd_DEPENDENCIES += logfile.la
endif
+if BUILD_PLUGIN_MADWIFI
+pkglib_LTLIBRARIES += madwifi.la
+madwifi_la_SOURCES = madwifi.c madwifi.h
+madwifi_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" madwifi.la
+collectd_DEPENDENCIES += madwifi.la
+endif
+
+if BUILD_PLUGIN_MATCH_EMPTY_COUNTER
+pkglib_LTLIBRARIES += match_empty_counter.la
+match_empty_counter_la_SOURCES = match_empty_counter.c
+match_empty_counter_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" match_empty_counter.la
+collectd_DEPENDENCIES += match_empty_counter.la
+endif
+
if BUILD_PLUGIN_MATCH_REGEX
pkglib_LTLIBRARIES += match_regex.la
match_regex_la_SOURCES = match_regex.c
collectd_DEPENDENCIES += nut.la
endif
+if BUILD_PLUGIN_OLSRD
+pkglib_LTLIBRARIES += olsrd.la
+olsrd_la_SOURCES = olsrd.c
+olsrd_la_LDFLAGS = -module -avoid-version
+olsrd_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+olsrd_la_LIBADD += -lsocket
+endif
+collectd_LDADD += "-dlopen" olsrd.la
+collectd_DEPENDENCIES += olsrd.la
+endif
+
if BUILD_PLUGIN_ONEWIRE
pkglib_LTLIBRARIES += onewire.la
onewire_la_SOURCES = onewire.c
collectd_DEPENDENCIES += thermal.la
endif
+if BUILD_PLUGIN_TOKYOTYRANT
+pkglib_LTLIBRARIES += tokyotyrant.la
+tokyotyrant_la_SOURCES = tokyotyrant.c
+tokyotyrant_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBTOKYOTYRANT_CPPFLAGS)
+tokyotyrant_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBTOKYOTYRANT_LDFLAGS)
+tokyotyrant_la_LIBADD = $(BUILD_WITH_LIBTOKYOTYRANT_LIBS)
+if BUILD_WITH_LIBSOCKET
+tokyotyrant_la_LIBADD += -lsocket
+endif
+collectd_LDADD += "-dlopen" tokyotyrant.la
+collectd_DEPENDENCIES += tokyotyrant.la
+endif
+
if BUILD_PLUGIN_UNIXSOCK
pkglib_LTLIBRARIES += unixsock.la
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 += wireless.la
endif
+if BUILD_PLUGIN_WRITE_HTTP
+pkglib_LTLIBRARIES += write_http.la
+write_http_la_SOURCES = write_http.c \
+ utils_format_json.c utils_format_json.h
+write_http_la_LDFLAGS = -module -avoid-version
+write_http_la_CFLAGS = $(AM_CFLAGS)
+write_http_la_LIBADD =
+collectd_LDADD += "-dlopen" write_http.la
+if BUILD_WITH_LIBCURL
+write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+collectd_DEPENDENCIES += write_http.la
+endif
+
if BUILD_PLUGIN_XMMS
pkglib_LTLIBRARIES += xmms.la
xmms_la_SOURCES = xmms.c
collectd_DEPENDENCIES += xmms.la
endif
+if BUILD_PLUGIN_ZFS_ARC
+pkglib_LTLIBRARIES += zfs_arc.la
+zfs_arc_la_SOURCES = zfs_arc.c
+zfs_arc_la_CFLAGS = $(AM_CFLAGS)
+zfs_arc_la_LDFLAGS = -module -avoid-version
+zfs_arc_la_LIBADD = -lkstat
+collectd_LDADD += "-dlopen" zfs_arc.la
+collectd_DEPENDENCIES += zfs_arc.la
+endif
+
dist_man_MANS = collectd.1 \
collectd.conf.5 \
#@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
+#@BUILD_PLUGIN_COUCHDB_TRUE@LoadPlugin couchdb
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
@LOAD_PLUGIN_CSV@LoadPlugin csv
#@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
#@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
+#@BUILD_PLUGIN_HTTP_TRUE@LoadPlugin http
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPTABLES_TRUE@LoadPlugin iptables
#@BUILD_PLUGIN_IPMI_TRUE@LoadPlugin ipmi
#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
+#@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
#@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
#@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
#@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
#@BUILD_PLUGIN_TEAMSPEAK2_TRUE@LoadPlugin teamspeak2
#@BUILD_PLUGIN_TED_TRUE@LoadPlugin ted
#@BUILD_PLUGIN_THERMAL_TRUE@LoadPlugin thermal
+#@BUILD_PLUGIN_TOKYOTYRANT_TRUE@LoadPlugin tokyotyrant
#@BUILD_PLUGIN_UNIXSOCK_TRUE@LoadPlugin unixsock
#@BUILD_PLUGIN_UPTIME_TRUE@LoadPlugin uptime
#@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
#@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
#@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
#@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
+#@BUILD_PLUGIN_WRITE_HTTP_TRUE@LoadPlugin write_http
#@BUILD_PLUGIN_XMMS_TRUE@LoadPlugin xmms
+#@BUILD_PLUGIN_ZFS_ARC_TRUE@LoadPlugin zfs_arc
##############################################################################
# Plugin configuration #
# </View>
#</Plugin>
+#<Plugin couchdb>
+## See: http://wiki.apache.org/couchdb/Runtime_Statistics
+# <URL "http://localhost:5984/_stats">
+# Instance "httpd"
+# <Key "httpd/requests/count">
+# Type "http_requests"
+# </Key>
+#
+# <Key "httpd_request_methods/*/count">
+# Type "http_request_methods"
+# </Key>
+#
+# <Key "httpd_status_codes/*/count">
+# Type "http_response_codes"
+# </Key>
+# </URL>
+## Database status metrics:
+# <URL "http://localhost:5984/_all_dbs">
+# Instance "dbs"
+# <Key "*/doc_count">
+# Type "gauge"
+# </Key>
+# <Key "*/doc_del_count">
+# Type "counter"
+# </Key>
+# <Key "*/disk_size">
+# Type "bytes"
+# </Key>
+# </URL>
+#</Plugin>
+
#<Plugin csv>
# DataDir "@prefix@/var/lib/@PACKAGE_NAME@/csv"
# StoreRates false
# MountPoint "/home"
# FSType "ext3"
# IgnoreSelected false
+# ReportByDevice false
#</Plugin>
#<Plugin disk>
# TranslateDevicename false
#</Plugin>
+#<Plugin http>
+# URL "http://example.com/collectd-import"
+# User "www-user"
+# Password "secret"
+#</Plugin>
+
#<Plugin interface>
# Interface "eth0"
# IgnoreSelected false
#<Plugin "java">
# JVMArg "-verbose:jni"
-# JVMArg "-Djava.class.path=/opt/collectd/lib/collectd/bindings/java"
+# JVMArg "-Djava.class.path=@prefix@/share/collectd/java"
#
# LoadPlugin "org.collectd.java.Foobar"
# <Plugin "org.collectd.java.Foobar">
# UPS "upsname@hostname:port"
#</Plugin>
+#<Plugin olsrd>
+# Host "127.0.0.1"
+# Port "2006"
+# CollectLinks "Summary"
+# CollectRoutes "Summary"
+# CollectTopology "Summary"
+#</Plugin>
+
#<Plugin onewire>
# Device "-s localhost:4304"
# Sensor "F10FCA000800"
# Version 1
# Community "community_string"
# Collect "std_traffic"
-# Inverval 120
+# Interval 120
# </Host>
# <Host "some.server.mydomain.org">
# Address "192.168.0.42"
# IgnoreSelected false
#</Plugin>
+#<Plugin tokyotyrant>
+# Host "localhost"
+# Port "1978"
+#</Plugin>
+
#<Plugin unixsock>
# SocketFile "@prefix@/var/run/@PACKAGE_NAME@-unixsock"
# SocketGroup "collectd"
# Verbose false
#</Plugin>
+#<Plugin write_http>
+# <URL "http://example.com/collectd-post">
+# User "collectd"
+# Password "weCh3ik0"
+# </URL>
+#</Plugin>
+
##############################################################################
# Filter configuration #
#----------------------------------------------------------------------------#
# configured at all: All values will be sent to all available write plugins. #
#----------------------------------------------------------------------------#
- #<Chain "Main">
+ #<Chain "PostCache">
# Target "write"
#</Chain>
else
dstype = 0;
}
+else if (strncasecmp ("Derive", ci->values[0].value.string,
+ strlen ("Derive")) == 0)
+ {
+ dstype = UTILS_MATCH_DS_TYPE_DERIVE;
+ if (strcasecmp ("DeriveSet", ci->values[0].value.string) == 0)
+ dstype |= UTILS_MATCH_CF_DERIVE_SET;
+ else if (strcasecmp ("DeriveAdd", ci->values[0].value.string) == 0)
+ dstype |= UTILS_MATCH_CF_DERIVE_ADD;
+ else if (strcasecmp ("DeriveInc", ci->values[0].value.string) == 0)
+ dstype |= UTILS_MATCH_CF_DERIVE_INC;
+ else
+ dstype = 0;
+ }
+else if (strncasecmp ("Absolute", ci->values[0].value.string,
+ strlen ("Absolute")) == 0)
+ {
+ dstype = UTILS_MATCH_DS_TYPE_ABSOLUTE;
+ if (strcasecmp ("AbsoluteSet", ci->values[0].value.string) == 0) /* Absolute DS is reset-on-read so no sense doin anything else but set */
+ dstype |= UTILS_MATCH_CF_ABSOLUTE_SET;
+ else
+ dstype = 0;
+ }
+
else
{
dstype = 0;
PACKAGE_NAME"/"PACKAGE_VERSION);
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, 1);
if (wp->user != NULL)
{
/**
* collectd - src/df.c
* Copyright (C) 2005-2007 Florian octo Forster
+ * Copyright (C) 2009 Paul Sadauskas
*
* 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:
* Florian octo Forster <octo at verplant.org>
+ * Paul Sadauskas <psadauskas at gmail.com>
**/
#include "collectd.h"
"MountPoint",
"FSType",
"IgnoreSelected",
- NULL
+ "ReportByDevice"
};
-static int config_keys_num = 4;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static ignorelist_t *il_device = NULL;
static ignorelist_t *il_mountpoint = NULL;
static ignorelist_t *il_fstype = NULL;
+static _Bool by_device = false;
+
static int df_init (void)
{
if (il_device == NULL)
}
else if (strcasecmp (key, "IgnoreSelected") == 0)
{
- if ((strcasecmp (value, "True") == 0)
- || (strcasecmp (value, "Yes") == 0)
- || (strcasecmp (value, "On") == 0))
+ if (IS_TRUE (value))
{
ignorelist_set_invert (il_device, 0);
ignorelist_set_invert (il_mountpoint, 0);
}
return (0);
}
+ else if (strcasecmp (key, "ReportByDevice") == 0)
+ {
+ if (IS_TRUE (value))
+ by_device = true;
+
+ return (0);
+ }
return (-1);
}
unsigned long long blocksize;
gauge_t df_free;
gauge_t df_used;
- char mnt_name[256];
+ char disk_name[256];
mnt_list = NULL;
if (cu_mount_getlist (&mnt_list) == NULL)
for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
{
- if (strcmp (mnt_ptr->dir, "/") == 0)
- {
- sstrncpy (mnt_name, "root", sizeof (mnt_name));
- }
- else
- {
- int i, len;
-
- sstrncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
- len = strlen (mnt_name);
-
- for (i = 0; i < len; i++)
- if (mnt_name[i] == '/')
- mnt_name[i] = '-';
- }
-
+ if (ignorelist_match (il_device,
+ (mnt_ptr->spec_device != NULL)
+ ? mnt_ptr->spec_device
+ : mnt_ptr->device))
+ continue;
+ if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
+ continue;
+ if (ignorelist_match (il_fstype, mnt_ptr->type))
+ continue;
+
if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
{
char errbuf[1024];
df_free = statbuf.f_bfree * blocksize;
df_used = (statbuf.f_blocks - statbuf.f_bfree) * blocksize;
- df_submit (mnt_name, df_used, df_free);
+ if (by_device)
+ {
+ /* eg, /dev/hda1 -- strip off the "/dev/" */
+ if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0)
+ sstrncpy (disk_name, mnt_ptr->spec_device + strlen ("/dev/"), sizeof (disk_name));
+ else
+ sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name));
+
+ if (strlen(disk_name) < 1)
+ {
+ DEBUG("df: no device name name for mountpoint %s, skipping", mnt_ptr->dir);
+ continue;
+ }
+ }
+ else
+ {
+ if (strcmp (mnt_ptr->dir, "/") == 0)
+ {
+ sstrncpy (disk_name, "root", sizeof (disk_name));
+ }
+ else
+ {
+ int i, len;
+
+ sstrncpy (disk_name, mnt_ptr->dir + 1, sizeof (disk_name));
+ len = strlen (disk_name);
+
+ for (i = 0; i < len; i++)
+ if (disk_name[i] == '/')
+ disk_name[i] = '-';
+ }
+ }
+
- if (ignorelist_match (il_device,
- (mnt_ptr->spec_device != NULL)
- ? mnt_ptr->spec_device
- : mnt_ptr->device))
- continue;
- if (ignorelist_match (il_mountpoint, mnt_ptr->dir))
- continue;
- if (ignorelist_match (il_fstype, mnt_ptr->type))
- continue;
-
+ df_submit (disk_name, df_used, df_free);
}
cu_mount_freelist (mnt_list);
#include "configfile.h"
#include "utils_fbhash.h"
#include "utils_avltree.h"
+#include "utils_cache.h"
#include "network.h"
#if HAVE_LIBGCRYPT
# include <gcrypt.h>
+ GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif
-/* 1500 - 40 - 8 = Ethernet packet - IPv6 header - UDP header */
-/* #define BUFF_SIZE 1452 */
-
#ifndef IPV6_ADD_MEMBERSHIP
# ifdef IPV6_JOIN_GROUP
# define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
# endif
#endif /* !IP_ADD_MEMBERSHIP */
-/* Buffer size to allocate. */
-#define BUFF_SIZE 1024
-
/*
* Maximum size required for encryption / signing:
*
struct receive_list_entry_s
{
- char data[BUFF_SIZE];
+ char *data;
int data_len;
int fd;
struct receive_list_entry_s *next;
* Private variables
*/
static int network_config_ttl = 0;
+static size_t network_config_packet_size = 1024;
static int network_config_forward = 0;
static sockent_t *sending_sockets = NULL;
static pthread_t dispatch_thread_id;
/* Buffer in which to-be-sent network packets are constructed. */
-static char send_buffer[BUFF_SIZE];
+static char *send_buffer;
static char *send_buffer_ptr;
static int send_buffer_fill;
static value_list_t send_buffer_vl = VALUE_LIST_STATIC;
static pthread_mutex_t send_buffer_lock = PTHREAD_MUTEX_INITIALIZER;
-/* In this cache we store all the values we received, so we can send out only
- * those values which were *not* received via the network plugin, too. This is
- * used for the `Forward false' option. */
-static c_avl_tree_t *cache_tree = NULL;
-static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
-static time_t cache_flush_last = 0;
-static int cache_flush_interval = 1800;
-
/*
* Private functions
*/
-static int cache_flush (void)
+static _Bool check_receive_okay (const value_list_t *vl) /* {{{ */
{
- char **keys = NULL;
- int keys_num = 0;
+ uint64_t time_sent = 0;
+ int status;
- char **tmp;
- int i;
+ status = uc_meta_data_get_unsigned_int (vl,
+ "network:time_sent", &time_sent);
- char *key;
- time_t *value;
- c_avl_iterator_t *iter;
+ /* This is a value we already sent. Don't allow it to be received again in
+ * order to avoid looping. */
+ if ((status == 0) && (time_sent >= ((uint64_t) vl->time)))
+ return (false);
- time_t curtime = time (NULL);
+ return (true);
+} /* }}} _Bool check_receive_okay */
- iter = c_avl_get_iterator (cache_tree);
- while (c_avl_iterator_next (iter, (void *) &key, (void *) &value) == 0)
- {
- if ((curtime - *value) <= cache_flush_interval)
- continue;
- tmp = (char **) realloc (keys,
- (keys_num + 1) * sizeof (char *));
- if (tmp == NULL)
- {
- sfree (keys);
- c_avl_iterator_destroy (iter);
- ERROR ("network plugin: cache_flush: realloc"
- " failed.");
- return (-1);
- }
- keys = tmp;
- keys[keys_num] = key;
- keys_num++;
- } /* while (c_avl_iterator_next) */
- c_avl_iterator_destroy (iter);
+static _Bool check_send_okay (const value_list_t *vl) /* {{{ */
+{
+ _Bool received = false;
+ int status;
- for (i = 0; i < keys_num; i++)
- {
- if (c_avl_remove (cache_tree, keys[i], (void *) &key,
- (void *) &value) != 0)
- {
- WARNING ("network plugin: cache_flush: c_avl_remove"
- " (%s) failed.", keys[i]);
- continue;
- }
+ if (network_config_forward != 0)
+ return (true);
- sfree (key);
- sfree (value);
- }
+ if (vl->meta == NULL)
+ return (true);
- sfree (keys);
+ status = meta_data_get_boolean (vl->meta, "network:received", &received);
+ if (status == -ENOENT)
+ return (true);
+ else if (status != 0)
+ {
+ ERROR ("network plugin: check_send_okay: meta_data_get_boolean failed "
+ "with status %i.", status);
+ return (true);
+ }
- DEBUG ("network plugin: cache_flush: Removed %i %s",
- keys_num, (keys_num == 1) ? "entry" : "entries");
- cache_flush_last = curtime;
- return (0);
-} /* int cache_flush */
+ /* By default, only *send* value lists that were not *received* by the
+ * network plugin. */
+ return (!received);
+} /* }}} _Bool check_send_okay */
-static int cache_check (const value_list_t *vl)
+static int network_dispatch_values (value_list_t *vl) /* {{{ */
{
- char key[1024];
- time_t *value = NULL;
- int retval = -1;
+ int status;
- if (cache_tree == NULL)
- return (-1);
+ if ((vl->time <= 0)
+ || (strlen (vl->host) <= 0)
+ || (strlen (vl->plugin) <= 0)
+ || (strlen (vl->type) <= 0))
+ return (-EINVAL);
- if (format_name (key, sizeof (key), vl->host, vl->plugin,
- vl->plugin_instance, vl->type, vl->type_instance))
- return (-1);
+ if (!check_receive_okay (vl))
+ {
+#if COLLECT_DEBUG
+ char name[6*DATA_MAX_NAME_LEN];
+ FORMAT_VL (name, sizeof (name), vl);
+ name[sizeof (name) - 1] = 0;
+ DEBUG ("network plugin: network_dispatch_values: "
+ "NOT dispatching %s.", name);
+#endif
+ return (0);
+ }
- pthread_mutex_lock (&cache_lock);
+ assert (vl->meta == NULL);
- if (c_avl_get (cache_tree, key, (void *) &value) == 0)
- {
- if (*value < vl->time)
- {
- *value = vl->time;
- retval = 0;
- }
- else
- {
- DEBUG ("network plugin: cache_check: *value = %i >= vl->time = %i",
- (int) *value, (int) vl->time);
- retval = 1;
- }
- }
- else
- {
- char *key_copy = strdup (key);
- value = malloc (sizeof (time_t));
- if ((key_copy != NULL) && (value != NULL))
- {
- *value = vl->time;
- c_avl_insert (cache_tree, key_copy, value);
- retval = 0;
- }
- else
- {
- sfree (key_copy);
- sfree (value);
- }
- }
+ vl->meta = meta_data_create ();
+ if (vl->meta == NULL)
+ {
+ ERROR ("network plugin: meta_data_create failed.");
+ return (-ENOMEM);
+ }
- if ((time (NULL) - cache_flush_last) > cache_flush_interval)
- cache_flush ();
+ status = meta_data_add_boolean (vl->meta, "network:received", true);
+ if (status != 0)
+ {
+ ERROR ("network plugin: meta_data_add_boolean failed.");
+ meta_data_destroy (vl->meta);
+ vl->meta = NULL;
+ return (status);
+ }
- pthread_mutex_unlock (&cache_lock);
+ plugin_dispatch_values (vl);
- return (retval);
-} /* int cache_check */
+ meta_data_destroy (vl->meta);
+ vl->meta = NULL;
+
+ return (0);
+} /* }}} int network_dispatch_values */
#if HAVE_LIBGCRYPT
static gcry_cipher_hd_t network_get_aes256_cypher (sockent_t *se, /* {{{ */
for (i = 0; i < num_values; i++)
{
- if (ds->ds[i].type == DS_TYPE_COUNTER)
+ pkg_values_types[i] = (uint8_t) ds->ds[i].type;
+ switch (ds->ds[i].type)
{
- pkg_values_types[i] = DS_TYPE_COUNTER;
- pkg_values[i].counter = htonll (vl->values[i].counter);
- }
- else
- {
- pkg_values_types[i] = DS_TYPE_GAUGE;
- pkg_values[i].gauge = htond (vl->values[i].gauge);
- }
- }
+ case DS_TYPE_COUNTER:
+ pkg_values[i].counter = htonll (vl->values[i].counter);
+ break;
+
+ case DS_TYPE_GAUGE:
+ pkg_values[i].gauge = htond (vl->values[i].gauge);
+ break;
+
+ case DS_TYPE_DERIVE:
+ pkg_values[i].derive = htonll (vl->values[i].derive);
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ pkg_values[i].absolute = htonll (vl->values[i].absolute);
+ break;
+
+ default:
+ free (pkg_values_types);
+ free (pkg_values);
+ ERROR ("network plugin: write_part_values: "
+ "Unknown data source type: %i",
+ ds->ds[i].type);
+ return (-1);
+ } /* switch (ds->ds[i].type) */
+ } /* for (num_values) */
/*
* Use `memcpy' to write everything to the buffer, because the pointer
for (i = 0; i < pkg_numval; i++)
{
- if (pkg_types[i] == DS_TYPE_COUNTER)
- pkg_values[i].counter = ntohll (pkg_values[i].counter);
- else if (pkg_types[i] == DS_TYPE_GAUGE)
- pkg_values[i].gauge = ntohd (pkg_values[i].gauge);
+ switch (pkg_types[i])
+ {
+ case DS_TYPE_COUNTER:
+ pkg_values[i].counter = (counter_t) ntohll (pkg_values[i].counter);
+ break;
+
+ case DS_TYPE_GAUGE:
+ pkg_values[i].gauge = (gauge_t) ntohd (pkg_values[i].gauge);
+ break;
+
+ case DS_TYPE_DERIVE:
+ pkg_values[i].derive = (derive_t) ntohll (pkg_values[i].derive);
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ pkg_values[i].absolute = (absolute_t) ntohll (pkg_values[i].absolute);
+ break;
+
+ default:
+ sfree (pkg_types);
+ sfree (pkg_values);
+ NOTICE ("network plugin: parse_part_values: "
+ "Don't know how to handle data source type %"PRIu8,
+ pkg_types[i]);
+ return (-1);
+ } /* switch (pkg_types[i]) */
}
*ret_buffer = buffer;
{
status = parse_part_values (&buffer, &buffer_size,
&vl.values, &vl.values_len);
-
if (status != 0)
break;
- if ((vl.time > 0)
- && (strlen (vl.host) > 0)
- && (strlen (vl.plugin) > 0)
- && (strlen (vl.type) > 0)
- && (cache_check (&vl) == 0))
- {
- plugin_dispatch_values (&vl);
- }
- else
- {
- DEBUG ("network plugin: parse_packet:"
- " NOT dispatching values");
- }
+ network_dispatch_values (&vl);
sfree (vl.values);
}
}
} /* while (buffer_size > sizeof (part_header_t)) */
+ if (status == 0 && buffer_size > 0)
+ WARNING ("network plugin: parse_packet: Received truncated "
+ "packet, try increasing `MaxPacketSize'");
+
return (status);
} /* }}} int parse_packet */
/* Lock and wait for more data to come in */
pthread_mutex_lock (&receive_list_lock);
while ((listen_loop == 0)
- && (receive_list_head == NULL))
+ && (receive_list_head == NULL))
pthread_cond_wait (&receive_list_cond, &receive_list_lock);
/* Remove the head entry and unlock */
if (se == NULL)
{
- ERROR ("network plugin: Got packet from FD %i, but can't "
- "find an appropriate socket entry.",
- ent->fd);
- sfree (ent);
- continue;
+ ERROR ("network plugin: Got packet from FD %i, but can't "
+ "find an appropriate socket entry.",
+ ent->fd);
+ sfree (ent->data);
+ sfree (ent);
+ continue;
}
parse_packet (se, ent->data, ent->data_len, /* flags = */ 0);
+ sfree (ent->data);
sfree (ent);
} /* while (42) */
static int network_receive (void) /* {{{ */
{
- char buffer[BUFF_SIZE];
+ char buffer[network_config_packet_size];
int buffer_len;
int i;
return (-1);
}
memset (ent, 0, sizeof (receive_list_entry_t));
+ ent->data = malloc (network_config_packet_size);
+ if (ent->data == NULL)
+ {
+ ERROR ("network plugin: malloc failed.");
+ return (-1);
+ }
ent->fd = listen_sockets_pollfd[i].fd;
ent->next = NULL;
- /* Hopefully this be optimized out by the compiler. It
- * might help prevent stupid bugs in the future though.
- */
- assert (sizeof (ent->data) == sizeof (buffer));
-
memcpy (ent->data, buffer, buffer_len);
ent->data_len = buffer_len;
static void network_init_buffer (void)
{
- memset (send_buffer, 0, sizeof (send_buffer));
+ memset (send_buffer, 0, network_config_packet_size);
send_buffer_ptr = send_buffer;
send_buffer_fill = 0;
{
int status;
- /* If the value is already in the cache, we have received it via the
- * network. We write it again if forwarding is activated. It's then in
- * the cache and should we receive it again we will ignore it. */
- status = cache_check (vl);
- if ((network_config_forward == 0)
- && (status != 0))
- return (0);
+ if (!check_send_okay (vl))
+ {
+#if COLLECT_DEBUG
+ char name[6*DATA_MAX_NAME_LEN];
+ FORMAT_VL (name, sizeof (name), vl);
+ name[sizeof (name) - 1] = 0;
+ DEBUG ("network plugin: network_write: "
+ "NOT sending %s.", name);
+#endif
+ return (0);
+ }
+
+ uc_meta_data_add_unsigned_int (vl,
+ "network:time_sent", (uint64_t) vl->time);
pthread_mutex_lock (&send_buffer_lock);
status = add_to_buffer (send_buffer_ptr,
- sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
+ network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
&send_buffer_vl,
ds, vl);
if (status >= 0)
flush_buffer ();
status = add_to_buffer (send_buffer_ptr,
- sizeof (send_buffer) - (send_buffer_fill + BUFF_SIG_SIZE),
+ network_config_packet_size - (send_buffer_fill + BUFF_SIG_SIZE),
&send_buffer_vl,
ds, vl);
ERROR ("network plugin: Unable to append to the "
"buffer for some weird reason");
}
- else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
+ else if ((network_config_packet_size - send_buffer_fill) < 15)
{
flush_buffer ();
}
return (0);
} /* }}} int network_config_set_ttl */
+static int network_config_set_buffer_size (const oconfig_item_t *ci) /* {{{ */
+{
+ int tmp;
+ if ((ci->values_num != 1)
+ || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ {
+ WARNING ("network plugin: The `MaxPacketSize' config option needs exactly "
+ "one numeric argument.");
+ return (-1);
+ }
+
+ tmp = (int) ci->values[0].value.number;
+ if ((tmp >= 1024) && (tmp <= 65535))
+ network_config_packet_size = tmp;
+
+ return (0);
+} /* }}} int network_config_set_buffer_size */
+
#if HAVE_LIBGCRYPT
static int network_config_set_string (const oconfig_item_t *ci, /* {{{ */
char **ret_string)
return (0);
} /* }}} int network_config_add_server */
-static int network_config_set_cache_flush (const oconfig_item_t *ci) /* {{{ */
-{
- int tmp;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
- {
- WARNING ("network plugin: The `CacheFlush' config option needs exactly "
- "one numeric argument.");
- return (-1);
- }
-
- tmp = (int) ci->values[0].value.number;
- if (tmp > 0)
- cache_flush_interval = tmp;
-
- return (0);
-} /* }}} int network_config_set_cache_flush */
-
static int network_config (oconfig_item_t *ci) /* {{{ */
{
int i;
network_config_add_server (child);
else if (strcasecmp ("TimeToLive", child->key) == 0)
network_config_set_ttl (child);
+ else if (strcasecmp ("MaxPacketSize", child->key) == 0)
+ network_config_set_buffer_size (child);
else if (strcasecmp ("Forward", child->key) == 0)
network_config_set_boolean (child, &network_config_forward);
else if (strcasecmp ("CacheFlush", child->key) == 0)
- network_config_set_cache_flush (child);
+ /* no op for backwards compatibility only */;
else
{
WARNING ("network plugin: Option `%s' is not allowed here.",
static int network_notification (const notification_t *n,
user_data_t __attribute__((unused)) *user_data)
{
- char buffer[BUFF_SIZE];
+ char buffer[network_config_packet_size];
char *buffer_ptr = buffer;
int buffer_free = sizeof (buffer);
int status;
if (send_buffer_fill > 0)
flush_buffer ();
- if (cache_tree != NULL)
- {
- void *key;
- void *value;
-
- while (c_avl_pick (cache_tree, &key, &value) == 0)
- {
- sfree (key);
- sfree (value);
- }
- c_avl_destroy (cache_tree);
- cache_tree = NULL;
- }
+ sfree (send_buffer);
/* TODO: Close `sending_sockets' */
plugin_unregister_write ("network");
plugin_unregister_shutdown ("network");
- /* Let the init function do it's move again ;) */
- cache_flush_last = 0;
-
return (0);
} /* int network_shutdown */
static int network_init (void)
{
+ static _Bool have_init = false;
+
/* Check if we were already initialized. If so, just return - there's
* nothing more to do (for now, that is). */
- if (cache_flush_last != 0)
+ if (have_init)
return (0);
+ have_init = true;
+ #if HAVE_LIBGCRYPT
+ gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+ gcry_control (GCRYCTL_INIT_SECMEM, 32768, 0);
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+ #endif
+
plugin_register_shutdown ("network", network_shutdown);
+ send_buffer = malloc (network_config_packet_size);
+ if (send_buffer == NULL)
+ {
+ ERROR ("network plugin: malloc failed.");
+ return (-1);
+ }
network_init_buffer ();
- cache_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp);
- cache_flush_last = time (NULL);
-
/* setup socket(s) and so on */
if (sending_sockets != NULL)
{
{
pthread_mutex_lock (&send_buffer_lock);
- if (((time (NULL) - cache_flush_last) >= timeout)
- && (send_buffer_fill > 0))
- {
- flush_buffer ();
- }
+ if (send_buffer_fill > 0)
+ flush_buffer ();
pthread_mutex_unlock (&send_buffer_lock);
}
le = llist_search (read_list, name);
+ if (le == NULL)
+ {
+ pthread_mutex_unlock (&read_lock);
+ WARNING ("plugin_unregister_read: No such read function: %s",
+ name);
+ return (-ENOENT);
+ }
+
llist_remove (read_list, le);
rf = le->value;
(*callback) ();
}
- destroy_all_callbacks (&list_write);
+ /* Write plugins which use the `user_data' pointer usually need the
+ * same data available to the flush callback. If this is the case, set
+ * the free_function to NULL when registering the flush callback and to
+ * the real free function when registering the write callback. This way
+ * the data isn't freed twice. */
destroy_all_callbacks (&list_flush);
+ destroy_all_callbacks (&list_write);
+
destroy_all_callbacks (&list_notification);
destroy_all_callbacks (&list_shutdown);
destroy_all_callbacks (&list_log);
data_set_t *ds;
+ int free_meta_data = 0;
+
if ((vl == NULL) || (vl->type[0] == 0)
|| (vl->values == NULL) || (vl->values_len < 1))
{
return (-1);
}
+ /* Free meta data only if the calling function didn't specify any. In
+ * this case matches and targets may add some and the calling function
+ * may not expect (and therefore free) that data. */
+ if (vl->meta == NULL)
+ free_meta_data = 1;
+
if (list_write == NULL)
c_complain_once (LOG_WARNING, &no_write_complaint,
"plugin_dispatch_values: No write callback has been "
vl->values_len = saved_values_len;
}
+ if ((free_meta_data != 0) && (vl->meta != NULL))
+ {
+ meta_data_destroy (vl->meta);
+ vl->meta = NULL;
+ }
+
return (0);
} /* int plugin_dispatch_values */
{"latency", "latency", NULL},
/* Other stuff.. */
- {"corrupt-packets", "io_packets", "corrupt"},
+ {"corrupt-packets", "ipt_packets", "corrupt"},
{"deferred-cache-inserts", "counter", "cache-deferred_insert"},
{"deferred-cache-lookup", "counter", "cache-deferred_lookup"},
{"qsize-a", "cache_size", "answers"},
{"qsize-q", "cache_size", "questions"},
- {"servfail-packets", "io_packets", "servfail"},
- {"timedout-packets", "io_packets", "timeout"},
+ {"servfail-packets", "ipt_packets", "servfail"},
+ {"timedout-packets", "ipt_packets", "timeout"},
{"udp4-answers", "dns_answer", "udp4"},
{"udp4-queries", "dns_question", "queries-udp4"},
{"udp6-answers", "dns_answer", "udp6"},
return;
}
- if (0 != parse_value (value, &values[0], ds->ds[0]))
+ if (0 != parse_value (value, &values[0], ds->ds[0].type))
{
ERROR ("powerdns plugin: Cannot convert `%s' "
"to a number.", value);
break;
}
+ struct timeval timeout;
+ timeout.tv_sec=2;
+ if (timeout.tv_sec < interval_g * 3 / 4)
+ timeout.tv_sec = interval_g * 3 / 4;
+ timeout.tv_usec=0;
+ status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout));
+ if (status != 0)
+ {
+ FUNC_ERROR ("setsockopt");
+ break;
+ }
+
status = connect (sd, (struct sockaddr *) &item->sockaddr,
sizeof (item->sockaddr));
if (status != 0)
powerdns_config_add_server (option);
else if (strcasecmp ("LocalSocket", option->key) == 0)
{
- char *temp = strdup (option->key);
- if (temp == NULL)
- return (1);
- sfree (local_sockpath);
- local_sockpath = temp;
+ if ((option->values_num != 1) || (option->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ WARNING ("powerdns plugin: `%s' needs exactly one string argument.", option->key);
+ }
+ else
+ {
+ char *temp = strdup (option->values[0].value.string);
+ if (temp == NULL)
+ return (1);
+ sfree (local_sockpath);
+ local_sockpath = temp;
+ }
}
else
{