Add a new UNKNOWN state as the initial state of metrics
authorLuis Fernández Álvarez <luis.fernandez.alvarez@cern.ch>
Wed, 24 Oct 2018 13:49:35 +0000 (15:49 +0200)
committerLuis Fernández Álvarez <luis.fernandez.alvarez@cern.ch>
Mon, 29 Oct 2018 16:49:11 +0000 (17:49 +0100)
* UNKNOWN becomes the default state of the metrics.
* States are renumbered so UNKNOWN is lower than OKAY and the threshold
evaluation logic is consistent.
* If an invalid datasource is set in a threshold it will resolve to
UNKNOWN.

src/daemon/utils_cache.c
src/daemon/utils_cache.h
src/threshold.c
src/write_riemann_threshold.c

index 610c11e..e09b099 100644 (file)
@@ -201,7 +201,7 @@ static int uc_insert(const data_set_t *ds, const value_list_t *vl,
   ce->last_time = vl->time;
   ce->last_update = cdtime();
   ce->interval = vl->interval;
-  ce->state = STATE_OKAY;
+  ce->state = STATE_UNKNOWN;
 
   if (c_avl_insert(cache_tree, key_copy, ce) != 0) {
     sfree(key_copy);
index 7200906..d3ea936 100644 (file)
 
 #include "plugin.h"
 
-#define STATE_OKAY 0
-#define STATE_WARNING 1
-#define STATE_ERROR 2
+#define STATE_UNKNOWN 0
+#define STATE_OKAY 1
+#define STATE_WARNING 2
+#define STATE_ERROR 3
 #define STATE_MISSING 15
 
 int uc_init(void);
index 79300f1..9d34363 100644 (file)
@@ -309,7 +309,10 @@ 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)
+    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;
@@ -367,6 +370,10 @@ static int ut_report_state(const data_set_t *ds, const value_list_t *vl,
       snprintf(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;
@@ -455,7 +462,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) {
@@ -484,6 +491,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;
@@ -525,7 +533,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,
index 35f3814..9d8267d 100644 (file)
@@ -63,7 +63,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) {
@@ -73,8 +73,9 @@ static int ut_check_one_data_source(
 
   /* 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)) {
+  prev_state = uc_get_state(ds, vl);
+  if ((th->hysteresis > 0) && (prev_state != STATE_OKAY) &&
+      (prev_state != STATE_UNKNOWN)) {
     switch (prev_state) {
     case STATE_ERROR:
       if ((!isnan(th->failure_min) &&