[collectd] [PATCH] vmem plugin: add Solaris and AIX support
Aurelien Reynaud
collectd at wattapower.net
Wed Jun 9 07:04:52 CEST 2010
---
configure.in | 2 +
src/Makefile.am | 7 ++
src/types.db | 1 +
src/vmem.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
4 files changed, 206 insertions(+), 8 deletions(-)
diff --git a/configure.in b/configure.in
index 13a1f9d..661cb14 100644
--- a/configure.in
+++ b/configure.in
@@ -4057,6 +4057,7 @@ then
plugin_swap="yes"
plugin_interface="yes"
plugin_load="yes"
+ plugin_vmem="yes"
fi
if test "x$with_procinfo" = "xyes"
@@ -4078,6 +4079,7 @@ then
plugin_interface="yes"
plugin_memory="yes"
plugin_tape="yes"
+ plugin_vmem="yes"
fi
if test "x$have_sys_swap_h$with_kstat$ac_system" = "xyesyesSolaris"
diff --git a/src/Makefile.am b/src/Makefile.am
index c6b0538..2ed4720 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1147,9 +1147,16 @@ if BUILD_PLUGIN_VMEM
pkglib_LTLIBRARIES += vmem.la
vmem_la_SOURCES = vmem.c
vmem_la_LDFLAGS = -module -avoid-version
+vmem_la_LIBADD =
collectd_LDADD += "-dlopen" vmem.la
collectd_DEPENDENCIES += vmem.la
+if BUILD_WITH_PERFSTAT
+vmem_la_LIBADD += -lperfstat
+endif
+if BUILD_WITH_LIBKSTAT
+vmem_la_LIBADD += -lkstat
endif
+endif # BUILD_PLUGIN_VMEM
if BUILD_PLUGIN_VSERVER
pkglib_LTLIBRARIES += vserver.la
diff --git a/src/types.db b/src/types.db
index 69301b2..684bc95 100644
--- a/src/types.db
+++ b/src/types.db
@@ -166,6 +166,7 @@ vmpage_action value:COUNTER:0:4294967295
vmpage_faults minflt:COUNTER:0:9223372036854775807, majflt:COUNTER:0:9223372036854775807
vmpage_io in:COUNTER:0:4294967295, out:COUNTER:0:4294967295
vmpage_number value:GAUGE:0:4294967295
+vmpage_counter value:COUNTER:0:U
voltage_threshold value:GAUGE:U:U, threshold:GAUGE:U:U
voltage value:GAUGE:U:U
vs_memory value:GAUGE:0:9223372036854775807
diff --git a/src/vmem.c b/src/vmem.c
index d32f1db..fe3a3ff 100644
--- a/src/vmem.c
+++ b/src/vmem.c
@@ -1,6 +1,7 @@
/**
* collectd - src/vmem.c
* Copyright (C) 2008 Florian octo Forster
+ * Copyright (C) 2010 Aurélien Reynaud
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -17,25 +18,36 @@
*
* Authors:
* Florian octo Forster <octo at verplant.org>
+ * Aurélien Reynaud <collectd at wattapower.net>
**/
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#if KERNEL_LINUX
+#if HAVE_PERFSTAT
+# include <sys/protosw.h>
+# include <libperfstat.h>
+#endif
+
+#ifdef HAVE_LIBKSTAT
+# include <sys/sysinfo.h>
+#endif /* HAVE_LIBKSTAT */
+
static const char *config_keys[] =
{
"Verbose"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
static int verbose_output = 0;
-/* #endif KERNEL_LINUX */
-#else
-# error "No applicable input method."
-#endif /* HAVE_LIBSTATGRAB */
+#if HAVE_LIBKSTAT
+/* Arbitrary value, might need adjustments for bigger setups */
+# define MAX_NUMCPU 256
+extern kstat_ctl_t *kc;
+static kstat_t *ksp[MAX_NUMCPU], *kspvm;
+static int numcpu;
+#endif /* HAVE_LIBKSTAT */
static void submit (const char *plugin_instance, const char *type,
const char *type_instance, value_t *values, int values_len)
@@ -65,7 +77,7 @@ static void submit_two (const char *plugin_instance, const char *type,
values[1].counter = c1;
submit (plugin_instance, type, type_instance, values, 2);
-} /* void submit_one */
+} /* void submit_two */
static void submit_one (const char *plugin_instance, const char *type,
const char *type_instance, value_t value)
@@ -73,6 +85,45 @@ static void submit_one (const char *plugin_instance, const char *type,
submit (plugin_instance, type, type_instance, &value, 1);
} /* void submit_one */
+static int vmem_init (void)
+{
+#if KERNEL_LINUX
+ /* No init stuff */
+/* #endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+ /* No init stuff */
+/* #endif HAVE_PERFSTAT */
+
+#elif HAVE_LIBKSTAT
+ kstat_t *ksp_chain;
+
+ numcpu = 0;
+
+ if (kc == NULL)
+ {
+ ERROR ("vmem plugin: kstat chain control structure not available.");
+ return (-1);
+ }
+
+ /* Solaris doesn't count linear... *sigh* */
+ for (numcpu = 0, ksp_chain = kc->kc_chain;
+ numcpu < MAX_NUMCPU && ksp_chain != NULL;
+ ksp_chain = ksp_chain->ks_next)
+ if (strncmp (ksp_chain->ks_module, "cpu_stat", 8) == 0)
+ ksp[numcpu++] = ksp_chain;
+
+ kspvm = kstat_lookup (kc, "unix", 0, "vminfo");
+ if (kspvm == NULL)
+ {
+ ERROR ("vmem plugin: Cannot find unix:0:vminfo kstat.");
+ return (-1);
+ }
+#endif /* HAVE_LIBKSTAT */
+
+ return (0);
+} /* int vmem_init */
+
static int vmem_config (const char *key, const char *value)
{
if (strcasecmp ("Verbose", key) == 0)
@@ -267,7 +318,143 @@ static int vmem_read (void)
if (pswpvalid == 0x03)
submit_two (NULL, "vmpage_io", "swap", pswpin, pswpout);
-#endif /* KERNEL_LINUX */
+/*#endif KERNEL_LINUX */
+
+#elif HAVE_PERFSTAT
+ perfstat_memory_total_t pmemory;
+ value_t value;
+
+ if (perfstat_memory_total (NULL, &pmemory,
+ sizeof (perfstat_memory_total_t), 1) < 0)
+ {
+ char errbuf[1024];
+ WARNING ("vmem plugin: perfstat_memory_total failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ /* Total virtual memory (in pages) */
+ value.gauge = pmemory.virt_total;
+ submit_one (NULL, "vmpage_number", "virt_total", value);
+ /* Active pages (pages are considered active if they have been accessed) */
+ value.gauge = pmemory.virt_active;
+ submit_one (NULL, "vmpage_number", "virt_active", value);
+
+ /* Number of page faults */
+ value.counter = pmemory.pgexct;
+ submit_one (NULL, "vmpage_action", "faults", value);
+
+ /* Number of pages paged in/out */
+ submit_two (NULL, "vmpage_io", "memory", (counter_t) pmemory.pgins,
+ (counter_t) pmemory.pgouts);
+ /* Number of page ins/outs from paging space */
+ submit_two (NULL, "vmpage_io", "swap", (counter_t) pmemory.pgspins,
+ (counter_t) pmemory.pgspouts);
+ /*
+ * Show the other statistics if verbose output is enabled.
+ */
+ if (verbose_output == 1)
+ {
+ /* Number of page steals */
+ value.counter = pmemory.pgsteals;
+ submit_one (NULL, "vmpage_action", "steals", value);
+ }
+
+/* #endif HAVE_PERFSTAT */
+
+#elif HAVE_LIBKSTAT
+ int cpu;
+ static cpu_stat_t cs;
+ static vminfo_t vm;
+ value_t value;
+ counter_t pgpgin = 0, pgpgout = 0;
+ counter_t pgswapin = 0, pgswapout = 0;
+ counter_t fspgin = 0, fspgout = 0;
+ counter_t anonpgin = 0, anonpgout = 0;
+ counter_t execpgin = 0, execpgout = 0;
+ counter_t minfault = 0, majfault = 0;
+ counter_t pgrec = 0, pgfrec = 0;
+ counter_t freed = 0;
+ counter_t scanned = 0;
+
+ if (kc == NULL || kspvm == NULL)
+ return (-1);
+
+ for (cpu = 0; cpu < numcpu; cpu++)
+ {
+ if (kstat_read (kc, ksp[cpu], &cs) == -1)
+ continue; /* error message? */
+
+ pgpgin += (counter_t) cs.cpu_vminfo.pgpgin;
+ pgpgout += (counter_t) cs.cpu_vminfo.pgpgout;
+ pgswapin += (counter_t) cs.cpu_vminfo.pgswapin;
+ pgswapout += (counter_t) cs.cpu_vminfo.pgswapout;
+ minfault += (counter_t) cs.cpu_vminfo.hat_fault;
+ minfault += (counter_t) cs.cpu_vminfo.as_fault;
+ majfault += (counter_t) cs.cpu_vminfo.maj_fault;
+ /*
+ * Skip the other statistics if verbose output is disabled.
+ */
+ if (verbose_output == 0)
+ continue;
+ fspgin += (counter_t) cs.cpu_vminfo.fspgin;
+ fspgout += (counter_t) cs.cpu_vminfo.fspgout;
+ anonpgin += (counter_t) cs.cpu_vminfo.anonpgin;
+ anonpgout += (counter_t) cs.cpu_vminfo.anonpgout;
+ execpgin += (counter_t) cs.cpu_vminfo.execpgin;
+ execpgout += (counter_t) cs.cpu_vminfo.execpgout;
+ pgrec += (counter_t) cs.cpu_vminfo.pgrec;
+ pgfrec += (counter_t) cs.cpu_vminfo.pgfrec;
+ freed += (counter_t) cs.cpu_vminfo.dfree;
+ scanned += (counter_t) cs.cpu_vminfo.scan;
+ }
+ submit_two (NULL, "vmpage_io", "memory", pgpgin, pgpgout);
+ submit_two (NULL, "vmpage_io", "swap", pgswapin, pgswapout);
+ submit_two (NULL, "vmpage_faults", NULL, minfault, majfault);
+ /*
+ * Show the other statistics if verbose output is enabled.
+ */
+ if (verbose_output == 1)
+ {
+ submit_two (NULL, "vmpage_io", "fs", fspgin, fspgout);
+ submit_two (NULL, "vmpage_io", "anonymous", anonpgin, anonpgout);
+ submit_two (NULL, "vmpage_io", "exec", execpgin, execpgout);
+ value.counter = pgrec;
+ submit_one (NULL, "vmpage_action", "pgrec", value);
+ value.counter = pgfrec;
+ submit_one (NULL, "vmpage_action", "pgfrec", value);
+ value.counter = freed;
+ submit_one (NULL, "vmpage_action", "freed", value);
+ value.counter = scanned;
+ submit_one (NULL, "vmpage_action", "scanned", value);
+ }
+
+ if (kstat_read (kc, kspvm, &vm) == -1)
+ {
+ ERROR ("vmem plugin: kstat_read failed.");
+ return (-1);
+ }
+ /*
+ * Total swapspace in Solaris consists of swap devices plus a variable amount
+ * of RAM. We have both total = available + reserved
+ * and total = free + allocated
+ * As allocated is a subset of reserved, we map this to
+ * used = allocated
+ * resv = reserved - allocated
+ * free = available
+ * so we have: used + resv + free = total
+ * Free RAM can be used as additional swap space if needed.
+ */
+ value.counter = (counter_t) vm.freemem;
+ submit_one (NULL, "vmpage_counter", "freemem", value);
+ value.counter = (counter_t) vm.swap_alloc;
+ submit_one (NULL, "vmpage_counter", "swapspace_used", value);
+ value.counter = (counter_t) vm.swap_avail;
+ submit_one (NULL, "vmpage_counter", "swapspace_free", value);
+ value.counter = (counter_t) vm.swap_resv - (counter_t) vm.swap_alloc;
+ submit_one (NULL, "vmpage_counter", "swapspace_resv", value);
+
+#endif /* HAVE_LIBKSTAT */
return (0);
} /* int vmem_read */
@@ -276,6 +463,7 @@ void module_register (void)
{
plugin_register_config ("vmem", vmem_config,
config_keys, config_keys_num);
+ plugin_register_init ("vmem", vmem_init);
plugin_register_read ("vmem", vmem_read);
} /* void module_register */
--
1.7.1
More information about the collectd
mailing list