[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