X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Fthreshold.c;h=e74dfc2ca2587001642f3cc13ca5b2bdb856eba5;hp=a4a999f571ee899c056df0ef0396b4619deece54;hb=54619dc85fd308b21ed09a0271e5c7383c7921b9;hpb=64b8150edec2271bb110f36e70915fdd87d9cac2 diff --git a/src/threshold.c b/src/threshold.c index a4a999f5..e74dfc2c 100644 --- a/src/threshold.c +++ b/src/threshold.c @@ -25,9 +25,9 @@ #include "collectd.h" -#include "common.h" #include "plugin.h" -#include "utils_avltree.h" +#include "utils/avltree/avltree.h" +#include "utils/common/common.h" #include "utils_cache.h" #include "utils_threshold.h" @@ -55,20 +55,20 @@ static int ut_threshold_add(const threshold_t *th) { /* {{{ */ if (format_name(name, sizeof(name), th->host, th->plugin, th->plugin_instance, th->type, th->type_instance) != 0) { ERROR("ut_threshold_add: format_name failed."); - return (-1); + return -1; } name_copy = strdup(name); if (name_copy == NULL) { ERROR("ut_threshold_add: strdup failed."); - return (-1); + return -1; } th_copy = malloc(sizeof(*th_copy)); if (th_copy == NULL) { sfree(name_copy); ERROR("ut_threshold_add: malloc failed."); - return (-1); + return -1; } memcpy(th_copy, th, sizeof(threshold_t)); @@ -100,7 +100,7 @@ static int ut_threshold_add(const threshold_t *th) { /* {{{ */ sfree(th_copy); } - return (status); + return status; } /* }}} int ut_threshold_add */ /* @@ -109,90 +109,6 @@ static int ut_threshold_add(const threshold_t *th) { /* {{{ */ * The following approximately two hundred functions are used to handle the * configuration and fill the threshold list. * {{{ */ -static int ut_config_type_datasource(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `DataSource' option needs exactly one " - "string argument."); - return (-1); - } - - sstrncpy(th->data_source, ci->values[0].value.string, - sizeof(th->data_source)); - - return (0); -} /* int ut_config_type_datasource */ - -static int ut_config_type_instance(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `Instance' option needs exactly one " - "string argument."); - return (-1); - } - - sstrncpy(th->type_instance, ci->values[0].value.string, - sizeof(th->type_instance)); - - return (0); -} /* int ut_config_type_instance */ - -static int ut_config_type_max(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return (-1); - } - - if (strcasecmp(ci->key, "WarningMax") == 0) - th->warning_max = ci->values[0].value.number; - else - th->failure_max = ci->values[0].value.number; - - return (0); -} /* int ut_config_type_max */ - -static int ut_config_type_min(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return (-1); - } - - if (strcasecmp(ci->key, "WarningMin") == 0) - th->warning_min = ci->values[0].value.number; - else - th->failure_min = ci->values[0].value.number; - - return (0); -} /* int ut_config_type_min */ - -static int ut_config_type_hits(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return (-1); - } - - th->hits = ci->values[0].value.number; - - return (0); -} /* int ut_config_type_hits */ - -static int ut_config_type_hysteresis(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_NUMBER)) { - WARNING("threshold values: The `%s' option needs exactly one " - "number argument.", - ci->key); - return (-1); - } - - th->hysteresis = ci->values[0].value.number; - - return (0); -} /* int ut_config_type_hysteresis */ - static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { threshold_t th; int status = 0; @@ -200,12 +116,12 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("threshold values: The `Type' block needs exactly one string " "argument."); - return (-1); + return -1; } if (ci->children_num < 1) { WARNING("threshold values: The `Type' block needs at least one option."); - return (-1); + return -1; } memcpy(&th, th_orig, sizeof(th)); @@ -223,15 +139,19 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { oconfig_item_t *option = ci->children + i; if (strcasecmp("Instance", option->key) == 0) - status = ut_config_type_instance(&th, option); + status = cf_util_get_string_buffer(option, th.type_instance, + sizeof(th.type_instance)); else if (strcasecmp("DataSource", option->key) == 0) - status = ut_config_type_datasource(&th, option); - else if ((strcasecmp("WarningMax", option->key) == 0) || - (strcasecmp("FailureMax", option->key) == 0)) - status = ut_config_type_max(&th, option); - else if ((strcasecmp("WarningMin", option->key) == 0) || - (strcasecmp("FailureMin", option->key) == 0)) - status = ut_config_type_min(&th, option); + status = cf_util_get_string_buffer(option, th.data_source, + sizeof(th.data_source)); + else if (strcasecmp("WarningMax", option->key) == 0) + status = cf_util_get_double(option, &th.warning_max); + else if (strcasecmp("FailureMax", option->key) == 0) + status = cf_util_get_double(option, &th.failure_max); + else if (strcasecmp("WarningMin", option->key) == 0) + status = cf_util_get_double(option, &th.warning_min); + else if (strcasecmp("FailureMin", option->key) == 0) + status = cf_util_get_double(option, &th.failure_min); else if (strcasecmp("Interesting", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_INTERESTING); else if (strcasecmp("Invert", option->key) == 0) @@ -243,9 +163,9 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { else if (strcasecmp("Percentage", option->key) == 0) status = cf_util_get_flag(option, &th.flags, UT_FLAG_PERCENTAGE); else if (strcasecmp("Hits", option->key) == 0) - status = ut_config_type_hits(&th, option); + status = cf_util_get_int(option, &th.hits); else if (strcasecmp("Hysteresis", option->key) == 0) - status = ut_config_type_hysteresis(&th, option); + status = cf_util_get_double(option, &th.hysteresis); else { WARNING("threshold values: Option `%s' not allowed inside a `Type' " "block.", @@ -261,22 +181,9 @@ static int ut_config_type(const threshold_t *th_orig, oconfig_item_t *ci) { status = ut_threshold_add(&th); } - return (status); + return status; } /* int ut_config_type */ -static int ut_config_plugin_instance(threshold_t *th, oconfig_item_t *ci) { - if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { - WARNING("threshold values: The `Instance' option needs exactly one " - "string argument."); - return (-1); - } - - sstrncpy(th->plugin_instance, ci->values[0].value.string, - sizeof(th->plugin_instance)); - - return (0); -} /* int ut_config_plugin_instance */ - static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { threshold_t th; int status = 0; @@ -284,13 +191,13 @@ static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("threshold values: The `Plugin' block needs exactly one string " "argument."); - return (-1); + return -1; } if (ci->children_num < 1) { WARNING("threshold values: The `Plugin' block needs at least one nested " "block."); - return (-1); + return -1; } memcpy(&th, th_orig, sizeof(th)); @@ -302,7 +209,8 @@ static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { if (strcasecmp("Type", option->key) == 0) status = ut_config_type(&th, option); else if (strcasecmp("Instance", option->key) == 0) - status = ut_config_plugin_instance(&th, option); + status = cf_util_get_string_buffer(option, th.plugin_instance, + sizeof(th.plugin_instance)); else { WARNING("threshold values: Option `%s' not allowed inside a `Plugin' " "block.", @@ -314,7 +222,7 @@ static int ut_config_plugin(const threshold_t *th_orig, oconfig_item_t *ci) { break; } - return (status); + return status; } /* int ut_config_plugin */ static int ut_config_host(const threshold_t *th_orig, oconfig_item_t *ci) { @@ -324,13 +232,13 @@ static int ut_config_host(const threshold_t *th_orig, oconfig_item_t *ci) { if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) { WARNING("threshold values: The `Host' block needs exactly one string " "argument."); - return (-1); + return -1; } if (ci->children_num < 1) { WARNING("threshold values: The `Host' block needs at least one nested " "block."); - return (-1); + return -1; } memcpy(&th, th_orig, sizeof(th)); @@ -354,11 +262,11 @@ static int ut_config_host(const threshold_t *th_orig, oconfig_item_t *ci) { break; } - return (status); + return status; } /* int ut_config_host */ - /* - * End of the functions used to configure threshold values. - */ +/* + * End of the functions used to configure threshold values. + */ /* }}} */ /* @@ -392,7 +300,7 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, DEBUG("ut_report_state: th->hits = %d, uc_get_hits = %d", th->hits, uc_get_hits(ds, vl)); (void)uc_inc_hits(ds, vl, 1); /* increase hit counter */ - return (0); + return 0; } } /* end check hits */ @@ -401,10 +309,13 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, /* If the state didn't change, report if `persistent' is specified. If the * state is `okay', then only report if `persist_ok` flag is set. */ if (state == state_old) { - if ((th->flags & UT_FLAG_PERSIST) == 0) - return (0); + if (state == STATE_UNKNOWN) { + /* From UNKNOWN to UNKNOWN. Persist doesn't apply here. */ + return 0; + } else if ((th->flags & UT_FLAG_PERSIST) == 0) + return 0; else if ((state == STATE_OKAY) && ((th->flags & UT_FLAG_PERSIST_OK) == 0)) - return (0); + return 0; } if (state != state_old) @@ -456,9 +367,14 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, if (state_old == STATE_MISSING) ssnprintf(buf, bufsize, ": Value is no longer missing."); else - ssnprintf(buf, bufsize, ": All data sources are within range again. " - "Current value of \"%s\" is %f.", + 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 if (state == STATE_UNKNOWN) { + ERROR("ut_report_state: metric transition to UNKNOWN from a different " + "state. This shouldn't happen."); + return 0; } else { double min; double max; @@ -476,8 +392,9 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "", max, ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : ""); } else { - ssnprintf(buf, bufsize, ": Data source \"%s\" is currently " - "%f. That is %s the %s threshold of %f%s.", + ssnprintf(buf, bufsize, + ": Data source \"%s\" is currently " + "%f. That is %s the %s threshold of %f%s.", ds->ds[ds_index].name, values[ds_index], isnan(min) ? "below" : "above", (state == STATE_ERROR) ? "failure" : "warning", @@ -510,8 +427,9 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, (value < min) ? min : max); } else /* is not inverted */ { - ssnprintf(buf, bufsize, ": Data source \"%s\" is currently " - "%f. That is %s the %s threshold of %f.", + ssnprintf(buf, bufsize, + ": Data source \"%s\" is currently " + "%f. That is %s the %s threshold of %f.", ds->ds[ds_index].name, values[ds_index], (values[ds_index] < min) ? "below" : "above", (state == STATE_ERROR) ? "failure" : "warning", @@ -522,7 +440,7 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl, plugin_dispatch_notification(&n); plugin_notification_meta_free(n.meta); - return (0); + return 0; } /* }}} int ut_report_state */ /* @@ -547,7 +465,7 @@ static int ut_check_one_data_source( if (ds != NULL) { ds_name = ds->ds[ds_index].name; if ((th->data_source[0] != 0) && (strcmp(ds_name, th->data_source) != 0)) - return (STATE_OKAY); + return STATE_UNKNOWN; } if ((th->flags & UT_FLAG_INVERT) != 0) { @@ -576,6 +494,7 @@ static int ut_check_one_data_source( case STATE_WARNING: hysteresis_for_warning = th->hysteresis; break; + case STATE_UNKNOWN: case STATE_OKAY: /* do nothing -- the hysteresis only applies to the non-normal states */ break; @@ -604,12 +523,12 @@ static int ut_check_one_data_source( } if (is_failure != 0) - return (STATE_ERROR); + return STATE_ERROR; if (is_warning != 0) - return (STATE_WARNING); + return STATE_WARNING; - return (STATE_OKAY); + return STATE_OKAY; } /* }}} int ut_check_one_data_source */ /* @@ -617,7 +536,8 @@ static int ut_check_one_data_source( * * Checks all data sources of a value list against the given threshold, using * the ut_check_one_data_source function above. Returns the worst status, - * which is `okay' if nothing has failed. + * which is `okay' if nothing has failed or `unknown' if no valid datasource was + * defined. * Returns less than zero if the data set doesn't have any data sources. */ static int ut_check_one_threshold(const data_set_t *ds, const value_list_t *vl, @@ -674,7 +594,7 @@ static int ut_check_one_threshold(const data_set_t *ds, const value_list_t *vl, if (ret_ds_index != NULL) *ret_ds_index = ds_index; - return (ret); + return ret; } /* }}} int ut_check_one_threshold */ /* @@ -698,7 +618,7 @@ static int ut_check_threshold(const data_set_t *ds, const value_list_t *vl, int worst_ds_index = -1; if (threshold_tree == NULL) - return (0); + return 0; /* Is this lock really necessary? So far, thresholds are only inserted at * startup. -octo */ @@ -706,13 +626,13 @@ static int ut_check_threshold(const data_set_t *ds, const value_list_t *vl, th = threshold_search(vl); pthread_mutex_unlock(&threshold_lock); if (th == NULL) - return (0); + return 0; DEBUG("ut_check_threshold: Found matching threshold(s)"); values = uc_get_rate(ds, vl); if (values == NULL) - return (0); + return 0; while (th != NULL) { int ds_index = -1; @@ -721,7 +641,7 @@ static int ut_check_threshold(const data_set_t *ds, const value_list_t *vl, if (status < 0) { ERROR("ut_check_threshold: ut_check_one_threshold failed."); sfree(values); - return (-1); + return -1; } if (worst_state < status) { @@ -738,12 +658,12 @@ static int ut_check_threshold(const data_set_t *ds, const value_list_t *vl, if (status != 0) { ERROR("ut_check_threshold: ut_report_state failed."); sfree(values); - return (-1); + return -1; } sfree(values); - return (0); + return 0; } /* }}} int ut_check_threshold */ /* @@ -760,12 +680,12 @@ static int ut_missing(const value_list_t *vl, cdtime_t now; if (threshold_tree == NULL) - return (0); + return 0; th = threshold_search(vl); /* dispatch notifications for "interesting" values only */ if ((th == NULL) || ((th->flags & UT_FLAG_INTERESTING) == 0)) - return (0); + return 0; now = cdtime(); missing_time = now - vl->time; @@ -779,7 +699,7 @@ static int ut_missing(const value_list_t *vl, plugin_dispatch_notification(&n); - return (0); + return 0; } /* }}} int ut_missing */ static int ut_config(oconfig_item_t *ci) { /* {{{ */ @@ -790,7 +710,7 @@ static int ut_config(oconfig_item_t *ci) { /* {{{ */ threshold_tree = c_avl_create((int (*)(const void *, const void *))strcmp); if (threshold_tree == NULL) { ERROR("ut_config: c_avl_create failed."); - return (-1); + return -1; } } @@ -828,7 +748,7 @@ static int ut_config(oconfig_item_t *ci) { /* {{{ */ /* user data = */ NULL); } - return (status); + return status; } /* }}} int um_config */ void module_register(void) {