swap plugin: Remove left-over debugging message.
[collectd.git] / src / swap.c
index a20087d..ae1865e 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * collectd - src/swap.c
- * Copyright (C) 2005-2010  Florian octo Forster
+ * Copyright (C) 2005-2014  Florian octo Forster
  * Copyright (C) 2009       Stefan Völkel
  * Copyright (C) 2009       Manuel Sanmartin
  * Copyright (C) 2010       Aurélien Reynaud
 #define MAX(x,y) ((x) > (y) ? (x) : (y))
 
 #if KERNEL_LINUX
-# define SWAP_HAVE_CONFIG 1
-/* No global variables */
+# define SWAP_HAVE_REPORT_BY_DEVICE 1
+static derive_t pagesize;
+static _Bool report_bytes = 0;
+static _Bool report_by_device = 0;
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
-# define SWAP_HAVE_CONFIG 1
+# define SWAP_HAVE_REPORT_BY_DEVICE 1
 static derive_t pagesize;
+static _Bool report_by_device = 0;
 /* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS */
 
 #elif defined(VM_SWAPUSAGE)
@@ -94,30 +97,66 @@ int kvm_pagesize;
 
 #elif HAVE_PERFSTAT
 static int pagesize;
-static perfstat_memory_total_t pmemory;
 /*# endif HAVE_PERFSTAT */
 
 #else
 # error "No applicable input method."
 #endif /* HAVE_LIBSTATGRAB */
 
-#if SWAP_HAVE_CONFIG
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
 static const char *config_keys[] =
 {
-       "ReportByDevice"
+       "ReportBytes",
+       "ReportByDevice",
+       "ValuesAbsolute",
+       "ValuesPercentage"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
-static _Bool report_by_device = 0;
-
 static int swap_config (const char *key, const char *value) /* {{{ */
 {
-       if (strcasecmp ("ReportByDevice", key) == 0)
+       if (strcasecmp ("ReportBytes", key) == 0)
        {
+#if KERNEL_LINUX
+               report_bytes = IS_TRUE (value) ? 1 : 0;
+#else
+               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)
+       {
+#if SWAP_HAVE_REPORT_BY_DEVICE
                if (IS_TRUE (value))
                        report_by_device = 1;
                else
                        report_by_device = 0;
+#else
+               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
+                       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
        {
@@ -126,12 +165,11 @@ static int swap_config (const char *key, const char *value) /* {{{ */
 
        return (0);
 } /* }}} int swap_config */
-#endif /* SWAP_HAVE_CONFIG */
 
 static int swap_init (void) /* {{{ */
 {
 #if KERNEL_LINUX
-       /* No init stuff */
+       pagesize = (derive_t) sysconf (_SC_PAGESIZE);
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
@@ -196,15 +234,33 @@ static void swap_submit (const char *plugin_instance, /* {{{ */
        plugin_dispatch_values (&vl);
 } /* }}} void swap_submit_inst */
 
-static void swap_submit_gauge (const char *plugin_instance, /* {{{ */
-               const char *type_instance, gauge_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;
-
-       v.gauge = value;
-       swap_submit (plugin_instance, "swap", type_instance, v);
-} /* }}} void swap_submit_gauge */
+       value_t v[1];
+       value_list_t vl = VALUE_LIST_INIT;
 
+       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, "swap", sizeof (vl.type));
+
+       if (values_absolute)
+               plugin_dispatch_multivalue (&vl, 0,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+       if (values_percentage)
+               plugin_dispatch_multivalue (&vl, 1,
+                               "used", used, "free", free,
+                               other_name, other_value, NULL);
+} /* }}} void swap_submit_usage */
+
+#if KERNEL_LINUX || HAVE_PERFSTAT
 static void swap_submit_derive (const char *plugin_instance, /* {{{ */
                const char *type_instance, derive_t value)
 {
@@ -213,7 +269,7 @@ static void swap_submit_derive (const char *plugin_instance, /* {{{ */
        v.derive = value;
        swap_submit (plugin_instance, "swap_io", type_instance, v);
 } /* }}} void swap_submit_derive */
-
+#endif
 
 #if KERNEL_LINUX
 static int swap_read_separate (void) /* {{{ */
@@ -237,9 +293,8 @@ static int swap_read_separate (void) /* {{{ */
                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)
@@ -250,7 +305,7 @@ static int swap_read_separate (void) /* {{{ */
 
                errno = 0;
                endptr = NULL;
-               size = strtod (fields[2], &endptr);
+               total = strtod (fields[2], &endptr);
                if ((endptr == fields[2]) || (errno != 0))
                        continue;
 
@@ -260,13 +315,10 @@ static int swap_read_separate (void) /* {{{ */
                if ((endptr == fields[3]) || (errno != 0))
                        continue;
 
-               if (size < used)
+               if (total < used)
                        continue;
 
-               free = size - used;
-
-               swap_submit_gauge (path, "used", used);
-               swap_submit_gauge (path, "free", free);
+               swap_submit_usage (path, used, total - used, NULL, NAN);
        }
 
        fclose (fh);
@@ -332,10 +384,7 @@ static int swap_read_combined (void) /* {{{ */
 
        swap_used = swap_total - (swap_free + swap_cached);
 
-       swap_submit_gauge (NULL, "used",   1024.0 * swap_used);
-       swap_submit_gauge (NULL, "free",   1024.0 * swap_free);
-       swap_submit_gauge (NULL, "cached", 1024.0 * swap_cached);
-
+       swap_submit_usage (NULL, swap_used, swap_free, "cached", swap_cached);
        return (0);
 } /* }}} int swap_read_combined */
 
@@ -407,6 +456,12 @@ static int swap_read_io (void) /* {{{ */
        if (have_data != 0x03)
                return (ENOENT);
 
+       if (report_bytes)
+       {
+               swap_in = swap_in * pagesize;
+               swap_out = swap_out * pagesize;
+       }
+
        swap_submit_derive (NULL, "in",  swap_in);
        swap_submit_derive (NULL, "out", swap_out);
 
@@ -439,9 +494,9 @@ static int swap_read (void) /* {{{ */
 /* kstat-based read function */
 static int swap_read_kstat (void) /* {{{ */
 {
-       derive_t swap_alloc;
-       derive_t swap_resv;
-       derive_t swap_avail;
+       gauge_t swap_alloc;
+       gauge_t swap_resv;
+       gauge_t swap_avail;
 
        struct anoninfo ai;
 
@@ -474,15 +529,11 @@ static int swap_read_kstat (void) /* {{{ */
         * swap_alloc = pagesize * ( ai.ani_max - ai.ani_free );
         * can suffer from a 32bit overflow.
         */
-       swap_alloc  = (derive_t) ((ai.ani_max - ai.ani_free) * pagesize);
-       swap_resv   = (derive_t) ((ai.ani_resv + ai.ani_free - ai.ani_max)
-                       * pagesize);
-       swap_avail  = (derive_t) ((ai.ani_max - ai.ani_resv) * pagesize);
-
-       swap_submit_gauge (NULL, "used", swap_alloc);
-       swap_submit_gauge (NULL, "free", swap_avail);
-       swap_submit_gauge (NULL, "reserved", swap_resv);
+       swap_alloc = (gauge_t) ((ai.ani_max - ai.ani_free) * pagesize);
+       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);
 
+       swap_submit_usage (NULL, swap_alloc, swap_avail, "reserved", swap_resv);
        return (0);
 } /* }}} int swap_read_kstat */
 /* #endif 0 && HAVE_LIBKSTAT */
@@ -497,8 +548,8 @@ static int swap_read (void) /* {{{ */
         int status;
         int i;
 
-        derive_t avail = 0;
-        derive_t total = 0;
+        gauge_t avail = 0;
+        gauge_t total = 0;
 
         swap_num = swapctl (SC_GETNSWP, NULL);
         if (swap_num < 0)
@@ -561,14 +612,14 @@ static int swap_read (void) /* {{{ */
         for (i = 0; i < swap_num; i++)
         {
                char path[PATH_MAX];
-               derive_t this_total;
-               derive_t this_avail;
+               gauge_t this_total;
+               gauge_t this_avail;
 
                 if ((s->swt_ent[i].ste_flags & ST_INDEL) != 0)
                         continue;
 
-               this_total = ((derive_t) s->swt_ent[i].ste_pages) * pagesize;
-               this_avail = ((derive_t) s->swt_ent[i].ste_free)  * pagesize;
+               this_total = (gauge_t) (s->swt_ent[i].ste_pages * pagesize);
+               this_avail = (gauge_t) (s->swt_ent[i].ste_free  * pagesize);
 
                /* Shortcut for the "combined" setting (default) */
                if (!report_by_device)
@@ -581,27 +632,23 @@ static int swap_read (void) /* {{{ */
                sstrncpy (path, s->swt_ent[i].ste_path, sizeof (path));
                escape_slashes (path, sizeof (path));
 
-               swap_submit_gauge (path, "used", (gauge_t) (this_total - this_avail));
-               swap_submit_gauge (path, "free", (gauge_t) this_avail);
+               swap_submit_usage (path, this_total - this_avail, this_avail,
+                               NULL, NAN);
         } /* for (swap_num) */
 
         if (total < avail)
         {
-                ERROR ("swap plugin: Total swap space (%"PRIi64") "
-                                "is less than free swap space (%"PRIi64").",
+                ERROR ("swap plugin: Total swap space (%g) is less than free swap space (%g).",
                                 total, avail);
                sfree (s_paths);
                 sfree (s);
                 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)
-       {
-               swap_submit_gauge (NULL, "used", (gauge_t) (total - avail));
-               swap_submit_gauge (NULL, "free", (gauge_t) avail);
-       }
+               swap_submit_usage (NULL, total - avail, avail, NULL, NAN);
 
        sfree (s_paths);
         sfree (s);
@@ -617,8 +664,8 @@ static int swap_read (void) /* {{{ */
        int status;
        int i;
 
-       derive_t used  = 0;
-       derive_t total = 0;
+       gauge_t used  = 0;
+       gauge_t total = 0;
 
        swap_num = swapctl (SWAP_NSWAP, NULL, 0);
        if (swap_num < 0)
@@ -647,35 +694,32 @@ static int swap_read (void) /* {{{ */
        }
 
 #if defined(DEV_BSIZE) && (DEV_BSIZE > 0)
-# define C_SWAP_BLOCK_SIZE ((derive_t) DEV_BSIZE)
+# define C_SWAP_BLOCK_SIZE ((gauge_t) DEV_BSIZE)
 #else
-# define C_SWAP_BLOCK_SIZE ((derive_t) 512)
+# define C_SWAP_BLOCK_SIZE 512.0
 #endif
 
+       /* TODO: Report per-device stats. The path name is available from
+        * swap_entries[i].se_path */
        for (i = 0; i < swap_num; i++)
        {
                if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
                        continue;
 
-               used  += ((derive_t) swap_entries[i].se_inuse)
-                       * C_SWAP_BLOCK_SIZE;
-               total += ((derive_t) swap_entries[i].se_nblks)
-                       * C_SWAP_BLOCK_SIZE;
+               used  += ((gauge_t) swap_entries[i].se_inuse) * C_SWAP_BLOCK_SIZE;
+               total += ((gauge_t) swap_entries[i].se_nblks) * C_SWAP_BLOCK_SIZE;
        }
 
        if (total < used)
        {
-               ERROR ("swap plugin: Total swap space (%"PRIu64") "
-                               "is less than used swap space (%"PRIu64").",
+               ERROR ("swap plugin: Total swap space (%g) is less than used swap space (%g).",
                                total, used);
                return (-1);
        }
 
-       swap_submit_gauge (NULL, "used", (gauge_t) used);
-       swap_submit_gauge (NULL, "free", (gauge_t) (total - used));
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
 
        sfree (swap_entries);
-
        return (0);
 } /* }}} int swap_read */
 /* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
@@ -698,8 +742,9 @@ static int swap_read (void) /* {{{ */
                return (-1);
 
        /* The returned values are bytes. */
-       swap_submit_gauge (NULL, "used", (gauge_t) sw_usage.xsu_used);
-       swap_submit_gauge (NULL, "free", (gauge_t) sw_usage.xsu_avail);
+       swap_submit_usage (NULL,
+                       (gauge_t) sw_usage.xsu_used, (gauge_t) sw_usage.xsu_avail,
+                       NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -711,9 +756,8 @@ static int swap_read (void) /* {{{ */
        struct kvm_swap data_s;
        int             status;
 
-       derive_t used;
-       derive_t free;
-       derive_t total;
+       gauge_t used;
+       gauge_t total;
 
        if (kvm_obj == NULL)
                return (-1);
@@ -723,16 +767,13 @@ static int swap_read (void) /* {{{ */
        if (status == -1)
                return (-1);
 
-       total = (derive_t) data_s.ksw_total;
-       used  = (derive_t) data_s.ksw_used;
-
-       total *= (derive_t) kvm_pagesize;
-       used  *= (derive_t) kvm_pagesize;
+       total = (gauge_t) data_s.ksw_total;
+       used  = (gauge_t) data_s.ksw_used;
 
-       free = total - used;
+       total *= (gauge_t) kvm_pagesize;
+       used  *= (gauge_t) kvm_pagesize;
 
-       swap_submit_gauge (NULL, "used", (gauge_t) used);
-       swap_submit_gauge (NULL, "free", (gauge_t) free);
+       swap_submit_usage (NULL, used, total - used, NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -744,12 +785,11 @@ static int swap_read (void) /* {{{ */
        sg_swap_stats *swap;
 
        swap = sg_get_swap_stats ();
-
        if (swap == NULL)
                return (-1);
 
-       swap_submit_gauge (NULL, "used", (gauge_t) swap->used);
-       swap_submit_gauge (NULL, "free", (gauge_t) swap->free);
+       swap_submit_usage (NULL, (gauge_t) swap->used, (gauge_t) swap->free,
+                       NULL, NAN);
 
        return (0);
 } /* }}} int swap_read */
@@ -758,15 +798,30 @@ static int swap_read (void) /* {{{ */
 #elif HAVE_PERFSTAT
 static int swap_read (void) /* {{{ */
 {
-        if(perfstat_memory_total(NULL, &pmemory, sizeof(perfstat_memory_total_t), 1) < 0)
+       perfstat_memory_total_t pmemory;
+       int status;
+
+       gauge_t total;
+       gauge_t free;
+       gauge_t reserved;
+
+       memset (&pmemory, 0, sizeof (pmemory));
+        status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
+       if (status < 0)
        {
                 char errbuf[1024];
-                WARNING ("memory plugin: perfstat_memory_total failed: %s",
+                WARNING ("swap plugin: perfstat_memory_total failed: %s",
                         sstrerror (errno, errbuf, sizeof (errbuf)));
                 return (-1);
         }
-       swap_submit_gauge (NULL, "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
-       swap_submit_gauge (NULL, "free", (gauge_t) pmemory.pgsp_free * 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 (NULL, "in",  (derive_t) pmemory.pgspins * pagesize);
+       swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
 
        return (0);
 } /* }}} int swap_read */
@@ -774,9 +829,8 @@ static int swap_read (void) /* {{{ */
 
 void module_register (void)
 {
-#if SWAP_HAVE_CONFIG
-       plugin_register_config ("swap", swap_config, config_keys, config_keys_num);
-#endif
+       plugin_register_config ("swap", swap_config,
+                       config_keys, config_keys_num);
        plugin_register_init ("swap", swap_init);
        plugin_register_read ("swap", swap_read);
 } /* void module_register */