From: Marc Fournier Date: Wed, 22 Apr 2015 06:46:00 +0000 (+0200) Subject: Merge branch 'collectd-4.10' into collectd-5.3 X-Git-Tag: collectd-5.5.0~12^2~5^2~9 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=ef4a3db895a0aba7107c0f1c6c2ef2a7f128aaf8;hp=15037c9f4b3c43ac3d09040e16c3a430c9fc2b22 Merge branch 'collectd-4.10' into collectd-5.3 --- diff --git a/.gitignore b/.gitignore index b85bdec6..6e87aaf2 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,9 @@ src/liboconfig/parser.c src/liboconfig/parser.h src/liboconfig/scanner.c +# protobuf stuff: +src/*.pb-c.[ch] + # make dist stuff: /collectd-*.tar.gz /collectd-*.tar.bz2 @@ -66,3 +69,9 @@ bindings/java/org/collectd/java/*.class # python stuff *.pyc + +# tag stuff +src/tags + +# backup stuff +*~ diff --git a/AUTHORS b/AUTHORS index f090840e..45645d1a 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,6 +15,9 @@ Sebastian "tokkee" Harl Contributors (sorted alphabetically) ==================================== +Akkarit Sangpetch + - write_mongodb plugin. + Alessandro Iurlano - Initial filecount plugin. @@ -34,16 +37,26 @@ Anthony Gialluca Antony Dovgal - memcached plugin. +Aurélien Reynaud + - LPAR plugin. + - Various fixes for AIX, HP-UX and Solaris. + Bruno Prémont - BIND plugin. - Many bugreports and -fixes in various plugins, especially a nasty bug in the network plugin. - Wireshark dissector. +Chris Lundquist + - Improvements to the write_mongodb plugin. + Christophe Kalt - The version 3 `log' mode. - Many Solaris related hints and fixes. +Cyril Feraudet + - ethstat plugin. + Dan Berrange - uuid plugin. @@ -75,6 +88,12 @@ Franck Lombardi Jason Pepas - nfs plugin. +Jérôme Renard + - varnish plugin. + +Kris Nielander + - tail_csv plugin. + LuboÅ¡ Staněk - sensors plugin improvements. - Time and effort to find a nasty bug in the ntpd-plugin. @@ -102,6 +121,9 @@ Marco Chiappero - ip6tables support in the iptables plugin. - openvpn plugin (support for more status file formats) +Michael Hanselmann + - md plugin. + Michael Stapelberg - OpenBSD port of the tcpconns plugin. @@ -146,6 +168,10 @@ Peter Holik Phoenix Kayo - pinba plugin. +Pierre-Yves Ritschard + - Write-Riemann plugin. + - Write-Graphite plugin: Notification support. + Piotr Hosowicz - SMF manifest for collectd. @@ -162,6 +188,12 @@ Rodolphe Quiédeville Scott Garrett - tape plugin. +Scott Sanders + - Write-Graphite plugin. + +Sebastien Pahl + - AMQP plugin. + Simon Kuhnle - OpenBSD code for the cpu and memory plugins. @@ -175,6 +207,9 @@ Sven Trenkel - netapp plugin. - python plugin. +Thomas Meson + - Graphite support for the AMQP plugin. + Tomasz Pala - conntrack plugin. diff --git a/ChangeLog b/ChangeLog index e8f73b5c..c5d263e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,640 @@ +2015-02-26, Version 5.3.2 + * Build system: Numerous fixes. Thanks to Bjørn Nordbø, Jim Radford, + KOMEDA Shinji, Lauri Tirkkonen, Manuel Luis Sanmartin Rozada, Marc + Fournier, Rainer Müller, Yoga Ramalingam and Yves Mettier. #326, + #373, #653, #828 + * collectd: A use-after-free has been fixed in the "parse_value()" + function. Thanks to Matthias Urlichs. + * collectd: Fix carriage return sign in types_list Thanks to Marc + Fournier and @NsLib. + * collectd: Fix programming error in src/configfile.c Thanks to + Wilfried Goesgens. + * collectd: An off-by-one error has been fixed in the + "strstripnewline()" function. Patch by Florian Forster. + * collectd: Use the complain mechanism to report filter chain write + failures. Thanks to Sebastian Harl. + * collectd: Spelling and grammar of error messages have been fixed. + Thanks to Katelyn Perry and Tim Laszlo. + * collectdctl: Fixed buffering issues which caused trouble on AIX and + Solaris. Thanks to Yoga Ramalingam. + * Documentation: Details and example about multi-instance filterchain + targets have been added. Thanks to Marc Fournier. + * Documentation: The "CollectStatistics" option of the rrdcached has + been documented. Thanks to Micha Krause. #907 + * Documentation: The write_redis has been documented. Thanks to Marc + Fournier. + * Documentation: The synopsis of the threshold has been fixed. Thanks + to Fabien Wernli. + * Documentation: The "GraphiteSeparateInstances" and + "GraphiteAlwaysAppendDS" options of the amqp have been documented. + Thanks to Marc Fournier. + * aggregation: "utils_vl_lookup": A race when creating user objects + has been fixed. Thanks to Sebastian Harl. #535 + * cpu: Temperature code for Mac OS X has been removed. + Thanks to Florian Forster and Marc Fournier. #22 + * csv: A regression which would lead to the "DataDir" option to be + ignored has been fixed. Thanks to Manuel Luis Sanmartin Rozada. + * curl, curl-json, curl-xml and write_http plugins: Call + "curl_global_init()" in the plugins' "init()" callback. Thanks to + Jeremy Katz. + * curl and memcachec plugins: Fix calculation of gauge, average, + minimum and maximum. Previously, they were calculated from the start + of the daemon, which is not the documented behavior. Thanks to + Florian Forster. #663 + * dbi plugin: Compatibility with new versions of libdbi has been + restored. Thanks to Florian Forster. #950 + * exec, unixsock plugins: Fix parsing of the "time" option of the + "PUTNOTIF" command. Thanks to Adrian Miron. #477 + * java: Conversion from Java's time representation to collectd's + representation has been fixed. Thanks to Manuel Luis Sanmartín + Rozada. + * ipmi: A conflict with the java over the "SIGUSR2" signal has been + fixed. Thanks to Vincent Bernat. #114 + * java: Make sure "cjni_thread_detach()" is called on all paths. + Thanks to Florian Forster. + * logfile and syslog plugins: Avoid total silence in case of a + misconfiguration. Thanks to Marc Fournier and Wilfried Goesgens. + * memcached: Connecting to a UNIX socket has been fixed. Thanks to Jim + Radford. + * network: Support for recent versions of gcrypt has been added. + Thanks to Vincent Bernat. #632 + * network: Robustness of the client connecting behavior has been + improved. Thanks to Florian Forster. #627 + * python: Don't create empty "meta_data_t" objects. Thanks to Florian + Forster. #716 + * python: Fix Py list length check in "cpy_build_meta()". Thanks to + Yoga Ramalingam. + * python: The "interval" member was fixed to export seconds as a + double. Thanks to Justin Burnham. + * replace and set targets: Fix error message. Thanks to Marc Fournier. + #448 + * rrdtool and rrdcached plugins: Honor the "DataDir" config option; + this fixes a regression. Thanks to Florian Forster. #380 + * rrdtool and rrdcached plugins: A memory leak when creating RRD files + has been fixed. Thanks to Yves Mettier. #661 + * snmp: Fix a memory leak. Thanks to Marc Fournier and Pierre-Yves + Ritschard. #610, #804 + * swap: Fix behavior under OpenVZ by making "cached" optional. Thanks + to Florian Forster. #733 + * threshold: Population of the "time" field in notifications has been + added. Thanks to Manuel Luis Sanmartín Rozada. + * libvirt: Only gather stats for running domains. Thanks to Ruben + Kerkhof. + * write_graphite: Escape characters not supported by Graphite. Thanks + to Pierre-Yves Ritschard and Marc Fournier. + * write_http: Make callback names context-dependent. Thanks to Marc + Fournier. #821 + * write_riemann: Receive acknowledge message when using TCP. Thanks to + John-John Tedro. + +2013-07-13, Version 5.3.1 + * Documentation: Various fixes. + * Configuration: Fix error handling: Errors in included files were + ignored, causing configuration mistakes to go unnoticed. + * dns plugin: Don't abort when PCAP returns an error. + * modbus plugin: The reconnection strategy was improved, fixing a + segfault in the libmodbud library. Thanks to Stefan Nickl and + Fabien Wernli for their patches. + * mysql plugin: The notification about a newly running MySQL slave + thread has been fixed. Thanks to Joaquín Cuenca Abela for the patch. + * snmp plugin: A build issue has been fixed (C99 mixed declaration). + The end-of-tree check has been improved by Pierre-Yves Ritschard. + * threshold plugin: Handling of the "Interesting" configuration option + has been fixed. Thanks to Björn for the patch. + * write_riemann plugin: A memory leak has been fixed. Thanks to Dave + Cottlehuber for reporting it. + +2013-04-09, Version 5.3.0 + * collectd: The "Include" statements can now be limited to include + only matching files in a directory. Thanks to Sebastian Harl for his + patch. + * collectd: Dispatches / writes are now handled by a thread pool. This + improves reliability and throughput for instances configured to act + as a "server". Thanks to Sebastian Harl and Dan Fandrich for + reviewing this change and fixing bugs. + * aggregation plugin: Selection of value lists is now possible using + regular expressions. Parts of the identifier of the resulting metric + can now be set via the configuration file. + * apcups plugin: The "ReportSeconds" option has been implemented. + * curl* plugins: Support for POST requests and custom request headers + has been added. Thanks to Dan Fandrich for his patch. + * curl_xml plugin: Support for XML namespaces has been added. Thanks + to Dan Fandrich for his patch. + * dbi plugin: Support for numeric options has been added. The + "Host" option has been added. Thanks to Daniel Hilst for his patch. + * disk plugin: Support for systems with >256 has been fixed. Thanks to + Greg Mason for his patch. + * libvirt plugin: Support for memory allocation has been added. Thanks + to Johan Wirén for his patch. + * netapp plugin: Support for "SnapVault", "VFiler" and deduplication / + compression and quota metrics. Thanks to Sebastian Harl for his + patches and teamix GmbH for sponsoring this work. + * postgresql plugin: The reconnection logic has been improved. Thanks + to Sebastian Harl for his patches. + * rrdtool, rrdcached plugins: The "CreateFilesAsync" option has been + implemented. When enabled, new RRD files will be created + asynchronously, which improved throughput of "server" instances. + Many thanks to Yves Mettier for all his input and code. + * tail_csv plugin: This new plugins allows to read metrics from CSV + files, such as Snort's statistics file. Thanks to Kris Nielander for + his patch. + * write_mongodb plugin: Authentication options have been added. + * write_riemann plugin: This new plugin allows sending metrics to + Riemann, a stream processing and alerting tool. Big thanks to + Pierre-Yves Ritschard for his work. + +2013-04-08, Version 5.2.2 + * Build system: A bad interaction between the Java detection code and + libltdl has been fixed. Thanks to Dave Cottlehuber for his patch. + Installation of the Perl bindings has been improved / fixed. Thanks + to Sebastian Harl for his patch. + * collectd: Fixed read callback scheduling at startup. + * apache, ascent, bind, curl, curl_json, curl_xml, nginx and + write_http plugins: Portability fixes, protection from infinite + redirect loops, improved error handling and incorrect dereferences + have been fixed. Most of these are related to the cURL library. + Thanks to Dan Fandrich for his patches. + * logfile plugin: Flush the output file handle. This works around + caching when logging to STDOUT and redirecting into a file. Thanks + to Nathan Huff for the patch. + * mysql plugin: Fix a memory leak in the error handling. Thanks to + Tomas Doran for his patch. + * netapp plugin: Fix the interval with which values are dispatched. + * network plugin: Build issues under FreeBSD and initialization have + been fixed. Thanks to Ed Schouten for his patch. + * nfs plugin: A compilation problem has been fixed. + * notify_email plugin: Add a character set to the mail header. Thanks + to Manuel Cissé for his patch. + * pf plugin: Build issues have been fixed. + * postgresql plugin: Build issues have been fixed. + * rrdcached plugin: Connect to the daemon from the read callback. + * snmp plugin: Matching of SNMP subtrees has been improved. Thanks to + "jkrabbe" for the patch. + * thermal plugin: The initialization of dispatched value lists has + been fixed. Thanks to Markus Knetschke for his patch. + * unixsock plugin: Parsing of options with an underscore, e.g. + "plugin_instance" has been fixed. Thanks to Tommie Gannert for his + patch. + +2013-01-27, Version 5.2.1 + * Build system: "make distcheck" has been fixed. Build fixes Solaris + and systems without gcrypt. Thanks to Yves Mettier for his patches. + * collectd: The complaint mechanism was fixed. It reported messages + more frequently than intended. + * collectd-tg: A manual page has been added. + * dns plugin: Build issues on FreeBSD have been fixed. Thanks to + Ed Schouten for his patch. + * ethstat plugin: Fix the "Map" config option. An incorrectly used + character pointer may lead to a segmentation fault. + * network plugin: Build issues on FreeBSD have been fixed. Thanks to + Ed Schouten for his patch. + * postgresql plugin: A memory leak in the writing code has been fixed. + A use-after-free issue that happened when more than one database was + configured was fixed. Thanks to Sebastian Harl for fixing these + problems. + * redis plugin: A build failure has been fixed. Thanks to Pierre-Yves + Ritschard for his patch. + * varnish plugin: Fix a problem with instances without name. + * write_graphite plugin: A regression which rendered the + "SeparateInstances" and "AlwaysAppendDS" options unusable has been + fixed. A failed assertion when using types with many data sources + has been fixed. Improve reporting of connection errors to not spam + log files too much. Thanks to Pierre-Yves Ritschard for reporting + the logging problem. + * zfs_arc plugin: Fix the type used for mutex misses. Thanks to Yves + Mettier for reporting this bug. + +2012-11-17, Version 5.2.0 + * collectd: The performance of the LISTVAL command has been improved. + Thanks to Yves Mettier for the patch. + * collectd: The possibility to configure the collection interval on a + per-plugin basis has been added. Huge thanks to Sebastian Harl for + his work. + * collectd-tg: This new binary allows to generate random but real + looking collectd network traffic. This can be used to load-test new + plugin, for example. + * libcollectdclient: Code for constructing and sending network packets + in the binary format has been added. + * aggregation plugin: This new plugin allows to aggregate multiple + value lists into one. + * amqp and write_http plugins: Meta data is now included in the JSON + output format. Thanks to Mark Wong for the patch. + * amqp plugin: Support for "Graphite" output has been added. Thanks to + Thomas Meson for the patch. + * contextswitch plugin: Support for AIX has been added. Thanks to + Manuel Rozada for his patch. + * disk plugin: The "UseBSDName" config option has been added to the + Mac OS X version. + * GenericJMX plugin: Automatically determine the host name if it isn't + configured. + * libvirt plugin: The "number" interface format has been added. Thanks + to "Davide Guerri" for the patch. + * memcached plugin: Support for multiple connections has been added. + Thanks to Nicolas Szalay for the patch. + * ntpd plugin: The "IncludeUnitID" config option has been added. The + behavior when a peer is unreachable has been improved. Thanks to + Johan Kiviniemi for the patches. + * oracle plugin: The "Host" config option has been added. + * pf plugin: This new plugin allows to collect statistics from BSD's + packet filter "pf". Thanks to Pierre-Yves Ritschard and Stefan Rinkes + for their work. + * postgresql plugin: The "Instance" config option has been added. + Support for writing values to a PostgreSQL database has been added. + Thanks to Sebastian Harl for the patches. + * processes plugin: Support for Solaris has been added. Thanks to + Cosmin Ioiart for the patch. + * redis plugin: Support for authenticating via password has been added. + Thanks to biancalana for the patch. + * rrdcached plugin: The "HeartBeat", "RRARows", "RRATimespan", + "StepSize" and "XFF" config options have been added. + * swap plugin: The "ReportBytes" config option has been added. The AIX + version now also exports "reserved" pages and swap-in / swap-out + "traffic". Thanks to Manuel Rozada for the patch. + * tcpconns plugin: Use a netlink socket rather than reading from /proc + for improved performance. Thanks to Michael Stapelberg for the patch. + +2013-04-08, Version 5.1.3 + * Build system: A bad interaction between the Java detection code and + libltdl has been fixed. Thanks to Dave Cottlehuber for his patch. + * collectd: Fixed read callback scheduling at startup. + * apache, ascent, bind, curl, curl_json, curl_xml, nginx and + write_http plugins: Portability fixes, protection from infinite + redirect loops, improved error handling and incorrect dereferences + have been fixed. Most of these are related to the cURL library. + Thanks to Dan Fandrich for his patches. + * logfile plugin: Flush the output file handle. This works around + caching when logging to STDOUT and redirecting into a file. Thanks + to Nathan Huff for the patch. + * mysql plugin: Fix a memory leak in the error handling. Thanks to + Tomas Doran for his patch. + * netapp plugin: Fix the interval with which values are dispatched. + * network plugin: Build issues under FreeBSD and initialization have + been fixed. Thanks to Ed Schouten for his patch. + * nfs plugin: A compilation problem has been fixed. + * notify_email plugin: Add a character set to the mail header. Thanks + to Manuel Cissé for his patch. + * rrdcached plugin: Connect to the daemon from the read callback. + * snmp plugin: Matching of SNMP subtrees has been improved. Thanks to + "jkrabbe" for the patch. + * thermal plugin: The initialization of dispatched value lists has + been fixed. Thanks to Markus Knetschke for his patch. + * unixsock plugin: Parsing of options with an underscore, e.g. + "plugin_instance" has been fixed. Thanks to Tommie Gannert for his + patch. + +2013-01-25, Version 5.1.2 + * Build system: "make distcheck" has been fixed. Thanks to Yves + Mettier for his patches. + * collectd: The complaint mechanism was fixed. It reported messages + more frequently than intended. + * dns plugin: Build issues on FreeBSD have been fixed. Thanks to + Ed Schouten for his patch. + * ethstat plugin: Fix the "Map" config option. An incorrectly used + character pointer may lead to a segmentation fault. + * network plugin: Build issues on FreeBSD have been fixed. Thanks to + Ed Schouten for his patch. + * varnish plugin: Fix a problem with instances without name. + * write_graphite: Improve reporting of connection errors to not spam + log files too much. Thanks to Pierre-Yves Ritschard for reporting + this problem. + * zfs_arc plugin: Fix the type used for mutex misses. Thanks to Yves + Mettier for reporting this bug. + +2012-11-11, Version 5.1.1 + * collectd: Create new directories with mode 0777 and let umask remove + unwanted permission bits. + * collectd: Build issues have been fixed. + * collectd: An incorrect assertion has been fixed in some common code + for Solaris. This should resolve pseudo-random assertion failures + under Solaris. Thanks to Jeff Blane for his help debugging this. + * collectd: A couple of memory leaks through PThread thread attributes + have been fixed. Thanks to Gerrie Roos for fixing these. + * collectdctl: Fix PUTVAL for data sets with multiple data sources. + Thanks to Cyril Feraudet for reporting this problem. + * contrib/migrate-4-5.px: Handle to "df" to "df_complex" conversion + correctly. + * apcups plugin: Improve the reconnect behavior. + * curl_xml plugin: The "Host" setting was silently ignored. Thanks to + Fabien Wernli for fixing this. + * df plugin: Ignore "rootfs" devices under Linux to avoid having them + reported twice. Thanks to Brune Prémont for fixing this. + * disk plugin: Fix incorrect computation of read and write latency (the + "disk_time" type). Previously, the numbers reported where too small + by a factor of "interval", e.g. when the interval is set to 10 + seconds, the values were too low by a factor of 10. Thanks to Manuel + Sanmartin for reporting this problem. + * dns plugin: A build issue under Solaris has been fixed. A erroneous + define that could lead to the reporting of bad data has been fixed by + Daniel Sutto. + * ethstat plugin: An off-by-one error and potential use of + uninitialized memory has been fixed. Thanks to Mark Voelker for + reporting these problems. + * memcachec plugin: A bug in the configuration handling has been fixed. + Thanks to Pascal Hofmann for fixing this issue. + * mysql plugin: Fix a bug when registering multiple databases. Thanks + to Sebastian Harl for fixing this. + * netapp plugin: Correctly close the connection on communication + errors. + * netlink plugin: The function used to query statistics has been + changed to be more in line with iproute2's behavior. Thanks to + "KIvosak" for the patch. + * network plugin: Initialization of libgcrypt has been fixed. Thanks to + Chris Lundquist for his patch. + * oracle plugin: Error messages have been improved. + * ping plugin: Don't enter the exponential back-off mode when + ping_send() fails. This should make recovery after a network failure + much faster. + * python plugin: Memory leaks have been fixed. Thanks to Tommie Gannert + and Sven Trenkel for fixing this. + * redis plugin: Fix a compilation problem on FreeBSD. Thanks to + "biancalana" for the fix. + * rrdtool plugin: Fix an out-of-bounds array access when printing a + warning message. Thanks to Will Hawkins for fixing this bug. + * snmp plugin: Support for the SNMP_ENDOFMIBVIEW return value has been + added. Support for more complex / unusual MIBs / subtrees has been + added. Thanks to Mark Juric to test the changes and point out these + problems. + * varnish plugin: Support for multiple instances of Varnish 3 has been + fixed. Thanks to Jonathan Huot for the patch. + * write_mongodb plugin: Add compatibility with libmongo 0.6.0 and + later. Thanks to Chris Lundquist for this patch. + +2012-04-01, Version 5.1.0 + * Build system, iptables plugin: The shipped version of libiptc has + been removed. + * collectd-nagios: A list of value lists can now be queried using + "-n LIST". Thanks to Sebastian Harl for his patches. + * bind plugin: The "ParseTime" option has been added. It allows to use + the system time rather than the time reported by BIND. + * curl, memcachec, tail plugins: The "ExcludeRegexp" option has been + added. Thanks to Peter Warasin for his initial patch. + * ethstat plugin: The new "ethstat" plugin reads performance statistics + directly from ethernet cards. Thanks to Cyril Feraudet for his patch. + * GenericJMX plugin: Support for querying MBean "Operations" (in + addition to "Attributes") has been added. Thanks to Pierre-Yves + Ritschard for his patch. + * irq plugin: The selection / ignore code now uses the default + ignorelist infrastructure, providing the standard feature set, e.g. + regex matching. + * md plugin: The new "md" plugin reports the number of disks in various + states in Linux software RAID devices. Thanks to Michael Hanselmann + for his patch. + * modbus plugin: Support for signed integer register types has been + added. + * nfs plugin: Support for Solaris has been added. Thanks to Cosmin + Ioiart for his patch. + * numa plugin: The new "numa" plugin reports statistics of the + Non-Uniform Memory Access (NUMA) subsystem of Linux. + * processes plugin: Various fixes for the FreeBSD implementation. + Thanks to Phil Kulin for his patch. + * rrdcached plugin: Passing flushes to the caching daemon has been + added. + * sensors plugin: The initialization code has been improved. Thanks to + Henrique de Moraes Holschuh for his patch. + * swap plugin: The "ReportByDevice" option has been added. + * syslog plugin: Support for writing notifications has been added. + Thanks to Fabien Wernli for his patch. + * tcpconns plugin: Support for AIX has been added. Thanks to Manuel + Luis Sanmartín Rozada for his patch. + * threshold plugin: The "PersistOK" option has been added. Thanks to + Aaron Brady for his patch. + * varnish plugin: Support for Varnish 3.0 has been added. Thanks to + Jérôme Renard for his patches. + * write_mongodb plugin: The new "write_mongodb" plugin writes value + lists to MongoDB, a shema-less database. Thanks to Akkarit Sangpetch + and Chris Lundquist for their work. + * write_graphite plugin: The new "write_graphite" plugin writes value + lists to Carbon, the storage layer of the Graphite time-series + database. Thanks to Scott Sanders and Pierre-Yves Ritschard for their + work. + * zfs_arc plugin: Several new statistics have been added. Thanks to + Aurelien Rougemont for his patches. + * scale target: Support for scaling specific data sources only has been + added. Thanks to Gerrie Roos for his patch. + +2012-11-11, Version 5.0.5 + * collectd: Create new directories with mode 0777 and let umask remove + unwanted permission bits. + * collectd: Build issues have been fixed. + * collectd: An incorrect assertion has been fixed in some common code + for Solaris. This should resolve pseudo-random assertion failures + under Solaris. Thanks to Jeff Blane for his help debugging this. + * collectd: A couple of memory leaks through PThread thread attributes + have been fixed. Thanks to Gerrie Roos for fixing these. + * collectdctl: Fix PUTVAL for data sets with multiple data sources. + Thanks to Cyril Feraudet for reporting this problem. + * contrib/migrate-4-5.px: Handle to "df" to "df_complex" conversion + correctly. + * apcups plugin: Improve the reconnect behavior. + * curl_xml plugin: The "Host" setting was silently ignored. Thanks to + Fabien Wernli for fixing this. + * df plugin: Ignore "rootfs" devices under Linux to avoid having them + reported twice. Thanks to Brune Prémont for fixing this. + * disk plugin: Fix incorrect computation of read and write latency (the + "disk_time" type). Previously, the numbers reported where too small + by a factor of "interval", e.g. when the interval is set to 10 + seconds, the values were too low by a factor of 10. Thanks to Manuel + Sanmartin for reporting this problem. + * dns plugin: A build issue under Solaris has been fixed. A erroneous + define that could lead to the reporting of bad data has been fixed by + Daniel Sutto. + * memcachec plugin: A bug in the configuration handling has been fixed. + Thanks to Pascal Hofmann for fixing this issue. + * mysql plugin: Fix a bug when registering multiple databases. Thanks + to Sebastian Harl for fixing this. + * netapp plugin: Correctly close the connection on communication + errors. + * netlink plugin: The function used to query statistics has been + changed to be more in line with iproute2's behavior. Thanks to + "KIvosak" for the patch. + * network plugin: Initialization of libgcrypt has been fixed. Thanks to + Chris Lundquist for his patch. + * oracle plugin: Error messages have been improved. + * ping plugin: Don't enter the exponential back-off mode when + ping_send() fails. This should make recovery after a network failure + much faster. + * python plugin: Memory leaks have been fixed. Thanks to Tommie Gannert + and Sven Trenkel for fixing this. + * redis plugin: Fix a compilation problem on FreeBSD. Thanks to + "biancalana" for the fix. + * rrdtool plugin: Fix an out-of-bounds array access when printing a + warning message. Thanks to Will Hawkins for fixing this bug. + * snmp plugin: Support for the SNMP_ENDOFMIBVIEW return value has been + added. Support for more complex / unusual MIBs / subtrees has been + added. Thanks to Mark Juric to test the changes and point out these + problems. + +2012-04-01, Version 5.0.4 + * Build system: Fix the use of a libltdl macro. Thanks to Clemens Lang + for fixing this. Adresses some issues with building the iptables + plugin under Gentoo. + * libcollectdclient: A memory leak in the lcc_getval() function has + been fixed. Thanks to Jason Schmidlapp for finding and fixing this + issue. + * bind plugin: The use of 'QType" types has been fixed. + * df plugin: Fixed compiler issue under Mac OS X 10.7. + * conntrack plugin: Support zero as legitimate value. Thanks to Louis + Opter for his patch. + * memcached plugin: Increased the size of a static buffer, which was + truncating status messages form memcached. Thanks to Timon for the + patch. + * network plugin: Forwarding of notifications has been disabled. This + was a contition not checked for before, which may retult in an + endless loop. + * processes plugin: Support for process names with spaces has been + added to the Linux implementation. Thanks to Darrell Bishop for his + patch. + * perl plugin: A race condition in several callbacks, including log and + write callbacks, has been fixed. Thanks to "Rrpv" for reporting this + bug. + * snmp plugin: A bug when casting unsigned integers to gauge values has + been fixed: Unsigned integers would be cast to a signed integer and + then to a gauge, possibly resulting in a negative value. + * tcpconns plugin: Compilation with newer versions of the FreeBSD + runtime has been fixed. + +2012-02-19, Version 5.0.3 + * Build system: Fix problems when building the ipvs and iptables + plugins. Thanks to Sebastian Harl for his patch. A bashism in the + version-gen.sh script has been fixed. Thanks to Jo-Philipp Wich for + his patch. + * csv and rrdtool plugins: Print a more helpful error message when the + DataDir is a symlink pointing to a non-existing location. Thanks to + Jonathan Nieder for his patch. + * exec plugin: Fix a problem when using select(2) to read from file + handles. Thanks to Gerrie Roos for his patch. + * network plugin: An incorrect error message in the handling of the + "Interface" configuration option has been fixed. Thanks to Gerrie + Roos for his patch. + * oracle plugin: A potential endless loop in the error handling has + been fixed. + * python plugin: A crash bug in the configuration handling has been + fixed. Thanks to Sven Trenkel for his patch. + * interfaces plugin: The change which was supposed to ignore "bogus" + interfaces has been reverted, since it ignored legit interfaces, such + as bonding pseudo-devices as well. + +2012-01-21, Version 5.0.2 + * curl_xml plugin: Fix handling of file:// and other URLs (which don't + follow HTTP status codes). Thanks to Fabien Wernli for his patch! + * df plugin: Fix handling of negative "available" counts. This can + occur with some file systems, for example UFS. Thanks to Toni Ylenius + for his patch. + * interface plugin: "mac" interfaces are now ignored on Solaris. These + pseudo-interfaces occur multiple times, causing warnings. Also switch + to 64-bit counters on Solaris, improving overflow behavior for + high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for + their patches. + * memory plugin: Account kernel and unused memory under Solaris. Thanks + to Fabien Wernli for his patch. + * network plugin: A bug in the interaction between the Network plugin + and filter chains has been fixed: When a filter modified a field such + as the hostname, subsequent values in the same network packets could + have ended up using the modified name rather than the original name. + Thanks to Sebastian Harl for identifying the problem. + * oracle plugin: A memory leak has been fixed in the parameter handling. + * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel + for fixing this bug! + +2011-10-07, Version 5.0.1 + * collectd: A mutex leak has been fixed in the meta data code. Thanks + to Rafal Lesniak for his patch. + * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks + to Peter Green for his patch. + * csv plugin: The line buffer size has been increased. Thanks to Colin + McCabe for the patch. + * curl_json plugin: Don't use the "parent" node to build the type + instance, if it is empty. Compatibility with libyajl 2 has been + added. Thanks to "spupykin" of the Arch Linux project for the initial + code. Formatting of time has been fixed in the JSON module. + * exec plugin: Fix the timestamp value passed to notification scripts. + Thanks to Alexander Kovalenko for fixing this. + * iptables plugin: Fix linking with some versions of libiptc. + * irq plugin: Fix support for interrupts under Linux. The old code + assumed that interrupts have a numeric value -- this is no longer + true for Linux. Thanks to Bostjan Skufca for implementing this. + * notify_desktop plugin: Compatibility with libnotify 0.7 has been + added. Thanks to Samuli Suominen for his patch. + * processes plugin: Fix handling of regular expressions containing + spaces. Thanks for Sebastian Harl for fixing this. + * rrdtool, rrdcached plugins: Improve precision of the XFF parameter. + Previously, values like 0.999 would have been rounded to 1.0. Thanks + to Francois-Xavier Bourlet for fixing this. + * varnish plugin: Fix data type handling of some metrics. Some values + were submitted as gauge even though they were derives. + * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike + Flisher for the fix. + +2011-03-28, Version 5.0.0 + * collectd: The "FQDNLookup" option is now enabled by default. + * collectd: The internal representation of time has been changed to + allow a higher accuracy than one second. + * collectdcmd: This new command line utility can send various commands + to collectd using the UnixSock plugin. Thanks to HÃ¥kon Dugstad + Johnsen and Sebastian Harl for their code. + * collectd-nagios: The "-m" option has been implemented (treat NaNs as + critical). + * collectd-tg: Traffic generator creating bogus network traffic + compatible to the Network plugin. This utility can be used to + stress-test new write plugins and collectd in general. + * libcollectdclient: Creating and sending network packets has been + added to the collectd client library. + * All data sets: The data source name of all data sets with exactly + one data source has been changed to "value". + * All plugins: All "counter" data sources have been converted to + "derive" data sources. All plugins now use "derive" by default, but + plugins such as the network plugin can still handle "counter", of + course. The minimum value of all derive data sources is zero, the + maximum value is unspecified. + * amqp plugin: The new AMQP plugin can send data to and receive data + from an AMQP broker. Thanks to Sebastien Pahl for his code. + * apache plugin: Backwards compatibility code has been removed. + Support for the IBM HTTP Server has been added. Thanks to Manuel + Luis Sanmartín Rozada for his patch. + * contextswitch plugin: Support for sysctlbyname(3) has been added. + Thanks to Kimo Rosenbaum for his patch. + * df plugin: The default behavior has been changed to be equivalent to + the "ReportReserved" behavior of v4. + * dns plugin: Improved RFC 1035 name parsing has been imported from + "dnstop". + * exec plugin: Backwards compatibility code has been removed. + * GenericJMX plugin: The "InstancePrefix" option has been added to + "Connection" blocks. + * hddtemp plugin: The "TranslateDevicename" config option has been + removed. + * interface plugin: Use the "plugin instance" to store the interface + value. + * libvirt plugin: The "InterfaceFormat" option has been added. Thanks + to Ruben Kerkhof for his patch. + * lpar plugin: New plugins for "logical partitions", a virtualization + technique of POWER CPUs. Thanks to Aurélien Reynaud for his code and + patience. + * modbus plugin: Support for libmodbus 2.9.2 has been added and the + license has been changed to LGPLv2.1. + * mysql plugin: Backwards compatibility code has been removed. The + data sets used have been improved. + * network plugin: The default buffer size has been increased to + 1452 bytes. + * perl plugin: Backwards compatibility code has been removed. + * postgresql plugin: Backwards compatibility code has been removed. + * redis plugin: Plugin for collecting statistics from Redis, a key- + value store, has been added. Thanks to Andres J. Diaz for his code. + * swap plugin: Implement collection of physical and virtual memory + statistics under Solaris. The new default is collecting physical + memory. Thanks to Aurélien Reynaud for his patches. + * threshold plugin: The threshold configuration has been moved into + this separate plugin. + * unixsock plugin: The "DeleteSocket" option has been added. + * varnish plugin: The new Varnish plugin reads statistics from + Varnish, a web accelerator. Thanks to Jérôme Renard and Marc + Fournier for their contributions. + * write_redis: New plugin for writing data to Redis, a key-value + store. + * zfs_arc plugin: The data sets have been replaced by more elegant + alternatives. + * v5upgrade target: Target for converting v4 data sets to the v5 + schema. + 2013-04-07, Version 4.10.9 * Build system: A bad interaction between the Java detection code and libltdl has been fixed. Thanks to Dave Cottlehuber for his patch. diff --git a/README b/README index 34caa85d..c3c45472 100644 --- a/README +++ b/README @@ -83,6 +83,9 @@ Features - entropy Amount of entropy available to the system. + - ethstat + Network interface card statistics. + - exec Values gathered by a custom program or script. See collectd-exec(5). @@ -125,8 +128,12 @@ Features - load System load average over the last 1, 5 and 15 minutes. + - lpar + Detailed CPU statistics of the “Logical Partitions” virtualization + technique built into IBM's POWER processors. + - libvirt - CPU, disk and network I/O statistics from virtual machines. + CPU, memory, disk and network I/O statistics from virtual machines. - madwifi Queries very detailed usage statistics from wireless LAN adapters and @@ -136,6 +143,10 @@ Features Motherboard sensors: temperature, fanspeed and voltage information, using mbmon(1). + - md + Linux software-RAID device information (number of active, failed, spare + and missing disks). + - memcachec Query and parse data from a memcache daemon (memcached). @@ -188,6 +199,9 @@ Features Network UPS tools: UPS current, voltage, power, charge, utilisation, temperature, etc. See upsd(8). + - numa + Information about Non-Uniform Memory Access (NUMA). + - olsrd Queries routing information from the “Optimized Link State Routing” daemon. @@ -208,6 +222,9 @@ Features write your own plugins in Perl and return arbitrary values using this API. See collectd-perl(5). + - pf + Query statistics from BSD's packet filter "pf". + - pinba Receive and dispatch timing values from Pinba, a profiling extension for PHP. @@ -235,6 +252,10 @@ Features collectd without the need to start a heavy interpreter every interval. See collectd-python(5) for details. + - redis + The redis plugin gathers information from a redis server, including: + uptime, used memory, total connections etc. + - routeros Query interface and wireless registration statistics from RouterOS. @@ -263,6 +284,10 @@ Features Follows (tails) logfiles, parses them by lines and submits matched values. + - tail_csv + Follows (tails) files in CSV format, parses each line and submits + extracted values. + - tape Bytes and operations read and written on tape devices. Solaris only. @@ -288,6 +313,9 @@ Features - users Users currently logged in. + - varnish + Various statistics from Varnish, an HTTP accelerator. + - vmem Virtual memory statistics, e. g. the number of page-ins/-outs or the number of pagefaults. @@ -308,6 +336,10 @@ Features * Output can be written or sent to various destinations by the following plugins: + - amqp + Sends JSON-encoded data to an Advanced Message Queuing Protocol (AMQP) + server, such as RabbitMQ. + - csv Write to comma separated values (CSV) files. This needs lots of diskspace but is extremely portable and can be analysed with almost @@ -343,11 +375,23 @@ Features needed. Please read collectd-unixsock(5) for a description on how that's done. + - write_graphite + Sends data to Carbon, the storage layer of Graphite. + - 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. + - write_mongodb + Sends data to MongoDB, a NoSQL database. + + - write_redis + Sends the values to a Redis key-value database server. + + - write_riemann + Sends data to Riemann, a stream processing and monitoring system. + * Logging is, as everything in collectd, provided by plugins. The following plugins keep up informed about what's going on: @@ -427,6 +471,14 @@ Features * Miscellaneous plugins: + - aggregation + Selects multiple value lists based on patterns or regular expressions + and creates new aggregated values lists from those. + + - threshold + Checks values against configured thresholds and creates notifications if + values are out of bounds. See collectd-threshold(5) for details. + - uuid Sets the hostname to an unique identifier. This is meant for setups where each client may migrate to another physical host, possibly going @@ -504,6 +556,10 @@ Prerequisites * libclntsh (optional) Used by the `oracle' plugin. + * libcredis (optional) + Used by the redis plugin. Please note that you require a 0.2.2 version + or higher. + * libcurl (optional) If you want to use the `apache', `ascent', `curl', `nginx', or `write_http' plugin. @@ -610,6 +666,10 @@ Prerequisites are supported. + * librabbitmq (optional; also called “rabbitmq-c”) + Used by the AMQP plugin for AMQP connections, for example to RabbitMQ. + + * librouteros (optional) Used by the `routeros' plugin to connect to a device running `RouterOS'. @@ -656,6 +716,10 @@ Prerequisites Parse JSON data. This is needed for the `curl_json' plugin. + * libvarnish (optional) + Fetches statistics from a Varnish instance. This is needed for the Varnish plugin + + Configuring / Compiling / Installing ------------------------------------ diff --git a/bindings/Makefile.am b/bindings/Makefile.am index 3876cc2c..07373e87 100644 --- a/bindings/Makefile.am +++ b/bindings/Makefile.am @@ -5,6 +5,7 @@ SUBDIRS += java endif EXTRA_DIST = perl/Makefile.PL \ + perl/uninstall_mod.pl \ perl/lib/Collectd.pm \ perl/lib/Collectd/Unixsock.pm \ perl/lib/Collectd/Plugins/Monitorus.pm \ @@ -33,12 +34,8 @@ install-exec-local: # Perl 'make uninstall' does not work as well as wanted. # So we do the work here. uninstall-local: - rm -f $(DESTDIR)$(mandir)/man3/Collectd::Unixsock.3pm - rm -f $(DESTDIR)$(datarootdir)/perl5/Collectd.pm - rm -f $(DESTDIR)$(datarootdir)/perl5/Collectd/Plugins/OpenVZ.pm - rm -f $(DESTDIR)$(datarootdir)/perl5/Collectd/Unixsock.pm - rm -f $(DESTDIR)$(prefix)/lib64/perl5/perllocal.pod - rm -f $(DESTDIR)$(prefix)/lib64/perl5/auto/Collectd/.packlist + @PERL@ -I$(DESTDIR)$(prefix) $(srcdir)/perl/uninstall_mod.pl Collectd + find $(DESTDIR)$(prefix) -name "perllocal.pod" -exec rm {} \; clean-local: rm -rf buildperl @@ -48,7 +45,13 @@ perl: buildperl/Makefile buildperl/Makefile: .perl-directory-stamp buildperl/Makefile.PL \ $(top_builddir)/config.status - cd buildperl && @PERL@ Makefile.PL INSTALL_BASE=$(prefix) @PERL_BINDINGS_OPTIONS@ + @# beautify the output a bit + @echo 'cd buildperl && @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@' + @cd buildperl && ( if ! @PERL@ Makefile.PL @PERL_BINDINGS_OPTIONS@; then \ + echo ""; \ + echo 'Check whether you have set $$PERL_MM_OPT in your environment and try using ./configure --with-perl-bindings=""'; \ + echo ""; \ + fi ) buildperl/Makefile.PL: .perl-directory-stamp $(top_builddir)/config.status diff --git a/bindings/java/org/collectd/api/CollectdFlushInterface.java b/bindings/java/org/collectd/api/CollectdFlushInterface.java index 3e492ddf..410c61c6 100644 --- a/bindings/java/org/collectd/api/CollectdFlushInterface.java +++ b/bindings/java/org/collectd/api/CollectdFlushInterface.java @@ -29,5 +29,5 @@ package org.collectd.api; */ public interface CollectdFlushInterface { - public int flush (int timeout, String identifier); + public int flush (Number timeout, String identifier); } diff --git a/bindings/java/org/collectd/api/ValueList.java b/bindings/java/org/collectd/api/ValueList.java index 1baeff24..b8d6f40f 100644 --- a/bindings/java/org/collectd/api/ValueList.java +++ b/bindings/java/org/collectd/api/ValueList.java @@ -87,10 +87,16 @@ public class ValueList extends PluginData { _ds = new DataSet (_type, dsrc); } + /** + * Returns the interval (in milliseconds) of the value list. + */ public long getInterval() { return _interval; } + /** + * Sets the interval (in milliseconds) of the value list. + */ public void setInterval(long interval) { _interval = interval; } diff --git a/bindings/java/org/collectd/java/GenericJMXConfConnection.java b/bindings/java/org/collectd/java/GenericJMXConfConnection.java index ffa9ded4..81aee033 100644 --- a/bindings/java/org/collectd/java/GenericJMXConfConnection.java +++ b/bindings/java/org/collectd/java/GenericJMXConfConnection.java @@ -1,6 +1,6 @@ /* * collectd/java - org/collectd/java/GenericJMXConfConnection.java - * Copyright (C) 2009 Florian octo Forster + * Copyright (C) 2009-2012 Florian octo Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,7 +16,7 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: - * Florian octo Forster + * Florian octo Forster */ package org.collectd.java; @@ -26,10 +26,10 @@ import java.util.Map; import java.util.Iterator; import java.util.ArrayList; import java.util.HashMap; +import java.net.InetAddress; +import java.net.UnknownHostException; import javax.management.MBeanServerConnection; -import javax.management.ObjectName; -import javax.management.MalformedObjectNameException; import javax.management.remote.JMXServiceURL; import javax.management.remote.JMXConnector; @@ -45,6 +45,7 @@ class GenericJMXConfConnection private String _username = null; private String _password = null; private String _host = null; + private String _instance_prefix = null; private String _service_url = null; private MBeanServerConnection _jmx_connection = null; private List _mbeans = null; @@ -76,6 +77,24 @@ class GenericJMXConfConnection return (v.getString ()); } /* }}} String getConfigString */ + private String getHost () /* {{{ */ + { + if (this._host != null) + { + return (this._host); + } + + try + { + InetAddress localHost = InetAddress.getLocalHost(); + return (localHost.getHostName ()); + } + catch (UnknownHostException e) + { + return ("localhost"); + } + } /* }}} String getHost */ + private void connect () /* {{{ */ { JMXServiceURL service_url; @@ -162,6 +181,12 @@ private void connect () /* {{{ */ if (tmp != null) this._service_url = tmp; } + else if (child.getKey ().equalsIgnoreCase ("InstancePrefix")) + { + String tmp = getConfigString (child); + if (tmp != null) + this._instance_prefix = tmp; + } else if (child.getKey ().equalsIgnoreCase ("Collect")) { String tmp = getConfigString (child); @@ -204,14 +229,15 @@ private void connect () /* {{{ */ + ((this._host != null) ? this._host : "(null)")); pd = new PluginData (); - pd.setHost ((this._host != null) ? this._host : "localhost"); + pd.setHost (this.getHost ()); pd.setPlugin ("GenericJMX"); for (int i = 0; i < this._mbeans.size (); i++) { int status; - status = this._mbeans.get (i).query (this._jmx_connection, pd); + status = this._mbeans.get (i).query (this._jmx_connection, pd, + this._instance_prefix); if (status != 0) { this._jmx_connection = null; diff --git a/bindings/java/org/collectd/java/GenericJMXConfMBean.java b/bindings/java/org/collectd/java/GenericJMXConfMBean.java index 1587bd5f..b1fbfb3e 100644 --- a/bindings/java/org/collectd/java/GenericJMXConfMBean.java +++ b/bindings/java/org/collectd/java/GenericJMXConfMBean.java @@ -1,6 +1,6 @@ /* * collectd/java - org/collectd/java/GenericJMXConfMBean.java - * Copyright (C) 2009 Florian octo Forster + * Copyright (C) 2009,2010 Florian octo Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -67,22 +67,6 @@ class GenericJMXConfMBean return (v.getString ()); } /* }}} String getConfigString */ - private String join (String separator, List list) /* {{{ */ - { - StringBuffer sb; - - sb = new StringBuffer (); - - for (int i = 0; i < list.size (); i++) - { - if (i > 0) - sb.append ("-"); - sb.append (list.get (i)); - } - - return (sb.toString ()); - } /* }}} String join */ - /* * * ObjectName "object name" @@ -170,7 +154,8 @@ class GenericJMXConfMBean return (this._name); } /* }}} */ - public int query (MBeanServerConnection conn, PluginData pd) /* {{{ */ + public int query (MBeanServerConnection conn, PluginData pd, /* {{{ */ + String instance_prefix) { Set names; Iterator iter; @@ -197,11 +182,12 @@ class GenericJMXConfMBean ObjectName objName; PluginData pd_tmp; List instanceList; - String instance; + StringBuffer instance; objName = iter.next (); pd_tmp = new PluginData (pd); instanceList = new ArrayList (); + instance = new StringBuffer (); Collectd.logDebug ("GenericJMXConfMBean: objName = " + objName.toString ()); @@ -224,14 +210,22 @@ class GenericJMXConfMBean } } + if (instance_prefix != null) + instance.append (instance_prefix); + if (this._instance_prefix != null) - instance = new String (this._instance_prefix - + join ("-", instanceList)); - else - instance = join ("-", instanceList); - pd_tmp.setPluginInstance (instance); + instance.append (this._instance_prefix); + + for (int i = 0; i < instanceList.size (); i++) + { + if (i > 0) + instance.append ("-"); + instance.append (instanceList.get (i)); + } + + pd_tmp.setPluginInstance (instance.toString ()); - Collectd.logDebug ("GenericJMXConfMBean: instance = " + instance); + Collectd.logDebug ("GenericJMXConfMBean: instance = " + instance.toString ()); for (int i = 0; i < this._values.size (); i++) this._values.get (i).query (conn, objName, pd_tmp); diff --git a/bindings/java/org/collectd/java/GenericJMXConfValue.java b/bindings/java/org/collectd/java/GenericJMXConfValue.java index 0eb0d5f8..9fb0fc2e 100644 --- a/bindings/java/org/collectd/java/GenericJMXConfValue.java +++ b/bindings/java/org/collectd/java/GenericJMXConfValue.java @@ -312,7 +312,14 @@ class GenericJMXConfValue try { - value = conn.getAttribute (objName, key); + try + { + value = conn.getAttribute (objName, key); + } + catch (javax.management.AttributeNotFoundException e) + { + value = conn.invoke (objName, key, /* args = */ null, /* types = */ null); + } } catch (Exception e) { diff --git a/bindings/perl/lib/Collectd.pm b/bindings/perl/lib/Collectd.pm index f1b5d859..c1adf442 100644 --- a/bindings/perl/lib/Collectd.pm +++ b/bindings/perl/lib/Collectd.pm @@ -42,6 +42,7 @@ our %EXPORT_TAGS = ( plugin_register plugin_unregister plugin_dispatch_values + plugin_get_interval plugin_write plugin_flush plugin_flush_one @@ -171,6 +172,7 @@ sub plugin_call_all { my $type = shift; my %plugins; + my $interval; our $cb_name = undef; @@ -194,13 +196,15 @@ sub plugin_call_all { %plugins = %{$plugins[$type]}; } + $interval = plugin_get_interval (); + foreach my $plugin (keys %plugins) { my $p = $plugins{$plugin}; my $status = 0; if ($p->{'wait_left'} > 0) { - $p->{'wait_left'} -= $interval_g; + $p->{'wait_left'} -= $interval; } next if ($p->{'wait_left'} > 0); @@ -227,11 +231,11 @@ sub plugin_call_all { if ($status) { $p->{'wait_left'} = 0; - $p->{'wait_time'} = $interval_g; + $p->{'wait_time'} = $interval; } elsif (TYPE_READ == $type) { - if ($p->{'wait_time'} < $interval_g) { - $p->{'wait_time'} = $interval_g; + if ($p->{'wait_time'} < $interval) { + $p->{'wait_time'} = $interval; } $p->{'wait_left'} = $p->{'wait_time'}; @@ -313,7 +317,7 @@ sub plugin_register { } %p = ( - wait_time => $interval_g, + wait_time => plugin_get_interval (), wait_left => 0, cb_name => $data, ); @@ -465,35 +469,6 @@ sub plugin_flush { } } -sub plugin_flush_one { - my $timeout = shift; - my $name = shift; - - WARNING ("Collectd::plugin_flush_one is deprecated - " - . "use Collectd::plugin_flush instead."); - - if (! (defined ($timeout) && defined ($name))) { - ERROR ("Usage: Collectd::plugin_flush_one(timeout, name)"); - return; - } - - plugin_flush (plugins => $name, timeout => $timeout); -} - -sub plugin_flush_all { - my $timeout = shift; - - WARNING ("Collectd::plugin_flush_all is deprecated - " - . "use Collectd::plugin_flush instead."); - - if (! defined ($timeout)) { - ERROR ("Usage: Collectd::plugin_flush_all(timeout)"); - return; - } - - plugin_flush (timeout => $timeout); -} - sub fc_call { my $type = shift; my $name = shift; diff --git a/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm b/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm index 29441574..ea3cee99 100644 --- a/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm +++ b/bindings/perl/lib/Collectd/Plugins/OpenVZ.pm @@ -36,7 +36,7 @@ my $last_stat = {}; sub openvz_read { - my %v = (time => time(), interval => $interval_g); + my %v = (time => time(), interval => plugin_get_interval()); my (@veids, $veid, $name, $key, $val, $i, @lines, @parts, @counters); @veids = map { s/ //g; $_; } split(/\n/, `$vzlist -Ho veid`); diff --git a/bindings/perl/uninstall_mod.pl b/bindings/perl/uninstall_mod.pl new file mode 100644 index 00000000..f8083af1 --- /dev/null +++ b/bindings/perl/uninstall_mod.pl @@ -0,0 +1,8 @@ +#! /usr/bin/perl + +use strict; +use ExtUtils::Installed; + +my $mod = $ARGV[0] || die "Usage : $0 Module\n"; +my $inst = ExtUtils::Installed->new(); +unlink $inst->files($mod), $inst->packlist($mod)->packlist_file(); diff --git a/clean.sh b/clean.sh index 098669da..9defb05d 100755 --- a/clean.sh +++ b/clean.sh @@ -47,4 +47,6 @@ true \ && rm -f -r src/libcollectdclient/.libs \ && rm -f src/libcollectdclient/*.o \ && rm -f src/libcollectdclient/*.la \ -&& rm -f src/libcollectdclient/*.lo +&& rm -f src/libcollectdclient/*.lo \ +&& rm -f bindings/.perl-directory-stamp \ +&& rm -f -r bindings/buildperl diff --git a/configure.in b/configure.in index 5dac5431..877ac449 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(collectd, m4_esyscmd(./version-gen.sh)) +AC_INIT(collectd, [m4_esyscmd(./version-gen.sh)]) AC_CONFIG_SRCDIR(src/collectd.c) AC_CONFIG_HEADERS(src/config.h) AC_CONFIG_AUX_DIR([libltdl/config]) @@ -24,7 +24,7 @@ m4_ifdef([LT_PACKAGE_VERSION], ] ) -AM_INIT_AUTOMAKE(dist-bzip2) +AM_INIT_AUTOMAKE([tar-pax dist-bzip2]) AC_LANG(C) AC_PREFIX_DEFAULT("/opt/collectd") @@ -49,6 +49,13 @@ AC_PROG_YACC PKG_PROG_PKG_CONFIG AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no]) +AC_CHECK_HEADERS([google/protobuf-c/protobuf-c.h], + [have_protobuf_c_h="yes"], + [have_protobuf_c_h="no"]) +if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes" +then + have_protoc_c="no (unable to find )" +fi AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes") AC_MSG_CHECKING([for kernel type ($host_os)]) @@ -91,6 +98,7 @@ fi if test "x$ac_system" = "xSolaris" then AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1, [Define to enforce POSIX thread semantics under Solaris.]) + AC_DEFINE(_REENTRANT, 1, [Define to enable reentrancy interfaces.]) fi if test "x$ac_system" = "xAIX" then @@ -109,9 +117,13 @@ AC_ARG_ENABLE(standards, if test "x$enable_standards" = "xyes" then AC_DEFINE(_ISOC99_SOURCE, 1, [Define to enforce ISO C99 compliance.]) - AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Define to enforce POSIX.1-2001 compliance.]) - AC_DEFINE(_XOPEN_SOURCE, 600, [Define to enforce X/Open 6 (XSI) compliance.]) + AC_DEFINE(_POSIX_C_SOURCE, 200809L, [Define to enforce POSIX.1-2008 compliance.]) + AC_DEFINE(_XOPEN_SOURCE, 700, [Define to enforce X/Open 7 (XSI) compliance.]) AC_DEFINE(_REENTRANT, 1, [Define to enable reentrancy interfaces.]) + if test "x$GCC" = "xyes" + then + CFLAGS="$CFLAGS -std=c99" + fi fi AM_CONDITIONAL(BUILD_FEATURE_STANDARDS, test "x$enable_standards" = "xyes") @@ -123,7 +135,7 @@ AC_HEADER_SYS_WAIT AC_HEADER_DIRENT AC_HEADER_STDBOOL -AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h) +AC_CHECK_HEADERS(stdio.h errno.h math.h stdarg.h syslog.h fcntl.h signal.h assert.h sys/types.h sys/socket.h sys/select.h poll.h netdb.h arpa/inet.h sys/resource.h sys/param.h kstat.h regex.h sys/ioctl.h endian.h sys/isa_defs.h fnmatch.h libgen.h) # For ping library AC_CHECK_HEADERS(netinet/in_systm.h, [], [], @@ -265,7 +277,19 @@ if test "x$ac_system" = "xDarwin" then AC_CHECK_HEADERS(mach/mach_init.h mach/host_priv.h mach/mach_error.h mach/mach_host.h mach/mach_port.h mach/mach_types.h mach/message.h mach/processor_set.h mach/processor.h mach/processor_info.h mach/task.h mach/thread_act.h mach/vm_region.h mach/vm_map.h mach/vm_prot.h mach/vm_statistics.h mach/kern_return.h) AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h IOKit/IOKitLib.h IOKit/IOTypes.h IOKit/ps/IOPSKeys.h IOKit/IOBSD.h IOKit/storage/IOBlockStorageDriver.h) + # For the battery plugin + AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [], +[ +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif +]) + fi + AC_CHECK_HEADERS(sys/sysctl.h, [], [], [ #if HAVE_SYS_TYPES_H @@ -293,18 +317,22 @@ else fi # For hddtemp module -AC_CHECK_HEADERS(linux/major.h libgen.h) +AC_CHECK_HEADERS(linux/major.h) -# For the battery plugin -AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [], +# For md module (Linux only) +if test "x$ac_system" = "xLinux" +then + AC_CHECK_HEADERS(linux/raid/md_u.h, + [have_linux_raid_md_u_h="yes"], + [have_linux_raid_md_u_h="no"], [ -#if HAVE_IOKIT_IOKITLIB_H -# include -#endif -#if HAVE_IOKIT_IOTYPES_H -# include -#endif +#include +#include +#include ]) +else + have_linux_raid_md_u_h="no" +fi # For the swap module have_linux_wireless_h="no" @@ -371,6 +399,18 @@ AC_CHECK_HEADERS(linux/if.h, [], [], # include #endif ]) +AC_CHECK_HEADERS(linux/inet_diag.h, [], [], +[ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_LINUX_INET_DIAG_H +# include +#endif +]) AC_CHECK_HEADERS(linux/netdevice.h, [], [], [ #if HAVE_SYS_TYPES_H @@ -384,6 +424,33 @@ AC_CHECK_HEADERS(linux/netdevice.h, [], [], #endif ]) +# For ethstat module +AC_CHECK_HEADERS(linux/sockios.h, + [have_linux_sockios_h="yes"], + [have_linux_sockios_h="no"], + [ +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif + ]) +AC_CHECK_HEADERS(linux/ethtool.h, + [have_linux_ethtool_h="yes"], + [have_linux_ethtool_h="no"], + [ +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif +#if HAVE_LINUX_SOCKIOS_H +# include +#endif + ]) + # For ipvs module have_linux_ip_vs_h="no" have_net_ip_vs_h="no" @@ -486,6 +553,24 @@ AC_CHECK_HEADERS(netinet/if_ether.h, [], [], #endif ]) +AC_CHECK_HEADERS(netinet/ip_compat.h) + +have_net_pfvar_h="no" +AC_CHECK_HEADERS(net/pfvar.h, + [have_net_pfvar_h="yes"], + [have_net_pfvar_h="no"], +[ +#if HAVE_SYS_IOCTL_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_NET_IF_H +# include +#endif +]) + # For the multimeter plugin have_termios_h="no" AC_CHECK_HEADERS(termios.h, [have_termios_h="yes"]) @@ -518,12 +603,12 @@ AC_CACHE_CHECK([for strtok_r], [c_cv_have_strtok_r_default], AC_LINK_IFELSE( [AC_LANG_PROGRAM( - [[[ +[[[ #include #include #include - ]]], - [[[ +]]], +[[[ char buffer[] = "foo,bar,baz"; char *token; char *dummy; @@ -536,7 +621,8 @@ AC_CACHE_CHECK([for strtok_r], dummy = NULL; printf ("token = %s;\n", token); } - ]]])], +]]] + )], [c_cv_have_strtok_r_default="yes"], [c_cv_have_strtok_r_default="no"] ) @@ -550,12 +636,12 @@ then [c_cv_have_strtok_r_reentrant], AC_LINK_IFELSE( [AC_LANG_PROGRAM( - [[[ +[[[ #include #include #include - ]]], - [[[ +]]], +[[[ char buffer[] = "foo,bar,baz"; char *token; char *dummy; @@ -568,7 +654,8 @@ then dummy = NULL; printf ("token = %s;\n", token); } - ]]])], +]]] + )], [c_cv_have_strtok_r_reentrant="yes"], [AC_MSG_FAILURE([strtok_r isn't available. Please file a bugreport!])] ) @@ -587,6 +674,27 @@ socket_needs_socket="no" AC_CHECK_FUNCS(socket, [], AC_CHECK_LIB(socket, socket, [socket_needs_socket="yes"], AC_MSG_ERROR(cannot find socket))) AM_CONDITIONAL(BUILD_WITH_LIBSOCKET, test "x$socket_needs_socket" = "xyes") +clock_gettime_needs_rt="no" +clock_gettime_needs_posix4="no" +have_clock_gettime="no" +AC_CHECK_FUNCS(clock_gettime, [have_clock_gettime="yes"]) +if test "x$have_clock_gettime" = "xno" +then + AC_CHECK_LIB(rt, clock_gettime, [clock_gettime_needs_rt="yes" + have_clock_gettime="yes"]) +fi +if test "x$have_clock_gettime" = "xno" +then + AC_CHECK_LIB(posix4, clock_gettime, [clock_gettime_needs_posix4="yes" + have_clock_gettime="yes"]) +fi +if test "x$have_clock_gettime" = "xyes" +then + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define if the clock_gettime(2) function is available.]) +else + AC_MSG_WARN(cannot find clock_gettime) +fi + nanosleep_needs_rt="no" nanosleep_needs_posix4="no" AC_CHECK_FUNCS(nanosleep, @@ -596,8 +704,9 @@ AC_CHECK_FUNCS(nanosleep, AC_CHECK_LIB(posix4, nanosleep, [nanosleep_needs_posix4="yes"], AC_MSG_ERROR(cannot find nanosleep)))) -AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$nanosleep_needs_rt" = "xyes") -AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$nanosleep_needs_posix4" = "xyes") + +AM_CONDITIONAL(BUILD_WITH_LIBRT, test "x$clock_gettime_needs_rt" = "xyes" || test "x$nanosleep_needs_rt" = "xyes") +AM_CONDITIONAL(BUILD_WITH_LIBPOSIX4, test "x$clock_gettime_needs_posix4" = "xyes" || test "x$nanosleep_needs_posix4" = "xyes") AC_CHECK_FUNCS(sysctl, [have_sysctl="yes"], [have_sysctl="no"]) AC_CHECK_FUNCS(sysctlbyname, [have_sysctlbyname="yes"], [have_sysctlbyname="no"]) @@ -607,13 +716,127 @@ AC_CHECK_FUNCS(thread_info, [have_thread_info="yes"], [have_thread_info="no"]) AC_CHECK_FUNCS(statfs, [have_statfs="yes"], [have_statfs="no"]) AC_CHECK_FUNCS(statvfs, [have_statvfs="yes"], [have_statvfs="no"]) AC_CHECK_FUNCS(getifaddrs, [have_getifaddrs="yes"], [have_getifaddrs="no"]) +AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"]) AC_CHECK_FUNCS(syslog, [have_syslog="yes"], [have_syslog="no"]) AC_CHECK_FUNCS(getutent, [have_getutent="yes"], [have_getutent="no"]) AC_CHECK_FUNCS(getutxent, [have_getutxent="yes"], [have_getutxent="no"]) -AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"]) -# For load module -AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"]) +# Check for strptime {{{ +if test "x$GCC" = "xyes" +then + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -Wall -Wextra -Werror" +fi + +AC_CHECK_FUNCS(strptime, [have_strptime="yes"], [have_strptime="no"]) +if test "x$have_strptime" = "xyes" +then + AC_CACHE_CHECK([whether strptime is exported by default], + [c_cv_have_strptime_default], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ +#include +]]], +[[[ + struct tm stm; + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm); +]]] + )], + [c_cv_have_strptime_default="yes"], + [c_cv_have_strptime_default="no"])) +fi +if test "x$have_strptime" = "xyes" && test "x$c_cv_have_strptime_default" = "xno" +then + AC_CACHE_CHECK([whether strptime needs standards mode], + [c_cv_have_strptime_standards], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ +#ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE 1 +#endif +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +#endif +#ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +#endif +#include +]]], +[[[ + struct tm stm; + (void) strptime ("2010-12-30%13:42:42", "%Y-%m-%dT%T", &stm); +]]] + )], + [c_cv_have_strptime_standards="yes"], + [c_cv_have_strptime_standards="no"])) + + if test "x$c_cv_have_strptime_standards" = "xyes" + then + AC_DEFINE([STRPTIME_NEEDS_STANDARDS], 1, [Set to true if strptime is only exported in X/Open mode (GNU libc).]) + else + have_strptime="no" + fi +fi + +if test "x$GCC" = "xyes" +then + CFLAGS="$SAVE_CFLAGS" +fi +# }}} Check for strptime + +AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"]) +if test "x$have_swapctl" = "xyes"; then + AC_CACHE_CHECK([whether swapctl takes two arguments], + [c_cv_have_swapctl_two_args], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64 +# undef _FILE_OFFSET_BITS +# undef _LARGEFILE64_SOURCE +#endif +#include +#include +]]], +[[[ +int num = swapctl(0, NULL); +]]] + )], + [c_cv_have_swapctl_two_args="yes"], + [c_cv_have_swapctl_two_args="no"] + ) + ) + AC_CACHE_CHECK([whether swapctl takes three arguments], + [c_cv_have_swapctl_three_args], + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( +[[[ +#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64 +# undef _FILE_OFFSET_BITS +# undef _LARGEFILE64_SOURCE +#endif +#include +#include +]]], +[[[ +int num = swapctl(0, NULL, 0); +]]] + )], + [c_cv_have_swapctl_three_args="yes"], + [c_cv_have_swapctl_three_args="no"] + ) + ) +fi +# Check for different versions of `swapctl' here.. +if test "x$have_swapctl" = "xyes"; then + if test "x$c_cv_have_swapctl_two_args" = "xyes"; then + AC_DEFINE(HAVE_SWAPCTL_TWO_ARGS, 1, + [Define if the function swapctl exists and takes two arguments.]) + fi + if test "x$c_cv_have_swapctl_three_args" = "xyes"; then + AC_DEFINE(HAVE_SWAPCTL_THREE_ARGS, 1, + [Define if the function swapctl exists and takes three arguments.]) + fi +fi # Check for NAN AC_ARG_WITH(nan-emulation, [AS_HELP_STRING([--with-nan-emulation], [use emulated NAN. For crosscompiling only.])], @@ -630,19 +853,19 @@ AC_ARG_WITH(nan-emulation, [AS_HELP_STRING([--with-nan-emulation], [use emulated if test "x$nan_type" = "xnone"; then AC_CACHE_CHECK([whether NAN is defined by default], [c_cv_have_nan_default], - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include static double foo = NAN; - ]]], - [[[ +]]], +[[[ if (isnan (foo)) return 0; else return 1; - ]]])], +]]] + )], [c_cv_have_nan_default="yes"], [c_cv_have_nan_default="no"] ) @@ -655,20 +878,20 @@ fi if test "x$nan_type" = "xnone"; then AC_CACHE_CHECK([whether NAN is defined by __USE_ISOC99], [c_cv_have_nan_isoc], - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ #include #define __USE_ISOC99 1 #include static double foo = NAN; - ]]], - [[[ +]]], +[[[ if (isnan (foo)) return 0; else return 1; - ]]])], +]]] + )], [c_cv_have_nan_isoc="yes"], [c_cv_have_nan_isoc="no"] ) @@ -683,9 +906,8 @@ if test "x$nan_type" = "xnone"; then LDFLAGS="$LDFLAGS -lm" AC_CACHE_CHECK([whether NAN can be defined by 0/0], [c_cv_have_nan_zero], - AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #ifdef NAN @@ -696,13 +918,14 @@ if test "x$nan_type" = "xnone"; then # define isnan(f) ((f) != (f)) #endif static double foo = NAN; - ]]], - [[[ +]]], +[[[ if (isnan (foo)) return 0; else return 1; - ]]])], +]]] + )], [c_cv_have_nan_zero="yes"], [c_cv_have_nan_zero="no"] ) @@ -744,9 +967,8 @@ fi; fi; fi if test "x$fp_layout_type" = "xunknown"; then AC_CACHE_CHECK([if doubles are stored in x86 representation], [c_cv_fp_layout_need_nothing], - AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #include @@ -759,8 +981,8 @@ if test "x$fp_layout_type" = "xunknown"; then #if HAVE_STDBOOL_H # include #endif - ]]], - [[[ +]]], +[[[ uint64_t i0; uint64_t i1; uint8_t c[8]; @@ -779,7 +1001,8 @@ if test "x$fp_layout_type" = "xunknown"; then return (0); else return (1); - ]]])], +]]] + )], [c_cv_fp_layout_need_nothing="yes"], [c_cv_fp_layout_need_nothing="no"] ) @@ -791,9 +1014,8 @@ fi if test "x$fp_layout_type" = "xunknown"; then AC_CACHE_CHECK([if endianflip converts to x86 representation], [c_cv_fp_layout_need_endianflip], - AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #include @@ -814,8 +1036,8 @@ if test "x$fp_layout_type" = "xunknown"; then (((uint64_t)(A) & 0x0000000000ff0000LL) << 24) | \ (((uint64_t)(A) & 0x000000000000ff00LL) << 40) | \ (((uint64_t)(A) & 0x00000000000000ffLL) << 56)) - ]]], - [[[ +]]], +[[[ uint64_t i0; uint64_t i1; uint8_t c[8]; @@ -834,7 +1056,8 @@ if test "x$fp_layout_type" = "xunknown"; then return (0); else return (1); - ]]])], +]]] + )], [c_cv_fp_layout_need_endianflip="yes"], [c_cv_fp_layout_need_endianflip="no"] ) @@ -846,9 +1069,8 @@ fi if test "x$fp_layout_type" = "xunknown"; then AC_CACHE_CHECK([if intswap converts to x86 representation], [c_cv_fp_layout_need_intswap], - AC_RUN_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_RUN_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #include @@ -863,8 +1085,8 @@ if test "x$fp_layout_type" = "xunknown"; then #endif #define intswap(A) ((((uint64_t)(A) & 0xffffffff00000000LL) >> 32) | \ (((uint64_t)(A) & 0x00000000ffffffffLL) << 32)) - ]]], - [[[ +]]], +[[[ uint64_t i0; uint64_t i1; uint8_t c[8]; @@ -883,7 +1105,8 @@ if test "x$fp_layout_type" = "xunknown"; then return (0); else return (1); - ]]])], +]]] + )], [c_cv_fp_layout_need_intswap="yes"], [c_cv_fp_layout_need_intswap="no"] ) @@ -929,14 +1152,16 @@ if test "x$have_getmntent" = "xc"; then AC_CACHE_CHECK([whether getmntent takes one argument], [c_cv_have_one_getmntent], AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT -#include "$srcdir/src/utils_mount.h"]], - [[[ - FILE *fh; - struct mntent *me; - fh = setmntent ("/etc/mtab", "r"); - me = getmntent (fh); - ]]] + [AC_LANG_PROGRAM( +[[[ +#include "$srcdir/src/utils_mount.h" +]]], +[[[ +FILE *fh; +struct mntent *me; +fh = setmntent ("/etc/mtab", "r"); +me = getmntent (fh); +]]] )], [c_cv_have_one_getmntent="yes"], [c_cv_have_one_getmntent="no"] @@ -945,15 +1170,17 @@ if test "x$have_getmntent" = "xc"; then AC_CACHE_CHECK([whether getmntent takes two arguments], [c_cv_have_two_getmntent], AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT -#include "$srcdir/src/utils_mount.h"]], - [[[ + [AC_LANG_PROGRAM( +[[[ +#include "$srcdir/src/utils_mount.h" +]]], +[[[ FILE *fh; struct mnttab mt; int status; fh = fopen ("/etc/mnttab", "r"); status = getmntent (fh, &mt); - ]]] +]]] )], [c_cv_have_two_getmntent="yes"], [c_cv_have_two_getmntent="no"] @@ -987,25 +1214,28 @@ if test "x$have_getmntent" = "xgen"; then fi # Check for htonll -AC_MSG_CHECKING([if have htonll defined]) - - have_htonll="no" - AC_LINK_IFELSE([ - AC_LANG_PROGRAM([[[ +AC_CACHE_CHECK([if have htonll defined], + [c_cv_have_htonll], + AC_LINK_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #if HAVE_INTTYPES_H # include #endif - ]]], [[[ +]]], +[[[ return htonll(0); - ]]]) - ], [ - have_htonll="yes" - AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.]) - ]) - -AC_MSG_RESULT([$have_htonll]) +]]] + )], + [c_cv_have_htonll="yes"], + [c_cv_have_htonll="no"] + ) +) +if test "x$c_cv_have_htonll" = "xyes" +then + AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.]) +fi # Check for structures AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_opackets, struct if_data.ifi_ierrors], @@ -1025,6 +1255,13 @@ AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_p #include #include ]) +AC_CHECK_MEMBERS([struct inet_diag_req.id, struct inet_diag_req.idiag_states], + [AC_DEFINE(HAVE_STRUCT_LINUX_INET_DIAG_REQ, 1, [Define if struct inet_diag_req exists and is usable.])], + [], + [ + #include + ]) + AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], @@ -1043,7 +1280,6 @@ AC_CHECK_MEMBERS([struct kinfo_proc.ki_pid, struct kinfo_proc.ki_rssize, struct have_struct_kinfo_proc_freebsd="no" ], [ -AC_INCLUDES_DEFAULT #include #include #include @@ -1060,7 +1296,6 @@ AC_CHECK_MEMBERS([struct kinfo_proc.kp_proc, struct kinfo_proc.kp_eproc], have_struct_kinfo_proc_openbsd="no" ], [ -AC_INCLUDES_DEFAULT #include #include #include @@ -1121,6 +1356,7 @@ AC_CHECK_MEMBERS([kstat_io_t.nwritten, kstat_io_t.writes, kstat_io_t.nwrites, ks # # Checks for libraries begin here # + with_libresolv="yes" AC_CHECK_LIB(resolv, res_search, [ @@ -1165,6 +1401,12 @@ fi if test "x$with_perfstat" = "xyes" then AC_DEFINE(HAVE_PERFSTAT, 1, [Define to 1 if you have the 'perfstat' library (-lperfstat)]) + # struct members pertaining to donation have been added to libperfstat somewhere between AIX5.3ML5 and AIX5.3ML9 + AC_CHECK_MEMBER([perfstat_partition_type_t.b.donate_enabled], [], [], [[#include @], [Path to libcredis.])], +[ + if test "x$withval" = "xyes" + then + with_libcredis="yes" + else if test "x$withval" = "xno" + then + with_libcredis="no" + else + with_libcredis="yes" + LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS -I$withval/include" + LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS -L$withval/lib" + fi; fi +], +[with_libcredis="yes"]) + +SAVE_CPPFLAGS="$CPPFLAGS" +SAVE_LDFLAGS="$LDFLAGS" + +CPPFLAGS="$CPPFLAGS $LIBCREDIS_CPPFLAGS" +LDFLAGS="$LDFLAGS $LIBCREDIS_LDFLAGS" + +if test "x$with_libcredis" = "xyes" +then + if test "x$LIBCREDIS_CPPFLAGS" != "x" + then + AC_MSG_NOTICE([libcredis CPPFLAGS: $LIBCREDIS_CPPFLAGS]) + fi + AC_CHECK_HEADERS(credis.h, + [with_libcredis="yes"], + [with_libcredis="no (credis.h not found)"]) +fi +if test "x$with_libcredis" = "xyes" +then + if test "x$LIBCREDIS_LDFLAGS" != "x" + then + AC_MSG_NOTICE([libcredis LDFLAGS: $LIBCREDIS_LDFLAGS]) + fi + AC_CHECK_LIB(credis, credis_info, + [with_libcredis="yes"], + [with_libcredis="no (symbol 'credis_info' not found)"]) + +fi + +CPPFLAGS="$SAVE_CPPFLAGS" +LDFLAGS="$SAVE_LDFLAGS" + +if test "x$with_libcredis" = "xyes" +then + BUILD_WITH_LIBCREDIS_CPPFLAGS="$LIBCREDIS_CPPFLAGS" + BUILD_WITH_LIBCREDIS_LDFLAGS="$LIBCREDIS_LDFLAGS" + AC_SUBST(BUILD_WITH_LIBCREDIS_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBCREDIS_LDFLAGS) +fi +AM_CONDITIONAL(BUILD_WITH_LIBCREDIS, test "x$with_libcredis" = "xyes") +# }}} + # --with-libcurl {{{ with_curl_config="curl-config" with_curl_cflags="" @@ -1563,7 +1862,9 @@ then [with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"]) if test "$with_libgcrypt" != "no"; then - AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)") + m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")]) + GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS" + GCRYPT_LIBS="$LIBGCRYPT_LIBS" fi fi @@ -1727,7 +2028,7 @@ then if test -d "$with_java_home" then AC_MSG_CHECKING([for jni.h]) - TMPVAR=`find "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' | head -n 1` + TMPVAR=`find "$with_java_home" -name jni.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1` if test "x$TMPVAR" != "x" then AC_MSG_RESULT([found in $TMPVAR]) @@ -1737,7 +2038,7 @@ then fi AC_MSG_CHECKING([for jni_md.h]) - TMPVAR=`find "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' | head -n 1` + TMPVAR=`find "$with_java_home" -name jni_md.h -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1` if test "x$TMPVAR" != "x" then AC_MSG_RESULT([found in $TMPVAR]) @@ -1747,7 +2048,7 @@ then fi AC_MSG_CHECKING([for libjvm.so]) - TMPVAR=`find "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' | head -n 1` + TMPVAR=`find "$with_java_home" -name libjvm.so -type f -exec 'dirname' '{}' ';' 2>/dev/null | head -n 1` if test "x$TMPVAR" != "x" then AC_MSG_RESULT([found in $TMPVAR]) @@ -1759,7 +2060,7 @@ then if test "x$JAVAC" = "x" then AC_MSG_CHECKING([for javac]) - TMPVAR=`find "$with_java_home" -name javac -type f | head -n 1` + TMPVAR=`find "$with_java_home" -name javac -type f 2>/dev/null | head -n 1` if test "x$TMPVAR" != "x" then JAVAC="$TMPVAR" @@ -1771,7 +2072,7 @@ then if test "x$JAR" = "x" then AC_MSG_CHECKING([for jar]) - TMPVAR=`find "$with_java_home" -name jar -type f | head -n 1` + TMPVAR=`find "$with_java_home" -name jar -type f 2>/dev/null | head -n 1` if test "x$TMPVAR" != "x" then JAR="$TMPVAR" @@ -1953,21 +2254,21 @@ then 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 + AC_MSG_NOTICE([Checking for libmodbus using $PKG_CONFIG]) + $PKG_CONFIG --exists 'libmodbus' 2>/dev/null if test $? -ne 0 then - with_libmodbus="no (pkg-config doesn't know library)" + with_libmodbus="no (pkg-config doesn't know libmodbus)" fi fi if test "x$with_libmodbus" = "xuse_pkgconfig" then - with_libmodbus_cflags="`$PKG_CONFIG --cflags 'modbus'`" + with_libmodbus_cflags="`$PKG_CONFIG --cflags 'libmodbus'`" if test $? -ne 0 then with_libmodbus="no ($PKG_CONFIG failed)" fi - with_libmodbus_libs="`$PKG_CONFIG --libs 'modbus'`" + with_libmodbus_libs="`$PKG_CONFIG --libs 'libmodbus'`" if test $? -ne 0 then with_libmodbus="no ($PKG_CONFIG failed)" @@ -1997,9 +2298,9 @@ then CPPFLAGS="$CPPFLAGS $with_libmodbus_cflags" LDFLAGS="$LDFLAGS $with_libmodbus_libs" - AC_CHECK_LIB(modbus, modbus_init_tcp, + AC_CHECK_LIB(modbus, modbus_connect, [with_libmodbus="yes"], - [with_libmodbus="no (symbol modbus_init_tcp not found)"]) + [with_libmodbus="no (symbol modbus_connect not found)"]) CPPFLAGS="$SAVE_CPPFLAGS" LDFLAGS="$SAVE_LDFLAGS" @@ -2013,6 +2314,69 @@ then fi # }}} +# --with-libmongoc {{{ +AC_ARG_WITH(libmongoc, [AS_HELP_STRING([--with-libmongoc@<:@=PREFIX@:>@], [Path to libmongoc.])], +[ + if test "x$withval" = "xyes" + then + with_libmongoc="yes" + else if test "x$withval" = "xno" + then + with_libmongoc="no" + else + with_libmongoc="yes" + LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include" + LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib" + fi; fi +], +[with_libmongoc="yes"]) + +SAVE_CPPFLAGS="$CPPFLAGS" +SAVE_LDFLAGS="$LDFLAGS" + +CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS" +LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS" + +if test "x$with_libmongoc" = "xyes" +then + if test "x$LIBMONGOC_CPPFLAGS" != "x" + then + AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS]) + fi + AC_CHECK_HEADERS(mongo.h, + [with_libmongoc="yes"], + [with_libmongoc="no ('mongo.h' not found)"], +[#if HAVE_STDINT_H +# define MONGO_HAVE_STDINT 1 +#else +# define MONGO_USE_LONG_LONG_INT 1 +#endif +]) +fi +if test "x$with_libmongoc" = "xyes" +then + if test "x$LIBMONGOC_LDFLAGS" != "x" + then + AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS]) + fi + AC_CHECK_LIB(mongoc, mongo_run_command, + [with_libmongoc="yes"], + [with_libmongoc="no (symbol 'mongo_run_command' not found)"]) +fi + +CPPFLAGS="$SAVE_CPPFLAGS" +LDFLAGS="$SAVE_LDFLAGS" + +if test "x$with_libmongoc" = "xyes" +then + BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS" + BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS" + AC_SUBST(BUILD_WITH_LIBMONGOC_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBMONGOC_LDFLAGS) +fi +AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes") +# }}} + # --with-libmysql {{{ with_mysql_config="mysql_config" with_mysql_cflags="" @@ -2154,35 +2518,36 @@ then #include ]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( - [[[ - #include - #include - #include - #include - #include - #include - ]]], [[[ - int retval = TCA_STATS2; - return (retval); - ]]] - )], - [AC_DEFINE([HAVE_TCA_STATS2], [1], [True if the enum-member TCA_STATS2 exists])]) +[[[ +#include +#include +#include +#include +#include +#include +]]], +[[[ +int retval = TCA_STATS2; +return (retval); +]]] + )], + [AC_DEFINE([HAVE_TCA_STATS2], [1], [True if the enum-member TCA_STATS2 exists])]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM( -[[[#include +[[[ +#include #include #include #include #include #include -]]], [[[ -int main (void) -{ - int retval = TCA_STATS; - return (retval); -}]]])], - [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])] - []); +]]], +[[[ +int retval = TCA_STATS; +return (retval); +]]] + )], + [AC_DEFINE([HAVE_TCA_STATS], 1, [True if the enum-member TCA_STATS exists])]) CFLAGS="$SAVE_CFLAGS" fi @@ -2201,8 +2566,10 @@ then AC_CACHE_CHECK( [if function 'rtnl_dump_filter' expects five arguments], [c_cv_rtnl_dump_filter_five_args], - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -AC_INCLUDES_DEFAULT + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ +#include +#include #include #include #if HAVE_LIBNETLINK_H @@ -2212,23 +2579,25 @@ AC_INCLUDES_DEFAULT #elif HAVE_LINUX_LIBNETLINK_H # include #endif - ]], [[[ +]]], +[[[ if (rtnl_dump_filter(NULL, NULL, NULL, NULL, NULL)) return 1; return 0; - ]]] - )], - [c_cv_rtnl_dump_filter_five_args="yes"], - [c_cv_rtnl_dump_filter_five_args="no"] - ) +]]] + )], + [c_cv_rtnl_dump_filter_five_args="yes"], + [c_cv_rtnl_dump_filter_five_args="no"] ) +) AC_CACHE_CHECK( [if function 'rtnl_dump_filter' expects three arguments], [c_cv_rtnl_dump_filter_three_args], AC_COMPILE_IFELSE([AC_LANG_PROGRAM( - [[ -AC_INCLUDES_DEFAULT +[[[ +#include +#include #include #include #if HAVE_LIBNETLINK_H @@ -2238,16 +2607,17 @@ AC_INCLUDES_DEFAULT #elif HAVE_LINUX_LIBNETLINK_H # include #endif - ]], [[[ +]]], +[[[ if (rtnl_dump_filter(NULL, NULL, NULL)) return 1; return 0; - ]]] - )], - [c_cv_rtnl_dump_filter_three_args="yes"], - [c_cv_rtnl_dump_filter_three_args="no"] - ) +]]] + )], + [c_cv_rtnl_dump_filter_three_args="yes"], + [c_cv_rtnl_dump_filter_three_args="no"] ) +) CFLAGS="$SAVE_CFLAGS" @@ -2488,7 +2858,7 @@ then fi AC_CHECK_HEADERS(oping.h, [with_liboping="yes"], - [with_liboping="no ('oping.h' not found)"]) + [with_liboping="no (oping.h not found)"]) fi if test "x$with_liboping" = "xyes" then @@ -2565,14 +2935,14 @@ fi if test "x$with_oracle" = "xyes" then SAVE_CPPFLAGS="$CPPFLAGS" - SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $with_oracle_cppflags" - LDFLAGS="$LDFLAGS $with_oracle_libs" + LIBS="$LIBS $with_oracle_libs" AC_CHECK_FUNC(OCIEnvCreate, [with_oracle="yes"], [with_oracle="no (Symbol 'OCIEnvCreate' not found)"]) CPPFLAGS="$SAVE_CPPFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" fi if test "x$with_oracle" = "xyes" then @@ -2659,7 +3029,27 @@ then fi if test "x$with_libpcap" = "xyes" then - AC_CHECK_HEADERS(pcap-bpf.h) + AC_CHECK_HEADERS(pcap-bpf.h,, + [with_libpcap="no (pcap-bpf.h not found)"]) +fi +if test "x$with_libpcap" = "xyes" +then + AC_CACHE_CHECK([whether libpcap has PCAP_ERROR_IFACE_NOT_UP], + [c_cv_libpcap_have_pcap_error_iface_not_up], + AC_COMPILE_IFELSE([AC_LANG_PROGRAM( +[[[ +#include +]]], +[[[ + int val = PCAP_ERROR_IFACE_NOT_UP; +]]] + )], + [c_cv_libpcap_have_pcap_error_iface_not_up="yes"], + [c_cv_libpcap_have_pcap_error_iface_not_up="no"])) +fi +if test "x$c_cv_libpcap_have_pcap_error_iface_not_up" != "xyes" +then + with_libpcap="no (pcap.h misses PCAP_ERROR_IFACE_NOT_UP)" fi AM_CONDITIONAL(BUILD_WITH_LIBPCAP, test "x$with_libpcap" = "xyes") # }}} @@ -2702,29 +3092,29 @@ if test "x$with_libperl" = "xyes" \ && test -n "$perl_interpreter" then SAVE_CFLAGS="$CFLAGS" - SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string) PERL_CFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ccopts` - PERL_LDFLAGS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts` + PERL_LIBS=`ARCHFLAGS="" $perl_interpreter -MExtUtils::Embed -e ldopts` CFLAGS="$CFLAGS $PERL_CFLAGS" - LDFLAGS="$LDFLAGS $PERL_LDFLAGS" + LIBS="$LIBS $PERL_LIBS" AC_CACHE_CHECK([for libperl], [c_cv_have_libperl], - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_LINK_IFELSE([AC_LANG_PROGRAM( +[[[ #define PERL_NO_GET_CONTEXT #include #include #include - ]]], - [[[ +]]], +[[[ dTHX; load_module (PERL_LOADMOD_NOIMPORT, newSVpv ("Collectd::Plugin::FooBar", 24), Nullsv); - ]]])], +]]] + )], [c_cv_have_libperl="yes"], [c_cv_have_libperl="no"] ) @@ -2734,13 +3124,13 @@ dnl ARCHFLAGS="" -> disable multi -arch on OSX (see Config_heavy.pl:fetch_string then AC_DEFINE(HAVE_LIBPERL, 1, [Define if libperl is present and usable.]) AC_SUBST(PERL_CFLAGS) - AC_SUBST(PERL_LDFLAGS) + AC_SUBST(PERL_LIBS) else with_libperl="no" fi CFLAGS="$SAVE_CFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" else if test -z "$perl_interpreter"; then with_libperl="no (no perl interpreter found)" c_cv_have_libperl="no" @@ -2750,15 +3140,14 @@ AM_CONDITIONAL(BUILD_WITH_LIBPERL, test "x$with_libperl" = "xyes") if test "x$with_libperl" = "xyes" then SAVE_CFLAGS="$CFLAGS" - SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" CFLAGS="$CFLAGS $PERL_CFLAGS" - LDFLAGS="$LDFLAGS $PERL_LDFLAGS" + LIBS="$LIBS $PERL_LIBS" AC_CACHE_CHECK([if perl supports ithreads], [c_cv_have_perl_ithreads], - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_LINK_IFELSE([AC_LANG_PROGRAM( +[[[ #include #include #include @@ -2766,8 +3155,9 @@ then #if !defined(USE_ITHREADS) # error "Perl does not support ithreads!" #endif /* !defined(USE_ITHREADS) */ - ]]], - [[[ ]]])], +]]], +[[[ ]]] + )], [c_cv_have_perl_ithreads="yes"], [c_cv_have_perl_ithreads="no"] ) @@ -2779,41 +3169,41 @@ then fi CFLAGS="$SAVE_CFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" fi if test "x$with_libperl" = "xyes" then SAVE_CFLAGS="$CFLAGS" - SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" # trigger an error if Perl_load_module*() uses __attribute__nonnull__(3) # (see issues #41 and #42) CFLAGS="$CFLAGS $PERL_CFLAGS -Wall -Werror" - LDFLAGS="$LDFLAGS $PERL_LDFLAGS" + LIBS="$LIBS $PERL_LIBS" AC_CACHE_CHECK([for broken Perl_load_module()], [c_cv_have_broken_perl_load_module], - AC_LINK_IFELSE( - [AC_LANG_PROGRAM( - [[[ + AC_LINK_IFELSE([AC_LANG_PROGRAM( +[[[ #define PERL_NO_GET_CONTEXT #include #include #include - ]]], - [[[ +]]], +[[[ dTHX; load_module (PERL_LOADMOD_NOIMPORT, newSVpv ("Collectd::Plugin::FooBar", 24), Nullsv); - ]]])], +]]] + )], [c_cv_have_broken_perl_load_module="no"], [c_cv_have_broken_perl_load_module="yes"] ) ) CFLAGS="$SAVE_CFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" fi AM_CONDITIONAL(HAVE_BROKEN_PERL_LOAD_MODULE, test "x$c_cv_have_broken_perl_load_module" = "xyes") @@ -2821,9 +3211,9 @@ AM_CONDITIONAL(HAVE_BROKEN_PERL_LOAD_MODULE, if test "x$with_libperl" = "xyes" then SAVE_CFLAGS="$CFLAGS" - SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" CFLAGS="$CFLAGS $PERL_CFLAGS" - LDFLAGS="$LDFLAGS $PERL_LDFLAGS" + LIBS="$LIBS $PERL_LIBS" AC_CHECK_MEMBER( [struct mgvtbl.svt_local], @@ -2842,7 +3232,7 @@ then fi CFLAGS="$SAVE_CFLAGS" - LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" fi # }}} @@ -3094,6 +3484,107 @@ then fi # }}} --with-python +# --with-librabbitmq {{{ +with_librabbitmq_cppflags="" +with_librabbitmq_ldflags="" +AC_ARG_WITH(librabbitmq, [AS_HELP_STRING([--with-librabbitmq@<:@=PREFIX@:>@], [Path to librabbitmq.])], +[ + if test "x$withval" != "xno" && test "x$withval" != "xyes" + then + with_librabbitmq_cppflags="-I$withval/include" + with_librabbitmq_ldflags="-L$withval/lib" + with_librabbitmq="yes" + else + with_librabbitmq="$withval" + fi +], +[ + with_librabbitmq="yes" +]) +SAVE_CPPFLAGS="$CPPFLAGS" +SAVE_LDFLAGS="$LDFLAGS" +CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags" +LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags" +if test "x$with_librabbitmq" = "xyes" +then + AC_CHECK_HEADERS(amqp.h, [with_librabbitmq="yes"], [with_librabbitmq="no (amqp.h not found)"]) +fi +if test "x$with_librabbitmq" = "xyes" +then + # librabbitmq up to version 0.9.1 provides "library_errno", later + # versions use "library_error". The library does not provide a version + # macro :( Use "AC_CHECK_MEMBERS" (plural) for automatic defines. + AC_CHECK_MEMBERS([amqp_rpc_reply_t.library_errno],,, + [ +#if HAVE_STDLIB_H +# include +#endif +#if HAVE_STDIO_H +# include +#endif +#if HAVE_STDINT_H +# include +#endif +#if HAVE_INTTYPES_H +# include +#endif +#include + ]) +fi +if test "x$with_librabbitmq" = "xyes" +then + AC_CHECK_LIB(rabbitmq, amqp_basic_publish, [with_librabbitmq="yes"], [with_librabbitmq="no (Symbol 'amqp_basic_publish' not found)"]) +fi +if test "x$with_librabbitmq" = "xyes" +then + BUILD_WITH_LIBRABBITMQ_CPPFLAGS="$with_librabbitmq_cppflags" + BUILD_WITH_LIBRABBITMQ_LDFLAGS="$with_librabbitmq_ldflags" + BUILD_WITH_LIBRABBITMQ_LIBS="-lrabbitmq" + AC_SUBST(BUILD_WITH_LIBRABBITMQ_CPPFLAGS) + AC_SUBST(BUILD_WITH_LIBRABBITMQ_LDFLAGS) + AC_SUBST(BUILD_WITH_LIBRABBITMQ_LIBS) + AC_DEFINE(HAVE_LIBRABBITMQ, 1, [Define if librabbitmq is present and usable.]) +fi +CPPFLAGS="$SAVE_CPPFLAGS" +LDFLAGS="$SAVE_LDFLAGS" +AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes") + +with_amqp_tcp_socket="no" +if test "x$with_librabbitmq" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags" + LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags" + LIBS="-lrabbitmq" + + AC_CHECK_HEADERS(amqp_tcp_socket.h amqp_socket.h) + AC_CHECK_FUNC(amqp_tcp_socket_new, [with_amqp_tcp_socket="yes"], [with_amqp_tcp_socket="no"]) + if test "x$with_amqp_tcp_socket" = "xyes" + then + AC_DEFINE(HAVE_AMQP_TCP_SOCKET, 1, + [Define if librabbitmq provides the new TCP socket interface.]) + fi + + AC_CHECK_DECLS(amqp_socket_close, + [amqp_socket_close_decl="yes"], [amqp_socket_close_decl="no"], + [[ +#include +#ifdef HAVE_AMQP_TCP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_SOCKET_H +# include +#endif + ]]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" +fi +# }}} + # --with-librouteros {{{ AC_ARG_WITH(librouteros, [AS_HELP_STRING([--with-librouteros@<:@=PREFIX@:>@], [Path to librouteros.])], [ @@ -3125,7 +3616,7 @@ then fi AC_CHECK_HEADERS(routeros_api.h, [with_librouteros="yes"], - [with_librouteros="no ('routeros_api.h' not found)"]) + [with_librouteros="no (routeros_api.h not found)"]) fi if test "x$with_librouteros" = "xyes" then @@ -3324,7 +3815,7 @@ then if test "$?" != "0" then with_libstatgrab_pkg_config="no" - with_libstatgrab="no ($PKG_CONFIG doesn't know libstatgrab)" + with_libstatgrab="no (pkg-config doesn't know libstatgrab)" temp_result="not found" fi AC_MSG_RESULT([$temp_result]) @@ -3544,7 +4035,7 @@ then $PKG_CONFIG --exists 'libupsclient' 2>/dev/null if test $? -ne 0 then - with_libupsclient="no (pkg-config doesn't know library)" + with_libupsclient="no (pkg-config doesn't know libupsclient)" fi fi if test "x$with_libupsclient" = "xuse_pkgconfig" @@ -3734,6 +4225,97 @@ fi AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes") # }}} +# --with-libvarnish {{{ +with_libvarnish_cppflags="" +with_libvarnish_cflags="" +with_libvarnish_libs="" +AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Path to libvarnish.])], +[ + if test "x$withval" = "xno" + then + with_libvarnish="no" + else if test "x$withval" = "xyes" + then + with_libvarnish="use_pkgconfig" + else if test -d "$with_libvarnish/lib" + then + AC_MSG_NOTICE([Not checking for libvarnish: Manually configured]) + with_libvarnish_cflags="-I$withval/include" + with_libvarnish_libs="-L$withval/lib -lvarnishapi" + with_libvarnish="yes" + fi; fi; fi +], +[with_libvarnish="use_pkgconfig"]) + +# configure using pkg-config +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + if test "x$PKG_CONFIG" = "x" + then + with_libvarnish="no (Don't have pkg-config)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG]) + $PKG_CONFIG --exists 'varnishapi' 2>/dev/null + if test $? -ne 0 + then + with_libvarnish="no (pkg-config doesn't know varnishapi)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`" + if test $? -ne 0 + then + with_libvarnish="no ($PKG_CONFIG failed)" + fi + with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`" + if test $? -ne 0 + then + with_libvarnish="no ($PKG_CONFIG failed)" + fi +fi +if test "x$with_libvarnish" = "xuse_pkgconfig" +then + with_libvarnish="yes" +fi + +# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do +# the actual checks. +if test "x$with_libvarnish" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags" + AC_CHECK_HEADERS(varnish/varnishapi.h, [], [with_libvarnish="no (varnish/varnishapi.h not found)"]) + + CPPFLAGS="$SAVE_CPPFLAGS" +fi +if test "x$with_libvarnish" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + #SAVE_LDFLAGS="$LDFLAGS" + + CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags" + #LDFLAGS="$LDFLAGS $with_libvarnish_libs" + + AC_CHECK_HEADERS(varnish/vsc.h, + [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])], + [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])]) + + CPPFLAGS="$SAVE_CPPFLAGS" + #LDFLAGS="$SAVE_LDFLAGS" +fi +if test "x$with_libvarnish" = "xyes" +then + BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags" + BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs" + AC_SUBST(BUILD_WITH_LIBVARNISH_CFLAGS) + AC_SUBST(BUILD_WITH_LIBVARNISH_LIBS) +fi +# }}} + # pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{ with_libxml2="no (pkg-config isn't available)" with_libxml2_cflags="" @@ -3748,7 +4330,7 @@ then then with_libxml2="yes" else - with_libxml2="no (pkg-config doesn't know library)" + with_libxml2="no (pkg-config doesn't know libxml-2.0)" fi $PKG_CONFIG --exists libvirt 2>/dev/null @@ -3756,7 +4338,7 @@ then then with_libvirt="yes" else - with_libvirt="no (pkg-config doesn't know library)" + with_libvirt="no (pkg-config doesn't know libvirt)" fi fi if test "x$with_libxml2" = "xyes" @@ -3873,7 +4455,7 @@ then $PKG_CONFIG --exists OpenIPMIpthread 2>/dev/null if test "$?" != "0" then - with_libopenipmipthread="no ($PKG_CONFIG doesn't know OpenIPMIpthread)" + with_libopenipmipthread="no (pkg-config doesn't know OpenIPMIpthread)" fi AC_MSG_RESULT([$with_libopenipmipthread]) fi @@ -3934,7 +4516,11 @@ fi PKG_CHECK_MODULES([LIBNOTIFY], [libnotify], [with_libnotify="yes"], - [with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)"]) + [if test "x$LIBNOTIFY_PKG_ERRORS" = "x"; then + with_libnotify="no" + else + with_libnotify="no ($LIBNOTIFY_PKG_ERRORS)" + fi]) # Check for enabled/disabled features # @@ -4074,6 +4660,8 @@ plugin_curl_xml="no" plugin_df="no" plugin_disk="no" plugin_entropy="no" +plugin_ethstat="no" +plugin_fscache="no" plugin_interface="no" plugin_ipmi="no" plugin_ipvs="no" @@ -4083,7 +4671,7 @@ plugin_load="no" plugin_memory="no" plugin_multimeter="no" plugin_nfs="no" -plugin_fscache="no" +plugin_numa="no" plugin_perl="no" plugin_processes="no" plugin_protocols="no" @@ -4110,12 +4698,13 @@ then plugin_cpufreq="yes" plugin_disk="yes" plugin_entropy="yes" + plugin_fscache="yes" plugin_interface="yes" plugin_irq="yes" plugin_load="yes" plugin_memory="yes" plugin_nfs="yes" - plugin_fscache="yes" + plugin_numa="yes" plugin_processes="yes" plugin_protocols="yes" plugin_serial="yes" @@ -4146,14 +4735,22 @@ then fi # AIX + +if test "x$ac_system" = "xAIX" +then + plugin_tcpconns="yes" +fi + if test "x$with_perfstat" = "xyes" then plugin_cpu="yes" + plugin_contextswitch="yes" plugin_disk="yes" plugin_memory="yes" plugin_swap="yes" plugin_interface="yes" plugin_load="yes" + plugin_uptime="yes" fi if test "x$with_procinfo" = "xyes" @@ -4164,6 +4761,7 @@ fi # Solaris if test "x$with_kstat" = "xyes" then + plugin_nfs="yes" plugin_uptime="yes" plugin_zfs_arc="yes" fi @@ -4177,11 +4775,6 @@ then plugin_tape="yes" fi -if test "x$have_sys_swap_h$with_kstat$ac_system" = "xyesyesSolaris" -then - plugin_swap="yes" -fi - # libstatgrab if test "x$with_libstatgrab" = "xyes" then @@ -4197,7 +4790,10 @@ fi if test "x$with_libcurl" = "xyes" && test "x$with_libxml2" = "xyes" then plugin_ascent="yes" - plugin_bind="yes" + if test "x$have_strptime" = "xyes" + then + plugin_bind="yes" + fi fi if test "x$with_libopenipmipthread" = "xyes" @@ -4223,11 +4819,15 @@ if test "x$have_sysctl" = "xyes" then plugin_cpu="yes" plugin_memory="yes" - plugin_swap="yes" plugin_uptime="yes" + if test "x$ac_system" = "xDarwin" + then + plugin_swap="yes" + fi fi if test "x$have_sysctlbyname" = "xyes" then + plugin_contextswitch="yes" plugin_cpu="yes" plugin_memory="yes" plugin_tcpconns="yes" @@ -4268,6 +4868,11 @@ then fi fi +if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes" +then + plugin_ethstat="yes" +fi + if test "x$have_getifaddrs" = "xyes" then plugin_interface="yes" @@ -4315,7 +4920,7 @@ then plugin_swap="yes" fi -if test "x$have_swapctl" = "xyes" +if test "x$have_swapctl" = "xyes" && test "x$c_cv_have_swapctl_two_args" = "xyes" then plugin_swap="yes" fi @@ -4355,6 +4960,8 @@ AC_ARG_ENABLE([all-plugins], m4_divert_once([HELP_ENABLE], []) +AC_PLUGIN([aggregation], [yes], [Aggregation plugin]) +AC_PLUGIN([amqp], [$with_librabbitmq], [AMQP output plugin]) AC_PLUGIN([apache], [$with_libcurl], [Apache httpd statistics]) AC_PLUGIN([apcups], [yes], [Statistics of UPSes by APC]) AC_PLUGIN([apple_sensors], [$with_libiokit], [Apple's hardware sensors]) @@ -4375,6 +4982,7 @@ AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics]) AC_PLUGIN([dns], [$with_libpcap], [DNS traffic analysis]) AC_PLUGIN([email], [yes], [EMail statistics]) AC_PLUGIN([entropy], [$plugin_entropy], [Entropy statistics]) +AC_PLUGIN([ethstat], [$plugin_ethstat], [Stats from NIC driver]) AC_PLUGIN([exec], [yes], [Execution of external programs]) AC_PLUGIN([filecount], [yes], [Count files in directories]) AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics]) @@ -4389,6 +4997,7 @@ AC_PLUGIN([java], [$with_java], [Embed the Java Virtual Machine]) AC_PLUGIN([libvirt], [$plugin_libvirt], [Virtual machine statistics]) AC_PLUGIN([load], [$plugin_load], [System load]) AC_PLUGIN([logfile], [yes], [File logging plugin]) +AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics]) AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics]) AC_PLUGIN([match_empty_counter], [yes], [The empty counter match]) AC_PLUGIN([match_hashed], [yes], [The hashed match]) @@ -4396,6 +5005,7 @@ 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([mbmon], [yes], [Query mbmond]) +AC_PLUGIN([md], [$have_linux_raid_md_u_h], [md (Linux software RAID) devices]) AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics]) AC_PLUGIN([memcached], [yes], [memcached statistics]) AC_PLUGIN([memory], [$plugin_memory], [Memory usage]) @@ -4410,12 +5020,14 @@ AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics]) AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications]) AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier]) AC_PLUGIN([ntpd], [yes], [NTPd statistics]) +AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory 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([perl], [$plugin_perl], [Embed a Perl interpreter]) +AC_PLUGIN([pf], [$have_net_pfvar_h], [BSD packet filter (PF) statistics]) # FIXME: Check for libevent, too. AC_PLUGIN([pinba], [$have_protoc_c], [Pinba statistics]) AC_PLUGIN([ping], [$with_liboping], [Network latency statistics]) @@ -4424,6 +5036,7 @@ AC_PLUGIN([powerdns], [yes], [PowerDNS statistics]) AC_PLUGIN([processes], [$plugin_processes], [Process statistics]) AC_PLUGIN([protocols], [$plugin_protocols], [Protocol (IP, TCP, ...) statistics]) AC_PLUGIN([python], [$with_python], [Embed a Python interpreter]) +AC_PLUGIN([redis], [$with_libcredis], [Redis plugin]) AC_PLUGIN([routeros], [$with_librouteros], [RouterOS plugin]) AC_PLUGIN([rrdcached], [$librrd_rrdc_update], [RRDTool output plugin]) AC_PLUGIN([rrdtool], [$with_librrd], [RRDTool output plugin]) @@ -4434,24 +5047,32 @@ AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics]) AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin]) AC_PLUGIN([table], [yes], [Parsing of tabular data]) AC_PLUGIN([tail], [yes], [Parsing of logfiles]) +AC_PLUGIN([tail_csv], [yes], [Parsing of CSV files]) AC_PLUGIN([tape], [$plugin_tape], [Tape drive statistics]) AC_PLUGIN([target_notification], [yes], [The notification target]) AC_PLUGIN([target_replace], [yes], [The replace target]) AC_PLUGIN([target_scale],[yes], [The scale target]) AC_PLUGIN([target_set], [yes], [The set target]) +AC_PLUGIN([target_v5upgrade], [yes], [The v5upgrade target]) AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics]) 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([threshold], [yes], [Threshold checking plugin]) 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([uuid], [yes], [UUID as hostname plugin]) +AC_PLUGIN([varnish], [$with_libvarnish], [Varnish cache statistics]) AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics]) AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics]) AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics]) +AC_PLUGIN([write_graphite], [yes], [Graphite / Carbon output plugin]) AC_PLUGIN([write_http], [$with_libcurl], [HTTP output plugin]) +AC_PLUGIN([write_mongodb], [$with_libmongoc], [MongoDB output plugin]) +AC_PLUGIN([write_redis], [$with_libcredis], [Redis output plugin]) +AC_PLUGIN([write_riemann], [$have_protoc_c], [Riemann output plugin]) AC_PLUGIN([xmms], [$with_libxmms], [XMMS statistics]) AC_PLUGIN([zfs_arc], [$plugin_zfs_arc], [ZFS ARC statistics]) @@ -4548,6 +5169,7 @@ then fi dnl Perl bindings +PERL_BINDINGS_OPTIONS="PREFIX=${prefix}" AC_ARG_WITH(perl-bindings, [AS_HELP_STRING([--with-perl-bindings@<:@=OPTIONS@:>@], [Options passed to "perl Makefile.PL".])], [ if test "x$withval" != "xno" && test "x$withval" != "xyes" @@ -4555,12 +5177,10 @@ AC_ARG_WITH(perl-bindings, [AS_HELP_STRING([--with-perl-bindings@<:@=OPTIONS@:>@ PERL_BINDINGS_OPTIONS="$withval" with_perl_bindings="yes" else - PERL_BINDINGS_OPTIONS="" with_perl_bindings="$withval" fi ], [ - PERL_BINDINGS_OPTIONS="" if test -n "$perl_interpreter" then with_perl_bindings="yes" @@ -4592,9 +5212,9 @@ AC_SUBST(LCC_VERSION_PATCH) AC_SUBST(LCC_VERSION_EXTRA) AC_SUBST(LCC_VERSION_STRING) -AC_CONFIG_FILES(src/libcollectdclient/lcc_features.h) +AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h) -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) +AC_OUTPUT(Makefile src/Makefile src/collectd.conf 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" @@ -4624,11 +5244,13 @@ cat < # -# Distributed under terms of the GPLv2 license. +# Distributed under terms of the GPLv2 license or newer. +# +# Frank Marien (frank@apsu.be) 6 Sep 2012 +# - quick fixes for 5.1 binary protocol +# - updated to python 3 +# - fixed for larger packet sizes (possible on lo interface) +# - fixed comment typo (decode_network_string decodes a string) """ Collectd network protocol implementation. """ -import socket -import struct - +import socket,struct,sys try: - from cStringIO import StringIO + from io import StringIO except ImportError: - from StringIO import StringIO + from cStringIO import StringIO from datetime import datetime from copy import deepcopy @@ -31,17 +35,19 @@ DEFAULT_IPv4_GROUP = "239.192.74.66" DEFAULT_IPv6_GROUP = "ff18::efc0:4a42" """Default IPv6 multicast group""" - +HR_TIME_DIV = (2.0**30) # Message kinds TYPE_HOST = 0x0000 TYPE_TIME = 0x0001 +TYPE_TIME_HR = 0x0008 TYPE_PLUGIN = 0x0002 TYPE_PLUGIN_INSTANCE = 0x0003 TYPE_TYPE = 0x0004 TYPE_TYPE_INSTANCE = 0x0005 TYPE_VALUES = 0x0006 TYPE_INTERVAL = 0x0007 +TYPE_INTERVAL_HR = 0x0009 # For notifications TYPE_MESSAGE = 0x0100 @@ -50,14 +56,14 @@ TYPE_SEVERITY = 0x0101 # DS kinds DS_TYPE_COUNTER = 0 DS_TYPE_GAUGE = 1 - +DS_TYPE_DERIVE = 2 +DS_TYPE_ABSOLUTE = 3 header = struct.Struct("!2H") number = struct.Struct("!Q") short = struct.Struct("!H") double = struct.Struct(" + use strict; use warnings; -use lib ('../lib'); use utf8; +use vars (qw($BASE_DIR)); + +BEGIN +{ + if (defined $ENV{'SCRIPT_FILENAME'}) + { + if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$}) + { + $::BASE_DIR = $1; + unshift (@::INC, "$::BASE_DIR/lib"); + } + } +} -use FindBin ('$RealBin'); use Carp (qw(confess cluck)); use CGI (':cgi'); use RRDs (); +use File::Temp (':POSIX'); use Collectd::Graph::Config (qw(gc_read_config gc_get_scalar)); use Collectd::Graph::TypeLoader (qw(tl_load_type)); @@ -17,200 +48,287 @@ use Collectd::Graph::Common (qw(sanitize_type get_selected_files epoch_to_rfc1123 flush_files)); use Collectd::Graph::Type (); -our $Debug = param ('debug'); -our $Begin = param ('begin'); -our $End = param ('end'); -our $GraphWidth = param ('width'); -our $GraphHeight = param ('height'); -our $Index = param ('index') || 0; -our $OutputFormat = 'PNG'; -our $ContentType = 'image/png'; - -if (param ('format')) +sub base_dir { - my $temp = param ('format') || ''; - $temp = uc ($temp); + if (defined $::BASE_DIR) + { + return ($::BASE_DIR); + } - if ($temp =~ m/^(PNG|SVG|EPS|PDF)$/) + if (!defined ($ENV{'SCRIPT_FILENAME'})) { - $OutputFormat = $temp; + return; + } - if ($OutputFormat eq 'SVG') { $ContentType = 'image/svg+xml'; } - elsif ($OutputFormat eq 'EPS') { $ContentType = 'image/eps'; } - elsif ($OutputFormat eq 'PDF') { $ContentType = 'application/pdf'; } + if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$}) + { + $::BASE_DIR = $1; + return ($::BASE_DIR); } + + return; } -if ($Debug) +sub lib_dir { - print < 0) && ($Begin > $End)) + if ($GraphHeight) { - my $temp = $End; - $End = $Begin; - $Begin = $temp; + $GraphHeight =~ s/\D//g; } -} -my $type = param ('type') or die; -my $obj; + if (!$GraphHeight) + { + $GraphHeight = gc_get_scalar ('GraphHeight', 100); + } -$obj = tl_load_type ($type); -if (!$obj) -{ - confess ("tl_load_type ($type) failed"); -} + { # Sanitize begin and end times + $End ||= 0; + $Begin ||= 0; -$type = ucfirst (lc ($type)); -$type =~ s/_([A-Za-z])/\U$1\E/g; -$type = sanitize_type ($type); + if ($End =~ m/\D/) + { + $End = 0; + } -my $files = get_selected_files (); -if ($Debug) -{ - require Data::Dumper; - print STDOUT Data::Dumper->Dump ([$files], ['files']); -} -for (@$files) -{ - $obj->addFiles ($_); -} + if (!$Begin || !($Begin =~ m/^-?([1-9][0-9]*)$/)) + { + $Begin = -86400; + } -my $expires = time (); -# IF (End is `now') -# OR (Begin is before `now' AND End is after `now') -if (($End == 0) || (($Begin <= $expires) && ($End >= $expires))) -{ - # 400 == width in pixels - my $timespan; + if ($Begin < 0) + { + if ($End) + { + $Begin = $End + $Begin; + } + else + { + $Begin = time () + $Begin; + } + } + + if ($Begin < 0) + { + $Begin = time () - 86400; + } + + if (($End > 0) && ($Begin > $End)) + { + my $temp = $End; + $End = $Begin; + $Begin = $temp; + } + } - if ($End == 0) + my $type = param ('type') or die; + my $obj; + + $obj = tl_load_type ($type); + if (!$obj) { - $timespan = $expires - $Begin; + confess ("tl_load_type ($type) failed"); } - else + + $type = ucfirst (lc ($type)); + $type =~ s/_([A-Za-z])/\U$1\E/g; + $type = sanitize_type ($type); + + my $files = get_selected_files (); + if (param ('debug')) { - $timespan = $End - $Begin; + require Data::Dumper; + print Data::Dumper->Dump ([$files], ['files']); + } + for (@$files) + { + $obj->addFiles ($_); + } + + my $expires = time (); +# IF (End is `now') +# OR (Begin is before `now' AND End is after `now') + if (($End == 0) || (($Begin <= $expires) && ($End >= $expires))) + { + # 400 == width in pixels + my $timespan; + + if ($End == 0) + { + $timespan = $expires - $Begin; + } + else + { + $timespan = $End - $Begin; + } + $expires += int ($timespan / 400.0); } - $expires += int ($timespan / 400.0); -} # IF (End is not `now') # AND (End is before `now') # ==> Graph will never change again! -elsif (($End > 0) && ($End < $expires)) -{ - $expires += (366 * 86400); -} -elsif ($Begin > $expires) -{ - $expires = $Begin; -} + elsif (($End > 0) && ($End < $expires)) + { + $expires += (366 * 86400); + } + elsif ($Begin > $expires) + { + $expires = $Begin; + } # Send FLUSH command to the daemon if necessary and possible. -flush_files ($files, + flush_files ($files, begin => $Begin, end => $End, addr => gc_get_scalar ('UnixSockAddr', undef), interval => gc_get_scalar ('Interval', 10)); -print STDOUT header (-Content_type => $ContentType, - -Last_Modified => epoch_to_rfc1123 ($obj->getLastModified ()), - -Expires => epoch_to_rfc1123 ($expires)); - -if ($Debug) -{ - print "\$expires = $expires;\n"; -} + print header (-Content_type => $ContentType, + -Last_Modified => epoch_to_rfc1123 ($obj->getLastModified ()), + -Expires => epoch_to_rfc1123 ($expires)); -my $args = $obj->getRRDArgs (0 + $Index); - -if ($Debug) -{ - require Data::Dumper; - print STDOUT Data::Dumper->Dump ([$obj], ['obj']); - print STDOUT join (",\n", @$args) . "\n"; - print STDOUT "Last-Modified: " . epoch_to_rfc1123 ($obj->getLastModified ()) . "\n"; -} -else -{ - my @timesel = (); + if (param ('debug')) + { + print "\$expires = $expires;\n"; + } - if ($End) # $Begin is always true + my $args = $obj->getRRDArgs (0 + $Index); + if (param ('debug')) { - @timesel = ('-s', $Begin, '-e', $End); + require Data::Dumper; + print Data::Dumper->Dump ([$obj], ['obj']); + print join (",\n", @$args) . "\n"; + print "Last-Modified: " . epoch_to_rfc1123 ($obj->getLastModified ()) . "\n"; } else { - @timesel = ('-s', $Begin); # End is implicitely `now'. - } + my @timesel = (); + my $tmpfile = tmpnam (); + my $status; - $| = 1; - RRDs::graph ('-', '-a', $OutputFormat, '--width', $GraphWidth, '--height', $GraphHeight, @timesel, @$args); - if (my $err = RRDs::error ()) - { - print STDERR "RRDs::graph failed: $err\n"; - exit (1); + if ($End) # $Begin is always true + { + @timesel = ('-s', $Begin, '-e', $End); + } + else + { + @timesel = ('-s', $Begin); # End is implicitely `now'. + } + + if (-S "/var/run/rrdcached.sock" && -w "/var/run/rrdcached.sock") + { + $ENV{"RRDCACHED_ADDRESS"} = "/var/run/rrdcached.sock"; + } + unlink ($tmpfile); + RRDs::graph ($tmpfile, '-a', $OutputFormat, '--width', $GraphWidth, '--height', $GraphHeight, @timesel, @$args); + if (my $err = RRDs::error ()) + { + print STDERR "RRDs::graph failed: $err\n"; + exit (1); + } + + $status = open (IMG, '<', $tmpfile) or die ("open ($tmpfile): $!"); + if (!$status) + { + print STDERR "graph.cgi: Unable to open temporary file \"$tmpfile\" for reading: $!\n"; + } + else + { + local $/ = undef; + while (my $data = ) + { + print STDOUT $data; + } + + close (IMG); + unlink ($tmpfile); + } } -} +} # sub main -exit (0); +main (); # vim: set shiftwidth=2 softtabstop=2 tabstop=8 : diff --git a/contrib/collection3/bin/index.cgi b/contrib/collection3/bin/index.cgi index e28e9857..4723af96 100755 --- a/contrib/collection3/bin/index.cgi +++ b/contrib/collection3/bin/index.cgi @@ -1,6 +1,7 @@ #!/usr/bin/perl -# Copyright (C) 2008 Florian octo Forster +# Copyright (C) 2008-2011 Florian Forster +# Copyright (C) 2011 noris network AG # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software @@ -14,14 +15,28 @@ # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Authors: +# Florian "octo" Forster use strict; use warnings; -use lib ('../lib'); use utf8; +use vars (qw($BASE_DIR)); + +BEGIN +{ + if (defined $ENV{'SCRIPT_FILENAME'}) + { + if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$}) + { + $::BASE_DIR = $1; + unshift (@::INC, "$::BASE_DIR/lib"); + } + } +} use Carp (qw(cluck confess)); -use FindBin ('$RealBin'); use CGI (':cgi'); use CGI::Carp ('fatalsToBrowser'); use HTML::Entities ('encode_entities'); @@ -35,8 +50,6 @@ use Collectd::Graph::Common (qw(get_files_from_directory get_all_hosts get_plugin_selection flush_files)); use Collectd::Graph::Type (); -our $Debug = param ('debug') ? 1 : 0; - our $TimeSpans = { Hour => 3600, @@ -46,23 +59,90 @@ our $TimeSpans = Year => 366 * 86400 }; -my $action = param ('action') || 'list_hosts'; -our %Actions = +my %Actions = ( list_hosts => \&action_list_hosts, show_selection => \&action_show_selection ); -if (!exists ($Actions{$action})) +sub base_dir { - print STDERR "No such action: $action\n"; - exit 1; + if (defined $::BASE_DIR) + { + return ($::BASE_DIR); + } + + if (!defined ($ENV{'SCRIPT_FILENAME'})) + { + return; + } + + if ($ENV{'SCRIPT_FILENAME'} =~ m{^(/.+)/bin/[^/]+$}) + { + $::BASE_DIR = $1; + return ($::BASE_DIR); + } + + return; } -gc_read_config ("$RealBin/../etc/collection.conf"); +sub lib_dir +{ + my $base = base_dir (); -$Actions{$action}->(); -exit (0); + if ($base) + { + return "$base/lib"; + } + else + { + return "../lib"; + } +} + +sub sysconf_dir +{ + my $base = base_dir (); + + if ($base) + { + return "$base/etc"; + } + else + { + return "../etc"; + } +} + +sub init +{ + my $lib_dir = lib_dir (); + my $sysconf_dir = sysconf_dir (); + + if (!grep { $lib_dir eq $_ } (@::INC)) + { + unshift (@::INC, $lib_dir); + } + + gc_read_config ("$sysconf_dir/collection.conf"); +} + +sub main +{ + my $Debug = param ('debug') ? 1 : 0; + my $action = param ('action') || 'list_hosts'; + + if (!exists ($Actions{$action})) + { + print STDERR "No such action: $action\n"; + return (1); + } + + init (); + + $Actions{$action}->(); + return (1); +} # sub main sub can_handle_xhtml { @@ -104,7 +184,7 @@ sub can_handle_xhtml } } # can_handle_xhtml -{my $html_started; +my $html_started; sub start_html { return if ($html_started); @@ -119,9 +199,8 @@ sub start_html if (can_handle_xhtml ()) { + print header (-Content_Type => 'application/xhtml+xml; charset=UTF-8'); print < @@ -133,9 +212,8 @@ HTML } else { + print header (-Content_Type => 'text/html; charset=UTF-8'); print < @@ -151,7 +229,7 @@ HTML HTML $html_started = 1; -}} +} sub end_html { @@ -159,6 +237,7 @@ sub end_html HTML + $html_started = 0; } sub contains_invalid_chars @@ -308,7 +387,7 @@ sub action_show_selection $all_files = get_selected_files (); $timespan = get_timespan_selection (); - if ($Debug) + if (param ('debug')) { print "
", Data::Dumper->Dump ([$all_files], ['all_files']), "
\n"; } @@ -333,7 +412,7 @@ sub action_show_selection $types->{$type} = tl_load_type ($file->{'type'}); if (!$types->{$type}) { - cluck ("tl_load_type (" . $file->{'type'} . ") failed"); + warn ("tl_load_type (" . $file->{'type'} . ") failed"); next; } } @@ -346,6 +425,12 @@ sub action_show_selection for (sort (keys %$types)) { my $type = $_; + + if (!defined ($types->{$type})) + { + next; + } + my $graphs_num = $types->{$type}->getGraphsNum (); for (my $i = 0; $i < $graphs_num; $i++) @@ -400,6 +485,8 @@ EOF end_html (); } +main (); + =head1 SEE ALSO L diff --git a/contrib/collection3/etc/collection.conf b/contrib/collection3/etc/collection.conf index 3bb3d8b1..3e19bfcd 100644 --- a/contrib/collection3/etc/collection.conf +++ b/contrib/collection3/etc/collection.conf @@ -2,24 +2,24 @@ GraphWidth 400 #UnixSockAddr "/var/run/collectd-unixsock" - DataSources count - DSName "count Bytes/s" + DataSources value + DSName "value Bytes/s" RRDTitle "Apache Traffic" RRDVerticalLabel "Bytes/s" RRDFormat "%5.1lf%s" - Color count 0000ff + Color value 0000ff - DataSources count - DSName "count Requests/s" + DataSources value + DSName "value Requests/s" RRDTitle "Apache Traffic" RRDVerticalLabel "Requests/s" RRDFormat "%5.2lf" - Color count 00d000 + Color value 00d000 Module GenericStacked - DataSources count + DataSources value RRDTitle "Apache scoreboard on {hostname}" RRDVerticalLabel "Slots" RRDFormat "%6.2lf" @@ -245,15 +245,15 @@ GraphWidth 400 RRDFormat "%6.1lf" - DataSources conntrack - DSName conntrack Conntrack count + DataSources value + DSName value Conntrack count RRDTitle "nf_conntrack connections on {hostname}" RRDVerticalLabel "Count" RRDFormat "%4.0lf" - DataSources entropy - DSName entropy Entropy bits + DataSources value + DSName value Entropy bits RRDTitle "Available entropy on {hostname}" RRDVerticalLabel "Bits" RRDFormat "%4.0lf" @@ -267,12 +267,12 @@ GraphWidth 400 Color value 00b000 - DataSources frequency - DSName frequency Frequency + DataSources value + DSName value Frequency RRDTitle "Frequency ({type_instance})" RRDVerticalLabel "Hertz" RRDFormat "%4.1lfHz" - Color frequency a000a0 + Color value a000a0 DataSources value @@ -542,16 +542,16 @@ GraphWidth 400 Scale 8 - DataSources percent - DSName percent Percent + DataSources value + DSName value Percent RRDTitle "Percent ({type_instance})" RRDVerticalLabel "Percent" RRDFormat "%4.1lf%%" - Color percent 0000ff + Color value 0000ff - DataSources ping - DSName "ping Latency" + DataSources value + DSName "value Latency" RRDTitle "Network latency ({type_instance})" RRDVerticalLabel "Milliseconds" RRDFormat "%5.2lfms" @@ -700,12 +700,12 @@ GraphWidth 400 Scale 0.001 - DataSources users - DSName users Users + DataSources value + DSName value Users RRDTitle "Users ({type_instance}) on {hostname}" RRDVerticalLabel "Users" RRDFormat "%.1lf" - Color users 0000f0 + Color value 0000f0 DataSources value diff --git a/contrib/collection3/lib/Collectd/Graph/Common.pm b/contrib/collection3/lib/Collectd/Graph/Common.pm index c6e25081..cc7e141f 100644 --- a/contrib/collection3/lib/Collectd/Graph/Common.pm +++ b/contrib/collection3/lib/Collectd/Graph/Common.pm @@ -1,5 +1,24 @@ package Collectd::Graph::Common; +# Copyright (C) 2008-2011 Florian Forster +# Copyright (C) 2011 noris network AG +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation; only version 2 of the License is applicable. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Authors: +# Florian "octo" Forster + use strict; use warnings; @@ -11,6 +30,8 @@ use CGI (':cgi'); use Exporter; use Collectd::Graph::Config (qw(gc_get_scalar)); +our $Cache = {}; + $ColorCanvas = 'FFFFFF'; $ColorFullBlue = '0000FF'; $ColorHalfBlue = 'B7B7F7'; @@ -191,22 +212,48 @@ sub ident_to_filename return ($ret); } # ident_to_filename +sub _part_to_string +{ + my $part = shift; + + if (!defined ($part)) + { + return ("(UNDEF)"); + } + if (ref ($part) eq 'ARRAY') + { + if (1 == @$part) + { + return ($part->[0]); + } + else + { + return ('(' . join (',', @$part) . ')'); + } + } + else + { + return ($part); + } +} # _part_to_string + sub ident_to_string { my $ident = shift; my $ret = ''; - $ret .= $ident->{'hostname'} . '/' . $ident->{'plugin'}; + $ret .= _part_to_string ($ident->{'hostname'}) + . '/' . _part_to_string ($ident->{'plugin'}); if (defined ($ident->{'plugin_instance'})) { - $ret .= '-' . $ident->{'plugin_instance'}; + $ret .= '-' . _part_to_string ($ident->{'plugin_instance'}); } - $ret .= '/' . $ident->{'type'}; + $ret .= '/' . _part_to_string ($ident->{'type'}); if (defined ($ident->{'type_instance'})) { - $ret .= '-' . $ident->{'type_instance'}; + $ret .= '-' . _part_to_string ($ident->{'type_instance'}); } return ($ret); @@ -258,27 +305,36 @@ sub get_files_from_directory sub get_all_hosts { - my $dh; - my @ret = (); - my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir); + my $ret = []; - opendir ($dh, "$data_dir") or confess ("opendir ($data_dir): $!"); - while (my $entry = readdir ($dh)) + if (defined ($Cache->{'get_all_hosts'})) { - next if ($entry =~ m/^\./); - next if (!-d "$data_dir/$entry"); - next if (!-r "$data_dir/$entry" or !-x "$data_dir/$entry"); - push (@ret, sanitize_hostname ($entry)); + $ret = $Cache->{'get_all_hosts'}; + } + else + { + my $dh; + my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir); + + opendir ($dh, "$data_dir") or confess ("opendir ($data_dir): $!"); + while (my $entry = readdir ($dh)) + { + next if ($entry =~ m/^\./); + next if (!-d "$data_dir/$entry"); + push (@$ret, sanitize_hostname ($entry)); + } + closedir ($dh); + + $Cache->{'get_all_hosts'} = $ret; } - closedir ($dh); if (wantarray ()) { - return (@ret); + return (@$ret); } - elsif (@ret) + elsif (@$ret) { - return (\@ret); + return ($ret); } else { @@ -292,12 +348,32 @@ sub get_all_plugins my $ret = {}; my $dh; my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir); + my $cache_key; - if (!@hosts) + if (@hosts) { + $cache_key = join (';', @hosts); + } + else + { + $cache_key = "/*/"; @hosts = get_all_hosts (); } + if (defined ($Cache->{'get_all_plugins'}{$cache_key})) + { + $ret = $Cache->{'get_all_plugins'}{$cache_key}; + + if (wantarray ()) + { + return (sort (keys %$ret)); + } + else + { + return ($ret); + } + } + for (@hosts) { my $host = $_; @@ -331,6 +407,7 @@ sub get_all_plugins closedir ($dh); } # for (@hosts) + $Cache->{'get_all_plugins'}{$cache_key} = $ret; if (wantarray ()) { return (sort (keys %$ret)); @@ -386,24 +463,44 @@ sub _filter_ident return (0); } # _filter_ident +sub _get_all_files +{ + my $ret; + + if (defined ($Cache->{'_get_all_files'})) + { + $ret = $Cache->{'_get_all_files'}; + } + else + { + my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir); + + $ret = get_files_from_directory ($data_dir, 3); + $Cache->{'_get_all_files'} = $ret; + } + + return ($ret); +} # _get_all_files + sub get_files_by_ident { my $ident = shift; my $all_files; my @ret = (); - my $data_dir = gc_get_scalar ('DataDir', $DefaultDataDir); - #if ($ident->{'hostname'}) - #{ - #$all_files = get_files_for_host ($ident->{'hostname'}); - #} - #else - #{ - $all_files = get_files_from_directory ($data_dir, 3); - #} + my $cache_key = ident_to_string ($ident); + if (defined ($Cache->{'get_files_by_ident'}{$cache_key})) + { + my $ret = $Cache->{'get_files_by_ident'}{$cache_key}; + + return ($ret) + } + + $all_files = _get_all_files (); @ret = grep { _filter_ident ($ident, $_) == 0 } (@$all_files); + $Cache->{'get_files_by_ident'}{$cache_key} = \@ret; return (\@ret); } # get_files_by_ident diff --git a/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm b/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm index 9078110b..5a0b522b 100644 --- a/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm +++ b/contrib/collection3/lib/Collectd/Graph/TypeLoader.pm @@ -92,7 +92,8 @@ sub _load_module_from_config $obj = _create_object ($module); if (!$obj) { - cluck ("Creating an $module object failed"); + #cluck ("Creating an $module object failed"); + warn ("Creating an $module object failed"); return; } } diff --git a/contrib/exec-ksm.sh b/contrib/exec-ksm.sh new file mode 100755 index 00000000..a21aa1d6 --- /dev/null +++ b/contrib/exec-ksm.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# collectd - contrib/exec-ksm.sh +# Copyright (C) 2011 Florian Forster +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# Authors: +# Florian Forster + +HOSTNAME="${COLLECTD_HOSTNAME:-$(hostname -f)}" +INTERVAL="${COLLECTD_INTERVAL:-60}" + +function read_file() { + local type="$1" + local type_instance="$2" + local file_name="/sys/kernel/mm/ksm/$3" + local ident="$HOSTNAME/exec-ksm/vmpage_number-${type_instance}" + + echo "PUTVAL \"$ident\" interval=$INTERVAL N:$(< $file_name)" +} + +if [[ 0 -eq $(< /sys/kernel/mm/ksm/run) ]]; then + echo "$0: KSM not active." >&2 + exit 1 +fi + +while sleep "$INTERVAL" +do + read_file vmpage_number shared pages_shared + read_file vmpage_number saved pages_sharing + read_file vmpage_number unshared pages_unshared + read_file vmpage_number volatile pages_volatile + read_file total_operations scan full_scans +done + +exit 0 diff --git a/contrib/exec-munin.px b/contrib/exec-munin.px index 907ea9bc..3e62ce00 100755 --- a/contrib/exec-munin.px +++ b/contrib/exec-munin.px @@ -46,7 +46,8 @@ use Regexp::Common ('number'); our $ConfigFile = '/etc/exec-munin.conf'; our $TypeMap = {}; our $Scripts = []; -our $Interval = 300; +our $Interval = defined ($ENV{'COLLECTD_INTERVAL'}) ? (0 + $ENV{'COLLECTD_INTERVAL'}) : 300; +our $Hostname = defined ($ENV{'COLLECTD_HOSTNAME'}) ? $ENV{'COLLECTD_HOSTNAME'} : ''; main (); exit (0); @@ -189,7 +190,7 @@ sub execute_script my $pinst; my $time = time (); my $script = shift; - my $host = hostname () || 'localhost'; + my $host = $Hostname || hostname () || 'localhost'; if (!open ($fh, '-|', $script)) { print STDERR "Cannot execute $script: $!"; @@ -206,8 +207,11 @@ sub execute_script my $field = $1; my $value = $2; my $type = (defined ($TypeMap->{$field})) ? $TypeMap->{$field} : $field; + my $ident = "$host/munin-$pinst/$type"; - print "$host/munin-$pinst/$type interval=$Interval $time:$value\n"; + $ident =~ s/"/\\"/g; + + print qq(PUTVAL "$ident" interval=$Interval $time:$value\n); } } diff --git a/contrib/exec-nagios.px b/contrib/exec-nagios.px index 02bd0a33..ec13b0a0 100755 --- a/contrib/exec-nagios.px +++ b/contrib/exec-nagios.px @@ -25,7 +25,8 @@ our $ConfigFile = '/etc/exec-nagios.conf'; our $TypeMap = {}; our $NRPEMap = {}; our $Scripts = []; -our $Interval = 300; +our $Interval = defined ($ENV{'COLLECTD_INTERVAL'}) ? (0 + $ENV{'COLLECTD_INTERVAL'}) : 300; +our $Hostname = defined ($ENV{'COLLECTD_HOSTNAME'}) ? $ENV{'COLLECTD_HOSTNAME'} : ''; main (); exit (0); @@ -351,6 +352,7 @@ sub handle_performance_data my $type = shift; my $time = shift; my $line = shift; + my $ident = "$host/$plugin-$pinst/$type-$tinst"; my $tinst; my $value; @@ -366,7 +368,9 @@ sub handle_performance_data return; } - print "PUTVAL $host/$plugin-$pinst/$type-$tinst interval=$Interval ${time}:$value\n"; + $ident =~ s/"/\\"/g; + + print qq(PUTVAL "$ident" interval=$Interval ${time}:$value\n); } sub execute_script @@ -376,7 +380,7 @@ sub execute_script my $time = time (); my $script = shift; my @args = (); - my $host = hostname () || 'localhost'; + my $host = $Hostname || hostname () || 'localhost'; my $state = 0; my $serviceoutput; @@ -438,7 +442,7 @@ sub execute_script close ($fh); # Save the exit status of the check in $state - $state = $?; + $state = $? >> 8; if ($state == 0) { diff --git a/contrib/exec-smartctl b/contrib/exec-smartctl index d4698160..99b69860 100755 --- a/contrib/exec-smartctl +++ b/contrib/exec-smartctl @@ -18,31 +18,29 @@ # smart ALL = (root) NOPASSWD: SMARTCTL # -- >8 -- -HOST="huhu" -INTERVAL=60 +HOSTNAME="${COLLECTD_HOSTNAME:-`hostname -f`}" +INTERVAL="${COLLECTD_INTERVAL:-60}" -while true +while sleep "$INTERVAL" do TEMP=$((sudo smartctl -d 3ware,0 -A /dev/twe0 | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null); if [ $? -ne 0 ] then TEMP="U" fi - echo "$HOST/exec-smart/temperature-3ware_0 interval=$INTERVAL N:$TEMP" + echo "PUTVAL $HOSTNAME/exec-smart/temperature-3ware_0 interval=$INTERVAL N:$TEMP" TEMP=$((sudo smartctl -d 3ware,1 -A /dev/twe0 | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null); if [ $? -ne 0 ] then TEMP="U" fi - echo "$HOST/exec-smart/temperature-3ware_1 interval=$INTERVAL N:$TEMP" + echo "PUTVAL $HOSTNAME/exec-smart/temperature-3ware_1 interval=$INTERVAL N:$TEMP" TEMP=$((sudo smartctl -d ata -A /dev/sda | grep Temperature_Celsius | awk '{ print $10; }') 2>/dev/null); if [ $? -ne 0 ] then TEMP="U" fi - echo "$HOST/exec-smart/temperature-sata_0 interval=$INTERVAL N:$TEMP" - - sleep $INTERVAL + echo "PUTVAL $HOSTNAME/exec-smart/temperature-sata_0 interval=$INTERVAL N:$TEMP" done diff --git a/contrib/migrate-4-5.px b/contrib/migrate-4-5.px new file mode 100755 index 00000000..c2a95558 --- /dev/null +++ b/contrib/migrate-4-5.px @@ -0,0 +1,255 @@ +#!/usr/bin/perl + +# collectd - contrib/migrate-4-5.px +# Copyright (C) 2010 Florian Forster +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. +# +# Authors: +# Florian Forster + +use strict; +use warnings; + +use Getopt::Long ('GetOptions'); +use Data::Dumper (); +use File::Basename ('dirname'); + +our $InDir = '/var/lib/collectd'; +our $RRDtool = 'rrdtool'; +our $RRDFilter = 'rrd_filter.px'; + +our %TypesCounterToDerive = # {{{ +( + apache_bytes => ["count"], + apache_requests => ["count"], + arc_counts => ["demand_data", "demand_metadata", "prefetch_data", "prefetch_metadata"], + arc_l2_bytes => ["read", "write"], + ath_stat => ["value"], + compression => ["uncompressed", "compressed"], + connections => ["value"], + cpu => ["value"], + current => ["value"], + disk_merged => ["read", "write"], + disk_octets => ["read", "write"], + disk_ops => ["read", "write"], + disk_ops_complex => ["value"], + disk_time => ["read", "write"], + dns_answer => ["value"], + dns_notify => ["value"], + dns_octets => ["queries", "responses"], + dns_opcode => ["value"], + dns_qtype => ["value"], + dns_query => ["value"], + dns_question => ["value"], + dns_rcode => ["value"], + dns_reject => ["value"], + dns_request => ["value"], + dns_resolver => ["value"], + dns_response => ["value"], + dns_transfer => ["value"], + dns_update => ["value"], + dns_zops => ["value"], + fscache_stat => ["value"], + fork_rate => ["value"], + http_request_methods => ["count"], + http_requests => ["count"], + http_response_codes => ["count"], + if_collisions => ["value"], + if_dropped => ["rx", "tx"], + if_errors => ["rx", "tx"], + if_multicast => ["value"], + if_octets => ["rx", "tx"], + if_packets => ["rx", "tx"], + if_rx_errors => ["value"], + if_tx_errors => ["value"], + io_octets => ["rx", "tx"], + io_packets => ["rx", "tx"], + ipt_bytes => ["value"], + ipt_packets => ["value"], + irq => ["value"], + memcached_command => ["value"], + memcached_octets => ["rx", "tx"], + memcached_ops => ["value"], + mysql_commands => ["value"], + mysql_handler => ["value"], + mysql_locks => ["value"], + mysql_log_position => ["value"], + mysql_octets => ["rx", "tx"], + nfs_procedure => ["value"], + nginx_requests => ["value"], + node_octets => ["rx", "tx"], + node_stat => ["value"], + operations => ["value"], + pg_blks => ["value"], + pg_n_tup_c => ["value"], + pg_scan => ["value"], + pg_xact => ["value"], + protocol_counter => ["value"], + ps_cputime => ["user", "syst"], + ps_pagefaults => ["minflt", "majflt"], + ps_code => ["value"], + ps_data => ["value"], + serial_octets => ["rx", "tx"], + swap_io => ["value"], + virt_cpu_total => ["ns"], + virt_vcpu => ["ns"], + vmpage_action => ["value"], + vmpage_faults => ["minflt", "majflt"], + vmpage_io => ["in", "out"], +); # }}} %TypesCounterToDerive + +our %TypesRenameDataSource = # {{{ +( + absolute => "count", + apache_bytes => "count", + apache_connections => "count", + apache_idle_workers => "count", + apache_requests => "count", + apache_scoreboard => "count", + conntrack => "entropy", + contextswitch => "contextswitches", + delay => "seconds", + entropy => "entropy", + file_size => "bytes", + frequency => "frequency", + frequency_offset => "ppm", + http_request_methods => "count", + http_requests => "count", + http_response_codes => "count", + percent => "percent", + ping => "ping", + records => "count", + time_dispersion => "seconds", + timeleft => "timeleft", + time_offset => "seconds", + users => "users", + virt_cpu_total => "ns", + virt_vcpu => "ns", +); # }}} %TypesRenameDataSource + +sub handle_file # {{{ +{ + my @path = @_; + my $path = join ('/', @path); + + if (!($path =~ m/\.rrd$/)) + { + return; + } + + my $tmp = pop (@path); + $tmp =~ s/\.rrd$//; + my ($type, $type_inst) = split (m/-/, $tmp, 2); + $type_inst ||= ''; + + $tmp = pop (@path); + my ($plugin, $plugin_inst) = split (m/-/, $tmp, 2); + $plugin_inst ||= ''; + + if ($TypesRenameDataSource{$type}) + { + my $old_ds = $TypesRenameDataSource{$type}; + print "$RRDtool tune \"$path\" --data-source-rename ${old_ds}:value\n"; + } + + if ($TypesCounterToDerive{$type}) + { + my $ds_names = $TypesCounterToDerive{$type}; + + for (@$ds_names) + { + my $name = $_; + print "$RRDtool tune \"$path\" --data-source-type ${name}:DERIVE --minimum ${name}:0 --maximum ${name}:U\n"; + } + } + + if ((($plugin eq 'df') || ($plugin eq 'interface')) + && (!$plugin_inst) && ($type_inst)) + { + my $dir = join ('/', @path); + print "mkdir -p \"$dir/$plugin-$type_inst\"\n"; + if (($plugin eq 'df') and ($type eq 'df')) + { + print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-free.rrd\" --map free:value\n"; + print "$RRDFilter --infile=\"$path\" --outfile=\"$dir/$plugin-$type_inst/df_complex-used.rrd\" --map used:value\n"; + } + else + { + print "mv \"$path\" \"$dir/$plugin-$type_inst/$type.rrd\"\n"; + } + } +} # }}} sub handle_file + +sub scan_dir # {{{ +{ + my @dir_parts = @_; + my $dir_str = join ('/', @dir_parts); + my $dh; + + opendir ($dh, $dir_str) || die; + while (my $entry = readdir ($dh)) + { + my $entry_path = "$dir_str/$entry"; + + if ($entry =~ m/^\./) + { + next; + } + + if (-d $entry_path) + { + scan_dir (@dir_parts, $entry); + } + elsif (-f $entry_path) + { + handle_file (@dir_parts, $entry); + } + } + closedir ($dh); +} # }}} sub scan_dir + +sub exit_usage # {{{ +{ + print STDERR < Source directory + Default: $InDir + --rrdtool Path to the RRDtool binary + Default: $RRDtool + --rrdfilter Path to the rrd_filter.px script + Default: $RRDFilter + +EOF + exit (1); +} # }}} sub exit_usage + +GetOptions ("indir|i=s" => \$InDir, + "rrdtool=s" => \$RRDtool, + "rrdfilter=s" => \$RRDFilter, + "help|h" => \&exit_usage) or exit_usage (); + +print "#!/bin/bash\n\n"; + +scan_dir ($InDir); + +# vim: set sw=2 sts=2 et fdm=marker : diff --git a/contrib/php-collection/definitions.php b/contrib/php-collection/definitions.php index c84aabea..7297d858 100644 --- a/contrib/php-collection/definitions.php +++ b/contrib/php-collection/definitions.php @@ -48,9 +48,9 @@ function load_graph_definitions($logarithmic = false, $tinylegend = false) { $GraphDefs = array(); $GraphDefs['apache_bytes'] = array( '-v', 'Bits/s', - 'DEF:min_raw={file}:count:MIN', - 'DEF:avg_raw={file}:count:AVERAGE', - 'DEF:max_raw={file}:count:MAX', + 'DEF:min_raw={file}:value:MIN', + 'DEF:avg_raw={file}:value:AVERAGE', + 'DEF:max_raw={file}:value:MAX', 'CDEF:min=min_raw,8,*', 'CDEF:avg=avg_raw,8,*', 'CDEF:max=max_raw,8,*', @@ -68,9 +68,9 @@ function load_graph_definitions($logarithmic = false, $tinylegend = false) { 'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'); $GraphDefs['apache_requests'] = array( '-v', 'Requests/s', - 'DEF:min={file}:count:MIN', - 'DEF:avg={file}:count:AVERAGE', - 'DEF:max={file}:count:MAX', + 'DEF:min={file}:value:MIN', + 'DEF:avg={file}:value:AVERAGE', + 'DEF:max={file}:value:MAX', "AREA:max#$HalfBlue", "AREA:min#$Canvas", "LINE1:avg#$FullBlue:Requests/s", @@ -79,9 +79,9 @@ function load_graph_definitions($logarithmic = false, $tinylegend = false) { 'GPRINT:max:MAX:%6.2lf Max,', 'GPRINT:avg:LAST:%6.2lf Last'); $GraphDefs['apache_scoreboard'] = array( - 'DEF:min={file}:count:MIN', - 'DEF:avg={file}:count:AVERAGE', - 'DEF:max={file}:count:MAX', + 'DEF:min={file}:value:MIN', + 'DEF:avg={file}:value:AVERAGE', + 'DEF:max={file}:value:MAX', "AREA:max#$HalfBlue", "AREA:min#$Canvas", "LINE1:avg#$FullBlue:Processes", @@ -2024,7 +2024,7 @@ function meta_graph_apache_scoreboard($host, $plugin, $plugin_instance, $type, $ if ($file == '') continue; - $sources[] = array('name'=>$inst, 'file'=>$file, 'ds'=>'count'); + $sources[] = array('name'=>$inst, 'file'=>$file, 'ds'=>'value'); } return collectd_draw_meta_stack($opts, $sources); diff --git a/contrib/postgresql/collectd_insert.sql b/contrib/postgresql/collectd_insert.sql new file mode 100644 index 00000000..00c5519b --- /dev/null +++ b/contrib/postgresql/collectd_insert.sql @@ -0,0 +1,234 @@ +-- collectd - contrib/postgresql/collectd_insert.sql +-- Copyright (C) 2012 Sebastian 'tokkee' Harl +-- All rights reserved. +-- +-- Redistribution and use in source and binary forms, with or without +-- modification, are permitted provided that the following conditions +-- are met: +-- +-- - Redistributions of source code must retain the above copyright +-- notice, this list of conditions and the following disclaimer. +-- +-- - Redistributions in binary form must reproduce the above copyright +-- notice, this list of conditions and the following disclaimer in the +-- documentation and/or other materials provided with the distribution. +-- +-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-- POSSIBILITY OF SUCH DAMAGE. + +-- Description: +-- ------------ +-- +-- This is a sample database setup that may be used to write data collected by +-- collectd to a PostgreSQL database. We're using two tables, 'identifiers' +-- and 'values' to store the value-list identifier and the actual values +-- respectively. +-- +-- The 'values' table is partitioned to improve performance and maintainance. +-- Please note that additional maintainance scripts are required in order to +-- keep the setup running -- see the comments below for details. +-- +-- The function 'collectd_insert' may be used to actually insert values +-- submitted by collectd into those tables. +-- +-- Sample configuration: +-- --------------------- +-- +-- +-- +-- Statement "SELECT collectd_insert($1, $2, $3, $4, $5, $6, $7, $8, $9);" +-- +-- +-- # ... +-- Writer sqlstore +-- +-- + +CREATE TABLE identifiers ( + id integer NOT NULL, + host character varying(64) NOT NULL, + plugin character varying(64) NOT NULL, + plugin_inst character varying(64) DEFAULT NULL::character varying, + type character varying(64) NOT NULL, + type_inst character varying(64) DEFAULT NULL::character varying +); +CREATE SEQUENCE identifiers_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; +ALTER SEQUENCE identifiers_id_seq OWNED BY identifiers.id; +ALTER TABLE ONLY identifiers + ALTER COLUMN id SET DEFAULT nextval('identifiers_id_seq'::regclass); +ALTER TABLE ONLY identifiers + ADD CONSTRAINT identifiers_host_plugin_plugin_inst_type_type_inst_key + UNIQUE (host, plugin, plugin_inst, type, type_inst); +ALTER TABLE ONLY identifiers + ADD CONSTRAINT identifiers_pkey PRIMARY KEY (id); + +-- optionally, create indexes for the identifier fields +CREATE INDEX identifiers_host ON identifiers USING btree (host); +CREATE INDEX identifiers_plugin ON identifiers USING btree (plugin); +CREATE INDEX identifiers_plugin_inst ON identifiers USING btree (plugin_inst); +CREATE INDEX identifiers_type ON identifiers USING btree (type); +CREATE INDEX identifiers_type_inst ON identifiers USING btree (type_inst); + +CREATE TABLE "values" ( + id integer NOT NULL, + tstamp timestamp with time zone NOT NULL, + name character varying(64) NOT NULL, + value double precision NOT NULL +); + +CREATE OR REPLACE VIEW collectd + AS SELECT host, plugin, plugin_inst, type, type_inst, + host + || '/' || plugin + || CASE + WHEN plugin_inst IS NOT NULL THEN '-' + ELSE '' + END + || coalesce(plugin_inst, '') + || '/' || type + || CASE + WHEN type_inst IS NOT NULL THEN '-' + ELSE '' + END + || coalesce(type_inst, '') AS identifier, + tstamp, name, value + FROM identifiers + JOIN values + ON values.id = identifiers.id; + +-- partition "values" by day (or week, month, ...) + +-- create the child tables for today and the next 'days' days: +-- this may, for example, be used in a daily cron-job (or similar) to create +-- the tables for the next couple of days +CREATE OR REPLACE FUNCTION values_update_childs( + integer + ) RETURNS SETOF text + LANGUAGE plpgsql + AS $_$ +DECLARE + days alias for $1; + cur_day date; + next_day date; + i integer; +BEGIN + IF days < 1 THEN + RAISE EXCEPTION 'Cannot have negative number of days'; + END IF; + + i := 0; + LOOP + EXIT WHEN i > days; + + SELECT CAST ('now'::date + i * '1day'::interval AS date) INTO cur_day; + SELECT CAST ('now'::date + (i + 1) * '1day'::interval AS date) INTO next_day; + + i := i + 1; + + BEGIN + EXECUTE 'CREATE TABLE "values$' || cur_day || '" ( + CHECK (tstamp >= TIMESTAMP ''' || cur_day || ''' ' + || 'AND tstamp < TIMESTAMP ''' || next_day || ''') + ) INHERITS (values)'; + EXCEPTION WHEN duplicate_table THEN + CONTINUE; + END; + + RETURN NEXT 'values$' || cur_day::text; + + EXECUTE 'ALTER TABLE ONLY "values$' || cur_day || '" + ADD CONSTRAINT "values_' || cur_day || '_pkey" + PRIMARY KEY (id, tstamp, name, value)'; + EXECUTE 'ALTER TABLE ONLY "values$' || cur_day || '" + ADD CONSTRAINT "values_' || cur_day || '_id_fkey" + FOREIGN KEY (id) REFERENCES identifiers(id)'; + END LOOP; + RETURN; +END; +$_$; + +-- create initial child tables +SELECT values_update_childs(2); + +CREATE OR REPLACE FUNCTION values_insert_trigger() + RETURNS trigger + LANGUAGE plpgsql + AS $_$ +DECLARE + child_tbl character varying; +BEGIN + SELECT 'values$' || CAST (NEW.tstamp AS DATE) INTO child_tbl; + -- Rather than using 'EXECUTE', some if-cascade checking the date may also + -- be used. However, this would require frequent updates of the trigger + -- function while this example works automatically. + EXECUTE 'INSERT INTO "' || child_tbl || '" VALUES ($1.*)' USING NEW; + RETURN NULL; +END; +$_$; + +CREATE TRIGGER insert_values_trigger + BEFORE INSERT ON values + FOR EACH ROW EXECUTE PROCEDURE values_insert_trigger(); + +-- when querying values make sure to enable constraint exclusion +-- SET constraint_exclusion = on; + +CREATE OR REPLACE FUNCTION collectd_insert( + timestamp with time zone, character varying, + character varying, character varying, + character varying, character varying, + character varying[], character varying[], double precision[] + ) RETURNS void + LANGUAGE plpgsql + AS $_$ +DECLARE + p_time alias for $1; + p_host alias for $2; + p_plugin alias for $3; + p_plugin_instance alias for $4; + p_type alias for $5; + p_type_instance alias for $6; + p_value_names alias for $7; + -- don't use the type info; for 'StoreRates true' it's 'gauge' anyway + -- p_type_names alias for $8; + p_values alias for $9; + ds_id integer; + i integer; +BEGIN + SELECT id INTO ds_id + FROM identifiers + WHERE host = p_host + AND plugin = p_plugin + AND COALESCE(plugin_inst, '') = COALESCE(p_plugin_instance, '') + AND type = p_type + AND COALESCE(type_inst, '') = COALESCE(p_type_instance, ''); + IF NOT FOUND THEN + INSERT INTO identifiers (host, plugin, plugin_inst, type, type_inst) + VALUES (p_host, p_plugin, p_plugin_instance, p_type, p_type_instance) + RETURNING id INTO ds_id; + END IF; + i := 1; + LOOP + EXIT WHEN i > array_upper(p_value_names, 1); + INSERT INTO values (id, tstamp, name, value) + VALUES (ds_id, p_time, p_value_names[i], p_values[i]); + i := i + 1; + END LOOP; +END; +$_$; + +-- vim: set expandtab : diff --git a/contrib/redhat/apache.conf b/contrib/redhat/apache.conf deleted file mode 100644 index e9c767a5..00000000 --- a/contrib/redhat/apache.conf +++ /dev/null @@ -1,8 +0,0 @@ -LoadPlugin apache -# -# URL "http://localhost/status?auto" -# User "www-user" -# Password "secret" -# CACert "/etc/ssl/ca.crt" -# - diff --git a/contrib/redhat/collectd.conf b/contrib/redhat/collectd.conf deleted file mode 100644 index f8352ffa..00000000 --- a/contrib/redhat/collectd.conf +++ /dev/null @@ -1,210 +0,0 @@ -# -# Config file for collectd(1). -# Please read collectd.conf(5) for a list of options. -# http://collectd.org/ -# - -#Hostname "localhost" -FQDNLookup true -BaseDir "/var/lib/collectd" -PIDFile "/var/run/collectd.pid" -PluginDir "/usr/lib/collectd" -TypesDB "/usr/share/collectd/types.db" -Interval 10 -ReadThreads 5 - -LoadPlugin apcups -#LoadPlugin apple_sensors -LoadPlugin battery -LoadPlugin conntrack -LoadPlugin cpu -LoadPlugin cpufreq -LoadPlugin csv -LoadPlugin df -LoadPlugin disk -LoadPlugin dns -LoadPlugin entropy -LoadPlugin exec -LoadPlugin hddtemp -LoadPlugin interface -#LoadPlugin iptables -#LoadPlugin ipvs -LoadPlugin irq -#LoadPlugin libvirt -LoadPlugin load -LoadPlugin logfile -LoadPlugin mbmon -LoadPlugin memcached -LoadPlugin memory -LoadPlugin multimeter -#LoadPlugin netlink -LoadPlugin network -LoadPlugin nfs -LoadPlugin ntpd -#LoadPlugin nut -LoadPlugin perl -LoadPlugin ping -LoadPlugin processes -LoadPlugin rrdtool -LoadPlugin serial -LoadPlugin swap -LoadPlugin syslog -#LoadPlugin tape -LoadPlugin tcpconns -LoadPlugin unixsock -LoadPlugin users -LoadPlugin uuid -LoadPlugin vserver -LoadPlugin wireless -#LoadPlugin xmms - - -# -# Host "localhost" -# Port "3551" -# - -# -# DataDir "/usr/var/lib/collectd/csv" -# StoreRates false -# - -# -# Device "/dev/hda1" -# Device "192.168.0.2:/mnt/nfs" -# MountPoint "/home" -# FSType "ext3" -# IgnoreSelected false -# - -# -# Interface "eth0" -# IgnoreSource "192.168.0.1" -# - -# -# Exec "user:group" "/path/to/exec" -# NotificationExec "/path/to/exec" -# - -# -# Host "127.0.0.1" -# Port "7634" -# TranslateDevicename false -# - -# -# Interface "eth0" -# IgnoreSelected false -# - -# -# Chain table chain -# - -# -# Irq 7 -# Irq 8 -# Irq 9 -# IgnoreSelected true -# - -# -# Connection "xen:///" -# RefreshInterval 60 -# Domain "name" -# BlockDevice "name:device" -# InterfaceDevice "name:device" -# IgnoreSelected false -# HostnameFormat name -# - -# -# LogLevel info -# File STDOUT -# Timestamp true -# - -# -# Host "127.0.0.1" -# Port "411" -# - -# -# Host "127.0.0.1" -# Port "11211" -# - -# -# Interface "All" -# VerboseInterface "All" -# QDisc "eth0" "pfifo_fast-1:0" -# Class "ppp0" "htb-1:10" -# Filter "ppp0" "u32-1:0" -# IgnoreSelected false -# - -# -# Server "ff18::efc0:4a42" "25826" -# Server "239.192.74.66" "25826" -# Listen "ff18::efc0:4a42" "25826" -# Listen "239.192.74.66" "25826" -# TimeToLive "128" -# Forward false -# CacheFlush 1800 -# - -# -# Host "localhost" -# Port 123 -# ReverseLookups false -# - -# -# UPS "upsname@hostname:port" -# - -# -# IncludeDir "/my/include/path" -# BaseName "Collectd::Plugin" -# EnableDebugger "" -# LoadPlugin foo -# - -# -# Host "host.foo.bar" -# TTL 255 -# - -# -# Process "name" -# - -# -# DataDir "/usr/var/lib/collectd/rrd" -# CacheTimeout 120 -# CacheFlush 900 -# - -# -# LogLevel info -# - -# -# ListeningPorts false -# LocalPort "25" -# RemotePort "25" -# - -# -# SocketFile "/usr/var/run/collectd-unixsock" -# SocketGroup "collectd" -# SocketPerms "0660" -# - -# -# UUIDFile "/etc/uuid" -# - -Include "/etc/collectd.d" - diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index 4617f6ca..ce715ea1 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -1,289 +1,2000 @@ - -%define with_java %(test -z "$JAVA_HOME" ; echo $?) - -Summary: Statistics collection daemon for filling RRD files. +# +# q: What is this ? +# a: A specfile for building RPM packages of current collectd releases, for +# RHEL/CentOS versions 5, 6 and 7. By default all the plugins which are +# buildable based on the libraries available in the distribution + the +# EPEL repository, will be built. Plugins depending on external libs will +# be packaged in separate RPMs. +# +# q: And how can I do that ? +# a: By following these instructions, using mock: +# +# - install and configure mock (https://fedoraproject.org/wiki/Projects/Mock) +# +# - enable the EPEL repository (http://dl.fedoraproject.org/pub/epel/) in the +# configuration files for your target systems (/etc/mock/*.cfg). +# +# - fetch the desired collectd release file from https://collectd.org/files/ +# and save it in your ~/rpmbuild/SOURCES/ directory (or build your own out of +# the git repository: ./build.sh && ./configure && make-dist-bz2) +# +# - copy this file in your ~/rpmbuild/SPECS/ directory. Make sure the +# "Version:" tag matches the version from the tarball. +# +# - build the SRPM first: +# mock -r centos-6-x86_64 --buildsrpm --spec ~/rpmbuild/SPECS/collectd.spec \ +# --sources ~/rpmbuild/SOURCES/ +# +# - then build the RPMs: +# mock -r centos-6-x86_64 --no-clean --rebuild \ +# /var/lib/mock/centos-6-x86_64/result/collectd-X.Y.Z-NN.src.rpm +# +# - you can also optionally enable/disable plugins which are disabled/enabled +# by default: +# mock -r centos-6-x86_64 --no-clean --without=java --with=oracle --rebuild \ +# /var/lib/mock/centos-6-x86_64/result/collectd-X.Y.Z-NN.src.rpm +# + +%global _hardened_build 1 +%{?perl_default_filter} + +# plugins only buildable on RHEL6 +# (NB: %{elN} macro is not available on RHEL < 6) +%{?el6:%global _has_libyajl 1} +%{?el6:%global _has_recent_libpcap 1} +%{?el6:%global _has_recent_sockios_h 1} +%{?el6:%global _has_recent_libganglia 1} +%{?el6:%global _has_working_libiptc 1} +%{?el6:%global _has_ip_vs_h 1} +%{?el6:%global _has_libmodbus 1} +%{?el6:%global _has_iproute 1} + +%{?el7:%global _has_libyajl 1} +%{?el7:%global _has_recent_libpcap 1} +%{?el7:%global _has_recent_sockios_h 1} +%{?el7:%global _has_working_libiptc 1} +%{?el7:%global _has_ip_vs_h 1} +%{?el7:%global _has_recent_librrd 1} +%{?el7:%global _has_varnish4 1} +%{?el7:%global _has_broken_libmemcached 1} +%{?el7:%global _has_iproute 1} + +# plugins enabled by default +%define with_aggregation 0%{!?_without_aggregation:1} +%define with_amqp 0%{!?_without_amqp:1} +%define with_apache 0%{!?_without_apache:1} +%define with_apcups 0%{!?_without_apcups:1} +%define with_ascent 0%{!?_without_ascent:1} +%define with_battery 0%{!?_without_battery:1} +%define with_bind 0%{!?_without_bind:1} +%define with_conntrack 0%{!?_without_conntrack:1} +%define with_contextswitch 0%{!?_without_contextswitch:1} +%define with_cpu 0%{!?_without_cpu:1} +%define with_cpufreq 0%{!?_without_cpufreq:1} +%define with_csv 0%{!?_without_csv:1} +%define with_curl 0%{!?_without_curl:1} +%define with_curl_json 0%{!?_without_curl_json:0%{?_has_libyajl}} +%define with_curl_xml 0%{!?_without_curl_xml:1} +%define with_dbi 0%{!?_without_dbi:1} +%define with_df 0%{!?_without_df:1} +%define with_disk 0%{!?_without_disk:1} +%define with_dns 0%{!?_without_dns:0%{?_has_recent_libpcap}} +%define with_email 0%{!?_without_email:1} +%define with_entropy 0%{!?_without_entropy:1} +%define with_ethstat 0%{!?_without_ethstat:0%{?_has_recent_sockios_h}} +%define with_exec 0%{!?_without_exec:1} +%define with_filecount 0%{!?_without_filecount:1} +%define with_fscache 0%{!?_without_fscache:1} +%define with_gmond 0%{!?_without_gmond:0%{?_has_recent_libganglia}} +%define with_hddtemp 0%{!?_without_hddtemp:1} +%define with_interface 0%{!?_without_interface:1} +%define with_ipmi 0%{!?_without_ipmi:1} +%define with_iptables 0%{!?_without_iptables:0%{?_has_working_libiptc}} +%define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}} +%define with_irq 0%{!?_without_irq:1} +%define with_java 0%{!?_without_java:1} +%define with_libvirt 0%{!?_without_libvirt:1} +%define with_load 0%{!?_without_load:1} +%define with_logfile 0%{!?_without_logfile:1} +%define with_madwifi 0%{!?_without_madwifi:1} +%define with_mbmon 0%{!?_without_mbmon:1} +%define with_md 0%{!?_without_md:1} +%define with_memcachec 0%{!?_without_memcachec:0%{!?_has_broken_libmemcached:1}} +%define with_memcached 0%{!?_without_memcached:1} +%define with_memory 0%{!?_without_memory:1} +%define with_multimeter 0%{!?_without_multimeter:1} +%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}} +%define with_mysql 0%{!?_without_mysql:1} +%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}} +%define with_network 0%{!?_without_network:1} +%define with_nfs 0%{!?_without_nfs:1} +%define with_nginx 0%{!?_without_nginx:1} +%define with_notify_desktop 0%{!?_without_notify_desktop:1} +%define with_notify_email 0%{!?_without_notify_email:1} +%define with_ntpd 0%{!?_without_ntpd:1} +%define with_numa 0%{!?_without_numa:1} +%define with_nut 0%{!?_without_nut:1} +%define with_olsrd 0%{!?_without_olsrd:1} +%define with_openvpn 0%{!?_without_openvpn:1} +%define with_perl 0%{!?_without_perl:1} +%define with_pinba 0%{!?_without_pinba:1} +%define with_ping 0%{!?_without_ping:1} +%define with_postgresql 0%{!?_without_postgresql:1} +%define with_powerdns 0%{!?_without_powerdns:1} +%define with_processes 0%{!?_without_processes:1} +%define with_protocols 0%{!?_without_protocols:1} +%define with_python 0%{!?_without_python:1} +%define with_rrdcached 0%{!?_without_rrdcached:0%{?_has_recent_librrd}} +%define with_rrdtool 0%{!?_without_rrdtool:1} +%define with_sensors 0%{!?_without_sensors:1} +%define with_serial 0%{!?_without_serial:1} +%define with_snmp 0%{!?_without_snmp:1} +%define with_swap 0%{!?_without_swap:1} +%define with_syslog 0%{!?_without_syslog:1} +%define with_table 0%{!?_without_table:1} +%define with_tail 0%{!?_without_tail:1} +%define with_tail_csv 0%{!?_without_tail_csv:1} +%define with_tcpconns 0%{!?_without_tcpconns:1} +%define with_teamspeak2 0%{!?_without_teamspeak2:1} +%define with_ted 0%{!?_without_ted:1} +%define with_thermal 0%{!?_without_thermal:1} +%define with_threshold 0%{!?_without_threshold:1} +%define with_unixsock 0%{!?_without_unixsock:1} +%define with_uptime 0%{!?_without_uptime:1} +%define with_users 0%{!?_without_users:1} +%define with_uuid 0%{!?_without_uuid:1} +%define with_varnish 0%{!?_without_varnish:0%{!?_has_varnish4:1}} +%define with_vmem 0%{!?_without_vmem:1} +%define with_vserver 0%{!?_without_vserver:1} +%define with_wireless 0%{!?_without_wireless:1} +%define with_write_graphite 0%{!?_without_write_graphite:1} +%define with_write_http 0%{!?_without_write_http:1} +%define with_write_riemann 0%{!?_without_write_riemann:1} + +# Plugins not built by default because of dependencies on libraries not +# available in RHEL or EPEL: + +# plugin apple_sensors disabled, requires a Mac +%define with_apple_sensors 0%{!?_without_apple_sensors:0} +# plugin lpar disabled, requires AIX +%define with_lpar 0%{!?_without_lpar:0} +# plugin netapp disabled, requires libnetapp +%define with_netapp 0%{!?_without_netapp:0} +# plugin onewire disabled, requires libowfs +%define with_onewire 0%{!?_without_onewire:0} +# plugin oracle disabled, requires Oracle +%define with_oracle 0%{!?_without_oracle:0} +# plugin oracle disabled, requires BSD +%define with_pf 0%{!?_without_pf:0} +# plugin redis disabled, requires credis +%define with_redis 0%{!?_without_redis:0} +# plugin routeros disabled, requires librouteros +%define with_routeros 0%{!?_without_routeros:0} +# plugin tape disabled, requires libkstat +%define with_tape 0%{!?_without_tape:0} +# plugin tokyotyrant disabled, requires tcrdb.h +%define with_tokyotyrant 0%{!?_without_tokyotyrant:0} +# plugin write_mongodb disabled, requires libmongoc +%define with_write_mongodb 0%{!?_without_write_mongodb:0} +# plugin write_redis disabled, requires credis +%define with_write_redis 0%{!?_without_write_redis:0} +# plugin xmms disabled, requires xmms +%define with_xmms 0%{!?_without_xmms:0} +# plugin zfs_arc disabled, requires FreeBSD/Solaris +%define with_zfs_arc 0%{!?_without_zfs_arc:0} + +Summary: Statistics collection daemon for filling RRD files Name: collectd -Version: 4.9.0 +Version: 5.3.2 Release: 1%{?dist} -Source: http://collectd.org/files/%{name}-%{version}.tar.gz -License: GPL +URL: http://collectd.org +Source: http://collectd.org/files/%{name}-%{version}.tar.bz2 +License: GPLv2 Group: System Environment/Daemons BuildRoot: %{_tmppath}/%{name}-%{version}-root -BuildPrereq: lm_sensors-devel, rrdtool-devel, libpcap-devel, net-snmp-devel, libstatgrab-devel, libxml2-devel, libiptcdata-devel -# libcurl deps -BuildPrereq: curl-devel,libidn-devel,openssl-devel -Requires: rrdtool, perl-Regexp-Common, libstatgrab -Packager: RightScale +BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel Vendor: collectd development team +Requires(post): chkconfig +Requires(preun): chkconfig, initscripts +Requires(postun): initscripts + %description collectd is a small daemon which collects system information periodically and provides mechanisms to monitor and store the values in a variety of ways. It -is written in C for performance. Since the daemon doesn't need to startup +is written in C for performance. Since the daemon doesn't need to start up every time it wants to update the values it's very fast and easy on the system. Also, the statistics are very fine grained since the files are updated -every 10 seconds. +every 10 seconds by default. +%if %{with_amqp} +%package amqp +Summary: AMQP plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: librabbitmq-devel +%description amqp +The AMQP plugin transmits or receives values collected by collectd via the +Advanced Message Queuing Protocol (AMQP). +%endif +%if %{with_apache} %package apache -Summary: apache-plugin for collectd. +Summary: Apache plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, curl +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel %description apache This plugin collects data provided by Apache's `mod_status'. +%endif + +%if %{with_ascent} +%package ascent +Summary: Ascent plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libxml2-devel, curl-devel +%description ascent +The Ascent plugin reads and parses the statistics page of Ascent, a free and +open-source server software for the game World of Warcraft by Blizzard +Entertainment. +%endif + +%if %{with_bind} +%package bind +Summary: Bind plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libxml2-devel, curl-devel +%description bind +The BIND plugin retrieves this information that's encoded in XML and provided +via HTTP and submits the values to collectd. +%endif +%if %{with_curl} +%package curl +Summary: Curl plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel +%description curl +The cURL plugin uses libcurl to read files and then parses them according to +the configuration. +%endif + +%if %{with_curl_json} +%package curl_json +Summary: Curl_json plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel, yajl-devel +%description curl_json +The cURL-JSON plugin queries JavaScript Object Notation (JSON) data using the +cURL library and parses it according to the user's configuration. +%endif + +%if %{with_curl_xml} +%package curl_xml +Summary: Curl_xml plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel, libxml2-devel +%description curl_xml +The cURL-XML plugin reads files using libcurl and parses it as Extensible +Markup Language (XML). +%endif + +%if %{with_dbi} +%package dbi +Summary: DBI plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libdbi-devel +%description dbi +The DBI plugin uses libdbi, a database abstraction library, to execute SQL +statements on a database and read back the result. +%endif + +%if %{with_dns} +%package dns +Summary: DNS plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release}, libpcap >= 1.0 +BuildRequires: libpcap-devel >= 1.0 +%description dns +The DNS plugin has a similar functionality to dnstop: It uses libpcap to get a +copy of all traffic from/to port UDP/53 (that's the DNS port), interprets the +packets and collects statistics of your DNS traffic. +%endif + +%if %{with_email} %package email -Summary: email-plugin for collectd. +Summary: Email plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, spamassassin +Requires: %{name}%{?_isa} = %{version}-%{release}, spamassassin %description email This plugin collects data provided by spamassassin. +%endif + +%if %{with_gmond} +%package gmond +Summary: Gmond plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: ganglia-devel +%description gmond +The gmond plugin subscribes to a Multicast group to receive data from gmond, +the client daemon of the Ganglia project. +%endif +%if %{with_hddtemp} +%package hddtemp +Summary: Hddtemp plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release}, hddtemp +%description hddtemp +The HDDTemp plugin collects the temperature of hard disks. The temperatures are +provided via SMART and queried by the external hddtemp daemon. +%endif + +%if %{with_ipmi} +%package ipmi +Summary: IPMI plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: OpenIPMI-devel +%description ipmi +The IPMI plugin uses the OpenIPMI library to read hardware sensors from servers +using the Intelligent Platform Management Interface (IPMI). +%endif + +%if %{with_iptables} +%package iptables +Summary: IPtables plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: iptables-devel +%description iptables +The IPtables plugin can gather statistics from your ip_tables based packet +filter (aka. firewall) for both the IPv4 and the IPv6 protocol. It can collect +the byte- and packet-counters of selected rules and submit them to collectd. +%endif + +%if %{with_java} +%package java +Summary: Java plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: java-devel, jpackage-utils +Requires: java, jpackage-utils +%description java +This plugin for collectd allows plugins to be written in Java and executed +in an embedded JVM. +%endif + +%if %{with_libvirt} +%package libvirt +Summary: Libvirt plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libvirt-devel +%description libvirt +This plugin collects information from virtualized guests. +%endif + +%if %{with_memcachec} +%package memcachec +Summary: Memcachec plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libmemcached-devel +%description memcachec +The Memcachec plugin uses libmemcached to read statistics from a Memcached +instance. Note that another plugin, named `memcached', exists and does a +similar job, without requiring the installation of libmemcached. +%endif + +%if %{with_modbus} +%package modbus +Summary: modbus plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libmodbus-devel +%description modbus +The modbus plugin collects values from Modbus/TCP enabled devices +%endif + +%if %{with_mysql} %package mysql -Summary: mysql-module for collectd. +Summary: MySQL plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, mysql +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: mysql-devel %description mysql -MySQL querying plugin. This plugins provides data of issued commands, called +MySQL querying plugin. This plugin provides data of issued commands, called handlers and database traffic. +%endif +%if %{with_netlink} +%package netlink +Summary: netlink plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: iproute-devel +%description netlink +The netlink plugin collects detailed network interface and routing statistics. +%endif + +%if %{with_nginx} %package nginx -Summary: nginx-plugin for collectd. +Summary: Nginx plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, curl +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel %description nginx This plugin gets data provided by nginx. +%endif +%if %{with_notify_desktop} +%package notify_desktop +Summary: Notify_desktop plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libnotify-devel, gtk2-devel +%description notify_desktop +The Notify Desktop plugin uses libnotify to display notifications to the user +via the desktop notification specification, i. e. on an X display. +%endif + +%if %{with_notify_email} +%package notify_email +Summary: Notify_email plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libesmtp-devel +%description notify_email +The Notify Email plugin uses libESMTP to send notifications to a configured +email address. +%endif + +%if %{with_nut} +%package nut +Summary: Nut plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: nut-devel +%description nut +This plugin for collectd provides Network UPS Tools support. +%endif + +%if %{with_perl} +%package perl +Summary: Perl plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) +%if 0%{?rhel} >= 6 +BuildRequires: perl-ExtUtils-Embed +%else +BuildRequires: perl +%endif +%description perl +The Perl plugin embeds a Perl interpreter into collectd and exposes the +application programming interface (API) to Perl-scripts. +%endif + +%if %{with_pinba} +%package pinba +Summary: Pinba plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: protobuf-c-devel +%description pinba +The Pinba plugin receives and dispatches timing values from Pinba, a profiling +extension for PHP. +%endif + +%if %{with_ping} +%package ping +Summary: Ping plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: liboping-devel +%description ping +The Ping plugin measures network latency using ICMP “echo requests”, usually +known as “ping”. +%endif + +%if %{with_postgresql} +%package postgresql +Summary: PostgreSQL plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: postgresql-devel +%description postgresql +The PostgreSQL plugin connects to and executes SQL statements on a PostgreSQL +database. +%endif + +%if %{with_python} +%package python +Summary: Python plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +%if 0%{?rhel} >= 6 +BuildRequires: python-devel +%else +BuildRequires: python26-devel +%endif +%description python +The Python plugin embeds a Python interpreter into collectd and exposes the +application programming interface (API) to Python-scripts. +%endif + +%if %{with_redis} +%package redis +Summary: Redis plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: credis-devel +%description redis +The Redis plugin connects to one or more instances of Redis, a key-value store, +and collects usage information using the credis library. +%endif + +%if %{with_rrdcached} +%package rrdcached +Summary: RRDCached plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release}, rrdtool >= 1.4 +BuildRequires: rrdtool-devel +%description rrdcached +The RRDCacheD plugin connects to the “RRD caching daemon”, rrdcached and +submits updates for RRD files to that daemon. +%endif + +%if %{with_rrdtool} +%package rrdtool +Summary: RRDtool plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: rrdtool-devel +%description rrdtool +The RRDtool plugin writes values to RRD-files using librrd. +%endif + +%if %{with_sensors} %package sensors -Summary: libsensors-module for collectd. +Summary: Sensors plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, lm_sensors +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: lm_sensors-devel %description sensors This plugin for collectd provides querying of sensors supported by lm_sensors. +%endif +%if %{with_snmp} %package snmp -Summary: snmp-module for collectd. +Summary: SNMP plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, net-snmp +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: net-snmp-devel %description snmp This plugin for collectd allows querying of network equipment using SNMP. +%endif -%if %with_java -%package java -Summary: java-module for collectd. +%if %{with_varnish} +%package varnish +Summary: Varnish plugin for collectd Group: System Environment/Daemons -Requires: collectd = %{version}, jdk >= 1.6 -BuildPrereq: jdk >= 1.6 -%description java -This plugin for collectd allows plugins to be written in Java and executed -in an embedded JVM. +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: varnish-libs-devel +%description varnish +The Varnish plugin collects information about Varnish, an HTTP accelerator. +%endif + +%if %{with_write_http} +%package write_http +Summary: Write-HTTP plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: curl-devel +%description write_http +The Write-HTTP plugin sends the values collected by collectd to a web-server +using HTTP POST requests. +%endif + +%if %{with_write_redis} +%package write_redis +Summary: Write-Redis plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: credis-devel +%description write_redis +The Write Redis plugin stores values in Redis, a “data structures server”. %endif +%if %{with_write_riemann} +%package write_riemann +Summary: riemann plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: protobuf-c-devel +%description write_riemann +The riemann plugin submits values to Riemann, an event stream processor. +%endif + +%package collection3 +Summary: Web-based viewer for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: httpd +%description collection3 +collection3 is a graphing front-end for the RRD files created by and filled +with collectd. It is written in Perl and should be run as an CGI-script. +Graphs are generated on-the-fly, so no cron job or similar is necessary. + +%package php-collection +Summary: collect php webfrontent +Group: System Environment/Daemons +Requires: collectd = %{version}-%{release} +Requires: httpd +Requires: php +Requires: php-rrdtool +%description php-collection +PHP graphing frontend for RRD files created by and filled with collectd. + +%package contrib +Summary: Contrib files for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +%description contrib +All the files found under contrib/ in the source tree are bundled in this +package. + +%package -n libcollectdclient +Summary: Collectd client library +Group: System Environment/Daemons +%description -n libcollectdclient +Collectd client library + +%package -n libcollectdclient-devel +Summary: Development files for libcollectdclient +Group: System Environment/Daemons +Requires: pkgconfig +Requires: libcollectdclient%{?_isa} = %{version}-%{release} +%description -n libcollectdclient-devel +Development files for libcollectdclient + + %prep -rm -rf $RPM_BUILD_ROOT -%setup +%setup -q %build -./configure CFLAGS=-"DLT_LAZY_OR_NOW='RTLD_LAZY|RTLD_GLOBAL'" --prefix=%{_prefix} --sbindir=%{_sbindir} --mandir=%{_mandir} --libdir=%{_libdir} --sysconfdir=%{_sysconfdir} \ - %{!?with_java:"--with-java=$JAVA_HOME --enable-java"} \ - --disable-battery -make +%if %{with_aggregation} +%define _with_aggregation --enable-aggregation +%else +%define _with_aggregation --disable-aggregation +%endif + +%if %{with_amqp} +%define _with_amqp --enable-amqp +%else +%define _with_amqp --disable-amqp +%endif + +%if %{with_apache} +%define _with_apache --enable-apache +%else +%define _with_apache --disable-apache +%endif + +%if %{with_apcups} +%define _with_apcups --enable-apcups +%else +%define _with_apcups --disable-apcups +%endif + +%if %{with_apple_sensors} +%define _with_apple_sensors --enable-apple_sensors +%else +%define _with_apple_sensors --disable-apple_sensors +%endif + +%if %{with_ascent} +%define _with_ascent --enable-ascent +%else +%define _with_ascent --disable-ascent +%endif + +%if %{with_battery} +%define _with_battery --enable-battery +%else +%define _with_battery --disable-battery +%endif + +%if %{with_bind} +%define _with_bind --enable-bind +%else +%define _with_bind --disable-bind +%endif + +%if %{with_conntrack} +%define _with_conntrack --enable-conntrack +%else +%define _with_conntrack --disable-conntrack +%endif + +%if %{with_contextswitch} +%define _with_contextswitch --enable-contextswitch +%else +%define _with_contextswitch --disable-contextswitch +%endif + +%if %{with_cpu} +%define _with_cpu --enable-cpu +%else +%define _with_cpu --disable-cpu +%endif + +%if %{with_cpufreq} +%define _with_cpufreq --enable-cpufreq +%else +%define _with_cpufreq --disable-cpufreq +%endif + +%if %{with_csv} +%define _with_csv --enable-csv +%else +%define _with_csv --disable-csv +%endif + +%if %{with_curl} +%define _with_curl --enable-curl +%else +%define _with_curl --disable-curl +%endif + +%if %{with_curl_json} +%define _with_curl_json --enable-curl_json +%else +%define _with_curl_json --disable-curl_json +%endif + +%if %{with_curl_xml} +%define _with_curl_xml --enable-curl_xml +%else +%define _with_curl_xml --disable-curl_xml +%endif + +%if %{with_dbi} +%define _with_dbi --enable-dbi +%else +%define _with_dbi --disable-dbi --without-libdbi +%endif + +%if %{with_df} +%define _with_df --enable-df +%else +%define _with_df --disable-df +%endif + +%if %{with_disk} +%define _with_disk --enable-disk +%else +%define _with_disk --disable-disk +%endif + +%if %{with_dns} +%define _with_dns --enable-dns +%else +%define _with_dns --disable-dns +%endif + +%if %{with_email} +%define _with_email --enable-email +%else +%define _with_email --disable-email +%endif + +%if %{with_entropy} +%define _with_entropy --enable-entropy +%else +%define _with_entropy --disable-entropy +%endif + +%if %{with_ethstat} +%define _with_ethstat --enable-ethstat +%else +%define _with_ethstat --disable-ethstat +%endif + +%if %{with_exec} +%define _with_exec --enable-exec +%else +%define _with_exec --disable-exec +%endif + +%if %{with_filecount} +%define _with_filecount --enable-filecount +%else +%define _with_filecount --disable-filecount +%endif + +%if %{with_fscache} +%define _with_fscache --enable-fscache +%else +%define _with_fscache --disable-fscache +%endif + +%if %{with_gmond} +%define _with_gmond --enable-gmond +%else +%define _with_gmond --disable-gmond +%endif + +%if %{with_hddtemp} +%define _with_hddtemp --enable-hddtemp +%else +%define _with_hddtemp --disable-hddtemp +%endif + +%if %{with_interface} +%define _with_interface --enable-interface +%else +%define _with_interface --disable-interface +%endif + +%if %{with_ipmi} +%define _with_ipmi --enable-ipmi +%else +%define _with_ipmi --disable-ipmi +%endif + +%if %{with_iptables} +%define _with_iptables --enable-iptables +%else +%define _with_iptables --disable-iptables +%endif + +%if %{with_ipvs} +%define _with_ipvs --enable-ipvs +%else +%define _with_ipvs --disable-ipvs +%endif + +%if %{with_irq} +%define _with_irq --enable-irq +%else +%define _with_irq --disable-irq +%endif + +%if %{with_java} +%define _with_java --enable-java --with-java=%{java_home}/ +%else +%define _with_java --disable-java +%endif + +%if %{with_libvirt} +%define _with_libvirt --enable-libvirt +%else +%define _with_libvirt --disable-libvirt +%endif + +%if %{with_load} +%define _with_load --enable-load +%else +%define _with_load --disable-load +%endif + +%if %{with_logfile} +%define _with_logfile --enable-logfile +%else +%define _with_logfile --disable-logfile +%endif + +%if %{with_lpar} +%define _with_lpar --enable-lpar +%else +%define _with_lpar --disable-lpar +%endif + +%if %{with_madwifi} +%define _with_madwifi --enable-madwifi +%else +%define _with_madwifi --disable-madwifi +%endif + +%if %{with_mbmon} +%define _with_mbmon --enable-mbmon +%else +%define _with_mbmon --disable-mbmon +%endif + +%if %{with_md} +%define _with_md --enable-md +%else +%define _with_md --disable-md +%endif + +%if %{with_memcachec} +%define _with_memcachec --enable-memcachec +%else +%define _with_memcachec --disable-memcachec +%endif + +%if %{with_memcached} +%define _with_memcached --enable-memcached +%else +%define _with_memcached --disable-memcached +%endif + +%if %{with_memory} +%define _with_memory --enable-memory +%else +%define _with_memory --disable-memory +%endif + +%if %{with_modbus} +%define _with_modbus --enable-modbus +%else +%define _with_modbus --disable-modbus +%endif + +%if %{with_multimeter} +%define _with_multimeter --enable-multimeter +%else +%define _with_multimeter --disable-multimeter +%endif + +%if %{with_mysql} +%define _with_mysql --enable-mysql +%else +%define _with_mysql --disable-mysql +%endif + +%if %{with_netapp} +%define _with_netapp --enable-netapp +%else +%define _with_netapp --disable-netapp +%endif + +%if %{with_netlink} +%define _with_netlink --enable-netlink +%else +%define _with_netlink --disable-netlink +%endif + +%if %{with_network} +%define _with_network --enable-network +%else +%define _with_network --disable-network +%endif + +%if %{with_nfs} +%define _with_nfs --enable-nfs +%else +%define _with_nfs --disable-nfs +%endif + +%if %{with_nginx} +%define _with_nginx --enable-nginx +%else +%define _with_nginx --disable-nginx +%endif + +%if %{with_notify_desktop} +%define _with_notify_desktop --enable-notify_desktop +%else +%define _with_notify_desktop --disable-notify_desktop +%endif + +%if %{with_notify_email} +%define _with_notify_email --enable-notify_email +%else +%define _with_notify_email --disable-notify_email --without-libesmpt +%endif + +%if %{with_ntpd} +%define _with_ntpd --enable-ntpd +%else +%define _with_ntpd --disable-ntpd +%endif + +%if %{with_numa} +%define _with_numa --enable-numa +%else +%define _with_numa --disable-numa +%endif + +%if %{with_nut} +%define _with_nut --enable-nut +%else +%define _with_nut --disable-nut +%endif + +%if %{with_olsrd} +%define _with_olsrd --enable-olsrd +%else +%define _with_olsrd --disable-olsrd +%endif + +%if %{with_onewire} +%define _with_onewire --enable-onewire +%else +%define _with_onewire --disable-onewire +%endif + +%if %{with_openvpn} +%define _with_openvpn --enable-openvpn +%else +%define _with_openvpn --disable-openvpn +%endif + +%if %{with_oracle} +%define _with_oracle --enable-oracle +%else +%define _with_oracle --disable-oracle +%endif + +%if %{with_perl} +%define _with_perl --enable-perl --with-perl-bindings="INSTALLDIRS=vendor" +%else +%define _with_perl --disable-perl --without-libperl +%endif + +%if %{with_pf} +%define _with_pf --enable-pf +%else +%define _with_pf --disable-pf +%endif + +%if %{with_pinba} +%define _with_pinba --enable-pinba +%else +%define _with_pinba --disable-pinba +%endif + +%if %{with_ping} +%define _with_ping --enable-ping +%else +%define _with_ping --disable-ping +%endif + +%if %{with_postgresql} +%define _with_postgresql --enable-postgresql +%else +%define _with_postgresql --disable-postgresql +%endif + +%if %{with_powerdns} +%define _with_powerdns --enable-powerdns +%else +%define _with_powerdns --disable-powerdns +%endif + +%if %{with_processes} +%define _with_processes --enable-processes +%else +%define _with_processes --disable-processes +%endif + +%if %{with_protocols} +%define _with_protocols --enable-protocols +%else +%define _with_protocols --disable-protocols +%endif + +%if %{with_python} +%if 0%{?rhel} >= 6 +%define _with_python --enable-python +%else +%define _with_python --enable-python --with-python=%{_bindir}/python2.6 +%endif +%else +%define _with_python --disable-python +%endif + +%if %{with_redis} +%define _with_redis --enable-redis +%else +%define _with_redis --disable-redis +%endif + +%if %{with_routeros} +%define _with_routeros --enable-routeros +%else +%define _with_routeros --disable-routeros +%endif + +%if %{with_rrdcached} +%define _with_rrdcached --enable-rrdcached +%else +%define _with_rrdcached --disable-rrdcached +%endif + +%if %{with_rrdtool} +%define _with_rrdtool --enable-rrdtool +%else +%define _with_rrdtool --disable-rrdtool +%endif + +%if %{with_sensors} +%define _with_sensors --enable-sensors +%else +%define _with_sensors --disable-sensors +%endif + +%if %{with_serial} +%define _with_serial --enable-serial +%else +%define _with_serial --disable-serial +%endif + +%if %{with_snmp} +%define _with_snmp --enable-snmp +%else +%define _with_snmp --disable-snmp +%endif + +%if %{with_swap} +%define _with_swap --enable-swap +%else +%define _with_swap --disable-swap +%endif + +%if %{with_syslog} +%define _with_syslog --enable-syslog +%else +%define _with_syslog --disable-syslog +%endif + +%if %{with_table} +%define _with_table --enable-table +%else +%define _with_table --disable-table +%endif + +%if %{with_tail} +%define _with_tail --enable-tail +%else +%define _with_tail --disable-tail +%endif + +%if %{with_tail_csv} +%define _with_tail_csv --enable-tail_csv +%else +%define _with_tail_csv --disable-tail_csv +%endif + +%if %{with_tape} +%define _with_tape --enable-tape +%else +%define _with_tape --disable-tape +%endif + +%if %{with_tcpconns} +%define _with_tcpconns --enable-tcpconns +%else +%define _with_tcpconns --disable-tcpconns +%endif + +%if %{with_teamspeak2} +%define _with_teamspeak2 --enable-teamspeak2 +%else +%define _with_teamspeak2 --disable-teamspeak2 +%endif + +%if %{with_ted} +%define _with_ted --enable-ted +%else +%define _with_ted --disable-ted +%endif + +%if %{with_thermal} +%define _with_thermal --enable-thermal +%else +%define _with_thermal --disable-thermal +%endif + +%if %{with_threshold} +%define _with_threshold --enable-threshold +%else +%define _with_threshold --disable-threshold +%endif + +%if %{with_tokyotyrant} +%define _with_tokyotyrant --enable-tokyotyrant +%else +%define _with_tokyotyrant --disable-tokyotyrant +%endif + +%if %{with_unixsock} +%define _with_unixsock --enable-unixsock +%else +%define _with_unixsock --disable-unixsock +%endif + +%if %{with_uptime} +%define _with_uptime --enable-uptime +%else +%define _with_uptime --disable-uptime +%endif + +%if %{with_users} +%define _with_users --enable-users +%else +%define _with_users --disable-users +%endif + +%if %{with_uuid} +%define _with_uuid --enable-uuid +%else +%define _with_uuid --disable-uuid +%endif + +%if %{with_varnish} +%define _with_varnish --enable-varnish +%else +%define _with_varnish --disable-varnish +%endif + +%if %{with_vmem} +%define _with_vmem --enable-vmem +%else +%define _with_vmem --disable-vmem +%endif + +%if %{with_vserver} +%define _with_vserver --enable-vserver +%else +%define _with_vserver --disable-vserver +%endif + +%if %{with_wireless} +%define _with_wireless --enable-wireless +%else +%define _with_wireless --disable-wireless +%endif + +%if %{with_write_graphite} +%define _with_write_graphite --enable-write_graphite +%else +%define _with_write_graphite --disable-write_graphite +%endif + +%if %{with_write_http} +%define _with_write_http --enable-write_http +%else +%define _with_write_http --disable-write_http +%endif + +%if %{with_write_mongodb} +%define _with_write_mongodb --enable-write_mongodb +%else +%define _with_write_mongodb --disable-write_mongodb --without-libmongoc +%endif + +%if %{with_write_redis} +%define _with_write_redis --enable-write_redis +%else +%define _with_write_redis --disable-write_redis --without-libcredis +%endif + +%if %{with_write_riemann} +%define _with_write_riemann --enable-write_riemann +%else +%define _with_write_riemann --disable-write_riemann +%endif + +%if %{with_xmms} +%define _with_xmms --enable-xmms +%else +%define _with_xmms --disable-xmms +%endif + +%if %{with_zfs_arc} +%define _with_zfs_arc --enable-zfs_arc +%else +%define _with_zfs_arc --disable-zfs_arc +%endif + +%configure CFLAGS="%{optflags} -DLT_LAZY_OR_NOW=\"RTLD_LAZY|RTLD_GLOBAL\"" \ + --disable-static \ + --without-included-ltdl \ + --enable-all-plugins=yes \ + --enable-match_empty_counter \ + --enable-match_hashed \ + --enable-match_regex \ + --enable-match_timediff \ + --enable-match_value \ + --enable-target_notification \ + --enable-target_replace \ + --enable-target_scale \ + --enable-target_set \ + --enable-target_v5upgrade \ + %{?_with_aggregation} \ + %{?_with_amqp} \ + %{?_with_apache} \ + %{?_with_apcups} \ + %{?_with_apple_sensors} \ + %{?_with_ascent} \ + %{?_with_battery} \ + %{?_with_bind} \ + %{?_with_conntrack} \ + %{?_with_contextswitch} \ + %{?_with_cpu} \ + %{?_with_cpufreq} \ + %{?_with_csv} \ + %{?_with_curl} \ + %{?_with_curl_json} \ + %{?_with_curl_xml} \ + %{?_with_dbi} \ + %{?_with_df} \ + %{?_with_disk} \ + %{?_with_dns} \ + %{?_with_email} \ + %{?_with_entropy} \ + %{?_with_ethstat} \ + %{?_with_exec} \ + %{?_with_filecount} \ + %{?_with_fscache} \ + %{?_with_gmond} \ + %{?_with_hddtemp} \ + %{?_with_interface} \ + %{?_with_ipmi} \ + %{?_with_iptables} \ + %{?_with_ipvs} \ + %{?_with_java} \ + %{?_with_libvirt} \ + %{?_with_lpar} \ + %{?_with_memcachec} \ + %{?_with_modbus} \ + %{?_with_multimeter} \ + %{?_with_mysql} \ + %{?_with_netapp} \ + %{?_with_netlink} \ + %{?_with_nginx} \ + %{?_with_notify_desktop} \ + %{?_with_notify_email} \ + %{?_with_nut} \ + %{?_with_onewire} \ + %{?_with_oracle} \ + %{?_with_perl} \ + %{?_with_pf} \ + %{?_with_pinba} \ + %{?_with_ping} \ + %{?_with_postgresql} \ + %{?_with_python} \ + %{?_with_redis} \ + %{?_with_routeros} \ + %{?_with_rrdcached} \ + %{?_with_rrdtool} \ + %{?_with_sensors} \ + %{?_with_snmp} \ + %{?_with_tape} \ + %{?_with_tokyotyrant} \ + %{?_with_varnish} \ + %{?_with_write_http} \ + %{?_with_write_mongodb} \ + %{?_with_write_redis} \ + %{?_with_xmms} \ + %{?_with_zfs_arc} \ + %{?_with_irq} \ + %{?_with_load} \ + %{?_with_logfile} \ + %{?_with_madwifi} \ + %{?_with_mbmon} \ + %{?_with_md} \ + %{?_with_memcached} \ + %{?_with_memory} \ + %{?_with_network} \ + %{?_with_nfs} \ + %{?_with_ntpd} \ + %{?_with_numa} \ + %{?_with_olsrd} \ + %{?_with_openvpn} \ + %{?_with_powerdns} \ + %{?_with_processes} \ + %{?_with_protocols} \ + %{?_with_serial} \ + %{?_with_swap} \ + %{?_with_syslog} \ + %{?_with_table} \ + %{?_with_tail} \ + %{?_with_tail_csv} \ + %{?_with_tcpconns} \ + %{?_with_teamspeak2} \ + %{?_with_ted} \ + %{?_with_thermal} \ + %{?_with_threshold} \ + %{?_with_unixsock} \ + %{?_with_uptime} \ + %{?_with_users} \ + %{?_with_uuid} \ + %{?_with_vmem} \ + %{?_with_vserver} \ + %{?_with_wireless}\ + %{?_with_write_graphite} \ + %{?_with_write_http} \ + %{?_with_write_riemann} + + +%{__make} %{?_smp_mflags} + %install -make install DESTDIR=$RPM_BUILD_ROOT -mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d -mkdir -p $RPM_BUILD_ROOT/var/www/cgi-bin -cp contrib/redhat/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd -cp contrib/collection.cgi $RPM_BUILD_ROOT/var/www/cgi-bin -mkdir -p $RPM_BUILD_ROOT/etc/collectd.d -mkdir -p $RPM_BUILD_ROOT/var/lib/collectd +rm -rf %{buildroot} +%{__make} install DESTDIR=%{buildroot} +%{__install} -Dp -m 0755 contrib/redhat/init.d-collectd %{buildroot}%{_initrddir}/collectd +%{__install} -Dp -m0644 src/collectd.conf %{buildroot}%{_sysconfdir}/collectd.conf +%{__install} -d %{buildroot}%{_sharedstatedir}/collectd/ +%{__install} -d %{buildroot}%{_sysconfdir}/collectd.d/ + +%{__mkdir} -p %{buildroot}%{_localstatedir}/www +%{__mkdir} -p %{buildroot}/%{_sysconfdir}/httpd/conf.d + +%{__mv} contrib/collection3 %{buildroot}%{_localstatedir}/www +%{__mv} contrib/redhat/collection3.conf %{buildroot}/%{_sysconfdir}/httpd/conf.d/ + +%{__mv} contrib/php-collection %{buildroot}%{_localstatedir}/www +%{__mv} contrib/redhat/php-collection.conf %{buildroot}/%{_sysconfdir}/httpd/conf.d/ + ### Clean up docs find contrib/ -type f -exec %{__chmod} a-x {} \; +# *.la files shouldn't be distributed. +rm -f %{buildroot}/%{_libdir}/{collectd/,}*.la + +# Remove Perl hidden .packlist files. +find %{buildroot} -type f -name .packlist -delete +# Remove Perl temporary file perllocal.pod +find %{buildroot} -type f -name perllocal.pod -delete + +%if ! %{with_java} +rm -f %{buildroot}%{_datadir}/collectd/java/collectd-api.jar +rm -f %{buildroot}%{_datadir}/collectd/java/generic-jmx.jar +rm -f %{buildroot}%{_mandir}/man5/collectd-java.5* +%endif + +%if ! %{with_perl} +rm -f %{buildroot}%{_mandir}/man5/collectd-perl.5* +rm -f %{buildroot}%{_mandir}/man3/Collectd::Unixsock.3pm* +rm -fr %{buildroot}/usr/lib/perl5/ +%endif + +%if ! %{with_postgresql} +rm -f %{buildroot}%{_datadir}/collectd/postgresql_default.conf +%endif + +%if ! %{with_python} +rm -f %{buildroot}%{_mandir}/man5/collectd-python.5* +%endif + +%if ! %{with_snmp} +rm -f %{buildroot}%{_mandir}/man5/collectd-snmp.5* +%endif -###Modify Config for Redhat Based Distros -sed -i 's:#BaseDir "/usr/var/lib/collectd":BaseDir "/var/lib/collectd":' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#PIDFile "/usr/var/run/collectd.pid":PIDFile "/var/run/collectd.pid":' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#PluginDir "/usr/lib/collectd":PluginDir "%{_libdir}/collectd":' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#TypesDB "/usr/share/collectd/types.db":TypesDB "/usr/share/collectd/types.db":' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#Interval 10:Interval 30:' $RPM_BUILD_ROOT/etc/collectd.conf -sed -i 's:#ReadThreads 5:ReadThreads 5:' $RPM_BUILD_ROOT/etc/collectd.conf -###Include broken out config directory -echo -e '\nInclude "/etc/collectd.d"' >> $RPM_BUILD_ROOT/etc/collectd.conf - -##Move config contribs -cp contrib/redhat/apache.conf $RPM_BUILD_ROOT/etc/collectd.d/apache.conf -cp contrib/redhat/email.conf $RPM_BUILD_ROOT/etc/collectd.d/email.conf -cp contrib/redhat/sensors.conf $RPM_BUILD_ROOT/etc/collectd.d/sensors.conf -cp contrib/redhat/mysql.conf $RPM_BUILD_ROOT/etc/collectd.d/mysql.conf -cp contrib/redhat/nginx.conf $RPM_BUILD_ROOT/etc/collectd.d/nginx.conf -cp contrib/redhat/snmp.conf $RPM_BUILD_ROOT/etc/collectd.d/snmp.conf %clean -rm -rf $RPM_BUILD_ROOT +rm -rf %{buildroot} %post /sbin/chkconfig --add collectd -/sbin/chkconfig collectd on %preun -if [ "$1" = 0 ]; then - /sbin/chkconfig collectd off - /etc/init.d/collectd stop - /sbin/chkconfig --del collectd +if [ $1 -eq 0 ]; then + /sbin/service collectd stop &>/dev/null + /sbin/chkconfig --del collectd fi -exit 0 %postun -if [ "$1" -ge 1 ]; then - /etc/init.d/collectd restart +if [ $1 -ge 1 ]; then + /sbin/service collectd condrestart &>/dev/null || : fi -exit 0 + +%post -n libcollectdclient -p /sbin/ldconfig +%postun -n libcollectdclient -p /sbin/ldconfig + %files -%defattr(-,root,root) -%doc AUTHORS COPYING ChangeLog INSTALL NEWS README contrib/ -%config %attr(0644,root,root) /etc/collectd.conf -%attr(0755,root,root) /etc/rc.d/init.d/collectd -%attr(0755,root,root) /var/www/cgi-bin/collection.cgi -%attr(0755,root,root) %{_sbindir}/collectd -%attr(0755,root,root) %{_bindir}/collectd-nagios -%attr(0755,root,root) %{_sbindir}/collectdmon -%attr(0644,root,root) %{_mandir}/man1/* -%attr(0644,root,root) %{_mandir}/man5/* -%dir /etc/collectd.d - -# client -%attr(0644,root,root) /usr/include/collectd/client.h -%attr(0644,root,root) /usr/include/collectd/lcc_features.h - -%attr(0644,root,root) %{_libdir}/libcollectdclient.* -%attr(0644,root,root) %{_libdir}/pkgconfig/libcollectdclient.pc - -# macro to grab binaries for a plugin, given a name -%define plugin_macro() \ -%attr(0644,root,root) %{_libdir}/%{name}/%1.a \ -%attr(0644,root,root) %{_libdir}/%{name}/%1.so* \ -%attr(0644,root,root) %{_libdir}/%{name}/%1.la - -%plugin_macro apcups -%plugin_macro ascent -%plugin_macro bind -%plugin_macro conntrack -%plugin_macro contextswitch -%plugin_macro cpufreq -%plugin_macro cpu -%plugin_macro csv -%plugin_macro curl -%plugin_macro df -%plugin_macro disk -%plugin_macro dns -%plugin_macro entropy -%plugin_macro email -%plugin_macro exec -%plugin_macro filecount -%plugin_macro fscache -%plugin_macro hddtemp -%plugin_macro interface -%plugin_macro iptables -%plugin_macro irq -%plugin_macro load -%plugin_macro logfile -%plugin_macro madwifi - -%plugin_macro match_empty_counter -%plugin_macro match_hashed -%plugin_macro match_regex -%plugin_macro match_timediff -%plugin_macro match_value - -%plugin_macro mbmon -%plugin_macro memcached -%plugin_macro memory -%plugin_macro multimeter -%plugin_macro network -%plugin_macro nfs -%plugin_macro ntpd -%plugin_macro openvpn -%plugin_macro olsrd -%plugin_macro perl -%plugin_macro powerdns -%plugin_macro processes -%plugin_macro protocols -%plugin_macro python -%plugin_macro rrdtool -%plugin_macro serial -%plugin_macro sensors -%plugin_macro swap -%plugin_macro syslog -%plugin_macro table -%plugin_macro tail - -%plugin_macro target_notification -%plugin_macro target_replace -%plugin_macro target_scale -%plugin_macro target_set - -%plugin_macro tcpconns -%plugin_macro teamspeak2 -%plugin_macro ted -%plugin_macro thermal -%plugin_macro unixsock -%plugin_macro uptime -%plugin_macro users -%plugin_macro uuid -%plugin_macro vmem -%plugin_macro vserver -%plugin_macro wireless -%plugin_macro write_http - -%attr(0644,root,root) %{_datadir}/%{name}/types.db - -%exclude %{_libdir}/perl5/5.8.8/%{_arch}-linux-thread-multi/perllocal.pod -%attr(0644,root,root) %{_libdir}/perl5/site_perl/5.8.8/%{_arch}-linux-thread-multi/auto/Collectd/.packlist -%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd.pm -%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Unixsock.pm -%attr(0644,root,root) /usr/lib/perl5/site_perl/5.8.8/Collectd/Plugins/OpenVZ.pm -%attr(0644,root,root) /usr/share/man/man3/Collectd::Unixsock.3pm.gz - -%exclude /usr/share/collectd/postgresql_default.conf - -%dir /var/lib/collectd - -%if %with_java -%files java -%attr(0644,root,root) /usr/share/%{name}/java/org/collectd/api/*.class -%attr(0644,root,root) /usr/share/%{name}/java/org/collectd/java/*.class -%plugin_macro java +%doc AUTHORS COPYING ChangeLog README +%config(noreplace) %{_sysconfdir}/collectd.conf +%{_initrddir}/collectd +%{_sbindir}/collectd +%{_bindir}/collectd-nagios +%{_bindir}/collectd-tg +%{_bindir}/collectdctl +%{_sbindir}/collectdmon +%{_datadir}/collectd/types.db +%{_sharedstatedir}/collectd +%{_mandir}/man1/collectd-nagios.1* +%{_mandir}/man1/collectd.1* +%{_mandir}/man1/collectdctl.1* +%{_mandir}/man1/collectdmon.1* +%{_mandir}/man1/collectd-tg.1* +%{_mandir}/man5/collectd-email.5* +%{_mandir}/man5/collectd-exec.5* +%{_mandir}/man5/collectd-threshold.5* +%{_mandir}/man5/collectd-unixsock.5* +%{_mandir}/man5/collectd.conf.5* +%{_mandir}/man5/types.db.5* + +# all plugins bundled with the main collectd package +%{_libdir}/%{name}/match_empty_counter.so +%{_libdir}/%{name}/match_hashed.so +%{_libdir}/%{name}/match_regex.so +%{_libdir}/%{name}/match_timediff.so +%{_libdir}/%{name}/match_value.so +%{_libdir}/%{name}/target_notification.so +%{_libdir}/%{name}/target_replace.so +%{_libdir}/%{name}/target_scale.so +%{_libdir}/%{name}/target_set.so +%{_libdir}/%{name}/target_v5upgrade.so + +%if %{with_aggregation} +%{_libdir}/%{name}/aggregation.so +%endif +%if %{with_apcups} +%{_libdir}/%{name}/apcups.so +%endif +%if %{with_battery} +%{_libdir}/%{name}/battery.so +%endif +%if %{with_conntrack} +%{_libdir}/%{name}/conntrack.so +%endif +%if %{with_contextswitch} +%{_libdir}/%{name}/contextswitch.so +%endif +%if %{with_cpu} +%{_libdir}/%{name}/cpu.so +%endif +%if %{with_cpufreq} +%{_libdir}/%{name}/cpufreq.so +%endif +%if %{with_csv} +%{_libdir}/%{name}/csv.so +%endif +%if %{with_df} +%{_libdir}/%{name}/df.so +%endif +%if %{with_disk} +%{_libdir}/%{name}/disk.so +%endif +%if %{with_ethstat} +%{_libdir}/%{name}/ethstat.so +%endif +%if %{with_entropy} +%{_libdir}/%{name}/entropy.so +%endif +%if %{with_exec} +%{_libdir}/%{name}/exec.so +%endif +%if %{with_filecount} +%{_libdir}/%{name}/filecount.so +%endif +%if %{with_fscache} +%{_libdir}/%{name}/fscache.so +%endif +%if %{with_interface} +%{_libdir}/%{name}/interface.so +%endif +%if %{with_ipvs} +%{_libdir}/%{name}/ipvs.so +%endif +%if %{with_irq} +%{_libdir}/%{name}/irq.so +%endif +%if %{with_load} +%{_libdir}/%{name}/load.so +%endif +%if %{with_logfile} +%{_libdir}/%{name}/logfile.so +%endif +%if %{with_madwifi} +%{_libdir}/%{name}/madwifi.so +%endif +%if %{with_mbmon} +%{_libdir}/%{name}/mbmon.so +%endif +%if %{with_md} +%{_libdir}/%{name}/md.so +%endif +%if %{with_memcached} +%{_libdir}/%{name}/memcached.so +%endif +%if %{with_memory} +%{_libdir}/%{name}/memory.so +%endif +%if %{with_multimeter} +%{_libdir}/%{name}/multimeter.so +%endif +%if %{with_network} +%{_libdir}/%{name}/network.so +%endif +%if %{with_nfs} +%{_libdir}/%{name}/nfs.so +%endif +%if %{with_ntpd} +%{_libdir}/%{name}/ntpd.so +%endif +%if %{with_numa} +%{_libdir}/%{name}/numa.so +%endif +%if %{with_openvpn} +%{_libdir}/%{name}/openvpn.so +%endif +%if %{with_olsrd} +%{_libdir}/%{name}/olsrd.so +%endif +%if %{with_powerdns} +%{_libdir}/%{name}/powerdns.so +%endif +%if %{with_processes} +%{_libdir}/%{name}/processes.so +%endif +%if %{with_protocols} +%{_libdir}/%{name}/protocols.so +%endif +%if %{with_serial} +%{_libdir}/%{name}/serial.so +%endif +%if %{with_swap} +%{_libdir}/%{name}/swap.so +%endif +%if %{with_syslog} +%{_libdir}/%{name}/syslog.so +%endif +%if %{with_table} +%{_libdir}/%{name}/table.so +%endif +%if %{with_tail} +%{_libdir}/%{name}/tail.so +%endif +%if %{with_tail_csv} +%{_libdir}/%{name}/tail_csv.so +%endif +%if %{with_tcpconns} +%{_libdir}/%{name}/tcpconns.so +%endif +%if %{with_teamspeak2} +%{_libdir}/%{name}/teamspeak2.so +%endif +%if %{with_ted} +%{_libdir}/%{name}/ted.so +%endif +%if %{with_thermal} +%{_libdir}/%{name}/thermal.so +%endif +%if %{with_load} +%{_libdir}/%{name}/threshold.so +%endif +%if %{with_unixsock} +%{_libdir}/%{name}/unixsock.so +%endif +%if %{with_uptime} +%{_libdir}/%{name}/uptime.so +%endif +%if %{with_users} +%{_libdir}/%{name}/users.so +%endif +%if %{with_uuid} +%{_libdir}/%{name}/uuid.so +%endif +%if %{with_vmem} +%{_libdir}/%{name}/vmem.so +%endif +%if %{with_vserver} +%{_libdir}/%{name}/vserver.so +%endif +%if %{with_wireless} +%{_libdir}/%{name}/wireless.so +%endif +%if %{with_write_graphite} +%{_libdir}/%{name}/write_graphite.so %endif + +%files -n libcollectdclient-devel +%{_includedir}/collectd/client.h +%{_includedir}/collectd/network.h +%{_includedir}/collectd/network_buffer.h +%{_includedir}/collectd/lcc_features.h +%{_libdir}/pkgconfig/libcollectdclient.pc + +%files -n libcollectdclient +%{_libdir}/libcollectdclient.so +%{_libdir}/libcollectdclient.so.* + +%if %{with_amqp} +%files amqp +%{_libdir}/%{name}/amqp.so +%endif + +%if %{with_apache} %files apache -%config %attr(0644,root,root) /etc/collectd.d/apache.conf -%plugin_macro apache +%{_libdir}/%{name}/apache.so +%endif + +%if %{with_ascent} +%files ascent +%{_libdir}/%{name}/ascent.so +%endif + +%if %{with_bind} +%files bind +%{_libdir}/%{name}/bind.so +%endif + +%if %{with_curl} +%files curl +%{_libdir}/%{name}/curl.so +%endif + +%if %{with_curl_json} +%files curl_json +%{_libdir}/%{name}/curl_json.so +%endif + +%if %{with_curl_xml} +%files curl_xml +%{_libdir}/%{name}/curl_xml.so +%endif + +%if %{with_dns} +%files dns +%{_libdir}/%{name}/dns.so +%endif +%if %{with_dbi} +%files dbi +%{_libdir}/%{name}/dbi.so +%endif + +%if %{with_email} %files email -%attr(0644,root,root) %{_libdir}/%{name}/email.so* -%attr(0644,root,root) %{_libdir}/%{name}/email.la -%config %attr(0644,root,root) /etc/collectd.d/email.conf +%{_libdir}/%{name}/email.so +%endif + +%if %{with_gmond} +%files gmond +%{_libdir}/%{name}/gmond.so +%endif + +%if %{with_hddtemp} +%files hddtemp +%{_libdir}/%{name}/hddtemp.so +%endif + +%if %{with_ipmi} +%files ipmi +%{_libdir}/%{name}/ipmi.so +%endif + +%if %{with_iptables} +%files iptables +%{_libdir}/%{name}/iptables.so +%endif + +%if %{with_java} +%files java +%{_datadir}/collectd/java/collectd-api.jar +%{_datadir}/collectd/java/generic-jmx.jar +%{_libdir}/%{name}/java.so +%{_mandir}/man5/collectd-java.5* +%endif + +%if %{with_libvirt} +%files libvirt +%{_libdir}/%{name}/libvirt.so +%endif +%if %{with_memcachec} +%files memcachec +%{_libdir}/%{name}/memcachec.so +%endif + +%if %{with_modbus} +%files modbus +%{_libdir}/%{name}/modbus.so +%endif + +%if %{with_mysql} %files mysql -%config %attr(0644,root,root) /etc/collectd.d/mysql.conf -%plugin_macro mysql +%{_libdir}/%{name}/mysql.so +%endif + +%if %{with_netlink} +%files netlink +%{_libdir}/%{name}/netlink.so +%endif +%if %{with_nginx} %files nginx -%config %attr(0644,root,root) /etc/collectd.d/nginx.conf -%plugin_macro nginx +%{_libdir}/%{name}/nginx.so +%endif + +%if %{with_notify_desktop} +%files notify_desktop +%{_libdir}/%{name}/notify_desktop.so +%endif + +%if %{with_notify_email} +%files notify_email +%{_libdir}/%{name}/notify_email.so +%endif + +%if %{with_nut} +%files nut +%{_libdir}/%{name}/nut.so +%endif + +%if %{with_perl} +%files perl +%{perl_vendorlib}/Collectd.pm +%{perl_vendorlib}/Collectd/ +%{_mandir}/man3/Collectd::Unixsock.3pm* +%{_mandir}/man5/collectd-perl.5* +%{_libdir}/%{name}/perl.so +%endif + +%if %{with_pinba} +%files pinba +%{_libdir}/%{name}/pinba.so +%endif + +%if %{with_ping} +%files ping +%{_libdir}/%{name}/ping.so +%endif + +%if %{with_postgresql} +%files postgresql +%{_datadir}/collectd/postgresql_default.conf +%{_libdir}/%{name}/postgresql.so +%endif +%if %{with_python} +%files python +%{_mandir}/man5/collectd-python* +%{_libdir}/%{name}/python.so +%endif + +%if %{with_redis} +%files redis +%{_libdir}/%{name}/redis.so +%endif + +%if %{with_rrdcached} +%files rrdcached +%{_libdir}/%{name}/rrdcached.so +%endif + +%if %{with_rrdtool} +%files rrdtool +%{_libdir}/%{name}/rrdtool.so +%endif + +%if %{with_sensors} %files sensors -%attr(0644,root,root) %{_libdir}/%{name}/sensors.so* -%attr(0644,root,root) %{_libdir}/%{name}/sensors.la -%config %attr(0644,root,root) /etc/collectd.d/sensors.conf +%{_libdir}/%{name}/sensors.so +%endif +%if %{with_snmp} %files snmp -%attr(0644,root,root) /etc/collectd.d/snmp.conf -%plugin_macro snmp +%{_mandir}/man5/collectd-snmp.5* +%{_libdir}/%{name}/snmp.so +%endif + +%if %{with_varnish} +%files varnish +%{_libdir}/%{name}/varnish.so +%endif + +%if %{with_write_http} +%files write_http +%{_libdir}/%{name}/write_http.so +%endif + +%if %{with_write_redis} +%files write_redis +%{_libdir}/%{name}/write_redis.so +%endif + +%if %{with_write_riemann} +%files write_riemann +%{_libdir}/%{name}/write_riemann.so +%endif + +%files collection3 +%{_localstatedir}/www/collection3 +%{_sysconfdir}/httpd/conf.d/collection3.conf + +%files php-collection +%{_localstatedir}/www/php-collection +%{_sysconfdir}/httpd/conf.d/php-collection.conf + +%files contrib +%doc contrib/ %changelog -* Tue Jan 04 2010 Rackspace 4.9.0 +* Tue Aug 06 2013 Marc Fournier 5.3.1-1 +- New upstream version +- Added RHEL5 support: + * conditionally disable plugins not building on this platform + * add/specify some build dependencies and options + * replace some RPM macros not available on this platform +- Removed duplicate --enable-aggregation +- Added some comments & usage examples +- Replaced a couple of "Buildrequires" by "BuildRequires" +- Enabled modbus plugin on RHEL6 +- Enabled netlink plugin on RHEL6 and RHEL7 +- Allow perl plugin to build on RHEL5 +- Add support for RHEL7 +- Misc perl-related improvements: + * prevent rpmbuild from extracting dependencies from files in /usr/share/doc + * don't package collection3 and php-collection twice + * keep perl scripts from contrib/ in collectd-contrib + +* Wed Apr 10 2013 Marc Fournier 5.3.0-1 +- New upstream version +- Enabled write_riemann plugin +- Enabled tail_csv plugin +- Installed collectd-tc manpage + +* Fri Jan 11 2013 Marc Fournier 5.2.0-3 +- remove dependency on libstatgrab, which isn't required on linux + +* Thu Jan 03 2013 Marc Fournier 5.2.0-2 +- collection3 and php-collection viewers are now in separate packages + +* Fri Dec 21 2012 Marc Fournier 5.2.0-1 +- New upstream version +- Enabled aggregation plugin +- Installed collectd-tc +- Added network.h and network_buffer.h to libcollectdclient-devel +- Moved libxml2-devel and libcurl-devel BRs to relevant plugins sections +- Moved libcollectdclient.so from libcollectdclient-devel to libcollectdclient +- Added rrdcached and redis plugin descriptions +- Mentioned new pf plugin in disabled plugins list + +* Sun Nov 18 2012 Ruben Kerkhof 5.1.0-3 +- Follow Fedora Packaging Guidelines in java subpackage + +* Sat Nov 17 2012 Ruben Kerkhof 5.1.0-2 +- Move perl stuff to perl_vendorlib +- Replace hardcoded paths with macros +- Remove unneccesary Requires +- Removed .a and .la files +- Some other small cleanups + +* Fri Nov 16 2012 Marc Fournier 5.1.0-1 +- New upstream version +- Changes to support 5.1.0 +- Enabled all buildable plugins based on libraries available on EL6 + EPEL +- All plugins requiring external libraries are now shipped in seperate + packages. +- No longer treat Java plugin as an exception, correctly set $JAVA_HOME during + the build process + ensure build deps are installed. +- Dropped per-plugin configuration files, as they tend to diverge from upstream + defaults. +- Moved perl stuff to /usr/share/perl5/ +- Don't alter Interval and ReadThreads by default, let the user change this + himself. +- Initscript improvements: + * checks configuration before (re)starting, based on debian's initscript + * use /etc/sysconfig instdead of /etc/default + * include optional $ARGS in arguments passed to collectd. +- Drop collection.cgi from main package, as it's been obsoleted by collection3 +- Moved contrib/ to its own package, to avoid cluttering the main package with + non-essential stuff. +- Replaced BuildPrereq by BuildRequires + +* Mon Jan 03 2011 Monetate 5.0.1 +- New upstream version +- Changes to support 5.0.1 + +* Mon Jan 04 2010 Rackspace 4.9.0 - New upstream version - Changes to support 4.9.0 - Added support for Java/GenericJMX plugin @@ -299,20 +2010,20 @@ exit 0 * Wed Jul 25 2007 Kjell Randa 4.0.5 - New major releas -- Changes to support 4.0.5 +- Changes to support 4.0.5 -* Wed Jan 11 2007 Iain Lea 3.11.0-0 +* Thu Jan 11 2007 Iain Lea 3.11.0-0 - fixed spec file to build correctly on fedora core - added improved init.d script to work with chkconfig -- added %post and %postun to call chkconfig automatically +- added %%post and %%postun to call chkconfig automatically * Sun Jul 09 2006 Florian octo Forster 3.10.0-1 - New upstream version -* Tue Jun 25 2006 Florian octo Forster 3.9.4-1 +* Sun Jun 25 2006 Florian octo Forster 3.9.4-1 - New upstream version -* Tue Jun 01 2006 Florian octo Forster 3.9.3-1 +* Thu Jun 01 2006 Florian octo Forster 3.9.3-1 - New upstream version * Tue May 09 2006 Florian octo Forster 3.9.2-1 @@ -328,10 +2039,10 @@ exit 0 - New upstream version - Added the `apache' package. -* Thu Mar 14 2006 Florian octo Forster 3.8.2-1 +* Tue Mar 14 2006 Florian octo Forster 3.8.2-1 - New upstream version -* Thu Mar 13 2006 Florian octo Forster 3.8.1-1 +* Mon Mar 13 2006 Florian octo Forster 3.8.1-1 - New upstream version * Thu Mar 09 2006 Florian octo Forster 3.8.0-1 @@ -368,7 +2079,7 @@ exit 0 * Sat Nov 05 2005 Florian octo Forster 3.3.0-1 - New upstream version -* Tue Oct 26 2005 Florian octo Forster 3.2.0-1 +* Wed Oct 26 2005 Florian octo Forster 3.2.0-1 - New upstream version - Added statement to remove the `*.la' files. This fixes a problem when `Unpackaged files terminate build' is in effect. @@ -385,13 +2096,13 @@ exit 0 * Fri Sep 16 2005 Florian octo Forster 2.1.0-1 - New upstream version -* Mon Sep 10 2005 Florian octo Forster 2.0.0-1 +* Sat Sep 10 2005 Florian octo Forster 2.0.0-1 - New upstream version * Mon Aug 29 2005 Florian octo Forster 1.8.0-1 - New upstream version -* Sun Aug 25 2005 Florian octo Forster 1.7.0-1 +* Thu Aug 25 2005 Florian octo Forster 1.7.0-1 - New upstream version * Sun Aug 21 2005 Florian octo Forster 1.6.0-1 diff --git a/contrib/redhat/collection3.conf b/contrib/redhat/collection3.conf new file mode 100644 index 00000000..91596b4f --- /dev/null +++ b/contrib/redhat/collection3.conf @@ -0,0 +1,5 @@ +Alias /collection3/ /var/www/collection3/ + + Options +Indexes + AllowOverride all + diff --git a/contrib/redhat/email.conf b/contrib/redhat/email.conf deleted file mode 100644 index 6f2cabae..00000000 --- a/contrib/redhat/email.conf +++ /dev/null @@ -1,8 +0,0 @@ -LoadPlugin email -# -# SocketFile "/usr/var/run/collectd-email" -# SocketGroup "collectd" -# SocketPerms "0770" -# MaxConns 5 -# - diff --git a/contrib/redhat/init.d-collectd b/contrib/redhat/init.d-collectd index a60acb39..ec55a52a 100644 --- a/contrib/redhat/init.d-collectd +++ b/contrib/redhat/init.d-collectd @@ -20,15 +20,31 @@ CONFIG=/etc/collectd.conf COLLECTD=/usr/sbin/collectd COLLECTDMONPID=/var/run/collectdmon.pid -if [ -r /etc/default/$prog ]; then - . /etc/default/$prog +if [ -r /etc/sysconfig/$service ]; then + . /etc/sysconfig/$service fi +check_config() { + if test ! -r "$CONFIG"; then + return 2 + fi + if ! $COLLECTD -t -C "$CONFIG"; then + return 1 + fi + return 0 +} + + start () { echo -n $"Starting collectd: " - if [ -r "$CONFIG" ] - then - daemon $prog -P $COLLECTDMONPID -c $COLLECTD -- -C "$CONFIG" + check_config + rc="$?" + if test "$rc" -ne 0; then + RETVAL=6 + echo $"not starting due to configuration error" + failure $"not starting $service due to configuration error" + else + daemon $prog -P $COLLECTDMONPID -c $COLLECTD -- -C "$CONFIG" $ARGS RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$service @@ -53,8 +69,16 @@ case "$1" in status $prog ;; restart|reload) - stop - start + check_config + rc="$?" + if test "$rc" -ne 0; then + RETVAL=6 + echo $"not restarting due to configuration error" + failure $"not restarting $service due to configuration error" + else + stop + start + fi ;; condrestart) [ -f /var/lock/subsys/$prog ] && restart || : diff --git a/contrib/redhat/mysql.conf b/contrib/redhat/mysql.conf deleted file mode 100644 index ad875577..00000000 --- a/contrib/redhat/mysql.conf +++ /dev/null @@ -1,9 +0,0 @@ -LoadPlugin mysql - -# -# Host "database.serv.er" -# User "db_user" -# Password "secret" -# Database "db_name" -# - diff --git a/contrib/redhat/nginx.conf b/contrib/redhat/nginx.conf deleted file mode 100644 index 56ce35da..00000000 --- a/contrib/redhat/nginx.conf +++ /dev/null @@ -1,8 +0,0 @@ -LoadPlugin nginx - -# -# URL "http://localhost/status?auto" -# User "www-user" -# Password "secret" -# CACert "/etc/ssl/ca.crt" -# diff --git a/contrib/redhat/php-collection.conf b/contrib/redhat/php-collection.conf new file mode 100644 index 00000000..88bb6090 --- /dev/null +++ b/contrib/redhat/php-collection.conf @@ -0,0 +1,6 @@ +Alias /php-collection/ /var/www/php-collection/ + + DirectoryIndex index.php + Options -Indexes + AddType application/x-httpd-php .php + diff --git a/contrib/redhat/sensors.conf b/contrib/redhat/sensors.conf deleted file mode 100644 index 82455f86..00000000 --- a/contrib/redhat/sensors.conf +++ /dev/null @@ -1,9 +0,0 @@ -LoadPlugin sensors - -# -# Sensor "it8712-isa-0290/temperature-temp1" -# Sensor "it8712-isa-0290/fanspeed-fan3" -# Sensor "it8712-isa-0290/voltage-in8" -# IgnoreSelected false -# - diff --git a/contrib/redhat/snmp.conf b/contrib/redhat/snmp.conf deleted file mode 100644 index e13833c3..00000000 --- a/contrib/redhat/snmp.conf +++ /dev/null @@ -1,44 +0,0 @@ -LoadPlugin snmp - -# -# -# Type "voltage" -# Table false -# Instance "input_line1" -# Values "SNMPv2-SMI::enterprises.6050.5.4.1.1.2.1" -# -# -# Type "users" -# Table false -# Instance "" -# Values "HOST-RESOURCES-MIB::hrSystemNumUsers.0" -# -# -# Type "if_octets" -# Table true -# Instance "IF-MIB::ifDescr" -# Values "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets" -# -# -# -# Address "192.168.0.2" -# Version 1 -# Community "community_string" -# Collect "std_traffic" -# Inverval 120 -# -# -# Address "192.168.0.42" -# Version 2 -# Community "another_string" -# Collect "std_traffic" "hr_users" -# -# -# Address "192.168.0.3" -# Version 1 -# Community "more_communities" -# Collect "powerplus_voltge_input" -# Interval 300 -# -# - diff --git a/contrib/upstart.collectd.conf b/contrib/upstart.collectd.conf new file mode 100644 index 00000000..1c7fd9c7 --- /dev/null +++ b/contrib/upstart.collectd.conf @@ -0,0 +1,47 @@ +description "start/stop/control collectd" +# http://collectd.org/ +# Upstart is the replacement init system used in Debian, Ubuntu, +# and in Fedora. Refer to http://upstart.ubuntu.com/cookbook/ +# +# Normally this file will live as `/etc/init/collectd.conf` + +usage "initctl collectd" +author "Dave Cottlehuber " +version "1.1" + +# There are a number of alternative start sequences however +# most of those do not work on all Ubuntu flavours and releases. +start on started networking and filesystem +stop on runlevel [!2345] + +# collectd itself will run with reduced privileges, but not +# all plugins will. Test and edit as required. +# An alternative configuration is as a user script in ~/.init/ however +# these cannot be started at boot time by the system without +# arcane trickery. Also a root user will not see these tasks/jobs +# by default. set*id is a reasonable and secure compromise. +#setuid nobody +#setgid nobody + +# Other parameters such as the path to the configuration file +# will have been compiled into the binary. These are trivially +# added as environment variables below, and then into both +# `pre-start` command check before collectd runs, and subsequent +# `exec` command parameters below. Remember that upstart runs all +# shell commands via `sh -e`. +env DAEMON=/usr/sbin/collectd + +# Tell upstart to watch for forking when tracking the pid for us. +expect fork + +# prevent thrashing - 10 restarts in 5 seconds +respawn +respawn limit 10 5 + +# Make a log available in /var/log/upstart/collectd.log +console log + +# The daemon will not start if the configuration is invalid. +pre-start exec $DAEMON -t +# Let's Fork! +exec $DAEMON diff --git a/src/Makefile.am b/src/Makefile.am index 47a9a08a..c24e7380 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,4 @@ SUBDIRS = libcollectdclient -if BUILD_WITH_OWN_LIBIPTC -SUBDIRS += owniptc -endif if BUILD_WITH_OWN_LIBOCONFIG SUBDIRS += liboconfig endif @@ -21,7 +18,7 @@ AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"' AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"' sbin_PROGRAMS = collectd collectdmon -bin_PROGRAMS = collectd-nagios +bin_PROGRAMS = collectd-nagios collectdctl collectd-tg collectd_SOURCES = collectd.c collectd.h \ common.c common.h \ @@ -36,11 +33,12 @@ collectd_SOURCES = collectd.c collectd.h \ utils_ignorelist.c utils_ignorelist.h \ utils_llist.c utils_llist.h \ utils_parse_option.c utils_parse_option.h \ + utils_random.c utils_random.h \ utils_tail_match.c utils_tail_match.h \ utils_match.c utils_match.h \ utils_subst.c utils_subst.h \ utils_tail.c utils_tail.h \ - utils_threshold.c utils_threshold.h \ + utils_time.c utils_time.h \ types_list.c types_list.h collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) @@ -93,6 +91,7 @@ collectdmon_SOURCES = collectdmon.c collectdmon_CPPFLAGS = $(AM_CPPFLAGS) collectd_nagios_SOURCES = collectd-nagios.c +collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd collectd_nagios_LDADD = if BUILD_WITH_LIBSOCKET collectd_nagios_LDADD += -lsocket @@ -104,10 +103,63 @@ endif collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la + +collectdctl_SOURCES = collectdctl.c +collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd +collectdctl_LDADD = +if BUILD_WITH_LIBSOCKET +collectdctl_LDADD += -lsocket +endif +if BUILD_AIX +collectdctl_LDADD += -lm +endif +collectdctl_LDADD += libcollectdclient/libcollectdclient.la +collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la + +collectd_tg_SOURCES = collectd-tg.c \ + utils_heap.c utils_heap.h +collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/src/libcollectdclient/collectd +collectd_tg_LDADD = +if BUILD_WITH_LIBSOCKET +collectd_tg_LDADD += -lsocket +endif +if BUILD_WITH_LIBRT +collectd_tg_LDADD += -lrt +endif +if BUILD_AIX +collectd_tg_LDADD += -lm +endif +collectd_tg_LDADD += libcollectdclient/libcollectdclient.la +collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la + + pkglib_LTLIBRARIES = BUILT_SOURCES = -CLEANFILES = +CLEANFILES = + +if BUILD_PLUGIN_AGGREGATION +pkglib_LTLIBRARIES += aggregation.la +aggregation_la_SOURCES = aggregation.c \ + utils_vl_lookup.c utils_vl_lookup.h +aggregation_la_LDFLAGS = -module -avoid-version +aggregation_la_LIBADD = -lm +collectd_LDADD += "-dlopen" aggregation.la +collectd_DEPENDENCIES += aggregation.la +endif + +if BUILD_PLUGIN_AMQP +pkglib_LTLIBRARIES += amqp.la +amqp_la_SOURCES = amqp.c \ + utils_cmd_putval.c utils_cmd_putval.h \ + utils_format_graphite.c utils_format_graphite.h \ + utils_format_json.c utils_format_json.h +amqp_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBRABBITMQ_LDFLAGS) +amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS) +amqp_la_LIBADD = $(BUILD_WITH_LIBRABBITMQ_LIBS) +collectd_LDADD += "-dlopen" amqp.la +collectd_DEPENDENCIES += amqp.la +endif if BUILD_PLUGIN_APACHE pkglib_LTLIBRARIES += apache.la @@ -139,7 +191,7 @@ if BUILD_PLUGIN_APPLE_SENSORS pkglib_LTLIBRARIES += apple_sensors.la apple_sensors_la_SOURCES = apple_sensors.c apple_sensors_la_LDFLAGS = -module -avoid-version -apple_sensors_la_LIBADD = -lIOKit +apple_sensors_la_LDFLAGS += -framework IOKit collectd_LDADD += "-dlopen" apple_sensors.la collectd_DEPENDENCIES += apple_sensors.la endif @@ -161,7 +213,7 @@ battery_la_SOURCES = battery.c battery_la_LDFLAGS = -module -avoid-version battery_la_LIBADD = if BUILD_WITH_LIBIOKIT -battery_la_LIBADD += -lIOKit +battery_la_LDFLAGS += -framework IOKit endif collectd_LDADD += "-dlopen" battery.la collectd_DEPENDENCIES += battery.la @@ -190,6 +242,10 @@ if BUILD_PLUGIN_CONTEXTSWITCH pkglib_LTLIBRARIES += contextswitch.la contextswitch_la_SOURCES = contextswitch.c contextswitch_la_LDFLAGS = -module -avoid-version +contextswitch_la_LIBADD = +if BUILD_WITH_PERFSTAT +contextswitch_la_LIBADD += -lperfstat +endif collectd_LDADD += "-dlopen" contextswitch.la collectd_DEPENDENCIES += contextswitch.la endif @@ -305,7 +361,7 @@ if BUILD_WITH_LIBDEVINFO disk_la_LIBADD += -ldevinfo endif if BUILD_WITH_LIBIOKIT -disk_la_LIBADD += -lIOKit +disk_la_LDFLAGS += -framework IOKit endif if BUILD_WITH_LIBSTATGRAB disk_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS) @@ -355,6 +411,14 @@ collectd_LDADD += "-dlopen" exec.la collectd_DEPENDENCIES += exec.la endif +if BUILD_PLUGIN_ETHSTAT +pkglib_LTLIBRARIES += ethstat.la +ethstat_la_SOURCES = ethstat.c +ethstat_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" ethstat.la +collectd_DEPENDENCIES += ethstat.la +endif + if BUILD_PLUGIN_FILECOUNT pkglib_LTLIBRARIES += filecount.la filecount_la_SOURCES = filecount.c @@ -413,13 +477,8 @@ if BUILD_PLUGIN_IPTABLES pkglib_LTLIBRARIES += iptables.la iptables_la_SOURCES = iptables.c iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS) -iptables_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBIPTC_LDFLAGS) -if BUILD_WITH_OWN_LIBIPTC -iptables_la_LIBADD = owniptc/libiptc.la -iptables_la_DEPENDENCIES = owniptc/libiptc.la -else -iptables_la_LIBADD = -liptc -endif +iptables_la_LDFLAGS = -module -avoid-version +iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS) collectd_LDADD += "-dlopen" iptables.la collectd_DEPENDENCIES += iptables.la endif @@ -500,6 +559,15 @@ collectd_LDADD += "-dlopen" logfile.la collectd_DEPENDENCIES += logfile.la endif +if BUILD_PLUGIN_LPAR +pkglib_LTLIBRARIES += lpar.la +lpar_la_SOURCES = lpar.c +lpar_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" lpar.la +collectd_DEPENDENCIES += lpar.la +lpar_la_LIBADD = -lperfstat +endif + if BUILD_PLUGIN_MADWIFI pkglib_LTLIBRARIES += madwifi.la madwifi_la_SOURCES = madwifi.c madwifi.h @@ -560,6 +628,14 @@ collectd_LDADD += "-dlopen" mbmon.la collectd_DEPENDENCIES += mbmon.la endif +if BUILD_PLUGIN_MD +pkglib_LTLIBRARIES += md.la +md_la_SOURCES = md.c +md_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" md.la +collectd_DEPENDENCIES += md.la +endif + if BUILD_PLUGIN_MEMCACHEC pkglib_LTLIBRARIES += memcachec.la memcachec_la_SOURCES = memcachec.c @@ -737,6 +813,14 @@ collectd_LDADD += "-dlopen" ntpd.la collectd_DEPENDENCIES += ntpd.la endif +if BUILD_PLUGIN_NUMA +pkglib_LTLIBRARIES += numa.la +numa_la_SOURCES = numa.c +numa_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" numa.la +collectd_DEPENDENCIES += numa.la +endif + if BUILD_PLUGIN_NUT pkglib_LTLIBRARIES += nut.la nut_la_SOURCES = nut.c @@ -807,15 +891,23 @@ perl_la_CFLAGS += -Wno-nonnull endif perl_la_LDFLAGS = -module -avoid-version \ $(PERL_LDFLAGS) +perl_la_LIBADD = $(PERL_LIBS) collectd_LDADD += "-dlopen" perl.la collectd_DEPENDENCIES += perl.la endif +if BUILD_PLUGIN_PF +pkglib_LTLIBRARIES += pf.la +pf_la_SOURCES = pf.c +pf_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" pf.la +collectd_DEPENDENCIES += pf.la +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 +nodist_pinba_la_SOURCES = pinba.pb-c.c pinba.pb-c.h pinba_la_LDFLAGS = -module -avoid-version pinba_la_LIBADD = -lprotobuf-c collectd_LDADD += "-dlopen" pinba.la @@ -886,6 +978,16 @@ collectd_LDADD += "-dlopen" protocols.la collectd_DEPENDENCIES += protocols.la endif +if BUILD_PLUGIN_REDIS +pkglib_LTLIBRARIES += redis.la +redis_la_SOURCES = redis.c +redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS) +redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS) +redis_la_LIBADD = -lcredis +collectd_LDADD += "-dlopen" redis.la +collectd_DEPENDENCIES += redis.la +endif + if BUILD_PLUGIN_ROUTEROS pkglib_LTLIBRARIES += routeros.la routeros_la_SOURCES = routeros.c @@ -1002,6 +1104,14 @@ collectd_LDADD += "-dlopen" tail.la collectd_DEPENDENCIES += tail.la endif +if BUILD_PLUGIN_TAIL_CSV +pkglib_LTLIBRARIES += tail_csv.la +tail_csv_la_SOURCES = tail_csv.c +tail_csv_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" tail_csv.la +collectd_DEPENDENCIES += tail_csv.la +endif + if BUILD_PLUGIN_TAPE pkglib_LTLIBRARIES += tape.la tape_la_SOURCES = tape.c @@ -1043,6 +1153,14 @@ collectd_LDADD += "-dlopen" target_set.la collectd_DEPENDENCIES += target_set.la endif +if BUILD_PLUGIN_TARGET_V5UPGRADE +pkglib_LTLIBRARIES += target_v5upgrade.la +target_v5upgrade_la_SOURCES = target_v5upgrade.c +target_v5upgrade_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" target_v5upgrade.la +collectd_DEPENDENCIES += target_v5upgrade.la +endif + if BUILD_PLUGIN_TCPCONNS pkglib_LTLIBRARIES += tcpconns.la tcpconns_la_SOURCES = tcpconns.c @@ -1079,6 +1197,14 @@ collectd_LDADD += "-dlopen" thermal.la collectd_DEPENDENCIES += thermal.la endif +if BUILD_PLUGIN_THRESHOLD +pkglib_LTLIBRARIES += threshold.la +threshold_la_SOURCES = threshold.c +threshold_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" threshold.la +collectd_DEPENDENCIES += threshold.la +endif + if BUILD_PLUGIN_TOKYOTYRANT pkglib_LTLIBRARIES += tokyotyrant.la tokyotyrant_la_SOURCES = tokyotyrant.c @@ -1097,7 +1223,6 @@ 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 @@ -1116,6 +1241,9 @@ uptime_la_LIBADD = if BUILD_WITH_LIBKSTAT uptime_la_LIBADD += -lkstat endif +if BUILD_WITH_PERFSTAT +uptime_la_LIBADD += -lperfstat +endif collectd_LDADD += "-dlopen" uptime.la collectd_DEPENDENCIES += uptime.la endif @@ -1144,6 +1272,16 @@ collectd_LDADD += "-dlopen" uuid.la collectd_DEPENDENCIES += uuid.la endif +if BUILD_PLUGIN_VARNISH +pkglib_LTLIBRARIES += varnish.la +varnish_la_SOURCES = varnish.c +varnish_la_LDFLAGS = -module -avoid-version +varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS) +varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS) +collectd_LDADD += "-dlopen" varnish.la +collectd_DEPENDENCIES += varnish.la +endif + if BUILD_PLUGIN_VMEM pkglib_LTLIBRARIES += vmem.la vmem_la_SOURCES = vmem.c @@ -1168,6 +1306,16 @@ collectd_LDADD += "-dlopen" wireless.la collectd_DEPENDENCIES += wireless.la endif +if BUILD_PLUGIN_WRITE_GRAPHITE +pkglib_LTLIBRARIES += write_graphite.la +write_graphite_la_SOURCES = write_graphite.c \ + utils_format_graphite.c utils_format_graphite.h \ + utils_format_json.c utils_format_json.h +write_graphite_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" write_graphite.la +collectd_DEPENDENCIES += write_graphite.la +endif + if BUILD_PLUGIN_WRITE_HTTP pkglib_LTLIBRARIES += write_http.la write_http_la_SOURCES = write_http.c \ @@ -1183,6 +1331,36 @@ endif collectd_DEPENDENCIES += write_http.la endif +if BUILD_PLUGIN_WRITE_MONGODB +pkglib_LTLIBRARIES += write_mongodb.la +write_mongodb_la_SOURCES = write_mongodb.c +write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS) +write_mongodb_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBMONGOC_LDFLAGS) +write_mongodb_la_LIBADD = -lmongoc +collectd_LDADD += "-dlopen" write_mongodb.la +collectd_DEPENDENCIES += write_mongodb.la +endif + +if BUILD_PLUGIN_WRITE_REDIS +pkglib_LTLIBRARIES += write_redis.la +write_redis_la_SOURCES = write_redis.c +write_redis_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBCREDIS_LDFLAGS) +write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCREDIS_CPPFLAGS) +write_redis_la_LIBADD = -lcredis +collectd_LDADD += "-dlopen" write_redis.la +collectd_DEPENDENCIES += write_redis.la +endif + +if BUILD_PLUGIN_WRITE_RIEMANN +pkglib_LTLIBRARIES += write_riemann.la +write_riemann_la_SOURCES = write_riemann.c +nodist_write_riemann_la_SOURCES = riemann.pb-c.c riemann.pb-c.h +write_riemann_la_LDFLAGS = -module -avoid-version +write_riemann_la_LIBADD = -lprotobuf-c +collectd_LDADD += "-dlopen" write_riemann.la +collectd_DEPENDENCIES += write_riemann.la +endif + if BUILD_PLUGIN_XMMS pkglib_LTLIBRARIES += xmms.la xmms_la_SOURCES = xmms.c @@ -1209,22 +1387,26 @@ dist_man_MANS = collectd.1 \ collectd.conf.5 \ collectd-email.5 \ collectd-exec.5 \ + collectdctl.1 \ collectd-java.5 \ collectdmon.1 \ collectd-nagios.1 \ collectd-perl.5 \ collectd-python.5 \ collectd-snmp.5 \ + collectd-tg.1 \ + collectd-threshold.5 \ collectd-unixsock.5 \ types.db.5 #collectd_1_SOURCES = collectd.pod -EXTRA_DIST = types.db pinba.proto +EXTRA_DIST = types.db EXTRA_DIST += collectd.conf.pod \ collectd-email.pod \ collectd-exec.pod \ + collectdctl.pod \ collectd-java.pod \ collectdmon.pod \ collectd-nagios.pod \ @@ -1232,6 +1414,8 @@ EXTRA_DIST += collectd.conf.pod \ collectd-python.pod \ collectd.pod \ collectd-snmp.pod \ + collectd-tg.pod \ + collectd-threshold.pod \ collectd-unixsock.pod \ postgresql_default.conf \ types.db.pod @@ -1252,8 +1436,26 @@ EXTRA_DIST += collectd.conf.pod \ echo "$@ has some POD errors!"; false; \ fi +# Protocol buffer for the "pinba" plugin. +EXTRA_DIST += pinba.proto +if HAVE_PROTOC_C +CLEANFILES += pinba.pb-c.c pinba.pb-c.h +BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h + pinba.pb-c.c pinba.pb-c.h: pinba.proto - protoc-c --c_out $(builddir) pinba.proto + protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto +endif + +# Protocol buffer for the "write_riemann" plugin. +EXTRA_DIST += riemann.proto +if HAVE_PROTOC_C +CLEANFILES += riemann.pb-c.c riemann.pb-c.h + +BUILT_SOURCES += riemann.pb-c.c riemann.pb-c.h + +riemann.pb-c.c riemann.pb-c.h: riemann.proto + protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto +endif install-exec-hook: $(mkinstalldirs) $(DESTDIR)$(sysconfdir) @@ -1272,3 +1474,16 @@ uninstall-hook: rm -f $(DESTDIR)$(pkgdatadir)/types.db; rm -f $(DESTDIR)$(sysconfdir)/collectd.conf rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf; + +if BUILD_FEATURE_DEBUG +bin_PROGRAMS += utils_vl_lookup_test +utils_vl_lookup_test_SOURCES = utils_vl_lookup_test.c \ + utils_vl_lookup.h utils_vl_lookup.c \ + utils_avltree.c utils_avltree.h \ + common.h + +utils_vl_lookup_test_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL) -DBUILD_TEST=1 +utils_vl_lookup_test_CFLAGS = $(AM_CFLAGS) +utils_vl_lookup_test_LDFLAGS = -export-dynamic +utils_vl_lookup_test_LDADD = +endif diff --git a/src/aggregation.c b/src/aggregation.c new file mode 100644 index 00000000..8175c66c --- /dev/null +++ b/src/aggregation.c @@ -0,0 +1,790 @@ +/** + * collectd - src/aggregation.c + * Copyright (C) 2012 Florian Forster + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Florian Forster + **/ + +#include "collectd.h" + +#include + +#include "plugin.h" +#include "common.h" +#include "configfile.h" +#include "meta_data.h" +#include "utils_cache.h" /* for uc_get_rate() */ +#include "utils_subst.h" +#include "utils_vl_lookup.h" + +#define AGG_MATCHES_ALL(str) (strcmp ("/.*/", str) == 0) +#define AGG_FUNC_PLACEHOLDER "%{aggregation}" + +struct aggregation_s /* {{{ */ +{ + identifier_t ident; + unsigned int group_by; + + unsigned int regex_fields; + + char *set_host; + char *set_plugin; + char *set_plugin_instance; + char *set_type_instance; + + _Bool calc_num; + _Bool calc_sum; + _Bool calc_average; + _Bool calc_min; + _Bool calc_max; + _Bool calc_stddev; +}; /* }}} */ +typedef struct aggregation_s aggregation_t; + +struct agg_instance_s; +typedef struct agg_instance_s agg_instance_t; +struct agg_instance_s /* {{{ */ +{ + pthread_mutex_t lock; + identifier_t ident; + + int ds_type; + + derive_t num; + gauge_t sum; + gauge_t squares_sum; + + gauge_t min; + gauge_t max; + + rate_to_value_state_t *state_num; + rate_to_value_state_t *state_sum; + rate_to_value_state_t *state_average; + rate_to_value_state_t *state_min; + rate_to_value_state_t *state_max; + rate_to_value_state_t *state_stddev; + + agg_instance_t *next; +}; /* }}} */ + +static lookup_t *lookup = NULL; + +static pthread_mutex_t agg_instance_list_lock = PTHREAD_MUTEX_INITIALIZER; +static agg_instance_t *agg_instance_list_head = NULL; + +static _Bool agg_is_regex (char const *str) /* {{{ */ +{ + size_t len; + + if (str == NULL) + return (0); + + len = strlen (str); + if (len < 3) + return (0); + + if ((str[0] == '/') && (str[len - 1] == '/')) + return (1); + else + return (0); +} /* }}} _Bool agg_is_regex */ + +static void agg_destroy (aggregation_t *agg) /* {{{ */ +{ + sfree (agg); +} /* }}} void agg_destroy */ + +/* Frees all dynamically allocated memory within the instance. */ +static void agg_instance_destroy (agg_instance_t *inst) /* {{{ */ +{ + if (inst == NULL) + return; + + /* Remove this instance from the global list of instances. */ + pthread_mutex_lock (&agg_instance_list_lock); + if (agg_instance_list_head == inst) + agg_instance_list_head = inst->next; + else if (agg_instance_list_head != NULL) + { + agg_instance_t *prev = agg_instance_list_head; + while ((prev != NULL) && (prev->next != inst)) + prev = prev->next; + if (prev != NULL) + prev->next = inst->next; + } + pthread_mutex_unlock (&agg_instance_list_lock); + + sfree (inst->state_num); + sfree (inst->state_sum); + sfree (inst->state_average); + sfree (inst->state_min); + sfree (inst->state_max); + sfree (inst->state_stddev); + + memset (inst, 0, sizeof (*inst)); + inst->ds_type = -1; + inst->min = NAN; + inst->max = NAN; +} /* }}} void agg_instance_destroy */ + +static int agg_instance_create_name (agg_instance_t *inst, /* {{{ */ + value_list_t const *vl, aggregation_t const *agg) +{ +#define COPY_FIELD(buffer, buffer_size, field, group_mask, all_value) do { \ + if (agg->set_ ## field != NULL) \ + sstrncpy (buffer, agg->set_ ## field, buffer_size); \ + else if ((agg->regex_fields & group_mask) \ + && (agg->group_by & group_mask)) \ + sstrncpy (buffer, vl->field, buffer_size); \ + else if ((agg->regex_fields & group_mask) \ + && (AGG_MATCHES_ALL (agg->ident.field))) \ + sstrncpy (buffer, all_value, buffer_size); \ + else \ + sstrncpy (buffer, agg->ident.field, buffer_size); \ +} while (0) + + /* Host */ + COPY_FIELD (inst->ident.host, sizeof (inst->ident.host), + host, LU_GROUP_BY_HOST, "global"); + + /* Plugin */ + if (agg->set_plugin != NULL) + sstrncpy (inst->ident.plugin, agg->set_plugin, + sizeof (inst->ident.plugin)); + else + sstrncpy (inst->ident.plugin, "aggregation", sizeof (inst->ident.plugin)); + + /* Plugin instance */ + if (agg->set_plugin_instance != NULL) + sstrncpy (inst->ident.plugin_instance, agg->set_plugin_instance, + sizeof (inst->ident.plugin_instance)); + else + { + char tmp_plugin[DATA_MAX_NAME_LEN]; + char tmp_plugin_instance[DATA_MAX_NAME_LEN] = ""; + + if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) + && (agg->group_by & LU_GROUP_BY_PLUGIN)) + sstrncpy (tmp_plugin, vl->plugin, sizeof (tmp_plugin)); + else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN) + && (AGG_MATCHES_ALL (agg->ident.plugin))) + sstrncpy (tmp_plugin, "", sizeof (tmp_plugin)); + else + sstrncpy (tmp_plugin, agg->ident.plugin, sizeof (tmp_plugin)); + + if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) + && (agg->group_by & LU_GROUP_BY_PLUGIN_INSTANCE)) + sstrncpy (tmp_plugin_instance, vl->plugin_instance, + sizeof (tmp_plugin_instance)); + else if ((agg->regex_fields & LU_GROUP_BY_PLUGIN_INSTANCE) + && (AGG_MATCHES_ALL (agg->ident.plugin_instance))) + sstrncpy (tmp_plugin_instance, "", sizeof (tmp_plugin_instance)); + else + sstrncpy (tmp_plugin_instance, agg->ident.plugin_instance, + sizeof (tmp_plugin_instance)); + + if ((strcmp ("", tmp_plugin) == 0) + && (strcmp ("", tmp_plugin_instance) == 0)) + sstrncpy (inst->ident.plugin_instance, AGG_FUNC_PLACEHOLDER, + sizeof (inst->ident.plugin_instance)); + else if (strcmp ("", tmp_plugin) != 0) + ssnprintf (inst->ident.plugin_instance, + sizeof (inst->ident.plugin_instance), + "%s-%s", tmp_plugin, AGG_FUNC_PLACEHOLDER); + else if (strcmp ("", tmp_plugin_instance) != 0) + ssnprintf (inst->ident.plugin_instance, + sizeof (inst->ident.plugin_instance), + "%s-%s", tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); + else + ssnprintf (inst->ident.plugin_instance, + sizeof (inst->ident.plugin_instance), + "%s-%s-%s", tmp_plugin, tmp_plugin_instance, AGG_FUNC_PLACEHOLDER); + } + + /* Type */ + sstrncpy (inst->ident.type, agg->ident.type, sizeof (inst->ident.type)); + + /* Type instance */ + COPY_FIELD (inst->ident.type_instance, sizeof (inst->ident.type_instance), + type_instance, LU_GROUP_BY_TYPE_INSTANCE, ""); + +#undef COPY_FIELD + + return (0); +} /* }}} int agg_instance_create_name */ + +/* Create a new aggregation instance. */ +static agg_instance_t *agg_instance_create (data_set_t const *ds, /* {{{ */ + value_list_t const *vl, aggregation_t *agg) +{ + agg_instance_t *inst; + + DEBUG ("aggregation plugin: Creating new instance."); + + inst = malloc (sizeof (*inst)); + if (inst == NULL) + { + ERROR ("aggregation plugin: malloc() failed."); + return (NULL); + } + memset (inst, 0, sizeof (*inst)); + pthread_mutex_init (&inst->lock, /* attr = */ NULL); + + inst->ds_type = ds->ds[0].type; + + agg_instance_create_name (inst, vl, agg); + + inst->min = NAN; + inst->max = NAN; + +#define INIT_STATE(field) do { \ + inst->state_ ## field = NULL; \ + if (agg->calc_ ## field) { \ + inst->state_ ## field = malloc (sizeof (*inst->state_ ## field)); \ + if (inst->state_ ## field == NULL) { \ + agg_instance_destroy (inst); \ + ERROR ("aggregation plugin: malloc() failed."); \ + return (NULL); \ + } \ + memset (inst->state_ ## field, 0, sizeof (*inst->state_ ## field)); \ + } \ +} while (0) + + INIT_STATE (num); + INIT_STATE (sum); + INIT_STATE (average); + INIT_STATE (min); + INIT_STATE (max); + INIT_STATE (stddev); + +#undef INIT_STATE + + pthread_mutex_lock (&agg_instance_list_lock); + inst->next = agg_instance_list_head; + agg_instance_list_head = inst; + pthread_mutex_unlock (&agg_instance_list_lock); + + return (inst); +} /* }}} agg_instance_t *agg_instance_create */ + +/* Update the num, sum, min, max, ... fields of the aggregation instance, if + * the rate of the value list is available. Value lists with more than one data + * source are not supported and will return an error. Returns zero on success + * and non-zero otherwise. */ +static int agg_instance_update (agg_instance_t *inst, /* {{{ */ + data_set_t const *ds, value_list_t const *vl) +{ + gauge_t *rate; + + if (ds->ds_num != 1) + { + ERROR ("aggregation plugin: The \"%s\" type (data set) has more than one " + "data source. This is currently not supported by this plugin. " + "Sorry.", ds->type); + return (EINVAL); + } + + rate = uc_get_rate (ds, vl); + if (rate == NULL) + { + char ident[6 * DATA_MAX_NAME_LEN]; + FORMAT_VL (ident, sizeof (ident), vl); + ERROR ("aggregation plugin: Unable to read the current rate of \"%s\".", + ident); + return (ENOENT); + } + + if (isnan (rate[0])) + { + sfree (rate); + return (0); + } + + pthread_mutex_lock (&inst->lock); + + inst->num++; + inst->sum += rate[0]; + inst->squares_sum += (rate[0] * rate[0]); + + if (isnan (inst->min) || (inst->min > rate[0])) + inst->min = rate[0]; + if (isnan (inst->max) || (inst->max < rate[0])) + inst->max = rate[0]; + + pthread_mutex_unlock (&inst->lock); + + sfree (rate); + return (0); +} /* }}} int agg_instance_update */ + +static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */ + char const *func, gauge_t rate, rate_to_value_state_t *state, + value_list_t *vl, char const *pi_prefix, cdtime_t t) +{ + value_t v; + int status; + + if (pi_prefix[0] != 0) + subst_string (vl->plugin_instance, sizeof (vl->plugin_instance), + pi_prefix, AGG_FUNC_PLACEHOLDER, func); + else + sstrncpy (vl->plugin_instance, func, sizeof (vl->plugin_instance)); + + memset (&v, 0, sizeof (v)); + status = rate_to_value (&v, rate, state, inst->ds_type, t); + if (status != 0) + { + /* If this is the first iteration and rate_to_value() was asked to return a + * COUNTER or a DERIVE, it will return EAGAIN. Catch this and handle + * gracefully. */ + if (status == EAGAIN) + return (0); + + WARNING ("aggregation plugin: rate_to_value failed with status %i.", + status); + return (-1); + } + + vl->values = &v; + vl->values_len = 1; + + plugin_dispatch_values (vl); + + vl->values = NULL; + vl->values_len = 0; + + return (0); +} /* }}} int agg_instance_read_func */ + +static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */ +{ + value_list_t vl = VALUE_LIST_INIT; + + /* Pre-set all the fields in the value list that will not change per + * aggregation type (sum, average, ...). The struct will be re-used and must + * therefore be dispatched using the "secure" function. */ + + vl.time = t; + vl.interval = 0; + + vl.meta = meta_data_create (); + if (vl.meta == NULL) + { + ERROR ("aggregation plugin: meta_data_create failed."); + return (-1); + } + meta_data_add_boolean (vl.meta, "aggregation:created", 1); + + sstrncpy (vl.host, inst->ident.host, sizeof (vl.host)); + sstrncpy (vl.plugin, inst->ident.plugin, sizeof (vl.plugin)); + sstrncpy (vl.type, inst->ident.type, sizeof (vl.type)); + sstrncpy (vl.type_instance, inst->ident.type_instance, + sizeof (vl.type_instance)); + +#define READ_FUNC(func, rate) do { \ + if (inst->state_ ## func != NULL) { \ + agg_instance_read_func (inst, #func, rate, \ + inst->state_ ## func, &vl, inst->ident.plugin_instance, t); \ + } \ +} while (0) + + pthread_mutex_lock (&inst->lock); + + READ_FUNC (num, (gauge_t) inst->num); + + /* All other aggregations are only defined when there have been any values + * at all. */ + if (inst->num > 0) + { + READ_FUNC (sum, inst->sum); + READ_FUNC (average, (inst->sum / ((gauge_t) inst->num))); + READ_FUNC (min, inst->min); + READ_FUNC (max, inst->max); + READ_FUNC (stddev, sqrt((((gauge_t) inst->num) * inst->squares_sum) + - (inst->sum * inst->sum)) / ((gauge_t) inst->num)); + } + + /* Reset internal state. */ + inst->num = 0; + inst->sum = 0.0; + inst->squares_sum = 0.0; + inst->min = NAN; + inst->max = NAN; + + pthread_mutex_unlock (&inst->lock); + + meta_data_destroy (vl.meta); + vl.meta = NULL; + + return (0); +} /* }}} int agg_instance_read */ + +/* lookup_class_callback_t for utils_vl_lookup */ +static void *agg_lookup_class_callback ( /* {{{ */ + data_set_t const *ds, value_list_t const *vl, void *user_class) +{ + return (agg_instance_create (ds, vl, (aggregation_t *) user_class)); +} /* }}} void *agg_class_callback */ + +/* lookup_obj_callback_t for utils_vl_lookup */ +static int agg_lookup_obj_callback (data_set_t const *ds, /* {{{ */ + value_list_t const *vl, + __attribute__((unused)) void *user_class, + void *user_obj) +{ + return (agg_instance_update ((agg_instance_t *) user_obj, ds, vl)); +} /* }}} int agg_lookup_obj_callback */ + +/* lookup_free_class_callback_t for utils_vl_lookup */ +static void agg_lookup_free_class_callback (void *user_class) /* {{{ */ +{ + agg_destroy ((aggregation_t *) user_class); +} /* }}} void agg_lookup_free_class_callback */ + +/* lookup_free_obj_callback_t for utils_vl_lookup */ +static void agg_lookup_free_obj_callback (void *user_obj) /* {{{ */ +{ + agg_instance_destroy ((agg_instance_t *) user_obj); +} /* }}} void agg_lookup_free_obj_callback */ + +/* + * + * + * Plugin "cpu" + * Type "cpu" + * + * GroupBy Host + * GroupBy TypeInstance + * + * CalculateNum true + * CalculateSum true + * CalculateAverage true + * CalculateMinimum true + * CalculateMaximum true + * CalculateStddev true + * + * + */ +static int agg_config_handle_group_by (oconfig_item_t const *ci, /* {{{ */ + aggregation_t *agg) +{ + int i; + + for (i = 0; i < ci->values_num; i++) + { + char const *value; + + if (ci->values[i].type != OCONFIG_TYPE_STRING) + { + ERROR ("aggregation plugin: Argument %i of the \"GroupBy\" option " + "is not a string.", i + 1); + continue; + } + + value = ci->values[i].value.string; + + if (strcasecmp ("Host", value) == 0) + agg->group_by |= LU_GROUP_BY_HOST; + else if (strcasecmp ("Plugin", value) == 0) + agg->group_by |= LU_GROUP_BY_PLUGIN; + else if (strcasecmp ("PluginInstance", value) == 0) + agg->group_by |= LU_GROUP_BY_PLUGIN_INSTANCE; + else if (strcasecmp ("TypeInstance", value) == 0) + agg->group_by |= LU_GROUP_BY_TYPE_INSTANCE; + else if (strcasecmp ("Type", value) == 0) + ERROR ("aggregation plugin: Grouping by type is not supported."); + else + WARNING ("aggregation plugin: The \"%s\" argument to the \"GroupBy\" " + "option is invalid and will be ignored.", value); + } /* for (ci->values) */ + + return (0); +} /* }}} int agg_config_handle_group_by */ + +static int agg_config_aggregation (oconfig_item_t *ci) /* {{{ */ +{ + aggregation_t *agg; + _Bool is_valid; + int status; + int i; + + agg = malloc (sizeof (*agg)); + if (agg == NULL) + { + ERROR ("aggregation plugin: malloc failed."); + return (-1); + } + memset (agg, 0, sizeof (*agg)); + + sstrncpy (agg->ident.host, "/.*/", sizeof (agg->ident.host)); + sstrncpy (agg->ident.plugin, "/.*/", sizeof (agg->ident.plugin)); + sstrncpy (agg->ident.plugin_instance, "/.*/", + sizeof (agg->ident.plugin_instance)); + sstrncpy (agg->ident.type, "/.*/", sizeof (agg->ident.type)); + sstrncpy (agg->ident.type_instance, "/.*/", + sizeof (agg->ident.type_instance)); + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Host", child->key) == 0) + cf_util_get_string_buffer (child, agg->ident.host, + sizeof (agg->ident.host)); + else if (strcasecmp ("Plugin", child->key) == 0) + cf_util_get_string_buffer (child, agg->ident.plugin, + sizeof (agg->ident.plugin)); + else if (strcasecmp ("PluginInstance", child->key) == 0) + cf_util_get_string_buffer (child, agg->ident.plugin_instance, + sizeof (agg->ident.plugin_instance)); + else if (strcasecmp ("Type", child->key) == 0) + cf_util_get_string_buffer (child, agg->ident.type, + sizeof (agg->ident.type)); + else if (strcasecmp ("TypeInstance", child->key) == 0) + cf_util_get_string_buffer (child, agg->ident.type_instance, + sizeof (agg->ident.type_instance)); + else if (strcasecmp ("SetHost", child->key) == 0) + cf_util_get_string (child, &agg->set_host); + else if (strcasecmp ("SetPlugin", child->key) == 0) + cf_util_get_string (child, &agg->set_plugin); + else if (strcasecmp ("SetPluginInstance", child->key) == 0) + cf_util_get_string (child, &agg->set_plugin_instance); + else if (strcasecmp ("SetTypeInstance", child->key) == 0) + cf_util_get_string (child, &agg->set_type_instance); + else if (strcasecmp ("GroupBy", child->key) == 0) + agg_config_handle_group_by (child, agg); + else if (strcasecmp ("CalculateNum", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_num); + else if (strcasecmp ("CalculateSum", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_sum); + else if (strcasecmp ("CalculateAverage", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_average); + else if (strcasecmp ("CalculateMinimum", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_min); + else if (strcasecmp ("CalculateMaximum", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_max); + else if (strcasecmp ("CalculateStddev", child->key) == 0) + cf_util_get_boolean (child, &agg->calc_stddev); + else + WARNING ("aggregation plugin: The \"%s\" key is not allowed inside " + " blocks and will be ignored.", child->key); + } + + if (agg_is_regex (agg->ident.host)) + agg->regex_fields |= LU_GROUP_BY_HOST; + if (agg_is_regex (agg->ident.plugin)) + agg->regex_fields |= LU_GROUP_BY_PLUGIN; + if (agg_is_regex (agg->ident.plugin_instance)) + agg->regex_fields |= LU_GROUP_BY_PLUGIN_INSTANCE; + if (agg_is_regex (agg->ident.type_instance)) + agg->regex_fields |= LU_GROUP_BY_TYPE_INSTANCE; + + /* Sanity checking */ + is_valid = 1; + if (strcmp ("/.*/", agg->ident.type) == 0) /* {{{ */ + { + ERROR ("aggregation plugin: It appears you did not specify the required " + "\"Type\" option in this aggregation. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); + is_valid = 0; + } + else if (strchr (agg->ident.type, '/') != NULL) + { + ERROR ("aggregation plugin: The \"Type\" may not contain the '/' " + "character. Especially, it may not be a regex. The current " + "value is \"%s\".", agg->ident.type); + is_valid = 0; + } /* }}} */ + + /* Check that there is at least one regex field without a grouping. {{{ */ + if ((agg->regex_fields & ~agg->group_by) == 0) + { + ERROR ("aggregation plugin: An aggregation must contain at least one " + "wildcard. This is achieved by leaving at least one of the \"Host\", " + "\"Plugin\", \"PluginInstance\" and \"TypeInstance\" options blank " + "or using a regular expression and not grouping by that field. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); + is_valid = 0; + } /* }}} */ + + /* Check that all grouping fields are regular expressions. {{{ */ + if (agg->group_by & ~agg->regex_fields) + { + ERROR ("aggregation plugin: Only wildcard fields (fields for which a " + "regular expression is configured or which are left blank) can be " + "specified in the \"GroupBy\" option. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); + is_valid = 0; + } /* }}} */ + + if (!agg->calc_num && !agg->calc_sum && !agg->calc_average /* {{{ */ + && !agg->calc_min && !agg->calc_max && !agg->calc_stddev) + { + ERROR ("aggregation plugin: No aggregation function has been specified. " + "Without this, I don't know what I should be calculating. " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); + is_valid = 0; + } /* }}} */ + + if (!is_valid) /* {{{ */ + { + sfree (agg); + return (-1); + } /* }}} */ + + status = lookup_add (lookup, &agg->ident, agg->group_by, agg); + if (status != 0) + { + ERROR ("aggregation plugin: lookup_add failed with status %i.", status); + sfree (agg); + return (-1); + } + + DEBUG ("aggregation plugin: Successfully added aggregation: " + "(Host \"%s\", Plugin \"%s\", PluginInstance \"%s\", " + "Type \"%s\", TypeInstance \"%s\")", + agg->ident.host, agg->ident.plugin, agg->ident.plugin_instance, + agg->ident.type, agg->ident.type_instance); + return (0); +} /* }}} int agg_config_aggregation */ + +static int agg_config (oconfig_item_t *ci) /* {{{ */ +{ + int i; + + pthread_mutex_lock (&agg_instance_list_lock); + + if (lookup == NULL) + { + lookup = lookup_create (agg_lookup_class_callback, + agg_lookup_obj_callback, + agg_lookup_free_class_callback, + agg_lookup_free_obj_callback); + if (lookup == NULL) + { + pthread_mutex_unlock (&agg_instance_list_lock); + ERROR ("aggregation plugin: lookup_create failed."); + return (-1); + } + } + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Aggregation", child->key) == 0) + agg_config_aggregation (child); + else + WARNING ("aggregation plugin: The \"%s\" key is not allowed inside " + " blocks and will be ignored.", child->key); + } + + pthread_mutex_unlock (&agg_instance_list_lock); + + return (0); +} /* }}} int agg_config */ + +static int agg_read (void) /* {{{ */ +{ + agg_instance_t *this; + cdtime_t t; + int success; + + t = cdtime (); + success = 0; + + pthread_mutex_lock (&agg_instance_list_lock); + + /* agg_instance_list_head only holds data, after the "write" callback has + * been called with a matching value list at least once. So on startup, + * there's a race between the aggregations read() and write() callback. If + * the read() callback is called first, agg_instance_list_head is NULL and + * "success" may be zero. This is expected and should not result in an error. + * Therefore we need to handle this case separately. */ + if (agg_instance_list_head == NULL) + { + pthread_mutex_unlock (&agg_instance_list_lock); + return (0); + } + + for (this = agg_instance_list_head; this != NULL; this = this->next) + { + int status; + + status = agg_instance_read (this, t); + if (status != 0) + WARNING ("aggregation plugin: Reading an aggregation instance " + "failed with status %i.", status); + else + success++; + } + + pthread_mutex_unlock (&agg_instance_list_lock); + + return ((success > 0) ? 0 : -1); +} /* }}} int agg_read */ + +static int agg_write (data_set_t const *ds, value_list_t const *vl, /* {{{ */ + __attribute__((unused)) user_data_t *user_data) +{ + _Bool created_by_aggregation = 0; + int status; + + /* Ignore values that were created by the aggregation plugin to avoid weird + * effects. */ + (void) meta_data_get_boolean (vl->meta, "aggregation:created", + &created_by_aggregation); + if (created_by_aggregation) + return (0); + + if (lookup == NULL) + status = ENOENT; + else + { + status = lookup_search (lookup, ds, vl); + if (status > 0) + status = 0; + } + + return (status); +} /* }}} int agg_write */ + +void module_register (void) +{ + plugin_register_complex_config ("aggregation", agg_config); + plugin_register_read ("aggregation", agg_read); + plugin_register_write ("aggregation", agg_write, /* user_data = */ NULL); +} + +/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */ diff --git a/src/amqp.c b/src/amqp.c new file mode 100644 index 00000000..24bc4881 --- /dev/null +++ b/src/amqp.c @@ -0,0 +1,1094 @@ +/** + * collectd - src/amqp.c + * Copyright (C) 2009 Sebastien Pahl + * Copyright (C) 2010-2012 Florian Forster + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Sebastien Pahl + * Florian Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "utils_cmd_putval.h" +#include "utils_format_json.h" +#include "utils_format_graphite.h" + +#include + +#include +#include + +#ifdef HAVE_AMQP_TCP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_TCP_SOCKET +#if defined HAVE_DECL_AMQP_SOCKET_CLOSE && !HAVE_DECL_AMQP_SOCKET_CLOSE +/* rabbitmq-c does not currently ship amqp_socket.h + * and, thus, does not define this function. */ +int amqp_socket_close(amqp_socket_t *); +#endif +#endif + +/* Defines for the delivery mode. I have no idea why they're not defined by the + * library.. */ +#define CAMQP_DM_VOLATILE 1 +#define CAMQP_DM_PERSISTENT 2 + +#define CAMQP_FORMAT_COMMAND 1 +#define CAMQP_FORMAT_JSON 2 +#define CAMQP_FORMAT_GRAPHITE 3 + +#define CAMQP_CHANNEL 1 + +/* + * Data types + */ +struct camqp_config_s +{ + _Bool publish; + char *name; + + char *host; + int port; + char *vhost; + char *user; + char *password; + + char *exchange; + char *routing_key; + + /* publish only */ + uint8_t delivery_mode; + _Bool store_rates; + int format; + /* publish & graphite format only */ + char *prefix; + char *postfix; + char escape_char; + unsigned int graphite_flags; + + /* subscribe only */ + char *exchange_type; + char *queue; + + amqp_connection_state_t connection; + pthread_mutex_t lock; +}; +typedef struct camqp_config_s camqp_config_t; + +/* + * Global variables + */ +static const char *def_host = "localhost"; +static const char *def_vhost = "/"; +static const char *def_user = "guest"; +static const char *def_password = "guest"; +static const char *def_exchange = "amq.fanout"; + +static pthread_t *subscriber_threads = NULL; +static size_t subscriber_threads_num = 0; +static _Bool subscriber_threads_running = 1; + +#define CONF(c,f) (((c)->f != NULL) ? (c)->f : def_##f) + +/* + * Functions + */ +static void camqp_close_connection (camqp_config_t *conf) /* {{{ */ +{ + int sockfd; + + if ((conf == NULL) || (conf->connection == NULL)) + return; + + sockfd = amqp_get_sockfd (conf->connection); + amqp_channel_close (conf->connection, CAMQP_CHANNEL, AMQP_REPLY_SUCCESS); + amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); + amqp_destroy_connection (conf->connection); + close (sockfd); + conf->connection = NULL; +} /* }}} void camqp_close_connection */ + +static void camqp_config_free (void *ptr) /* {{{ */ +{ + camqp_config_t *conf = ptr; + + if (conf == NULL) + return; + + camqp_close_connection (conf); + + sfree (conf->name); + sfree (conf->host); + sfree (conf->vhost); + sfree (conf->user); + sfree (conf->password); + sfree (conf->exchange); + sfree (conf->exchange_type); + sfree (conf->queue); + sfree (conf->routing_key); + sfree (conf->prefix); + sfree (conf->postfix); + + + sfree (conf); +} /* }}} void camqp_config_free */ + +static char *camqp_bytes_cstring (amqp_bytes_t *in) /* {{{ */ +{ + char *ret; + + if ((in == NULL) || (in->bytes == NULL)) + return (NULL); + + ret = malloc (in->len + 1); + if (ret == NULL) + return (NULL); + + memcpy (ret, in->bytes, in->len); + ret[in->len] = 0; + + return (ret); +} /* }}} char *camqp_bytes_cstring */ + +static _Bool camqp_is_error (camqp_config_t *conf) /* {{{ */ +{ + amqp_rpc_reply_t r; + + r = amqp_get_rpc_reply (conf->connection); + if (r.reply_type == AMQP_RESPONSE_NORMAL) + return (0); + + return (1); +} /* }}} _Bool camqp_is_error */ + +static char *camqp_strerror (camqp_config_t *conf, /* {{{ */ + char *buffer, size_t buffer_size) +{ + amqp_rpc_reply_t r; + + r = amqp_get_rpc_reply (conf->connection); + switch (r.reply_type) + { + case AMQP_RESPONSE_NORMAL: + sstrncpy (buffer, "Success", sizeof (buffer)); + break; + + case AMQP_RESPONSE_NONE: + sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer)); + break; + + case AMQP_RESPONSE_LIBRARY_EXCEPTION: +#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO + if (r.library_errno) + return (sstrerror (r.library_errno, buffer, buffer_size)); +#else + if (r.library_error) + return (sstrerror (r.library_error, buffer, buffer_size)); +#endif + else + sstrncpy (buffer, "End of stream", sizeof (buffer)); + break; + + case AMQP_RESPONSE_SERVER_EXCEPTION: + if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD) + { + amqp_connection_close_t *m = r.reply.decoded; + char *tmp = camqp_bytes_cstring (&m->reply_text); + ssnprintf (buffer, buffer_size, "Server connection error %d: %s", + m->reply_code, tmp); + sfree (tmp); + } + else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD) + { + amqp_channel_close_t *m = r.reply.decoded; + char *tmp = camqp_bytes_cstring (&m->reply_text); + ssnprintf (buffer, buffer_size, "Server channel error %d: %s", + m->reply_code, tmp); + sfree (tmp); + } + else + { + ssnprintf (buffer, buffer_size, "Server error method %#"PRIx32, + r.reply.id); + } + break; + + default: + ssnprintf (buffer, buffer_size, "Unknown reply type %i", + (int) r.reply_type); + } + + return (buffer); +} /* }}} char *camqp_strerror */ + +#if HAVE_AMQP_RPC_REPLY_T_LIBRARY_ERRNO +static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */ +{ + amqp_exchange_declare_ok_t *ed_ret; + + if (conf->exchange_type == NULL) + return (0); + + ed_ret = amqp_exchange_declare (conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* exchange = */ amqp_cstring_bytes (conf->exchange), + /* type = */ amqp_cstring_bytes (conf->exchange_type), + /* passive = */ 0, + /* durable = */ 0, + /* auto_delete = */ 1, + /* arguments = */ AMQP_EMPTY_TABLE); + if ((ed_ret == NULL) && camqp_is_error (conf)) + { + char errbuf[1024]; + ERROR ("amqp plugin: amqp_exchange_declare failed: %s", + camqp_strerror (conf, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (-1); + } + + INFO ("amqp plugin: Successfully created exchange \"%s\" " + "with type \"%s\".", + conf->exchange, conf->exchange_type); + + return (0); +} /* }}} int camqp_create_exchange */ +#else +static int camqp_create_exchange (camqp_config_t *conf) /* {{{ */ +{ + amqp_exchange_declare_ok_t *ed_ret; + amqp_table_t argument_table; + struct amqp_table_entry_t_ argument_table_entries[1]; + + if (conf->exchange_type == NULL) + return (0); + + /* Valid arguments: "auto_delete", "internal" */ + argument_table.num_entries = STATIC_ARRAY_SIZE (argument_table_entries); + argument_table.entries = argument_table_entries; + argument_table_entries[0].key = amqp_cstring_bytes ("auto_delete"); + argument_table_entries[0].value.kind = AMQP_FIELD_KIND_BOOLEAN; + argument_table_entries[0].value.value.boolean = 1; + + ed_ret = amqp_exchange_declare (conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* exchange = */ amqp_cstring_bytes (conf->exchange), + /* type = */ amqp_cstring_bytes (conf->exchange_type), + /* passive = */ 0, + /* durable = */ 0, +#if defined(AMQP_VERSION) && AMQP_VERSION >= 0x00060000 + /* auto delete = */ 0, + /* internal = */ 0, +#endif + /* arguments = */ argument_table); + if ((ed_ret == NULL) && camqp_is_error (conf)) + { + char errbuf[1024]; + ERROR ("amqp plugin: amqp_exchange_declare failed: %s", + camqp_strerror (conf, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (-1); + } + + INFO ("amqp plugin: Successfully created exchange \"%s\" " + "with type \"%s\".", + conf->exchange, conf->exchange_type); + + return (0); +} /* }}} int camqp_create_exchange */ +#endif + +static int camqp_setup_queue (camqp_config_t *conf) /* {{{ */ +{ + amqp_queue_declare_ok_t *qd_ret; + amqp_basic_consume_ok_t *cm_ret; + + qd_ret = amqp_queue_declare (conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ (conf->queue != NULL) + ? amqp_cstring_bytes (conf->queue) + : AMQP_EMPTY_BYTES, + /* passive = */ 0, + /* durable = */ 0, + /* exclusive = */ 0, + /* auto_delete = */ 1, + /* arguments = */ AMQP_EMPTY_TABLE); + if (qd_ret == NULL) + { + ERROR ("amqp plugin: amqp_queue_declare failed."); + camqp_close_connection (conf); + return (-1); + } + + if (conf->queue == NULL) + { + conf->queue = camqp_bytes_cstring (&qd_ret->queue); + if (conf->queue == NULL) + { + ERROR ("amqp plugin: camqp_bytes_cstring failed."); + camqp_close_connection (conf); + return (-1); + } + + INFO ("amqp plugin: Created queue \"%s\".", conf->queue); + } + DEBUG ("amqp plugin: Successfully created queue \"%s\".", conf->queue); + + /* bind to an exchange */ + if (conf->exchange != NULL) + { + amqp_queue_bind_ok_t *qb_ret; + + assert (conf->queue != NULL); + qb_ret = amqp_queue_bind (conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ amqp_cstring_bytes (conf->queue), + /* exchange = */ amqp_cstring_bytes (conf->exchange), + /* routing_key = */ (conf->routing_key != NULL) + ? amqp_cstring_bytes (conf->routing_key) + : AMQP_EMPTY_BYTES, + /* arguments = */ AMQP_EMPTY_TABLE); + if ((qb_ret == NULL) && camqp_is_error (conf)) + { + char errbuf[1024]; + ERROR ("amqp plugin: amqp_queue_bind failed: %s", + camqp_strerror (conf, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (-1); + } + + DEBUG ("amqp plugin: Successfully bound queue \"%s\" to exchange \"%s\".", + conf->queue, conf->exchange); + } /* if (conf->exchange != NULL) */ + + cm_ret = amqp_basic_consume (conf->connection, + /* channel = */ CAMQP_CHANNEL, + /* queue = */ amqp_cstring_bytes (conf->queue), + /* consumer_tag = */ AMQP_EMPTY_BYTES, + /* no_local = */ 0, + /* no_ack = */ 1, + /* exclusive = */ 0, + /* arguments = */ AMQP_EMPTY_TABLE + ); + if ((cm_ret == NULL) && camqp_is_error (conf)) + { + char errbuf[1024]; + ERROR ("amqp plugin: amqp_basic_consume failed: %s", + camqp_strerror (conf, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (-1); + } + + return (0); +} /* }}} int camqp_setup_queue */ + +static int camqp_connect (camqp_config_t *conf) /* {{{ */ +{ + amqp_rpc_reply_t reply; + int status; +#ifdef HAVE_AMQP_TCP_SOCKET + amqp_socket_t *socket; +#else + int sockfd; +#endif + + if (conf->connection != NULL) + return (0); + + conf->connection = amqp_new_connection (); + if (conf->connection == NULL) + { + ERROR ("amqp plugin: amqp_new_connection failed."); + return (ENOMEM); + } + +#ifdef HAVE_AMQP_TCP_SOCKET +# define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us */ + /* TODO: add support for SSL using amqp_ssl_socket_new + * and related functions */ + socket = amqp_tcp_socket_new (conf->connection); + if (! socket) + { + ERROR ("amqp plugin: amqp_tcp_socket_new failed."); + amqp_destroy_connection (conf->connection); + conf->connection = NULL; + return (ENOMEM); + } + + status = amqp_socket_open (socket, CONF(conf, host), conf->port); + if (status < 0) + { + char errbuf[1024]; + status *= -1; + ERROR ("amqp plugin: amqp_socket_open failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + amqp_destroy_connection (conf->connection); + conf->connection = NULL; + return (status); + } +#else /* HAVE_AMQP_TCP_SOCKET */ +# define CLOSE_SOCKET() close(sockfd) + /* this interface is deprecated as of rabbitmq-c 0.4 */ + sockfd = amqp_open_socket (CONF(conf, host), conf->port); + if (sockfd < 0) + { + char errbuf[1024]; + status = (-1) * sockfd; + ERROR ("amqp plugin: amqp_open_socket failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + amqp_destroy_connection (conf->connection); + conf->connection = NULL; + return (status); + } + amqp_set_sockfd (conf->connection, sockfd); +#endif + + reply = amqp_login (conf->connection, CONF(conf, vhost), + /* channel max = */ 0, + /* frame max = */ 131072, + /* heartbeat = */ 0, + /* authentication = */ AMQP_SASL_METHOD_PLAIN, + CONF(conf, user), CONF(conf, password)); + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + ERROR ("amqp plugin: amqp_login (vhost = %s, user = %s) failed.", + CONF(conf, vhost), CONF(conf, user)); + amqp_destroy_connection (conf->connection); + CLOSE_SOCKET (); + conf->connection = NULL; + return (1); + } + + amqp_channel_open (conf->connection, /* channel = */ 1); + /* FIXME: Is checking "reply.reply_type" really correct here? How does + * it get set? --octo */ + if (reply.reply_type != AMQP_RESPONSE_NORMAL) + { + ERROR ("amqp plugin: amqp_channel_open failed."); + amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); + amqp_destroy_connection (conf->connection); + CLOSE_SOCKET (); + conf->connection = NULL; + return (1); + } + + INFO ("amqp plugin: Successfully opened connection to vhost \"%s\" " + "on %s:%i.", CONF(conf, vhost), CONF(conf, host), conf->port); + + status = camqp_create_exchange (conf); + if (status != 0) + return (status); + + if (!conf->publish) + return (camqp_setup_queue (conf)); + return (0); +} /* }}} int camqp_connect */ + +static int camqp_shutdown (void) /* {{{ */ +{ + size_t i; + + DEBUG ("amqp plugin: Shutting down %zu subscriber threads.", + subscriber_threads_num); + + subscriber_threads_running = 0; + for (i = 0; i < subscriber_threads_num; i++) + { + /* FIXME: Sending a signal is not very elegant here. Maybe find out how + * to use a timeout in the thread and check for the variable in regular + * intervals. */ + pthread_kill (subscriber_threads[i], SIGTERM); + pthread_join (subscriber_threads[i], /* retval = */ NULL); + } + + subscriber_threads_num = 0; + sfree (subscriber_threads); + + DEBUG ("amqp plugin: All subscriber threads exited."); + + return (0); +} /* }}} int camqp_shutdown */ + +/* + * Subscribing code + */ +static int camqp_read_body (camqp_config_t *conf, /* {{{ */ + size_t body_size, const char *content_type) +{ + char body[body_size + 1]; + char *body_ptr; + size_t received; + amqp_frame_t frame; + int status; + + memset (body, 0, sizeof (body)); + body_ptr = &body[0]; + received = 0; + + while (received < body_size) + { + status = amqp_simple_wait_frame (conf->connection, &frame); + if (status < 0) + { + char errbuf[1024]; + status = (-1) * status; + ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (status); + } + + if (frame.frame_type != AMQP_FRAME_BODY) + { + NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8, + frame.frame_type); + return (-1); + } + + if ((body_size - received) < frame.payload.body_fragment.len) + { + WARNING ("amqp plugin: Body is larger than indicated by header."); + return (-1); + } + + memcpy (body_ptr, frame.payload.body_fragment.bytes, + frame.payload.body_fragment.len); + body_ptr += frame.payload.body_fragment.len; + received += frame.payload.body_fragment.len; + } /* while (received < body_size) */ + + if (strcasecmp ("text/collectd", content_type) == 0) + { + status = handle_putval (stderr, body); + if (status != 0) + ERROR ("amqp plugin: handle_putval failed with status %i.", + status); + return (status); + } + else if (strcasecmp ("application/json", content_type) == 0) + { + ERROR ("amqp plugin: camqp_read_body: Parsing JSON data has not " + "been implemented yet. FIXME!"); + return (0); + } + else + { + ERROR ("amqp plugin: camqp_read_body: Unknown content type \"%s\".", + content_type); + return (EINVAL); + } + + /* not reached */ + return (0); +} /* }}} int camqp_read_body */ + +static int camqp_read_header (camqp_config_t *conf) /* {{{ */ +{ + int status; + amqp_frame_t frame; + amqp_basic_properties_t *properties; + char *content_type; + + status = amqp_simple_wait_frame (conf->connection, &frame); + if (status < 0) + { + char errbuf[1024]; + status = (-1) * status; + ERROR ("amqp plugin: amqp_simple_wait_frame failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + camqp_close_connection (conf); + return (status); + } + + if (frame.frame_type != AMQP_FRAME_HEADER) + { + NOTICE ("amqp plugin: Unexpected frame type: %#"PRIx8, + frame.frame_type); + return (-1); + } + + properties = frame.payload.properties.decoded; + content_type = camqp_bytes_cstring (&properties->content_type); + if (content_type == NULL) + { + ERROR ("amqp plugin: Unable to determine content type."); + return (-1); + } + + status = camqp_read_body (conf, + (size_t) frame.payload.properties.body_size, + content_type); + + sfree (content_type); + return (status); +} /* }}} int camqp_read_header */ + +static void *camqp_subscribe_thread (void *user_data) /* {{{ */ +{ + camqp_config_t *conf = user_data; + int status; + + cdtime_t interval = plugin_get_interval (); + + while (subscriber_threads_running) + { + amqp_frame_t frame; + + status = camqp_connect (conf); + if (status != 0) + { + struct timespec ts_interval; + ERROR ("amqp plugin: camqp_connect failed. " + "Will sleep for %.3f seconds.", + CDTIME_T_TO_DOUBLE (interval)); + CDTIME_T_TO_TIMESPEC (interval, &ts_interval); + nanosleep (&ts_interval, /* remaining = */ NULL); + continue; + } + + status = amqp_simple_wait_frame (conf->connection, &frame); + if (status < 0) + { + struct timespec ts_interval; + ERROR ("amqp plugin: amqp_simple_wait_frame failed. " + "Will sleep for %.3f seconds.", + CDTIME_T_TO_DOUBLE (interval)); + camqp_close_connection (conf); + CDTIME_T_TO_TIMESPEC (interval, &ts_interval); + nanosleep (&ts_interval, /* remaining = */ NULL); + continue; + } + + if (frame.frame_type != AMQP_FRAME_METHOD) + { + DEBUG ("amqp plugin: Unexpected frame type: %#"PRIx8, + frame.frame_type); + continue; + } + + if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD) + { + DEBUG ("amqp plugin: Unexpected method id: %#"PRIx32, + frame.payload.method.id); + continue; + } + + status = camqp_read_header (conf); + + amqp_maybe_release_buffers (conf->connection); + } /* while (subscriber_threads_running) */ + + camqp_config_free (conf); + pthread_exit (NULL); + return (NULL); +} /* }}} void *camqp_subscribe_thread */ + +static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */ +{ + int status; + pthread_t *tmp; + + tmp = realloc (subscriber_threads, + sizeof (*subscriber_threads) * (subscriber_threads_num + 1)); + if (tmp == NULL) + { + ERROR ("amqp plugin: realloc failed."); + camqp_config_free (conf); + return (ENOMEM); + } + subscriber_threads = tmp; + tmp = subscriber_threads + subscriber_threads_num; + memset (tmp, 0, sizeof (*tmp)); + + status = plugin_thread_create (tmp, /* attr = */ NULL, + camqp_subscribe_thread, conf); + if (status != 0) + { + char errbuf[1024]; + ERROR ("amqp plugin: pthread_create failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + camqp_config_free (conf); + return (status); + } + + subscriber_threads_num++; + + return (0); +} /* }}} int camqp_subscribe_init */ + +/* + * Publishing code + */ +/* XXX: You must hold "conf->lock" when calling this function! */ +static int camqp_write_locked (camqp_config_t *conf, /* {{{ */ + const char *buffer, const char *routing_key) +{ + amqp_basic_properties_t props; + int status; + + status = camqp_connect (conf); + if (status != 0) + return (status); + + memset (&props, 0, sizeof (props)); + props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG + | AMQP_BASIC_DELIVERY_MODE_FLAG + | AMQP_BASIC_APP_ID_FLAG; + if (conf->format == CAMQP_FORMAT_COMMAND) + props.content_type = amqp_cstring_bytes("text/collectd"); + else if (conf->format == CAMQP_FORMAT_JSON) + props.content_type = amqp_cstring_bytes("application/json"); + else if (conf->format == CAMQP_FORMAT_GRAPHITE) + props.content_type = amqp_cstring_bytes("text/graphite"); + else + assert (23 == 42); + props.delivery_mode = conf->delivery_mode; + props.app_id = amqp_cstring_bytes("collectd"); + + status = amqp_basic_publish(conf->connection, + /* channel = */ 1, + amqp_cstring_bytes(CONF(conf, exchange)), + amqp_cstring_bytes (routing_key), + /* mandatory = */ 0, + /* immediate = */ 0, + &props, + amqp_cstring_bytes(buffer)); + if (status != 0) + { + ERROR ("amqp plugin: amqp_basic_publish failed with status %i.", + status); + camqp_close_connection (conf); + } + + return (status); +} /* }}} int camqp_write_locked */ + +static int camqp_write (const data_set_t *ds, const value_list_t *vl, /* {{{ */ + user_data_t *user_data) +{ + camqp_config_t *conf = user_data->data; + char routing_key[6 * DATA_MAX_NAME_LEN]; + char buffer[4096]; + int status; + + if ((ds == NULL) || (vl == NULL) || (conf == NULL)) + return (EINVAL); + + memset (buffer, 0, sizeof (buffer)); + + if (conf->routing_key != NULL) + { + sstrncpy (routing_key, conf->routing_key, sizeof (routing_key)); + } + else + { + size_t i; + ssnprintf (routing_key, sizeof (routing_key), "collectd/%s/%s/%s/%s/%s", + vl->host, + vl->plugin, vl->plugin_instance, + vl->type, vl->type_instance); + + /* Switch slashes (the only character forbidden by collectd) and dots + * (the separation character used by AMQP). */ + for (i = 0; routing_key[i] != 0; i++) + { + if (routing_key[i] == '.') + routing_key[i] = '/'; + else if (routing_key[i] == '/') + routing_key[i] = '.'; + } + } + + if (conf->format == CAMQP_FORMAT_COMMAND) + { + status = create_putval (buffer, sizeof (buffer), ds, vl); + if (status != 0) + { + ERROR ("amqp plugin: create_putval failed with status %i.", + status); + return (status); + } + } + else if (conf->format == CAMQP_FORMAT_JSON) + { + size_t bfree = sizeof (buffer); + size_t bfill = 0; + + format_json_initialize (buffer, &bfill, &bfree); + format_json_value_list (buffer, &bfill, &bfree, ds, vl, conf->store_rates); + format_json_finalize (buffer, &bfill, &bfree); + } + else if (conf->format == CAMQP_FORMAT_GRAPHITE) + { + status = format_graphite (buffer, sizeof (buffer), ds, vl, + conf->prefix, conf->postfix, conf->escape_char, + conf->graphite_flags); + if (status != 0) + { + ERROR ("amqp plugin: format_graphite failed with status %i.", + status); + return (status); + } + } + else + { + ERROR ("amqp plugin: Invalid format (%i).", conf->format); + return (-1); + } + + pthread_mutex_lock (&conf->lock); + status = camqp_write_locked (conf, buffer, routing_key); + pthread_mutex_unlock (&conf->lock); + + return (status); +} /* }}} int camqp_write */ + +/* + * Config handling + */ +static int camqp_config_set_format (oconfig_item_t *ci, /* {{{ */ + camqp_config_t *conf) +{ + char *string; + int status; + + string = NULL; + status = cf_util_get_string (ci, &string); + if (status != 0) + return (status); + + assert (string != NULL); + if (strcasecmp ("Command", string) == 0) + conf->format = CAMQP_FORMAT_COMMAND; + else if (strcasecmp ("JSON", string) == 0) + conf->format = CAMQP_FORMAT_JSON; + else if (strcasecmp ("Graphite", string) == 0) + conf->format = CAMQP_FORMAT_GRAPHITE; + else + { + WARNING ("amqp plugin: Invalid format string: %s", + string); + } + + free (string); + + return (0); +} /* }}} int config_set_string */ + +static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */ + _Bool publish) +{ + camqp_config_t *conf; + int status; + int i; + + conf = malloc (sizeof (*conf)); + if (conf == NULL) + { + ERROR ("amqp plugin: malloc failed."); + return (ENOMEM); + } + + /* Initialize "conf" {{{ */ + memset (conf, 0, sizeof (*conf)); + conf->publish = publish; + conf->name = NULL; + conf->format = CAMQP_FORMAT_COMMAND; + conf->host = NULL; + conf->port = 5672; + conf->vhost = NULL; + conf->user = NULL; + conf->password = NULL; + conf->exchange = NULL; + conf->routing_key = NULL; + /* publish only */ + conf->delivery_mode = CAMQP_DM_VOLATILE; + conf->store_rates = 0; + /* publish & graphite only */ + conf->prefix = NULL; + conf->postfix = NULL; + conf->escape_char = '_'; + /* subscribe only */ + conf->exchange_type = NULL; + conf->queue = NULL; + /* general */ + conf->connection = NULL; + pthread_mutex_init (&conf->lock, /* attr = */ NULL); + /* }}} */ + + status = cf_util_get_string (ci, &conf->name); + if (status != 0) + { + sfree (conf); + return (status); + } + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Host", child->key) == 0) + status = cf_util_get_string (child, &conf->host); + else if (strcasecmp ("Port", child->key) == 0) + { + status = cf_util_get_port_number (child); + if (status > 0) + { + conf->port = status; + status = 0; + } + } + else if (strcasecmp ("VHost", child->key) == 0) + status = cf_util_get_string (child, &conf->vhost); + else if (strcasecmp ("User", child->key) == 0) + status = cf_util_get_string (child, &conf->user); + else if (strcasecmp ("Password", child->key) == 0) + status = cf_util_get_string (child, &conf->password); + else if (strcasecmp ("Exchange", child->key) == 0) + status = cf_util_get_string (child, &conf->exchange); + else if ((strcasecmp ("ExchangeType", child->key) == 0) && !publish) + status = cf_util_get_string (child, &conf->exchange_type); + else if ((strcasecmp ("Queue", child->key) == 0) && !publish) + status = cf_util_get_string (child, &conf->queue); + else if (strcasecmp ("RoutingKey", child->key) == 0) + status = cf_util_get_string (child, &conf->routing_key); + else if ((strcasecmp ("Persistent", child->key) == 0) && publish) + { + _Bool tmp = 0; + status = cf_util_get_boolean (child, &tmp); + if (tmp) + conf->delivery_mode = CAMQP_DM_PERSISTENT; + else + conf->delivery_mode = CAMQP_DM_VOLATILE; + } + else if ((strcasecmp ("StoreRates", child->key) == 0) && publish) + { + status = cf_util_get_boolean (child, &conf->store_rates); + (void) cf_util_get_flag (child, &conf->graphite_flags, + GRAPHITE_STORE_RATES); + } + else if ((strcasecmp ("Format", child->key) == 0) && publish) + status = camqp_config_set_format (child, conf); + else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish) + status = cf_util_get_string (child, &conf->prefix); + else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish) + status = cf_util_get_string (child, &conf->postfix); + else if ((strcasecmp ("GraphiteEscapeChar", child->key) == 0) && publish) + { + char *tmp_buff = NULL; + status = cf_util_get_string (child, &tmp_buff); + if (strlen (tmp_buff) > 1) + WARNING ("amqp plugin: The option \"GraphiteEscapeChar\" handles " + "only one character. Others will be ignored."); + conf->escape_char = tmp_buff[0]; + sfree (tmp_buff); + } + else + WARNING ("amqp plugin: Ignoring unknown " + "configuration option \"%s\".", child->key); + + if (status != 0) + break; + } /* for (i = 0; i < ci->children_num; i++) */ + + if ((status == 0) && (conf->exchange == NULL)) + { + if (conf->exchange_type != NULL) + WARNING ("amqp plugin: The option \"ExchangeType\" was given " + "without the \"Exchange\" option. It will be ignored."); + + if (!publish && (conf->routing_key != NULL)) + WARNING ("amqp plugin: The option \"RoutingKey\" was given " + "without the \"Exchange\" option. It will be ignored."); + + } + + if (status != 0) + { + camqp_config_free (conf); + return (status); + } + + if (conf->exchange != NULL) + { + DEBUG ("amqp plugin: camqp_config_connection: exchange = %s;", + conf->exchange); + } + + if (publish) + { + char cbname[128]; + user_data_t ud = { conf, camqp_config_free }; + + ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name); + + status = plugin_register_write (cbname, camqp_write, &ud); + if (status != 0) + { + camqp_config_free (conf); + return (status); + } + } + else + { + status = camqp_subscribe_init (conf); + if (status != 0) + { + camqp_config_free (conf); + return (status); + } + } + + return (0); +} /* }}} int camqp_config_connection */ + +static int camqp_config (oconfig_item_t *ci) /* {{{ */ +{ + int i; + + for (i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Publish", child->key) == 0) + camqp_config_connection (child, /* publish = */ 1); + else if (strcasecmp ("Subscribe", child->key) == 0) + camqp_config_connection (child, /* publish = */ 0); + else + WARNING ("amqp plugin: Ignoring unknown config option \"%s\".", + child->key); + } /* for (ci->children_num) */ + + return (0); +} /* }}} int camqp_config */ + +void module_register (void) +{ + plugin_register_complex_config ("amqp", camqp_config); + plugin_register_shutdown ("amqp", camqp_shutdown); +} /* void module_register */ + +/* vim: set sw=4 sts=4 et fdm=marker : */ diff --git a/src/apache.c b/src/apache.c index 23bba3ea..f0ab22a8 100644 --- a/src/apache.c +++ b/src/apache.c @@ -1,6 +1,6 @@ /** * collectd - src/apache.c - * Copyright (C) 2006-2009 Florian octo Forster + * Copyright (C) 2006-2010 Florian octo Forster * Copyright (C) 2007 Florent EppO Monbillard * Copyright (C) 2009 Amit Gupta * @@ -144,6 +144,8 @@ static size_t apache_header_callback (void *buf, size_t size, size_t nmemb, st->server_type = APACHE; else if (strstr (buf, "lighttpd") != NULL) st->server_type = LIGHTTPD; + else if (strstr (buf, "IBM_HTTP_Server") != NULL) + st->server_type = APACHE; else { const char *hdr = buf; @@ -333,57 +335,22 @@ static int config (oconfig_item_t *ci) { int status = 0; int i; - oconfig_item_t *lci = NULL; /* legacy config */ for (i = 0; i < ci->children_num; i++) { oconfig_item_t *child = ci->children + i; - if (strcasecmp ("Instance", child->key) == 0 && child->children_num > 0) + if (strcasecmp ("Instance", child->key) == 0) config_add (child); else - { - /* legacy mode - convert to config */ - if (lci == NULL) - { - lci = malloc (sizeof(*lci)); - if (lci == NULL) - { - ERROR ("apache plugin: malloc failed."); - return (-1); - } - memset (lci, '\0', sizeof (*lci)); - } - - lci->children_num++; - lci->children = - realloc (lci->children, - lci->children_num * sizeof (*child)); - if (lci->children == NULL) - { - ERROR ("apache plugin: realloc failed."); - return (-1); - } - memcpy (&lci->children[lci->children_num-1], child, sizeof (*child)); - } + WARNING ("apache plugin: The configuration option " + "\"%s\" is not allowed here. Did you " + "forget to add an block " + "around the configuration?", + child->key); } /* for (ci->children) */ - if (lci) - { - /* create a entry */ - lci->key = "Instance"; - lci->values_num = 1; - lci->values = (oconfig_value_t *) malloc (lci->values_num * sizeof (oconfig_value_t)); - lci->values[0].type = OCONFIG_TYPE_STRING; - lci->values[0].value.string = ""; - - status = config_add (lci); - sfree (lci->values); - sfree (lci->children); - sfree (lci); - } - - return status; + return (status); } /* int config */ /* initialize curl for each host */ @@ -421,6 +388,8 @@ static int init_host (apache_t *st) /* {{{ */ st->server_type = APACHE; else if (strcasecmp(st->server, "lighttpd") == 0) st->server_type = LIGHTTPD; + else if (strcasecmp(st->server, "ibm_http_server") == 0) + st->server_type = APACHE; else WARNING ("apache plugin: Unknown `Server' setting: %s", st->server); @@ -509,13 +478,13 @@ static void submit_value (const char *type, const char *type_instance, plugin_dispatch_values (&vl); } /* void submit_value */ -static void submit_counter (const char *type, const char *type_instance, - counter_t c, apache_t *st) +static void submit_derive (const char *type, const char *type_instance, + derive_t c, apache_t *st) { value_t v; - v.counter = c; + v.derive = c; submit_value (type, type_instance, v, st); -} /* void submit_counter */ +} /* void submit_derive */ static void submit_gauge (const char *type, const char *type_instance, gauge_t g, apache_t *st) @@ -677,11 +646,11 @@ static int apache_read_host (user_data_t *user_data) /* {{{ */ { if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "Accesses:") == 0)) - submit_counter ("apache_requests", "", + submit_derive ("apache_requests", "", atoll (fields[2]), st); else if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "kBytes:") == 0)) - submit_counter ("apache_bytes", "", + submit_derive ("apache_bytes", "", 1024LL * atoll (fields[2]), st); } else if (fields_num == 2) diff --git a/src/apcups.c b/src/apcups.c index 4fbbde63..ee15b14f 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -70,6 +70,8 @@ struct apc_detail_s /* Default values for contacting daemon */ static char *conf_host = NULL; static int conf_port = NISPORT; +/* Defaults to false for backwards compatibility. */ +static _Bool conf_report_seconds = 0; static int global_sockfd = -1; @@ -81,9 +83,9 @@ static const char *config_keys[] = { "Host", "Port", - NULL + "ReportSeconds" }; -static int config_keys_num = 2; +static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static int net_shutdown (int *fd) { @@ -360,7 +362,13 @@ static int apc_query_server (char *host, int port, else if (strcmp ("LINEFREQ", key) == 0) apcups_detail->linefreq = value; else if (strcmp ("TIMELEFT", key) == 0) + { + /* Convert minutes to seconds if requested by + * the user. */ + if (conf_report_seconds) + value *= 60.0; apcups_detail->timeleft = value; + } tokptr = strtok_r (NULL, ":", &toksaveptr); } /* while (tokptr != NULL) */ @@ -403,6 +411,13 @@ static int apcups_config (const char *key, const char *value) } conf_port = port_tmp; } + else if (strcasecmp (key, "ReportSeconds") == 0) + { + if (IS_TRUE (value)) + conf_report_seconds = 1; + else + conf_report_seconds = 0; + } else { return (-1); @@ -450,7 +465,7 @@ static int apcups_read (void) apcups_detail.battv = -1.0; apcups_detail.loadpct = -1.0; apcups_detail.bcharge = -1.0; - apcups_detail.timeleft = -1.0; + apcups_detail.timeleft = NAN; apcups_detail.itemp = -300.0; apcups_detail.linefreq = -1.0; diff --git a/src/bind.c b/src/bind.c index d358146a..03dfcc77 100644 --- a/src/bind.c +++ b/src/bind.c @@ -1,7 +1,7 @@ /** * collectd - src/bind.c - * Copyright (C) 2009 Bruno Prémont - * Copyright (C) 2009 Florian Forster + * Copyright (C) 2009 Bruno Prémont + * Copyright (C) 2009,2010 Florian Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,14 +18,22 @@ * * Authors: * Bruno Prémont - * Florian Forster + * Florian Forster **/ #include "config.h" -#ifndef _XOPEN_SOURCE -# define _XOPEN_SOURCE 600 /* glibc2 needs this for strptime */ -#endif +#if STRPTIME_NEEDS_STANDARDS +# ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE 1 +# endif +# ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +# endif +# ifndef _XOPEN_SOURCE +# define _XOPEN_SOURCE 500 +# endif +#endif /* STRPTIME_NEEDS_STANDARDS */ #include "collectd.h" #include "common.h" @@ -90,6 +98,10 @@ struct list_info_ptr_s }; typedef struct list_info_ptr_s list_info_ptr_t; +/* FIXME: Enabled by default for backwards compatibility. */ +/* TODO: Remove time parsing code. */ +static _Bool config_parse_time = 1; + static char *url = NULL; static int global_opcodes = 1; static int global_qtypes = 1; @@ -241,7 +253,8 @@ static void submit (time_t ts, const char *plugin_instance, /* {{{ */ vl.values = values; vl.values_len = 1; - vl.time = ts; + if (config_parse_time) + vl.time = TIME_T_TO_CDTIME_T (ts); sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "bind", sizeof(vl.plugin)); if (plugin_instance) { @@ -337,36 +350,31 @@ static int bind_xml_list_callback (const char *name, /* {{{ */ return (0); } /* }}} int bind_xml_list_callback */ -static int bind_xml_read_counter (xmlDoc *doc, xmlNode *node, /* {{{ */ - counter_t *ret_value) +static int bind_xml_read_derive (xmlDoc *doc, xmlNode *node, /* {{{ */ + derive_t *ret_value) { - char *str_ptr, *end_ptr; - long long int value; + char *str_ptr; + value_t value; + int status; str_ptr = (char *) xmlNodeListGetString (doc, node->xmlChildrenNode, 1); if (str_ptr == NULL) { - ERROR ("bind plugin: bind_xml_read_counter: xmlNodeListGetString failed."); + ERROR ("bind plugin: bind_xml_read_derive: xmlNodeListGetString failed."); return (-1); } - errno = 0; - value = strtoll (str_ptr, &end_ptr, 10); - xmlFree(str_ptr); - if (str_ptr == end_ptr || errno) + status = parse_value (str_ptr, &value, DS_TYPE_DERIVE); + if (status != 0) { - if (errno && (value < 0)) - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with underflow."); - else if (errno && (value > 0)) - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed with overflow."); - else - ERROR ("bind plugin: bind_xml_read_counter: strtoll failed."); + ERROR ("bind plugin: Parsing string \"%s\" to derive value failed.", + str_ptr); return (-1); } - *ret_value = value; + *ret_value = value.derive; return (0); -} /* }}} int bind_xml_read_counter */ +} /* }}} int bind_xml_read_derive */ static int bind_xml_read_gauge (xmlDoc *doc, xmlNode *node, /* {{{ */ gauge_t *ret_value) @@ -527,7 +535,7 @@ static int bind_parse_generic_name_value (const char *xpath_expression, /* {{{ * if (ds_type == DS_TYPE_GAUGE) status = bind_xml_read_gauge (doc, counter, &value.gauge); else - status = bind_xml_read_counter (doc, counter, &value.counter); + status = bind_xml_read_derive (doc, counter, &value.derive); if (status != 0) continue; @@ -600,7 +608,7 @@ static int bind_parse_generic_value_list (const char *xpath_expression, /* {{{ * if (ds_type == DS_TYPE_GAUGE) status = bind_xml_read_gauge (doc, child, &value.gauge); else - status = bind_xml_read_counter (doc, child, &value.counter); + status = bind_xml_read_derive (doc, child, &value.derive); if (status != 0) continue; @@ -1361,6 +1369,8 @@ static int bind_config (oconfig_item_t *ci) /* {{{ */ bind_config_set_bool ("MemoryStats", &global_memory_stats, child); else if (strcasecmp ("View", child->key) == 0) bind_config_add_view (child); + else if (strcasecmp ("ParseTime", child->key) == 0) + cf_util_get_boolean (child, &config_parse_time); else { WARNING ("bind plugin: Unknown configuration option " diff --git a/src/collectd-email.pod b/src/collectd-email.pod index e19d13ec..6f585427 100644 --- a/src/collectd-email.pod +++ b/src/collectd-email.pod @@ -1,3 +1,5 @@ +=encoding UTF-8 + =head1 NAME collectd-email - Documentation of collectd's C diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod index 81b3a2ec..fd9b3a0c 100644 --- a/src/collectd-exec.pod +++ b/src/collectd-exec.pod @@ -1,3 +1,5 @@ +=encoding UTF-8 + =head1 NAME collectd-exec - Documentation of collectd's C @@ -116,12 +118,8 @@ case you're confused. Since examples usually let one understand a lot better, here are some: - leeloo/cpu-0/cpu-idle N:2299366 - alice/interface/if_octets-eth0 interval=10 1180647081:421465:479194 - -Since this action was the only one supported with older versions of the C all lines were treated as if they were prefixed with B. This is -still the case to maintain backwards compatibility but deprecated. + PUTVAL leeloo/cpu-0/cpu-idle N:2299366 + PUTVAL alice/interface/if_octets-eth0 interval=10 1180647081:421465:479194 =item B [I] BI @@ -190,13 +188,13 @@ The data is passed to the executables over C in a format very similar to HTTP: At first there is a "header" with one line per field. Every line consists of a field name, ended by a colon, and the associated value until end-of-line. The "header" is ended by two newlines immediately following another, -i.Ee. an empty line. The rest, basically the "body", is the message of -the notification. +i.e. an empty line. The rest, basically the "body", is the message of the +notification. The following is an example notification passed to a program: Severity: FAILURE - Time: 1200928930 + Time: 1200928930.515 Host: myhost.mydomain.org \n This is a test notification to demonstrate the format @@ -212,7 +210,9 @@ Severity of the notification. May either be B, B, or B. =item B