From: Andrés J. Díaz Date: Mon, 6 Jul 2009 15:53:03 +0000 (+0200) Subject: src/utils_threshold.c: Percentage support in thresholds X-Git-Tag: collectd-4.8.0~84 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=f49370d16f2b7f1bb9bdf5c6ebc990827c657801 src/utils_threshold.c: Percentage support in thresholds Hi all! I attach a patch to add percentage support in thresholds, like this example: WarningMax 90 Percentage true The percentage option works like collectd-nagios, that is, calculate the percentage of the value of the first DS over the total. For df plugin, for example, calculate the percentage of the "used" DS. Bugs and suggestions are welcome :) Enjoy! Regards, Andres --- diff --git a/src/utils_threshold.c b/src/utils_threshold.c index 03a3f2d4..083a0185 100644 --- a/src/utils_threshold.c +++ b/src/utils_threshold.c @@ -33,6 +33,7 @@ * {{{ */ #define UT_FLAG_INVERT 0x01 #define UT_FLAG_PERSIST 0x02 +#define UT_FLAG_PERCENTAGE 0x04 typedef struct threshold_s { @@ -262,6 +263,24 @@ static int ut_config_type_persist (threshold_t *th, oconfig_item_t *ci) return (0); } /* int ut_config_type_persist */ +static int ut_config_type_percentage(threshold_t *th, oconfig_item_t *ci) +{ + if ((ci->values_num != 1) + || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN)) + { + WARNING ("threshold values: The `Percentage' option needs exactly one " + "boolean argument."); + return (-1); + } + + if (ci->values[0].value.boolean) + th->flags |= UT_FLAG_PERCENTAGE; + else + th->flags &= ~UT_FLAG_PERCENTAGE; + + return (0); +} /* int ut_config_type_percentage */ + static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci) { int i; @@ -309,6 +328,8 @@ static int ut_config_type (const threshold_t *th_orig, oconfig_item_t *ci) status = ut_config_type_invert (&th, option); else if (strcasecmp ("Persist", option->key) == 0) status = ut_config_type_persist (&th, option); + else if (strcasecmp ("Percentage", option->key) == 0) + status = ut_config_type_percentage (&th, option); else { WARNING ("threshold values: Option `%s' not allowed inside a `Type' " @@ -467,7 +488,7 @@ int ut_config (const oconfig_item_t *ci) th.warning_max = NAN; th.failure_min = NAN; th.failure_max = NAN; - + for (i = 0; i < ci->children_num; i++) { oconfig_item_t *option = ci->children + i; @@ -644,29 +665,32 @@ static int ut_report_state (const data_set_t *ds, if (!isnan (min) && !isnan (max)) { status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently " - "%f. That is within the %s region of %f and %f.", + "%f. That is within the %s region of %f and %f%s.", ds->ds[ds_index].name, values[ds_index], (state == STATE_ERROR) ? "failure" : "warning", - min, max); + min, max, + ((th->flags & UT_FLAG_PERCENTAGE) == UT_FLAG_PERCENTAGE) ? "%" : "" ); } else { status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently " - "%f. That is %s the %s threshold of %f.", + "%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", - isnan (min) ? max : min); + isnan (min) ? max : min, + ((th->flags & UT_FLAG_PERCENTAGE) == UT_FLAG_PERCENTAGE) ? "%" : "" ); } } else /* is not inverted */ { status = ssnprintf (buf, bufsize, ": Data source \"%s\" is currently " - "%f. That is %s the %s threshold of %f.", + "%f. That is %s the %s threshold of %f%s.", ds->ds[ds_index].name, values[ds_index], (values[ds_index] < min) ? "below" : "above", (state == STATE_ERROR) ? "failure" : "warning", - (values[ds_index] < min) ? min : max); + (values[ds_index] < min) ? min : max, + ((th->flags & UT_FLAG_PERCENTAGE) == UT_FLAG_PERCENTAGE) ? "%" : "" ); } buf += status; bufsize -= status; @@ -699,10 +723,13 @@ static int ut_check_one_data_source (const data_set_t *ds, int is_failure = 0; /* check if this threshold applies to this data source */ - ds_name = ds->ds[ds_index].name; - if ((th->data_source[0] != 0) - && (strcmp (ds_name, th->data_source) != 0)) - return (STATE_OKAY); + 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); + } if ((th->flags & UT_FLAG_INVERT) != 0) { @@ -743,6 +770,30 @@ static int ut_check_one_threshold (const data_set_t *ds, int ds_index = -1; int i; + if ((th->flags & UT_FLAG_PERCENTAGE) == UT_FLAG_PERCENTAGE) + { + + gauge_t sum=0.0; + gauge_t percentage; + + for (i = 0; i < ds->ds_num; i++) + if (!isnan (values[i])) + sum += values[i]; + + if (sum == 0.0) + { + WARNING ("Values sum for percentage seems up to zero"); + return(STATE_WARNING); + } + + percentage = 100.0 * values[0] / sum; + + if (ret_ds_index != NULL) + *ret_ds_index = 0; + + return ut_check_one_data_source (NULL, vl, th, &percentage, 0); + } + for (i = 0; i < ds->ds_num; i++) { int status;