]> arthur.barton.de Git - netdata.git/commitdiff
context index converted to family index; alarm.sh now knows the total time an alarm...
authorCosta Tsaousis <costa@tsaousis.gr>
Sat, 20 Aug 2016 18:17:08 +0000 (21:17 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Sat, 20 Aug 2016 18:17:08 +0000 (21:17 +0300)
plugins.d/alarm.sh
src/health.c
src/health.h
src/rrd.c
src/rrd.h

index b789295cb76c1a42b25ecd01afb38153819f01b2..f31bd42003cb3b3da902377de1d524915687a375 100755 (executable)
@@ -29,6 +29,7 @@ value="${5}"      # the current value
 old_value="${6}"  # the previous value
 src="${7}"        # the line number and file the alarm has been configured
 duration="${8}"   # the duration in seconds the previous state took
+non_clear_duration="${9}" # the total duration in seconds this is non-clear
 
 # get the system hostname
 hostname="$(hostname)"
@@ -84,7 +85,7 @@ duration4human() {
 }
 
 severity="${status}"
-raised_for="<br/>(was in ${old_status,,} for $(duration4human ${duration}))"
+raised_for="<br/>(was ${old_status,,} for $(duration4human ${duration}))"
 status_message="status unknown"
 color="grey"
 alarm="${name} = ${value}"
@@ -124,14 +125,26 @@ then
 elif [ "${status}" = "CLEAR" ]
 then
     severity="Recovered from ${old_status}"
+    if [ $non_clear_duration > $duration ]
+    then
+        raised_for="<br/>(had issues for $(duration4human ${non_clear_duration}))"
+    fi
 
 elif [ "${old_status}" = "WARNING" -a "${status}" = "CRITICAL" ]
 then
     severity="Escalated to ${status}"
+    if [ $non_clear_duration > $duration ]
+    then
+        raised_for="<br/>(has issues for $(duration4human ${non_clear_duration}))"
+    fi
 
 elif [ "${old_status}" = "CRITICAL" -a "${status}" = "WARNING" ]
 then
     severity="Demoted to ${status}"
+    if [ $non_clear_duration > $duration ]
+    then
+        raised_for="<br/>(has issues for $(duration4human ${non_clear_duration}))"
+    fi
 
 else
     raised_for=
index 9c685a0ccfbde04445d3a803d1b6d1e76b87f72b..3a4932ae5de9edc8bb7f0efa9ff8251315e04807 100644 (file)
@@ -156,7 +156,7 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal
         return 1;
     }
 
-    rv = rrdvar_index_find(&st->rrdcontext->variables_root_index, variable, hash);
+    rv = rrdvar_index_find(&st->rrdfamily->variables_root_index, variable, hash);
     if(rv) {
         *result = rrdvar2number(rv);
         return 1;
@@ -171,8 +171,8 @@ int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, cal
     debug(D_HEALTH, "Available local chart '%s' variables:", st->id);
     avl_traverse_lock(&st->variables_root_index, dump_variable);
 
-    debug(D_HEALTH, "Available context '%s' variables:", st->rrdcontext->id);
-    avl_traverse_lock(&st->rrdcontext->variables_root_index, dump_variable);
+    debug(D_HEALTH, "Available context '%s' variables:", st->rrdfamily->family);
+    avl_traverse_lock(&st->rrdfamily->variables_root_index, dump_variable);
 
     debug(D_HEALTH, "Available host '%s' variables:", st->rrdhost->hostname);
     avl_traverse_lock(&st->rrdhost->variables_root_index, dump_variable);
@@ -202,9 +202,9 @@ RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, int type, void *va
     rs->rrdset = st;
 
     rs->local        = rrdvar_create_and_index("local",   &st->variables_root_index, rs->variable, rs->type, rs->value);
-    rs->context      = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullid, rs->type, rs->value);
+    rs->context      = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rs->fullid, rs->type, rs->value);
     rs->host         = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullid, rs->type, rs->value);
-    rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->type, rs->value);
+    rs->context_name = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rs->fullname, rs->type, rs->value);
     rs->host_name    = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullname, rs->type, rs->value);
 
     rs->next = st->variables;
@@ -229,12 +229,12 @@ void rrdsetvar_rename_all(RRDSET *st) {
 
         if (strcmp(buffer, rs->fullname)) {
             // name changed
-            rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rs->context_name);
+            rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->context_name);
             rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_name);
 
             freez(rs->fullname);
             rs->fullname = strdupz(st->name);
-            rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->fullname, rs->type, rs->value);
+            rs->context_name = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rs->fullname, rs->type, rs->value);
             rs->host_name    = rrdvar_create_and_index("host",    &st->rrdhost->variables_root_index, rs->fullname, rs->type, rs->value);
         }
     }
@@ -247,9 +247,9 @@ void rrdsetvar_free(RRDSETVAR *rs) {
     debug(D_VARIABLES, "RRDSETVAR free for chart id '%s' name '%s', variable '%s'", st->id, st->name, rs->variable);
 
     rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local);
-    rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rs->context);
+    rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->context);
     rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host);
-    rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rs->context_name);
+    rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->context_name);
     rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_name);
 
     if(st->variables == rs) {
@@ -313,8 +313,8 @@ RRDDIMVAR *rrddimvar_create(RRDDIM *rd, int type, const char *prefix, const char
     rs->local_id     = rrdvar_create_and_index("local",   &st->variables_root_index, rs->id, rs->type, rs->value);
     rs->local_name   = rrdvar_create_and_index("local",   &st->variables_root_index, rs->name, rs->type, rs->value);
 
-    rs->context_id   = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->id, rs->type, rs->value);
-    rs->context_name = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rs->name, rs->type, rs->value);
+    rs->context_id   = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rs->id, rs->type, rs->value);
+    rs->context_name = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rs->name, rs->type, rs->value);
 
     rs->host_fullidid     = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidid, rs->type, rs->value);
     rs->host_fullidname   = rrdvar_create_and_index("host", &st->rrdhost->variables_root_index, rs->fullidname, rs->type, rs->value);
@@ -380,8 +380,8 @@ void rrddimvar_free(RRDDIMVAR *rs) {
     rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local_id);
     rrdvar_free(st->rrdhost, &st->variables_root_index, rs->local_name);
 
-    rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rs->context_id);
-    rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rs->context_name);
+    rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->context_id);
+    rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rs->context_name);
 
     rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullidid);
     rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rs->host_fullidname);
@@ -426,7 +426,7 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
         st->red = rc->red;
 
     rc->local    = rrdvar_create_and_index("local", &st->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
-    rc->context  = rrdvar_create_and_index("context", &st->rrdcontext->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
+    rc->context  = rrdvar_create_and_index("context", &st->rrdfamily->variables_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
 
     char fullname[RRDVAR_MAX_LENGTH + 1];
     snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name);
@@ -485,7 +485,7 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) {
     rrdvar_free(st->rrdhost, &st->variables_root_index, rc->local);
     rc->local = NULL;
 
-    rrdvar_free(st->rrdhost, &st->rrdcontext->variables_root_index, rc->context);
+    rrdvar_free(st->rrdhost, &st->rrdfamily->variables_root_index, rc->context);
     rc->context = NULL;
 
     rrdvar_free(st->rrdhost, &st->rrdhost->variables_root_index, rc->hostid);
@@ -1446,7 +1446,7 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
     const char *exec = ae->exec;
     if(!exec) exec = health_default_exec;
 
-    snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u'",
+    snprintfz(buffer, FILENAME_MAX, "exec %s '%s' '%s' '%s' '%s' '%0.0Lf' '%0.0Lf' '%s' '%u' '%u'",
               exec,
               ae->name,
               ae->chart?ae->chart:"NOCAHRT",
@@ -1455,7 +1455,8 @@ static inline void health_alarm_execute(ALARM_ENTRY *ae) {
               ae->new_value,
               ae->old_value,
               ae->source?ae->source:"UNKNOWN",
-              (uint32_t)ae->duration
+              (uint32_t)ae->duration,
+              (uint32_t)ae->non_clear_duration
     );
 
     debug(D_HEALTH, "executing command '%s'", buffer);
@@ -1510,6 +1511,9 @@ static inline void health_alarm_log(time_t when,
     ae->new_status = new_status;
     ae->duration = duration;
 
+    if(ae->old_status == RRDCALC_STATUS_WARNING || ae->old_status == RRDCALC_STATUS_CRITICAL)
+        ae->non_clear_duration += ae->duration;
+
     // link it
     ae->next = health_log.alarms;
     health_log.alarms = ae;
@@ -1523,8 +1527,19 @@ static inline void health_alarm_log(time_t when,
                 t->hash_chart == ae->hash_chart &&
                 !strcmp(t->name, ae->name) &&
                 t->chart && ae->chart && !strcmp(t->chart, ae->chart)) {
-            t->notifications |= HEALTH_ENTRY_NOTIFICATIONS_UPDATED;
-            t->updated_by = ae;
+
+            if(!(t->notifications & HEALTH_ENTRY_NOTIFICATIONS_UPDATED) && !t->updated_by) {
+                t->notifications |= HEALTH_ENTRY_NOTIFICATIONS_UPDATED;
+                t->updated_by = ae;
+
+                if((t->new_status == RRDCALC_STATUS_WARNING || t->new_status == RRDCALC_STATUS_CRITICAL) &&
+                   (t->old_status == RRDCALC_STATUS_WARNING || t->old_status == RRDCALC_STATUS_CRITICAL))
+                    ae->non_clear_duration += t->non_clear_duration;
+            }
+            else {
+                // no need to continue
+                break;
+            }
         }
     }
 }
index 3af3faff466761bf101bbe99e04102b76e7fdb53..1b2aa5e25352824e89083e803b7f21d0b8c4f6bb 100644 (file)
@@ -13,7 +13,7 @@ extern int rrdvar_compare(void *a, void *b);
 // the variables as stored in the variables indexes
 // there are 3 indexes:
 // 1. at each chart   (RRDSET.variables_root_index)
-// 2. at each context (RRDCONTEXT.variables_root_index)
+// 2. at each context (RRDFAMILY.variables_root_index)
 // 3. at each host    (RRDHOST.variables_root_index)
 typedef struct rrdvar {
     avl avl;
@@ -214,6 +214,7 @@ typedef struct alarm_entry {
 
     time_t when;
     time_t duration;
+    time_t non_clear_duration;
 
     char *name;
     uint32_t hash_name;
index eb6ef24f0bbe94933d95219291c3a91553e15775..a83af003ec324f2ad94b9e8910643c0f5ed1cc7a 100644 (file)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -16,7 +16,7 @@ int rrd_memory_mode = RRD_MEMORY_MODE_SAVE;
 
 static int rrdset_compare(void* a, void* b);
 static int rrdset_compare_name(void* a, void* b);
-static int rrdcontext_compare(void* a, void* b);
+static int rrdfamily_compare(void *a, void *b);
 
 // ----------------------------------------------------------------------------
 // RRDHOST
@@ -33,8 +33,8 @@ RRDHOST localhost = {
             { NULL, rrdset_compare_name },
             AVL_LOCK_INITIALIZER
         },
-        .rrdcontext_root_index = {
-            { NULL, rrdcontext_compare },
+        .rrdfamily_root_index = {
+            { NULL, rrdfamily_compare },
             AVL_LOCK_INITIALIZER
         },
         .variables_root_index = {
@@ -70,56 +70,56 @@ void rrdhost_check_wrlock_int(RRDHOST *host, const char *file, const char *funct
 }
 
 // ----------------------------------------------------------------------------
-// RRDCONTEXT index
+// RRDFAMILY index
 
-static int rrdcontext_compare(void* a, void* b) {
-    if(((RRDCONTEXT *)a)->hash < ((RRDCONTEXT *)b)->hash) return -1;
-    else if(((RRDCONTEXT *)a)->hash > ((RRDCONTEXT *)b)->hash) return 1;
-    else return strcmp(((RRDCONTEXT *)a)->id, ((RRDCONTEXT *)b)->id);
+static int rrdfamily_compare(void *a, void *b) {
+    if(((RRDFAMILY *)a)->hash_family < ((RRDFAMILY *)b)->hash_family) return -1;
+    else if(((RRDFAMILY *)a)->hash_family > ((RRDFAMILY *)b)->hash_family) return 1;
+    else return strcmp(((RRDFAMILY *)a)->family, ((RRDFAMILY *)b)->family);
 }
 
-#define rrdcontext_index_add(host, rc) (RRDCONTEXT *)avl_insert_lock(&((host)->rrdcontext_root_index), (avl *)(rc))
-#define rrdcontext_index_del(host, rc) (RRDCONTEXT *)avl_remove_lock(&((host)->rrdcontext_root_index), (avl *)(rc))
+#define rrdfamily_index_add(host, rc) (RRDFAMILY *)avl_insert_lock(&((host)->rrdfamily_root_index), (avl *)(rc))
+#define rrdfamily_index_del(host, rc) (RRDFAMILY *)avl_remove_lock(&((host)->rrdfamily_root_index), (avl *)(rc))
 
-static RRDCONTEXT *rrdcontext_index_find(RRDHOST *host, const char *id, uint32_t hash) {
-    RRDCONTEXT tmp;
-    tmp.id = id;
-    tmp.hash = (hash)?hash:simple_hash(tmp.id);
+static RRDFAMILY *rrdfamily_index_find(RRDHOST *host, const char *id, uint32_t hash) {
+    RRDFAMILY tmp;
+    tmp.family = id;
+    tmp.hash_family = (hash)?hash:simple_hash(tmp.family);
 
-    return (RRDCONTEXT *)avl_search_lock(&(host->rrdcontext_root_index), (avl *) &tmp);
+    return (RRDFAMILY *)avl_search_lock(&(host->rrdfamily_root_index), (avl *) &tmp);
 }
 
-RRDCONTEXT *rrdcontext_create(const char *id) {
-    RRDCONTEXT *rc = rrdcontext_index_find(&localhost, id, 0);
+RRDFAMILY *rrdfamily_create(const char *id) {
+    RRDFAMILY *rc = rrdfamily_index_find(&localhost, id, 0);
     if(!rc) {
-        rc = callocz(1, sizeof(RRDCONTEXT));
+        rc = callocz(1, sizeof(RRDFAMILY));
 
-        rc->id = strdupz(id);
-        rc->hash = simple_hash(rc->id);
+        rc->family = strdupz(id);
+        rc->hash_family = simple_hash(rc->family);
 
         // initialize the variables index
         avl_init_lock(&rc->variables_root_index, rrdvar_compare);
 
-        RRDCONTEXT *ret = rrdcontext_index_add(&localhost, rc);
+        RRDFAMILY *ret = rrdfamily_index_add(&localhost, rc);
         if(ret != rc)
-            fatal("INTERNAL ERROR: Expected to INSERT RRDCONTEXT '%s' into index, but inserted '%s'.", rc->id, (ret)?ret->id:"NONE");
+            fatal("INTERNAL ERROR: Expected to INSERT RRDFAMILY '%s' into index, but inserted '%s'.", rc->family, (ret)?ret->family:"NONE");
     }
 
     rc->use_count++;
     return rc;
 }
 
-void rrdcontext_free(RRDCONTEXT *rc) {
+void rrdfamily_free(RRDFAMILY *rc) {
     rc->use_count--;
     if(!rc->use_count) {
-        RRDCONTEXT *ret = rrdcontext_index_del(&localhost, rc);
+        RRDFAMILY *ret = rrdfamily_index_del(&localhost, rc);
         if(ret != rc)
-            fatal("INTERNAL ERROR: Expected to DELETE RRDCONTEXT '%s' from index, but deleted '%s'.", rc->id, (ret)?ret->id:"NONE");
+            fatal("INTERNAL ERROR: Expected to DELETE RRDFAMILY '%s' from index, but deleted '%s'.", rc->family, (ret)?ret->family:"NONE");
 
         if(rc->variables_root_index.avl_tree.root != NULL)
-            fatal("INTERNAL ERROR: Variables index of RRDCONTEXT '%s' that is freed, is not empty.", rc->id);
+            fatal("INTERNAL ERROR: Variables index of RRDFAMILY '%s' that is freed, is not empty.", rc->family);
 
-        freez((void *)rc->id);
+        freez((void *)rc->family);
         freez(rc);
     }
 }
@@ -547,7 +547,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
         st->title = config_get(st->id, "title", varvalue);
     }
 
-    st->rrdcontext = rrdcontext_create(st->context);
+    st->rrdfamily = rrdfamily_create(st->family);
     st->rrdhost = &localhost;
 
     st->next = localhost.rrdset_root;
@@ -779,9 +779,9 @@ void rrdset_free_all(void)
 
         rrdset_index_del(&localhost, st);
 
-        st->rrdcontext->use_count--;
-        if(!st->rrdcontext->use_count)
-            rrdcontext_free(st->rrdcontext);
+        st->rrdfamily->use_count--;
+        if(!st->rrdfamily->use_count)
+            rrdfamily_free(st->rrdfamily);
 
         pthread_rwlock_unlock(&st->rwlock);
 
index 0fd2d4567d1fac1da6e2129ae03c7700aa41c70f..4c894344820f45178cfdcffbc4b87c2540e3f922 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -78,17 +78,17 @@ extern const char *rrddim_algorithm_name(int chart_type);
 // ----------------------------------------------------------------------------
 // RRD CONTEXT
 
-struct rrdcontext {
+struct rrdfamily {
     avl avl;
 
-    const char *id;
-    uint32_t hash;
+    const char *family;
+    uint32_t hash_family;
 
     size_t use_count;
 
     avl_tree_lock variables_root_index;
 };
-typedef struct rrdcontext RRDCONTEXT;
+typedef struct rrdfamily RRDFAMILY;
 
 // ----------------------------------------------------------------------------
 // RRD DIMENSION
@@ -252,7 +252,7 @@ struct rrdset {
     total_number collected_total;                   // used internally to calculate percentages
     total_number last_collected_total;              // used internally to calculate percentages
 
-    RRDCONTEXT *rrdcontext;
+    RRDFAMILY *rrdfamily;
     struct rrdhost *rrdhost;
 
     struct rrdset *next;                            // linking of rrdsets
@@ -297,7 +297,7 @@ struct rrdhost {
     avl_tree_lock rrdset_root_index;
     avl_tree_lock rrdset_root_index_name;
 
-    avl_tree_lock rrdcontext_root_index;
+    avl_tree_lock rrdfamily_root_index;
     avl_tree_lock variables_root_index;
 
     // all RRDCALCs are primarily allocated and linked here