Merge branch 'collectd-5.3' into collectd-5.4
authorMarc Fournier <marc.fournier@camptocamp.com>
Mon, 24 Nov 2014 08:23:18 +0000 (09:23 +0100)
committerMarc Fournier <marc.fournier@camptocamp.com>
Mon, 24 Nov 2014 08:23:18 +0000 (09:23 +0100)
Conflicts:
src/write_graphite.c

14 files changed:
contrib/exec-nagios.px
src/Makefile.am
src/collectd.conf.pod
src/cpu.c
src/filter_chain.c
src/libcollectdclient/network_buffer.c
src/logfile.c
src/network.c
src/plugin.c
src/snmp.c
src/swap.c
src/syslog.c
src/write_graphite.c
src/write_redis.c

index c7f18c5..ec13b0a 100755 (executable)
@@ -442,7 +442,7 @@ sub execute_script
 
   close ($fh);
   # Save the exit status of the check in $state
-  $state = $?;
+  $state = $? >> 8;
 
   if ($state == 0)
   {
index 36ce028..2abea1f 100644 (file)
@@ -143,7 +143,7 @@ pkglib_LTLIBRARIES += aggregation.la
 aggregation_la_SOURCES = aggregation.c \
                          utils_vl_lookup.c utils_vl_lookup.h
 aggregation_la_LDFLAGS = -module -avoid-version
-aggregation_la_LIBADD =
+aggregation_la_LIBADD = -lm
 collectd_LDADD += "-dlopen" aggregation.la
 collectd_DEPENDENCIES += aggregation.la
 endif
index 8a6614b..03a1444 100644 (file)
@@ -6304,6 +6304,61 @@ number.
 
 =back
 
+=head2 Plugin C<write_redis>
+
+The I<write_redis plugin> submits values to I<Redis>, a data structure server.
+
+Synopsis:
+
+  <Plugin "write_redis">
+    <Node "example">
+        Host "localhost"
+        Port "6379"
+        Timeout 1000
+    </Node>
+  </Plugin>
+
+Values are submitted to I<Sorted Sets>, using the metric name as the key, and
+the timestamp as the score. Retrieving a date range can then be done using the
+C<ZRANGEBYSCORE> I<Redis> command. Additionnally, all the identifiers of these
+I<Sorted Sets> are kept in a I<Set> called C<collectd/values> and can be
+retrieved using the C<SMEMBERS> I<Redis> command. See
+L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
+details.
+
+The information shown in the synopsis above is the I<default configuration>
+which is used by the plugin if no configuration is present.
+
+The plugin can send values to multiple instances of I<Redis> by specifying
+one B<Node> block for each instance. Within the B<Node> blocks, the following
+options are available:
+
+=over 4
+
+=item B<Node> I<Nodename>
+
+The B<Node> block identifies a new I<Redis> node, that is a new I<Redis>
+instance running in an specified host and port. The name for node is a
+canonical identifier which is used as I<plugin instance>. It is limited to
+64E<nbsp>characters in length.
+
+=item B<Host> I<Hostname>
+
+The B<Host> option is the hostname or IP-address where the I<Redis> instance is
+running on.
+
+=item B<Port> I<Port>
+
+The B<Port> option is the TCP port on which the Redis instance accepts
+connections. Either a service name of a port number may be given. Please note
+that numerical port numbers must be given as a string, too.
+
+=item B<Timeout> I<Timeout in miliseconds>
+
+The B<Timeout> option sets the socket connection timeout, in milliseconds.
+
+=back
+
 =head2 Plugin C<write_riemann>
 
 The I<write_riemann plugin> will send values to I<Riemann>, a powerfull stream
index 2247d5f..1c4e5f6 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
 static mach_port_t port_host;
 static processor_port_array_t cpu_list;
 static mach_msg_type_number_t cpu_list_len;
-
-#if PROCESSOR_TEMPERATURE
-static int cpu_temp_retry_counter = 0;
-static int cpu_temp_retry_step    = 1;
-static int cpu_temp_retry_max     = 1;
-#endif /* PROCESSOR_TEMPERATURE */
 /* #endif PROCESSOR_CPU_LOAD_INFO */
 
 #elif defined(KERNEL_LINUX)
@@ -147,7 +141,7 @@ static int pnumcpu;
 
 static int init (void)
 {
-#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
+#if PROCESSOR_CPU_LOAD_INFO
        kern_return_t status;
 
        port_host = mach_host_self ();
@@ -262,33 +256,27 @@ static void submit (int cpu_num, const char *type_instance, derive_t value)
 
 static int cpu_read (void)
 {
-#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
+#if PROCESSOR_CPU_LOAD_INFO
        int cpu;
 
        kern_return_t status;
        
-#if PROCESSOR_CPU_LOAD_INFO
        processor_cpu_load_info_data_t cpu_info;
        mach_msg_type_number_t         cpu_info_len;
-#endif
-#if PROCESSOR_TEMPERATURE
-       processor_info_data_t          cpu_temp;
-       mach_msg_type_number_t         cpu_temp_len;
-#endif
 
        host_t cpu_host;
 
        for (cpu = 0; cpu < cpu_list_len; cpu++)
        {
-#if PROCESSOR_CPU_LOAD_INFO
                cpu_host = 0;
                cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
 
-               if ((status = processor_info (cpu_list[cpu],
-                                               PROCESSOR_CPU_LOAD_INFO, &cpu_host,
-                                               (processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS)
+               status = processor_info (cpu_list[cpu], PROCESSOR_CPU_LOAD_INFO, &cpu_host,
+                               (processor_info_t) &cpu_info, &cpu_info_len);
+               if (status != KERN_SUCCESS)
                {
-                       ERROR ("cpu plugin: processor_info failed with status %i", (int) status);
+                       ERROR ("cpu plugin: processor_info (PROCESSOR_CPU_LOAD_INFO) failed: %s",
+                                       mach_error_string (status));
                        continue;
                }
 
@@ -302,49 +290,6 @@ static int cpu_read (void)
                submit (cpu, "nice", (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE]);
                submit (cpu, "system", (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM]);
                submit (cpu, "idle", (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE]);
-#endif /* PROCESSOR_CPU_LOAD_INFO */
-#if PROCESSOR_TEMPERATURE
-               /*
-                * Not all Apple computers do have this ability. To minimize
-                * the messages sent to the syslog we do an exponential
-                * stepback if `processor_info' fails. We still try ~once a day
-                * though..
-                */
-               if (cpu_temp_retry_counter > 0)
-               {
-                       cpu_temp_retry_counter--;
-                       continue;
-               }
-
-               cpu_temp_len = PROCESSOR_INFO_MAX;
-
-               status = processor_info (cpu_list[cpu],
-                               PROCESSOR_TEMPERATURE,
-                               &cpu_host,
-                               cpu_temp, &cpu_temp_len);
-               if (status != KERN_SUCCESS)
-               {
-                       ERROR ("cpu plugin: processor_info failed: %s",
-                                       mach_error_string (status));
-
-                       cpu_temp_retry_counter = cpu_temp_retry_step;
-                       cpu_temp_retry_step *= 2;
-                       if (cpu_temp_retry_step > cpu_temp_retry_max)
-                               cpu_temp_retry_step = cpu_temp_retry_max;
-
-                       continue;
-               }
-
-               if (cpu_temp_len != 1)
-               {
-                       DEBUG ("processor_info (PROCESSOR_TEMPERATURE) returned %i elements..?",
-                                       (int) cpu_temp_len);
-                       continue;
-               }
-
-               cpu_temp_retry_counter = 0;
-               cpu_temp_retry_step    = 1;
-#endif /* PROCESSOR_TEMPERATURE */
        }
 /* #endif PROCESSOR_CPU_LOAD_INFO */
 
index 7d8369b..5ad9655 100644 (file)
@@ -73,6 +73,15 @@ struct fc_chain_s /* {{{ */
   fc_chain_t  *next;
 }; /* }}} */
 
+/* Writer configuration. */
+struct fc_writer_s;
+typedef struct fc_writer_s fc_writer_t; /* {{{ */
+struct fc_writer_s
+{
+  char *plugin;
+  c_complain_t complaint;
+}; /* }}} */
+
 /*
  * Global variables
  */
@@ -609,16 +618,13 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
 {
   int i;
 
-  char **plugin_list;
-  size_t plugin_list_len;
-
-  plugin_list = NULL;
-  plugin_list_len = 0;
+  fc_writer_t *plugin_list = NULL;
+  size_t plugin_list_len = 0;
 
   for (i = 0; i < ci->children_num; i++)
   {
     oconfig_item_t *child = ci->children + i;
-    char **temp;
+    fc_writer_t *temp;
     int j;
 
     if (strcasecmp ("Plugin", child->key) != 0)
@@ -631,14 +637,17 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
 
     for (j = 0; j < child->values_num; j++)
     {
+      char *plugin;
+
       if (child->values[j].type != OCONFIG_TYPE_STRING)
       {
         ERROR ("Filter subsystem: Built-in target `write': "
             "The `Plugin' option accepts only string arguments.");
         continue;
       }
+      plugin = child->values[j].value.string;
 
-      temp = (char **) realloc (plugin_list, (plugin_list_len + 2)
+      temp = (fc_writer_t *) realloc (plugin_list, (plugin_list_len + 2)
           * (sizeof (*plugin_list)));
       if (temp == NULL)
       {
@@ -647,14 +656,15 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
       }
       plugin_list = temp;
 
-      plugin_list[plugin_list_len] = fc_strdup (child->values[j].value.string);
-      if (plugin_list[plugin_list_len] == NULL)
+      plugin_list[plugin_list_len].plugin = fc_strdup (plugin);
+      if (plugin_list[plugin_list_len].plugin == NULL)
       {
         ERROR ("fc_bit_write_create: fc_strdup failed.");
         continue;
       }
+      C_COMPLAIN_INIT (&plugin_list[plugin_list_len].complaint);
       plugin_list_len++;
-      plugin_list[plugin_list_len] = NULL;
+      plugin_list[plugin_list_len].plugin = NULL;
     } /* for (j = 0; j < child->values_num; j++) */
   } /* for (i = 0; i < ci->children_num; i++) */
 
@@ -665,7 +675,7 @@ static int fc_bit_write_create (const oconfig_item_t *ci, /* {{{ */
 
 static int fc_bit_write_destroy (void **user_data) /* {{{ */
 {
-  char **plugin_list;
+  fc_writer_t *plugin_list;
   size_t i;
 
   if ((user_data == NULL) || (*user_data == NULL))
@@ -673,8 +683,8 @@ static int fc_bit_write_destroy (void **user_data) /* {{{ */
 
   plugin_list = *user_data;
 
-  for (i = 0; plugin_list[i] != NULL; i++)
-    free (plugin_list[i]);
+  for (i = 0; plugin_list[i].plugin != NULL; i++)
+    free (plugin_list[i].plugin);
   free (plugin_list);
 
   return (0);
@@ -684,23 +694,23 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
     value_list_t *vl, notification_meta_t __attribute__((unused)) **meta,
     void **user_data)
 {
-  char **plugin_list;
+  fc_writer_t *plugin_list;
   int status;
 
   plugin_list = NULL;
   if (user_data != NULL)
     plugin_list = *user_data;
 
-  if ((plugin_list == NULL) || (plugin_list[0] == NULL))
+  if ((plugin_list == NULL) || (plugin_list[0].plugin == NULL))
   {
-    static c_complain_t enoent_complaint = C_COMPLAIN_INIT_STATIC;
+    static c_complain_t write_complaint = C_COMPLAIN_INIT_STATIC;
 
     status = plugin_write (/* plugin = */ NULL, ds, vl);
     if (status == ENOENT)
     {
       /* in most cases this is a permanent error, so use the complain
        * mechanism rather than spamming the logs */
-      c_complain (LOG_INFO, &enoent_complaint,
+      c_complain (LOG_INFO, &write_complaint,
           "Filter subsystem: Built-in target `write': Dispatching value to "
           "all write plugins failed with status %i (ENOENT). "
           "Most likely this means you didn't load any write plugins.",
@@ -708,13 +718,16 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
     }
     else if (status != 0)
     {
-      INFO ("Filter subsystem: Built-in target `write': Dispatching value to "
+      /* often, this is a permanent error (e.g. target system unavailable),
+       * so use the complain mechanism rather than spamming the logs */
+      c_complain (LOG_INFO, &write_complaint,
+          "Filter subsystem: Built-in target `write': Dispatching value to "
           "all write plugins failed with status %i.", status);
     }
     else
     {
       assert (status == 0);
-      c_release (LOG_INFO, &enoent_complaint, "Filter subsystem: "
+      c_release (LOG_INFO, &write_complaint, "Filter subsystem: "
           "Built-in target `write': Some write plugin is back to normal "
           "operation. `write' succeeded.");
     }
@@ -723,13 +736,21 @@ static int fc_bit_write_invoke (const data_set_t *ds, /* {{{ */
   {
     size_t i;
 
-    for (i = 0; plugin_list[i] != NULL; i++)
+    for (i = 0; plugin_list[i].plugin != NULL; i++)
     {
-      status = plugin_write (plugin_list[i], ds, vl);
+      status = plugin_write (plugin_list[i].plugin, ds, vl);
       if (status != 0)
       {
-        INFO ("Filter subsystem: Built-in target `write': Dispatching value to "
-            "the `%s' plugin failed with status %i.", plugin_list[i], status);
+        c_complain (LOG_INFO, &plugin_list[i].complaint,
+            "Filter subsystem: Built-in target `write': Dispatching value to "
+            "the `%s' plugin failed with status %i.",
+            plugin_list[i].plugin, status);
+      }
+      else
+      {
+        c_release (LOG_INFO, &plugin_list[i].complaint,
+            "Filter subsystem: Built-in target `write': Plugin `%s' is back "
+            "to normal operation. `write' succeeded.", plugin_list[i].plugin);
       }
     } /* for (i = 0; plugin_list[i] != NULL; i++) */
   }
index 7b06620..61c7c22 100644 (file)
@@ -54,7 +54,9 @@
 /* Re enable deprecation warnings */
 #  pragma GCC diagnostic warning "-Wdeprecated-declarations"
 # endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
 #endif
 
 #include "collectd/network_buffer.h"
@@ -131,7 +133,9 @@ static _Bool have_gcrypt (void) /* {{{ */
   need_init = 0;
 
 #if HAVE_LIBGCRYPT
+# if GCRYPT_VERSION_NUMBER < 0x010600
   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
 
   if (!gcry_check_version (GCRYPT_VERSION))
     return (0);
index 0f20f3c..63448cb 100644 (file)
@@ -54,7 +54,11 @@ static int logfile_config (const char *key, const char *value)
 {
        if (0 == strcasecmp (key, "LogLevel")) {
                log_level = parse_log_severity(value);
-               if (log_level == -1) return 1; /* to keep previous behaviour */
+               if (log_level < 0) {
+                       log_level = LOG_INFO;
+                       ERROR ("logfile: invalid loglevel [%s] defaulting to 'info'", value);
+                       return (1);
+               }
        }
        else if (0 == strcasecmp (key, "File")) {
                sfree (log_file);
index ce9b0cc..a2221e5 100644 (file)
@@ -76,7 +76,9 @@
 /* Re enable deprecation warnings */
 #  pragma GCC diagnostic warning "-Wdeprecated-declarations"
 # endif
+# if GCRYPT_VERSION_NUMBER < 0x010600
 GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# endif
 #endif
 
 #ifndef IPV6_ADD_MEMBERSHIP
@@ -508,7 +510,9 @@ static void network_init_gcrypt (void) /* {{{ */
   * above doesn't count, as it doesn't implicitly initalize Libgcrypt.
   *
   * tl;dr: keep all these gry_* statements in this exact order please. */
+# if GCRYPT_VERSION_NUMBER < 0x010600
   gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# endif
   gcry_check_version (NULL);
   gcry_control (GCRYCTL_INIT_SECMEM, 32768);
   gcry_control (GCRYCTL_INITIALIZATION_FINISHED);
@@ -1996,7 +2000,7 @@ static sockent_t *sockent_create (int type) /* {{{ */
 {
        sockent_t *se;
 
-       if ((type != SOCKENT_TYPE_CLIENT) || (type != SOCKENT_TYPE_SERVER))
+       if ((type != SOCKENT_TYPE_CLIENT) && (type != SOCKENT_TYPE_SERVER))
                return (NULL);
 
        se = malloc (sizeof (*se));
index 6c7aa05..b60c04b 100644 (file)
@@ -339,7 +339,7 @@ static int plugin_load_file (char *file, uint32_t flags)
 
                ssnprintf (errbuf, sizeof (errbuf),
                                "lt_dlopen (\"%s\") failed: %s. "
-                               "The most common cause for this problem are "
+                               "The most common cause for this problem is "
                                "missing dependencies. Use ldd(1) to check "
                                "the dependencies of the plugin "
                                "/ shared object.",
index 3e6cb91..7d340d1 100644 (file)
@@ -1316,6 +1316,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
         snmp_free_pdu (res);
       res = NULL;
 
+      /* snmp_synch_response already freed our PDU */
+      req = NULL;
       sfree (errstr);
       csnmp_host_close_session (host);
 
index 46d3534..1621f7a 100644 (file)
@@ -339,7 +339,7 @@ static int swap_read_combined (void) /* {{{ */
 
        fclose (fh);
 
-       if (have_data != 0x07)
+       if ((have_data & 0x03) != 0x03)
                return (ENOENT);
 
        if (isnan (swap_total)
@@ -351,7 +351,8 @@ static int swap_read_combined (void) /* {{{ */
 
        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);
+       if (have_data & 0x04)
+               swap_submit_gauge (NULL, "cached", 1024.0 * swap_cached);
 
        return (0);
 } /* }}} int swap_read_combined */
index 4f5d0c4..834ba79 100644 (file)
@@ -48,7 +48,11 @@ static int sl_config (const char *key, const char *value)
        {
                log_level = parse_log_severity (value);
                if (log_level < 0)
+               {
+                       log_level = LOG_INFO;
+                       ERROR ("syslog: invalid loglevel [%s] defaulting to 'info'", value);
                        return (1);
+               }
        }
        else if (strcasecmp (key, "NotifyLevel") == 0)
        {
index c17b7f3..504ea9d 100644 (file)
@@ -192,6 +192,8 @@ static int wg_callback_init (struct wg_callback *cb)
     const char *service = cb->service ? cb->service : WG_DEFAULT_SERVICE;
     const char *protocol = cb->protocol ? cb->protocol : WG_DEFAULT_PROTOCOL;
 
+    char connerr[1024] = "";
+
     if (cb->sock_fd > 0)
         return (0);
 
@@ -221,12 +223,19 @@ static int wg_callback_init (struct wg_callback *cb)
     {
         cb->sock_fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype,
                 ai_ptr->ai_protocol);
-        if (cb->sock_fd < 0)
+        if (cb->sock_fd < 0) {
+            char errbuf[1024];
+            snprintf (connerr, sizeof (connerr), "failed to open socket: %s",
+                    sstrerror (errno, errbuf, sizeof (errbuf)));
             continue;
+        }
 
         status = connect (cb->sock_fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
         if (status != 0)
         {
+            char errbuf[1024];
+            snprintf (connerr, sizeof (connerr), "failed to connect to remote "
+                    "host: %s", sstrerror (errno, errbuf, sizeof (errbuf)));
             close (cb->sock_fd);
             cb->sock_fd = -1;
             continue;
@@ -239,11 +248,12 @@ static int wg_callback_init (struct wg_callback *cb)
 
     if (cb->sock_fd < 0)
     {
-        char errbuf[1024];
+        if (connerr[0] == '\0')
+            /* this should not happen but try to get a message anyway */
+            sstrerror (errno, connerr, sizeof (connerr));
         c_complain (LOG_ERR, &cb->init_complaint,
-                "write_graphite plugin: Connecting to %s:%s via %s failed. "
-                "The last error was: %s", node, service, protocol,
-                sstrerror (errno, errbuf, sizeof (errbuf)));
+                  "write_graphite plugin: Connecting to %s:%s via %s failed. "
+                  "The last error was: %s", node, service, protocol, connerr);
         return (-1);
     }
     else
index 58f2cae..1d9ec27 100644 (file)
@@ -84,7 +84,7 @@ static int wr_write (const data_set_t *ds, /* {{{ */
   }                                                                  \
 } while (0)
 
-  APPEND ("%lu", (unsigned long) vl->time);
+  APPEND ("%lu:", (unsigned long) vl->time);
   for (i = 0; i < ds->ds_num; i++)
   {
     if (ds->ds[i].type == DS_TYPE_COUNTER)