#endif
#include "collectd.h"
+
#include "common.h"
#include "plugin.h"
static _Bool report_by_device = 0;
/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS
+/* No global variables */
+/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
+
#elif defined(VM_SWAPUSAGE)
/* No global variables */
/* #endif defined(VM_SWAPUSAGE) */
static _Bool values_absolute = 1;
static _Bool values_percentage = 0;
-static const char *config_keys[] =
-{
- "ReportBytes",
- "ReportByDevice",
- "ValuesAbsolute",
- "ValuesPercentage"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
-static int swap_config (const char *key, const char *value) /* {{{ */
+static int swap_config (oconfig_item_t *ci) /* {{{ */
{
- if (strcasecmp ("ReportBytes", key) == 0)
+ for (int i = 0; i < ci->children_num; i++)
{
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("ReportBytes", child->key) == 0)
#if KERNEL_LINUX
- report_bytes = IS_TRUE (value) ? 1 : 0;
+ cf_util_get_boolean (child, &report_bytes);
#else
- WARNING ("swap plugin: The \"ReportBytes\" option is only "
- "valid under Linux. "
- "The option is going to be ignored.");
+ WARNING ("swap plugin: The \"ReportBytes\" option "
+ "is only valid under Linux. "
+ "The option is going to be ignored.");
#endif
- }
- else if (strcasecmp ("ReportByDevice", key) == 0)
- {
+ else if (strcasecmp ("ReportByDevice", child->key) == 0)
#if SWAP_HAVE_REPORT_BY_DEVICE
- if (IS_TRUE (value))
- report_by_device = 1;
- else
- report_by_device = 0;
+ cf_util_get_boolean (child, &report_by_device);
#else
- WARNING ("swap plugin: The \"ReportByDevice\" option is not "
- "supported on this platform. "
- "The option is going to be ignored.");
+ WARNING ("swap plugin: The \"ReportByDevice\" option "
+ "is not supported on this platform. "
+ "The option is going to be ignored.");
#endif /* SWAP_HAVE_REPORT_BY_DEVICE */
- }
- else if (strcasecmp (key, "ValuesAbsolute") == 0)
- {
- if (IS_TRUE (value))
- values_absolute = 1;
+ else if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+ cf_util_get_boolean (child, &values_absolute);
+ else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+ cf_util_get_boolean (child, &values_percentage);
else
- values_absolute = 0;
-
- return (0);
- }
- else if (strcasecmp (key, "ValuesPercentage") == 0)
- {
- if (IS_TRUE (value))
- values_percentage = 1;
- else
- values_percentage = 0;
-
- return (0);
- }
- else
- {
- return (-1);
+ WARNING ("swap plugin: Unknown config option: \"%s\"",
+ child->key);
}
return (0);
/* #endif defined(VM_SWAPUSAGE) */
#elif HAVE_LIBKVM_GETSWAPINFO
+ char errbuf[_POSIX2_LINE_MAX];
+
if (kvm_obj != NULL)
{
kvm_close (kvm_obj);
kvm_pagesize = getpagesize ();
- if ((kvm_obj = kvm_open (NULL, /* execfile */
- NULL, /* corefile */
- NULL, /* swapfile */
- O_RDONLY, /* flags */
- NULL)) /* errstr */
- == NULL)
+ kvm_obj = kvm_openfiles (NULL, "/dev/null", NULL, O_RDONLY, errbuf);
+
+ if (kvm_obj == NULL)
{
- ERROR ("swap plugin: kvm_open failed.");
+ ERROR ("swap plugin: kvm_openfiles failed, %s", errbuf);
return (-1);
}
/* #endif HAVE_LIBKVM_GETSWAPINFO */
return (0);
} /* }}} int swap_init */
-static void swap_submit (const char *plugin_instance, /* {{{ */
- const char *type, const char *type_instance,
- value_t value)
+static void swap_submit_usage (char const *plugin_instance, /* {{{ */
+ gauge_t used, gauge_t free,
+ char const *other_name, gauge_t other_value)
{
+ value_t v[1];
value_list_t vl = VALUE_LIST_INIT;
- assert (type != NULL);
-
- vl.values = &value;
- vl.values_len = 1;
+ vl.values = v;
+ vl.values_len = STATIC_ARRAY_SIZE (v);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
if (plugin_instance != NULL)
- sstrncpy (vl.plugin_instance, plugin_instance, 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));
+ sstrncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "swap", sizeof (vl.type));
- plugin_dispatch_values (&vl);
-} /* }}} void swap_submit_inst */
+ if (values_absolute)
+ plugin_dispatch_multivalue (&vl, 0, DS_TYPE_GAUGE,
+ "used", used, "free", free,
+ other_name, other_value, NULL);
+ if (values_percentage)
+ plugin_dispatch_multivalue (&vl, 1, DS_TYPE_GAUGE,
+ "used", used, "free", free,
+ other_name, other_value, NULL);
+} /* }}} void swap_submit_usage */
-static void swap_submit_gauge (char const *plugin_instance, char const *type, /* {{{ */
- char const *type_instance, gauge_t value)
+#if KERNEL_LINUX || HAVE_PERFSTAT
+__attribute__((nonnull(1)))
+static void swap_submit_derive (char const *type_instance, /* {{{ */
+ derive_t value)
{
- value_t v;
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t v[1];
- v.gauge = value;
- swap_submit (plugin_instance, type, type_instance, v);
-} /* }}} void swap_submit_gauge */
+ v[0].derive = value;
-#if KERNEL_LINUX || HAVE_PERFSTAT
-static void swap_submit_derive (const char *plugin_instance, /* {{{ */
- const char *type_instance, derive_t value)
-{
- value_t v;
+ vl.values = v;
+ vl.values_len = STATIC_ARRAY_SIZE (v);
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
+ sstrncpy (vl.type, "swap_io", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- v.derive = value;
- swap_submit (plugin_instance, "swap_io", type_instance, v);
+ plugin_dispatch_values (&vl);
} /* }}} void swap_submit_derive */
#endif
char *endptr;
char path[PATH_MAX];
- gauge_t size;
+ gauge_t total;
gauge_t used;
- gauge_t free;
numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields != 5)
errno = 0;
endptr = NULL;
- size = strtod (fields[2], &endptr);
+ total = strtod (fields[2], &endptr);
if ((endptr == fields[2]) || (errno != 0))
continue;
if ((endptr == fields[3]) || (errno != 0))
continue;
- if (size < used)
+ if (total < used)
continue;
- free = size - used;
-
- if (values_absolute)
- {
- swap_submit_gauge (path, "swap", "used", used);
- swap_submit_gauge (path, "swap", "free", free);
- }
- if (values_percentage)
- {
- swap_submit_gauge (path, "percent", "used", 100.0 * used / (used + free));
- swap_submit_gauge (path, "percent", "free", 100.0 * free / (used + free));
- }
+ swap_submit_usage (path, used * 1024.0, (total - used) * 1024.0,
+ NULL, NAN);
}
fclose (fh);
FILE *fh;
char buffer[1024];
- uint8_t have_data = 0;
- gauge_t swap_used = 0.0;
- gauge_t swap_cached = 0.0;
- gauge_t swap_free = 0.0;
- gauge_t swap_total = 0.0;
+ gauge_t swap_used = NAN;
+ gauge_t swap_cached = NAN;
+ gauge_t swap_free = NAN;
+ gauge_t swap_total = NAN;
fh = fopen ("/proc/meminfo", "r");
if (fh == NULL)
continue;
if (strcasecmp (fields[0], "SwapTotal:") == 0)
- {
- swap_total = strtod (fields[1], /* endptr = */ NULL);
- have_data |= 0x01;
- }
+ strtogauge (fields[1], &swap_total);
else if (strcasecmp (fields[0], "SwapFree:") == 0)
- {
- swap_free = strtod (fields[1], /* endptr = */ NULL);
- have_data |= 0x02;
- }
+ strtogauge (fields[1], &swap_free);
else if (strcasecmp (fields[0], "SwapCached:") == 0)
- {
- swap_cached = strtod (fields[1], /* endptr = */ NULL);
- have_data |= 0x04;
- }
+ strtogauge (fields[1], &swap_cached);
}
fclose (fh);
- if (have_data != 0x07)
+ if (isnan (swap_total) || isnan (swap_free))
return (ENOENT);
- if (isnan (swap_total)
- || (swap_total <= 0.0)
- || ((swap_free + swap_cached) > swap_total))
- return (EINVAL);
-
- swap_used = swap_total - (swap_free + swap_cached);
+ /* Some systems, OpenVZ for example, don't provide SwapCached. */
+ if (isnan (swap_cached))
+ swap_used = swap_total - swap_free;
+ else
+ swap_used = swap_total - (swap_free + swap_cached);
+ assert (!isnan (swap_used));
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", 1024.0 * swap_used);
- swap_submit_gauge (NULL, "swap", "free", 1024.0 * swap_free);
- swap_submit_gauge (NULL, "swap", "cached", 1024.0 * swap_cached);
- }
- if (values_percentage)
- {
- swap_submit_gauge (NULL, "percent", "used", 100.0 * swap_used / swap_total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * swap_free / swap_total);
- swap_submit_gauge (NULL, "percent", "cached", 100.0 * swap_cached / swap_total);
- }
+ if (swap_used < 0.0)
+ return (EINVAL);
+ swap_submit_usage (NULL, swap_used * 1024.0, swap_free * 1024.0,
+ isnan (swap_cached) ? NULL : "cached",
+ isnan (swap_cached) ? NAN : swap_cached * 1024.0);
return (0);
} /* }}} int swap_read_combined */
swap_out = swap_out * pagesize;
}
- swap_submit_derive (NULL, "in", swap_in);
- swap_submit_derive (NULL, "out", swap_out);
+ swap_submit_derive ("in", swap_in);
+ swap_submit_derive ("out", swap_out);
return (0);
} /* }}} int swap_read_io */
swap_resv = (gauge_t) ((ai.ani_resv + ai.ani_free - ai.ani_max) * pagesize);
swap_avail = (gauge_t) ((ai.ani_max - ai.ani_resv) * pagesize);
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", swap_alloc);
- swap_submit_gauge (NULL, "swap", "free", swap_avail);
- swap_submit_gauge (NULL, "swap", "reserved", swap_resv);
- }
- if (values_percentage)
- {
- gauge_t swap_total = swap_alloc + swap_avail + swap_resv;
-
- swap_submit_gauge (NULL, "percent", "used", 100.0 * swap_alloc / swap_total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * swap_avail / swap_total);
- swap_submit_gauge (NULL, "percent", "cached", 100.0 * swap_resv / swap_total);
- }
-
+ swap_submit_usage (NULL, swap_alloc, swap_avail, "reserved", swap_resv);
return (0);
} /* }}} int swap_read_kstat */
/* #endif 0 && HAVE_LIBKSTAT */
char *s_paths;
int swap_num;
int status;
- int i;
gauge_t avail = 0;
gauge_t total = 0;
return (0);
/* Allocate and initialize the swaptbl_t structure */
- s = (swaptbl_t *) smalloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
+ s = malloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
if (s == NULL)
{
- ERROR ("swap plugin: smalloc failed.");
+ ERROR ("swap plugin: malloc failed.");
return (-1);
}
s_paths = calloc (swap_num, PATH_MAX);
if (s_paths == NULL)
{
- ERROR ("swap plugin: malloc failed.");
+ ERROR ("swap plugin: calloc failed.");
sfree (s);
return (-1);
}
- for (i = 0; i < swap_num; i++)
+ for (int i = 0; i < swap_num; i++)
s->swt_ent[i].ste_path = s_paths + (i * PATH_MAX);
s->swt_n = swap_num;
/* less elements returned than requested */
swap_num = status;
- for (i = 0; i < swap_num; i++)
+ for (int i = 0; i < swap_num; i++)
{
char path[PATH_MAX];
gauge_t this_total;
sstrncpy (path, s->swt_ent[i].ste_path, sizeof (path));
escape_slashes (path, sizeof (path));
- if (values_absolute)
- {
- swap_submit_gauge (path, "swap", "used", this_total - this_avail);
- swap_submit_gauge (path, "swap", "free", this_avail);
- }
- if (values_percentage)
- {
- swap_submit_gauge (path, "percent", "used", 100.0 * (this_total - this_avail) / this_total);
- swap_submit_gauge (path, "percent", "free", 100.0 * this_avail / this_total);
- }
-
+ swap_submit_usage (path, this_total - this_avail, this_avail,
+ NULL, NAN);
} /* for (swap_num) */
if (total < avail)
return (-1);
}
- /* If the "separate" option was specified (report_by_device == 2), all
+ /* If the "separate" option was specified (report_by_device == 1), all
* values have already been dispatched from within the loop. */
if (!report_by_device)
- {
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", (total - avail));
- swap_submit_gauge (NULL, "swap", "free", avail);
- }
- if (values_percentage)
- {
- swap_submit_gauge (NULL, "percent", "used", 100.0 * (total - avail) / total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * avail / total);
- }
- }
+ swap_submit_usage (NULL, total - avail, avail, NULL, NAN);
sfree (s_paths);
sfree (s);
struct swapent *swap_entries;
int swap_num;
int status;
- int i;
gauge_t used = 0;
gauge_t total = 0;
# define C_SWAP_BLOCK_SIZE 512.0
#endif
- for (i = 0; i < swap_num; i++)
+ /* TODO: Report per-device stats. The path name is available from
+ * swap_entries[i].se_path */
+ for (int i = 0; i < swap_num; i++)
{
if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
continue;
return (-1);
}
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", used);
- swap_submit_gauge (NULL, "swap", "free", (total - used));
- }
- if (values_percentage)
- {
- swap_submit_gauge (NULL, "percent", "used", 100.0 * used / total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * (total - used) / total);
- }
+ swap_submit_usage (NULL, used, total - used, NULL, NAN);
sfree (swap_entries);
-
return (0);
} /* }}} int swap_read */
/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
return (-1);
/* The returned values are bytes. */
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", (gauge_t) sw_usage.xsu_used);
- swap_submit_gauge (NULL, "swap", "free", (gauge_t) sw_usage.xsu_avail);
- }
- if (values_percentage)
- {
- gauge_t swap_total = (gauge_t) (sw_usage.xsu_used + sw_usage.xsu_avail);
- swap_submit_gauge (NULL, "percent", "used", 100.0 * ((gauge_t) sw_usage.xsu_used) / swap_total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * ((gauge_t) sw_usage.xsu_avail) / swap_total);
- }
+ swap_submit_usage (NULL,
+ (gauge_t) sw_usage.xsu_used, (gauge_t) sw_usage.xsu_avail,
+ NULL, NAN);
return (0);
} /* }}} int swap_read */
int status;
gauge_t used;
- gauge_t free;
gauge_t total;
if (kvm_obj == NULL)
total *= (gauge_t) kvm_pagesize;
used *= (gauge_t) kvm_pagesize;
- free = total - used;
-
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", used);
- swap_submit_gauge (NULL, "swap", "free", free);
- }
- if (values_percentage)
- {
- swap_submit_gauge (NULL, "percent", "used", 100.0 * used / total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * free / total);
- }
+ swap_submit_usage (NULL, used, total - used, NULL, NAN);
return (0);
} /* }}} int swap_read */
sg_swap_stats *swap;
swap = sg_get_swap_stats ();
-
if (swap == NULL)
return (-1);
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", (gauge_t) swap->used);
- swap_submit_gauge (NULL, "swap", "free", (gauge_t) swap->free);
- }
- if (values_percentage)
- {
- gauge_t swap_total = (gauge_t) (swap->used + swap->free);
- swap_submit_gauge (NULL, "percent", "used", 100.0 * ((gauge_t) swap->used) / swap_total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * ((gauge_t) swap->free) / swap_total);
- }
+ swap_submit_usage (NULL, (gauge_t) swap->used, (gauge_t) swap->free,
+ NULL, NAN);
return (0);
} /* }}} int swap_read */
#elif HAVE_PERFSTAT
static int swap_read (void) /* {{{ */
{
- perfstat_memory_total_t pmemory;
+ perfstat_memory_total_t pmemory = { 0 };
int status;
- memset (&pmemory, 0, sizeof (pmemory));
+ gauge_t total;
+ gauge_t free;
+ gauge_t reserved;
+
status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
if (status < 0)
{
return (-1);
}
- if (values_absolute)
- {
- swap_submit_gauge (NULL, "swap", "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
- swap_submit_gauge (NULL, "swap", "free", (gauge_t) pmemory.pgsp_free * pagesize);
- swap_submit_gauge (NULL, "swap", "reserved", (gauge_t) pmemory.pgsp_rsvd * pagesize);
- }
- if (values_percentage)
- {
- gauge_t swap_total = (gauge_t) pmemory.pgsp_total;
- swap_submit_gauge (NULL, "percent", "used", 100.0 * ((gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free)) / swap_total);
- swap_submit_gauge (NULL, "percent", "free", 100.0 * ((gauge_t) pmemory.pgsp_free) / swap_total);
- swap_submit_gauge (NULL, "percent", "reserved", 100.0 * ((gauge_t) pmemory.pgsp_rsvd) / swap_total);
- }
- swap_submit_derive (NULL, "in", (derive_t) pmemory.pgspins * pagesize);
- swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
+ total = (gauge_t) (pmemory.pgsp_total * pagesize);
+ free = (gauge_t) (pmemory.pgsp_free * pagesize);
+ reserved = (gauge_t) (pmemory.pgsp_rsvd * pagesize);
+
+ swap_submit_usage (NULL, total - free, free, "reserved", reserved);
+ swap_submit_derive ("in", (derive_t) pmemory.pgspins * pagesize);
+ swap_submit_derive ("out", (derive_t) pmemory.pgspouts * pagesize);
return (0);
} /* }}} int swap_read */
void module_register (void)
{
- plugin_register_config ("swap", swap_config,
- config_keys, config_keys_num);
+ plugin_register_complex_config ("swap", swap_config);
plugin_register_init ("swap", swap_init);
plugin_register_read ("swap", swap_read);
} /* void module_register */