netapp plugin: Print a notice if all WAFL values have been disabled.
[collectd.git] / src / openvpn.c
index 16d4502..9f386f0 100644 (file)
@@ -1,7 +1,7 @@
 /**
  * collectd - src/openvpn.c
  * Copyright (C) 2008  Doug MacEachern
- * Copyright (C) 2008  Florian octo Forster
+ * Copyright (C) 2009  Florian octo Forster
  *
  * 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
 #include "common.h"
 #include "plugin.h"
 
-static char *status_file = "/etc/openvpn/openvpn-status.log";
+#define DEFAULT_STATUS_FILE "/etc/openvpn/openvpn-status.log"
+#define CLIENT_LIST_PREFIX  "CLIENT_LIST,"
+
+static char *status_file = NULL;
+
+/* For compression stats we need to convert these counters to a rate. */
+static counter_t pre_compress_old    = 0;
+static counter_t post_compress_old   = 0;
+static counter_t pre_decompress_old  = 0;
+static counter_t post_decompress_old = 0;
+static int compression_counter_valid = 0;
 
 static const char *config_keys[] =
 {
@@ -65,27 +75,51 @@ static void openvpn_submit (char *name, counter_t rx, counter_t tx)
 
        vl.values = values;
        vl.values_len = STATIC_ARRAY_SIZE (values);
-       vl.time = time (NULL);
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
-       sstrncpy (vl.type_instance, name, sizeof (vl.type_instance));
+       sstrncpy (vl.plugin_instance, name, sizeof (vl.plugin_instance));
        sstrncpy (vl.type, "if_octets", sizeof (vl.type));
 
        plugin_dispatch_values (&vl);
 } /* void openvpn_submit */
 
+static void compression_submit (char *type_instance, gauge_t ratio)
+{
+       value_t values[1];
+       value_list_t vl = VALUE_LIST_INIT;
+
+       values[0].gauge = ratio;
+
+       vl.values = values;
+       vl.values_len = STATIC_ARRAY_SIZE (values);
+       sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+       sstrncpy (vl.plugin, "openvpn", sizeof (vl.plugin));
+       sstrncpy (vl.type, "compression_ratio", sizeof (vl.type));
+       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type));
+
+       plugin_dispatch_values (&vl);
+} /* void compression_submit */
+
 static int openvpn_read (void)
 {
-       char *name;
-       counter_t rx, tx;
        FILE *fh;
        char buffer[1024];
-       char *fields[8];
-       const int max_fields = sizeof(fields)/sizeof(fields[0]);
+       char *fields[10];
+       const int max_fields = STATIC_ARRAY_SIZE (fields);
        int   fields_num;
-       static const char *prefix = "CLIENT_LIST,";
 
-       fh = fopen (status_file, "r");
+       counter_t pre_compress_new    = 0;
+       counter_t post_compress_new   = 0;
+       counter_t pre_decompress_new  = 0;
+       counter_t post_decompress_new = 0;
+
+       /* Clear the least significant four bits, just to make sure all four
+        * counters above are considered to be invalid. */
+       compression_counter_valid &= ~0x0f;
+
+       fh = fopen ((status_file != NULL)
+                       ? status_file
+                       : DEFAULT_STATUS_FILE, "r");
        if (fh == NULL)
                return (-1);
 
@@ -95,23 +129,87 @@ static int openvpn_read (void)
          */
        while (fgets (buffer, sizeof (buffer), fh) != NULL)
        {
-               if (strncmp(buffer, prefix, strlen(prefix)) != 0)
-               {
+               fields_num = openvpn_strsplit (buffer, fields, max_fields);
+
+               /* Expect at least ``key,value''. */
+               if (fields_num < 2)
                        continue;
-               }
 
-               fields_num = openvpn_strsplit (buffer, fields, max_fields);
-               if (fields_num != max_fields)
+               if (strcmp (fields[0], "CLIENT_LIST") == 0)
                {
-                       continue;
+                       char *name;
+                       counter_t rx;
+                       counter_t tx;
+
+                       /* The line we're expecting has 8 fields. We ignore all lines
+                        * with more or less fields. */
+                       if (fields_num != 8)
+                               continue;
+
+                       name =      fields[1];  /* "Common Name" */
+                       rx = atoll (fields[4]); /* "Bytes Received */
+                       tx = atoll (fields[5]); /* "Bytes Sent" */
+                       openvpn_submit (name, rx, tx);
+               }
+               else if (strcmp (fields[0], "pre-compress") == 0)
+               {
+                       pre_compress_new = atoll (fields[1]);
+                       compression_counter_valid |= 0x01;
+               }
+               else if (strcmp (fields[0], "post-compress") == 0)
+               {
+                       post_compress_new = atoll (fields[1]);
+                       compression_counter_valid |= 0x02;
+               }
+               else if (strcmp (fields[0], "pre-decompress") == 0)
+               {
+                       pre_decompress_new = atoll (fields[1]);
+                       compression_counter_valid |= 0x04;
+               }
+               else if (strcmp (fields[0], "post-decompress") == 0)
+               {
+                       post_decompress_new = atoll (fields[1]);
+                       compression_counter_valid |= 0x08;
                }
-               name =      fields[1];  /* "Common Name" */
-               rx = atoll (fields[4]); /* "Bytes Received */
-               tx = atoll (fields[5]); /* "Bytes Sent" */
-               openvpn_submit (name, rx, tx);
        }
        fclose (fh);
 
+       /* Check that all four counters are valid, {pre,post}_*_{old,new}. */
+       if ((compression_counter_valid & 0x33) == 0x33)
+       {
+               counter_t pre_diff;
+               counter_t post_diff;
+
+               pre_diff = counter_diff (pre_compress_old, pre_compress_new);
+               post_diff = counter_diff (post_compress_old, post_compress_new);
+
+               /* If we compress, we're sending. */
+               compression_submit ("tx",
+                               ((gauge_t) post_diff) / ((gauge_t) pre_diff));
+       }
+
+       /* Now check the other found counters. */
+       if ((compression_counter_valid & 0xcc) == 0xcc)
+       {
+               counter_t pre_diff;
+               counter_t post_diff;
+
+               pre_diff = counter_diff (pre_decompress_old, pre_decompress_new);
+               post_diff = counter_diff (post_decompress_old, post_decompress_new);
+
+               /* If we decompress, we're receiving. */
+               compression_submit ("rx",
+                               ((gauge_t) pre_diff) / ((gauge_t) post_diff));
+       }
+
+       /* Now copy all the new counters to the old counters and move the flags
+        * up. */
+       pre_compress_old = pre_compress_new;
+       post_compress_old = post_compress_new;
+       pre_decompress_old = pre_decompress_new;
+       post_decompress_old = post_decompress_new;
+       compression_counter_valid = (compression_counter_valid & 0x0f) << 4;
+
        return (0);
 } /* int openvpn_read */
 
@@ -119,7 +217,8 @@ static int openvpn_config (const char *key, const char *value)
 {
        if (strcasecmp ("StatusFile", key) == 0)
        {
-               status_file = strdup(value);
+               sfree (status_file);
+               status_file = sstrdup (value);
        }
        else
        {