From: Florian Forster Date: Fri, 16 Sep 2016 08:50:34 +0000 (+0200) Subject: Merge branch 'pr/1918' X-Git-Tag: collectd-5.7.0~77 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=6f4f918d4d5e70c75471632254ecb9c55fd8d62f;hp=03542f95bdf02fc0a02f16038e0c4460ddcde01f;p=collectd.git Merge branch 'pr/1918' --- diff --git a/ChangeLog b/ChangeLog index 4e969b59..51559545 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,161 @@ +2016-09-11, Version 5.6.0 + * Build system: An option to to avoid building the DF plugin against XFS + has been added. Thanks to Ruben Kerkhof. #1878 + * Build system: Autoconf ≥ 2.60, a C99-capable compiler and pkg-config + are now required. Thanks to Ruben Kerkhof. + * Build system: Building with "-Werror" is now optional. Thanks to Ruben + Kerkhof. #1222 + * Build system: Many compilation issues on non-Linux platforms have been + fixed, leading to wider plugin support. Thanks to Ruben Kerkhof, + Dagobert Michelsen, Havard Eidnes and Robert Viduya. + * Build system: The configuration summary now also ends up in + config.log. Thanks to Sebastian Harl. + * collectd: All command-line options now override global options from + the config file. Thanks to Sebastian Harl. #366 + * collectd: A number of unit tests for commonly used functions have been + added. Thanks to Florian Forster. + * collectd: Plugins start up and read timeouts are now logged. Thanks to + Marc Fournier. #1293, #1254 + * collectd: Support for a timeout has been added to "FLUSH" callbacks. + Thanks to Manuel Luis Sanmartín Rozada. + * collectd: The "-T" command line switch now reports more errors. Thanks + to Corey Kosak. #1642 + * collectd: The max size of value list elements ("DATA_MAX_NAME_LEN") + has been doubled and is now configurable at build time. Thanks to Amy + Lin, Florian Forster and Radu Brumariu. #1120 + * Set target: The "MetaData" option has been added. Thanks to Yves + Mettier and Kevin Bowling. #1106, #1656, #1913 + * AMQP, Write_HTTP, Write_Kafka plugins: Support for libyajl < 2 has + been added. Thanks to Florian Forster. + * APC UPS plugin: Parsing of end markers has been fixed. Thanks to + Florian Forster #617 + * APC UPS plugin: The "PersistentConnection" option has been added. + Thanks to Florian Forster #617 + * ceph, DNS, Exec, IPTables, Ping, turbostat plugins: When running + unprivileged, these plugins will now warn about insuffiscient + permissions or capabilities(7). Thanks to Marc Fournier. #1530 + * Chrony plugin: This new plugin collects NTP data from the chrony NTP + server. Thanks to Claudius Zingerli. #1548 + * cpusleep plugin: This new plugin measures time spent by CPU in deep + sleep mode. Thanks to Rinigus. #1826 + * CPU plugin: The "ReportNumCpu" option has been added. Thanks to Fabien + Wernli. + * cURL, cURL-JSON, cURL-XML plugins: The new "Statistics" reports + various per-HTTP connection timers. Thanks to Sebastian Harl. #1004 + * DBI plugin: The "Interval" option has been added to "Database" blocks. + Thanks to Michal Bebjak. + * Disk plugin: Support for FreeBSD has been added. Thanks to Xin Li, + Brad Davis, Ruben Kerfhof and Kevin Bowling. + * Empty Counter match: Support for derives has been implemented. Thanks + to Florian Forster. #1813 + * GenericJMX plugin: Support for TabularData and the "PluginName" option + have been added. Thanks to David Crane. #1290, #1291 + * GPS plugin: This new plugin reports the number of sattelites seen by + and precision of a GPS receiver. Thanks to Nicolas Jourden. #1346 + * gRPC plugin: This new client and server plugin allows sending and + receiving metrics using the gRPC protocol. Comparable to the UnixSock + plugin, but using TCP and TLS. Thanks to Sebastian Harl and Florian + Forster. + * Interface plugin: Reporting dropped packets has been added. Thanks to + Marc Falzon. #1555 + * Interface plugin: The "ReportInactive" has been added, letting users + skip inactive network interfaces. Thanks to Rinigus. #1791 + * Interface plugin: The new, Solaris-only "UniqueName" option has been + added. Thanks to Yoga Ramalingam. #1416 + * Lua plugin: This new language binding allows writing plugins using the + Lua programming language. Thanks to Julien Ammous, Florian Forster and + Ruben Kerkhof. + * Memory plugin: Reporting of ARC memory on Solaris has been added. + Thanks to Brian ONeill. + * MQTT plugin: This new plugin sends metrics to and/or receives metrics + from an MQTT broker. Thanks to Marc Falzon, Jan-Piet Mens, Nicholas + Humfrey and Florian Forster. #805, #1124 + * MySQL plugin: Connection to the database server can now be done over + SSL. Thanks to Brian Lalor. #1256 + * MySQL plugin: Monitoring slow queries has been added. Thanks to skob. + #1773 + * MySQL plugin: mysql_bpool_pages-flushed has been renamed to + mysql_bpool_counters-pages_flushed because the value is cumulative. + Thanks to Marek Becka. + * MySQL plugin: Support for Galera statistics has been added. Thanks to + Rachid Zarouali. #1849 + * MySQL plugin: Support for InnoDB metrics was improved. Thanks to Aman + Gupta. #1111 + * MySQL plugin: The "mysql_sort" type has been split into 3 different + types. Thanks to Pavel Rochnyack. #1592 + * Network plugin: Decryption error logging has been improved. Thanks to + Pavel Rochnyack. #1735 + * Notify Nagios plugin: This new plugin sends notifications to Nagios as + a passive check result. Thanks to Florian Forster. + * NTPd plugin: The plugin now detects if the ntp daemon reports + nanoseconds instead of microseconds. Thanks to Matwey V. Kornilov. + #1783 + * OpenLDAP plugin: Several connection-related improvements have been + made. Thanks to Marc Fournier. #1308 + * OpenLDAP plugin: Support for "simple authentication" has been added. + Thanks to Marek Becka. #1087 + * Ping plugin: The "Size" option has been added, allowing the ICMP data + payload size to be configured. Thanks to Witold Baryluk. #1395 + * PostgreSQL, DBI, Oracle plugins: The new "PluginInstanceFrom" option + has been added. Thanks to Pavel Rochnyack. #1707 + * PowerDNS plugin: The recursor metrics have been updated to 3.7.3 and + missing rr types have been added. Thanks to Ruben Kerkhof. + * Processes plugin: Counting of context switches was added for Linux. + Thanks to Manuel Luis Sanmartín Rozada. #1036 + * Processes plugin: Improve reliability of thread counts on Linux. + Thanks to Manuel Luis Sanmartín Rozada. + * Python plugin: Minimal Python version requirement has been bumped to + 2.6. Thanks to Ruben Kerkhof. #1864 + * Redis plugin: Several additional metrics are now collected. Thanks to + Marc Falzon and Matteo Contrini. #1807, #1483 + * Sensors plugin: The "UseLabels" option has been added. Thanks to + Christian Fetzer. + * SMART plugin: The new "IgnoreSleepMode" option has been added. Thanks + to Scott Talbert. #1770 + * SMART plugin: The new "UseSerial" option allows identifying devices in + a stable way. Thanks to Scott Talbert. #1794 + * SNMP plugin: The "IpAddress" can now be used for instances. Thanks to + Vincent Bernat. #1397 + * StatsD plugin: Latency calculation histogram is now able to shrink + automatically to optimal size. Thanks to Pavel Rochnyack. #1622 + * StatsD plugin: The "CounterSum" option has been added. Thanks to + Florian Forster. #929, #1282, #1311 + * UUID plugin: The plugin now also looks in in smbios system table and + "/sys/class/dmi". Thanks to Ruben Kerkhof. #1490 + * virt plugin: The "PluginInstanceFormat" option has been added. Thanks + to Ruben Kerkhof. #1100 + * Write Graphite plugin: The "ReconnectInterval" option has been added. + Thanks to Toni Moreno and Florian Forster. + * Write HTTP plugin: A KairosDB formatter has been added. Thanks to + Aurélien Rougemont. #1809 + * Write HTTP plugin: Notifications are now handled by this plugin. + Thanks to Florian Forster. + * Write HTTP plugin: The "LogHttpError" option has been added. Thanks to + vzubko. + * Write HTTP plugin: The new "Headers" option allows setting custom HTTP + headers in outgoing requests. Thanks to Brandon Arp. #1634 + * Write Kafka plugin: Key handling has been made more comprehensive and + reliable. Thanks to Florian Forster, Pierre-Yves Ritschard and Vincent + Bernat. #1765, #1695, #1393 + * Write Redis plugin: The "Database", "MaxSetSize", "Prefix" and + "StoreRates" options have been added. Thanks to Brian Kelly and + Sebastian Pfahl. + * Write Riemann plugin: The new "BatchFlushTimeout" and "Timeout" option + have been added. Thanks to Pierre-Yves Ritschard and Gergely Nagy. + * Write Riemann plugin: This plugin now requires the riemann-c-client + library, version 1.6.0+. This adds support for submitting values to + Riemann over TLS. Thanks to Gergely Nagy. #986 + * Write TSDB, Write Sensu, Write Riemann, Write Graphite, Write TSDB + plugin: TCP keepalive is now enabled, helping graceful recovery from + unclean network disconnections. Thanks to Marc Fournier. #1549 + * XenCPU plugin: This new plugin collects XEN Hypervisor CPU stats. + Thanks to Pavel Rochnyack. #1608 + * ZFS ARC plugin: Several new statistics have been added and a couple of + obsolete ones removed. Thanks to Brad Davis, Brian ONeill and Ruben + Kerkhof. + * Zone plugin: This new plugin reads per-zone CPU usage on Solaris. + Thanks to Mathijs Mohlmann and Dagobert Michelsen. + 2016-07-25, Version 5.5.2 * collectd: A division by zero has been fixed in the "plugin_dispatch_multivalue()" function. Thanks to Corey Kosak. diff --git a/bindings/perl/lib/Collectd.pm b/bindings/perl/lib/Collectd.pm index c1adf442..7e89e45f 100644 --- a/bindings/perl/lib/Collectd.pm +++ b/bindings/perl/lib/Collectd.pm @@ -172,7 +172,6 @@ sub plugin_call_all { my $type = shift; my %plugins; - my $interval; our $cb_name = undef; @@ -181,13 +180,13 @@ sub plugin_call_all { } if (TYPE_LOG != $type) { - DEBUG ("Collectd::plugin_call: type = \"$type\" (" + DEBUG ("Collectd::plugin_call_all: type = \"$type\" (" . $types{$type} . "), args=\"" . join(', ', map { defined($_) ? $_ : '' } @_) . "\""); } if (! defined $plugins[$type]) { - ERROR ("Collectd::plugin_call: unknown type \"$type\""); + ERROR ("Collectd::plugin_call_all: unknown type \"$type\""); return; } @@ -196,21 +195,9 @@ 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; - } - - next if ($p->{'wait_left'} > 0); - - $cb_name = $p->{'cb_name'}; - $status = call_by_name (@_); + $cb_name = $plugins{$plugin}; + my $status = call_by_name (@_); if (! $status) { my $err = undef; @@ -230,23 +217,7 @@ sub plugin_call_all { } if ($status) { - $p->{'wait_left'} = 0; - $p->{'wait_time'} = $interval; - } - elsif (TYPE_READ == $type) { - if ($p->{'wait_time'} < $interval) { - $p->{'wait_time'} = $interval; - } - - $p->{'wait_left'} = $p->{'wait_time'}; - $p->{'wait_time'} *= 2; - - if ($p->{'wait_time'} > 86400) { - $p->{'wait_time'} = 86400; - } - - WARNING ("${plugin}->read() failed with status $status. " - . "Will suspend it for $p->{'wait_left'} seconds."); + #NOOP } elsif (TYPE_INIT == $type) { ERROR ("${plugin}->init() failed with status $status. " @@ -309,21 +280,29 @@ sub plugin_register { } elsif ((TYPE_DATASET != $type) && (! ref $data)) { my $pkg = scalar caller; - - my %p : shared; - if ($data !~ m/^$pkg\:\:/) { $data = $pkg . "::" . $data; } - - %p = ( - wait_time => plugin_get_interval (), - wait_left => 0, - cb_name => $data, - ); - + if (TYPE_READ == $type) { + return plugin_register_read($name, $data); + } + if (TYPE_WRITE == $type) { + return plugin_register_write($name, $data); + } + if (TYPE_LOG == $type) { + return plugin_register_log($name, $data); + } + if (TYPE_NOTIF == $type) { + return plugin_register_notification($name, $data); + } + if (TYPE_FLUSH == $type) { + #For collectd-5.6 only + lock %{$plugins[$type]}; + $plugins[$type]->{$name} = $data; + return plugin_register_flush($name, $data); + } lock %{$plugins[$type]}; - $plugins[$type]->{$name} = \%p; + $plugins[$type]->{$name} = $data; } else { ERROR ("Collectd::plugin_register: Invalid data."); @@ -351,6 +330,21 @@ sub plugin_unregister { lock %cf_callbacks; delete $cf_callbacks{$name}; } + elsif (TYPE_READ == $type) { + return plugin_unregister_read ($name); + } + elsif (TYPE_WRITE == $type) { + return plugin_unregister_write($name); + } + elsif (TYPE_LOG == $type) { + return plugin_unregister_log ($name); + } + elsif (TYPE_NOTIF == $type) { + return plugin_unregister_notification($name); + } + elsif (TYPE_FLUSH == $type) { + return plugin_unregister_flush($name); + } elsif (defined $plugins[$type]) { lock %{$plugins[$type]}; delete $plugins[$type]->{$name}; diff --git a/contrib/examples/myplugin.c b/contrib/examples/myplugin.c index e1b89f6c..71fb5f8b 100644 --- a/contrib/examples/myplugin.c +++ b/contrib/examples/myplugin.c @@ -85,36 +85,50 @@ static int my_init (void) } /* static int my_init (void) */ /* - * This function is called in regular intervalls to collect the data. + * This is a utility function used by the read callback to populate a + * value_list_t and pass it to plugin_dispatch_values. */ -static int my_read (void) +static int my_submit (gauge_t value) { - value_t values[1]; /* the size of this list should equal the number of - data sources */ value_list_t vl = VALUE_LIST_INIT; - /* do the magic to read the data */ - values[0].gauge = random (); - - vl.values = values; + /* Convert the gauge_t to a value_t and add it to the value_list_t. */ + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; - vl.time = time (NULL); + + /* Only set vl.time yourself if you update multiple metrics (i.e. you + * have multiple calls to plugin_dispatch_values()) and they need to all + * have the same timestamp. */ + /* vl.time = cdtime(); */ + sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin)); /* it is strongly recommended to use a type defined in the types.db file * instead of a custom type */ - sstrncpy (vl.type, "myplugin", sizeof (vl.plugin)); + sstrncpy (vl.type, "myplugin", sizeof (vl.type)); /* optionally set vl.plugin_instance and vl.type_instance to reasonable * values (default: "") */ /* dispatch the values to collectd which passes them on to all registered * write functions */ - plugin_dispatch_values (&vl); + return plugin_dispatch_values (&vl); +} + +/* + * This function is called in regular intervalls to collect the data. + */ +static int my_read (void) +{ + /* do the magic to read the data */ + gauge_t value = random (); + + if (my_submit (value) != 0) + WARNING ("myplugin plugin: Dispatching a random value failed."); /* A return value != 0 indicates an error and the plugin will be skipped * for an increasing amount of time. */ - return 0; + return 0; } /* static int my_read (void) */ /* diff --git a/contrib/migrate-4-5.px b/contrib/migrate-4-5.px index c2a95558..8e5a7ed4 100755 --- a/contrib/migrate-4-5.px +++ b/contrib/migrate-4-5.px @@ -104,8 +104,6 @@ our %TypesCounterToDerive = # {{{ 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"], diff --git a/src/Makefile.am b/src/Makefile.am index b76e43cd..3477dc24 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1285,6 +1285,7 @@ pkglib_LTLIBRARIES += write_log.la write_log_la_SOURCES = write_log.c \ utils_format_graphite.c utils_format_graphite.h write_log_la_LDFLAGS = $(PLUGIN_LDFLAGS) +write_log_la_LIBADD = libformat_json.la endif if BUILD_PLUGIN_WRITE_MONGODB diff --git a/src/amqp.c b/src/amqp.c index 89f051e8..06fd1f1d 100644 --- a/src/amqp.c +++ b/src/amqp.c @@ -1070,11 +1070,13 @@ static int camqp_config_connection (oconfig_item_t *ci, /* {{{ */ 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); + status = plugin_register_write (cbname, camqp_write, + &(user_data_t) { + .data = conf, + .free_func = camqp_config_free, + }); if (status != 0) { camqp_config_free (conf); diff --git a/src/apache.c b/src/apache.c index e10a15d4..578b8dee 100644 --- a/src/apache.c +++ b/src/apache.c @@ -239,23 +239,22 @@ static int config_add (oconfig_item_t *ci) if (status == 0) { - user_data_t ud = { - .data = st, - .free_func = apache_free - }; - char callback_name[3*DATA_MAX_NAME_LEN]; ssnprintf (callback_name, sizeof (callback_name), "apache/%s/%s", (st->host != NULL) ? st->host : hostname_g, - (st->name != NULL) ? st->name : "default"), + (st->name != NULL) ? st->name : "default"); status = plugin_register_complex_read (/* group = */ NULL, /* name = */ callback_name, /* callback = */ apache_read_host, /* interval = */ 0, - /* user_data = */ &ud); + &(user_data_t) { + .data = st, + .free_func = apache_free, + }); + } if (status != 0) @@ -412,19 +411,15 @@ static void submit_value (const char *type, const char *type_instance, } /* void submit_value */ static void submit_derive (const char *type, const char *type_instance, - derive_t c, apache_t *st) + derive_t d, apache_t *st) { - value_t v; - v.derive = c; - submit_value (type, type_instance, v, st); + submit_value (type, type_instance, (value_t) { .derive = d }, st); } /* void submit_derive */ static void submit_gauge (const char *type, const char *type_instance, gauge_t g, apache_t *st) { - value_t v; - v.gauge = g; - submit_value (type, type_instance, v, st); + submit_value (type, type_instance, (value_t) { .gauge = g }, st); } /* void submit_gauge */ static void submit_scoreboard (char *buf, apache_t *st) diff --git a/src/apcups.c b/src/apcups.c index af5f24c7..821bd65e 100644 --- a/src/apcups.c +++ b/src/apcups.c @@ -416,12 +416,9 @@ static int apcups_config (oconfig_item_t *ci) static void apc_submit_generic (const char *type, const char *type_inst, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apcups", sizeof (vl.plugin)); diff --git a/src/apple_sensors.c b/src/apple_sensors.c index 48fbcb91..06ca7a85 100644 --- a/src/apple_sensors.c +++ b/src/apple_sensors.c @@ -83,15 +83,9 @@ static int as_init (void) static void as_submit (const char *type, const char *type_instance, double val) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - DEBUG ("type = %s; type_instance = %s; val = %f;", - type, type_instance, val); - - values[0].gauge = val; - - vl.values = values; + vl.values = &(value_t) { .gauge = val }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "apple_sensors", sizeof (vl.plugin)); diff --git a/src/aquaero.c b/src/aquaero.c index 81a4efd4..08271f87 100644 --- a/src/aquaero.c +++ b/src/aquaero.c @@ -60,16 +60,13 @@ static void aquaero_submit (const char *type, const char *type_instance, double value) { const char *instance = conf_device?conf_device:"default"; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; /* Don't report undefined values. */ if (value == AQ5_FLOAT_UNDEF) return; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/ascent.c b/src/ascent.c index 11bb97f0..16568e6c 100644 --- a/src/ascent.c +++ b/src/ascent.c @@ -126,12 +126,9 @@ static int config_keys_num = STATIC_ARRAY_SIZE (config_keys); static int ascent_submit_gauge (const char *plugin_instance, /* {{{ */ const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ascent", sizeof (vl.plugin)); diff --git a/src/battery.c b/src/battery.c index 3e6d7bda..ebf41deb 100644 --- a/src/battery.c +++ b/src/battery.c @@ -78,12 +78,9 @@ static _Bool query_statefs = 0; static void battery_submit2 (char const *plugin_instance, /* {{{ */ char const *type, char const *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "battery", sizeof (vl.plugin)); @@ -392,47 +389,17 @@ static int sysfs_file_to_buffer(char const *dir, /* {{{ */ char const *basename, char *buffer, size_t buffer_size) { - int status; - FILE *fp; char filename[PATH_MAX]; + int status; ssnprintf (filename, sizeof (filename), "%s/%s/%s", dir, power_supply, basename); - /* No file isn't the end of the world -- not every system will be - * reporting the same set of statistics */ - if (access (filename, R_OK) != 0) - return ENOENT; - - fp = fopen (filename, "r"); - if (fp == NULL) - { - status = errno; - if (status != ENOENT) - { - char errbuf[1024]; - WARNING ("battery plugin: fopen (%s) failed: %s", filename, - sstrerror (status, errbuf, sizeof (errbuf))); - } + status = (int) read_file_contents (filename, buffer, buffer_size); + if (status < 0) return status; - } - - if (fgets (buffer, buffer_size, fp) == NULL) - { - status = errno; - if (status != ENODEV) - { - char errbuf[1024]; - WARNING ("battery plugin: fgets (%s) failed: %s", filename, - sstrerror (status, errbuf, sizeof (errbuf))); - } - fclose (fp); - return status; - } strstripnewline (buffer); - - fclose (fp); return 0; } /* }}} int sysfs_file_to_buffer */ diff --git a/src/battery_statefs.c b/src/battery_statefs.c index 53730ed0..03729fdb 100644 --- a/src/battery_statefs.c +++ b/src/battery_statefs.c @@ -51,18 +51,12 @@ SOFTWARE. #include #define STATEFS_ROOT "/run/state/namespaces/Battery/" -#define BUFFER_SIZE 512 - -static int submitted_this_run = 0; static void battery_submit(const char *type, gauge_t value, const char *type_instance) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "battery", sizeof(vl.plugin)); @@ -72,67 +66,52 @@ static void battery_submit(const char *type, gauge_t value, if (type_instance != NULL) sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance)); plugin_dispatch_values(&vl); - - submitted_this_run++; -} - -static _Bool getvalue(const char *fname, gauge_t *value) { - FILE *fh; - char buffer[BUFFER_SIZE]; - - if ((fh = fopen(fname, "r")) == NULL) { - WARNING("battery plugin: cannot open StateFS file %s", fname); - return (0); - } - - if (fgets(buffer, STATIC_ARRAY_SIZE(buffer), fh) == NULL) { - fclose(fh); - return (0); // empty file - } - - (*value) = atof(buffer); - - fclose(fh); - - return (1); } /* cannot be static, is referred to from battery.c */ int battery_read_statefs(void) { - gauge_t value = NAN; - - submitted_this_run = 0; - - if (getvalue(STATEFS_ROOT "ChargePercentage", &value)) - battery_submit("charge", value, NULL); - // Use capacity as a charge estimate if ChargePercentage is not available - else if (getvalue(STATEFS_ROOT "Capacity", &value)) - battery_submit("charge", value, NULL); - - if (getvalue(STATEFS_ROOT "Current", &value)) - battery_submit("current", value * 1e-6, NULL); // from uA to A - - if (getvalue(STATEFS_ROOT "Energy", &value)) - battery_submit("energy_wh", value * 1e-6, NULL); // from uWh to Wh - - if (getvalue(STATEFS_ROOT "Power", &value)) - battery_submit("power", value * 1e-6, NULL); // from uW to W - - if (getvalue(STATEFS_ROOT "Temperature", &value)) - battery_submit("temperature", value * 0.1, NULL); // from 10xC to C - - if (getvalue(STATEFS_ROOT "TimeUntilFull", &value)) - battery_submit("duration", value, "full"); - - if (getvalue(STATEFS_ROOT "TimeUntilLow", &value)) - battery_submit("duration", value, "low"); + value_t v; + int success = 0; + + if (parse_value_file(STATEFS_ROOT "ChargePercentage", &v, DS_TYPE_GAUGE) == 0) { + battery_submit("charge", v.gauge, NULL); + success++; + } else if (parse_value_file(STATEFS_ROOT "Capacity", &v, DS_TYPE_GAUGE) == 0) { + // Use capacity as a charge estimate if ChargePercentage is not available + battery_submit("charge", v.gauge, NULL); + success++; + } else { + WARNING("battery plugin: Neither \""STATEFS_ROOT"ChargePercentage\" " + "nor \""STATEFS_ROOT"Capacity\" could be read."); + } - if (getvalue(STATEFS_ROOT "Voltage", &value)) - battery_submit("voltage", value * 1e-6, NULL); // from uV to V + struct { + char *path; + char *type; + char *type_instance; + gauge_t factor; + } metrics[] = { + {STATEFS_ROOT "Current", "current", NULL, 1e-6}, // from uA to A + {STATEFS_ROOT "Energy", "energy_wh", NULL, 1e-6}, // from uWh to Wh + {STATEFS_ROOT "Power", "power", NULL, 1e-6}, // from uW to W + {STATEFS_ROOT "Temperature", "temperature", NULL, 0.1}, // from 10xC to C + {STATEFS_ROOT "TimeUntilFull", "duration", "full", 1.0}, + {STATEFS_ROOT "TimeUntilLow", "duration", "low", 1.0}, + {STATEFS_ROOT "Voltage", "voltage", NULL, 1e-6}, // from uV to V + }; + + for (size_t i = 0; i < STATIC_ARRAY_SIZE(metrics); i++) { + if (parse_value_file(metrics[i].path, &v, DS_TYPE_GAUGE) != 0) { + WARNING("battery plugin: Reading \"%s\" failed.", metrics[i].path); + continue; + } + + battery_submit(metrics[i].type, v.gauge * metrics[i].factor, metrics[i].type_instance); + success++; + } - if (submitted_this_run == 0) { - ERROR("battery plugin: statefs backend: none of the statistics are " - "available"); + if (success == 0) { + ERROR("battery plugin: statefs backend: none of the statistics are available"); return (-1); } diff --git a/src/bind.c b/src/bind.c index 9b6b32e3..09de4a3f 100644 --- a/src/bind.c +++ b/src/bind.c @@ -247,12 +247,9 @@ static int memsummary_translation_table_length = static void submit (time_t ts, const char *plugin_instance, /* {{{ */ const char *type, const char *type_instance, value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0] = value; - - vl.values = values; + vl.values = &value; vl.values_len = 1; if (config_parse_time) vl.time = TIME_T_TO_CDTIME_T (ts); diff --git a/src/chrony.c b/src/chrony.c index f6294e49..353ede79 100644 --- a/src/chrony.c +++ b/src/chrony.c @@ -677,12 +677,9 @@ ntohf(tFloat p_float) static void chrony_push_data(const char *p_type, const char *p_type_inst, double p_value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = p_value; /* TODO: Check type??? (counter, gauge, derive, absolute) */ - - vl.values = values; + vl.values = &(value_t) { .gauge = p_value }; vl.values_len = 1; /* XXX: Shall g_chrony_host/g_chrony_port be reflected in the plugin's output? */ diff --git a/src/collectd-perl.pod b/src/collectd-perl.pod index 0102e921..9af3c0c9 100644 --- a/src/collectd-perl.pod +++ b/src/collectd-perl.pod @@ -75,6 +75,20 @@ Adds I to the B<@INC> array. This is the same as using the B<-IDir> command line option or B in the source code. Please note that it only has effect on plugins loaded after this option. +=item B I + +The C used to register one flush callback (called B<"perl">) and +call all Perl-based flush handlers when this callback was called. Newer versions +of the plugin wrap the Perl flush handlers and register them directly with the +daemon I to the legacy B<"perl"> callback. This allows to call +specific Perl flush handlers, but has the downside that flushing I plugins +now calls the Perl flush handlers twice (once directly and once via the legacy +callback). Unfortunately, removing the B<"perl"> callback would break backwards +compatibility. + +This option allows you to disable the legacy B<"perl"> flush callback if you care +about the double call and don't call the B<"perl"> callback in your setup. + =back =head1 WRITING YOUR OWN PLUGINS @@ -759,18 +773,6 @@ dispatched by the perl plugin after upgrades. =back -=head1 KNOWN BUGS - -=over 4 - -=item * - -Currently, it is not possible to flush a single Perl plugin only. You can -either flush all Perl plugins or none at all and you have to use C as -plugin name when doing so. - -=back - =head1 SEE ALSO L, diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 0fc13dcc..345af3d5 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -597,8 +597,11 @@ # # -# ReportPerNodeHP "true" -# ReportRootHP "true" +# ReportPerNodeHP true +# ReportRootHP true +# ValuesPages true +# ValuesBytes false +# ValuesPercentage false # # @@ -1415,6 +1418,8 @@ # StoreRates true # AlwaysAppendDS false # EscapeCharacter "_" +# SeparateInstances false +# DropDuplicateFields false # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 20d8c6b6..9d4b7918 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -241,6 +241,12 @@ Path to the plugins (shared objects) of collectd. Set one or more files that contain the data-set descriptions. See L for a description of the format of this file. +If this option is not specified, a default file is read. If you need to define +custom types in addition to the types defined in the default file, you need to +explicitly load both. In other words, if the B option is encountered +the default behavior is disabled and if you need the default types you have to +also explicitly load them. + =item B I Configures the interval in which to query the read plugins. Obviously smaller @@ -2830,20 +2836,35 @@ options (default is enabled). =over 4 -=item B I|I +=item B B|B If enabled, information will be collected from the hugepage counters in "/sys/devices/system/node/*/hugepages". This is used to check the per-node hugepage statistics on a NUMA system. -=item B I|I +=item B B|B If enabled, information will be collected from the hugepage counters in "/sys/kernel/mm/hugepages". This can be used on both NUMA and non-NUMA systems to check the overall hugepage statistics. +=item B B|B + +Whether to report hugepages metrics in number of pages. +Defaults to B. + +=item B B|B + +Whether to report hugepages metrics in bytes. +Defaults to B. + +=item B B|B + +Whether to report hugepages metrics as percentage. +Defaults to B. + =back =head2 Plugin C @@ -7818,6 +7839,32 @@ If set to B, append the name of the I (DS) to the "metric" identifier. If set to B (the default), this is only done when there is more than one DS. +=item B B|B + +If set to B, detect and remove duplicate components in Graphite metric +names. For example, the metric name C will +be shortened to C. + +=back + +=head2 Plugin C + +The C plugin writes metrics as INFO log messages. + +This plugin supports two output formats: I and I. + +Synopsis: + + + Format Graphite + + +=over 4 + +=item B I + +The output format to use. Can be one of C or C. + =back =head2 Plugin C @@ -9093,6 +9140,8 @@ Available options: =item B I +=item B I I + Match values where the given regular expressions match the various fields of the identifier of a value. If multiple regular expressions are given, B regexen must match for a value to match. @@ -9381,6 +9430,10 @@ Available options: =item B I I +=item B I I I + +=item B I I + Match the appropriate field with the given regular expression I. If the regular expression matches, that part that matches is replaced with I. If multiple places of the input buffer match a given regular @@ -9419,9 +9472,37 @@ Available options: =item B I I -Set the appropriate field to the given string. The strings for plugin instance -and type instance may be empty, the strings for host and plugin may not be -empty. It's currently not possible to set the type of a value this way. +Set the appropriate field to the given string. The strings for plugin instance, +type instance, and meta data may be empty, the strings for host and plugin may +not be empty. It's currently not possible to set the type of a value this way. + +The following placeholders will be replaced by an appropriate value: + +=over 4 + +=item B<%{host}> + +=item B<%{plugin}> + +=item B<%{plugin_instance}> + +=item B<%{type}> + +=item B<%{type_instance}> + +These placeholders are replaced by the identifier field of the same name. + +=item B<%{meta:>IB<}> + +These placeholders are replaced by the meta data value with the given name. + +=back + +Please note that these placeholders are B! + +=item B I + +Delete the named meta data field. =back diff --git a/src/conntrack.c b/src/conntrack.c index ce90ede3..4a72b2f6 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -74,61 +74,26 @@ static void conntrack_submit (const char *type, const char *type_instance, static int conntrack_read (void) { value_t conntrack, conntrack_max, conntrack_pct; - FILE *fh; - char buffer[64] = { 0 }; - size_t buffer_len; - fh = fopen (old_files?CONNTRACK_FILE_OLD:CONNTRACK_FILE, "r"); - if (fh == NULL) - return (-1); - - if (fgets (buffer, sizeof (buffer), fh) == NULL) + char const *path = old_files ? CONNTRACK_FILE_OLD : CONNTRACK_FILE; + if (parse_value_file (path, &conntrack, DS_TYPE_GAUGE) != 0) { - fclose (fh); + ERROR ("conntrack plugin: Reading \"%s\" failed.", path); return (-1); } - fclose (fh); - /* strip trailing newline. */ - buffer_len = strlen (buffer); - while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1])) + path = old_files ? CONNTRACK_MAX_FILE_OLD : CONNTRACK_MAX_FILE; + if (parse_value_file (path, &conntrack_max, DS_TYPE_GAUGE) != 0) { - buffer[buffer_len - 1] = 0; - buffer_len--; - } - - if (parse_value (buffer, &conntrack, DS_TYPE_GAUGE) != 0) - return (-1); - - conntrack_submit ("conntrack", NULL, conntrack); - - fh = fopen (old_files?CONNTRACK_MAX_FILE_OLD:CONNTRACK_MAX_FILE, "r"); - if (fh == NULL) - return (-1); - - memset (buffer, 0, sizeof (buffer)); - if (fgets (buffer, sizeof (buffer), fh) == NULL) - { - fclose (fh); + ERROR ("conntrack plugin: Reading \"%s\" failed.", path); return (-1); } - fclose (fh); - - /* strip trailing newline. */ - buffer_len = strlen (buffer); - while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1])) - { - buffer[buffer_len - 1] = 0; - buffer_len--; - } - - if (parse_value (buffer, &conntrack_max, DS_TYPE_GAUGE) != 0) - return (-1); - conntrack_submit ("conntrack", "max", conntrack_max); conntrack_pct.gauge = (conntrack.gauge / conntrack_max.gauge) * 100; - conntrack_submit ("percent", "used", conntrack_pct); + conntrack_submit ("conntrack", NULL, conntrack); + conntrack_submit ("conntrack", "max", conntrack_max); + conntrack_submit ("percent", "used", conntrack_pct); return (0); } /* static int conntrack_read */ diff --git a/src/contextswitch.c b/src/contextswitch.c index 76e2a6c0..3bd6d9f5 100644 --- a/src/contextswitch.c +++ b/src/contextswitch.c @@ -49,12 +49,9 @@ static void cs_submit (derive_t context_switches) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = (derive_t) context_switches; - - vl.values = values; + vl.values = &(value_t) { .derive = context_switches }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "contextswitch", sizeof (vl.plugin)); diff --git a/src/cpu.c b/src/cpu.c index 1ac5b4a3..fbd07143 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -325,12 +325,9 @@ static int init (void) static void submit_value (int cpu_num, int cpu_state, const char *type, value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - memcpy(&values[0], &value, sizeof(value)); - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -346,26 +343,22 @@ static void submit_value (int cpu_num, int cpu_state, const char *type, value_t plugin_dispatch_values (&vl); } -static void submit_percent(int cpu_num, int cpu_state, gauge_t percent) +static void submit_percent (int cpu_num, int cpu_state, gauge_t value) { - value_t value; - /* This function is called for all known CPU states, but each read * method will only report a subset. The remaining states are left as * NAN and we ignore them here. */ - if (isnan (percent)) + if (isnan (value)) return; - value.gauge = percent; - submit_value (cpu_num, cpu_state, "percent", value); + submit_value (cpu_num, cpu_state, "percent", + (value_t) { .gauge = value }); } -static void submit_derive(int cpu_num, int cpu_state, derive_t derive) +static void submit_derive (int cpu_num, int cpu_state, derive_t value) { - value_t value; - - value.derive = derive; - submit_value (cpu_num, cpu_state, "cpu", value); + submit_value (cpu_num, cpu_state, "cpu", + (value_t) { .derive = value }); } /* Takes the zero-index number of a CPU and makes sure that the module-global @@ -464,14 +457,11 @@ static void cpu_commit_one (int cpu_num, /* {{{ */ } /* }}} void cpu_commit_one */ /* Commits the number of cores */ -static void cpu_commit_num_cpu (gauge_t num_cpu) /* {{{ */ +static void cpu_commit_num_cpu (gauge_t value) /* {{{ */ { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = num_cpu; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -555,7 +545,7 @@ static int cpu_stage (size_t cpu_num, size_t state, derive_t d, cdtime_t now) /* int status; cpu_state_t *s; gauge_t rate = NAN; - value_t val = {.derive = d}; + value_t val = { .derive = d }; if (state >= COLLECTD_CPU_STATE_ACTIVE) return (EINVAL); diff --git a/src/cpufreq.c b/src/cpufreq.c index 1e9e8579..a2cc3ad2 100644 --- a/src/cpufreq.c +++ b/src/cpufreq.c @@ -25,8 +25,6 @@ #include "common.h" #include "plugin.h" -#define MODULE_NAME "cpufreq" - static int num_cpu = 0; static int cpufreq_init (void) @@ -59,72 +57,39 @@ static int cpufreq_init (void) return (0); } /* int cpufreq_init */ -static void cpufreq_submit (int cpu_num, double value) +static void cpufreq_submit (int cpu_num, value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "cpufreq", sizeof (vl.plugin)); sstrncpy (vl.type, "cpufreq", sizeof (vl.type)); - ssnprintf (vl.type_instance, sizeof (vl.type_instance), - "%i", cpu_num); + ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%i", cpu_num); plugin_dispatch_values (&vl); } static int cpufreq_read (void) { - int status; - unsigned long long val; - FILE *fp; - char filename[256]; - char buffer[16]; - for (int i = 0; i < num_cpu; i++) { - status = ssnprintf (filename, sizeof (filename), - "/sys/devices/system/cpu/cpu%d/cpufreq/" - "scaling_cur_freq", i); - if ((status < 1) || ((unsigned int)status >= sizeof (filename))) - return (-1); + char filename[PATH_MAX]; + ssnprintf (filename, sizeof (filename), + "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i); - if ((fp = fopen (filename, "r")) == NULL) + value_t v; + if (parse_value_file (filename, &v, DS_TYPE_GAUGE) != 0) { - char errbuf[1024]; - WARNING ("cpufreq: fopen (%s): %s", filename, - sstrerror (errno, errbuf, - sizeof (errbuf))); - return (-1); + WARNING ("cpufreq plugin: Reading \"%s\" failed.", filename); + continue; } - if (fgets (buffer, 16, fp) == NULL) - { - char errbuf[1024]; - WARNING ("cpufreq: fgets: %s", - sstrerror (errno, errbuf, - sizeof (errbuf))); - fclose (fp); - return (-1); - } - - if (fclose (fp)) - { - char errbuf[1024]; - WARNING ("cpufreq: fclose: %s", - sstrerror (errno, errbuf, - sizeof (errbuf))); - } - - - /* You're seeing correctly: The file is reporting kHz values.. */ - val = atoll (buffer) * 1000; + /* convert kHz to Hz */ + v.gauge *= 1000.0; - cpufreq_submit (i, val); + cpufreq_submit (i, v); } return (0); diff --git a/src/cpusleep.c b/src/cpusleep.c index 326c29ce..5de0e470 100644 --- a/src/cpusleep.c +++ b/src/cpusleep.c @@ -37,12 +37,9 @@ #include static void cpusleep_submit(derive_t cpu_sleep) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = cpu_sleep; - - vl.values = values; + vl.values = &(value_t) { .derive = cpu_sleep }; vl.values_len = 1; sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "cpusleep", sizeof(vl.plugin)); diff --git a/src/curl.c b/src/curl.c index 74ef13c9..8401e6ca 100644 --- a/src/curl.c +++ b/src/curl.c @@ -608,14 +608,11 @@ static int cc_init (void) /* {{{ */ } /* }}} int cc_init */ static void cc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */ - const cu_match_value_t *mv) + value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0] = mv->value; - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "curl", sizeof (vl.plugin)); @@ -629,12 +626,9 @@ static void cc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */ static void cc_submit_response_code (const web_page_t *wp, long code) /* {{{ */ { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = code; - - vl.values = values; + vl.values = &(value_t) { .gauge = (gauge_t) code }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "curl", sizeof (vl.plugin)); @@ -647,12 +641,9 @@ static void cc_submit_response_code (const web_page_t *wp, long code) /* {{{ */ static void cc_submit_response_time (const web_page_t *wp, /* {{{ */ cdtime_t response_time) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = CDTIME_T_TO_DOUBLE (response_time); - - vl.values = values; + vl.values = &(value_t) { .gauge = CDTIME_T_TO_DOUBLE (response_time) }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "curl", sizeof (vl.plugin)); @@ -714,7 +705,7 @@ static int cc_read_page (web_page_t *wp) /* {{{ */ continue; } - cc_submit (wp, wm, mv); + cc_submit (wp, wm, mv->value); match_value_reset (mv); } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */ diff --git a/src/curl_json.c b/src/curl_json.c index ab0237e1..4dab1abd 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -144,6 +144,9 @@ static int cj_get_type (cj_key_t *key) { const data_set_t *ds; + if ((key == NULL) || !CJ_IS_KEY (key)) + return -EINVAL; + ds = plugin_get_ds (key->type); if (ds == NULL) { @@ -227,12 +230,15 @@ static int cj_cb_number (void *ctx, buffer[sizeof (buffer) - 1] = 0; if ((key == NULL) || !CJ_IS_KEY (key)) { - if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/) + if (key != NULL && !db->state[db->depth].in_array/*can be inhomogeneous*/) { NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects" " a map.", buffer); + return (CJ_CB_CONTINUE); + } + cj_cb_inc_array_index (ctx, /* update_key = */ 1); key = db->state[db->depth].key; - if (key == NULL) { + if ((key == NULL) || !CJ_IS_KEY (key)) { return (CJ_CB_CONTINUE); } } @@ -769,14 +775,12 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */ cb_name = ssnprintf_alloc ("curl_json-%s-%s", db->instance, db->url ? db->url : db->sock); - user_data_t ud = { - .data = db, - .free_func = cj_free - }; - plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read, /* interval = */ db->interval, - &ud); + &(user_data_t) { + .data = db, + .free_func = cj_free, + }); sfree (cb_name); } else diff --git a/src/curl_xml.c b/src/curl_xml.c index c8a1313c..924665c7 100644 --- a/src/curl_xml.c +++ b/src/curl_xml.c @@ -1026,13 +1026,12 @@ static int cx_config_add_url (oconfig_item_t *ci) /* {{{ */ cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url); - user_data_t ud = { - .data = db, - .free_func = cx_free - }; - plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read, - /* interval = */ 0, &ud); + /* interval = */ 0, + &(user_data_t) { + .data = db, + .free_func = cx_free, + }); sfree (cb_name); } else diff --git a/src/daemon/common.c b/src/daemon/common.c index 05b11990..e2c872cc 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -334,50 +334,60 @@ int strsplit (char *string, char **fields, size_t size) return ((int) i); } -int strjoin (char *buffer, size_t buffer_size, - char **fields, size_t fields_num, - const char *sep) -{ - size_t avail; - char *ptr; - size_t sep_len; +int strjoin(char *buffer, size_t buffer_size, char **fields, size_t fields_num, + const char *sep) { + size_t avail = 0; + char *ptr = buffer; + size_t sep_len = 0; - if ((buffer_size < 1) || (fields_num == 0)) - return (-1); + size_t buffer_req = 0; - memset (buffer, 0, buffer_size); - ptr = buffer; - avail = buffer_size - 1; + if (((fields_num != 0) && (fields == NULL)) || + ((buffer_size != 0) && (buffer == NULL))) + return (-EINVAL); - sep_len = 0; - if (sep != NULL) - sep_len = strlen (sep); + if (buffer != NULL) + buffer[0] = 0; - for (size_t i = 0; i < fields_num; i++) - { - size_t field_len; + if (buffer_size != 0) + avail = buffer_size - 1; - if ((i > 0) && (sep_len > 0)) - { - if (avail < sep_len) - return (-1); + if (sep != NULL) + sep_len = strlen(sep); - memcpy (ptr, sep, sep_len); - ptr += sep_len; - avail -= sep_len; - } + for (size_t i = 0; i < fields_num; i++) { + size_t field_len = strlen(fields[i]); - field_len = strlen (fields[i]); - if (avail < field_len) - return (-1); + if (i != 0) + buffer_req += sep_len; + buffer_req += field_len; - memcpy (ptr, fields[i], field_len); - ptr += field_len; - avail -= field_len; - } + if ((i != 0) && (sep_len > 0)) { + if (sep_len >= avail) { + /* prevent subsequent iterations from writing to the + * buffer. */ + avail = 0; + continue; + } - assert (buffer[buffer_size - 1] == 0); - return ((int) strlen (buffer)); + memcpy(ptr, sep, sep_len); + + ptr += sep_len; + avail -= sep_len; + } + + if (field_len > avail) + field_len = avail; + + memcpy(ptr, fields[i], field_len); + ptr += field_len; + + avail -= field_len; + if (ptr != NULL) + *ptr = 0; + } + + return (int)buffer_req; } int escape_string (char *buffer, size_t buffer_size) @@ -1199,6 +1209,18 @@ int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds) return (0); } /* int parse_values */ +int parse_value_file (char const *path, value_t *ret_value, int ds_type) +{ + char buffer[256]; + + if (read_file_contents (path, buffer, sizeof (buffer)) < 0) + return errno; + + strstripnewline (buffer); + + return parse_value (buffer, ret_value, ds_type); +} /* int parse_value_file */ + #if !HAVE_GETPWNAM_R int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) diff --git a/src/daemon/common.h b/src/daemon/common.h index 720e5f1b..6d01ca4b 100644 --- a/src/daemon/common.h +++ b/src/daemon/common.h @@ -147,10 +147,12 @@ int strsplit (char *string, char **fields, size_t size); * is equivalent to the Perl built-in `join'. * * PARAMETERS - * `dst' Buffer where the result is stored. + * `dst' Buffer where the result is stored. Can be NULL if you need to + * determine the required buffer size only. * `dst_len' Length of the destination buffer. No more than this many * bytes will be written to the memory pointed to by `dst', - * including the trailing null-byte. + * including the trailing null-byte. Must be zero if dst is + * NULL. * `fields' Array of strings to be joined. * `fields_num' Number of elements in the `fields' array. * `sep' String to be inserted between any two elements of `fields'. @@ -158,9 +160,10 @@ int strsplit (char *string, char **fields, size_t size); * Instead of passing "" (empty string) one can pass NULL. * * RETURN VALUE - * Returns the number of characters in `dst', NOT including the trailing - * null-byte. If an error occurred (empty array or `dst' too small) a value - * smaller than zero will be returned. + * Returns the number of characters in the resulting string, excluding a + * tailing null byte. If this value is greater than or equal to "dst_len", the + * result in "dst" is truncated (but still null terminated). On error a + * negative value is returned. */ int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const char *sep); @@ -322,6 +325,11 @@ int parse_identifier_vl (const char *str, value_list_t *vl); int parse_value (const char *value, value_t *ret_value, int ds_type); int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds); +/* parse_value_file reads "path" and parses its content as an integer or + * floating point, depending on "ds_type". On success, the value is stored in + * "ret_value" and zero is returned. On failure, a non-zero value is returned. */ +int parse_value_file (char const *path, value_t *ret_value, int ds_type); + #if !HAVE_GETPWNAM_R int getpwnam_r (const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); diff --git a/src/daemon/common_test.c b/src/daemon/common_test.c index 202ddf6c..44e198dd 100644 --- a/src/daemon/common_test.c +++ b/src/daemon/common_test.c @@ -148,46 +148,54 @@ DEF_TEST(strsplit) return (0); } -DEF_TEST(strjoin) -{ - char buffer[16]; - char *fields[4]; - int status; - - fields[0] = "foo"; - fields[1] = "bar"; - fields[2] = "baz"; - fields[3] = "qux"; - - status = strjoin (buffer, sizeof (buffer), fields, 2, "!"); - OK(status == 7); - EXPECT_EQ_STR ("foo!bar", buffer); - - status = strjoin (buffer, sizeof (buffer), fields, 1, "!"); - OK(status == 3); - EXPECT_EQ_STR ("foo", buffer); - - status = strjoin (buffer, sizeof (buffer), fields, 0, "!"); - OK(status < 0); - - status = strjoin (buffer, sizeof (buffer), fields, 2, "rcht"); - OK(status == 10); - EXPECT_EQ_STR ("foorchtbar", buffer); - - status = strjoin (buffer, sizeof (buffer), fields, 4, ""); - OK(status == 12); - EXPECT_EQ_STR ("foobarbazqux", buffer); +DEF_TEST(strjoin) { + struct { + char **fields; + size_t fields_num; + char *separator; + + int want_return; + char *want_buffer; + } cases + [] = { + /* Normal case. */ + {(char *[]){"foo", "bar"}, 2, "!", 7, "foo!bar"}, + /* One field only. */ + {(char *[]){"foo"}, 1, "!", 3, "foo"}, + /* No fields at all. */ + {NULL, 0, "!", 0, ""}, + /* Longer separator. */ + {(char *[]){"foo", "bar"}, 2, "rcht", 10, "foorchtbar"}, + /* Empty separator. */ + {(char *[]){"foo", "bar"}, 2, "", 6, "foobar"}, + /* NULL separator. */ + {(char *[]){"foo", "bar"}, 2, NULL, 6, "foobar"}, + /* buffer not large enough -> string is truncated. */ + {(char *[]){"aaaaaa", "bbbbbb", "c!"}, 3, "-", 16, "aaaaaa-bbbbbb-c"}, + /* buffer not large enough -> last field fills buffer completely. */ + {(char *[]){"aaaaaaa", "bbbbbbb", "!"}, 3, "-", 17, + "aaaaaaa-bbbbbbb"}, + /* buffer not large enough -> string does *not* end in separator. */ + {(char *[]){"aaaa", "bbbb", "cccc", "!"}, 4, "-", 16, + "aaaa-bbbb-cccc"}, + /* buffer not large enough -> string does not end with partial + separator. */ + {(char *[]){"aaaaaa", "bbbbbb", "!"}, 3, "+-", 17, "aaaaaa+-bbbbbb"}, + }; + + for (size_t i = 0; i < STATIC_ARRAY_SIZE(cases); i++) { + char buffer[16]; + int status; - status = strjoin (buffer, sizeof (buffer), fields, 4, "!"); - OK(status == 15); - EXPECT_EQ_STR ("foo!bar!baz!qux", buffer); + memset(buffer, 0xFF, sizeof(buffer)); + status = strjoin(buffer, sizeof(buffer), cases[i].fields, + cases[i].fields_num, cases[i].separator); + EXPECT_EQ_INT(cases[i].want_return, status); + EXPECT_EQ_STR(cases[i].want_buffer, buffer); + } - fields[0] = "0123"; - fields[1] = "4567"; - fields[2] = "8901"; - fields[3] = "2345"; - status = strjoin (buffer, sizeof (buffer), fields, 4, "-"); - OK(status < 0); + /* use (NULL, 0) to determine required buffer size. */ + EXPECT_EQ_INT(3, strjoin(NULL, 0, (char *[]){"a", "b"}, 2, "-")); return (0); } diff --git a/src/daemon/meta_data.c b/src/daemon/meta_data.c index 9e4fd07e..a11fccb2 100644 --- a/src/daemon/meta_data.c +++ b/src/daemon/meta_data.c @@ -26,9 +26,12 @@ #include "collectd.h" +#include "common.h" #include "plugin.h" #include "meta_data.h" +#define MD_MAX_NONSTRING_CHARS 128 + /* * Data types */ @@ -729,4 +732,68 @@ int meta_data_get_boolean (meta_data_t *md, /* {{{ */ return (0); } /* }}} int meta_data_get_boolean */ +int meta_data_as_string (meta_data_t *md, /* {{{ */ + const char *key, char **value) +{ + meta_entry_t *e; + char *actual; + char buffer[MD_MAX_NONSTRING_CHARS]; /* For non-string types. */ + char *temp; + int type; + + if ((md == NULL) || (key == NULL) || (value == NULL)) + return (-EINVAL); + + pthread_mutex_lock (&md->lock); + + e = md_entry_lookup (md, key); + if (e == NULL) + { + pthread_mutex_unlock (&md->lock); + return (-ENOENT); + } + + type = e->type; + + switch (type) + { + case MD_TYPE_STRING: + actual = e->value.mv_string; + break; + case MD_TYPE_SIGNED_INT: + ssnprintf (buffer, sizeof (buffer), "%"PRIi64, e->value.mv_signed_int); + actual = buffer; + break; + case MD_TYPE_UNSIGNED_INT: + ssnprintf (buffer, sizeof (buffer), "%"PRIu64, e->value.mv_unsigned_int); + actual = buffer; + break; + case MD_TYPE_DOUBLE: + ssnprintf (buffer, sizeof (buffer), GAUGE_FORMAT, e->value.mv_double); + actual = buffer; + break; + case MD_TYPE_BOOLEAN: + actual = e->value.mv_boolean ? "true" : "false"; + break; + default: + pthread_mutex_unlock (&md->lock); + ERROR ("meta_data_as_string: unknown type %d for key `%s'", type, key); + return (-ENOENT); + } + + pthread_mutex_unlock (&md->lock); + + temp = md_strdup (actual); + if (temp == NULL) + { + pthread_mutex_unlock (&md->lock); + ERROR ("meta_data_as_string: md_strdup failed for key `%s'.", key); + return (-ENOMEM); + } + + *value = temp; + + return (0); +} /* }}} int meta_data_as_string */ + /* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/daemon/meta_data.h b/src/daemon/meta_data.h index 0398c546..f4a4f212 100644 --- a/src/daemon/meta_data.h +++ b/src/daemon/meta_data.h @@ -84,5 +84,10 @@ int meta_data_get_boolean (meta_data_t *md, const char *key, _Bool *value); +/* Returns the value as a string, regardless of the type. */ +int meta_data_as_string (meta_data_t *md, + const char *key, + char **value); + #endif /* META_DATA_H */ /* vim: set sw=2 sts=2 et : */ diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index c6efc3fe..d4b962fb 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -151,34 +151,28 @@ static const char *plugin_get_dir (void) } static void plugin_update_internal_statistics (void) { /* {{{ */ - derive_t copy_write_queue_length; - value_list_t vl = VALUE_LIST_INIT; - value_t values[2]; - copy_write_queue_length = write_queue_length; + gauge_t copy_write_queue_length = (gauge_t) write_queue_length; /* Initialize `vl' */ - vl.values = values; - vl.values_len = 2; - vl.time = 0; + value_list_t vl = VALUE_LIST_INIT; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "collectd", sizeof (vl.plugin)); - vl.type_instance[0] = 0; - vl.values_len = 1; - /* Write queue */ sstrncpy (vl.plugin_instance, "write_queue", sizeof (vl.plugin_instance)); /* Write queue : queue length */ - vl.values[0].gauge = (gauge_t) copy_write_queue_length; + vl.values = &(value_t) { .gauge = copy_write_queue_length }; + vl.values_len = 1; sstrncpy (vl.type, "queue_length", sizeof (vl.type)); vl.type_instance[0] = 0; plugin_dispatch_values (&vl); /* Write queue : Values dropped (queue length > low limit) */ - vl.values[0].derive = (derive_t) stats_values_dropped; + vl.values = &(value_t) { .gauge = (gauge_t) stats_values_dropped }; + vl.values_len = 1; sstrncpy (vl.type, "derive", sizeof (vl.type)); sstrncpy (vl.type_instance, "dropped", sizeof (vl.type_instance)); plugin_dispatch_values (&vl); @@ -188,7 +182,8 @@ static void plugin_update_internal_statistics (void) { /* {{{ */ sizeof (vl.plugin_instance)); /* Cache : Nb entry in cache tree */ - vl.values[0].gauge = (gauge_t) uc_get_size(); + vl.values = &(value_t) { .gauge = (gauge_t) uc_get_size() }; + vl.values_len = 1; sstrncpy (vl.type, "cache_size", sizeof (vl.type)); vl.type_instance[0] = 0; plugin_dispatch_values (&vl); diff --git a/src/dbi.c b/src/dbi.c index 19d4b0a6..fefbf87b 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -390,24 +390,19 @@ static int cdbi_config_add_database (oconfig_item_t *ci) /* {{{ */ } else { - char *name = NULL; - databases = temp; databases[databases_num] = db; databases_num++; - name = ssnprintf_alloc("dbi:%s", db->name); - - user_data_t ud = { - .data = db - }; - + char *name = ssnprintf_alloc("dbi:%s", db->name); plugin_register_complex_read (/* group = */ NULL, /* name = */ name ? name : db->name, /* callback = */ cdbi_read_database, /* interval = */ (db->interval > 0) ? db->interval : 0, - /* user_data = */ &ud); - free (name); + &(user_data_t) { + .data = db, + }); + sfree (name); } } diff --git a/src/df.c b/src/df.c index af54c92f..632787b2 100644 --- a/src/df.c +++ b/src/df.c @@ -161,12 +161,9 @@ static void df_submit_one (char *plugin_instance, const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "df", sizeof (vl.plugin)); diff --git a/src/disk.c b/src/disk.c index 465b0057..2c0d8b59 100644 --- a/src/disk.c +++ b/src/disk.c @@ -297,14 +297,14 @@ static void disk_submit (const char *plugin_instance, const char *type, derive_t read, derive_t write) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = read; - values[1].derive = write; + value_t values[] = { + { .derive = read }, + { .derive = write }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "disk", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plugin_instance, @@ -317,14 +317,14 @@ static void disk_submit (const char *plugin_instance, #if KERNEL_FREEBSD || KERNEL_LINUX static void submit_io_time (char const *plugin_instance, derive_t io_time, derive_t weighted_time) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = io_time; - values[1].derive = weighted_time; + value_t values[] = { + { .derive = io_time }, + { .derive = weighted_time }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "disk", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); @@ -337,12 +337,9 @@ static void submit_io_time (char const *plugin_instance, derive_t io_time, deriv #if KERNEL_LINUX static void submit_in_progress (char const *disk_name, gauge_t in_progress) { - value_t v; value_list_t vl = VALUE_LIST_INIT; - v.gauge = in_progress; - - vl.values = &v; + vl.values = &(value_t) { .gauge = in_progress }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "disk", sizeof (vl.plugin)); @@ -352,7 +349,6 @@ static void submit_in_progress (char const *disk_name, gauge_t in_progress) plugin_dispatch_values (&vl); } - static counter_t disk_calc_time_incr (counter_t delta_time, counter_t delta_ops) { double interval = CDTIME_T_TO_DOUBLE (plugin_get_interval ()); diff --git a/src/dns.c b/src/dns.c index 0494b4ba..ae53710b 100644 --- a/src/dns.c +++ b/src/dns.c @@ -370,12 +370,9 @@ static int dns_init (void) static void submit_derive (const char *type, const char *type_instance, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "dns", sizeof (vl.plugin)); @@ -387,14 +384,14 @@ static void submit_derive (const char *type, const char *type_instance, static void submit_octets (derive_t queries, derive_t responses) { - value_t values[2]; + value_t values[] = { + { .derive = queries }, + { .derive = responses }, + }; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = queries; - values[1].derive = responses; - vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "dns", sizeof (vl.plugin)); sstrncpy (vl.type, "dns_octets", sizeof (vl.type)); diff --git a/src/email.c b/src/email.c index 2662da9e..97fbdfe6 100644 --- a/src/email.c +++ b/src/email.c @@ -653,12 +653,9 @@ static int email_shutdown (void) static void email_submit (const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "email", sizeof (vl.plugin)); diff --git a/src/entropy.c b/src/entropy.c index f4f4ac4a..b385c2a7 100644 --- a/src/entropy.c +++ b/src/entropy.c @@ -35,14 +35,11 @@ #define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail" -static void entropy_submit (double entropy) +static void entropy_submit (value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = entropy; - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "entropy", sizeof (vl.plugin)); @@ -53,26 +50,14 @@ static void entropy_submit (double entropy) static int entropy_read (void) { - double entropy; - FILE *fh; - char buffer[64]; - - fh = fopen (ENTROPY_FILE, "r"); - if (fh == NULL) - return (-1); - - if (fgets (buffer, sizeof (buffer), fh) == NULL) + value_t v; + if (parse_value_file (ENTROPY_FILE, &v, DS_TYPE_GAUGE) != 0) { - fclose (fh); + ERROR ("entropy plugin: Reading \""ENTROPY_FILE"\" failed."); return (-1); } - fclose (fh); - - entropy = atof (buffer); - - if (entropy > 0.0) - entropy_submit (entropy); + entropy_submit (v); return (0); } diff --git a/src/ethstat.c b/src/ethstat.c index d0e77281..f0b8d9f0 100644 --- a/src/ethstat.c +++ b/src/ethstat.c @@ -172,7 +172,6 @@ static void ethstat_submit_value (const char *device, { static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; value_map_t *map = NULL; @@ -189,8 +188,7 @@ static void ethstat_submit_value (const char *device, return; } - values[0].derive = value; - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/fhcount.c b/src/fhcount.c index 4b3abff7..a2f5aa8c 100644 --- a/src/fhcount.c +++ b/src/fhcount.c @@ -60,13 +60,9 @@ static int fhcount_config(const char *key, const char *value) { static void fhcount_submit( const char *type, const char *type_instance, gauge_t value) { - - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; // Compose the metric @@ -79,7 +75,6 @@ static void fhcount_submit( plugin_dispatch_values(&vl); } - static int fhcount_read(void) { int numfields = 0; int buffer_len = 60; diff --git a/src/filecount.c b/src/filecount.c index 9de9e6c5..c1e53a2d 100644 --- a/src/filecount.c +++ b/src/filecount.c @@ -61,13 +61,10 @@ static size_t directories_num = 0; static void fc_submit_dir (const fc_directory_conf_t *dir) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = (gauge_t) dir->files_num; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); + vl.values = &(value_t) { .gauge = (gauge_t) dir->files_num }; + vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "filecount", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dir->instance, sizeof (vl.plugin_instance)); @@ -75,7 +72,7 @@ static void fc_submit_dir (const fc_directory_conf_t *dir) plugin_dispatch_values (&vl); - values[0].gauge = (gauge_t) dir->files_size; + vl.values = &(value_t) { .gauge = (gauge_t) dir->files_size }; sstrncpy (vl.type, "bytes", sizeof (vl.type)); plugin_dispatch_values (&vl); diff --git a/src/gps.c b/src/gps.c index f72cef49..d5b7176b 100644 --- a/src/gps.c +++ b/src/gps.c @@ -220,12 +220,9 @@ quit: */ static void cgps_submit (const char *type, gauge_t value, const char *type_instance) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "gps", sizeof (vl.plugin)); diff --git a/src/hddtemp.c b/src/hddtemp.c index 865ea861..31960b54 100644 --- a/src/hddtemp.c +++ b/src/hddtemp.c @@ -226,12 +226,9 @@ static int hddtemp_config (const char *key, const char *value) static void hddtemp_submit (char *type_instance, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "hddtemp", sizeof (vl.plugin)); diff --git a/src/hugepages.c b/src/hugepages.c index ac9441d0..f62df830 100644 --- a/src/hugepages.c +++ b/src/hugepages.c @@ -4,15 +4,15 @@ * * Copyright(c) 2016 Intel Corporation. All rights reserved. * - * 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: + * 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 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, @@ -25,83 +25,105 @@ * Authors: * Jaroslav Safka * Kim-Marie Jones + * Florian Forster */ #include "collectd.h" + #include "common.h" /* auxiliary functions */ #include "plugin.h" /* plugin_register_*, plugin_dispatch_values */ static const char g_plugin_name[] = "hugepages"; -static const char g_cfg_rpt_numa[] = "ReportPerNodeHP"; -static const char g_cfg_rpt_mm[] = "ReportRootHP"; -static const char *g_config_keys[] = { - g_cfg_rpt_numa, - g_cfg_rpt_mm, -}; -static size_t g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys); -static int g_flag_rpt_numa = 1; -static int g_flag_rpt_mm = 1; +static _Bool g_flag_rpt_numa = 1; +static _Bool g_flag_rpt_mm = 1; + +static _Bool g_values_pages = 1; +static _Bool g_values_bytes = 0; +static _Bool g_values_percent = 0; + +#define HP_HAVE_NR 0x01 +#define HP_HAVE_SURPLUS 0x02 +#define HP_HAVE_FREE 0x04 +#define HP_HAVE_ALL 0x07 struct entry_info { char *d_name; const char *node; -}; + size_t page_size_kb; -static int huge_config_callback(const char *key, const char *val) -{ - DEBUG("%s: HugePages config key='%s', val='%s'", g_plugin_name, key, val); + gauge_t nr; + gauge_t surplus; + gauge_t free; + uint8_t flags; +}; - if (strcasecmp(key, g_cfg_rpt_numa) == 0) { - g_flag_rpt_numa = IS_TRUE(val); - return 0; - } - if (strcasecmp(key, g_cfg_rpt_mm) == 0) { - g_flag_rpt_mm = IS_TRUE(val); - return 0; +static int hp_config(oconfig_item_t *ci) { + for (int i = 0; i < ci->children_num; i++) { + oconfig_item_t *child = ci->children + i; + if (strcasecmp("ReportPerNodeHP", child->key) == 0) + cf_util_get_boolean(child, &g_flag_rpt_numa); + else if (strcasecmp("ReportRootHP", child->key) == 0) + cf_util_get_boolean(child, &g_flag_rpt_mm); + else if (strcasecmp("ValuesPages", child->key) == 0) + cf_util_get_boolean(child, &g_values_pages); + else if (strcasecmp("ValuesBytes", child->key) == 0) + cf_util_get_boolean(child, &g_values_bytes); + else if (strcasecmp("ValuesPercentage", child->key) == 0) + cf_util_get_boolean(child, &g_values_percent); + else + ERROR("%s: Invalid configuration option: \"%s\".", g_plugin_name, + child->key); } - return -1; + return (0); } -static void submit_hp(const char *plug_inst, const char *type, - const char *type_instance, gauge_t free_value, gauge_t used_value) -{ - value_t values[2]; +static void submit_hp(const struct entry_info *info) { value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = free_value; - values[1].gauge = used_value; - - vl.values = values; - vl.values_len = 2; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); - sstrncpy (vl.plugin, g_plugin_name, sizeof (vl.plugin)); - sstrncpy (vl.plugin_instance, plug_inst, sizeof (vl.plugin_instance)); - sstrncpy (vl.type, type, sizeof (vl.type)); - - if (type_instance != NULL) { - sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); + vl.values = &(value_t) { .gauge = NAN }; + vl.values_len = 1; + + sstrncpy(vl.host, hostname_g, sizeof(vl.host)); + sstrncpy(vl.plugin, g_plugin_name, sizeof(vl.plugin)); + if (info->node) { + ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%zuKb", + info->node, info->page_size_kb); + } else { + ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%zuKb", + info->page_size_kb); } - DEBUG("submit_hp pl_inst:%s, inst_type %s, type %s, free=%lf, used=%lf", - plug_inst, type_instance, type, free_value, used_value); + /* ensure all metrics have the same timestamp */ + vl.time = cdtime(); - plugin_dispatch_values (&vl); + gauge_t free = info->free; + gauge_t used = (info->nr + info->surplus) - info->free; + + if (g_values_pages) { + sstrncpy(vl.type, "vmpage_number", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE, + "free", free, "used", used, NULL); + } + if (g_values_bytes) { + gauge_t page_size = (gauge_t)(1024 * info->page_size_kb); + sstrncpy(vl.type, "memory", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ 0, DS_TYPE_GAUGE, + "free", free * page_size, "used", + used * page_size, NULL); + } + if (g_values_percent) { + sstrncpy(vl.type, "percent", sizeof(vl.type)); + plugin_dispatch_multivalue(&vl, /* store_percentage = */ 1, DS_TYPE_GAUGE, + "free", free, "used", used, NULL); + } } static int read_hugepage_entry(const char *path, const char *entry, - void *e_info) -{ + void *e_info) { char path2[PATH_MAX]; - static const char type[] = "hugepages"; - static const char partial_type_inst[] = "free_used"; - char type_instance[PATH_MAX]; - char *strin; - struct entry_info *hpsize_plinst = e_info; - static int flag = 0; - static double used_hp = 0; - static double free_hp = 0; + struct entry_info *info = e_info; double value; ssnprintf(path2, sizeof(path2), "%s/%s", path, entry); @@ -112,58 +134,40 @@ static int read_hugepage_entry(const char *path, const char *entry, return -1; } - if (fscanf(fh, "%lf", &value) !=1) { + if (fscanf(fh, "%lf", &value) != 1) { ERROR("%s: cannot parse file %s", g_plugin_name, path2); fclose(fh); return -1; } + fclose(fh); if (strcmp(entry, "nr_hugepages") == 0) { - used_hp += value; - flag++; + info->nr = value; + info->flags |= HP_HAVE_NR; } else if (strcmp(entry, "surplus_hugepages") == 0) { - used_hp += value; - flag++; + info->surplus = value; + info->flags |= HP_HAVE_SURPLUS; } else if (strcmp(entry, "free_hugepages") == 0) { - used_hp -= value; - free_hp = value; - flag++; + info->free = value; + info->flags |= HP_HAVE_FREE; } - if (flag == 3) { - /* Can now submit "used" and "free" values. - * 0x2D is the ASCII "-" character, after which the string - * contains "kB" - * The string passed as param 3 to submit_hp is of the format: - * --kB - */ - strin = strchr(hpsize_plinst->d_name, 0x2D); - if (strin != NULL) { - ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, strin); - } else { - ssnprintf(type_instance, sizeof(type_instance), "%s%s", partial_type_inst, - hpsize_plinst->d_name); - } - submit_hp(hpsize_plinst->node, type, type_instance, free_hp, used_hp); - - /* Reset for next time */ - flag = 0; - used_hp = 0; - free_hp = 0; + if (info->flags != HP_HAVE_ALL) { + return 0; } - fclose(fh); + submit_hp(info); + + /* Reset flags so subsequent calls don't submit again. */ + info->flags = 0; return 0; } -static int read_syshugepages(const char* path, const char* node) -{ - static const char hugepages_dir[] = "hugepages"; +static int read_syshugepages(const char *path, const char *node) { + static const char hugepages_dir[] = "hugepages-"; DIR *dir; struct dirent *result; char path2[PATH_MAX]; - struct entry_info e_info; - long lim; dir = opendir(path); if (dir == NULL) { @@ -171,55 +175,56 @@ static int read_syshugepages(const char* path, const char* node) return -1; } - errno = 0; - if ((lim = pathconf(path, _PC_NAME_MAX)) == -1) { - /* Limit not defined if errno == 0, otherwise error */ - if (errno != 0) { - ERROR("%s: pathconf failed", g_plugin_name); - closedir(dir); - return -1; - } else { - lim = PATH_MAX; - } - } - /* read "hugepages-XXXXXkB" entries */ while ((result = readdir(dir)) != NULL) { - if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir)-1)) { + if (strncmp(result->d_name, hugepages_dir, sizeof(hugepages_dir) - 1)) { /* not node dir */ errno = 0; continue; } - /* /sys/devices/system/node/node?/hugepages/ */ - ssnprintf(path2, (size_t) lim, "%s/%s", path, result->d_name); + long page_size = strtol(result->d_name + strlen(hugepages_dir), + /* endptr = */ NULL, /* base = */ 10); + if (errno != 0) { + char errbuf[1024]; + ERROR("%s: failed to determine page size from directory name \"%s\": %s", + g_plugin_name, result->d_name, + sstrerror(errno, errbuf, sizeof(errbuf))); + continue; + } - e_info.d_name = result->d_name; - e_info.node = node; - walk_directory(path2, read_hugepage_entry, &e_info, 0); + /* /sys/devices/system/node/node?/hugepages/ */ + ssnprintf(path2, sizeof(path2), "%s/%s", path, result->d_name); + + walk_directory(path2, read_hugepage_entry, + &(struct entry_info){ + .d_name = result->d_name, + .node = node, + .page_size_kb = (size_t)page_size, + }, + /* hidden = */ 0); errno = 0; } /* Check if NULL return from readdir() was an error */ if (errno != 0) { - ERROR("%s: readdir failed", g_plugin_name); - closedir(dir); - return -1; + ERROR("%s: readdir failed", g_plugin_name); + closedir(dir); + return -1; } closedir(dir); return 0; } -static int read_nodes(void) -{ +static int read_nodes(void) { static const char sys_node[] = "/sys/devices/system/node"; static const char node_string[] = "node"; - static const char sys_node_hugepages[] = "/sys/devices/system/node/%s/hugepages"; + static const char sys_node_hugepages[] = + "/sys/devices/system/node/%s/hugepages"; DIR *dir; struct dirent *result; char path[PATH_MAX]; - long lim; dir = opendir(sys_node); if (dir == NULL) { @@ -227,44 +232,30 @@ static int read_nodes(void) return -1; } - errno = 0; - if ((lim = pathconf(sys_node, _PC_NAME_MAX)) == -1) { - /* Limit not defined if errno == 0, otherwise error */ - if (errno != 0) { - ERROR("%s: pathconf failed", g_plugin_name); - closedir(dir); - return -1; - } else { - lim = PATH_MAX; - } - } - while ((result = readdir(dir)) != NULL) { - if (strncmp(result->d_name, node_string, sizeof(node_string)-1)) { + if (strncmp(result->d_name, node_string, sizeof(node_string) - 1)) { /* not node dir */ errno = 0; continue; } - ssnprintf(path, (size_t) lim, sys_node_hugepages, result->d_name); + ssnprintf(path, sizeof(path), sys_node_hugepages, result->d_name); read_syshugepages(path, result->d_name); errno = 0; } /* Check if NULL return from readdir() was an error */ if (errno != 0) { - ERROR("%s: readdir failed", g_plugin_name); - closedir(dir); - return -1; + ERROR("%s: readdir failed", g_plugin_name); + closedir(dir); + return -1; } closedir(dir); return 0; } - -static int huge_read(void) -{ +static int huge_read(void) { static const char sys_mm_hugepages[] = "/sys/kernel/mm/hugepages"; if (g_flag_rpt_mm) { @@ -281,10 +272,7 @@ static int huge_read(void) return 0; } -void module_register(void) -{ - plugin_register_config(g_plugin_name, huge_config_callback, g_config_keys, - g_config_keys_num); +void module_register(void) { + plugin_register_complex_config(g_plugin_name, hp_config); plugin_register_read(g_plugin_name, huge_read); } - diff --git a/src/interface.c b/src/interface.c index b8ed6e40..849de955 100644 --- a/src/interface.c +++ b/src/interface.c @@ -168,17 +168,17 @@ static void if_submit (const char *dev, const char *type, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; if (ignorelist_match (ignorelist, dev) != 0) return; - values[0].derive = rx; - values[1].derive = tx; - vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "interface", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); diff --git a/src/ipc.c b/src/ipc.c index b164cdf7..d6d2bbd5 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -97,12 +97,9 @@ static void ipc_submit_g (const char *plugin_instance, const char *type_instance, gauge_t value) /* {{{ */ { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ipc", sizeof (vl.plugin)); diff --git a/src/ipmi.c b/src/ipmi.c index ad62299e..a42b787f 100644 --- a/src/ipmi.c +++ b/src/ipmi.c @@ -115,7 +115,6 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, ipmi_states_t __attribute__((unused)) *states, void *user_data) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; c_ipmi_sensor_list_t *list_item = (c_ipmi_sensor_list_t *)user_data; @@ -214,9 +213,7 @@ static void sensor_read_handler (ipmi_sensor_t *sensor, return; } - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/iptables.c b/src/iptables.c index f6911221..35975e6d 100644 --- a/src/iptables.c +++ b/src/iptables.c @@ -242,7 +242,6 @@ static int submit6_match (const struct ip6t_entry_match *match, int rule_num) { int status; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; /* Select the rules to collect */ @@ -260,8 +259,6 @@ static int submit6_match (const struct ip6t_entry_match *match, return (0); } - vl.values = values; - vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin)); @@ -285,16 +282,16 @@ static int submit6_match (const struct ip6t_entry_match *match, } sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type)); - values[0].derive = (derive_t) entry->counters.bcnt; + vl.values = &(value_t) { .derive = (derive_t) entry->counters.bcnt }; + vl.values_len = 1; plugin_dispatch_values (&vl); sstrncpy (vl.type, "ipt_packets", sizeof (vl.type)); - values[0].derive = (derive_t) entry->counters.pcnt; + vl.values = &(value_t) { .derive = (derive_t) entry->counters.pcnt }; plugin_dispatch_values (&vl); return (0); -} /* int submit_match */ - +} /* int submit6_match */ /* This needs to return `int' for IPT_MATCH_ITERATE to work. */ static int submit_match (const struct ipt_entry_match *match, @@ -303,7 +300,6 @@ static int submit_match (const struct ipt_entry_match *match, int rule_num) { int status; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; /* Select the rules to collect */ @@ -321,8 +317,6 @@ static int submit_match (const struct ipt_entry_match *match, return (0); } - vl.values = values; - vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin)); @@ -346,11 +340,12 @@ static int submit_match (const struct ipt_entry_match *match, } sstrncpy (vl.type, "ipt_bytes", sizeof (vl.type)); - values[0].derive = (derive_t) entry->counters.bcnt; + vl.values = &(value_t) { .derive = (derive_t) entry->counters.bcnt }; + vl.values_len = 1; plugin_dispatch_values (&vl); sstrncpy (vl.type, "ipt_packets", sizeof (vl.type)); - values[0].derive = (derive_t) entry->counters.pcnt; + vl.values = &(value_t) { .derive = (derive_t) entry->counters.pcnt }; plugin_dispatch_values (&vl); return (0); diff --git a/src/ipvs.c b/src/ipvs.c index 92690e88..d2ceb50b 100644 --- a/src/ipvs.c +++ b/src/ipvs.c @@ -228,12 +228,9 @@ static int get_ti (struct ip_vs_dest_entry *de, char *ti, size_t size) static void cipvs_submit_connections (const char *pi, const char *ti, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -250,14 +247,14 @@ static void cipvs_submit_connections (const char *pi, const char *ti, static void cipvs_submit_if (const char *pi, const char *t, const char *ti, derive_t rx, derive_t tx) { - value_t values[2]; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = rx; - values[1].derive = tx; - vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ipvs", sizeof (vl.plugin)); diff --git a/src/irq.c b/src/irq.c index 0f1d3f0c..cb444a47 100644 --- a/src/irq.c +++ b/src/irq.c @@ -72,15 +72,12 @@ static int irq_config (const char *key, const char *value) static void irq_submit (const char *irq_name, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; if (ignorelist_match (ignorelist, irq_name) != 0) return; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "irq", sizeof (vl.plugin)); diff --git a/src/java.c b/src/java.c index 67740ac8..cd173c58 100644 --- a/src/java.c +++ b/src/java.c @@ -1425,13 +1425,11 @@ static jint JNICALL cjni_api_register_read (JNIEnv *jvm_env, /* {{{ */ DEBUG ("java plugin: Registering new read callback: %s", cbi->name); - user_data_t ud = { - .data = cbi, - .free_func = cjni_callback_info_destroy - }; - plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read, - /* interval = */ 0, &ud); + /* interval = */ 0, &(user_data_t) { + .data = cbi, + .free_func = cjni_callback_info_destroy, + }); (*jvm_env)->DeleteLocalRef (jvm_env, o_read); @@ -1449,12 +1447,10 @@ static jint JNICALL cjni_api_register_write (JNIEnv *jvm_env, /* {{{ */ DEBUG ("java plugin: Registering new write callback: %s", cbi->name); - user_data_t ud = { - .data = cbi, - .free_func = cjni_callback_info_destroy - }; - - plugin_register_write (cbi->name, cjni_write, &ud); + plugin_register_write (cbi->name, cjni_write, &(user_data_t) { + .data = cbi, + .free_func = cjni_callback_info_destroy, + }); (*jvm_env)->DeleteLocalRef (jvm_env, o_write); @@ -1472,12 +1468,10 @@ static jint JNICALL cjni_api_register_flush (JNIEnv *jvm_env, /* {{{ */ DEBUG ("java plugin: Registering new flush callback: %s", cbi->name); - user_data_t ud = { - .data = cbi, - .free_func = cjni_callback_info_destroy - }; - - plugin_register_flush (cbi->name, cjni_flush, &ud); + plugin_register_flush (cbi->name, cjni_flush, &(user_data_t) { + .data = cbi, + .free_func = cjni_callback_info_destroy, + }); (*jvm_env)->DeleteLocalRef (jvm_env, o_flush); @@ -1502,12 +1496,10 @@ static jint JNICALL cjni_api_register_log (JNIEnv *jvm_env, /* {{{ */ DEBUG ("java plugin: Registering new log callback: %s", cbi->name); - user_data_t ud = { - .data = cbi, - .free_func = cjni_callback_info_destroy - }; - - plugin_register_log (cbi->name, cjni_log, &ud); + plugin_register_log (cbi->name, cjni_log, &(user_data_t) { + .data = cbi, + .free_func = cjni_callback_info_destroy, + }); (*jvm_env)->DeleteLocalRef (jvm_env, o_log); @@ -1526,12 +1518,10 @@ static jint JNICALL cjni_api_register_notification (JNIEnv *jvm_env, /* {{{ */ DEBUG ("java plugin: Registering new notification callback: %s", cbi->name); - user_data_t ud = { - .data = cbi, - .free_func = cjni_callback_info_destroy - }; - - plugin_register_notification (cbi->name, cjni_notification, &ud); + plugin_register_notification (cbi->name, cjni_notification, &(user_data_t) { + .data = cbi, + .free_func = cjni_callback_info_destroy, + }); (*jvm_env)->DeleteLocalRef (jvm_env, o_notification); diff --git a/src/load.c b/src/load.c index cc3be37e..a3f6bb1f 100644 --- a/src/load.c +++ b/src/load.c @@ -78,8 +78,6 @@ static int load_config (const char *key, const char *value) } static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum) { - value_t values[3]; - value_list_t vl = VALUE_LIST_INIT; int cores = 0; char errbuf[1024]; @@ -97,9 +95,12 @@ static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum) lnum /= cores; } - values[0].gauge = snum; - values[1].gauge = mnum; - values[2].gauge = lnum; + value_list_t vl = VALUE_LIST_INIT; + value_t values[] = { + { .gauge = snum }, + { .gauge = mnum }, + { .gauge = lnum }, + }; vl.values = values; vl.values_len = STATIC_ARRAY_SIZE (values); diff --git a/src/lpar.c b/src/lpar.c index 5b0bd13d..0e32c834 100644 --- a/src/lpar.c +++ b/src/lpar.c @@ -114,12 +114,9 @@ static int lpar_init (void) static void lpar_submit (const char *type_instance, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = (gauge_t)value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; if (report_by_serial) { diff --git a/src/lua.c b/src/lua.c index ba5fbcea..d10b4ea7 100644 --- a/src/lua.c +++ b/src/lua.c @@ -303,15 +303,13 @@ static int lua_cb_register_read(lua_State *L) /* {{{ */ cb->lua_function_name = strdup(function_name); pthread_mutex_init(&cb->lock, NULL); - user_data_t ud = { - .data = cb - }; - int status = plugin_register_complex_read(/* group = */ "lua", /* name = */ function_name, /* callback = */ clua_read, /* interval = */ 0, - /* user_data = */ &ud); + &(user_data_t) { + .data = cb, + }); if (status != 0) return luaL_error(L, "%s", "plugin_register_complex_read failed"); @@ -349,13 +347,11 @@ static int lua_cb_register_write(lua_State *L) /* {{{ */ cb->lua_function_name = strdup(function_name); pthread_mutex_init(&cb->lock, NULL); - user_data_t ud = { - .data = cb - }; - int status = plugin_register_write(/* name = */ function_name, /* callback = */ clua_write, - /* user_data = */ &ud); + &(user_data_t) { + .data = cb, + }); if (status != 0) return luaL_error(L, "%s", "plugin_register_write failed"); diff --git a/src/lvm.c b/src/lvm.c index 6b9a0317..77cb6eb8 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -55,12 +55,9 @@ static char const *get_lv_property_string(lv_t lv, char const *property) static void lvm_submit (char const *plugin_instance, char const *type_instance, uint64_t ivalue) { - value_t v; value_list_t vl = VALUE_LIST_INIT; - v.gauge = (gauge_t) ivalue; - - vl.values = &v; + vl.values = &(value_t) { .gauge = (gauge_t) ivalue }; vl.values_len = 1; sstrncpy(vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/madwifi.c b/src/madwifi.c index 053bd7fa..42474bc7 100644 --- a/src/madwifi.c +++ b/src/madwifi.c @@ -538,7 +538,7 @@ static int madwifi_config (const char *key, const char *value) static void submit (const char *dev, const char *type, const char *ti1, - const char *ti2, value_t *val, int len) + const char *ti2, value_t *val, size_t len) { value_list_t vl = VALUE_LIST_INIT; @@ -558,28 +558,26 @@ static void submit (const char *dev, const char *type, const char *ti1, } static void submit_derive (const char *dev, const char *type, const char *ti1, - const char *ti2, derive_t val) + const char *ti2, derive_t value) { - value_t item; - item.derive = val; - submit (dev, type, ti1, ti2, &item, 1); + submit (dev, type, ti1, ti2, &(value_t) { .derive = value }, 1); } static void submit_derive2 (const char *dev, const char *type, const char *ti1, const char *ti2, derive_t val1, derive_t val2) { - value_t items[2]; - items[0].derive = val1; - items[1].derive = val2; - submit (dev, type, ti1, ti2, items, 2); + value_t values[] = { + { .derive = val1 }, + { .derive = val2 }, + }; + + submit (dev, type, ti1, ti2, values, STATIC_ARRAY_SIZE (values)); } static void submit_gauge (const char *dev, const char *type, const char *ti1, - const char *ti2, gauge_t val) + const char *ti2, gauge_t value) { - value_t item; - item.gauge = val; - submit (dev, type, ti1, ti2, &item, 1); + submit (dev, type, ti1, ti2, &(value_t) { .gauge = value }, 1); } static void submit_antx (const char *dev, const char *name, diff --git a/src/match_regex.c b/src/match_regex.c index cd630167..dd8319ea 100644 --- a/src/match_regex.c +++ b/src/match_regex.c @@ -33,7 +33,10 @@ #include "collectd.h" +#include "common.h" #include "filter_chain.h" +#include "meta_data.h" +#include "utils_llist.h" #include #include @@ -64,6 +67,7 @@ struct mr_match_s mr_regex_t *plugin_instance; mr_regex_t *type; mr_regex_t *type_instance; + llist_t *meta; /* Maps each meta key into mr_regex_t* */ _Bool invert; }; @@ -77,7 +81,7 @@ static void mr_free_regex (mr_regex_t *r) /* {{{ */ regfree (&r->re); memset (&r->re, 0, sizeof (r->re)); - free (r->re_str); + sfree (r->re_str); if (r->next != NULL) mr_free_regex (r->next); @@ -93,8 +97,14 @@ static void mr_free_match (mr_match_t *m) /* {{{ */ mr_free_regex (m->plugin_instance); mr_free_regex (m->type); mr_free_regex (m->type_instance); + for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) + { + sfree (e->key); + mr_free_regex ((mr_regex_t *) e->value); + } + llist_destroy (m->meta); - free (m); + sfree (m); } /* }}} void mr_free_match */ static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */ @@ -127,31 +137,25 @@ static int mr_match_regexen (mr_regex_t *re_head, /* {{{ */ return (FC_MATCH_MATCHES); } /* }}} int mr_match_regexen */ -static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */ - oconfig_item_t *ci) +static int mr_add_regex (mr_regex_t **re_head, const char *re_str, /* {{{ */ + const char *option) { mr_regex_t *re; int status; - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) - { - log_warn ("`%s' needs exactly one string argument.", ci->key); - return (-1); - } - re = calloc (1, sizeof (*re)); if (re == NULL) { - log_err ("mr_config_add_regex: calloc failed."); + log_err ("mr_add_regex: calloc failed."); return (-1); } re->next = NULL; - re->re_str = strdup (ci->values[0].value.string); + re->re_str = strdup (re_str); if (re->re_str == NULL) { - free (re); - log_err ("mr_config_add_regex: strdup failed."); + sfree (re); + log_err ("mr_add_regex: strdup failed."); return (-1); } @@ -162,9 +166,9 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */ regerror (status, &re->re, errmsg, sizeof (errmsg)); errmsg[sizeof (errmsg) - 1] = 0; log_err ("Compiling regex `%s' for `%s' failed: %s.", - re->re_str, ci->key, errmsg); - free (re->re_str); - free (re); + re->re_str, option, errmsg); + sfree (re->re_str); + sfree (re); return (-1); } @@ -184,8 +188,78 @@ static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */ } return (0); +} /* }}} int mr_add_regex */ + +static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */ + oconfig_item_t *ci) +{ + if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) + { + log_warn ("`%s' needs exactly one string argument.", ci->key); + return (-1); + } + + return mr_add_regex (re_head, ci->values[0].value.string, ci->key); } /* }}} int mr_config_add_regex */ +static int mr_config_add_meta_regex (llist_t **meta, /* {{{ */ + oconfig_item_t *ci) +{ + char *meta_key; + llentry_t *entry; + mr_regex_t *re_head; + int status; + char buffer[1024]; + + if ((ci->values_num != 2) + || (ci->values[0].type != OCONFIG_TYPE_STRING) + || (ci->values[1].type != OCONFIG_TYPE_STRING)) + { + log_warn ("`%s' needs exactly two string arguments.", ci->key); + return (-1); + } + + if (*meta == NULL) + { + *meta = llist_create(); + if (*meta == NULL) + { + log_err ("mr_config_add_meta_regex: llist_create failed."); + return (-1); + } + } + + meta_key = ci->values[0].value.string; + entry = llist_search (*meta, meta_key); + if (entry == NULL) + { + meta_key = strdup (meta_key); + if (meta_key == NULL) + { + log_err ("mr_config_add_meta_regex: strdup failed."); + return (-1); + } + entry = llentry_create (meta_key, NULL); + if (entry == NULL) + { + log_err ("mr_config_add_meta_regex: llentry_create failed."); + sfree (meta_key); + return (-1); + } + /* meta_key and entry will now be freed by mr_free_match(). */ + llist_append (*meta, entry); + } + + ssnprintf (buffer, sizeof (buffer), "%s `%s'", ci->key, meta_key); + /* Can't pass &entry->value into mr_add_regex, so copy in/out. */ + re_head = entry->value; + status = mr_add_regex (&re_head, ci->values[1].value.string, buffer); + if (status == 0) { + entry->value = re_head; + } + return status; +} /* }}} int mr_config_add_meta_regex */ + static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ { mr_match_t *m; @@ -216,6 +290,8 @@ static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ status = mr_config_add_regex (&m->type, child); else if (strcasecmp ("TypeInstance", child->key) == 0) status = mr_config_add_regex (&m->type_instance, child); + else if (strcasecmp ("MetaData", child->key) == 0) + status = mr_config_add_meta_regex (&m->meta, child); else if (strcasecmp ("Invert", child->key) == 0) status = cf_util_get_boolean(child, &m->invert); else @@ -236,7 +312,8 @@ static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ && (m->plugin == NULL) && (m->plugin_instance == NULL) && (m->type == NULL) - && (m->type_instance == NULL)) + && (m->type_instance == NULL) + && (m->meta == NULL)) { log_err ("No (valid) regular expressions have been configured. " "This match will be ignored."); @@ -295,6 +372,25 @@ static int mr_match (const data_set_t __attribute__((unused)) *ds, /* {{{ */ if (mr_match_regexen (m->type_instance, vl->type_instance) == FC_MATCH_NO_MATCH) return (nomatch_value); + if (vl->meta != NULL) + { + for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next) + { + mr_regex_t *meta_re = (mr_regex_t *) e->value; + char *value; + int status = meta_data_get_string (vl->meta, e->key, &value); + if (status == (-ENOENT)) /* key is not present */ + return (nomatch_value); + if (status != 0) /* some other problem */ + continue; /* error will have already been printed. */ + if (mr_match_regexen (meta_re, value) == FC_MATCH_NO_MATCH) + { + sfree (value); + return (nomatch_value); + } + sfree (value); + } + } return (match_value); } /* }}} int mr_match */ diff --git a/src/mbmon.c b/src/mbmon.c index 9629b896..b72be896 100644 --- a/src/mbmon.c +++ b/src/mbmon.c @@ -218,12 +218,9 @@ static int mbmon_config (const char *key, const char *value) static void mbmon_submit (const char *type, const char *type_instance, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "mbmon", sizeof (vl.plugin)); diff --git a/src/md.c b/src/md.c index 44cad2ed..db85c46c 100644 --- a/src/md.c +++ b/src/md.c @@ -72,12 +72,9 @@ static int md_config (const char *key, const char *value) static void md_submit (const int minor, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "md", sizeof (vl.plugin)); diff --git a/src/memcachec.c b/src/memcachec.c index dff55461..97e75c0c 100644 --- a/src/memcachec.c +++ b/src/memcachec.c @@ -441,14 +441,11 @@ static int cmc_init (void) /* {{{ */ } /* }}} int cmc_init */ static void cmc_submit (const web_page_t *wp, const web_match_t *wm, /* {{{ */ - const cu_match_value_t *mv) + value_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0] = mv->value; - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "memcachec", sizeof (vl.plugin)); @@ -496,7 +493,7 @@ static int cmc_read_page (web_page_t *wp) /* {{{ */ continue; } - cmc_submit (wp, wm, mv); + cmc_submit (wp, wm, mv->value); match_value_reset (mv); } /* for (wm = wp->matches; wm != NULL; wm = wm->next) */ diff --git a/src/memcached.c b/src/memcached.c index 9e6e7252..77cadebb 100644 --- a/src/memcached.c +++ b/src/memcached.c @@ -262,13 +262,10 @@ static void memcached_init_vl (value_list_t *vl, memcached_t const *st) static void submit_derive (const char *type, const char *type_inst, derive_t value, memcached_t *st) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - memcached_init_vl (&vl, st); - - values[0].derive = value; - vl.values = values; + memcached_init_vl (&vl, st); + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.type, type, sizeof (vl.type)); if (type_inst != NULL) @@ -280,15 +277,15 @@ static void submit_derive (const char *type, const char *type_inst, static void submit_derive2 (const char *type, const char *type_inst, derive_t value0, derive_t value1, memcached_t *st) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - memcached_init_vl (&vl, st); - - values[0].derive = value0; - values[1].derive = value1; + value_t values[] = { + { .derive = value0 }, + { .derive = value1 }, + }; + memcached_init_vl (&vl, st); vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.type, type, sizeof (vl.type)); if (type_inst != NULL) sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); @@ -299,13 +296,10 @@ static void submit_derive2 (const char *type, const char *type_inst, static void submit_gauge (const char *type, const char *type_inst, gauge_t value, memcached_t *st) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - memcached_init_vl (&vl, st); - - values[0].gauge = value; - vl.values = values; + memcached_init_vl (&vl, st); + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.type, type, sizeof (vl.type)); if (type_inst != NULL) @@ -317,15 +311,15 @@ static void submit_gauge (const char *type, const char *type_inst, static void submit_gauge2 (const char *type, const char *type_inst, gauge_t value0, gauge_t value1, memcached_t *st) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - memcached_init_vl (&vl, st); - - values[0].gauge = value0; - values[1].gauge = value1; + value_t values[] = { + { .gauge = value0 }, + { .gauge = value1 }, + }; + memcached_init_vl (&vl, st); vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.type, type, sizeof (vl.type)); if (type_inst != NULL) sstrncpy (vl.type_instance, type_inst, sizeof (vl.type_instance)); @@ -554,16 +548,15 @@ static int memcached_add_read_callback (memcached_t *st) assert (st->name != NULL); ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name); - user_data_t ud = { - .data = st, - .free_func = memcached_free - }; - status = plugin_register_complex_read (/* group = */ "memcached", /* name = */ callback_name, /* callback = */ memcached_read, /* interval = */ 0, - /* user_data = */ &ud); + &(user_data_t) { + .data = st, + .free_func = memcached_free, + }); + return (status); } /* int memcached_add_read_callback */ diff --git a/src/mic.c b/src/mic.c index 3e31889f..5ec382ba 100644 --- a/src/mic.c +++ b/src/mic.c @@ -150,17 +150,15 @@ static int mic_config (const char *key, const char *value) { return (0); } -static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 val) +static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; /* MicAccessAPI reports KB's of memory, adjust for this */ - DEBUG("mic plugin: Memory Value Report; %u %lf",val,((gauge_t)val)*1024.0); - values[0].gauge = ((gauge_t)val)*1024.0; + DEBUG("mic plugin: Memory Value Report; %u %lf",value,((gauge_t)value)*1024.0); - vl.values=values; - vl.values_len=1; + vl.values = &(value_t) { .gauge = ((gauge_t)value) * 1024.0 }; + vl.values_len = 1; strncpy (vl.host, hostname_g, sizeof (vl.host)); strncpy (vl.plugin, "mic", sizeof (vl.plugin)); @@ -190,15 +188,12 @@ static int mic_read_memory(int mic) return (0); } -static void mic_submit_temp(int micnumber, const char *type, gauge_t val) +static void mic_submit_temp(int micnumber, const char *type, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = val; - - vl.values=values; - vl.values_len=1; + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; strncpy (vl.host, hostname_g, sizeof (vl.host)); strncpy (vl.plugin, "mic", sizeof (vl.plugin)); @@ -237,15 +232,12 @@ static int mic_read_temps(int mic) } static void mic_submit_cpu(int micnumber, const char *type_instance, - int core, derive_t val) + int core, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = val; - - vl.values=values; - vl.values_len=1; + vl.values = &(value_t) { .derive = value }; + vl.values_len = 1; strncpy (vl.host, hostname_g, sizeof (vl.host)); strncpy (vl.plugin, "mic", sizeof (vl.plugin)); @@ -296,15 +288,12 @@ static int mic_read_cpu(int mic) return (0); } -static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t val) +static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = val; - - vl.values=values; - vl.values_len=1; + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; strncpy (vl.host, hostname_g, sizeof (vl.host)); strncpy (vl.plugin, "mic", sizeof (vl.plugin)); @@ -358,13 +347,13 @@ static int mic_read (void) U32 ret; int error; - error=0; - for (int i=0;ihost); plugin_register_complex_read (/* group = */ NULL, name, /* callback = */ mb_read, /* interval = */ host->interval, - &ud); + &(user_data_t) { + .data = host, + .free_func = host_free, + }); } else { diff --git a/src/mqtt.c b/src/mqtt.c index ad889953..c08fd29e 100644 --- a/src/mqtt.c +++ b/src/mqtt.c @@ -631,11 +631,9 @@ static int mqtt_config_publisher (oconfig_item_t *ci) } ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name); - user_data_t user_data = { - .data = conf - }; - - plugin_register_write (cb_name, mqtt_write, &user_data); + plugin_register_write (cb_name, mqtt_write, &(user_data_t) { + .data = conf, + }); return (0); } /* mqtt_config_publisher */ diff --git a/src/multimeter.c b/src/multimeter.c index 02fe1ad3..2ffcc8f2 100644 --- a/src/multimeter.c +++ b/src/multimeter.c @@ -193,12 +193,9 @@ static int multimeter_init (void) static void multimeter_submit (double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "multimeter", sizeof (vl.plugin)); diff --git a/src/mysql.c b/src/mysql.c index 32b72e28..a64b0e5b 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -233,14 +233,11 @@ static int mysql_config_database (oconfig_item_t *ci) /* {{{ */ else sstrncpy (cb_name, "mysql", sizeof (cb_name)); - user_data_t ud = { - .data = db, - .free_func = mysql_database_free - }; - plugin_register_complex_read (/* group = */ NULL, cb_name, - mysql_read, - /* interval = */ 0, &ud); + mysql_read, /* interval = */ 0, &(user_data_t) { + .data = db, + .free_func = mysql_database_free, + }); } else { @@ -368,39 +365,24 @@ static void submit (const char *type, const char *type_instance, plugin_dispatch_values (&vl); } /* submit */ -static void counter_submit (const char *type, const char *type_instance, - derive_t value, mysql_database_t *db) -{ - value_t values[1]; - - values[0].derive = value; - submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db); -} /* void counter_submit */ - static void gauge_submit (const char *type, const char *type_instance, gauge_t value, mysql_database_t *db) { - value_t values[1]; - - values[0].gauge = value; - submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db); + submit (type, type_instance, &(value_t) { .gauge = value }, 1, db); } /* void gauge_submit */ static void derive_submit (const char *type, const char *type_instance, derive_t value, mysql_database_t *db) { - value_t values[1]; - - values[0].derive = value; - submit (type, type_instance, values, STATIC_ARRAY_SIZE (values), db); + submit (type, type_instance, &(value_t) { .derive = value }, 1, db); } /* void derive_submit */ static void traffic_submit (derive_t rx, derive_t tx, mysql_database_t *db) { - value_t values[2]; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; submit ("mysql_octets", NULL, values, STATIC_ARRAY_SIZE (values), db); } /* void traffic_submit */ @@ -465,7 +447,7 @@ static int mysql_read_master_stats (mysql_database_t *db, MYSQL *con) } position = atoll (row[1]); - counter_submit ("mysql_log_position", "master-bin", position, db); + derive_submit ("mysql_log_position", "master-bin", position, db); row = mysql_fetch_row (res); if (row != NULL) @@ -523,10 +505,10 @@ static int mysql_read_slave_stats (mysql_database_t *db, MYSQL *con) double gauge; counter = atoll (row[READ_MASTER_LOG_POS_IDX]); - counter_submit ("mysql_log_position", "slave-read", counter, db); + derive_submit ("mysql_log_position", "slave-read", counter, db); counter = atoll (row[EXEC_MASTER_LOG_POS_IDX]); - counter_submit ("mysql_log_position", "slave-exec", counter, db); + derive_submit ("mysql_log_position", "slave-exec", counter, db); if (row[SECONDS_BEHIND_MASTER_IDX] != NULL) { @@ -676,7 +658,7 @@ static int mysql_read_innodb_stats (mysql_database_t *db, MYSQL *con) switch (metrics[i].ds_type) { case DS_TYPE_COUNTER: - counter_submit(metrics[i].type, key, (counter_t)val, db); + derive_submit(metrics[i].type, key, (counter_t)val, db); break; case DS_TYPE_GAUGE: gauge_submit(metrics[i].type, key, (gauge_t)val, db); @@ -839,7 +821,7 @@ static int mysql_read (user_data_t *ud) /* Ignore `prepared statements' */ if (strncmp (key, "Com_stmt_", strlen ("Com_stmt_")) != 0) - counter_submit ("mysql_commands", + derive_submit ("mysql_commands", key + strlen ("Com_"), val, db); } @@ -849,7 +831,7 @@ static int mysql_read (user_data_t *ud) if (val == 0ULL) continue; - counter_submit ("mysql_handler", + derive_submit ("mysql_handler", key + strlen ("Handler_"), val, db); } @@ -890,7 +872,7 @@ static int mysql_read (user_data_t *ud) else if (strncmp (key, "Table_locks_", strlen ("Table_locks_")) == 0) { - counter_submit ("mysql_locks", + derive_submit ("mysql_locks", key + strlen ("Table_locks_"), val, db); } @@ -902,7 +884,7 @@ static int mysql_read (user_data_t *ud) else if (strcmp (key, "Innodb_buffer_pool_pages_dirty") == 0) gauge_submit ("mysql_bpool_pages", "dirty", val, db); else if (strcmp (key, "Innodb_buffer_pool_pages_flushed") == 0) - counter_submit ("mysql_bpool_counters", "pages_flushed", val, db); + derive_submit ("mysql_bpool_counters", "pages_flushed", val, db); else if (strcmp (key, "Innodb_buffer_pool_pages_free") == 0) gauge_submit ("mysql_bpool_pages", "free", val, db); else if (strcmp (key, "Innodb_buffer_pool_pages_misc") == 0) @@ -910,19 +892,19 @@ static int mysql_read (user_data_t *ud) else if (strcmp (key, "Innodb_buffer_pool_pages_total") == 0) gauge_submit ("mysql_bpool_pages", "total", val, db); else if (strcmp (key, "Innodb_buffer_pool_read_ahead_rnd") == 0) - counter_submit ("mysql_bpool_counters", "read_ahead_rnd", val, db); + derive_submit ("mysql_bpool_counters", "read_ahead_rnd", val, db); else if (strcmp (key, "Innodb_buffer_pool_read_ahead") == 0) - counter_submit ("mysql_bpool_counters", "read_ahead", val, db); + derive_submit ("mysql_bpool_counters", "read_ahead", val, db); else if (strcmp (key, "Innodb_buffer_pool_read_ahead_evicted") == 0) - counter_submit ("mysql_bpool_counters", "read_ahead_evicted", val, db); + derive_submit ("mysql_bpool_counters", "read_ahead_evicted", val, db); else if (strcmp (key, "Innodb_buffer_pool_read_requests") == 0) - counter_submit ("mysql_bpool_counters", "read_requests", val, db); + derive_submit ("mysql_bpool_counters", "read_requests", val, db); else if (strcmp (key, "Innodb_buffer_pool_reads") == 0) - counter_submit ("mysql_bpool_counters", "reads", val, db); + derive_submit ("mysql_bpool_counters", "reads", val, db); else if (strcmp (key, "Innodb_buffer_pool_wait_free") == 0) - counter_submit ("mysql_bpool_counters", "wait_free", val, db); + derive_submit ("mysql_bpool_counters", "wait_free", val, db); else if (strcmp (key, "Innodb_buffer_pool_write_requests") == 0) - counter_submit ("mysql_bpool_counters", "write_requests", val, db); + derive_submit ("mysql_bpool_counters", "write_requests", val, db); else if (strcmp (key, "Innodb_buffer_pool_bytes_data") == 0) gauge_submit ("mysql_bpool_bytes", "data", val, db); else if (strcmp (key, "Innodb_buffer_pool_bytes_dirty") == 0) @@ -930,80 +912,80 @@ static int mysql_read (user_data_t *ud) /* data */ if (strcmp (key, "Innodb_data_fsyncs") == 0) - counter_submit ("mysql_innodb_data", "fsyncs", val, db); + derive_submit ("mysql_innodb_data", "fsyncs", val, db); else if (strcmp (key, "Innodb_data_read") == 0) - counter_submit ("mysql_innodb_data", "read", val, db); + derive_submit ("mysql_innodb_data", "read", val, db); else if (strcmp (key, "Innodb_data_reads") == 0) - counter_submit ("mysql_innodb_data", "reads", val, db); + derive_submit ("mysql_innodb_data", "reads", val, db); else if (strcmp (key, "Innodb_data_writes") == 0) - counter_submit ("mysql_innodb_data", "writes", val, db); + derive_submit ("mysql_innodb_data", "writes", val, db); else if (strcmp (key, "Innodb_data_written") == 0) - counter_submit ("mysql_innodb_data", "written", val, db); + derive_submit ("mysql_innodb_data", "written", val, db); /* double write */ else if (strcmp (key, "Innodb_dblwr_writes") == 0) - counter_submit ("mysql_innodb_dblwr", "writes", val, db); + derive_submit ("mysql_innodb_dblwr", "writes", val, db); else if (strcmp (key, "Innodb_dblwr_pages_written") == 0) - counter_submit ("mysql_innodb_dblwr", "written", val, db); + derive_submit ("mysql_innodb_dblwr", "written", val, db); else if (strcmp (key, "Innodb_dblwr_page_size") == 0) gauge_submit ("mysql_innodb_dblwr", "page_size", val, db); /* log */ else if (strcmp (key, "Innodb_log_waits") == 0) - counter_submit ("mysql_innodb_log", "waits", val, db); + derive_submit ("mysql_innodb_log", "waits", val, db); else if (strcmp (key, "Innodb_log_write_requests") == 0) - counter_submit ("mysql_innodb_log", "write_requests", val, db); + derive_submit ("mysql_innodb_log", "write_requests", val, db); else if (strcmp (key, "Innodb_log_writes") == 0) - counter_submit ("mysql_innodb_log", "writes", val, db); + derive_submit ("mysql_innodb_log", "writes", val, db); else if (strcmp (key, "Innodb_os_log_fsyncs") == 0) - counter_submit ("mysql_innodb_log", "fsyncs", val, db); + derive_submit ("mysql_innodb_log", "fsyncs", val, db); else if (strcmp (key, "Innodb_os_log_written") == 0) - counter_submit ("mysql_innodb_log", "written", val, db); + derive_submit ("mysql_innodb_log", "written", val, db); /* pages */ else if (strcmp (key, "Innodb_pages_created") == 0) - counter_submit ("mysql_innodb_pages", "created", val, db); + derive_submit ("mysql_innodb_pages", "created", val, db); else if (strcmp (key, "Innodb_pages_read") == 0) - counter_submit ("mysql_innodb_pages", "read", val, db); + derive_submit ("mysql_innodb_pages", "read", val, db); else if (strcmp (key, "Innodb_pages_written") == 0) - counter_submit ("mysql_innodb_pages", "written", val, db); + derive_submit ("mysql_innodb_pages", "written", val, db); /* row lock */ else if (strcmp (key, "Innodb_row_lock_time") == 0) - counter_submit ("mysql_innodb_row_lock", "time", val, db); + derive_submit ("mysql_innodb_row_lock", "time", val, db); else if (strcmp (key, "Innodb_row_lock_waits") == 0) - counter_submit ("mysql_innodb_row_lock", "waits", val, db); + derive_submit ("mysql_innodb_row_lock", "waits", val, db); /* rows */ else if (strcmp (key, "Innodb_rows_deleted") == 0) - counter_submit ("mysql_innodb_rows", "deleted", val, db); + derive_submit ("mysql_innodb_rows", "deleted", val, db); else if (strcmp (key, "Innodb_rows_inserted") == 0) - counter_submit ("mysql_innodb_rows", "inserted", val, db); + derive_submit ("mysql_innodb_rows", "inserted", val, db); else if (strcmp (key, "Innodb_rows_read") == 0) - counter_submit ("mysql_innodb_rows", "read", val, db); + derive_submit ("mysql_innodb_rows", "read", val, db); else if (strcmp (key, "Innodb_rows_updated") == 0) - counter_submit ("mysql_innodb_rows", "updated", val, db); + derive_submit ("mysql_innodb_rows", "updated", val, db); } else if (strncmp (key, "Select_", strlen ("Select_")) == 0) { - counter_submit ("mysql_select", key + strlen ("Select_"), + derive_submit ("mysql_select", key + strlen ("Select_"), val, db); } else if (strncmp (key, "Sort_", strlen ("Sort_")) == 0) { if (strcmp (key, "Sort_merge_passes") == 0) - counter_submit ("mysql_sort_merge_passes", NULL, val, db); + derive_submit ("mysql_sort_merge_passes", NULL, val, db); else if (strcmp (key, "Sort_rows") == 0) - counter_submit ("mysql_sort_rows", NULL, val, db); + derive_submit ("mysql_sort_rows", NULL, val, db); else if (strcmp (key, "Sort_range") == 0) - counter_submit ("mysql_sort", "range", val, db); + derive_submit ("mysql_sort", "range", val, db); else if (strcmp (key, "Sort_scan") == 0) - counter_submit ("mysql_sort", "scan", val, db); + derive_submit ("mysql_sort", "scan", val, db); } else if (strncmp (key, "Slow_queries", strlen ("Slow_queries")) == 0) { - counter_submit ("mysql_slow_queries", NULL , val, db); + derive_submit ("mysql_slow_queries", NULL , val, db); } } mysql_free_result (res); res = NULL; diff --git a/src/netapp.c b/src/netapp.c index d7396964..e83a4753 100644 --- a/src/netapp.c +++ b/src/netapp.c @@ -617,7 +617,7 @@ static data_volume_perf_t *get_volume_perf (cfg_volume_perf_t *cvp, /* {{{ */ static int submit_values (const char *host, /* {{{ */ const char *plugin_inst, const char *type, const char *type_inst, - value_t *values, int values_len, + value_t *values, size_t values_len, cdtime_t timestamp, cdtime_t interval) { value_list_t vl = VALUE_LIST_INIT; @@ -649,50 +649,42 @@ static int submit_two_derive (const char *host, const char *plugin_inst, /* {{{ const char *type, const char *type_inst, derive_t val0, derive_t val1, cdtime_t timestamp, cdtime_t interval) { - value_t values[2]; - - values[0].derive = val0; - values[1].derive = val1; + value_t values[] = { + { .derive = val0 }, + { .derive = val1 }, + }; return (submit_values (host, plugin_inst, type, type_inst, - values, 2, timestamp, interval)); + values, STATIC_ARRAY_SIZE (values), timestamp, interval)); } /* }}} int submit_two_derive */ static int submit_derive (const char *host, const char *plugin_inst, /* {{{ */ const char *type, const char *type_inst, derive_t counter, cdtime_t timestamp, cdtime_t interval) { - value_t v; - - v.derive = counter; - return (submit_values (host, plugin_inst, type, type_inst, - &v, 1, timestamp, interval)); + &(value_t) { .derive = counter }, 1, timestamp, interval)); } /* }}} int submit_derive */ static int submit_two_gauge (const char *host, const char *plugin_inst, /* {{{ */ const char *type, const char *type_inst, gauge_t val0, gauge_t val1, cdtime_t timestamp, cdtime_t interval) { - value_t values[2]; - - values[0].gauge = val0; - values[1].gauge = val1; + value_t values[] = { + { .gauge = val0 }, + { .gauge = val1 }, + }; return (submit_values (host, plugin_inst, type, type_inst, - values, 2, timestamp, interval)); + values, STATIC_ARRAY_SIZE (values), timestamp, interval)); } /* }}} int submit_two_gauge */ static int submit_double (const char *host, const char *plugin_inst, /* {{{ */ const char *type, const char *type_inst, double d, cdtime_t timestamp, cdtime_t interval) { - value_t v; - - v.gauge = (gauge_t) d; - return (submit_values (host, plugin_inst, type, type_inst, - &v, 1, timestamp, interval)); + &(value_t) { .gauge = counter }, 1, timestamp, interval)); } /* }}} int submit_uint64 */ /* Calculate hit ratio from old and new counters and submit the resulting @@ -707,7 +699,7 @@ static int submit_cache_ratio (const char *host, /* {{{ */ cdtime_t timestamp, cdtime_t interval) { - value_t v; + value_t v = { .gauge = NAN }; if ((new_hits >= old_hits) && (new_misses >= old_misses)) { uint64_t hits; @@ -717,8 +709,6 @@ static int submit_cache_ratio (const char *host, /* {{{ */ misses = new_misses - old_misses; v.gauge = 100.0 * ((gauge_t) hits) / ((gauge_t) (hits + misses)); - } else { - v.gauge = NAN; } return (submit_values (host, plugin_inst, "cache_ratio", type_inst, @@ -2879,15 +2869,13 @@ static int cna_register_host (host_config_t *host) /* {{{ */ else ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name); - user_data_t ud = { - .data = host, - .free_func = (void (*) (void *)) free_host_config - }; - plugin_register_complex_read (/* group = */ NULL, cb_name, /* callback = */ cna_read, /* interval = */ host->interval, - /* user data = */ &ud); + &(user_data_t) { + .data = host, + .free_func = (void *) free_host_config, + }); return (0); } /* }}} int cna_register_host */ diff --git a/src/netlink.c b/src/netlink.c index cfca46f7..786056d4 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -194,12 +194,9 @@ static int check_ignorelist (const char *dev, static void submit_one (const char *dev, const char *type, const char *type_instance, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin)); @@ -216,14 +213,14 @@ static void submit_two (const char *dev, const char *type, const char *type_instance, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "netlink", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); diff --git a/src/nginx.c b/src/nginx.c index 16ce3d5f..3850accf 100644 --- a/src/nginx.c +++ b/src/nginx.c @@ -210,7 +210,7 @@ static void submit (const char *type, const char *inst, long long value) return; vl.values = values; - vl.values_len = 1; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "nginx", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance)); diff --git a/src/ntpd.c b/src/ntpd.c index 30f29c97..ccdecd98 100644 --- a/src/ntpd.c +++ b/src/ntpd.c @@ -313,12 +313,9 @@ static int ntpd_config (const char *key, const char *value) static void ntpd_submit (const char *type, const char *type_inst, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ntpd", sizeof (vl.plugin)); diff --git a/src/nut.c b/src/nut.c index b5c6b41b..29074c4e 100644 --- a/src/nut.c +++ b/src/nut.c @@ -120,13 +120,10 @@ static int nut_config (const char *key, const char *value) static void nut_submit (nut_ups_t *ups, const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; sstrncpy (vl.host, (strcasecmp (ups->hostname, "localhost") == 0) ? hostname_g diff --git a/src/olsrd.c b/src/olsrd.c index 899ad3e8..3bf71280 100644 --- a/src/olsrd.c +++ b/src/olsrd.c @@ -216,12 +216,9 @@ __attribute__ ((nonnull(2))) static void olsrd_submit (const char *plugin_instance, /* {{{ */ const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/onewire.c b/src/onewire.c index 235eff80..0b4b6f56 100644 --- a/src/onewire.c +++ b/src/onewire.c @@ -336,7 +336,6 @@ static int cow_load_config (const char *key, const char *value) static int cow_read_values (const char *path, const char *name, const ow_family_features_t *family_info) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; int success = 0; @@ -347,9 +346,6 @@ static int cow_read_values (const char *path, const char *name, return 0; } - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance)); @@ -359,6 +355,7 @@ static int cow_read_values (const char *path, const char *name, char *buffer; size_t buffer_size; int status; + char errbuf[1024]; char file[4096]; char *endptr; @@ -373,14 +370,14 @@ static int cow_read_values (const char *path, const char *name, status = OW_get (file, &buffer, &buffer_size); if (status < 0) { - ERROR ("onewire plugin: OW_get (%s/%s) failed. status = %#x;", - path, family_info->features[i].filename, status); + ERROR ("onewire plugin: OW_get (%s/%s) failed. error = %s;", + path, family_info->features[i].filename, sstrerror(errno, errbuf, sizeof (errbuf))); return (-1); } DEBUG ("Read onewire device %s as %s", file, buffer); endptr = NULL; - values[0].gauge = strtod (buffer, &endptr); + gauge_t g = strtod (buffer, &endptr); if (endptr == NULL) { ERROR ("onewire plugin: Buffer is not a number: %s", buffer); @@ -391,6 +388,9 @@ static int cow_read_values (const char *path, const char *name, sstrncpy (vl.type_instance, family_info->features[i].type_instance, sizeof (vl.type_instance)); + vl.values = &(value_t) { .gauge = g }; + vl.values_len = 1; + plugin_dispatch_values (&vl); success++; @@ -430,6 +430,7 @@ static int cow_read_bus (const char *path) char *buffer; size_t buffer_size; int status; + char errbuf[1024]; char *buffer_ptr; char *dummy; @@ -439,8 +440,8 @@ static int cow_read_bus (const char *path) status = OW_get (path, &buffer, &buffer_size); if (status < 0) { - ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;", - path, status); + ERROR ("onewire plugin: OW_get (%s) failed. error = %s;", + path, sstrerror(errno, errbuf, sizeof (errbuf))); return (-1); } DEBUG ("onewire plugin: OW_get (%s) returned: %s", @@ -493,20 +494,17 @@ static int cow_read_bus (const char *path) static int cow_simple_read (void) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; char *buffer; size_t buffer_size; int status; + char errbuf[1024]; char *endptr; direct_access_element_t *traverse; /* traverse list and check entries */ for (traverse = direct_list; traverse != NULL; traverse = traverse->next) { - vl.values = values; - vl.values_len = 1; - sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "onewire", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, traverse->address, sizeof (vl.plugin_instance)); @@ -514,16 +512,15 @@ static int cow_simple_read (void) status = OW_get (traverse->path, &buffer, &buffer_size); if (status < 0) { - ERROR ("onewire plugin: OW_get (%s) failed. status = %#x;", + ERROR ("onewire plugin: OW_get (%s) failed. status = %s;", traverse->path, - status); + sstrerror(errno, errbuf, sizeof (errbuf))); return (-1); } DEBUG ("onewire plugin: Read onewire device %s as %s", traverse->path, buffer); - endptr = NULL; - values[0].gauge = strtod (buffer, &endptr); + gauge_t g = strtod (buffer, &endptr); if (endptr == NULL) { ERROR ("onewire plugin: Buffer is not a number: %s", buffer); @@ -533,6 +530,9 @@ static int cow_simple_read (void) sstrncpy (vl.type, traverse->file, sizeof (vl.type)); sstrncpy (vl.type_instance, "", sizeof ("")); + vl.values = &(value_t) { .gauge = g }; + vl.values_len = 1; + plugin_dispatch_values (&vl); free (buffer); } /* for (traverse) */ @@ -590,6 +590,7 @@ static int cow_shutdown (void) static int cow_init (void) { int status; + char errbuf[1024]; if (device_g == NULL) { @@ -601,7 +602,7 @@ static int cow_init (void) status = (int) OW_init (device_g); if (status != 0) { - ERROR ("onewire plugin: OW_init(%s) failed: %i.", device_g, status); + ERROR ("onewire plugin: OW_init(%s) failed: %s.", device_g, sstrerror(errno, errbuf, sizeof (errbuf))); return (1); } diff --git a/src/openldap.c b/src/openldap.c index d424cb45..dd3226d3 100644 --- a/src/openldap.c +++ b/src/openldap.c @@ -192,17 +192,13 @@ static void cldap_submit_value (const char *type, const char *type_instance, /* static void cldap_submit_derive (const char *type, const char *type_instance, /* {{{ */ derive_t d, cldap_t *st) { - value_t v; - v.derive = d; - cldap_submit_value (type, type_instance, v, st); + cldap_submit_value (type, type_instance, (value_t) { .derive = d }, st); } /* }}} void cldap_submit_derive */ static void cldap_submit_gauge (const char *type, const char *type_instance, /* {{{ */ gauge_t g, cldap_t *st) { - value_t v; - v.gauge = g; - cldap_submit_value (type, type_instance, v, st); + cldap_submit_value (type, type_instance, (value_t) { .gauge = g }, st); } /* }}} void cldap_submit_gauge */ static int cldap_read_host (user_data_t *ud) /* {{{ */ @@ -663,15 +659,13 @@ static int cldap_config_add (oconfig_item_t *ci) /* {{{ */ (st->host != NULL) ? st->host : hostname_g, (st->name != NULL) ? st->name : "default"); - user_data_t ud = { - .data = st - }; - status = plugin_register_complex_read (/* group = */ NULL, /* name = */ callback_name, /* callback = */ cldap_read_host, /* interval = */ 0, - /* user_data = */ &ud); + &(user_data_t) { + .data = st, + }); } } diff --git a/src/openvpn.c b/src/openvpn.c index 00ae736a..81ffa899 100644 --- a/src/openvpn.c +++ b/src/openvpn.c @@ -99,13 +99,10 @@ static int openvpn_strsplit (char *string, char **fields, size_t size) static void numusers_submit (const char *pinst, const char *tinst, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin)); sstrncpy (vl.type, "users", sizeof (vl.type)); @@ -122,11 +119,11 @@ static void numusers_submit (const char *pinst, const char *tinst, static void iostats_submit (const char *pinst, const char *tinst, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; /* NOTE ON THE NEW NAMING SCHEMA: * using plugin_instance to identify each vpn config (and @@ -152,11 +149,11 @@ static void iostats_submit (const char *pinst, const char *tinst, static void compression_submit (const char *pinst, const char *tinst, derive_t uncompressed, derive_t compressed) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = uncompressed; - values[1].derive = compressed; + value_t values[] = { + { .derive = uncompressed }, + { .derive = compressed }, + }; vl.values = values; vl.values_len = STATIC_ARRAY_SIZE (values); diff --git a/src/perl.c b/src/perl.c index 9eef6c1a..4a11d6c1 100644 --- a/src/perl.c +++ b/src/perl.c @@ -22,6 +22,7 @@ * * Authors: * Sebastian Harl + * Pavel Rochnyak **/ /* @@ -77,8 +78,9 @@ #define PLUGIN_LOG 4 #define PLUGIN_NOTIF 5 #define PLUGIN_FLUSH 6 +#define PLUGIN_FLUSH_ALL 7 /* For collectd-5.6 only */ -#define PLUGIN_TYPES 7 +#define PLUGIN_TYPES 8 #define PLUGIN_CONFIG 254 #define PLUGIN_DATASET 255 @@ -102,6 +104,16 @@ /* this is defined in DynaLoader.a */ void boot_DynaLoader (PerlInterpreter *, CV *); +static XS (Collectd_plugin_register_read); +static XS (Collectd_plugin_register_write); +static XS (Collectd_plugin_register_log); +static XS (Collectd_plugin_register_notification); +static XS (Collectd_plugin_register_flush); +static XS (Collectd_plugin_unregister_read); +static XS (Collectd_plugin_unregister_write); +static XS (Collectd_plugin_unregister_log); +static XS (Collectd_plugin_unregister_notification); +static XS (Collectd_plugin_unregister_flush); static XS (Collectd_plugin_register_ds); static XS (Collectd_plugin_unregister_ds); static XS (Collectd_plugin_dispatch_values); @@ -113,6 +125,14 @@ static XS (Collectd_plugin_log); static XS (Collectd__fc_register); static XS (Collectd_call_by_name); +static int perl_read (user_data_t *ud); +static int perl_write (const data_set_t *ds, const value_list_t *vl, + user_data_t *user_data); +static void perl_log (int level, const char *msg, user_data_t *user_data); +static int perl_notify (const notification_t *notif, user_data_t *user_data); +static int perl_flush (cdtime_t timeout, const char *identifier, + user_data_t *user_data); + /* * private data types */ @@ -165,6 +185,8 @@ extern char **environ; * private variables */ +static _Bool register_legacy_flush = 1; + /* if perl_threads != NULL perl_threads->head must * point to the "base" thread */ static c_ithread_list_t *perl_threads = NULL; @@ -182,6 +204,18 @@ static struct { XS ((*f)); } api[] = { + { "Collectd::plugin_register_read", Collectd_plugin_register_read }, + { "Collectd::plugin_register_write", Collectd_plugin_register_write }, + { "Collectd::plugin_register_log", Collectd_plugin_register_log }, + { "Collectd::plugin_register_notification", + Collectd_plugin_register_notification }, + { "Collectd::plugin_register_flush", Collectd_plugin_register_flush }, + { "Collectd::plugin_unregister_read", Collectd_plugin_unregister_read }, + { "Collectd::plugin_unregister_write", Collectd_plugin_unregister_write }, + { "Collectd::plugin_unregister_log", Collectd_plugin_unregister_log }, + { "Collectd::plugin_unregister_notification", + Collectd_plugin_unregister_notification }, + { "Collectd::plugin_unregister_flush", Collectd_plugin_unregister_flush }, { "Collectd::plugin_register_data_set", Collectd_plugin_register_ds }, { "Collectd::plugin_unregister_data_set", Collectd_plugin_unregister_ds }, { "Collectd::plugin_dispatch_values", Collectd_plugin_dispatch_values }, @@ -1010,7 +1044,7 @@ static int call_pv_locked (pTHX_ const char* sub_name) return 0; } - ret = call_pv (sub_name, G_SCALAR); + ret = call_pv (sub_name, G_SCALAR|G_EVAL); t->running = old_running; return ret; @@ -1019,12 +1053,13 @@ static int call_pv_locked (pTHX_ const char* sub_name) /* * Call all working functions of the given type. */ -static int pplugin_call_all (pTHX_ int type, ...) +static int pplugin_call (pTHX_ int type, ...) { int retvals = 0; va_list ap; int ret = 0; + char *subname; dSP; @@ -1038,9 +1073,17 @@ static int pplugin_call_all (pTHX_ int type, ...) PUSHMARK (SP); - XPUSHs (sv_2mortal (newSViv ((IV)type))); + if (PLUGIN_READ == type) { + subname = va_arg(ap, char *); + } + else if (PLUGIN_WRITE == type) { + data_set_t *ds; + value_list_t *vl; - if (PLUGIN_WRITE == type) { + AV *pds = newAV (); + HV *pvl = newHV (); + + subname = va_arg(ap, char *); /* * $_[0] = $plugin_type; * @@ -1066,12 +1109,6 @@ static int pplugin_call_all (pTHX_ int type, ...) * type_instance => $type_instance * }; */ - data_set_t *ds; - value_list_t *vl; - - AV *pds = newAV (); - HV *pvl = newHV (); - ds = va_arg (ap, data_set_t *); vl = va_arg (ap, value_list_t *); @@ -1094,6 +1131,7 @@ static int pplugin_call_all (pTHX_ int type, ...) XPUSHs (sv_2mortal (newRV_noinc ((SV *)pvl))); } else if (PLUGIN_LOG == type) { + subname = va_arg(ap, char *); /* * $_[0] = $level; * @@ -1103,6 +1141,10 @@ static int pplugin_call_all (pTHX_ int type, ...) XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); } else if (PLUGIN_NOTIF == type) { + notification_t *n; + HV *notif = newHV (); + + subname = va_arg(ap, char *); /* * $_[0] = * { @@ -1116,9 +1158,6 @@ static int pplugin_call_all (pTHX_ int type, ...) * type_instance => $type_instance * }; */ - notification_t *n; - HV *notif = newHV (); - n = va_arg (ap, notification_t *); if (-1 == notification2hv (aTHX_ n, notif)) { @@ -1132,23 +1171,53 @@ static int pplugin_call_all (pTHX_ int type, ...) } else if (PLUGIN_FLUSH == type) { cdtime_t timeout; + subname = va_arg(ap, char *); + /* + * $_[0] = $timeout; + * $_[1] = $identifier; + */ + timeout = va_arg (ap, cdtime_t); + XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout)))); + XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); + } + else if (PLUGIN_FLUSH_ALL == type) { + cdtime_t timeout; + subname = "Collectd::plugin_call_all"; /* * $_[0] = $timeout; * $_[1] = $identifier; */ timeout = va_arg (ap, cdtime_t); + XPUSHs (sv_2mortal (newSViv ((IV)PLUGIN_FLUSH))); XPUSHs (sv_2mortal (newSVnv (CDTIME_T_TO_DOUBLE (timeout)))); XPUSHs (sv_2mortal (newSVpv (va_arg (ap, char *), 0))); } + else if (PLUGIN_INIT == type) { + subname = "Collectd::plugin_call_all"; + XPUSHs (sv_2mortal (newSViv ((IV)type))); + } + else if (PLUGIN_SHUTDOWN == type) { + subname = "Collectd::plugin_call_all"; + XPUSHs (sv_2mortal (newSViv ((IV)type))); + } + else { /* Unknown type. Run 'plugin_call_all' and make compiler happy */ + subname = "Collectd::plugin_call_all"; + XPUSHs (sv_2mortal (newSViv ((IV)type))); + } PUTBACK; - retvals = call_pv_locked (aTHX_ "Collectd::plugin_call_all"); + retvals = call_pv_locked (aTHX_ subname); SPAGAIN; - if (0 < retvals) { + if (SvTRUE(ERRSV)) { + if (PLUGIN_LOG != type) + ERROR ("perl: %s error: %s", subname, SvPV_nolen(ERRSV)); + ret = -1; + } + else if (0 < retvals) { SV *tmp = POPs; if (! SvTRUE (tmp)) ret = -1; @@ -1160,7 +1229,7 @@ static int pplugin_call_all (pTHX_ int type, ...) va_end (ap); return ret; -} /* static int pplugin_call_all (int, ...) */ +} /* static int pplugin_call (int, ...) */ /* * collectd's Perl interpreter based thread implementation. @@ -1176,6 +1245,10 @@ static void c_ithread_destroy (c_ithread_t *ithread) assert (NULL != perl_threads); PERL_SET_CONTEXT (aTHX); + /* Mark as running to avoid deadlock: + c_ithread_destroy -> log_debug -> perl_log() + */ + ithread->running = 1; log_debug ("Shutting down Perl interpreter %p...", aTHX); #if COLLECT_DEBUG @@ -1399,7 +1472,11 @@ static int fc_call (pTHX_ int type, int cb_type, pfc_user_data_t *data, ...) } SPAGAIN; - if (0 < retvals) { + if (SvTRUE(ERRSV)) { + ERROR ("perl: Collectd::fc_call error: %s", SvPV_nolen(ERRSV)); + ret = -1; + } + else if (0 < retvals) { SV *tmp = POPs; /* the exec callbacks return a status, while @@ -1568,6 +1645,173 @@ static target_proc_t ptarget = { * Exported Perl API. */ +static void _plugin_register_generic_userdata (pTHX, int type, const char *desc) +{ + int ret = 0; + user_data_t userdata; + char *pluginname; + + dXSARGS; + + if (2 != items) { + log_err ("Usage: Collectd::plugin_register_%s(pluginname, subname)", + desc); + XSRETURN_EMPTY; + } + + if (! SvOK (ST (0))) { + log_err ("Collectd::plugin_register_%s(pluginname, subname): " + "Invalid pluginname", desc); + XSRETURN_EMPTY; + } + if (! SvOK (ST (1))) { + log_err ("Collectd::plugin_register_%s(pluginname, subname): " + "Invalid subname", desc); + XSRETURN_EMPTY; + } + + /* Use pluginname as-is to allow flush a single perl plugin */ + pluginname = SvPV_nolen (ST (0)); + + log_debug ("Collectd::plugin_register_%s: " + "plugin = \"%s\", sub = \"%s\"", + desc, pluginname, SvPV_nolen (ST (1))); + + memset(&userdata, 0, sizeof(userdata)); + userdata.data = strdup(SvPV_nolen (ST (1))); + userdata.free_func = free; + + if (PLUGIN_READ == type) { + ret = plugin_register_complex_read( + "perl", /* group */ + pluginname, + perl_read, + plugin_get_interval(), /* Default interval */ + &userdata); + } + else if (PLUGIN_WRITE == type) { + ret = plugin_register_write(pluginname, perl_write, &userdata); + } + else if (PLUGIN_LOG == type) { + ret = plugin_register_log(pluginname, perl_log, &userdata); + } + else if (PLUGIN_NOTIF == type) { + ret = plugin_register_notification(pluginname, perl_notify, &userdata); + } + else if (PLUGIN_FLUSH == type) { + if (1 == register_legacy_flush) { /* For collectd-5.7 only, #1731 */ + register_legacy_flush = 0; + ret = plugin_register_flush("perl", perl_flush, /* user_data = */ NULL); + } + + if (0 == ret) + ret = plugin_register_flush(pluginname, perl_flush, &userdata); + } + else { + ret = -1; + } + + if (0 == ret) + XSRETURN_YES; + else { + free (userdata.data); + XSRETURN_EMPTY; + } +} /* static void _plugin_register_generic_userdata ( ... ) */ + +/* + * Collectd::plugin_register_TYPE (pluginname, subname). + * + * pluginname: + * name of the perl plugin + * + * subname: + * name of the plugin's subroutine that does the work + */ + +static XS (Collectd_plugin_register_read) { + return _plugin_register_generic_userdata(aTHX, PLUGIN_READ, "read"); +} + +static XS (Collectd_plugin_register_write) { + return _plugin_register_generic_userdata(aTHX, PLUGIN_WRITE, "write"); +} + +static XS (Collectd_plugin_register_log) { + return _plugin_register_generic_userdata(aTHX, PLUGIN_LOG, "log"); +} + +static XS (Collectd_plugin_register_notification) { + return _plugin_register_generic_userdata(aTHX, PLUGIN_NOTIF, "notification"); +} + +static XS (Collectd_plugin_register_flush) { + return _plugin_register_generic_userdata(aTHX, PLUGIN_FLUSH, "flush"); +} + +typedef int perl_unregister_function_t(const char *name); + +static void _plugin_unregister_generic (pTHX, + perl_unregister_function_t *unreg, const char *desc) +{ + dXSARGS; + + if (1 != items) { + log_err ("Usage: Collectd::plugin_unregister_%s(pluginname)", desc); + XSRETURN_EMPTY; + } + + if (! SvOK (ST (0))) { + log_err ("Collectd::plugin_unregister_%s(pluginname): " + "Invalid pluginname", desc); + XSRETURN_EMPTY; + } + + log_debug ("Collectd::plugin_unregister_%s: plugin = \"%s\"", + desc, SvPV_nolen (ST (0))); + + unreg(SvPV_nolen (ST (0))); + + XSRETURN_EMPTY; + + return; +} /* static void _plugin_unregister_generic ( ... ) */ + +/* + * Collectd::plugin_unregister_TYPE (pluginname). + * + * TYPE: + * type of callback to be unregistered: read, write, log, notification, flush + * + * pluginname: + * name of the perl plugin + */ + +static XS (Collectd_plugin_unregister_read) { + return _plugin_unregister_generic(aTHX, + plugin_unregister_read, "read"); +} + +static XS (Collectd_plugin_unregister_write) { + return _plugin_unregister_generic(aTHX, + plugin_unregister_write, "write"); +} + +static XS (Collectd_plugin_unregister_log) { + return _plugin_unregister_generic(aTHX, + plugin_unregister_log, "log"); +} + +static XS (Collectd_plugin_unregister_notification) { + return _plugin_unregister_generic(aTHX, + plugin_unregister_notification, "notification"); +} + +static XS (Collectd_plugin_unregister_flush) { + return _plugin_unregister_generic(aTHX, + plugin_unregister_flush, "flush"); +} + /* * Collectd::plugin_register_data_set (type, dataset). * @@ -1955,14 +2199,14 @@ static int perl_init (void) assert (aTHX == perl_threads->head->interp); pthread_mutex_lock (&perl_threads->mutex); - status = pplugin_call_all (aTHX_ PLUGIN_INIT); + status = pplugin_call (aTHX_ PLUGIN_INIT); pthread_mutex_unlock (&perl_threads->mutex); return status; } /* static int perl_init (void) */ -static int perl_read (void) +static int perl_read (user_data_t *user_data) { dTHX; @@ -1986,11 +2230,12 @@ static int perl_read (void) log_debug ("perl_read: c_ithread: interp = %p (active threads: %i)", aTHX, perl_threads->number_of_threads); - return pplugin_call_all (aTHX_ PLUGIN_READ); -} /* static int perl_read (void) */ + + return pplugin_call (aTHX_ PLUGIN_READ, user_data->data); +} /* static int perl_read (user_data_t *user_data) */ static int perl_write (const data_set_t *ds, const value_list_t *vl, - user_data_t __attribute__((unused)) *user_data) + user_data_t *user_data) { int status; dTHX; @@ -2016,7 +2261,7 @@ static int perl_write (const data_set_t *ds, const value_list_t *vl, log_debug ("perl_write: c_ithread: interp = %p (active threads: %i)", aTHX, perl_threads->number_of_threads); - status = pplugin_call_all (aTHX_ PLUGIN_WRITE, ds, vl); + status = pplugin_call (aTHX_ PLUGIN_WRITE, user_data->data, ds, vl); if (aTHX == perl_threads->head->interp) pthread_mutex_unlock (&perl_threads->mutex); @@ -2025,7 +2270,7 @@ static int perl_write (const data_set_t *ds, const value_list_t *vl, } /* static int perl_write (const data_set_t *, const value_list_t *) */ static void perl_log (int level, const char *msg, - user_data_t __attribute__((unused)) *user_data) + user_data_t *user_data) { dTHX; @@ -2050,7 +2295,7 @@ static void perl_log (int level, const char *msg, if (aTHX == perl_threads->head->interp) pthread_mutex_lock (&perl_threads->mutex); - pplugin_call_all (aTHX_ PLUGIN_LOG, level, msg); + pplugin_call (aTHX_ PLUGIN_LOG, user_data->data, level, msg); if (aTHX == perl_threads->head->interp) pthread_mutex_unlock (&perl_threads->mutex); @@ -2058,8 +2303,7 @@ static void perl_log (int level, const char *msg, return; } /* static void perl_log (int, const char *) */ -static int perl_notify (const notification_t *notif, - user_data_t __attribute__((unused)) *user_data) +static int perl_notify (const notification_t *notif, user_data_t *user_data) { dTHX; @@ -2075,11 +2319,11 @@ static int perl_notify (const notification_t *notif, aTHX = t->interp; } - return pplugin_call_all (aTHX_ PLUGIN_NOTIF, notif); + return pplugin_call (aTHX_ PLUGIN_NOTIF, user_data->data, notif); } /* static int perl_notify (const notification_t *) */ static int perl_flush (cdtime_t timeout, const char *identifier, - user_data_t __attribute__((unused)) *user_data) + user_data_t *user_data) { dTHX; @@ -2095,7 +2339,12 @@ static int perl_flush (cdtime_t timeout, const char *identifier, aTHX = t->interp; } - return pplugin_call_all (aTHX_ PLUGIN_FLUSH, timeout, identifier); + + /* For collectd-5.6 only, #1731 */ + if (user_data == NULL || user_data->data == NULL) + return pplugin_call (aTHX_ PLUGIN_FLUSH_ALL, timeout, identifier); + + return pplugin_call (aTHX_ PLUGIN_FLUSH, user_data->data, timeout, identifier); } /* static int perl_flush (const int) */ static int perl_shutdown (void) @@ -2106,6 +2355,7 @@ static int perl_shutdown (void) dTHX; plugin_unregister_complex_config ("perl"); + plugin_unregister_read_group ("perl"); if (NULL == perl_threads) return 0; @@ -2121,14 +2371,10 @@ static int perl_shutdown (void) log_debug ("perl_shutdown: c_ithread: interp = %p (active threads: %i)", aTHX, perl_threads->number_of_threads); - plugin_unregister_log ("perl"); - plugin_unregister_notification ("perl"); plugin_unregister_init ("perl"); - plugin_unregister_read ("perl"); - plugin_unregister_write ("perl"); - plugin_unregister_flush ("perl"); + plugin_unregister_flush ("perl"); /* For collectd-5.6 only, #1731 */ - ret = pplugin_call_all (aTHX_ PLUGIN_SHUTDOWN); + ret = pplugin_call (aTHX_ PLUGIN_SHUTDOWN); pthread_mutex_lock (&perl_threads->mutex); t = perl_threads->tail; @@ -2338,15 +2584,7 @@ static int init_pi (int argc, char **argv) perl_run (aTHX); - plugin_register_log ("perl", perl_log, /* user_data = */ NULL); - plugin_register_notification ("perl", perl_notify, - /* user_data = */ NULL); plugin_register_init ("perl", perl_init); - - plugin_register_read ("perl", perl_read); - - plugin_register_write ("perl", perl_write, /* user_data = */ NULL); - plugin_register_flush ("perl", perl_flush, /* user_data = */ NULL); plugin_register_shutdown ("perl", perl_shutdown); return 0; } /* static int init_pi (const char **, const int) */ @@ -2568,6 +2806,8 @@ static int perl_config (oconfig_item_t *ci) current_status = perl_config_includedir (aTHX_ c); else if (0 == strcasecmp (c->key, "Plugin")) current_status = perl_config_plugin (aTHX_ c); + else if (0 == strcasecmp (c->key, "RegisterLegacyFlush")) + cf_util_get_boolean (c, ®ister_legacy_flush); else { log_warn ("Ignoring unknown config key \"%s\".", c->key); diff --git a/src/pinba.c b/src/pinba.c index 8a0902aa..76b765b8 100644 --- a/src/pinba.c +++ b/src/pinba.c @@ -677,38 +677,36 @@ static int plugin_shutdown (void) /* {{{ */ static int plugin_submit (const pinba_statnode_t *res) /* {{{ */ { - value_t value; value_list_t vl = VALUE_LIST_INIT; - vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "pinba", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, res->name, sizeof (vl.plugin_instance)); - value.derive = res->req_count; + vl.values = &(value_t) { .derive = res->req_count }; sstrncpy (vl.type, "total_requests", sizeof (vl.type)); plugin_dispatch_values (&vl); - value.derive = float_counter_get (&res->req_time, /* factor = */ 1000); + vl.values = &(value_t) { .derive = float_counter_get (&res->req_time, /* factor = */ 1000) }; sstrncpy (vl.type, "total_time_in_ms", sizeof (vl.type)); plugin_dispatch_values (&vl); - value.derive = res->doc_size; + vl.values = &(value_t) { .derive = res->doc_size }; sstrncpy (vl.type, "total_bytes", sizeof (vl.type)); plugin_dispatch_values (&vl); - value.derive = float_counter_get (&res->ru_utime, /* factor = */ 100); + vl.values = &(value_t) { .derive = float_counter_get (&res->ru_utime, /* factor = */ 100) }; sstrncpy (vl.type, "cpu", sizeof (vl.type)); sstrncpy (vl.type_instance, "user", sizeof (vl.type_instance)); plugin_dispatch_values (&vl); - value.derive = float_counter_get (&res->ru_stime, /* factor = */ 100); + vl.values = &(value_t) { .derive = float_counter_get (&res->ru_stime, /* factor = */ 100) }; sstrncpy (vl.type, "cpu", sizeof (vl.type)); sstrncpy (vl.type_instance, "system", sizeof (vl.type_instance)); plugin_dispatch_values (&vl); - value.gauge = res->mem_peak; + vl.values = &(value_t) { .gauge = res->mem_peak }; sstrncpy (vl.type, "memory", sizeof (vl.type)); sstrncpy (vl.type_instance, "peak", sizeof (vl.type_instance)); plugin_dispatch_values (&vl); diff --git a/src/ping.c b/src/ping.c index 5f66aab3..39e9de51 100644 --- a/src/ping.c +++ b/src/ping.c @@ -615,12 +615,9 @@ static int ping_config (const char *key, const char *value) /* {{{ */ static void submit (const char *host, const char *type, /* {{{ */ gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ping", sizeof (vl.plugin)); diff --git a/src/powerdns.c b/src/powerdns.c index f907d006..eb541800 100644 --- a/src/powerdns.c +++ b/src/powerdns.c @@ -300,10 +300,10 @@ static char *local_sockpath = NULL; /* */ static void submit (const char *plugin_instance, /* {{{ */ - const char *pdns_type, const char *value) + const char *pdns_type, const char *value_str) { value_list_t vl = VALUE_LIST_INIT; - value_t values[1]; + value_t value; const char *type = NULL; const char *type_instance = NULL; @@ -318,7 +318,7 @@ static void submit (const char *plugin_instance, /* {{{ */ if (i >= lookup_table_length) { INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;", - pdns_type, value); + pdns_type, value_str); return; } @@ -345,14 +345,14 @@ static void submit (const char *plugin_instance, /* {{{ */ return; } - if (0 != parse_value (value, &values[0], ds->ds[0].type)) + if (0 != parse_value (value_str, &value, ds->ds[0].type)) { ERROR ("powerdns plugin: Cannot convert `%s' " - "to a number.", value); + "to a number.", value_str); return; } - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "powerdns", sizeof (vl.plugin)); diff --git a/src/processes.c b/src/processes.c index 0513a156..f470c84c 100644 --- a/src/processes.c +++ b/src/processes.c @@ -660,12 +660,9 @@ static int ps_init (void) /* submit global state (e.g.: qty of zombies, running, etc..) */ static void ps_submit_state (const char *state, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "processes", sizeof (vl.plugin)); @@ -679,11 +676,10 @@ static void ps_submit_state (const char *state, double value) /* submit info about specific process (e.g.: memory taken, cpu usage, etc..) */ static void ps_submit_proc_list (procstat_t *ps) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; + value_t values[2]; vl.values = values; - vl.values_len = 2; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "processes", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance)); @@ -784,12 +780,9 @@ static void ps_submit_proc_list (procstat_t *ps) #if KERNEL_LINUX || KERNEL_SOLARIS static void ps_submit_fork_rate (derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = value; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy(vl.host, hostname_g, sizeof (vl.host)); sstrncpy(vl.plugin, "processes", sizeof (vl.plugin)); diff --git a/src/protocols.c b/src/protocols.c index 208da8b2..ae35c425 100644 --- a/src/protocols.c +++ b/src/protocols.c @@ -55,11 +55,11 @@ static ignorelist_t *values_list = NULL; static void submit (const char *protocol_name, const char *str_key, const char *str_value) { - value_t values[1]; + value_t value; value_list_t vl = VALUE_LIST_INIT; int status; - status = parse_value (str_value, values, DS_TYPE_DERIVE); + status = parse_value (str_value, &value, DS_TYPE_DERIVE); if (status != 0) { ERROR ("protocols plugin: Parsing string as integer failed: %s", @@ -67,7 +67,7 @@ static void submit (const char *protocol_name, return; } - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "protocols", sizeof (vl.plugin)); diff --git a/src/python.c b/src/python.c index ec2317b3..5274262b 100644 --- a/src/python.c +++ b/src/python.c @@ -665,12 +665,11 @@ static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObjec c->data = data; c->next = NULL; - user_data_t user_data = { - .data = c, - .free_func = cpy_destroy_user_data - }; + register_function(buf, handler, &(user_data_t) { + .data = c, + .free_func = cpy_destroy_user_data, + }); - register_function(buf, handler, &user_data); ++cpy_num_callbacks; return cpy_string_to_unicode_or_bytes(buf); } @@ -704,13 +703,12 @@ static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwd c->data = data; c->next = NULL; - user_data_t user_data = { - .data = c, - .free_func = cpy_destroy_user_data - }; - plugin_register_complex_read(/* group = */ "python", buf, - cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data); + cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), + &(user_data_t) { + .data = c, + .free_func = cpy_destroy_user_data, + }); ++cpy_num_callbacks; return cpy_string_to_unicode_or_bytes(buf); } diff --git a/src/redis.c b/src/redis.c index 5214eccc..7f57571e 100644 --- a/src/redis.c +++ b/src/redis.c @@ -252,12 +252,9 @@ static void redis_submit (char *plugin_instance, const char *type, const char *type_instance, value_t value) /* {{{ */ { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0] = value; - - vl.values = values; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "redis", sizeof (vl.plugin)); diff --git a/src/routeros.c b/src/routeros.c index a270f484..5e8a2943 100644 --- a/src/routeros.c +++ b/src/routeros.c @@ -52,11 +52,11 @@ typedef struct cr_data_s cr_data_t; static void cr_submit_io (cr_data_t *rd, const char *type, /* {{{ */ const char *type_instance, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; vl.values_len = STATIC_ARRAY_SIZE (values); @@ -325,7 +325,6 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */ { cr_data_t *router_data; char read_name[128]; - user_data_t user_data; int status; router_data = calloc (1, sizeof (*router_data)); @@ -409,11 +408,12 @@ static int cr_config_router (oconfig_item_t *ci) /* {{{ */ } ssnprintf (read_name, sizeof (read_name), "routeros/%s", router_data->node); - user_data.data = router_data; - user_data.free_func = (void *) cr_free_data; if (status == 0) status = plugin_register_complex_read (/* group = */ NULL, read_name, - cr_read, /* interval = */ 0, &user_data); + cr_read, /* interval = */ 0, &(user_data_t) { + .data = router_data, + .free_func = (void *) cr_free_data, + }); if (status != 0) cr_free_data (router_data); diff --git a/src/rrdcached.c b/src/rrdcached.c index 04254194..07eac7b6 100644 --- a/src/rrdcached.c +++ b/src/rrdcached.c @@ -292,8 +292,9 @@ static int rc_read (void) int status; rrdc_stats_t *head; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; + vl.values = &(value_t) { .gauge = NAN }; + vl.values_len = 1; if (daemon_address == NULL) return (-1); @@ -301,9 +302,6 @@ static int rc_read (void) if (!config_collect_stats) return (-1); - vl.values = values; - vl.values_len = 1; - if ((strncmp ("unix:", daemon_address, strlen ("unix:")) == 0) || (daemon_address[0] == '/')) sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -330,9 +328,9 @@ static int rc_read (void) for (rrdc_stats_t *ptr = head; ptr != NULL; ptr = ptr->next) { if (ptr->type == RRDC_STATS_TYPE_GAUGE) - values[0].gauge = (gauge_t) ptr->value.gauge; + vl.values[0].gauge = (gauge_t) ptr->value.gauge; else if (ptr->type == RRDC_STATS_TYPE_COUNTER) - values[0].counter = (counter_t) ptr->value.counter; + vl.values[0].counter = (counter_t) ptr->value.counter; else continue; diff --git a/src/sensors.c b/src/sensors.c index 4f3d0d60..f13b3ea1 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -481,12 +481,11 @@ static int sensors_shutdown (void) static void sensors_submit (const char *plugin_instance, const char *type, const char *type_instance, - double val) + double value) { char match_key[1024]; int status; - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; status = ssnprintf (match_key, sizeof (match_key), "%s/%s-%s", @@ -501,9 +500,7 @@ static void sensors_submit (const char *plugin_instance, return; } - values[0].gauge = val; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/serial.c b/src/serial.c index cf7ad2a1..48223202 100644 --- a/src/serial.c +++ b/src/serial.c @@ -33,14 +33,14 @@ static void serial_submit (const char *type_instance, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "serial", sizeof (vl.plugin)); sstrncpy (vl.type, "serial_octets", sizeof (vl.type)); diff --git a/src/sigrok.c b/src/sigrok.c index 40064553..5b850040 100644 --- a/src/sigrok.c +++ b/src/sigrok.c @@ -161,7 +161,6 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi, { const struct sr_datafeed_analog *analog; struct config_device *cfdev; - value_t value; value_list_t vl = VALUE_LIST_INIT; /* Find this device's configuration. */ @@ -199,8 +198,7 @@ static void sigrok_feed_callback(const struct sr_dev_inst *sdi, /* Ignore all but the first sample on the first probe. */ analog = packet->payload; - value.gauge = analog->data[0]; - vl.values = &value; + vl.values = &(value_t) { .gauge = analog->data[0] }; vl.values_len = 1; sstrncpy(vl.host, hostname_g, sizeof(vl.host)); sstrncpy(vl.plugin, "sigrok", sizeof(vl.plugin)); diff --git a/src/smart.c b/src/smart.c index 752cb74c..52e78a15 100644 --- a/src/smart.c +++ b/src/smart.c @@ -86,12 +86,9 @@ static int smart_config (const char *key, const char *value) static void smart_submit (const char *dev, const char *type, const char *type_inst, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "smart", sizeof (vl.plugin)); @@ -106,17 +103,20 @@ static void smart_handle_disk_attribute(SkDisk *d, const SkSmartAttributeParsedD void* userdata) { const char *dev = userdata; - value_t values[4]; - value_list_t vl = VALUE_LIST_INIT; - if (!a->current_value_valid || !a->worst_value_valid) return; - values[0].gauge = a->current_value; - values[1].gauge = a->worst_value; - values[2].gauge = a->threshold_valid?a->threshold:0; - values[3].gauge = a->pretty_value; + if (!a->current_value_valid || !a->worst_value_valid) + return; + + value_list_t vl = VALUE_LIST_INIT; + value_t values[] = { + { .gauge = a->current_value }, + { .gauge = a->worst_value }, + { .gauge = a->threshold_valid ? a->threshold : 0 }, + { .gauge = a->pretty_value }, + }; vl.values = values; - vl.values_len = 4; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "smart", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance)); diff --git a/src/snmp.c b/src/snmp.c index abeda436..d80ee922 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -764,13 +764,11 @@ static int csnmp_config_add_host (oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name); - user_data_t ud = { - .data = hd, - .free_func = csnmp_host_definition_destroy - }; - status = plugin_register_complex_read (/* group = */ NULL, cb_name, - csnmp_read_host, hd->interval, /* user_data = */ &ud); + csnmp_read_host, hd->interval, &(user_data_t) { + .data = hd, + .free_func = csnmp_host_definition_destroy, + }); if (status != 0) { ERROR ("snmp plugin: Registering complex read function failed."); diff --git a/src/statsd.c b/src/statsd.c index 9c138f97..82ae387b 100644 --- a/src/statsd.c +++ b/src/statsd.c @@ -752,10 +752,9 @@ static int statsd_metric_clear_set_unsafe (statsd_metric_t *metric) /* {{{ */ /* Must hold metrics_lock when calling this function. */ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metric) /* {{{ */ { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - vl.values = values; + vl.values = &(value_t) { .gauge = NAN }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "statsd", sizeof (vl.plugin)); @@ -772,7 +771,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri sstrncpy (vl.type_instance, name, sizeof (vl.type_instance)); if (metric->type == STATSD_GAUGE) - values[0].gauge = (gauge_t) metric->value; + vl.values[0].gauge = (gauge_t) metric->value; else if (metric->type == STATSD_TIMER) { _Bool have_events = (metric->updates_num > 0); @@ -782,7 +781,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-average", name); - values[0].gauge = have_events + vl.values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_average (metric->latency)) : NAN; plugin_dispatch_values (&vl); @@ -790,7 +789,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri if (conf_timer_lower) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-lower", name); - values[0].gauge = have_events + vl.values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_min (metric->latency)) : NAN; plugin_dispatch_values (&vl); @@ -799,7 +798,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri if (conf_timer_upper) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-upper", name); - values[0].gauge = have_events + vl.values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_max (metric->latency)) : NAN; plugin_dispatch_values (&vl); @@ -808,7 +807,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri if (conf_timer_sum) { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-sum", name); - values[0].gauge = have_events + vl.values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_sum (metric->latency)) : NAN; plugin_dispatch_values (&vl); @@ -818,7 +817,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri { ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-percentile-%.0f", name, conf_timer_percentile[i]); - values[0].gauge = have_events + vl.values[0].gauge = have_events ? CDTIME_T_TO_DOUBLE (latency_counter_get_percentile (metric->latency, conf_timer_percentile[i])) : NAN; plugin_dispatch_values (&vl); @@ -830,7 +829,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri sstrncpy (vl.type, "gauge", sizeof (vl.type)); ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-count", name); - values[0].gauge = latency_counter_get_num (metric->latency); + vl.values[0].gauge = latency_counter_get_num (metric->latency); plugin_dispatch_values (&vl); } @@ -840,9 +839,9 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri else if (metric->type == STATSD_SET) { if (metric->set == NULL) - values[0].gauge = 0.0; + vl.values[0].gauge = 0.0; else - values[0].gauge = (gauge_t) c_avl_size (metric->set); + vl.values[0].gauge = (gauge_t) c_avl_size (metric->set); } else { /* STATSD_COUNTER */ gauge_t delta = nearbyint (metric->value); @@ -854,7 +853,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri if (conf_counter_sum) { sstrncpy (vl.type, "count", sizeof (vl.type)); - values[0].gauge = delta; + vl.values[0].gauge = delta; plugin_dispatch_values (&vl); /* restore vl.type */ @@ -866,7 +865,7 @@ static int statsd_metric_submit_unsafe (char const *name, statsd_metric_t *metri metric->value -= delta; metric->counter += (derive_t) delta; - values[0].derive = metric->counter; + vl.values[0].derive = metric->counter; } return (plugin_dispatch_values (&vl)); diff --git a/src/swap.c b/src/swap.c index 9c63e9bb..3cc9516e 100644 --- a/src/swap.c +++ b/src/swap.c @@ -194,11 +194,10 @@ static void swap_submit_usage (char const *plugin_instance, /* {{{ */ gauge_t used, gauge_t free, char const *other_name, gauge_t other_value) { - value_t v[1]; value_list_t vl = VALUE_LIST_INIT; - vl.values = v; - vl.values_len = STATIC_ARRAY_SIZE (v); + vl.values = &(value_t) { .gauge = NAN }; + vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "swap", sizeof (vl.plugin)); if (plugin_instance != NULL) @@ -222,12 +221,9 @@ static void swap_submit_derive (char const *type_instance, /* {{{ */ derive_t value) { value_list_t vl = VALUE_LIST_INIT; - value_t v[1]; - v[0].derive = value; - - vl.values = v; - vl.values_len = STATIC_ARRAY_SIZE (v); + vl.values = &(value_t) { .derive = value }; + vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "swap", sizeof (vl.plugin)); sstrncpy (vl.type, "swap_io", sizeof (vl.type)); diff --git a/src/tail.c b/src/tail.c index e8cde1ed..74fdf84a 100644 --- a/src/tail.c +++ b/src/tail.c @@ -339,11 +339,10 @@ static int ctail_init (void) { ssnprintf(str, sizeof(str), "tail-%zu", i); - user_data_t ud = { - .data = tail_match_list[i] - }; - - plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud); + plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], + &(user_data_t) { + .data = tail_match_list[i], + }); } return (0); diff --git a/src/tail_csv.c b/src/tail_csv.c index 1bdf8b29..faeb56f8 100644 --- a/src/tail_csv.c +++ b/src/tail_csv.c @@ -482,13 +482,11 @@ static int tcsv_config_add_file(oconfig_item_t *ci) ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path); - user_data_t ud = { - .data = id, - .free_func = tcsv_instance_definition_destroy - }; - - status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &ud); - + status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, + &(user_data_t) { + .data = id, + .free_func = tcsv_instance_definition_destroy, + }); if (status != 0){ ERROR("tail_csv plugin: Registering complex read function failed."); tcsv_instance_definition_destroy(id); diff --git a/src/tape.c b/src/tape.c index 52da2bc6..8ec9bf28 100644 --- a/src/tape.c +++ b/src/tape.c @@ -61,14 +61,14 @@ static void tape_submit (const char *plugin_instance, const char *type, derive_t read, derive_t write) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = read; - values[1].derive = write; + value_t values[] = { + { .derive = read }, + { .derive = write }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "tape", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plugin_instance, diff --git a/src/target_replace.c b/src/target_replace.c index 40a6fec9..dba3a8cf 100644 --- a/src/target_replace.c +++ b/src/target_replace.c @@ -38,11 +38,22 @@ struct tr_action_s { regex_t re; char *replacement; - int may_be_empty; + _Bool may_be_empty; tr_action_t *next; }; +struct tr_meta_data_action_s; +typedef struct tr_meta_data_action_s tr_meta_data_action_t; +struct tr_meta_data_action_s +{ + char *key; + regex_t re; + char *replacement; + + tr_meta_data_action_t *next; +}; + struct tr_data_s { tr_action_t *host; @@ -50,6 +61,7 @@ struct tr_data_s tr_action_t *plugin_instance; /* tr_action_t *type; */ tr_action_t *type_instance; + tr_meta_data_action_t *meta; }; typedef struct tr_data_s tr_data_t; @@ -85,8 +97,23 @@ static void tr_action_destroy (tr_action_t *act) /* {{{ */ sfree (act); } /* }}} void tr_action_destroy */ +static void tr_meta_data_action_destroy (tr_meta_data_action_t *act) /* {{{ */ +{ + if (act == NULL) + return; + + sfree (act->key); + regfree (&act->re); + sfree (act->replacement); + + if (act->next != NULL) + tr_meta_data_action_destroy (act->next); + + sfree (act); +} /* }}} void tr_meta_data_action_destroy */ + static int tr_config_add_action (tr_action_t **dest, /* {{{ */ - const oconfig_item_t *ci, int may_be_empty) + const oconfig_item_t *ci, _Bool may_be_empty) { tr_action_t *act; int status; @@ -131,8 +158,7 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */ if (act->replacement == NULL) { ERROR ("tr_config_add_action: tr_strdup failed."); - regfree (&act->re); - sfree (act); + tr_action_destroy (act); return (-ENOMEM); } @@ -153,8 +179,108 @@ static int tr_config_add_action (tr_action_t **dest, /* {{{ */ return (0); } /* }}} int tr_config_add_action */ +static int tr_config_add_meta_action (tr_meta_data_action_t **dest, /* {{{ */ + const oconfig_item_t *ci, _Bool should_delete) +{ + tr_meta_data_action_t *act; + int status; + + if (dest == NULL) + return (-EINVAL); + + if (should_delete) + { + if ((ci->values_num != 2) + || (ci->values[0].type != OCONFIG_TYPE_STRING) + || (ci->values[1].type != OCONFIG_TYPE_STRING)) + { + ERROR ("Target `replace': The `%s' option requires exactly two string " + "arguments.", ci->key); + return (-1); + } + } + else + { + if ((ci->values_num != 3) + || (ci->values[0].type != OCONFIG_TYPE_STRING) + || (ci->values[1].type != OCONFIG_TYPE_STRING) + || (ci->values[2].type != OCONFIG_TYPE_STRING)) + { + ERROR ("Target `replace': The `%s' option requires exactly three string " + "arguments.", ci->key); + return (-1); + } + } + + if (strlen (ci->values[0].value.string) == 0) + { + ERROR ("Target `replace': The `%s' option does not accept empty string as " + "first argument.", ci->key); + return (-1); + } + + act = calloc (1, sizeof (*act)); + if (act == NULL) + { + ERROR ("tr_config_add_meta_action: calloc failed."); + return (-ENOMEM); + } + + act->key = NULL; + act->replacement = NULL; + + status = regcomp (&act->re, ci->values[1].value.string, REG_EXTENDED); + if (status != 0) + { + char errbuf[1024] = ""; + + /* regerror assures null termination. */ + regerror (status, &act->re, errbuf, sizeof (errbuf)); + ERROR ("Target `replace': Compiling the regular expression `%s' " + "failed: %s.", + ci->values[1].value.string, errbuf); + sfree (act->key); + sfree (act); + return (-EINVAL); + } + + act->key = tr_strdup (ci->values[0].value.string); + if (act->key == NULL) + { + ERROR ("tr_config_add_meta_action: tr_strdup failed."); + tr_meta_data_action_destroy (act); + return (-ENOMEM); + } + + if (!should_delete) { + act->replacement = tr_strdup (ci->values[2].value.string); + if (act->replacement == NULL) + { + ERROR ("tr_config_add_meta_action: tr_strdup failed."); + tr_meta_data_action_destroy (act); + return (-ENOMEM); + } + } + + /* Insert action at end of list. */ + if (*dest == NULL) + *dest = act; + else + { + tr_meta_data_action_t *prev; + + prev = *dest; + while (prev->next != NULL) + prev = prev->next; + + prev->next = act; + } + + return (0); +} /* }}} int tr_config_add_meta_action */ + static int tr_action_invoke (tr_action_t *act_head, /* {{{ */ - char *buffer_in, size_t buffer_in_size, int may_be_empty) + char *buffer_in, size_t buffer_in_size, _Bool may_be_empty) { int status; char buffer[DATA_MAX_NAME_LEN]; @@ -215,6 +341,119 @@ static int tr_action_invoke (tr_action_t *act_head, /* {{{ */ return (0); } /* }}} int tr_action_invoke */ +static int tr_meta_data_action_invoke ( /* {{{ */ + tr_meta_data_action_t *act_head, meta_data_t **dest) +{ + int status; + regmatch_t matches[8] = { [0] = { 0 } }; + + if (act_head == NULL) + return (-EINVAL); + + if ((*dest) == NULL) /* nothing to do */ + return (0); + + for (tr_meta_data_action_t *act = act_head; act != NULL; act = act->next) + { + char temp[DATA_MAX_NAME_LEN]; + char *subst_status; + int value_type; + int meta_data_status; + char *value; + meta_data_t *result; + + value_type = meta_data_type (*dest, act->key); + if (value_type == 0) /* not found */ + continue; + if (value_type != MD_TYPE_STRING) + { + WARNING ("Target `replace': Attempting replace on metadata key `%s', " + "which isn't a string.", + act->key); + continue; + } + + meta_data_status = meta_data_get_string (*dest, act->key, &value); + if (meta_data_status != 0) + { + ERROR ("Target `replace': Unable to retrieve metadata value for `%s'.", + act->key); + return (meta_data_status); + } + + DEBUG ("target_replace plugin: tr_meta_data_action_invoke: `%s' " + "old value = `%s'", act->key, value); + + status = regexec (&act->re, value, + STATIC_ARRAY_SIZE (matches), matches, + /* flags = */ 0); + if (status == REG_NOMATCH) + { + sfree (value); + continue; + } + else if (status != 0) + { + char errbuf[1024] = ""; + + regerror (status, &act->re, errbuf, sizeof (errbuf)); + ERROR ("Target `replace': Executing a regular expression failed: %s.", + errbuf); + sfree (value); + continue; + } + + if (act->replacement == NULL) + { + /* no replacement; delete the key */ + DEBUG ("target_replace plugin: tr_meta_data_action_invoke: " + "deleting `%s'", act->key); + meta_data_delete (*dest, act->key); + sfree (value); + continue; + } + + subst_status = subst (temp, sizeof (temp), value, + (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, act->replacement); + if (subst_status == NULL) + { + ERROR ("Target `replace': subst (value = %s, start = %zu, end = %zu, " + "replacement = %s) failed.", + value, (size_t) matches[0].rm_so, (size_t) matches[0].rm_eo, + act->replacement); + sfree (value); + continue; + } + + DEBUG ("target_replace plugin: tr_meta_data_action_invoke: `%s' " + "value `%s' -> `%s'", act->key, value, temp); + + if ((result = meta_data_create()) == NULL) + { + ERROR ("Target `replace': failed to create metadata for `%s'.", + act->key); + sfree (value); + return (-ENOMEM); + } + + meta_data_status = meta_data_add_string (result, act->key, temp); + if (meta_data_status != 0) + { + ERROR ("Target `replace': Unable to set metadata value for `%s'.", + act->key); + meta_data_destroy (result); + sfree (value); + return (meta_data_status); + } + + meta_data_clone_merge (dest, result); + meta_data_destroy (result); + sfree (value); + } /* for (act = act_head; act != NULL; act = act->next) */ + + return (0); +} /* }}} int tr_meta_data_action_invoke */ + static int tr_destroy (void **user_data) /* {{{ */ { tr_data_t *data; @@ -231,6 +470,7 @@ static int tr_destroy (void **user_data) /* {{{ */ tr_action_destroy (data->plugin_instance); /* tr_action_destroy (data->type); */ tr_action_destroy (data->type_instance); + tr_meta_data_action_destroy (data->meta); sfree (data); return (0); @@ -253,6 +493,7 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ data->plugin_instance = NULL; /* data->type = NULL; */ data->type_instance = NULL; + data->meta = NULL; status = 0; for (int i = 0; i < ci->children_num; i++) @@ -277,6 +518,12 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ else if (strcasecmp ("TypeInstance", child->key) == 0) status = tr_config_add_action (&data->type_instance, child, /* may be empty = */ 1); + else if (strcasecmp ("MetaData", child->key) == 0) + status = tr_config_add_meta_action (&data->meta, child, + /* should delete = */ 0); + else if (strcasecmp ("DeleteMetaData", child->key) == 0) + status = tr_config_add_meta_action (&data->meta, child, + /* should delete = */ 1); else { ERROR ("Target `replace': The `%s' configuration option is not understood " @@ -295,7 +542,8 @@ static int tr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ && (data->plugin == NULL) && (data->plugin_instance == NULL) /* && (data->type == NULL) */ - && (data->type_instance == NULL)) + && (data->type_instance == NULL) + && (data->meta == NULL)) { ERROR ("Target `replace': You need to set at least one of `Host', " "`Plugin', `PluginInstance' or `TypeInstance'."); @@ -330,13 +578,18 @@ static int tr_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */ return (-EINVAL); } + if (data->meta != NULL) + { + tr_meta_data_action_invoke (data->meta, &(vl->meta)); + } + #define HANDLE_FIELD(f,e) \ if (data->f != NULL) \ tr_action_invoke (data->f, vl->f, sizeof (vl->f), e) HANDLE_FIELD (host, 0); HANDLE_FIELD (plugin, 0); HANDLE_FIELD (plugin_instance, 1); - /* HANDLE_FIELD (type); */ + /* HANDLE_FIELD (type, 0); */ HANDLE_FIELD (type_instance, 1); return (FC_TARGET_CONTINUE); diff --git a/src/target_set.c b/src/target_set.c index 4f00cbbd..3de86e48 100644 --- a/src/target_set.c +++ b/src/target_set.c @@ -28,6 +28,28 @@ #include "common.h" #include "filter_chain.h" +#include "meta_data.h" +#include "utils_subst.h" + +struct ts_key_list_s +{ + char *key; + struct ts_key_list_s *next; +}; +typedef struct ts_key_list_s ts_key_list_t; + +static void ts_key_list_free (ts_key_list_t *l) /* {{{ */ +{ + if (l == NULL) + return; + + sfree (l->key); + + if (l->next != NULL) + ts_key_list_free (l->next); + + sfree (l); +} /* }}} void ts_name_list_free */ struct ts_data_s { @@ -37,6 +59,7 @@ struct ts_data_s /* char *type; */ char *type_instance; meta_data_t *meta; + ts_key_list_t *meta_delete; }; typedef struct ts_data_s ts_data_t; @@ -47,7 +70,7 @@ static int ts_util_get_key_and_string_wo_strdup (const oconfig_item_t *ci, char || (ci->values[1].type != OCONFIG_TYPE_STRING)) { ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires " - "exactly two string argument.", ci->key); + "exactly two string arguments.", ci->key); return (-1); } @@ -92,31 +115,105 @@ static int ts_config_add_meta (meta_data_t **dest, /* {{{ */ if (strlen (key) == 0) { - ERROR ("Target `set': The `%s' option does not accept empty string as first argument.", - ci->key); + ERROR ("Target `set': The `%s' option does not accept empty string as " + "first argument.", ci->key); return (-1); } if (!may_be_empty && (strlen (string) == 0)) { - ERROR ("Target `set': The `%s' option does not accept empty string as second argument.", - ci->key); + ERROR ("Target `set': The `%s' option does not accept empty string as " + "second argument.", ci->key); return (-1); } if ((*dest) == NULL) { - // Create a new meta_data_t + /* Create a new meta_data_t */ if ((*dest = meta_data_create()) == NULL) { ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key); - return (-1); + return (-ENOMEM); } } return (meta_data_add_string (*dest, key, string)); } /* }}} int ts_config_add_meta */ +static int ts_config_add_meta_delete (ts_key_list_t **dest, /* {{{ */ + const oconfig_item_t *ci) +{ + ts_key_list_t *entry = NULL; + + entry = calloc (1, sizeof (*entry)); + if (entry == NULL) + { + ERROR ("ts_config_add_meta_delete: calloc failed."); + return (-ENOMEM); + } + + if (cf_util_get_string (ci, &entry->key) != 0) + { + ts_key_list_free (entry); + return (-1); /* An error has already been reported. */ + } + + if (strlen (entry->key) == 0) + { + ERROR ("Target `set': The `%s' option does not accept empty string as " + "first argument.", ci->key); + ts_key_list_free (entry); + return (-1); + } + + entry->next = *dest; + *dest = entry; + + return (0); +} /* }}} int ts_config_add_meta_delete */ + +static void ts_subst (char *dest, size_t size, const char *string, /* {{{ */ + const value_list_t *vl) +{ + char temp[DATA_MAX_NAME_LEN]; + + /* Initialize the field with the template. */ + sstrncpy (dest, string, size); + + if (strchr (dest, '%') == NULL) + return; + +#define REPLACE_FIELD(t, v) \ + if (subst_string (temp, sizeof (temp), dest, t, v) != NULL) \ + sstrncpy (dest, temp, size); + REPLACE_FIELD ("%{host}", vl->host); + REPLACE_FIELD ("%{plugin}", vl->plugin); + REPLACE_FIELD ("%{plugin_instance}", vl->plugin_instance); + REPLACE_FIELD ("%{type}", vl->type); + REPLACE_FIELD ("%{type_instance}", vl->type_instance); + + if (vl->meta != NULL) + { + char **meta_toc; + int meta_entries = meta_data_toc (vl->meta, &meta_toc); + for (int i = 0; i < meta_entries; i++) + { + char meta_name[DATA_MAX_NAME_LEN]; + char *value_str; + const char *key = meta_toc[i]; + + ssnprintf (meta_name, sizeof (meta_name), "%%{meta:%s}", key); + if (meta_data_as_string (vl->meta, key, &value_str) != 0) + continue; + + REPLACE_FIELD (meta_name, value_str); + sfree (value_str); + } + + strarray_free (meta_toc, (size_t) meta_entries); + } +} /* }}} int ts_subst */ + static int ts_destroy (void **user_data) /* {{{ */ { ts_data_t *data; @@ -134,6 +231,7 @@ static int ts_destroy (void **user_data) /* {{{ */ /* free (data->type); */ free (data->type_instance); meta_data_destroy(data->meta); + ts_key_list_free (data->meta_delete); free (data); return (0); @@ -157,6 +255,7 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ /* data->type = NULL; */ data->type_instance = NULL; data->meta = NULL; + data->meta_delete = NULL; status = 0; for (int i = 0; i < ci->children_num; i++) @@ -184,6 +283,8 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ else if (strcasecmp ("MetaData", child->key) == 0) status = ts_config_add_meta (&data->meta, child, /* may be empty = */ 1); + else if (strcasecmp ("DeleteMetaData", child->key) == 0) + status = ts_config_add_meta_delete (&data->meta_delete, child); else { ERROR ("Target `set': The `%s' configuration option is not understood " @@ -203,13 +304,30 @@ static int ts_create (const oconfig_item_t *ci, void **user_data) /* {{{ */ && (data->plugin_instance == NULL) /* && (data->type == NULL) */ && (data->type_instance == NULL) - && (data->meta == NULL)) + && (data->meta == NULL) + && (data->meta_delete == NULL)) { ERROR ("Target `set': You need to set at least one of `Host', " - "`Plugin', `PluginInstance', `TypeInstance', `MetaData'."); + "`Plugin', `PluginInstance', `TypeInstance', " + "`MetaData', or `DeleteMetaData'."); status = -1; } + if (data->meta != NULL) + { + /* If data->meta_delete is NULL, this loop is a no-op. */ + for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next) + { + if (meta_data_type (data->meta, l->key) != 0) + { + /* MetaData and DeleteMetaData for the same key. */ + ERROR ("Target `set': Can only have one of `MetaData' or " + "`DeleteMetaData' for any given key."); + status = -1; + } + } + } + break; } @@ -227,6 +345,8 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */ notification_meta_t __attribute__((unused)) **meta, void **user_data) { ts_data_t *data; + value_list_t orig; + meta_data_t *new_meta = NULL; if ((ds == NULL) || (vl == NULL) || (user_data == NULL)) return (-EINVAL); @@ -238,17 +358,79 @@ static int ts_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */ return (-EINVAL); } + orig = *vl; + if (data->meta != NULL) { - meta_data_clone_merge(&(vl->meta), data->meta); + char temp[DATA_MAX_NAME_LEN*2]; + int meta_entries; + char **meta_toc; + + if ((new_meta = meta_data_create()) == NULL) + { + ERROR ("Target `set': failed to create replacement metadata."); + return (-ENOMEM); + } + + meta_entries = meta_data_toc (data->meta, &meta_toc); + for (int i = 0; i < meta_entries; i++) + { + const char *key = meta_toc[i]; + char *string; + int status; + + status = meta_data_get_string (data->meta, key, &string); + if (status) + { + ERROR ("Target `set': Unable to get replacement metadata value `%s'.", + key); + strarray_free (meta_toc, (size_t) meta_entries); + return (status); + } + + ts_subst (temp, sizeof (temp), string, &orig); + + DEBUG ("target_set: ts_invoke: setting metadata value for key `%s': " + "`%s'.", key, temp); + + status = meta_data_add_string (new_meta, key, temp); + + if (status) + { + ERROR ("Target `set': Unable to set metadata value `%s'.", key); + strarray_free (meta_toc, (size_t) meta_entries); + return (status); + } + } + + strarray_free (meta_toc, (size_t) meta_entries); + } + +#define SUBST_FIELD(f) \ + if (data->f != NULL) { \ + ts_subst (vl->f, sizeof (vl->f), data->f, &orig); \ + DEBUG ("target_set: ts_invoke: setting "#f": `%s'.", vl->f); \ + } + SUBST_FIELD (host); + SUBST_FIELD (plugin); + SUBST_FIELD (plugin_instance); + /* SUBST_FIELD (type); */ + SUBST_FIELD (type_instance); + + /* Need to merge the metadata in now, because of the shallow copy. */ + if (new_meta != NULL) + { + meta_data_clone_merge(&(vl->meta), new_meta); + meta_data_destroy(new_meta); } -#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); } - SET_FIELD (host); - SET_FIELD (plugin); - SET_FIELD (plugin_instance); - /* SET_FIELD (type); */ - SET_FIELD (type_instance); + /* If data->meta_delete is NULL, this loop is a no-op. */ + for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next) + { + DEBUG ("target_set: ts_invoke: deleting metadata value for key `%s'.", + l->key); + meta_data_delete(vl->meta, l->key); + } return (FC_TARGET_CONTINUE); } /* }}} int ts_invoke */ diff --git a/src/target_v5upgrade.c b/src/target_v5upgrade.c index f7baa3ae..3f2c9583 100644 --- a/src/target_v5upgrade.c +++ b/src/target_v5upgrade.c @@ -53,7 +53,6 @@ static void v5_swap_instances (value_list_t *vl) /* {{{ */ static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; /* Can't upgrade if both instances have been set. */ if ((vl->plugin_instance[0] != 0) @@ -64,7 +63,7 @@ static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -113,7 +112,6 @@ static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; if (vl->values_len != 5) return (FC_TARGET_STOP); @@ -122,7 +120,7 @@ static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -171,7 +169,6 @@ static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; if (vl->values_len != 4) return (FC_TARGET_STOP); @@ -180,7 +177,7 @@ static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -224,7 +221,6 @@ static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; _Bool is_hits; if (vl->values_len != 4) @@ -241,7 +237,7 @@ static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -285,7 +281,6 @@ static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_values[2]; if (vl->values_len != 2) return (FC_TARGET_STOP); @@ -294,8 +289,6 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ * memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = new_values; - new_vl.values_len = 2; new_vl.meta = NULL; /* Change the type/-instance to "io_octets-L2" */ @@ -303,8 +296,12 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ * sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance)); /* Copy the actual values. */ - new_vl.values[0].derive = (derive_t) vl->values[0].counter; - new_vl.values[1].derive = (derive_t) vl->values[1].counter; + value_t values[] = { + { .derive = (derive_t) vl->values[0].counter }, + { .derive = (derive_t) vl->values[1].counter }, + }; + new_vl.values = values; + new_vl.values_len = STATIC_ARRAY_SIZE (values); /* Dispatch new value lists instead of this one */ plugin_dispatch_values (&new_vl); @@ -322,7 +319,6 @@ static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ * static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; if (vl->values_len != 1) return (FC_TARGET_STOP); @@ -331,7 +327,7 @@ static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -359,7 +355,6 @@ static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; if (vl->values_len != 1) return (FC_TARGET_STOP); @@ -368,7 +363,7 @@ static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; @@ -397,7 +392,6 @@ static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */ static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */ { value_list_t new_vl; - value_t new_value; if (vl->values_len != 4) return (FC_TARGET_STOP); @@ -406,7 +400,7 @@ static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */ memcpy (&new_vl, vl, sizeof (new_vl)); /* Reset data we can't simply copy */ - new_vl.values = &new_value; + new_vl.values = &(value_t) { .gauge = NAN }; new_vl.values_len = 1; new_vl.meta = NULL; diff --git a/src/teamspeak2.c b/src/teamspeak2.c index a1cde320..a709e79d 100644 --- a/src/teamspeak2.c +++ b/src/teamspeak2.c @@ -121,12 +121,9 @@ static void tss2_submit_gauge (const char *plugin_instance, /* * Submits a gauge value to the collectd daemon */ - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin)); @@ -150,14 +147,14 @@ static void tss2_submit_io (const char *plugin_instance, const char *type, /* * Submits the io rx/tx tuple to the collectd daemon */ - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; - vl.values_len = 2; + vl.values_len = STATIC_ARRAY_SIZE (values); sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "teamspeak2", sizeof (vl.plugin)); diff --git a/src/ted.c b/src/ted.c index 5ed6c278..f167546b 100644 --- a/src/ted.c +++ b/src/ted.c @@ -263,12 +263,9 @@ static int ted_open_device (void) static void ted_submit (const char *type, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "ted", sizeof (vl.plugin)); diff --git a/src/thermal.c b/src/thermal.c index e001a62a..aa95dac3 100644 --- a/src/thermal.c +++ b/src/thermal.c @@ -47,14 +47,11 @@ enum dev_type { }; static void thermal_submit (const char *plugin_instance, enum dev_type dt, - gauge_t value) + value_t value) { value_list_t vl = VALUE_LIST_INIT; - value_t v; - - v.gauge = value; - vl.values = &v; + vl.values = &value; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -72,52 +69,26 @@ static void thermal_submit (const char *plugin_instance, enum dev_type dt, static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir, const char *name, void __attribute__((unused)) *user_data) { - char filename[256]; - char data[1024]; - int len; + char filename[PATH_MAX]; _Bool success = 0; + value_t value; if (device_list && ignorelist_match (device_list, name)) return -1; - len = ssnprintf (filename, sizeof (filename), - "%s/%s/temp", dirname_sysfs, name); - if ((len < 0) || ((size_t) len >= sizeof (filename))) - return -1; - - len = (ssize_t) read_file_contents (filename, data, sizeof(data)); - if (len > 1 && data[--len] == '\n') { - char *endptr = NULL; - double temp; - - data[len] = 0; - errno = 0; - temp = strtod (data, &endptr) / 1000.0; - - if (endptr == data + len && errno == 0) { - thermal_submit(name, TEMP, temp); - success = 1; - } + ssnprintf (filename, sizeof (filename), "%s/%s/temp", dirname_sysfs, name); + if (parse_value_file (filename, &value, DS_TYPE_GAUGE) == 0) + { + value.gauge /= 1000.0; + thermal_submit(name, TEMP, value); + success = 1; } - len = ssnprintf (filename, sizeof (filename), - "%s/%s/cur_state", dirname_sysfs, name); - if ((len < 0) || ((size_t) len >= sizeof (filename))) - return -1; - - len = (ssize_t) read_file_contents (filename, data, sizeof(data)); - if (len > 1 && data[--len] == '\n') { - char *endptr = NULL; - double state; - - data[len] = 0; - errno = 0; - state = strtod (data, &endptr); - - if (endptr == data + len && errno == 0) { - thermal_submit(name, COOLING_DEV, state); - success = 1; - } + ssnprintf (filename, sizeof (filename), "%s/%s/cur_state", dirname_sysfs, name); + if (parse_value_file (filename, &value, DS_TYPE_GAUGE) == 0) + { + thermal_submit(name, COOLING_DEV, value); + success = 1; } return (success ? 0 : -1); @@ -176,7 +147,7 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir, temp = (strtod (data + len, &endptr) + add) * factor; if (endptr != data + len && errno == 0) { - thermal_submit(name, TEMP, temp); + thermal_submit(name, TEMP, (value_t) { .gauge = temp }); return 0; } } diff --git a/src/tokyotyrant.c b/src/tokyotyrant.c index 7c6d9129..154215f8 100644 --- a/src/tokyotyrant.c +++ b/src/tokyotyrant.c @@ -86,15 +86,12 @@ static void printerr (void) ecode, tcrdberrmsg(ecode)); } -static void tt_submit (gauge_t val, const char* type) +static void tt_submit (gauge_t value, const char* type) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = val; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; sstrncpy (vl.host, config_host, sizeof (vl.host)); sstrncpy (vl.plugin, "tokyotyrant", sizeof (vl.plugin)); diff --git a/src/turbostat.c b/src/turbostat.c index 2d8a08e6..e74cba28 100644 --- a/src/turbostat.c +++ b/src/turbostat.c @@ -524,10 +524,8 @@ turbostat_submit (const char *plugin_instance, gauge_t value) { value_list_t vl = VALUE_LIST_INIT; - value_t v; - v.gauge = value; - vl.values = &v; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, PLUGIN_NAME, sizeof (vl.plugin)); @@ -1018,8 +1016,7 @@ parse_int_file(const char *fmt, ...) { va_list args; char path[PATH_MAX]; - FILE *filep; - int len, value; + int len; va_start(args, fmt); len = vsnprintf(path, sizeof(path), fmt, args); @@ -1029,18 +1026,13 @@ parse_int_file(const char *fmt, ...) return -1; } - filep = fopen(path, "r"); - if (!filep) { - ERROR("turbostat plugin: Failed to open '%s'", path); - return -1; - } - if (fscanf(filep, "%d", &value) != 1) { - ERROR("turbostat plugin: Failed to parse number from '%s'", path); - fclose(filep); + value_t v; + if (parse_value_file (path, &v, DS_TYPE_DERIVE) != 0) { + ERROR ("turbostat plugin: Parsing \"%s\" failed.", path); return -1; } - fclose(filep); - return value; + + return (int) v.derive; } static int diff --git a/src/types.db b/src/types.db index 6ec78128..4f8d31c7 100644 --- a/src/types.db +++ b/src/types.db @@ -94,7 +94,6 @@ hash_collisions value:DERIVE:0:U http_request_methods value:DERIVE:0:U http_requests value:DERIVE:0:U http_response_codes value:DERIVE:0:U -hugepages free:GAUGE:0:4294967295, used:GAUGE:0:4294967295 humidity value:GAUGE:0:100 if_collisions value:DERIVE:0:U if_dropped rx:DERIVE:0:U, tx:DERIVE:0:U diff --git a/src/uptime.c b/src/uptime.c index cbe2f8c5..34c3e85a 100644 --- a/src/uptime.c +++ b/src/uptime.c @@ -58,14 +58,11 @@ static time_t boottime; extern kstat_ctl_t *kc; #endif /* #endif HAVE_LIBKSTAT */ -static void uptime_submit (gauge_t uptime) +static void uptime_submit (gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = uptime; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); diff --git a/src/users.c b/src/users.c index 30e0dbe6..ce626ae3 100644 --- a/src/users.c +++ b/src/users.c @@ -45,12 +45,9 @@ static void users_submit (gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "users", sizeof (vl.plugin)); diff --git a/src/utils_format_graphite.c b/src/utils_format_graphite.c index e5234204..0af586ff 100644 --- a/src/utils_format_graphite.c +++ b/src/utils_format_graphite.c @@ -150,18 +150,29 @@ static int gr_format_name (char *ret, int ret_len, sstrncpy (tmp_plugin, n_plugin, sizeof (tmp_plugin)); if (n_type_instance[0] != '\0') - ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s", - n_type, - (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-', - n_type_instance); + { + if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0) + sstrncpy (tmp_type, n_type_instance, sizeof (tmp_type)); + else + ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s", + n_type, + (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-', + n_type_instance); + } else sstrncpy (tmp_type, n_type, sizeof (tmp_type)); /* Assert always_append_ds -> ds_name */ assert (!(flags & GRAPHITE_ALWAYS_APPEND_DS) || (ds_name != NULL)); if (ds_name != NULL) - ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s", - prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name); + { + if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(tmp_plugin, tmp_type) == 0) + ssnprintf (ret, ret_len, "%s%s%s.%s.%s", + prefix, n_host, postfix, tmp_plugin, ds_name); + else + ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s", + prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name); + } else ssnprintf (ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix, tmp_plugin, tmp_type); diff --git a/src/utils_format_graphite.h b/src/utils_format_graphite.h index 60576dac..5165f9e6 100644 --- a/src/utils_format_graphite.h +++ b/src/utils_format_graphite.h @@ -29,6 +29,7 @@ #define GRAPHITE_STORE_RATES 0x01 #define GRAPHITE_SEPARATE_INSTANCES 0x02 #define GRAPHITE_ALWAYS_APPEND_DS 0x04 +#define GRAPHITE_DROP_DUPE_FIELDS 0x08 int format_graphite (char *buffer, size_t buffer_size, const data_set_t *ds, diff --git a/src/varnish.c b/src/varnish.c index 6cc092c0..18f5902f 100644 --- a/src/varnish.c +++ b/src/varnish.c @@ -117,22 +117,16 @@ static int varnish_submit_gauge (const char *plugin_instance, /* {{{ */ const char *category, const char *type, const char *type_instance, uint64_t gauge_value) { - value_t value; - - value.gauge = (gauge_t) gauge_value; - - return (varnish_submit (plugin_instance, category, type, type_instance, value)); + return (varnish_submit (plugin_instance, category, type, type_instance, + (value_t) { .gauge = (gauge_t) gauge_value })); } /* }}} int varnish_submit_gauge */ static int varnish_submit_derive (const char *plugin_instance, /* {{{ */ const char *category, const char *type, const char *type_instance, uint64_t derive_value) { - value_t value; - - value.derive = (derive_t) derive_value; - - return (varnish_submit (plugin_instance, category, type, type_instance, value)); + return (varnish_submit (plugin_instance, category, type, type_instance, + (value_t) { .derive = (derive_t) derive_value })); } /* }}} int varnish_submit_derive */ #if HAVE_VARNISH_V3 || HAVE_VARNISH_V4 @@ -951,16 +945,14 @@ static int varnish_init (void) /* {{{ */ varnish_config_apply_default (conf); - user_data_t ud = { - .data = conf, - .free_func = varnish_config_free - }; - plugin_register_complex_read (/* group = */ "varnish", /* name = */ "varnish/localhost", /* callback = */ varnish_read, /* interval = */ 0, - /* user data = */ &ud); + &(user_data_t) { + .data = conf, + .free_func = varnish_config_free, + }); return (0); } /* }}} int varnish_init */ @@ -968,7 +960,6 @@ static int varnish_init (void) /* {{{ */ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */ { user_config_t *conf; - user_data_t ud; char callback_name[DATA_MAX_NAME_LEN]; conf = calloc (1, sizeof (*conf)); @@ -1132,14 +1123,14 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */ ssnprintf (callback_name, sizeof (callback_name), "varnish/%s", (conf->instance == NULL) ? "localhost" : conf->instance); - ud.data = conf; - ud.free_func = varnish_config_free; - plugin_register_complex_read (/* group = */ "varnish", /* name = */ callback_name, /* callback = */ varnish_read, /* interval = */ 0, - /* user data = */ &ud); + &(user_data_t) { + .data = conf, + .free_func = varnish_config_free, + }); have_instance = 1; diff --git a/src/virt.c b/src/virt.c index c1c77bcf..99fe42db 100644 --- a/src/virt.c +++ b/src/virt.c @@ -223,103 +223,71 @@ init_value_list (value_list_t *vl, virDomainPtr dom) } /* void init_value_list */ -static void -memory_submit (gauge_t memory, virDomainPtr dom) +static void submit (virDomainPtr dom, + char const *type, char const *type_instance, + value_t *values, size_t values_len) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - init_value_list (&vl, dom); - values[0].gauge = memory; - vl.values = values; - vl.values_len = 1; + vl.values_len = values_len; - sstrncpy (vl.type, "memory", sizeof (vl.type)); - sstrncpy (vl.type_instance, "total", sizeof (vl.type_instance)); + sstrncpy (vl.type, type, sizeof (vl.type)); + if (type_instance != NULL) + sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance)); plugin_dispatch_values (&vl); } static void -memory_stats_submit (gauge_t memory, virDomainPtr dom, int tag_index) +memory_submit (gauge_t value, virDomainPtr dom) +{ + submit (dom, "memory", "total", &(value_t) { .gauge = value }, 1); +} + +static void +memory_stats_submit (gauge_t value, virDomainPtr dom, int tag_index) { static const char *tags[] = { "swap_in", "swap_out", "major_fault", "minor_fault", "unused", "available", "actual_balloon", "rss"}; - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, dom); - - values[0].gauge = memory; - - vl.values = values; - vl.values_len = 1; - - sstrncpy (vl.type, "memory", sizeof (vl.type)); - sstrncpy (vl.type_instance, tags[tag_index], sizeof (vl.type_instance)); + if ((tag_index < 0) || (tag_index >= STATIC_ARRAY_SIZE (tags))) { + ERROR ("virt plugin: Array index out of bounds: tag_index = %d", tag_index); + return; + } - plugin_dispatch_values (&vl); + submit (dom, "memory", tags[tag_index], &(value_t) { .gauge = value }, 1); } static void -cpu_submit (unsigned long long cpu_time, +cpu_submit (unsigned long long value, virDomainPtr dom, const char *type) { - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, dom); - - values[0].derive = cpu_time; - - vl.values = values; - vl.values_len = 1; - - sstrncpy (vl.type, type, sizeof (vl.type)); - - plugin_dispatch_values (&vl); + submit (dom, type, NULL, &(value_t) { .derive = (derive_t) value }, 1); } static void -vcpu_submit (derive_t cpu_time, +vcpu_submit (derive_t value, virDomainPtr dom, int vcpu_nr, const char *type) { - value_t values[1]; - value_list_t vl = VALUE_LIST_INIT; + char type_instance[DATA_MAX_NAME_LEN]; - init_value_list (&vl, dom); + ssnprintf (type_instance, sizeof (type_instance), "%d", vcpu_nr); - values[0].derive = cpu_time; - vl.values = values; - vl.values_len = 1; - - sstrncpy (vl.type, type, sizeof (vl.type)); - ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%d", vcpu_nr); - - plugin_dispatch_values (&vl); + submit (dom, type, type_instance, &(value_t) { .derive = value }, 1); } static void submit_derive2 (const char *type, derive_t v0, derive_t v1, virDomainPtr dom, const char *devname) { - value_t values[2]; - value_list_t vl = VALUE_LIST_INIT; - - init_value_list (&vl, dom); + value_t values[] = { + { .derive = v0 }, + { .derive = v1 }, + }; - values[0].derive = v0; - values[1].derive = v1; - vl.values = values; - vl.values_len = 2; - - sstrncpy (vl.type, type, sizeof (vl.type)); - sstrncpy (vl.type_instance, devname, sizeof (vl.type_instance)); - - plugin_dispatch_values (&vl); + submit (dom, type, devname, values, STATIC_ARRAY_SIZE (values)); } /* void submit_derive2 */ static int diff --git a/src/vmem.c b/src/vmem.c index 46ffa13b..027f7bdd 100644 --- a/src/vmem.c +++ b/src/vmem.c @@ -65,12 +65,13 @@ static void submit (const char *plugin_instance, const char *type, static void submit_two (const char *plugin_instance, const char *type, const char *type_instance, derive_t c0, derive_t c1) { - value_t values[2]; + value_t values[] = { + { .derive = c0 }, + { .derive = c1 }, + }; - values[0].derive = c0; - values[1].derive = c1; - - submit (plugin_instance, type, type_instance, values, 2); + submit (plugin_instance, type, type_instance, + values, STATIC_ARRAY_SIZE (values)); } /* void submit_one */ static void submit_one (const char *plugin_instance, const char *type, diff --git a/src/vserver.c b/src/vserver.c index a7305936..f3a2b5a4 100644 --- a/src/vserver.c +++ b/src/vserver.c @@ -56,11 +56,11 @@ static int vserver_init (void) static void traffic_submit (const char *plugin_instance, const char *type_instance, derive_t rx, derive_t tx) { - value_t values[2]; value_list_t vl = VALUE_LIST_INIT; - - values[0].derive = rx; - values[1].derive = tx; + value_t values[] = { + { .derive = rx }, + { .derive = tx }, + }; vl.values = values; vl.values_len = STATIC_ARRAY_SIZE (values); @@ -76,12 +76,12 @@ static void traffic_submit (const char *plugin_instance, static void load_submit (const char *plugin_instance, gauge_t snum, gauge_t mnum, gauge_t lnum) { - value_t values[3]; value_list_t vl = VALUE_LIST_INIT; - - values[0].gauge = snum; - values[1].gauge = mnum; - values[2].gauge = lnum; + value_t values[] = { + { .gauge = snum }, + { .gauge = mnum }, + { .gauge = lnum }, + }; vl.values = values; vl.values_len = STATIC_ARRAY_SIZE (values); @@ -97,13 +97,10 @@ static void submit_gauge (const char *plugin_instance, const char *type, const char *type_instance, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; - vl.values_len = STATIC_ARRAY_SIZE (values); + vl.values = &(value_t) { .gauge = value }; + vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "vserver", sizeof (vl.plugin)); sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance)); diff --git a/src/wireless.c b/src/wireless.c index b9984625..7d57fea9 100644 --- a/src/wireless.c +++ b/src/wireless.c @@ -54,12 +54,9 @@ static double wireless_dbm_to_watt (double dbm) static void wireless_submit (const char *plugin_instance, const char *type, double value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "wireless", sizeof (vl.plugin)); diff --git a/src/write_graphite.c b/src/write_graphite.c index fe2376ad..ebc5ce20 100644 --- a/src/write_graphite.c +++ b/src/write_graphite.c @@ -548,6 +548,9 @@ static int wg_config_node (oconfig_item_t *ci) else if (strcasecmp ("AlwaysAppendDS", child->key) == 0) cf_util_get_flag (child, &cb->format_flags, GRAPHITE_ALWAYS_APPEND_DS); + else if (strcasecmp ("DropDuplicateFields", child->key) == 0) + cf_util_get_flag (child, &cb->format_flags, + GRAPHITE_DROP_DUPE_FIELDS); else if (strcasecmp ("EscapeCharacter", child->key) == 0) config_set_char (&cb->escape_char, child); else @@ -575,15 +578,13 @@ static int wg_config_node (oconfig_item_t *ci) ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s", cb->name); - user_data_t ud = { - .data = cb, - .free_func = wg_callback_free - }; - - plugin_register_write (callback_name, wg_write, &ud); + plugin_register_write (callback_name, wg_write, + &(user_data_t) { + .data = cb, + .free_func = wg_callback_free, + }); - ud.free_func = NULL; - plugin_register_flush (callback_name, wg_flush, &ud); + plugin_register_flush (callback_name, wg_flush, &(user_data_t) { .data = cb }); return (0); } diff --git a/src/write_kafka.c b/src/write_kafka.c index 9fda2dfc..75da6aaa 100644 --- a/src/write_kafka.c +++ b/src/write_kafka.c @@ -383,12 +383,11 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{ ssnprintf(callback_name, sizeof(callback_name), "write_kafka/%s", tctx->topic_name); - user_data_t ud = { - .data = tctx, - .free_func = kafka_topic_context_free - }; - - status = plugin_register_write (callback_name, kafka_write, &ud); + status = plugin_register_write (callback_name, kafka_write, + &(user_data_t) { + .data = tctx, + .free_func = kafka_topic_context_free, + }); if (status != 0) { WARNING ("write_kafka plugin: plugin_register_write (\"%s\") " "failed with status %i.", diff --git a/src/write_log.c b/src/write_log.c index b0dc6f11..e10a912e 100644 --- a/src/write_log.c +++ b/src/write_log.c @@ -31,20 +31,26 @@ #include "plugin.h" #include "utils_format_graphite.h" +#include "utils_format_json.h" #include -#define WL_BUF_SIZE 8192 +#define WL_BUF_SIZE 16384 -static int wl_write_messages (const data_set_t *ds, const value_list_t *vl) +#define WL_FORMAT_GRAPHITE 1 +#define WL_FORMAT_JSON 2 + +/* Plugin:WriteLog has to also operate without a config, so use a global. */ +int wl_format = WL_FORMAT_GRAPHITE; + +static int wl_write_graphite (const data_set_t *ds, const value_list_t *vl) { char buffer[WL_BUF_SIZE] = { 0 }; int status; if (0 != strcmp (ds->type, vl->type)) { - ERROR ("write_log plugin: DS type does not match " - "value list type"); + ERROR ("write_log plugin: DS type does not match value list type"); return -1; } @@ -56,20 +62,95 @@ static int wl_write_messages (const data_set_t *ds, const value_list_t *vl) INFO ("write_log values:\n%s", buffer); return (0); -} /* int wl_write_messages */ +} /* int wl_write_graphite */ + +static int wl_write_json (const data_set_t *ds, const value_list_t *vl) +{ + char buffer[WL_BUF_SIZE] = { 0 }; + size_t bfree = sizeof(buffer); + size_t bfill = 0; + + if (0 != strcmp (ds->type, vl->type)) + { + ERROR ("write_log plugin: DS type does not match value list type"); + return -1; + } + + format_json_initialize(buffer, &bfill, &bfree); + format_json_value_list(buffer, &bfill, &bfree, ds, vl, + /* store rates = */ 0); + format_json_finalize(buffer, &bfill, &bfree); + + INFO ("write_log values:\n%s", buffer); + + return (0); +} /* int wl_write_json */ static int wl_write (const data_set_t *ds, const value_list_t *vl, __attribute__ ((unused)) user_data_t *user_data) { - int status; + int status = 0; - status = wl_write_messages (ds, vl); + if (wl_format == WL_FORMAT_GRAPHITE) + { + status = wl_write_graphite (ds, vl); + } + else if (wl_format == WL_FORMAT_JSON) + { + status = wl_write_json (ds, vl); + } return (status); } +static int wl_config (oconfig_item_t *ci) /* {{{ */ +{ + _Bool format_seen = 0; + + for (int i = 0; i < ci->children_num; i++) + { + oconfig_item_t *child = ci->children + i; + + if (strcasecmp ("Format", child->key) == 0) + { + char str[16]; + + if (cf_util_get_string_buffer (child, str, sizeof (str)) != 0) + continue; + + if (format_seen) + { + WARNING ("write_log plugin: Redefining option `%s'.", + child->key); + } + format_seen = 1; + + if (strcasecmp ("Graphite", str) == 0) + wl_format = WL_FORMAT_GRAPHITE; + else if (strcasecmp ("JSON", str) == 0) + wl_format = WL_FORMAT_JSON; + else + { + ERROR ("write_log plugin: Unknown format `%s' for option `%s'.", + str, child->key); + return (-EINVAL); + } + } + else + { + ERROR ("write_log plugin: Invalid configuration option: `%s'.", + child->key); + return (-EINVAL); + } + } + + return (0); +} /* }}} int wl_config */ + void module_register (void) { + plugin_register_complex_config ("write_log", wl_config); + /* If config is supplied, the global wl_format will be set. */ plugin_register_write ("write_log", wl_write, NULL); } diff --git a/src/write_mongodb.c b/src/write_mongodb.c index 6d5f3794..796574e7 100644 --- a/src/write_mongodb.c +++ b/src/write_mongodb.c @@ -339,12 +339,11 @@ static int wm_config_node (oconfig_item_t *ci) /* {{{ */ ssnprintf (cb_name, sizeof (cb_name), "write_mongodb/%s", node->name); - user_data_t ud = { - .data = node, - .free_func = wm_config_free - }; - - status = plugin_register_write (cb_name, wm_write, &ud); + status = plugin_register_write (cb_name, wm_write, + &(user_data_t) { + .data = node, + .free_func = wm_config_free, + }); INFO ("write_mongodb plugin: registered write plugin %s %d",cb_name,status); } diff --git a/src/write_redis.c b/src/write_redis.c index 47224162..def3d9cd 100644 --- a/src/write_redis.c +++ b/src/write_redis.c @@ -234,12 +234,11 @@ static int wr_config_node (oconfig_item_t *ci) /* {{{ */ ssnprintf (cb_name, sizeof (cb_name), "write_redis/%s", node->name); - user_data_t ud = { - .data = node, - .free_func = wr_config_free - }; - - status = plugin_register_write (cb_name, wr_write, &ud); + status = plugin_register_write (cb_name, wr_write, + &(user_data_t) { + .data = node, + .free_func = wr_config_free, + }); } if (status != 0) diff --git a/src/xencpu.c b/src/xencpu.c index f1cd9388..93575df2 100644 --- a/src/xencpu.c +++ b/src/xencpu.c @@ -108,14 +108,11 @@ static int xencpu_shutdown (void) return 0; } /* static int xencpu_shutdown */ -static void submit_value (int cpu_num, gauge_t percent) +static void submit_value (int cpu_num, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = percent; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); @@ -145,9 +142,10 @@ static int xencpu_read (void) int status; for (int cpu = 0; cpu < nr_cpus; cpu++) { gauge_t rate = NAN; - value_t value = {.derive = cpu_info[cpu].idletime}; - status = value_to_rate (&rate, value, DS_TYPE_DERIVE, now, &cpu_states[cpu]); + status = value_to_rate (&rate, + (value_t) { .derive = cpu_info[cpu].idletime }, DS_TYPE_DERIVE, + now, &cpu_states[cpu]); if (status == 0) { submit_value(cpu, 100 - rate/10000000); } diff --git a/src/xmms.c b/src/xmms.c index 35359950..2ba30827 100644 --- a/src/xmms.c +++ b/src/xmms.c @@ -35,12 +35,9 @@ static gint xmms_session; static void cxmms_submit (const char *type, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = value; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "xmms", sizeof (vl.plugin)); diff --git a/src/zfs_arc.c b/src/zfs_arc.c index 8261282a..e4110859 100644 --- a/src/zfs_arc.c +++ b/src/zfs_arc.c @@ -138,7 +138,7 @@ static long long get_zfs_value(kstat_t *dummy __attribute__((unused)), } #endif -static void za_submit (const char* type, const char* type_instance, value_t* values, int values_len) +static void za_submit (const char* type, const char* type_instance, value_t* values, size_t values_len) { value_list_t vl = VALUE_LIST_INIT; @@ -155,45 +155,34 @@ static void za_submit (const char* type, const char* type_instance, value_t* val static void za_submit_gauge (const char* type, const char* type_instance, gauge_t value) { - value_t vv; - - vv.gauge = value; - za_submit (type, type_instance, &vv, 1); + za_submit (type, type_instance, &(value_t) { .gauge = value }, 1); } static int za_read_derive (kstat_t *ksp, const char *kstat_value, const char *type, const char *type_instance) { - long long tmp; - value_t v; - - tmp = get_zfs_value (ksp, (char *)kstat_value); + long long tmp = get_zfs_value (ksp, (char *)kstat_value); if (tmp == -1LL) { WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value); return (-1); } - v.derive = (derive_t) tmp; - za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1); + za_submit (type, type_instance, &(value_t) { .derive = (derive_t) tmp }, /* values_num = */ 1); return (0); } static int za_read_gauge (kstat_t *ksp, const char *kstat_value, const char *type, const char *type_instance) { - long long tmp; - value_t v; - - tmp = get_zfs_value (ksp, (char *)kstat_value); + long long tmp = get_zfs_value (ksp, (char *)kstat_value); if (tmp == -1LL) { WARNING ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value); return (-1); } - v.gauge = (gauge_t) tmp; - za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1); + za_submit (type, type_instance, &(value_t) { .gauge = (gauge_t) tmp }, /* values_num = */ 1); return (0); } @@ -215,7 +204,6 @@ static void za_submit_ratio (const char* type_instance, gauge_t hits, gauge_t mi static int za_read (void) { gauge_t arc_hits, arc_misses, l2_hits, l2_misses; - value_t l2_io[2]; kstat_t *ksp = NULL; #if defined(KERNEL_LINUX) @@ -331,10 +319,11 @@ static int za_read (void) za_submit_ratio ("L2", l2_hits, l2_misses); /* I/O */ - l2_io[0].derive = get_zfs_value(ksp, "l2_read_bytes"); - l2_io[1].derive = get_zfs_value(ksp, "l2_write_bytes"); - - za_submit ("io_octets", "L2", l2_io, /* num values = */ 2); + value_t l2_io[] = { + { .derive = (derive_t) get_zfs_value(ksp, "l2_read_bytes") }, + { .derive = (derive_t) get_zfs_value(ksp, "l2_write_bytes") }, + }; + za_submit ("io_octets", "L2", l2_io, STATIC_ARRAY_SIZE (l2_io)); #if defined(KERNEL_LINUX) free_zfs_values (ksp); diff --git a/src/zookeeper.c b/src/zookeeper.c index 84174853..7e551918 100644 --- a/src/zookeeper.c +++ b/src/zookeeper.c @@ -66,14 +66,11 @@ static int zookeeper_config(const char *key, const char *value) return 0; } -static void zookeeper_submit_gauge (const char * type, const char * type_inst, gauge_t val) +static void zookeeper_submit_gauge (const char * type, const char * type_inst, gauge_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].gauge = val; - - vl.values = values; + vl.values = &(value_t) { .gauge = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin)); @@ -84,14 +81,11 @@ static void zookeeper_submit_gauge (const char * type, const char * type_inst, g plugin_dispatch_values (&vl); } /* zookeeper_submit_gauge */ -static void zookeeper_submit_derive (const char * type, const char * type_inst, derive_t val) +static void zookeeper_submit_derive (const char * type, const char * type_inst, derive_t value) { - value_t values[1]; value_list_t vl = VALUE_LIST_INIT; - values[0].derive = val; - - vl.values = values; + vl.values = &(value_t) { .derive = value }; vl.values_len = 1; sstrncpy (vl.host, hostname_g, sizeof (vl.host)); sstrncpy (vl.plugin, "zookeeper", sizeof (vl.plugin)); diff --git a/version-gen.sh b/version-gen.sh index 70b8c266..2ef5279f 100755 --- a/version-gen.sh +++ b/version-gen.sh @@ -1,6 +1,6 @@ #!/bin/sh -DEFAULT_VERSION="5.5.2.git" +DEFAULT_VERSION="5.6.0.git" if [ -d .git ]; then VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"