Batterycharge, -current and voltage of ACPI and PMU based laptop
batteries.
+ - curl
+ Parse statistics from websites using regular expressions.
+
+ - bind
+ Name server and resolver statistics from the `statistics-channel'
+ interface of BIND 9.5, 9,6 and later.
+
- cpu
CPU utilization: Time spent in the system, user, nice, idle, and related
states.
- cpufreq
CPU frequency (For laptops with speed step or a similar technology)
+ - dbi
+ Executes SQL statements on various databases and interprets the returned
+ data.
+
- df
Mountpoint usage (Basically the values `df(1)' delivers)
Iptables' counters: Number of bytes that were matched by a certain
iptables rule.
+ - ipmi
+ IPMI (Intelligent Platform Management Interface) sensors information.
+
- ipvs
IPVS connection statistics (number of connections, octets and packets
for each service and destination).
Read onewire sensors using the owcapu library of the owfs project.
Please read in collectd.conf(5) why this plugin is experimental.
+ - openvpn
+ RX and TX of each client in openvpn-status.log (status-version 2).
+ <http://openvpn.net/index.php/documentation/howto.html>
+
+ - oracle
+ Query data from an Oracle database.
+
- perl
The perl plugin implements a Perl-interpreter into collectd. You can
write your own plugins in Perl and return arbitrary values using this
PostgreSQL database statistics: active server connections, transaction
numbers, block IO, table row manipulations.
+ - powerdns
+ PowerDNS name server statistics.
+
- processes
Process counts: Number of running, sleeping, zombie, ... processes.
+ - rrdcached
+ RRDtool caching daemon (RRDcacheD) statistics.
+
- sensors
System sensors, accessed using lm_sensors: Voltages, temperatures and
fan rotation speeds.
- tcpconns
Number of TCP connections to specific local and remote ports.
+ - teamspeak2
+ TeamSpeak2 server statistics.
+
+ - thermal
+ Linux ACPI thermal zone information.
+
- users
Users currently logged in.
you can easily do weird stuff with the plugins we didn't dare think of
;) See collectd-perl(5).
+ - rrdcached
+ Output to round-robin-database (RRD) files using the RRDtool caching
+ daemon (RRDcacheD) - see rrdcached(1). That daemon provides a general
+ implementation of the caching done by the `rrdtool' plugin.
+
- rrdtool
Output to round-robin-database (RRD) files using librrd. See rrdtool(1).
This is likely the most popular destination for such values. Since
Notifications are propagated to plugins written in Perl as well.
See collectd-perl(5).
+ * Value processing can be controlled using the "filter chain" infrastructure
+ and "matches" and "targets". The following plugins are available:
+
+ - match_regex
+ Match values by their identifier based on regular expressions.
+
+ - match_timediff
+ Match values with an invalid timestamp.
+
+ - match_value
+ Select values by their data sources' values.
+
+ - target_notification
+ Create and dispatch a notification.
+
+ - target_replace
+ Replace parts of an identifier using regular expressions.
+
+ - target_set
+ Set (overwrite) entire parts of an identifier.
+
* Miscellaneous plugins:
- uuid
since collectd is programmed multithreaded it benefits from hyperthreading
and multicore processors and makes sure that the daemon isn't idle if only
one plugins waits for an IO-operation to complete.
-
+
* Once set up, hardly any maintenance is necessary. Setup is kept as easy
as possible and the default values should be okay for most users.
* CoreFoundation.framework and IOKit.framework (optional)
For compiling on Darwin in general and the `apple_sensors' plugin in
particular.
+ <http://developer.apple.com/corefoundation/>
+
+ * libclntsh (optional)
+ Used by the `oracle' plugin.
* libcurl (optional)
- If you want to use the `apache', `ascent', or `nginx' plugin.
+ If you want to use the `apache', `ascent', `curl' or `nginx' plugin.
+ <http://curl.haxx.se/>
+
+ * libdbi (optional)
+ Used by the `dbi' plugin to connect to various databases.
+ <http://libdbi.sourceforge.net/>
* libesmtp (optional)
For the `notify_email' plugin.
+ <http://www.stafford.uklinux.net/libesmtp/>
* libhal (optional)
If present, the uuid plugin will check for UUID from HAL.
+ <http://hal.freedesktop.org/>
- * libiptc (optional)
+ * libiptc (optional, if not found a version shipped with this distribution
+ can be used if the Linux kernel headers are available)
For querying iptables counters.
+ <http://netfilter.org/>
* libmysqlclient (optional)
Unsurprisingly used by the `mysql' plugin.
+ <http://dev.mysql.com/>
* libnetlink (optional)
Used, obviously, for the `netlink' plugin.
+ <http://www.linuxfoundation.org/en/Net:Iproute2>
* libnetsnmp (optional)
For the `snmp' plugin.
+ <http://www.net-snmp.org/>
* libnotify (optional)
For the `notify_desktop' plugin.
+ <http://www.galago-project.org/>
* liboping (optional, if not found a version shipped with this distribution
can be used)
Used by the `ping' plugin to send and receive ICMP packets.
+ <http://verplant.org/liboping/>
* libowcapi (optional)
Used by the `onewire' plugin to read values from onewire sensors (or the
owserver(1) daemon).
+ <http://www.owfs.org/>
* libpcap (optional)
Used to capture packets by the `dns' plugin.
+ <http://www.tcpdump.org/>
* libperl (optional)
Obviously used by the `perl' plugin. The library has to be compiled with
ithread support (introduced in Perl 5.6.0).
+ <http://www.perl.org/>
* libpq (optional)
The PostgreSQL C client library used by the `postgresql' plugin.
+ <http://www.postgresql.org/>
- * librrd (optional; headers and library; rrdtool 1.0 and 1.2 both work fine)
- If built without `librrd' the resulting binary will be `client only', i.e.
- will send its values via multicast and not create any RRD files itself.
- Alternatively you can chose to write CSV-files (Comma Separated Values)
- instead.
+ * librrd (optional)
+ Used by the `rrdtool' and `rrdcached' plugins. The latter requires RRDtool
+ client support which was added after version 1.3 of RRDtool. Versions 1.0,
+ 1.2 and 1.3 are known to work with the `rrdtool' plugin.
+ <http://oss.oetiker.ch/rrdtool/>
* librt, libsocket, libkstat, libdevinfo (optional)
Various standard Solaris libraries which provide system functions.
+ <http://developers.sun.com/solaris/>
* libsensors (optional)
To read from `lm_sensors', see the `sensors' plugin.
+ <http://www.lm-sensors.org/>
- * libstatgrab (optional) may be used to collect statistics on systems other
- than Linux and/or Solaris. Note that CPU- and disk-statistics, while being
- provided by this library, are not supported in collectd right now..
- <http://www.i-scream.org/libstatgrab/>
+ * libstatgrab (optional)
+ Used by various plugins to collect statistics on systems other than Linux
+ and/or Solaris.
+ <http://www.i-scream.org/libstatgrab/>
* libupsclient/nut (optional)
For the `nut' plugin which queries nut's `upsd'.
+ <http://networkupstools.org/>
* libvirt (optional)
Collect statistics from virtual machines.
+ <http://libvirt.org/>
* libxml2 (optional)
Parse XML data. This is needed for the `ascent' and `libvirt' plugins.
+ <http://xmlsoft.org/>
* libxmms (optional)
+ <http://www.xmms.org/>
Configuring / Compiling / Installing
`./configure && make && make install'. For detailed, generic instructions
see INSTALL. For a complete list of configure options and their description,
run `./configure --help'.
-
+
By default, the configure script will check for all build dependencies and
disable all plugins whose requirements cannot be fulfilled (any other plugin
will be enabled). To enable a plugin, install missing dependencies (see
that the compiled binary actually behaves as it should, but since NANs
are likely never passed to the libm you have a good chance to be lucky.
+ Likewise, collectd needs to know the layout of doubles in memory, in order
+ to craft uniform network packets over different architectures. For this, it
+ needs to know how to convert doubles into the memory layout used by x86. The
+ configure script tries to figure this out by compiling and running a few
+ small test programs. This is of course not possible when cross-compiling.
+ You can use the `--with-fp-layout' option to tell the configure script which
+ conversion method to assume. Valid arguments are:
+
+ * `nothing' (12345678 -> 12345678)
+ * `endianflip' (12345678 -> 87654321)
+ * `intswap' (12345678 -> 56781234)
+
Contact
-------
- For questions, bugreports, development information and basically all other
- concerns please send an email to collectd's mailinglist at
+ For questions, bug reports, development information and basically all other
+ concerns please send an email to collectd's mailing list at
<collectd at verplant.org>.
For live discussion and more personal contact visit us in IRC, we're in
Sebastian tokkee Harl <sh at tokkee.org>,
and many contributors (see `AUTHORS').
- Please send bugreports and patches to the mailinglist, see `Contact' above.
+ Please send bug reports and patches to the mailing list, see `Contact'
+ above.
# Pre-defined queries of collectd's postgresql plugin.
+#
+# Do not edit this file. If you want to change any of the query definitions,
+# overwrite them in collectd.conf instead.
+#
+# This file is distributed under the same terms as collectd itself.
<Query backends>
- Query "SELECT count(*) \
+ Statement "SELECT count(*) AS count \
FROM pg_stat_activity \
WHERE datname = $1;"
Param database
- Column pg_numbackends
+ <Result>
+ Type "pg_numbackends"
+ ValuesFrom "count"
+ </Result>
</Query>
<Query transactions>
- Query "SELECT xact_commit, xact_rollback \
+ Statement "SELECT xact_commit, xact_rollback \
FROM pg_stat_database \
WHERE datname = $1;"
Param database
- Column pg_xact commit
- Column pg_xact rollback
+ <Result>
+ Type "pg_xact"
+ InstancePrefix "commit"
+ ValuesFrom "xact_commit"
+ </Result>
+ <Result>
+ Type "pg_xact"
+ InstancePrefix "rollback"
+ ValuesFrom "xact_rollback"
+ </Result>
</Query>
<Query queries>
- Query "SELECT sum(n_tup_ins), sum(n_tup_upd), sum(n_tup_del) \
+ Statement "SELECT sum(n_tup_ins) AS ins, \
+ sum(n_tup_upd) AS upd, \
+ sum(n_tup_del) AS del \
FROM pg_stat_user_tables;"
- Column pg_n_tup_c ins
- Column pg_n_tup_c upd
- Column pg_n_tup_c del
-
- MaxPGVersion 80299
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "ins"
+ ValuesFrom "ins"
+ </Result>
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "upd"
+ ValuesFrom "upd"
+ </Result>
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "del"
+ ValuesFrom "del"
+ </Result>
+
+ MaxVersion 80299
</Query>
<Query queries>
- Query "SELECT sum(n_tup_ins), sum(n_tup_upd), sum(n_tup_del), \
- sum(n_tup_hot_upd) \
+ Statement "SELECT sum(n_tup_ins) AS ins, \
+ sum(n_tup_upd) AS upd, \
+ sum(n_tup_del) AS del, \
+ sum(n_tup_hot_upd) AS hot_upd \
FROM pg_stat_user_tables;"
- Column pg_n_tup_c ins
- Column pg_n_tup_c upd
- Column pg_n_tup_c del
- Column pg_n_tup_c hot_upd
-
- MinPGVersion 80300
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "ins"
+ ValuesFrom "ins"
+ </Result>
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "upd"
+ ValuesFrom "upd"
+ </Result>
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "del"
+ ValuesFrom "del"
+ </Result>
+ <Result>
+ Type "pg_n_tup_c"
+ InstancePrefix "hot_upd"
+ ValuesFrom "hot_upd"
+ </Result>
+
+ MinVersion 80300
</Query>
<Query query_plans>
- Query "SELECT sum(seq_scan), sum(seq_tup_read), \
- sum(idx_scan), sum(idx_tup_fetch) \
+ Statement "SELECT sum(seq_scan) AS seq, \
+ sum(seq_tup_read) AS seq_tup_read, \
+ sum(idx_scan) AS idx, \
+ sum(idx_tup_fetch) AS idx_tup_fetch \
FROM pg_stat_user_tables;"
- Column pg_scan seq
- Column pg_scan seq_tup_read
- Column pg_scan idx
- Column pg_scan idx_tup_fetch
+ <Result>
+ Type "pg_scan"
+ InstancePrefix "seq"
+ ValuesFrom "seq"
+ </Result>
+ <Result>
+ Type "pg_scan"
+ InstancePrefix "seq_tup_read"
+ ValuesFrom "seq_tup_read"
+ </Result>
+ <Result>
+ Type "pg_scan"
+ InstancePrefix "idx"
+ ValuesFrom "idx"
+ </Result>
+ <Result>
+ Type "pg_scan"
+ InstancePrefix "idx_tup_fetch"
+ ValuesFrom "idx_tup_fetch"
+ </Result>
</Query>
<Query table_states>
- Query "SELECT sum(n_live_tup), sum(n_dead_tup) \
+ Statement "SELECT sum(n_live_tup) AS live, sum(n_dead_tup) AS dead \
FROM pg_stat_user_tables;"
- Column pg_n_tup_g live
- Column pg_n_tup_g dead
-
- MinPGVersion 80300
+ <Result>
+ Type "pg_n_tup_g"
+ InstancePrefix "live"
+ ValuesFrom "live"
+ </Result>
+ <Result>
+ Type "pg_n_tup_g"
+ InstancePrefix "dead"
+ ValuesFrom "dead"
+ </Result>
+
+ MinVersion 80300
</Query>
<Query disk_io>
- Statement "SELECT sum(heap_blks_read) AS heap_read, \
- sum(heap_blks_hit) AS heap_hit, \
- sum(idx_blks_read) AS idx_read, \
- sum(idx_blks_hit) AS idx_hit, \
- sum(toast_blks_read) AS toast_read, \
- sum(toast_blks_hit) AS toast_hit, \
- sum(tidx_blks_read) AS tidx_read, \
- sum(tidx_blks_hit) AS tidx_hit \
- Query "SELECT coalesce(sum(heap_blks_read), 0), \
- coalesce(sum(heap_blks_hit), 0), \
- coalesce(sum(idx_blks_read), 0), \
- coalesce(sum(idx_blks_hit), 0), \
- coalesce(sum(toast_blks_read), 0), \
- coalesce(sum(toast_blks_hit), 0), \
- coalesce(sum(tidx_blks_read), 0), \
- coalesce(sum(tidx_blks_hit), 0) \
++ Statement "SELECT coalesce(sum(heap_blks_read), 0) AS heap_read, \
++ coalesce(sum(heap_blks_hit), 0) AS heap_hit, \
++ coalesce(sum(idx_blks_read), 0) AS idx_read, \
++ coalesce(sum(idx_blks_hit), 0) AS idx_hit, \
++ coalesce(sum(toast_blks_read), 0) AS toast_read, \
++ coalesce(sum(toast_blks_hit), 0) AS toast_hit, \
++ coalesce(sum(tidx_blks_read), 0) AS tidx_read, \
++ coalesce(sum(tidx_blks_hit), 0) AS tidx_hit \
FROM pg_statio_user_tables;"
- Column pg_blks heap_read
- Column pg_blks heap_hit
- Column pg_blks idx_read
- Column pg_blks idx_hit
- Column pg_blks toast_read
- Column pg_blks toast_hit
- Column pg_blks tidx_read
- Column pg_blks tidx_hit
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "heap_read"
+ ValuesFrom "heap_read"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "heap_hit"
+ ValuesFrom "heap_hit"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "idx_read"
+ ValuesFrom "idx_read"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "idx_hit"
+ ValuesFrom "idx_hit"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "toast_read"
+ ValuesFrom "toast_read"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "toast_hit"
+ ValuesFrom "toast_hit"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "tidx_read"
+ ValuesFrom "tidx_read"
+ </Result>
+ <Result>
+ Type "pg_blks"
+ InstancePrefix "tidx_hit"
+ ValuesFrom "tidx_hit"
+ </Result>
</Query>
<Query disk_usage>
- Query "SELECT pg_database_size($1);"
+ Statement "SELECT pg_database_size($1) AS size;"
Param database
- Column pg_db_size
+ <Result>
+ Type pg_db_size
+ ValuesFrom "size"
+ </Result>
</Query>
# vim: set ft=config :
#include "plugin.h"
#include "common.h"
#include "utils_avltree.h"
+#include "utils_rrdcreate.h"
#include <rrd.h>
/*
* Private variables
*/
-static int rra_timespans[] =
-{
- 3600,
- 86400,
- 604800,
- 2678400,
- 31622400
-};
-static int rra_timespans_num = STATIC_ARRAY_SIZE (rra_timespans);
-
-static int *rra_timespans_custom = NULL;
-static int rra_timespans_custom_num = 0;
-
-static char *rra_types[] =
-{
- "AVERAGE",
- "MIN",
- "MAX"
-};
-static int rra_types_num = STATIC_ARRAY_SIZE (rra_types);
-
static const char *config_keys[] =
{
"CacheTimeout",
/* If datadir is zero, the daemon's basedir is used. If stepsize or heartbeat
* is zero a default, depending on the `interval' member of the value list is
* being used. */
-static char *datadir = NULL;
-static int stepsize = 0;
-static int heartbeat = 0;
-static int rrarows = 1200;
-static double xff = 0.1;
-static double write_rate = 0.0;
+static char *datadir = NULL;
+static double write_rate = 0.0;
+static rrdcreate_config_t rrdcreate_config =
+{
+ /* stepsize = */ 0,
+ /* heartbeat = */ 0,
+ /* rrarows = */ 1200,
+ /* xff = */ 0.1,
+
+ /* timespans = */ NULL,
+ /* timespans_num = */ 0,
+
+ /* consolidation_functions = */ NULL,
+ /* consolidation_functions_num = */ 0
+};
/* XXX: If you need to lock both, cache_lock and queue_lock, at the same time,
* ALWAYS lock `cache_lock' first! */
static int do_shutdown = 0;
-/* * * * * * * * * *
- * WARNING: Magic *
- * * * * * * * * * */
-
-static void rra_free (int rra_num, char **rra_def)
-{
- int i;
-
- for (i = 0; i < rra_num; i++)
- {
- sfree (rra_def[i]);
- }
- sfree (rra_def);
-} /* void rra_free */
-
-static int rra_get (char ***ret, const value_list_t *vl)
-{
- char **rra_def;
- int rra_num;
-
- int *rts;
- int rts_num;
-
- int rra_max;
-
- int span;
-
- int cdp_num;
- int cdp_len;
- int i, j;
-
- char buffer[64];
-
- /* The stepsize we use here: If it is user-set, use it. If not, use the
- * interval of the value-list. */
- int ss;
-
- if (rrarows <= 0)
- {
- *ret = NULL;
- return (-1);
- }
-
- ss = (stepsize > 0) ? stepsize : vl->interval;
- if (ss <= 0)
- {
- *ret = NULL;
- return (-1);
- }
-
- /* Use the configured timespans or fall back to the built-in defaults */
- if (rra_timespans_custom_num != 0)
- {
- rts = rra_timespans_custom;
- rts_num = rra_timespans_custom_num;
- }
- else
- {
- rts = rra_timespans;
- rts_num = rra_timespans_num;
- }
-
- rra_max = rts_num * rra_types_num;
-
- if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
- return (-1);
- memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
- rra_num = 0;
-
- cdp_len = 0;
- for (i = 0; i < rts_num; i++)
- {
- span = rts[i];
-
- if ((span / ss) < rrarows)
- span = ss * rrarows;
-
- if (cdp_len == 0)
- cdp_len = 1;
- else
- cdp_len = (int) floor (((double) span)
- / ((double) (rrarows * ss)));
-
- cdp_num = (int) ceil (((double) span)
- / ((double) (cdp_len * ss)));
-
- for (j = 0; j < rra_types_num; j++)
- {
- if (rra_num >= rra_max)
- break;
-
- if (ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
- rra_types[j], xff,
- cdp_len, cdp_num) >= sizeof (buffer))
- {
- ERROR ("rra_get: Buffer would have been truncated.");
- continue;
- }
-
- rra_def[rra_num++] = sstrdup (buffer);
- }
- }
-
-#if COLLECT_DEBUG
- DEBUG ("rra_num = %i", rra_num);
- for (i = 0; i < rra_num; i++)
- DEBUG (" %s", rra_def[i]);
-#endif
-
- *ret = rra_def;
- return (rra_num);
-} /* int rra_get */
-
-static void ds_free (int ds_num, char **ds_def)
-{
- int i;
-
- for (i = 0; i < ds_num; i++)
- if (ds_def[i] != NULL)
- free (ds_def[i]);
- free (ds_def);
-}
-
-static int ds_get (char ***ret, const data_set_t *ds, const value_list_t *vl)
-{
- char **ds_def;
- int ds_num;
-
- char min[32];
- char max[32];
- char buffer[128];
-
- DEBUG ("ds->ds_num = %i", ds->ds_num);
-
- ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
- if (ds_def == NULL)
- {
- char errbuf[1024];
- ERROR ("rrdtool plugin: malloc failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
- memset (ds_def, '\0', ds->ds_num * sizeof (char *));
-
- for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
- {
- data_source_t *d = ds->ds + ds_num;
- char *type;
- int status;
-
- ds_def[ds_num] = NULL;
-
- if (d->type == DS_TYPE_COUNTER)
- type = "COUNTER";
- else if (d->type == DS_TYPE_GAUGE)
- type = "GAUGE";
- else
- {
- ERROR ("rrdtool plugin: Unknown DS type: %i",
- d->type);
- break;
- }
-
- if (isnan (d->min))
- {
- sstrncpy (min, "U", sizeof (min));
- }
- else
- ssnprintf (min, sizeof (min), "%lf", d->min);
-
- if (isnan (d->max))
- {
- sstrncpy (max, "U", sizeof (max));
- }
- else
- ssnprintf (max, sizeof (max), "%lf", d->max);
-
- status = ssnprintf (buffer, sizeof (buffer),
- "DS:%s:%s:%i:%s:%s",
- d->name, type,
- (heartbeat > 0) ? heartbeat : (2 * vl->interval),
- min, max);
- if ((status < 1) || (status >= sizeof (buffer)))
- break;
-
- ds_def[ds_num] = sstrdup (buffer);
- } /* for ds_num = 0 .. ds->ds_num */
-
-#if COLLECT_DEBUG
-{
- int i;
- DEBUG ("ds_num = %i", ds_num);
- for (i = 0; i < ds_num; i++)
- DEBUG (" %s", ds_def[i]);
-}
-#endif
-
- if (ds_num != ds->ds_num)
- {
- ds_free (ds_num, ds_def);
- return (-1);
- }
-
- *ret = ds_def;
- return (ds_num);
-}
-
#if HAVE_THREADSAFE_LIBRRD
-static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, const char **argv)
-{
- int status;
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
-
- status = rrd_create_r (filename, pdp_step, last_up, argc, (void *) argv);
-
- if (status != 0)
- {
- WARNING ("rrdtool plugin: rrd_create_r (%s) failed: %s",
- filename, rrd_get_error ());
- }
-
- return (status);
-} /* int srrd_create */
-
static int srrd_update (char *filename, char *template,
int argc, const char **argv)
{
/* #endif HAVE_THREADSAFE_LIBRRD */
#else /* !HAVE_THREADSAFE_LIBRRD */
-static int srrd_create (char *filename, unsigned long pdp_step, time_t last_up,
- int argc, const char **argv)
-{
- int status;
-
- int new_argc;
- char **new_argv;
-
- char pdp_step_str[16];
- char last_up_str[16];
-
- new_argc = 6 + argc;
- new_argv = (char **) malloc ((new_argc + 1) * sizeof (char *));
- if (new_argv == NULL)
- {
- ERROR ("rrdtool plugin: malloc failed.");
- return (-1);
- }
-
- if (last_up == 0)
- last_up = time (NULL) - 10;
-
- ssnprintf (pdp_step_str, sizeof (pdp_step_str), "%lu", pdp_step);
- ssnprintf (last_up_str, sizeof (last_up_str), "%u", (unsigned int) last_up);
-
- new_argv[0] = "create";
- new_argv[1] = filename;
- new_argv[2] = "-s";
- new_argv[3] = pdp_step_str;
- new_argv[4] = "-b";
- new_argv[5] = last_up_str;
-
- memcpy (new_argv + 6, argv, argc * sizeof (char *));
- new_argv[new_argc] = NULL;
-
- pthread_mutex_lock (&librrd_lock);
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
-
- status = rrd_create (new_argc, new_argv);
- pthread_mutex_unlock (&librrd_lock);
-
- if (status != 0)
- {
- WARNING ("rrdtool plugin: rrd_create (%s) failed: %s",
- filename, rrd_get_error ());
- }
-
- sfree (new_argv);
-
- return (status);
-} /* int srrd_create */
-
static int srrd_update (char *filename, char *template,
int argc, const char **argv)
{
} /* int srrd_update */
#endif /* !HAVE_THREADSAFE_LIBRRD */
-static int rrd_create_file (char *filename, const data_set_t *ds, const value_list_t *vl)
-{
- char **argv;
- int argc;
- char **rra_def;
- int rra_num;
- char **ds_def;
- int ds_num;
- int status = 0;
-
- if (check_create_dir (filename))
- return (-1);
-
- if ((rra_num = rra_get (&rra_def, vl)) < 1)
- {
- ERROR ("rrd_create_file failed: Could not calculate RRAs");
- return (-1);
- }
-
- if ((ds_num = ds_get (&ds_def, ds, vl)) < 1)
- {
- ERROR ("rrd_create_file failed: Could not calculate DSes");
- return (-1);
- }
-
- argc = ds_num + rra_num;
-
- if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
- {
- char errbuf[1024];
- ERROR ("rrd_create failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (-1);
- }
-
- memcpy (argv, ds_def, ds_num * sizeof (char *));
- memcpy (argv + ds_num, rra_def, rra_num * sizeof (char *));
- argv[ds_num + rra_num] = NULL;
-
- assert (vl->time > 10);
- status = srrd_create (filename,
- (stepsize > 0) ? stepsize : vl->interval,
- vl->time - 10,
- argc, (const char **)argv);
-
- free (argv);
- ds_free (ds_num, ds_def);
- rra_free (rra_num, rra_def);
-
- return (status);
-}
-
static int value_list_to_string (char *buffer, int buffer_len,
const data_set_t *ds, const value_list_t *vl)
{
} /* int value_list_to_string */
static int value_list_to_filename (char *buffer, int buffer_len,
- const data_set_t *ds, const value_list_t *vl)
+ const data_set_t __attribute__((unused)) *ds, const value_list_t *vl)
{
int offset = 0;
int status;
return (0);
} /* int value_list_to_filename */
-static void *rrd_queue_thread (void *data)
+static void *rrd_queue_thread (void __attribute__((unused)) *data)
{
struct timeval tv_next_update;
struct timeval tv_now;
rrd_cache_t *cache_entry;
char **values;
int values_num;
+ int status;
int i;
pthread_mutex_lock (&queue_lock);
while (true)
{
struct timespec ts_wait;
- int status;
while ((flushq_head == NULL) && (queue_head == NULL)
&& (do_shutdown == 0))
break;
gettimeofday (&tv_now, /* timezone = */ NULL);
- status = timeval_sub_timespec (&tv_next_update, &tv_now,
- &ts_wait);
+ status = timeval_cmp (tv_next_update, tv_now, NULL);
/* We're good to go */
- if (status != 0)
+ if (status <= 0)
break;
/* We're supposed to wait a bit with this update, so we'll
* we make a copy of it's values */
pthread_mutex_lock (&cache_lock);
- c_avl_get (cache, queue_entry->filename, (void *) &cache_entry);
+ status = c_avl_get (cache, queue_entry->filename,
+ (void *) &cache_entry);
- values = cache_entry->values;
- values_num = cache_entry->values_num;
+ if (status == 0)
+ {
+ values = cache_entry->values;
+ values_num = cache_entry->values_num;
- cache_entry->values = NULL;
- cache_entry->values_num = 0;
- cache_entry->flags = FLAG_NONE;
+ cache_entry->values = NULL;
+ cache_entry->values_num = 0;
+ cache_entry->flags = FLAG_NONE;
+ }
pthread_mutex_unlock (&cache_lock);
+ if (status != 0)
+ {
+ sfree (queue_entry->filename);
+ sfree (queue_entry);
+ continue;
+ }
+
/* Update `tv_next_update' */
if (write_rate > 0.0)
{
pthread_mutex_lock (&cache_lock);
+ /* This shouldn't happen, but it did happen at least once, so we'll be
+ * careful. */
+ if (cache == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ WARNING ("rrdtool plugin: cache == NULL.");
+ return (-1);
+ }
+
c_avl_get (cache, filename, (void *) &rc);
if (rc == NULL)
{
if (errno == ENOENT)
{
- if (rrd_create_file (filename, ds, vl))
+ status = cu_rrd_create_file (filename,
+ ds, vl, &rrdcreate_config);
+ if (status != 0)
return (-1);
}
else
}
else if (strcasecmp ("StepSize", key) == 0)
{
- stepsize = atoi (value);
- if (stepsize < 0)
- stepsize = 0;
+ int temp = atoi (value);
+ if (temp > 0)
+ rrdcreate_config.stepsize = temp;
}
else if (strcasecmp ("HeartBeat", key) == 0)
{
- heartbeat = atoi (value);
- if (heartbeat < 0)
- heartbeat = 0;
+ int temp = atoi (value);
+ if (temp > 0)
+ rrdcreate_config.heartbeat = temp;
}
else if (strcasecmp ("RRARows", key) == 0)
{
"be greater than 0.\n");
return (1);
}
- rrarows = tmp;
+ rrdcreate_config.rrarows = tmp;
}
else if (strcasecmp ("RRATimespan", key) == 0)
{
{
dummy = NULL;
- tmp_alloc = realloc (rra_timespans_custom,
- sizeof (int) * (rra_timespans_custom_num + 1));
+ tmp_alloc = realloc (rrdcreate_config.timespans,
+ sizeof (int) * (rrdcreate_config.timespans_num + 1));
if (tmp_alloc == NULL)
{
fprintf (stderr, "rrdtool: realloc failed.\n");
free (value_copy);
return (1);
}
- rra_timespans_custom = tmp_alloc;
- rra_timespans_custom[rra_timespans_custom_num] = atoi (ptr);
- if (rra_timespans_custom[rra_timespans_custom_num] != 0)
- rra_timespans_custom_num++;
+ rrdcreate_config.timespans = tmp_alloc;
+ rrdcreate_config.timespans[rrdcreate_config.timespans_num] = atoi (ptr);
+ if (rrdcreate_config.timespans[rrdcreate_config.timespans_num] != 0)
+ rrdcreate_config.timespans_num++;
} /* while (strtok_r) */
- qsort (/* base = */ rra_timespans_custom,
- /* nmemb = */ rra_timespans_custom_num,
- /* size = */ sizeof (rra_timespans_custom[0]),
+ qsort (/* base = */ rrdcreate_config.timespans,
+ /* nmemb = */ rrdcreate_config.timespans_num,
+ /* size = */ sizeof (rrdcreate_config.timespans[0]),
/* compar = */ rrd_compare_numeric);
free (value_copy);
"be in the range 0 to 1 (exclusive).");
return (1);
}
- xff = tmp;
+ rrdcreate_config.xff = tmp;
}
else if (strcasecmp ("WritesPerSecond", key) == 0)
{
{
int status;
- if (stepsize < 0)
- stepsize = 0;
- if (heartbeat <= 0)
- heartbeat = 2 * stepsize;
+ if (rrdcreate_config.stepsize < 0)
+ rrdcreate_config.stepsize = 0;
+ if (rrdcreate_config.heartbeat <= 0)
+ rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
- if ((heartbeat > 0) && (heartbeat < interval_g))
+ if ((rrdcreate_config.heartbeat > 0)
+ && (rrdcreate_config.heartbeat < interval_g))
WARNING ("rrdtool plugin: Your `heartbeat' is "
"smaller than your `interval'. This will "
"likely cause problems.");
- else if ((stepsize > 0) && (stepsize < interval_g))
+ else if ((rrdcreate_config.stepsize > 0)
+ && (rrdcreate_config.stepsize < interval_g))
WARNING ("rrdtool plugin: Your `stepsize' is "
"smaller than your `interval'. This will "
"create needlessly big RRD-files.");
DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
" heartbeat = %i; rrarows = %i; xff = %lf;",
(datadir == NULL) ? "(null)" : datadir,
- stepsize, heartbeat, rrarows, xff);
+ rrdcreate_config.stepsize,
+ rrdcreate_config.heartbeat,
+ rrdcreate_config.rrarows,
+ rrdcreate_config.xff);
return (0);
} /* int rrd_init */
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_complain.h"
#include <pthread.h>
char *community;
int version;
void *sess_handle;
+ c_complain_t complaint;
uint32_t interval;
time_t next_update;
data_definition_t **data_list;
/*
* Private functions
*/
+/* Many functions to handle the configuration. {{{ */
/* First there are many functions which do configuration stuff. It's a big
* bloated and messy, I'm afraid. */
return (-1);
}
- hd->interval = (int) ci->values[0].value.number;
- if (hd->interval < 0)
- hd->interval = 0;
+ hd->interval = ci->values[0].value.number >= 0
+ ? (uint32_t) ci->values[0].value.number
+ : 0;
return (0);
} /* int csnmp_config_add_host_interval */
return (-1);
memset (hd, '\0', sizeof (host_definition_t));
hd->version = 2;
+ C_COMPLAIN_INIT (&hd->complaint);
hd->name = strdup (ci->values[0].value.string);
if (hd->name == NULL)
return (0);
} /* int csnmp_config */
-/* End of the config stuff. Now the interesting part begins */
+/* }}} End of the config stuff. Now the interesting part begins */
static void csnmp_host_close_session (host_definition_t *host)
{
}
} /* void csnmp_host_open_session */
+ /* TODO: Check if negative values wrap around. Problem: negative temperatures. */
static value_t csnmp_value_list_to_value (struct variable_list *vl, int type,
double scale, double shift)
{
sstrncpy (vl.plugin, "snmp", sizeof (vl.plugin));
vl.interval = host->interval;
- vl.time = time (NULL);
subid = 0;
have_more = 1;
break;
}
- for (i = 0; i < oid_list_len; i++)
+ for (i = 0; (uint32_t) i < oid_list_len; i++)
snmp_add_null_var (req, oid_list[i].oid, oid_list[i].oid_len);
res = NULL;
char *errstr = NULL;
snmp_sess_error (host->sess_handle, NULL, NULL, &errstr);
- ERROR ("snmp plugin: host %s: snmp_sess_synch_response failed: %s",
+
+ c_complain (LOG_ERR, &host->complaint,
+ "snmp plugin: host %s: snmp_sess_synch_response failed: %s",
host->name, (errstr == NULL) ? "Unknown problem" : errstr);
if (res != NULL)
}
status = 0;
assert (res != NULL);
+ c_release (LOG_INFO, &host->complaint,
+ "snmp plugin: host %s: snmp_sess_synch_response successful.",
+ host->name);
vb = res->variables;
if (vb == NULL)
return (-1);
}
- vl.time = time (NULL);
for (vb = res->variables; vb != NULL; vb = vb->next_variable)
{
time_end = time (NULL);
DEBUG ("snmp plugin: csnmp_read_host (%s) finished at %u;", host->name,
(unsigned int) time_end);
- if ((time_end - time_start) > host->interval)
+ if ((uint32_t) (time_end - time_start) > host->interval)
{
WARNING ("snmp plugin: Host `%s' should be queried every %i seconds, "
"but reading all values takes %u seconds.",
return (0);
} /* int csnmp_read_host */
-static void *csnmp_read_thread (void *data)
+static void *csnmp_read_thread (void __attribute__((unused)) *data)
{
host_definition_t *host;
{
host->interval = interval_g;
}
- else if (host->interval < interval_g)
+ else if (host->interval < (uint32_t) interval_g)
{
host->interval = interval_g;
WARNING ("snmp plugin: Data for host `%s' will be collected every %i seconds.",
} /* void module_register */
/*
- * vim: shiftwidth=2 softtabstop=2 tabstop=8
+ * vim: shiftwidth=2 softtabstop=2 tabstop=8 fdm=marker
*/