From: Florian Forster Date: Sun, 13 Jun 2010 19:44:09 +0000 (+0200) Subject: Merge branch 'collectd-4.9' into collectd-4.10 X-Git-Tag: collectd-4.10.1~6 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=2bdaa472d6955a8c93c6aa77f11748d4c611558e;hp=7d2c6544020d6864593bfcad284ca17faa337739;p=collectd.git Merge branch 'collectd-4.9' into collectd-4.10 --- diff --git a/AUTHORS b/AUTHORS index 4b133fa0..45689652 100644 --- a/AUTHORS +++ b/AUTHORS @@ -23,6 +23,7 @@ Alvaro Barcellos Amit Gupta - Multiple servers in the apache plugin. + - curl_xml plugin. Anthony Dewhurst - zfs_arc plugin. @@ -139,6 +140,9 @@ Peter Holik - Some bugfixes in the exec plugin. - Notifications in the ipmi plugin. +Phoenix Kayo + - pinba plugin. + Piotr Hosowicz - SMF manifest for collectd. diff --git a/ChangeLog b/ChangeLog index 488487ff..75f5b195 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,59 @@ +2010-05-01, Version 4.10.0 + * collectd: JSON output now includes the "dstypes" and "dsnames" + fields. This makes it easier for external applications to interpret + the data. Thanks to Chris Buben for his work. + * collectd: The new "Timeout" option can be used to specify a + "timeout" for missing values. This is used in the threshold checking + code to detect missing values. Thanks to Andrés J. Díaz for the + patch. + * apache plugin: Support for "IdleWorkers" (Apache 1.*: "IdleServers") + has been added. + * curl plugin: The new "ExcludeRegex" allows to easily exclude certain + lines from the match. + * curl_xml plugin: This new plugin allows to read XML files using cURL + and extract metrics included in the files. Thanks to Amit Gupta for + his work. + * filecount plugin: The new "IncludeHidden" option allows to include + "hidden" files and directories in the statistics. Thanks to Vaclav + Malek for the patch. + * logfile plugin: The new "PrintSeverity" option allows to include the + severity of a message in the output. Thanks to Clément Stenac for + his patch. + * memcachec plugin: The new "ExcludeRegex" allows to easily exclude + certain lines from the match. + * modbus plugin: This new plugin allows to read registers from + Modbus-TCP enabled devices. + * network plugin: The new "Interface" option allows to set the + interface to be used for multicast and, if supported, unicast + traffic. Thanks to Max Henkel for his work. + * openvpn plugin: The "CollectUserCount" and "CollectIndividualUsers" + options allow more detailed control over how to report sessions of + multiple users. Thanks to Fabian Schuh for his work. + * pinba plugin: This new plugin receives timing information from the + Pinba PHP extension, which can be used for profiling PHP code and + webserver performance. Thanks to Phoenix Kayo for his work. + * ping plugin: The new "MaxMissed" allows to re-resolve a hosts + address when it doesn't reply to a number of ping requests. Thanks + to Stefan Völkel for the patch. + * postgresql plugin: The "Interval" config option has been added. The + plugin has been relicensed under the 2-clause BSD license. Thanks to + Sebastian Harl for his work. + * processes plugin: Support for "code" and "data" virtual memory sizes + has been added. Thanks to Clément Stenac for his patch. + * python plugin: Support for Python 3 has been implemented. Thanks to + Sven Trenkel for his work. + * routeros plugin: Support for collecting CPU load, memory usage, used + and free disk space, sectors written and number of bad blocks from + MikroTik devices has been added. + * swap plugin: Support for Linux < 2.6 has been added. Thanks to Lorin + Scraba for his patch. + * tail plugin: The new "ExcludeRegex" allows to easily exclude certain + lines from the match. Thanks to Peter Warasin for his patch. + * write_http plugin: The "StoreRates" option has been added. Thanks to + Paul Sadauskas for his patch. + * regex match: The "Invert" option has been added. Thanks to Julien + Ammous for his patch. + 2010-04-22, Version 4.9.2 * Build system, various plugins: Fixes for AIX compatibility have been added. Thanks to Manuel Sanmartin for his patches. diff --git a/README b/README index 14e11cf2..ade430cc 100644 --- a/README +++ b/README @@ -57,6 +57,10 @@ Features Retrieves JSON data via cURL and parses it according to user configuration. + - curl_xml + Retrieves XML data via cURL and parses it according to user + configuration. + - dbi Executes SQL statements on various databases and interprets the returned data. @@ -143,6 +147,10 @@ Features Memory utilization: Memory occupied by running processes, page cache, buffer cache and free. + - modbus + Reads values from Modbus/TCP enabled devices. Supports reading values + from multiple "slaves" so gateway devices can be used. + - multimeter Information provided by serial multimeters, such as the `Metex M-4650CR'. @@ -200,6 +208,10 @@ Features write your own plugins in Perl and return arbitrary values using this API. See collectd-perl(5). + - pinba + Receive and dispatch timing values from Pinba, a profiling extension for + PHP. + - ping Network latency: Time to reach the default gateway or another given host. @@ -537,6 +549,10 @@ Prerequisites Used by the `memcachec' plugin to connect to a memcache daemon. + * libmodbus (optional) + Used by the `modbus' plugin to communicate with Modbus/TCP devices. + + * libmysqlclient (optional) Unsurprisingly used by the `mysql' plugin. @@ -579,6 +595,11 @@ Prerequisites The PostgreSQL C client library used by the `postgresql' plugin. + * libprotobuf-c, protoc-c (optional) + Used by the `pinba' plugin to generate a parser for the network packets + sent by the Pinba PHP extension. + + * libpython (optional) Used by the `python' plugin. Currently, only 2.3 ≦ Python < 3 is supported. diff --git a/configure.in b/configure.in index 45b87e9b..13a1f9dd 100644 --- a/configure.in +++ b/configure.in @@ -47,6 +47,9 @@ AC_PROG_LEX AC_PROG_YACC PKG_PROG_PKG_CONFIG +AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no]) +AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes") + AC_MSG_CHECKING([for kernel type ($host_os)]) case $host_os in *linux*) @@ -477,7 +480,7 @@ AC_HEADER_TIME # Checks for library functions. # AC_PROG_GCC_TRADITIONAL -AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv) +AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname) AC_FUNC_STRERROR_R @@ -1000,6 +1003,13 @@ AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_p #include ]) +AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], + [], + [ + #include + #include + ]) + AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct kinfo_proc.ki_rusage], [ AC_DEFINE(HAVE_STRUCT_KINFO_PROC_FREEBSD, 1, @@ -1875,6 +1885,98 @@ fi AM_CONDITIONAL(BUILD_WITH_LIBMEMCACHED, test "x$with_libmemcached" = "xyes") # }}} +# --with-libmodbus {{{ +with_libmodbus_config="" +with_libmodbus_cflags="" +with_libmodbus_libs="" +AC_ARG_WITH(libmodbus, [AS_HELP_STRING([--with-libmodbus@<:@=PREFIX@:>@], [Path to the modbus library.])], +[ + if test "x$withval" = "xno" + then + with_libmodbus="no" + else if test "x$withval" = "xyes" + then + with_libmodbus="use_pkgconfig" + else if test -d "$with_libmodbus/lib" + then + AC_MSG_NOTICE([Not checking for libmodbus: Manually configured]) + with_libmodbus_cflags="-I$withval/include" + with_libmodbus_libs="-L$withval/lib -lmodbus" + with_libmodbus="yes" + fi; fi; fi +], +[with_libmodbus="use_pkgconfig"]) + +# configure using pkg-config +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + if test "x$PKG_CONFIG" = "x" + then + with_libmodbus="no (Don't have pkg-config)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + AC_MSG_NOTICE([Checking for modbus using $PKG_CONFIG]) + $PKG_CONFIG --exists 'modbus' 2>/dev/null + if test $? -ne 0 + then + with_libmodbus="no (pkg-config doesn't know library)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + with_libmodbus_cflags="`$PKG_CONFIG --cflags 'modbus'`" + if test $? -ne 0 + then + with_libmodbus="no ($PKG_CONFIG failed)" + fi + with_libmodbus_libs="`$PKG_CONFIG --libs 'modbus'`" + if test $? -ne 0 + then + with_libmodbus="no ($PKG_CONFIG failed)" + fi +fi +if test "x$with_libmodbus" = "xuse_pkgconfig" +then + with_libmodbus="yes" +fi + +# with_libmodbus_cflags and with_libmodbus_libs are set up now, let's do +# the actual checks. +if test "x$with_libmodbus" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" + + AC_CHECK_HEADERS(modbus/modbus.h, [], [with_libmodbus="no (modbus/modbus.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libmodbus" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + + CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" + LDFLAGS="$LDFLAGS $with_libmodbus_libs" + + AC_CHECK_LIB(modbus, modbus_init_tcp, + [with_libmodbus="yes"], + [with_libmodbus="no (symbol modbus_init_tcp not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_libmodbus" = "xyes" +then + BUILD_WITH_LIBMODBUS_CFLAGS="$with_libmodbus_cflags" + BUILD_WITH_LIBMODBUS_LIBS="$with_libmodbus_libs" + AC_SUBST(BUILD_WITH_LIBMODBUS_CFLAGS) + AC_SUBST(BUILD_WITH_LIBMODBUS_LIBS) +fi +# }}} + # --with-libmysql {{{ with_mysql_config="mysql_config" with_mysql_cflags="" @@ -2820,7 +2922,7 @@ fi if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python CPPFLAGS]) - python_include_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_python_inc()" | "$with_python_prog" 2>&1` + python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x" @@ -2843,7 +2945,7 @@ fi if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python LDFLAGS]) - python_library_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0)" | "$with_python_prog" 2>&1` + python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x" @@ -2858,7 +2960,7 @@ fi if test "x$with_python" = "xyes" then AC_MSG_CHECKING([for Python LIBS]) - python_library_flags=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0)" | "$with_python_prog" 2>&1` + python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1` python_config_status=$? if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x" @@ -3818,7 +3920,7 @@ AC_DEFUN( enable_plugin="yes" force="yes" else - enable_plugin="no" + enable_plugin="no (disabled on command line)" fi; fi ], [ @@ -3871,6 +3973,7 @@ plugin_contextswitch="no" plugin_cpu="no" plugin_cpufreq="no" plugin_curl_json="no" +plugin_curl_xml="no" plugin_df="no" plugin_disk="no" plugin_entropy="no" @@ -4010,6 +4113,11 @@ then plugin_curl_json="yes" fi +if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes" +then + plugin_curl_xml="yes" +fi + if test "x$have_processor_info" = "xyes" then plugin_cpu="yes" @@ -4163,6 +4271,7 @@ 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([curl_xml], [$plugin_curl_xml], [CURL generic xml 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]) @@ -4193,6 +4302,7 @@ AC_PLUGIN([mbmon], [yes], [Query mbmond]) AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics]) AC_PLUGIN([memcached], [yes], [memcached statistics]) AC_PLUGIN([memory], [$plugin_memory], [Memory usage]) +AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin]) AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values]) AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics]) AC_PLUGIN([netapp], [$with_libnetapp], [NetApp plugin]) @@ -4209,6 +4319,8 @@ AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics]) AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics]) AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin]) AC_PLUGIN([perl], [$plugin_perl], [Embed a Perl interpreter]) +# FIXME: Check for libevent, too. +AC_PLUGIN([pinba], [$have_protoc_c], [Pinba statistics]) AC_PLUGIN([ping], [$with_liboping], [Network latency statistics]) AC_PLUGIN([postgresql], [$with_libpq], [PostgreSQL database statistics]) AC_PLUGIN([powerdns], [yes], [PowerDNS statistics]) @@ -4426,6 +4538,7 @@ Configuration: libkstat . . . . . . $with_kstat libkvm . . . . . . . $with_libkvm libmemcached . . . . $with_libmemcached + libmodbus . . . . . . $with_libmodbus libmysql . . . . . . $with_libmysql libnetapp . . . . . . $with_libnetapp libnetlink . . . . . $with_libnetlink @@ -4449,6 +4562,8 @@ Configuration: libxml2 . . . . . . . $with_libxml2 libxmms . . . . . . . $with_libxmms libyajl . . . . . . . $with_libyajl + libevent . . . . . . $with_libevent + protobuf-c . . . . . $have_protoc_c oracle . . . . . . . $with_oracle python . . . . . . . $with_python @@ -4473,6 +4588,7 @@ Configuration: csv . . . . . . . . . $enable_csv curl . . . . . . . . $enable_curl curl_json . . . . . . $enable_curl_json + curl_xml . . . . . . $enable_curl_xml dbi . . . . . . . . . $enable_dbi df . . . . . . . . . $enable_df disk . . . . . . . . $enable_disk @@ -4503,6 +4619,7 @@ Configuration: memcachec . . . . . . $enable_memcachec memcached . . . . . . $enable_memcached memory . . . . . . . $enable_memory + modbus . . . . . . . $enable_modbus multimeter . . . . . $enable_multimeter mysql . . . . . . . . $enable_mysql netapp . . . . . . . $enable_netapp @@ -4519,6 +4636,7 @@ Configuration: openvpn . . . . . . . $enable_openvpn oracle . . . . . . . $enable_oracle perl . . . . . . . . $enable_perl + pinba . . . . . . . . $enable_pinba ping . . . . . . . . $enable_ping postgresql . . . . . $enable_postgresql powerdns . . . . . . $enable_powerdns diff --git a/contrib/collectd_unixsock.py b/contrib/collectd_unixsock.py index ebe549c8..c482ac61 100644 --- a/contrib/collectd_unixsock.py +++ b/contrib/collectd_unixsock.py @@ -28,14 +28,15 @@ # 3. This notice may not be removed or altered from any source distribution. import socket +import sys class Collectd(): def __init__(self, path='/var/run/collectd-unixsock', noisy=False): self.noisy = noisy - self._sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self._sock.connect(path) + self.path = path + self._sock = self._connect() def flush(self, timeout=None, plugins=[], identifiers=[]): """Send a FLUSH command. @@ -138,8 +139,20 @@ class Collectd(): return self._cmd('PUTVAL %s' % ' '.join(args)) def _cmd(self, c): + try: + return self._cmdattempt(c) + except socket.error, (errno, errstr): + sys.stderr.write("[error] Sending to socket failed: [%d] %s\n" + % (errno, errstr)) + self._sock = self._connect() + return self._cmdattempt(c) + + def _cmdattempt(self, c): if self.noisy: print "[send] %s" % c + if not self._sock: + sys.stderr.write("[error] Socket unavailable. Can not send.") + return False self._sock.send(c + "\n") status_message = self._readline() if self.noisy: @@ -151,18 +164,39 @@ class Collectd(): return int(code) return False + def _connect(self): + try: + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.connect(self.path) + if self.noisy: + print "[socket] connected to %s" % self.path + return sock + except socket.error, (errno, errstr): + sys.stderror.write("[error] Connecting to socket failed: [%d] %s" + % (errno, errstr)) + return None + def _readline(self): """Read single line from socket""" - data = '' - buf = [] - recv = self._sock.recv - while data != "\n": - data = recv(1) - if not data: - break - if data != "\n": - buf.append(data) - return ''.join(buf) + if not self._sock: + sys.stderr.write("[error] Socket unavailable. Can not read.") + return None + try: + data = '' + buf = [] + recv = self._sock.recv + while data != "\n": + data = recv(1) + if not data: + break + if data != "\n": + buf.append(data) + return ''.join(buf) + except socket.error, (errno, errstr): + sys.stderror.write("[error] Reading from socket failed: [%d] %s" + % (errno, errstr)) + self._sock = self._connect() + return None def _readlines(self, sizehint=0): """Read multiple lines from socket""" @@ -179,7 +213,13 @@ class Collectd(): return list def __del__(self): - self._sock.close() + if not self._sock: + return + try: + self._sock.close() + except socket.error, (errno, errstr): + sys.stderror.write("[error] Closing socket failed: [%d] %s" + % (errno, errstr)) if __name__ == '__main__': diff --git a/contrib/collection.cgi b/contrib/collection.cgi index 100c0c73..af64fb1c 100755 --- a/contrib/collection.cgi +++ b/contrib/collection.cgi @@ -976,6 +976,28 @@ sub load_graph_definitions 'GPRINT:avg:LAST:%5.1lf%s Last', 'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l' ], + apache_connections => ['DEF:min={file}:count:MIN', + 'DEF:avg={file}:count:AVERAGE', + 'DEF:max={file}:count:MAX', + "AREA:max#$HalfBlue", + "AREA:min#$Canvas", + "LINE1:avg#$FullBlue:Connections", + 'GPRINT:min:MIN:%6.2lf Min,', + 'GPRINT:avg:AVERAGE:%6.2lf Avg,', + 'GPRINT:max:MAX:%6.2lf Max,', + 'GPRINT:avg:LAST:%6.2lf Last' + ], + apache_idle_workers => ['DEF:min={file}:count:MIN', + 'DEF:avg={file}:count:AVERAGE', + 'DEF:max={file}:count:MAX', + "AREA:max#$HalfBlue", + "AREA:min#$Canvas", + "LINE1:avg#$FullBlue:Idle Workers", + 'GPRINT:min:MIN:%6.2lf Min,', + 'GPRINT:avg:AVERAGE:%6.2lf Avg,', + 'GPRINT:max:MAX:%6.2lf Max,', + 'GPRINT:avg:LAST:%6.2lf Last' + ], apache_requests => ['DEF:min={file}:count:MIN', 'DEF:avg={file}:count:AVERAGE', 'DEF:max={file}:count:MAX', diff --git a/contrib/python/getsigchld.py b/contrib/python/getsigchld.py new file mode 100644 index 00000000..557adc09 --- /dev/null +++ b/contrib/python/getsigchld.py @@ -0,0 +1,21 @@ +#!/usr/bin/python + +############################################################################### +# WARNING! Importing this script will break the exec plugin! # +############################################################################### +# Use this if you want to create new processes from your python scripts. # +# Normally you will get a OSError exception when the new process terminates # +# because collectd will ignore the SIGCHLD python is waiting for. # +# This script will restore the default SIGCHLD behavior so python scripts can # +# create new processes without errors. # +############################################################################### +# WARNING! Importing this script will break the exec plugin! # +############################################################################### + +import signal +import collectd + +def init(): + signal.signal(signal.SIGCHLD, signal.SIG_DFL) + +collectd.register_init(init) diff --git a/src/Makefile.am b/src/Makefile.am index 4c3f5e97..c6b0538d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -107,6 +107,9 @@ collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la pkglib_LTLIBRARIES = +BUILT_SOURCES = +CLEANFILES = + if BUILD_PLUGIN_APACHE pkglib_LTLIBRARIES += apache.la apache_la_SOURCES = apache.c @@ -260,6 +263,17 @@ collectd_LDADD += "-dlopen" curl_json.la collectd_DEPENDENCIES += curl_json.la endif +if BUILD_PLUGIN_CURL_XML +pkglib_LTLIBRARIES += curl_xml.la +curl_xml_la_SOURCES = curl_xml.c +curl_xml_la_LDFLAGS = -module -avoid-version +curl_xml_la_CFLAGS = $(AM_CFLAGS) \ + $(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS) +curl_xml_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBXML2_LIBS) +collectd_LDADD += "-dlopen" curl_xml.la +collectd_DEPENDENCIES += curl_xml.la +endif + if BUILD_PLUGIN_DBI pkglib_LTLIBRARIES += dbi.la dbi_la_SOURCES = dbi.c \ @@ -590,6 +604,16 @@ memory_la_LIBADD += -lperfstat endif endif +if BUILD_PLUGIN_MODBUS +pkglib_LTLIBRARIES += modbus.la +modbus_la_SOURCES = modbus.c +modbus_la_LDFLAGS = -module -avoid-version +modbus_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMODBUS_CFLAGS) +modbus_la_LIBADD = $(BUILD_WITH_LIBMODBUS_LIBS) +collectd_LDADD += "-dlopen" modbus.la +collectd_DEPENDENCIES += modbus.la +endif + if BUILD_PLUGIN_MULTIMETER pkglib_LTLIBRARIES += multimeter.la multimeter_la_SOURCES = multimeter.c @@ -786,6 +810,17 @@ collectd_LDADD += "-dlopen" perl.la collectd_DEPENDENCIES += perl.la endif +if BUILD_PLUGIN_PINBA +BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h +CLEANFILES += pinba.pb-c.c pinba.pb-c.h +pkglib_LTLIBRARIES += pinba.la +pinba_la_SOURCES = pinba.c +pinba_la_LDFLAGS = -module -avoid-version +pinba_la_LIBADD = -lprotobuf-c +collectd_LDADD += "-dlopen" pinba.la +collectd_DEPENDENCIES += pinba.la +endif + if BUILD_PLUGIN_PING pkglib_LTLIBRARIES += ping.la ping_la_SOURCES = ping.c @@ -820,6 +855,10 @@ if BUILD_PLUGIN_PYTHON pkglib_LTLIBRARIES += python.la python_la_SOURCES = python.c pyconfig.c pyvalues.c cpython.h python_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_PYTHON_CPPFLAGS) +python_la_CFLAGS = $(AM_CFLAGS) +if COMPILER_IS_GCC +python_la_CFLAGS += -fno-strict-aliasing -Wno-strict-aliasing +endif python_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_PYTHON_LDFLAGS) python_la_LIBADD = $(BUILD_WITH_PYTHON_LIBS) collectd_LDADD += "-dlopen" python.la @@ -1163,7 +1202,6 @@ collectd_LDADD += "-dlopen" zfs_arc.la collectd_DEPENDENCIES += zfs_arc.la endif - dist_man_MANS = collectd.1 \ collectd.conf.5 \ collectd-email.5 \ @@ -1179,7 +1217,7 @@ dist_man_MANS = collectd.1 \ #collectd_1_SOURCES = collectd.pod -EXTRA_DIST = types.db +EXTRA_DIST = types.db pinba.proto EXTRA_DIST += collectd.conf.pod \ collectd-email.pod \ @@ -1211,6 +1249,9 @@ EXTRA_DIST += collectd.conf.pod \ echo "$@ has some POD errors!"; false; \ fi +pinba.pb-c.c pinba.pb-c.h: pinba.proto + protoc-c --c_out $(builddir) pinba.proto + install-exec-hook: $(mkinstalldirs) $(DESTDIR)$(sysconfdir) if test -e $(DESTDIR)$(sysconfdir)/collectd.conf; \ diff --git a/src/apache.c b/src/apache.c index ad877b5f..3d6d957c 100644 --- a/src/apache.c +++ b/src/apache.c @@ -313,7 +313,8 @@ static int config_add (oconfig_item_t *ci) (st->host != NULL) ? st->host : hostname_g, (st->name != NULL) ? st->name : "default"), - status = plugin_register_complex_read (callback_name, + status = plugin_register_complex_read (/* group = */ NULL, + /* name = */ callback_name, /* callback = */ apache_read_host, /* interval = */ NULL, /* user_data = */ &ud); @@ -688,6 +689,9 @@ static int apache_read_host (user_data_t *user_data) /* {{{ */ else if ((strcmp (fields[0], "BusyServers:") == 0) /* Apache 1.* */ || (strcmp (fields[0], "BusyWorkers:") == 0) /* Apache 2.* */) submit_gauge ("apache_connections", NULL, atol (fields[1]), st); + else if ((strcmp (fields[0], "IdleServers:") == 0) /* Apache 1.x */ + || (strcmp (fields[0], "IdleWorkers:") == 0) /* Apache 2.x */) + submit_gauge ("apache_idle_workers", NULL, atol (fields[1]), st); } } diff --git a/src/battery.c b/src/battery.c index b62ad81d..4178d8b5 100644 --- a/src/battery.c +++ b/src/battery.c @@ -514,7 +514,8 @@ static int battery_read (void) if (0 == access (battery_acpi_dir, R_OK)) walk_directory (battery_acpi_dir, battery_read_acpi, - /* user_data = */ NULL); + /* user_data = */ NULL, + /* include hidden */ 0); else { char errbuf[1024]; diff --git a/src/collectd-python.pod b/src/collectd-python.pod index 45a06d1d..b9408a3d 100644 --- a/src/collectd-python.pod +++ b/src/collectd-python.pod @@ -27,8 +27,7 @@ for collectd in Python. This is a lot more efficient than executing a Python-script every time you want to read a value with the C (see L) and provides a lot more functionality, too. -Currently only I is supported and at least I is -required. +At least python I is required. =head1 CONFIGURATION @@ -106,6 +105,15 @@ environment variable, e.g. I before starting collectd. Depending on your version of python this might or might not result in an B exception which can be ignored. +If you really need to spawn new processes from python you can register an init +callback and reset the action for SIGCHLD to the default behavior. Please note +that this I break the exec plugin. Do not even load the exec plugin if +you intend to do this! + +There is an example script located in B to do +this. If you import this from I SIGCHLD will be handled +normally and spawning processes from python will work as intended. + =back =item EB IE block @@ -119,6 +127,29 @@ The I identifies the callback. =back +=head1 STRINGS + +There are a lot of places where strings are send from collectd to python and +from python to collectd. How exactly this works depends on wheather byte or +unicode strings or python2 or python3 are used. + +Python2 has I, which is just bytes, and I. Python3 has I, +which is a unicode object, and I. + +When passing strings from python to collectd all of these object are supported +in all places, however I should be used if possible. These strings must +not contain a NUL byte. Ignoring this will result in a I exception. +If a byte string was used it will be used as is by collectd. If a unicode +object was used it will be encoded using the default encoding (see above). If +this is not possible python will raise a I exception. + +Wenn passing strings from collectd to python the behavior depends on the +python version used. Python2 will always receive a I object. Python3 will +usually receive a I object as well, however the original string will be +decoded to unicode using the default encoding. If this fails because the +string is not a valid sequence for this encoding a I object will be +returned instead. + =head1 WRITING YOUR OWN PLUGINS Writing your own plugins is quite simple. collectd manages plugins by means of @@ -209,6 +240,28 @@ collectd you're done. The following complex types are used to pass values between the Python plugin and collectd: +=head2 Signed + +The Signed class is just a long. It has all its methods and behaves exactly +like any other long object. It is used to indicate if an integer was or should +be stored as a signed or unsigned integer object. + + class Signed(long) + +This is a long by another name. Use it in meta data dicts +to choose the way it is stored in the meta data. + +=head2 Unsigned + +The Unsigned class is just a long. It has all its methods and behaves exactly +like any other long object. It is used to indicate if an integer was or should +be stored as a signed or unsigned integer object. + + class Unsigned(long) + +This is a long by another name. Use it in meta data dicts +to choose the way it is stored in the meta data. + =head2 Config The Config class is an object which keeps the information provided in the @@ -372,6 +425,16 @@ If the sequence does not have the correct size upon dispatch a I exception will be raised. If the content of the sequence is not a number, a I exception will be raised. +=item meta + +These are the meta data for this Value object. +It has to be a dictionary of numbers, strings or bools. All keys must be +strings. I and objects will be dispatched as signed integers unless +they are between 2**63 and 2**64-1, which will result in a unsigned integer. +You can force one of these storage classes by using the classes +B and B. A meta object received by a write +callback will always contain B or B objects. + =back =head2 Notification diff --git a/src/collectd.c b/src/collectd.c index bc69a3b7..277d3b0d 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -41,6 +41,7 @@ */ char hostname_g[DATA_MAX_NAME_LEN]; int interval_g; +int timeout_g; #if HAVE_LIBKSTAT kstat_ctl_t *kc; #endif /* HAVE_LIBKSTAT */ @@ -148,6 +149,18 @@ static int init_global_variables (void) } DEBUG ("interval_g = %i;", interval_g); + str = global_option_get ("Timeout"); + if (str == NULL) + str = "2"; + timeout_g = atoi (str); + if (timeout_g <= 1) + { + fprintf (stderr, "Cannot set the timeout to a correct value.\n" + "Please check your settings.\n"); + return (-1); + } + DEBUG ("timeout_g = %i;", timeout_g); + if (init_hostname () != 0) return (-1); DEBUG ("hostname_g = %s;", hostname_g); @@ -259,9 +272,10 @@ static void exit_usage (int status) #endif " -h Display help (this message)\n" "\nBuiltin defaults:\n" - " Config-File "CONFIGFILE"\n" - " PID-File "PIDFILE"\n" - " Data-Directory "PKGLOCALSTATEDIR"\n" + " Config file "CONFIGFILE"\n" + " PID file "PIDFILE"\n" + " Plugin directory "PLUGINDIR"\n" + " Data directory "PKGLOCALSTATEDIR"\n" "\n"PACKAGE" "VERSION", http://collectd.org/\n" "by Florian octo Forster \n" "for contributions see `AUTHORS'\n"); diff --git a/src/collectd.conf.in b/src/collectd.conf.in index c047a1a6..d8e39dbe 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -17,6 +17,7 @@ FQDNLookup true #PluginDir "@prefix@/lib/@PACKAGE_NAME@" #TypesDB "@prefix@/share/@PACKAGE_NAME@/types.db" #Interval 10 +#Timeout 2 #ReadThreads 5 ############################################################################## @@ -34,6 +35,7 @@ FQDNLookup true # LogLevel @DEFAULT_LOG_LEVEL@ # File STDOUT # Timestamp true +# PrintSeverity false # # @@ -63,6 +65,7 @@ FQDNLookup true @LOAD_PLUGIN_CSV@LoadPlugin csv #@BUILD_PLUGIN_CURL_TRUE@LoadPlugin curl #@BUILD_PLUGIN_CURL_JSON_TRUE@LoadPlugin curl_json +#@BUILD_PLUGIN_CURL_XML_TRUE@LoadPlugin curl_xml #@BUILD_PLUGIN_DBI_TRUE@LoadPlugin dbi #@BUILD_PLUGIN_DF_TRUE@LoadPlugin df #@BUILD_PLUGIN_DISK_TRUE@LoadPlugin disk @@ -87,6 +90,7 @@ FQDNLookup true #@BUILD_PLUGIN_MEMCACHEC_TRUE@LoadPlugin memcachec #@BUILD_PLUGIN_MEMCACHED_TRUE@LoadPlugin memcached @BUILD_PLUGIN_MEMORY_TRUE@@BUILD_PLUGIN_MEMORY_TRUE@LoadPlugin memory +#@BUILD_PLUGIN_MODBUS_TRUE@LoadPlugin modbus #@BUILD_PLUGIN_MULTIMETER_TRUE@LoadPlugin multimeter #@BUILD_PLUGIN_MYSQL_TRUE@LoadPlugin mysql #@BUILD_PLUGIN_NETAPP_TRUE@LoadPlugin netapp @@ -103,6 +107,7 @@ FQDNLookup true #@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn #@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle #@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl +#@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba #@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping #@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql #@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns @@ -231,6 +236,25 @@ FQDNLookup true # # +# +# +# Host "my_host" +# Instance "some_instance" +# User "collectd" +# Password "thaiNg0I" +# VerifyPeer true +# VerifyHost true +# CACert "/path/to/ca.crt" +# +# +# Type "magic_level" +# #InstancePrefix "prefix-" +# InstanceFrom "td[1]" +# ValuesFrom "td[2]/span[@class=\"level\"]" +# +# +# + # # # Statement "SELECT 'customers' AS c_key, COUNT(*) AS c_value FROM customers_tbl" @@ -293,6 +317,7 @@ FQDNLookup true # MTime "-5m" # Size "+10k" # Recursive true +# IncludeHidden false # # @@ -389,6 +414,7 @@ FQDNLookup true # Key "page_key" # # Regex "(\\d+) bytes sent" +# ExcludeRegex "" # DSType CounterAdd # Type "ipt_octets" # Instance "type_instance" @@ -401,6 +427,26 @@ FQDNLookup true # Port "11211" # +# +# +# RegisterBase 1234 +# RegisterType float +# Type gauge +# Instance "..." +# +# +# +# Address "addr" +# Port "1234" +# Interval 60 +# +# +# Instance "foobar" # optional +# Collect "data_name" +# +# +# + # # # Host "database.serv.er" @@ -480,14 +526,33 @@ FQDNLookup true # @LOAD_PLUGIN_NETWORK@ +# # client setup: @LOAD_PLUGIN_NETWORK@ Server "ff18::efc0:4a42" "25826" -@LOAD_PLUGIN_NETWORK@ Server "239.192.74.66" "25826" -# Listen "ff18::efc0:4a42" "25826" -# Listen "239.192.74.66" "25826" +@LOAD_PLUGIN_NETWORK@ +# SecurityLevel Encrypt +# Username "user" +# Password "secret" +# Interface "eth0" +@LOAD_PLUGIN_NETWORK@ # TimeToLive "128" -# Forward false -# CacheFlush 1800 +# +# # server setup: +# Listen "ff18::efc0:4a42" "25826" +# +# SecurityLevel Sign +# AuthFile "/etc/collectd/passwd" +# Interface "eth0" +# +# MaxPacketSize 1024 +# +# # proxy setup (client and server as above): +# Forward true +# +# # statistics about the network plugin itself # ReportStats false +# +# # "garbage collection" +# CacheFlush 1800 @LOAD_PLUGIN_NETWORK@ # @@ -541,6 +606,10 @@ FQDNLookup true # # StatusFile "/etc/openvpn/openvpn-status.log" +# ImprovedNamingSchema false +# CollectCompression true +# CollectIndividualUsers true +# CollectUserCount false # # @@ -573,6 +642,16 @@ FQDNLookup true # # +# +# Address "::0" +# Port "30002" +# +# Host "host name" +# Server "server name" +# Script "script name" +# +# + # # Host "host.foo.bar" # Interval 1.0 @@ -617,6 +696,7 @@ FQDNLookup true # Query magic # # +# Interval 60 # Service "service_name" # Query backend # predefined # Query rt36_tickets @@ -665,6 +745,10 @@ FQDNLookup true # Password "dozaiTh4" # CollectInterface true # CollectRegistrationTable true +# CollectCPULoad true +# CollectMemory true +# CollectDF true +# CollectDisk true # # @@ -760,6 +844,7 @@ FQDNLookup true # # # Regex "\\" +# ExcludeRegex "\\.*mail_spool defer" # DSType "CounterInc" # Type "counter" # Instance "local_user" @@ -813,6 +898,11 @@ FQDNLookup true # # User "collectd" # Password "weCh3ik0" +# VerifyPeer true +# VerifyHost true +# CACert "/etc/ssl/ca.crt" +# Format "Command" +# StoreRates false # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 2eb8d304..cc448a0e 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -102,6 +102,16 @@ Configures the interval in which to query the read plugins. Obviously smaller values lead to a higher system load produced by collectd, while higher values lead to more coarse statistics. +=item B I + +Consider a value list "missing" when no update has been read or received for +I iterations. By default, I considers a value list +missing when no update has been received for twice the update interval. Since +this setting uses iterations, the maximum allowed time without update depends +on the I information contained in each value list. This is used in +the I configuration to dispatch notifications about missing values, +see L<"THRESHOLD CONFIGURATION"> below. + =item B I Number of threads to start for reading plugins. The default value is B<5>, but @@ -619,6 +629,110 @@ Type-instance to use. Defaults to the current map key or current string array el =back +=head2 Plugin C + +The B uses B (L) and B +(L) to retrieve XML data via cURL. + + + + Host "my_host" + Instance "some_instance" + User "collectd" + Password "thaiNg0I" + VerifyPeer true + VerifyHost true + CACert "/path/to/ca.crt" + + + Type "magic_level" + #InstancePrefix "prefix-" + InstanceFrom "td[1]" + ValuesFrom "td[2]/span[@class=\"level\"]" + + + + +In the B block, there may be one or more B blocks, each defining a +URL to be fetched via HTTP (using libcurl). Within each B block there are +options which specify the connection parameters, for example authentication +information, and one or more B blocks. + +Each B block specifies how to get one type of information. The +string argument must be a valid XPath expression which returns a list +of "base elements". One value is dispatched for each "base element". The +I and values are looked up using further I expressions +that should be relative to the base element. + +Within the B block the following options are accepted: + +=over 4 + +=item B I + +Use I as the host name when submitting values. Defaults to the global +host name setting. + +=item B I + +Use I as the plugin instance when submitting values. Defaults to an +empty string (no plugin instance). + +=item B I +=item B I +=item B B|B +=item B B|B +=item B I + +These options behave exactly equivalent to the appropriate options of the +I and I plugins. Please see there for a detailed description. + +=item EB IE + +Within each B block, there must be one or more B blocks. Each +B block specifies how to get one type of information. The string +argument must be a valid XPath expression which returns a list of "base +elements". One value is dispatched for each "base element". + +Within the B block the following options are accepted: + +=over 4 + +=item B I + +Specifies the I used for submitting patches. This determines the number +of values that are required / expected and whether the strings are parsed as +signed or unsigned integer or as double values. See L for details. +This option is required. + +=item B I + +Prefix the I with I. The values are simply +concatenated together without any separator. +This option is optional. + +=item B I + +Specifies a XPath expression to use for determining the I. The +XPath expression must return exactly one element. The element's value is then +used as I, possibly prefixed with I (see above). + +This value is required. As a special exception, if the "base XPath expression" +(the argument to the B block) returns exactly one argument, then this +option may be omitted. + +=item B I [I ...] + +Specifies one or more XPath expression to use for reading the values. The +number of XPath expressions must match the number of data sources in the +I specified with B (see above). Each XPath expression must return +exactly one element. The element's value is then parsed as a number and used as +value for the appropriate value in the value list dispatched to the daemon. + +=back + +=back + =head2 Plugin C This plugin uses the B library (L) to @@ -1104,6 +1218,12 @@ note that there are 1000 bytes in a kilobyte, not 1024. Controls whether or not to recurse into subdirectories. Enabled by default. +=item B I|I + +Controls whether or not to include "hidden" files and directories in the count. +"Hidden" files and directories are those, whose name begins with a dot. +Defaults to I, i.e. by default hidden files and directories are ignored. + =back =head2 Plugin C @@ -1473,6 +1593,11 @@ running in foreground- or non-daemon-mode. Prefix all lines printed by the current time. Defaults to B. +=item B B|B + +When enabled, all lines are prefixed by the severity of the log message, for +example "warning". Defaults to B. + =back B: There is no need to notify the daemon after moving or removing the @@ -1573,6 +1698,132 @@ TCP-Port to connect to. Defaults to B<11211>. =back +=head2 Plugin C + +The B connects to a Modbus "slave" via Modbus/TCP and reads +register values. It supports reading single registers (unsigned 16Ebit +values), large integer values (unsigned 32Ebit values) and floating point +values (two registers interpreted as IEEE floats in big endian notation). + +Synopsis: + + + RegisterBase 0 + RegisterType float + Type voltage + Instance "input-1" + + + + RegisterBase 2 + RegisterType float + Type voltage + Instance "input-2" + + + + Address "192.168.0.42" + Port "502" + Interval 60 + + + Instance "power-supply" + Collect "voltage-input-1" + Collect "voltage-input-2" + + + +=over 4 + +=item EB IE blocks + +Data blocks define a mapping between register numbers and the "types" used by +I. + +Within EDataE/E blocks, the following options are allowed: + +=over 4 + +=item B I + +Configures the base register to read from the device. If the option +B has been set to B or B, this and the next +register will be read (the register number is increased by one). + +=item B B|B|B + +Specifies what kind of data is returned by the device. If the type is B +or B, two 16Ebit registers will be read and the data is combined +into one value. Defaults to B. + +=item B I + +Specifies the "type" (data set) to use when dispatching the value to +I. Currently, only data sets with exactly one data source are +supported. + +=item B I + +Sets the type instance to use when dispatching the value to I. If +unset, an empty string (no type instance) is used. + +=back + +=item EB IE blocks + +Host blocks are used to specify to which hosts to connect and what data to read +from their "slaves". The string argument I is used as hostname when +dispatching the values to I. + +Within EHostE/E blocks, the following options are allowed: + +=over 4 + +=item B
I + +Specifies the node name (the actual network address) used to connect to the +host. This may be an IP address or a hostname. Please note that the used +I library only supports IPv4 at the moment. + +=item B I + +Specifies the port used to connect to the host. The port can either be given as +a number or as a service name. Please note that the I argument must be +a string, even if ports are given in their numerical form. Defaults to "502". + +=item B I + +Sets the interval (in seconds) in which the values will be collected from this +host. By default the global B setting will be used. + +=item EB IE + +Over each TCP connection, multiple Modbus devices may be reached. The slave ID +is used to specify which device should be addressed. For each device you want +to query, one B block must be given. + +Within ESlaveE/E blocks, the following options are allowed: + +=over 4 + +=item B I + +Specify the plugin instance to use when dispatching the values to I. +By default "slave_I" is used. + +=item B I + +Specifies which data to retrieve from the device. I must be the same +string as the I argument passed to a B block. You can specify this +option multiple times to collect more than one value from a slave. At least one +B option is mandatory. + +=back + +=back + +=back + =head2 Plugin C The C requires B to be installed. It connects to @@ -2271,6 +2522,15 @@ B require this setting. This feature is only available if the I plugin was linked with I. +=item B I + +Set the outgoing interface for IP packets. This applies at least +to IPv6 packets and if possible to IPv4. If this option is not applicable, +undefined or a non-existent interface name is specified, the default +behavior is to let the kernel choose the appropriate interface. Be warned +that the manual selection of an interface for unicast traffic is only +necessary in rare cases. + =back =item BListen> I [I]B> @@ -2319,6 +2579,14 @@ Each time a packet is received, the modification time of the file is checked using L. If the file has been changed, the contents is re-read. While the file is being read, it is locked using L. +=item B I + +Set the incoming interface for IP packets explicitly. This applies at least +to IPv6 packets and if possible to IPv4. If this option is not applicable, +undefined or a non-existent interface name is specified, the default +behavior is, to let the kernel choose the appropriate interface. Thus incoming +traffic gets only accepted, if it arrives on the given interface. + =back =item B I<1-255> @@ -2668,12 +2936,24 @@ and the client's "common name" will be used as type instance. This is required when reading multiple status files. Enabling this option is recommended, but to maintain backwards compatibility this option is disabled by default. -=item B B|B +=item B B|B Sets whether or not statistics about the compression used by OpenVPN should be collected. This information is only available in I mode. Enabled by default. +=item B B|B + +Sets whether or not traffic information is collected for each connected client +individually. If set to false, currently no traffic data is collected at all +because aggregating this data in a save manner is tricky. Defaults to B. + +=item B B|B + +When enabled, the number of currently connected clients or users is collected. +This is especially interesting when B is disabled, but +can be configured independently from that option. Defaults to B. + =back =head2 Plugin C @@ -2743,6 +3023,83 @@ refer to them from. This plugin embeds a Perl-interpreter into collectd and provides an interface to collectd's plugin system. See L for its documentation. +=head2 Plugin C + +The I receives profiling information from I, an extension +for the I interpreter. At the end of executing a script, i.e. after a +PHP-based webpage has been delivered, the extension will send a UDP packet +containing timing information, peak memory usage and so on. The plugin will +wait for such packets, parse them and account the provided information, which +is then dispatched to the daemon once per interval. + +Synopsis: + + + Address "::0" + Port "30002" + # Overall statistics for the website. + + Server "www.example.com" + + # Statistics for www-a only + + Host "www-a.example.com" + Server "www.example.com" + + # Statistics for www-b only + + Host "www-b.example.com" + Server "www.example.com" + + + +The plugin provides the following configuration options: + +=over 4 + +=item B
I + +Configures the address used to open a listening socket. By default, plugin will +bind to the I address C<::0>. + +=item B I + +Configures the port (service) to bind to. By default the default Pinba port +"30002" will be used. The option accepts service names in addition to port +numbers and thus requires a I argument. + +=item EB IE block + +The packets sent by the Pinba extension include the hostname of the server, the +server name (the name of the virtual host) and the script that was executed. +Using B blocks it is possible to separate the data into multiple groups +to get more meaningful statistics. Each packet is added to all matching groups, +so that a packet may be accounted for more than once. + +=over 4 + +=item B I + +Matches the hostname of the system the webserver / script is running on. This +will contain the result of the L system call. If not +configured, all hostnames will be accepted. + +=item B I + +Matches the name of the I, i.e. the contents of the +C<$_SERVER["SERVER_NAME"]> variable when within PHP. If not configured, all +server names will be accepted. + +=item B