// SPDX-License-Identifier: GPL-3.0-or-later
#include "rrd.h"
// ----------------------------------------------------------------------------
// 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:
return "REMOVED";
case RRDCALC_STATUS_UNDEFINED:
return "UNDEFINED";
case RRDCALC_STATUS_UNINITIALIZED:
return "UNINITIALIZED";
case RRDCALC_STATUS_CLEAR:
return "CLEAR";
case RRDCALC_STATUS_RAISED:
return "RAISED";
case RRDCALC_STATUS_WARNING:
return "WARNING";
case RRDCALC_STATUS_CRITICAL:
return "CRITICAL";
default:
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, 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 && !uuid_memcmp(&ae->config_hash_id, config_hash_id))) {
if(next_event_id) *next_event_id = ae->alarm_event_id + 1;
break;
}
}
uint32_t alarm_id;
if(ae)
alarm_id = ae->alarm_id;
else {
alarm_id = sql_get_alarm_id(host, chart, name, next_event_id, config_hash_id);
if (!alarm_id) {
//check possible stored config hash as zeroes or null
alarm_id = sql_get_alarm_id_check_zero_hash(host, chart, name, next_event_id, config_hash_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++;
}
}
}
rw_spinlock_read_unlock(&host->health_log.spinlock);
return alarm_id;
}
// ----------------------------------------------------------------------------
// RRDCALC replacing info/summary text variables with RRDSET labels
static STRING *rrdcalc_replace_variables_with_rrdset_labels(const char *line, RRDCALC *rc) {
if (!line || !*line)
return NULL;
size_t pos = 0;
char *temp = strdupz(line);
char var[RRDCALC_VAR_MAX];
char *m, *lbl_value = NULL;
while ((m = strchr(temp + pos, '$')) && *(m+1) == '{') {
int i = 0;
char *e = m;
while (*e) {
var[i++] = *e;
if (*e == '}' || i == RRDCALC_VAR_MAX - 1)
break;
e++;
}
var[i] = '\0';
pos = m - temp + 1;
if (!strcmp(var, RRDCALC_VAR_FAMILY)) {
char *buf = find_and_replace(temp, var, (rc