+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.
my $type = shift;
my %plugins;
- my $interval;
our $cb_name = undef;
}
if (TYPE_LOG != $type) {
- DEBUG ("Collectd::plugin_call: type = \"$type\" ("
+ DEBUG ("Collectd::plugin_call_all: type = \"$type\" ("
. $types{$type} . "), args=\""
. join(', ', map { defined($_) ? $_ : '<undef>' } @_) . "\"");
}
if (! defined $plugins[$type]) {
- ERROR ("Collectd::plugin_call: unknown type \"$type\"");
+ ERROR ("Collectd::plugin_call_all: unknown type \"$type\"");
return;
}
%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;
}
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. "
}
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.");
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};
} /* 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) */
/*
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"],
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
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);
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)
} /* 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)
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));
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));
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));
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));
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));
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 */
#include <stdio.h>
#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));
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);
}
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);
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? */
command line option or B<use lib Dir> in the source code. Please note that it
only has effect on plugins loaded after this option.
+=item B<RegisterLegacyFlush> I<true|false>
+
+The C<Perl plugin> 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<in addition> to the legacy B<"perl"> callback. This allows to call
+specific Perl flush handlers, but has the downside that flushing I<all> 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
=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<perl> as
-plugin name when doing so.
-
-=back
-
=head1 SEE ALSO
L<collectd(1)>,
#</Plugin>
#<Plugin hugepages>
-# ReportPerNodeHP "true"
-# ReportRootHP "true"
+# ReportPerNodeHP true
+# ReportRootHP true
+# ValuesPages true
+# ValuesBytes false
+# ValuesPercentage false
#</Plugin>
#<Plugin interface>
# StoreRates true
# AlwaysAppendDS false
# EscapeCharacter "_"
+# SeparateInstances false
+# DropDuplicateFields false
# </Node>
#</Plugin>
Set one or more files that contain the data-set descriptions. See
L<types.db(5)> 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<TypesDB> option is encountered
+the default behavior is disabled and if you need the default types you have to
+also explicitly load them.
+
=item B<Interval> I<Seconds>
Configures the interval in which to query the read plugins. Obviously smaller
=over 4
-=item B<ReportPerNodeHP> I<true>|I<false>
+=item B<ReportPerNodeHP> B<true>|B<false>
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<ReportRootHP> I<true>|I<false>
+=item B<ReportRootHP> B<true>|B<false>
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<ValuesPages> B<true>|B<false>
+
+Whether to report hugepages metrics in number of pages.
+Defaults to B<true>.
+
+=item B<ValuesBytes> B<false>|B<true>
+
+Whether to report hugepages metrics in bytes.
+Defaults to B<false>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Whether to report hugepages metrics as percentage.
+Defaults to B<false>.
+
=back
=head2 Plugin C<interface>
identifier. If set to B<false> (the default), this is only done when there is
more than one DS.
+=item B<DropDuplicateFields> B<false>|B<true>
+
+If set to B<true>, detect and remove duplicate components in Graphite metric
+names. For example, the metric name C<host.load.load.shortterm> will
+be shortened to C<host.load.shortterm>.
+
+=back
+
+=head2 Plugin C<write_log>
+
+The C<write_log> plugin writes metrics as INFO log messages.
+
+This plugin supports two output formats: I<Graphite> and I<JSON>.
+
+Synopsis:
+
+ <Plugin write_log>
+ Format Graphite
+ </Plugin>
+
+=over 4
+
+=item B<Format> I<Format>
+
+The output format to use. Can be one of C<Graphite> or C<JSON>.
+
=back
=head2 Plugin C<write_tsdb>
=item B<TypeInstance> I<Regex>
+=item B<MetaData> I<String> I<Regex>
+
Match values where the given regular expressions match the various fields of
the identifier of a value. If multiple regular expressions are given, B<all>
regexen must match for a value to match.
=item B<TypeInstance> I<Regex> I<Replacement>
+=item B<MetaData> I<String> I<Regex> I<Replacement>
+
+=item B<DeleteMetaData> I<String> I<Regex>
+
Match the appropriate field with the given regular expression I<Regex>. If the
regular expression matches, that part that matches is replaced with
I<Replacement>. If multiple places of the input buffer match a given regular
=item B<MetaData> I<String> I<String>
-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:>I<name>B<}>
+
+These placeholders are replaced by the meta data value with the given name.
+
+=back
+
+Please note that these placeholders are B<case sensitive>!
+
+=item B<DeleteMetaData> I<String>
+
+Delete the named meta data field.
=back
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 */
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));
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));
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
} /* }}} 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));
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);
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "cpufreq"
-
static int num_cpu = 0;
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);
#include <time.h>
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));
} /* }}} 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));
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));
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));
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) */
{
const data_set_t *ds;
+ if ((key == NULL) || !CJ_IS_KEY (key))
+ return -EINVAL;
+
ds = plugin_get_ds (key->type);
if (ds == NULL)
{
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);
}
}
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
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
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)
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)
* 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'.
* 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);
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);
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);
}
#include "collectd.h"
+#include "common.h"
#include "plugin.h"
#include "meta_data.h"
+#define MD_MAX_NONSTRING_CHARS 128
+
/*
* Data types
*/
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 : */
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 : */
}
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);
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);
}
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);
}
}
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));
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,
#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));
#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));
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 ());
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));
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));
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));
#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));
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);
}
{
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;
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));
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
plugin_dispatch_values(&vl);
}
-
static int fhcount_read(void) {
int numfields = 0;
int buffer_len = 60;
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));
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);
*/
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));
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));
*
* 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,
* Authors:
* Jaroslav Safka <jaroslavx.safka@intel.com>
* Kim-Marie Jones <kim-marie.jones@intel.com>
+ * Florian Forster <octo at collectd.org>
*/
#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);
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 "<size>kB"
- * The string passed as param 3 to submit_hp is of the format:
- * <type>-<partial_type_inst>-<size>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) {
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) {
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) {
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);
}
-
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));
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));
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;
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));
int rule_num)
{
int status;
- value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
/* Select the rules to collect */
return (0);
}
- vl.values = values;
- vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "ip6tables", sizeof (vl.plugin));
}
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,
int rule_num)
{
int status;
- value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
/* Select the rules to collect */
return (0);
}
- vl.values = values;
- vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "iptables", sizeof (vl.plugin));
}
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);
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));
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));
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));
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);
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);
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);
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);
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);
}
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];
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);
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)
{
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");
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");
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));
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;
}
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,
#include "collectd.h"
+#include "common.h"
#include "filter_chain.h"
+#include "meta_data.h"
+#include "utils_llist.h"
#include <sys/types.h>
#include <regex.h>
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;
};
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);
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, /* {{{ */
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);
}
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);
}
}
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;
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
&& (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.");
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 */
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));
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));
} /* }}} 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));
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) */
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)
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));
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)
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));
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 */
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));
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));
}
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));
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));
U32 ret;
int error;
- error=0;
- for (int i=0;i<num_mics;i++) {
+ error = 0;
+ for (int i = 0;i<num_mics;i++) {
ret = MicInitAdapter(&mic_handle,&mics[i]);
if (ret != MIC_ACCESS_API_SUCCESS) {
ERROR("mic plugin: Problem initializing MicAdapter: %s",
MicGetErrorString(ret));
- error=1;
+ error = 1;
}
if (error == 0 && show_memory)
if (ret != MIC_ACCESS_API_SUCCESS) {
ERROR("mic plugin: Problem closing MicAdapter: %s",
MicGetErrorString(ret));
- error=2;
+ error = 2;
break;
}
}
if (num_mics==0)
- error=3;
+ error = 3;
return error;
}
if (status == 0)
{
- user_data_t ud;
char name[1024];
- ud.data = host;
- ud.free_func = host_free;
-
ssnprintf (name, sizeof (name), "modbus-%s", host->host);
plugin_register_complex_read (/* group = */ NULL, name,
/* callback = */ mb_read,
/* interval = */ host->interval,
- &ud);
+ &(user_data_t) {
+ .data = host,
+ .free_func = host_free,
+ });
}
else
{
}
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 */
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));
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
{
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 */
}
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)
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)
{
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);
/* 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);
}
if (val == 0ULL)
continue;
- counter_submit ("mysql_handler",
+ derive_submit ("mysql_handler",
key + strlen ("Handler_"),
val, db);
}
else if (strncmp (key, "Table_locks_",
strlen ("Table_locks_")) == 0)
{
- counter_submit ("mysql_locks",
+ derive_submit ("mysql_locks",
key + strlen ("Table_locks_"),
val, db);
}
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)
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)
/* 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;
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;
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
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;
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,
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 */
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));
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));
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));
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));
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
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));
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;
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));
char *buffer;
size_t buffer_size;
int status;
+ char errbuf[1024];
char file[4096];
char *endptr;
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);
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++;
char *buffer;
size_t buffer_size;
int status;
+ char errbuf[1024];
char *buffer_ptr;
char *dummy;
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",
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));
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);
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) */
static int cow_init (void)
{
int status;
+ char errbuf[1024];
if (device_g == NULL)
{
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);
}
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) /* {{{ */
(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,
+ });
}
}
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));
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
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);
*
* Authors:
* Sebastian Harl <sh at tokkee.org>
+ * Pavel Rochnyak <pavel2000 ngs.ru>
**/
/*
#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
/* 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);
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
*/
* 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;
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 },
return 0;
}
- ret = call_pv (sub_name, G_SCALAR);
+ ret = call_pv (sub_name, G_SCALAR|G_EVAL);
t->running = old_running;
return ret;
/*
* 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;
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;
*
* 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 *);
XPUSHs (sv_2mortal (newRV_noinc ((SV *)pvl)));
}
else if (PLUGIN_LOG == type) {
+ subname = va_arg(ap, char *);
/*
* $_[0] = $level;
*
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] =
* {
* type_instance => $type_instance
* };
*/
- notification_t *n;
- HV *notif = newHV ();
-
n = va_arg (ap, notification_t *);
if (-1 == notification2hv (aTHX_ n, notif)) {
}
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;
va_end (ap);
return ret;
-} /* static int pplugin_call_all (int, ...) */
+} /* static int pplugin_call (int, ...) */
/*
* collectd's Perl interpreter based thread implementation.
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
}
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
* 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).
*
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;
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;
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);
} /* 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;
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);
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;
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;
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)
dTHX;
plugin_unregister_complex_config ("perl");
+ plugin_unregister_read_group ("perl");
if (NULL == perl_threads)
return 0;
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;
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) */
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);
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);
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));
/* <https://doc.powerdns.com/md/recursor/stats/> */
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;
if (i >= lookup_table_length)
{
INFO ("powerdns plugin: submit: Not found in lookup table: %s = %s;",
- pdns_type, value);
+ pdns_type, value_str);
return;
}
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));
/* 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));
/* 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));
#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));
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",
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));
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);
}
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);
}
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));
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);
{
cr_data_t *router_data;
char read_name[128];
- user_data_t user_data;
int status;
router_data = calloc (1, sizeof (*router_data));
}
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);
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);
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));
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;
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",
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));
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));
{
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. */
/* 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));
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));
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));
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.");
/* 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));
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);
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);
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);
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);
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);
{
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);
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);
}
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);
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 */
metric->value -= delta;
metric->counter += (derive_t) delta;
- values[0].derive = metric->counter;
+ vl.values[0].derive = metric->counter;
}
return (plugin_dispatch_values (&vl));
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)
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));
{
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);
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);
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,
{
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;
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;
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;
if (act->replacement == NULL)
{
ERROR ("tr_config_add_action: tr_strdup failed.");
- regfree (&act->re);
- sfree (act);
+ tr_action_destroy (act);
return (-ENOMEM);
}
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];
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;
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);
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++)
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 "
&& (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'.");
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);
#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
{
/* char *type; */
char *type_instance;
meta_data_t *meta;
+ ts_key_list_t *meta_delete;
};
typedef struct ts_data_s ts_data_t;
|| (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);
}
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;
/* free (data->type); */
free (data->type_instance);
meta_data_destroy(data->meta);
+ ts_key_list_free (data->meta_delete);
free (data);
return (0);
/* 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++)
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 "
&& (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;
}
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);
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 */
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)
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;
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);
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;
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);
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;
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)
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;
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);
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" */
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);
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);
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;
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);
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;
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);
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;
/*
* 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));
/*
* 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));
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));
};
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));
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);
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;
}
}
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));
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));
{
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);
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
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
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));
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));
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);
#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,
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
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 */
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));
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;
} /* 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
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,
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);
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);
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));
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));
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
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);
}
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.",
#include "plugin.h"
#include "utils_format_graphite.h"
+#include "utils_format_json.h"
#include <netdb.h>
-#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;
}
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);
}
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);
}
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)
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));
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);
}
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));
}
#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;
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);
}
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)
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);
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));
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));
#!/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'`"