summaryrefslogtreecommitdiffstats
path: root/database/rrdcalc.c
diff options
context:
space:
mode:
Diffstat (limited to 'database/rrdcalc.c')
-rw-r--r--database/rrdcalc.c104
1 files changed, 69 insertions, 35 deletions
diff --git a/database/rrdcalc.c b/database/rrdcalc.c
index 948ebe8a..d85825c5 100644
--- a/database/rrdcalc.c
+++ b/database/rrdcalc.c
@@ -5,6 +5,33 @@
// ----------------------------------------------------------------------------
// RRDCALC helpers
+void rrdcalc_flags_to_json_array(BUFFER *wb, const char *key, RRDCALC_FLAGS flags) {
+ buffer_json_member_add_array(wb, key);
+
+ if(flags & RRDCALC_FLAG_DB_ERROR)
+ buffer_json_add_array_item_string(wb, "DB_ERROR");
+ if(flags & RRDCALC_FLAG_DB_NAN)
+ buffer_json_add_array_item_string(wb, "DB_NAN");
+ if(flags & RRDCALC_FLAG_CALC_ERROR)
+ buffer_json_add_array_item_string(wb, "CALC_ERROR");
+ if(flags & RRDCALC_FLAG_WARN_ERROR)
+ buffer_json_add_array_item_string(wb, "WARN_ERROR");
+ if(flags & RRDCALC_FLAG_CRIT_ERROR)
+ buffer_json_add_array_item_string(wb, "CRIT_ERROR");
+ if(flags & RRDCALC_FLAG_RUNNABLE)
+ buffer_json_add_array_item_string(wb, "RUNNABLE");
+ if(flags & RRDCALC_FLAG_DISABLED)
+ buffer_json_add_array_item_string(wb, "DISABLED");
+ if(flags & RRDCALC_FLAG_SILENCED)
+ buffer_json_add_array_item_string(wb, "SILENCED");
+ if(flags & RRDCALC_FLAG_RUN_ONCE)
+ buffer_json_add_array_item_string(wb, "RUN_ONCE");
+ if(flags & RRDCALC_FLAG_FROM_TEMPLATE)
+ buffer_json_add_array_item_string(wb, "FROM_TEMPLATE");
+
+ buffer_json_array_close(wb);
+}
+
inline const char *rrdcalc_status2string(RRDCALC_STATUS status) {
switch(status) {
case RRDCALC_STATUS_REMOVED:
@@ -29,18 +56,18 @@ inline const char *rrdcalc_status2string(RRDCALC_STATUS status) {
return "CRITICAL";
default:
- error("Unknown alarm status %d", status);
+ netdata_log_error("Unknown alarm status %d", status);
return "UNKNOWN";
}
}
-uint32_t rrdcalc_get_unique_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id) {
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+uint32_t rrdcalc_get_unique_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id) {
+ rw_spinlock_read_lock(&host->health_log.spinlock);
// re-use old IDs, by looking them up in the alarm log
ALARM_ENTRY *ae = NULL;
for(ae = host->health_log.alarms; ae ;ae = ae->next) {
- if(unlikely(name == ae->name && chart == ae->chart)) {
+ if(unlikely(name == ae->name && chart == ae->chart && !uuid_memcmp(&ae->config_hash_id, config_hash_id))) {
if(next_event_id) *next_event_id = ae->alarm_event_id + 1;
break;
}
@@ -52,13 +79,17 @@ uint32_t rrdcalc_get_unique_id(RRDHOST *host, STRING *chart, STRING *name, uint3
alarm_id = ae->alarm_id;
else {
- if (unlikely(!host->health_log.next_alarm_id))
- host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
+ alarm_id = sql_get_alarm_id(host, chart, name, next_event_id, config_hash_id);
- alarm_id = host->health_log.next_alarm_id++;
+ if (!alarm_id) {
+ if (unlikely(!host->health_log.next_alarm_id))
+ host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
+
+ alarm_id = host->health_log.next_alarm_id++;
+ }
}
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_read_unlock(&host->health_log.spinlock);
return alarm_id;
}
@@ -175,28 +206,29 @@ RRDCALC *rrdcalc_acquired_to_rrdcalc(const RRDCALC_ACQUIRED *rca) {
static void rrdcalc_link_to_rrdset(RRDSET *st, RRDCALC *rc) {
RRDHOST *host = st->rrdhost;
- debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rrdcalc_chart_name(rc), rrdcalc_name(rc), rrdset_id(st), rrdhost_hostname(host));
+ netdata_log_debug(D_HEALTH, "Health linking alarm '%s.%s' to chart '%s' of host '%s'", rrdcalc_chart_name(rc), rrdcalc_name(rc), rrdset_id(st), rrdhost_hostname(host));
+ rc->last_status_change_value = rc->value;
rc->last_status_change = now_realtime_sec();
rc->rrdset = st;
- netdata_rwlock_wrlock(&st->alerts.rwlock);
+ rw_spinlock_write_lock(&st->alerts.spinlock);
DOUBLE_LINKED_LIST_APPEND_ITEM_UNSAFE(st->alerts.base, rc, prev, next);
- netdata_rwlock_unlock(&st->alerts.rwlock);
+ rw_spinlock_write_unlock(&st->alerts.spinlock);
if(rc->update_every < rc->rrdset->update_every) {
- error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rrdset_id(rc->rrdset), rrdcalc_name(rc), rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every);
+ netdata_log_error("Health alarm '%s.%s' has update every %d, less than chart update every %d. Setting alarm update frequency to %d.", rrdset_id(rc->rrdset), rrdcalc_name(rc), rc->update_every, rc->rrdset->update_every, rc->rrdset->update_every);
rc->update_every = rc->rrdset->update_every;
}
if(!isnan(rc->green) && isnan(st->green)) {
- debug(D_HEALTH, "Health alarm '%s.%s' green threshold set from " NETDATA_DOUBLE_FORMAT_AUTO
+ netdata_log_debug(D_HEALTH, "Health alarm '%s.%s' green threshold set from " NETDATA_DOUBLE_FORMAT_AUTO
" to " NETDATA_DOUBLE_FORMAT_AUTO ".", rrdset_id(rc->rrdset), rrdcalc_name(rc), rc->rrdset->green, rc->green);
st->green = rc->green;
}
if(!isnan(rc->red) && isnan(st->red)) {
- debug(D_HEALTH, "Health alarm '%s.%s' red threshold set from " NETDATA_DOUBLE_FORMAT_AUTO " to " NETDATA_DOUBLE_FORMAT_AUTO
+ netdata_log_debug(D_HEALTH, "Health alarm '%s.%s' red threshold set from " NETDATA_DOUBLE_FORMAT_AUTO " to " NETDATA_DOUBLE_FORMAT_AUTO
".", rrdset_id(rc->rrdset), rrdcalc_name(rc), rc->rrdset->red, rc->red);
st->red = rc->red;
}
@@ -269,14 +301,15 @@ static void rrdcalc_link_to_rrdset(RRDSET *st, RRDCALC *rc) {
now - rc->last_status_change,
rc->old_value,
rc->value,
+ RRDCALC_STATUS_REMOVED,
rc->status,
- RRDCALC_STATUS_UNINITIALIZED,
rc->source,
rc->units,
rc->info,
0,
rrdcalc_isrepeating(rc)?HEALTH_ENTRY_FLAG_IS_REPEATING:0);
+ rc->ae = ae;
health_alarm_log_add_entry(host, ae);
}
@@ -284,8 +317,8 @@ static void rrdcalc_unlink_from_rrdset(RRDCALC *rc, bool having_ll_wrlock) {
RRDSET *st = rc->rrdset;
if(!st) {
- debug(D_HEALTH, "Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rrdcalc_chart_name(rc), rrdcalc_name(rc));
- error("Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rrdcalc_chart_name(rc), rrdcalc_name(rc));
+ netdata_log_debug(D_HEALTH, "Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rrdcalc_chart_name(rc), rrdcalc_name(rc));
+ netdata_log_error("Requested to unlink RRDCALC '%s.%s' which is not linked to any RRDSET", rrdcalc_chart_name(rc), rrdcalc_name(rc));
return;
}
@@ -320,20 +353,21 @@ static void rrdcalc_unlink_from_rrdset(RRDCALC *rc, bool having_ll_wrlock) {
0,
0);
+ rc->ae = ae;
health_alarm_log_add_entry(host, ae);
}
- debug(D_HEALTH, "Health unlinking alarm '%s.%s' from chart '%s' of host '%s'", rrdcalc_chart_name(rc), rrdcalc_name(rc), rrdset_id(st), rrdhost_hostname(host));
+ netdata_log_debug(D_HEALTH, "Health unlinking alarm '%s.%s' from chart '%s' of host '%s'", rrdcalc_chart_name(rc), rrdcalc_name(rc), rrdset_id(st), rrdhost_hostname(host));
// unlink it
if(!having_ll_wrlock)
- netdata_rwlock_wrlock(&st->alerts.rwlock);
+ rw_spinlock_write_lock(&st->alerts.spinlock);
DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(st->alerts.base, rc, prev, next);
if(!having_ll_wrlock)
- netdata_rwlock_unlock(&st->alerts.rwlock);
+ rw_spinlock_write_unlock(&st->alerts.spinlock);
rc->rrdset = NULL;
@@ -378,7 +412,7 @@ static inline bool rrdcalc_check_if_it_matches_rrdset(RRDCALC *rc, RRDSET *st) {
void rrdcalc_link_matching_alerts_to_rrdset(RRDSET *st) {
RRDHOST *host = st->rrdhost;
- // debug(D_HEALTH, "find matching alarms for chart '%s'", st->id);
+ // netdata_log_debug(D_HEALTH, "find matching alarms for chart '%s'", st->id);
RRDCALC *rc;
foreach_rrdcalc_in_rrdhost_read(host, rc) {
@@ -478,17 +512,17 @@ static void rrdcalc_rrdhost_insert_callback(const DICTIONARY_ITEM *item __maybe_
if(rt->calculation) {
rc->calculation = expression_parse(rt->calculation->source, NULL, NULL);
if(!rc->calculation)
- error("Health alarm '%s.%s': failed to parse calculation expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->calculation->source);
+ netdata_log_error("Health alarm '%s.%s': failed to parse calculation expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->calculation->source);
}
if(rt->warning) {
rc->warning = expression_parse(rt->warning->source, NULL, NULL);
if(!rc->warning)
- error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->warning->source);
+ netdata_log_error("Health alarm '%s.%s': failed to re-parse warning expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->warning->source);
}
if(rt->critical) {
rc->critical = expression_parse(rt->critical->source, NULL, NULL);
if(!rc->critical)
- error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->critical->source);
+ netdata_log_error("Health alarm '%s.%s': failed to re-parse critical expression '%s'", rrdset_id(st), rrdcalctemplate_name(rt), rt->critical->source);
}
}
else if(ctr->from_config) {
@@ -497,7 +531,7 @@ static void rrdcalc_rrdhost_insert_callback(const DICTIONARY_ITEM *item __maybe_
;
}
- rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id);
+ rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id, &rc->config_hash_id);
if(rc->calculation) {
rc->calculation->status = &rc->status;
@@ -523,7 +557,7 @@ static void rrdcalc_rrdhost_insert_callback(const DICTIONARY_ITEM *item __maybe_
rc->critical->rrdcalc = rc;
}
- debug(D_HEALTH, "Health added alarm '%s.%s': exec '%s', recipient '%s', green " NETDATA_DOUBLE_FORMAT_AUTO
+ netdata_log_debug(D_HEALTH, "Health added alarm '%s.%s': exec '%s', recipient '%s', green " NETDATA_DOUBLE_FORMAT_AUTO
", red " NETDATA_DOUBLE_FORMAT_AUTO
", lookup: group %d, after %d, before %d, options %u, dimensions '%s', for each dimension '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u",
rrdcalc_chart_name(rc),
@@ -669,23 +703,23 @@ void rrdcalc_add_from_rrdcalctemplate(RRDHOST *host, RRDCALCTEMPLATE *rt, RRDSET
dictionary_set_advanced(host->rrdcalc_root_index, key, (ssize_t)(key_len + 1), NULL, sizeof(RRDCALC), &tmp);
if(tmp.react_action != RRDCALC_REACT_NEW && tmp.existing_from_template == false)
- error("RRDCALC: from template '%s' on chart '%s' with key '%s', failed to be added to host '%s'. It is manually configured.",
+ netdata_log_error("RRDCALC: from template '%s' on chart '%s' with key '%s', failed to be added to host '%s'. It is manually configured.",
string2str(rt->name), rrdset_id(st), key, rrdhost_hostname(host));
}
int rrdcalc_add_from_config(RRDHOST *host, RRDCALC *rc) {
if(!rc->chart) {
- error("Health configuration for alarm '%s' does not have a chart", rrdcalc_name(rc));
+ netdata_log_error("Health configuration for alarm '%s' does not have a chart", rrdcalc_name(rc));
return 0;
}
if(!rc->update_every) {
- error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rrdcalc_chart_name(rc), rrdcalc_name(rc));
+ netdata_log_error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rrdcalc_chart_name(rc), rrdcalc_name(rc));
return 0;
}
if(!RRDCALC_HAS_DB_LOOKUP(rc) && !rc->calculation && !rc->warning && !rc->critical) {
- error("Health configuration for alarm '%s.%s' is useless (no db lookup, no calculation, no warning and no critical expressions)", rrdcalc_chart_name(rc), rrdcalc_name(rc));
+ netdata_log_error("Health configuration for alarm '%s.%s' is useless (no db lookup, no calculation, no warning and no critical expressions)", rrdcalc_chart_name(rc), rrdcalc_name(rc));
return 0;
}
@@ -716,7 +750,7 @@ int rrdcalc_add_from_config(RRDHOST *host, RRDCALC *rc) {
rrdset_foreach_done(st);
}
else {
- error(
+ netdata_log_error(
"RRDCALC: from config '%s' on chart '%s' failed to be added to host '%s'. It already exists.",
string2str(rc->name),
string2str(rc->chart),
@@ -749,7 +783,7 @@ void rrdcalc_delete_alerts_not_matching_host_labels_from_this_host(RRDHOST *host
continue;
if(!rrdlabels_match_simple_pattern_parsed(host->rrdlabels, rc->host_labels_pattern, '=', NULL)) {
- log_health("Health configuration for alarm '%s' cannot be applied, because the host %s does not have the label(s) '%s'",
+ netdata_log_health("Health configuration for alarm '%s' cannot be applied, because the host %s does not have the label(s) '%s'",
rrdcalc_name(rc),
rrdhost_hostname(host),
rrdcalc_host_labels(rc));
@@ -774,10 +808,10 @@ void rrdcalc_delete_alerts_not_matching_host_labels_from_all_hosts() {
void rrdcalc_unlink_all_rrdset_alerts(RRDSET *st) {
RRDCALC *rc, *last = NULL;
- netdata_rwlock_wrlock(&st->alerts.rwlock);
+ rw_spinlock_write_lock(&st->alerts.spinlock);
while((rc = st->alerts.base)) {
if(last == rc) {
- error("RRDCALC: malformed list of alerts linked to chart - cannot cleanup - giving up.");
+ netdata_log_error("RRDCALC: malformed list of alerts linked to chart - cannot cleanup - giving up.");
break;
}
last = rc;
@@ -793,7 +827,7 @@ void rrdcalc_unlink_all_rrdset_alerts(RRDSET *st) {
}
}
- netdata_rwlock_unlock(&st->alerts.rwlock);
+ rw_spinlock_write_unlock(&st->alerts.spinlock);
}
void rrdcalc_delete_all(RRDHOST *host) {