X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fthreshold.c;h=1d9bcf95ba8fcfe52a2ce0de5a1d1a5c5ce07034;hb=ec9ed6fe4108f7fd3d4ef84e887bb6d3dc022e14;hp=c1af40b81e019e967026cf43c3e40be1a97954c1;hpb=43a771aa5443266cca4cb7aecaf70eb75100a32c;p=collectd.git diff --git a/src/threshold.c b/src/threshold.c index c1af40b8..1d9bcf95 100644 --- a/src/threshold.c +++ b/src/threshold.c @@ -24,47 +24,12 @@ **/ #include "collectd.h" + #include "common.h" #include "plugin.h" #include "utils_avltree.h" #include "utils_cache.h" - -#include -#include - -/* - * Private data structures - * {{{ */ -#define UT_FLAG_INVERT 0x01 -#define UT_FLAG_PERSIST 0x02 -#define UT_FLAG_PERCENTAGE 0x04 -#define UT_FLAG_INTERESTING 0x08 -#define UT_FLAG_PERSIST_OK 0x10 -typedef struct threshold_s -{ - char host[DATA_MAX_NAME_LEN]; - char plugin[DATA_MAX_NAME_LEN]; - char plugin_instance[DATA_MAX_NAME_LEN]; - char type[DATA_MAX_NAME_LEN]; - char type_instance[DATA_MAX_NAME_LEN]; - char data_source[DATA_MAX_NAME_LEN]; - gauge_t warning_min; - gauge_t warning_max; - gauge_t failure_min; - gauge_t failure_max; - gauge_t hysteresis; - unsigned int flags; - int hits; - struct threshold_s *next; -} threshold_t; -/* }}} */ - -/* - * Private (static) variables - * {{{ */ -static c_avl_tree_t *threshold_tree = NULL; -static pthread_mutex_t threshold_lock = PTHREAD_MUTEX_INITIALIZER; -/* }}} */ +#include "utils_threshold.h" /* * Threshold management @@ -72,31 +37,6 @@ static pthread_mutex_t threshold_lock = PTHREAD_MUTEX_INITIALIZER; * The following functions add, delete, search, etc. configured thresholds to * the underlying AVL trees. */ -/* - * threshold_t *threshold_get - * - * Retrieve one specific threshold configuration. For looking up a threshold - * matching a value_list_t, see "threshold_search" below. Returns NULL if the - * specified threshold doesn't exist. - */ -static threshold_t *threshold_get (const char *hostname, - const char *plugin, const char *plugin_instance, - const char *type, const char *type_instance) -{ /* {{{ */ - char name[6 * DATA_MAX_NAME_LEN]; - threshold_t *th = NULL; - - format_name (name, sizeof (name), - (hostname == NULL) ? "" : hostname, - (plugin == NULL) ? "" : plugin, plugin_instance, - (type == NULL) ? "" : type, type_instance); - name[sizeof (name) - 1] = '\0'; - - if (c_avl_get (threshold_tree, name, (void *) &th) == 0) - return (th); - else - return (NULL); -} /* }}} threshold_t *threshold_get */ /* * int ut_threshold_add @@ -128,7 +68,7 @@ static int ut_threshold_add (const threshold_t *th) return (-1); } - th_copy = (threshold_t *) malloc (sizeof (threshold_t)); + th_copy = malloc (sizeof (*th_copy)); if (th_copy == NULL) { sfree (name_copy); @@ -136,7 +76,6 @@ static int ut_threshold_add (const threshold_t *th) return (-1); } memcpy (th_copy, th, sizeof (threshold_t)); - th_ptr = NULL; DEBUG ("ut_threshold_add: Adding entry `%s'", name); @@ -171,58 +110,6 @@ static int ut_threshold_add (const threshold_t *th) return (status); } /* }}} int ut_threshold_add */ -/* - * threshold_t *threshold_search - * - * Searches for a threshold configuration using all the possible variations of - * "Host", "Plugin" and "Type" blocks. Returns NULL if no threshold could be - * found. - * XXX: This is likely the least efficient function in collectd. - */ -static threshold_t *threshold_search (const value_list_t *vl) -{ /* {{{ */ - threshold_t *th; - - if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, vl->plugin, NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, "", NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get (vl->host, "", NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", vl->plugin, NULL, - vl->type, NULL)) != NULL) - return (th); - else if ((th = threshold_get ("", "", NULL, - vl->type, vl->type_instance)) != NULL) - return (th); - else if ((th = threshold_get ("", "", NULL, - vl->type, NULL)) != NULL) - return (th); - - return (NULL); -} /* }}} threshold_t *threshold_search */ - /* * Configuration * ============= @@ -329,7 +216,6 @@ static int ut_config_type_hysteresis (threshold_t *th, oconfig_item_t *ci) static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci) { - int i; threshold_t th; int status = 0; @@ -358,7 +244,7 @@ static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci) th.hysteresis = 0; th.flags = UT_FLAG_INTERESTING; /* interesting by default */ - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -423,7 +309,6 @@ static int ut_config_plugin_instance (threshold_t *th, oconfig_item_t *ci) static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci) { - int i; threshold_t th; int status = 0; @@ -445,7 +330,7 @@ static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci) memcpy (&th, th_orig, sizeof (th)); sstrncpy (th.plugin, ci->values[0].value.string, sizeof (th.plugin)); - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -469,7 +354,6 @@ static int ut_config_plugin (const threshold_t *th_orig, oconfig_item_t *ci) static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci) { - int i; threshold_t th; int status = 0; @@ -491,7 +375,7 @@ static int ut_config_host (const threshold_t *th_orig, oconfig_item_t *ci) memcpy (&th, th_orig, sizeof (th)); sstrncpy (th.host, ci->values[0].value.string, sizeof (th.host)); - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -624,7 +508,10 @@ static int ut_report_state (const data_set_t *ds, if (state_old == STATE_MISSING) ssnprintf (buf, bufsize, ": Value is no longer missing."); else - ssnprintf (buf, bufsize, ": All data sources are within range again."); + ssnprintf (buf, bufsize, + ": All data sources are within range again. " + "Current value of \"%s\" is %f.", + ds->ds[ds_index].name, values[ds_index]); } else { @@ -660,10 +547,9 @@ static int ut_report_state (const data_set_t *ds, { gauge_t value; gauge_t sum; - int i; sum = 0.0; - for (i = 0; i < vl->values_len; i++) + for (size_t i = 0; i < vl->values_len; i++) { if (isnan (values[i])) continue; @@ -738,23 +624,40 @@ static int ut_check_one_data_source (const data_set_t *ds, /* XXX: This is an experimental code, not optimized, not fast, not reliable, * and probably, do not work as you expect. Enjoy! :D */ - if ( (th->hysteresis > 0) && ((prev_state = uc_get_state(ds,vl)) != STATE_OKAY) ) - { - switch(prev_state) + if (th->hysteresis > 0) + { + prev_state = uc_get_state(ds,vl); + /* The purpose of hysteresis is elliminating flapping state when the value + * oscilates around the thresholds. In other words, what is important is + * the previous state; if the new value would trigger a transition, make + * sure that we artificially widen the range which is considered to apply + * for the previous state, and only trigger the notification if the value + * is outside of this expanded range. + * + * There is no hysteresis for the OKAY state. + * */ + gauge_t hysteresis_for_warning = 0, hysteresis_for_failure = 0; + switch (prev_state) { case STATE_ERROR: - if ( (!isnan (th->failure_min) && ((th->failure_min + th->hysteresis) < values[ds_index])) || - (!isnan (th->failure_max) && ((th->failure_max - th->hysteresis) > values[ds_index])) ) - return (STATE_OKAY); - else - is_failure++; + hysteresis_for_failure = th->hysteresis; + break; case STATE_WARNING: - if ( (!isnan (th->warning_min) && ((th->warning_min + th->hysteresis) < values[ds_index])) || - (!isnan (th->warning_max) && ((th->warning_max - th->hysteresis) > values[ds_index])) ) - return (STATE_OKAY); - else - is_warning++; - } + hysteresis_for_warning = th->hysteresis; + break; + case STATE_OKAY: + /* do nothing -- the hysteresis only applies to the non-normal states */ + break; + } + + if ((!isnan (th->failure_min) && (th->failure_min + hysteresis_for_failure > values[ds_index])) + || (!isnan (th->failure_max) && (th->failure_max - hysteresis_for_failure < values[ds_index]))) + is_failure++; + + if ((!isnan (th->warning_min) && (th->warning_min + hysteresis_for_warning > values[ds_index])) + || (!isnan (th->warning_max) && (th->warning_max - hysteresis_for_warning < values[ds_index]))) + is_warning++; + } else { /* no hysteresis */ if ((!isnan (th->failure_min) && (th->failure_min > values[ds_index])) @@ -764,7 +667,7 @@ static int ut_check_one_data_source (const data_set_t *ds, if ((!isnan (th->warning_min) && (th->warning_min > values[ds_index])) || (!isnan (th->warning_max) && (th->warning_max < values[ds_index]))) is_warning++; - } + } if (is_failure != 0) return (STATE_ERROR); @@ -791,7 +694,6 @@ static int ut_check_one_threshold (const data_set_t *ds, { /* {{{ */ int ret = -1; int ds_index = -1; - int i; gauge_t values_copy[ds->ds_num]; memcpy (values_copy, values, sizeof (values_copy)); @@ -810,7 +712,7 @@ static int ut_check_one_threshold (const data_set_t *ds, } /* Prepare `sum' and `num'. */ - for (i = 0; i < ds->ds_num; i++) + for (size_t i = 0; i < ds->ds_num; i++) if (!isnan (values[i])) { num++; @@ -820,17 +722,17 @@ static int ut_check_one_threshold (const data_set_t *ds, if ((num == 0) /* All data sources are undefined. */ || (sum == 0.0)) /* Sum is zero, cannot calculate percentage. */ { - for (i = 0; i < ds->ds_num; i++) + for (size_t i = 0; i < ds->ds_num; i++) values_copy[i] = NAN; } else /* We can actually calculate the percentage. */ { - for (i = 0; i < ds->ds_num; i++) + for (size_t i = 0; i < ds->ds_num; i++) values_copy[i] = 100.0 * values[i] / sum; } } /* if (UT_FLAG_PERCENTAGE) */ - for (i = 0; i < ds->ds_num; i++) + for (size_t i = 0; i < ds->ds_num; i++) { int status; @@ -853,7 +755,7 @@ static int ut_check_one_threshold (const data_set_t *ds, * * Gets a list of matching thresholds and searches for the worst status by one * of the thresholds. Then reports that status using the ut_report_state - * function above. + * function above. * Returns zero on success and if no threshold has been configured. Returns * less than zero on failure. */ @@ -960,15 +862,12 @@ static int ut_missing (const value_list_t *vl, static int ut_config (oconfig_item_t *ci) { /* {{{ */ - int i; int status = 0; int old_size = c_avl_size (threshold_tree); - threshold_t th; - if (threshold_tree == NULL) { - threshold_tree = c_avl_create ((void *) strcmp); + threshold_tree = c_avl_create ((int (*) (const void *, const void *)) strcmp); if (threshold_tree == NULL) { ERROR ("ut_config: c_avl_create failed."); @@ -976,17 +875,15 @@ static int ut_config (oconfig_item_t *ci) } } - memset (&th, '\0', sizeof (th)); - th.warning_min = NAN; - th.warning_max = NAN; - th.failure_min = NAN; - th.failure_max = NAN; + threshold_t th = { + .warning_min = NAN, + .warning_max = NAN, + .failure_min = NAN, + .failure_max = NAN, + .flags = UT_FLAG_INTERESTING /* interesting by default */ + }; - th.hits = 0; - th.hysteresis = 0; - th.flags = UT_FLAG_INTERESTING; /* interesting by default */ - - for (i = 0; i < ci->children_num; i++) + for (int i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i;