From: Marc Fournier Date: Mon, 24 Nov 2014 08:44:45 +0000 (+0100) Subject: Merge branch 'collectd-5.4' X-Git-Tag: collectd-5.5.0~127 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=e1812f8e5c5f91328398c66b602d07ee7c6ede51;hp=e4df561e0843e4fc93a57609955fea00618da6ec Merge branch 'collectd-5.4' Conflicts: src/Makefile.am src/cpu.c src/swap.c src/write_redis.c NB: dropped change to src/swap.c made in 1a146775d4, as suggested in the commit message. --- diff --git a/contrib/exec-nagios.px b/contrib/exec-nagios.px index c7f18c58..ec13b0a0 100755 --- a/contrib/exec-nagios.px +++ b/contrib/exec-nagios.px @@ -442,7 +442,7 @@ sub execute_script close ($fh); # Save the exit status of the check in $state - $state = $?; + $state = $? >> 8; if ($state == 0) { diff --git a/contrib/redhat/init.d-collectd b/contrib/redhat/init.d-collectd index abdb168f..4c69f3c9 100644 --- a/contrib/redhat/init.d-collectd +++ b/contrib/redhat/init.d-collectd @@ -21,6 +21,8 @@ COLLECTD=/usr/sbin/collectd COLLECTDMONPIDDIR="/var/run" COLLECTDMONPID="$COLLECTDMONPIDDIR/collectdmon.pid" +MAXWAIT=30 + if [ -r /etc/sysconfig/$service ]; then . /etc/sysconfig/$service fi @@ -58,7 +60,7 @@ start () { } stop () { echo -n $"Stopping collectd: " - killproc -p $COLLECTDMONPID $prog + killproc -p $COLLECTDMONPID -d $MAXWAIT $prog RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$service diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 5196979e..a25cce55 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -347,6 +347,41 @@ # # +# +# Instance "test_http_json" +# +# Type "gauge" +# # Expect: 1 +# +# +# Type "gauge" +# # Expect: 2 +# +# +# Type "gauge" +# # Expect: 3 +# +# +# Type "gauge" +# # Expect: 4 +# +# +# Type "gauge" +# # Expect: 5 +# +# +# Type "gauge" +# # Expect: 6 +# +# +# put this as test.json on your webserver, the above config demonstraces +# how to match them. +# { +# "testArray":[1,2], +# "testArrayInbetween":[{"blarg":3},{"blub":4}], +# "testDirectHit":5, +# "testSubLevelHit":{"oneMoreLevel":6} +# } ## See: http://wiki.apache.org/couchdb/Runtime_Statistics # # Instance "httpd" @@ -1039,6 +1074,12 @@ # DeleteGauges false # DeleteSets false # TimerPercentile 90.0 +# TimerPercentile 95.0 +# TimerPercentile 99.0 +# TimerLower false +# TimerUpper false +# TimerSum false +# TimerCount false # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 20c61260..a65d432b 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -5812,7 +5812,20 @@ that I of all reported timers are smaller than or equal to the computed latency. This is useful for cutting off the long tail latency, as it's often done in I (SLAs). -If not specified, no percentile is calculated / dispatched. +Different percentiles can be calculated by setting this option several times. +If none are specified, no percentiles are calculated / dispatched. + +=item B B|B + +=item B B|B + +=item B B|B + +=item B B|B + +Calculate and dispatch various values out of I metrics received during +an interval. If set to B, the default, these values aren't calculated / +dispatched. =back @@ -7105,6 +7118,61 @@ want to set B to your Kafka broker list. =back +=head2 Plugin C + +The I submits values to I, a data structure server. + +Synopsis: + + + + Host "localhost" + Port "6379" + Timeout 1000 + + + +Values are submitted to I, using the metric name as the key, and +the timestamp as the score. Retrieving a date range can then be done using the +C I command. Additionnally, all the identifiers of these +I are kept in a I called C and can be +retrieved using the C I command. See +L and L for +details. + +The information shown in the synopsis above is the I +which is used by the plugin if no configuration is present. + +The plugin can send values to multiple instances of I by specifying +one B block for each instance. Within the B blocks, the following +options are available: + +=over 4 + +=item B I + +The B block identifies a new I node, that is a new I +instance running in an specified host and port. The name for node is a +canonical identifier which is used as I. It is limited to +64Echaracters in length. + +=item B I + +The B option is the hostname or IP-address where the I instance is +running on. + +=item B I + +The B 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 I + +The B option sets the socket connection timeout, in milliseconds. + +=back + =head2 Plugin C The I will send values to I, a powerful stream diff --git a/src/cpu.c b/src/cpu.c index d1978f96..2fb4918b 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -131,12 +131,6 @@ static const char *cpu_state_names[] = { 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) @@ -222,7 +216,7 @@ static int cpu_config (char const *key, char const *value) /* {{{ */ 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 (); @@ -577,33 +571,27 @@ static int cpu_read (void) { cdtime_t now = cdtime (); -#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; } @@ -617,50 +605,6 @@ static int cpu_read (void) cpu_stage (cpu, CPU_STATE_NICE, (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE], now); cpu_stage (cpu, CPU_STATE_SYSTEM, (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM], now); cpu_stage (cpu, CPU_STATE_IDLE, (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE], now); -#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 */ diff --git a/src/curl_json.c b/src/curl_json.c index 8a084fed..e99500aa 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -234,9 +234,14 @@ static int cj_cb_number (void *ctx, if (key != NULL) NOTICE ("curl_json plugin: Found \"%s\", but the configuration expects" " a map.", buffer); - cj_cb_inc_array_index (ctx, /* update_key = */ 0); - return (CJ_CB_CONTINUE); - } else { + cj_cb_inc_array_index (ctx, /* update_key = */ 1); + key = db->state[db->depth].key; + if (key == NULL) { + return (CJ_CB_CONTINUE); + } + } + else + { cj_cb_inc_array_index (ctx, /* update_key = */ 1); } @@ -276,10 +281,21 @@ static int cj_cb_map_key (void *ctx, memcpy (name, in_name, name_len); name[name_len] = 0; - if (c_avl_get (tree, name, (void *) &value) == 0) - db->state[db->depth].key = value; + if (c_avl_get (tree, name, (void *) &value) == 0) { + if (CJ_IS_KEY((cj_key_t*)value)) { + db->state[db->depth].key = value; + } + else { + db->state[db->depth].tree = (c_avl_tree_t*) value; + } + } else if (c_avl_get (tree, CJ_ANY, (void *) &value) == 0) - db->state[db->depth].key = value; + if (CJ_IS_KEY((cj_key_t*)value)) { + db->state[db->depth].key = value; + } + else { + db->state[db->depth].tree = (c_avl_tree_t*) value; + } else db->state[db->depth].key = NULL; } diff --git a/src/daemon/common.c b/src/daemon/common.c index 535dfad3..e2b618fb 100644 --- a/src/daemon/common.c +++ b/src/daemon/common.c @@ -475,8 +475,8 @@ size_t strstripnewline (char *buffer) if ((buffer[buffer_len - 1] != '\n') && (buffer[buffer_len - 1] != '\r')) break; - buffer[buffer_len] = 0; buffer_len--; + buffer[buffer_len] = 0; } return (buffer_len); diff --git a/src/daemon/filter_chain.c b/src/daemon/filter_chain.c index c87b8773..b93435fd 100644 --- a/src/daemon/filter_chain.c +++ b/src/daemon/filter_chain.c @@ -78,6 +78,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 */ @@ -627,16 +636,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) @@ -649,14 +655,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) { @@ -665,14 +674,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++) */ @@ -683,7 +693,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)) @@ -691,8 +701,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); @@ -702,23 +712,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.", @@ -726,13 +736,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."); } @@ -741,13 +754,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++) */ } diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c index 97b794f7..6c6ab63c 100644 --- a/src/daemon/plugin.c +++ b/src/daemon/plugin.c @@ -393,7 +393,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.", diff --git a/src/write_graphite.c b/src/write_graphite.c index d3d52027..41451a8c 100644 --- a/src/write_graphite.c +++ b/src/write_graphite.c @@ -197,6 +197,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); @@ -233,12 +235,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; @@ -251,11 +260,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