summaryrefslogtreecommitdiffstats
path: root/database/sqlite
diff options
context:
space:
mode:
Diffstat (limited to 'database/sqlite')
-rw-r--r--database/sqlite/sqlite_aclk.c28
-rw-r--r--database/sqlite/sqlite_aclk.h12
-rw-r--r--database/sqlite/sqlite_aclk_alert.c297
-rw-r--r--database/sqlite/sqlite_aclk_node.c6
-rw-r--r--database/sqlite/sqlite_context.c44
-rw-r--r--database/sqlite/sqlite_db_migration.c116
-rw-r--r--database/sqlite/sqlite_functions.c118
-rw-r--r--database/sqlite/sqlite_functions.h2
-rw-r--r--database/sqlite/sqlite_health.c1354
-rw-r--r--database/sqlite/sqlite_health.h23
-rw-r--r--database/sqlite/sqlite_metadata.c185
11 files changed, 1557 insertions, 628 deletions
diff --git a/database/sqlite/sqlite_aclk.c b/database/sqlite/sqlite_aclk.c
index a33e09f5d..fedce50eb 100644
--- a/database/sqlite/sqlite_aclk.c
+++ b/database/sqlite/sqlite_aclk.c
@@ -67,7 +67,7 @@ static void aclk_database_enq_cmd(struct aclk_database_cmd *cmd)
/* wake up event loop */
int rc = uv_async_send(&aclk_sync_config.async);
if (unlikely(rc))
- debug(D_ACLK_SYNC, "Failed to wake up event loop");
+ netdata_log_debug(D_ACLK_SYNC, "Failed to wake up event loop");
}
enum {
@@ -226,14 +226,14 @@ static void sql_delete_aclk_table_list(char *host_guid)
uuid_unparse_lower(host_uuid, host_str);
uuid_unparse_lower_fix(&host_uuid, uuid_str);
- debug(D_ACLK_SYNC, "Checking if I should delete aclk tables for node %s", host_str);
+ netdata_log_debug(D_ACLK_SYNC, "Checking if I should delete aclk tables for node %s", host_str);
if (is_host_available(&host_uuid)) {
- debug(D_ACLK_SYNC, "Host %s exists, not deleting aclk sync tables", host_str);
+ netdata_log_debug(D_ACLK_SYNC, "Host %s exists, not deleting aclk sync tables", host_str);
return;
}
- debug(D_ACLK_SYNC, "Host %s does NOT exist, can delete aclk sync tables", host_str);
+ netdata_log_debug(D_ACLK_SYNC, "Host %s does NOT exist, can delete aclk sync tables", host_str);
sqlite3_stmt *res = NULL;
BUFFER *sql = buffer_create(ACLK_SYNC_QUERY_SIZE, &netdata_buffers_statistics.buffers_sqlite);
@@ -257,7 +257,7 @@ static void sql_delete_aclk_table_list(char *host_guid)
rc = db_execute(db_meta, buffer_tostring(sql));
if (unlikely(rc))
- error("Failed to drop unused ACLK tables");
+ netdata_log_error("Failed to drop unused ACLK tables");
fail:
buffer_free(sql);
@@ -265,7 +265,7 @@ fail:
static int sql_check_aclk_table(void *data __maybe_unused, int argc __maybe_unused, char **argv __maybe_unused, char **column __maybe_unused)
{
- debug(D_ACLK_SYNC,"Scheduling aclk sync table check for node %s", (char *) argv[0]);
+ netdata_log_debug(D_ACLK_SYNC,"Scheduling aclk sync table check for node %s", (char *) argv[0]);
struct aclk_database_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = ACLK_DATABASE_DELETE_HOST;
@@ -280,7 +280,7 @@ static int sql_check_aclk_table(void *data __maybe_unused, int argc __maybe_unus
static void sql_check_aclk_table_list(void)
{
char *err_msg = NULL;
- debug(D_ACLK_SYNC,"Cleaning tables for nodes that do not exist");
+ netdata_log_debug(D_ACLK_SYNC,"Cleaning tables for nodes that do not exist");
int rc = sqlite3_exec_monitored(db_meta, SQL_SELECT_ACLK_ACTIVE_LIST, sql_check_aclk_table, NULL, &err_msg);
if (rc != SQLITE_OK) {
error_report("Query failed when trying to check for obsolete ACLK sync tables, %s", err_msg);
@@ -305,7 +305,7 @@ static int sql_maint_aclk_sync_database(void *data __maybe_unused, int argc __ma
static void sql_maint_aclk_sync_database_all(void)
{
char *err_msg = NULL;
- debug(D_ACLK_SYNC,"Cleaning tables for nodes that do not exist");
+ netdata_log_debug(D_ACLK_SYNC,"Cleaning tables for nodes that do not exist");
int rc = sqlite3_exec_monitored(db_meta, SQL_SELECT_ACLK_ALERT_LIST, sql_maint_aclk_sync_database, NULL, &err_msg);
if (rc != SQLITE_OK) {
error_report("Query failed when trying to check for obsolete ACLK sync tables, %s", err_msg);
@@ -385,7 +385,7 @@ static void aclk_synchronization(void *arg __maybe_unused)
config->timer_req.data = config;
fatal_assert(0 == uv_timer_start(&config->timer_req, timer_cb, TIMER_PERIOD_MS, TIMER_PERIOD_MS));
- info("Starting ACLK synchronization thread");
+ netdata_log_info("Starting ACLK synchronization thread");
config->cleanup_after = now_realtime_sec() + ACLK_DATABASE_CLEANUP_FIRST;
config->initialized = true;
@@ -444,7 +444,7 @@ static void aclk_synchronization(void *arg __maybe_unused)
sql_process_queue_removed_alerts_to_aclk(cmd.param[0]);
break;
default:
- debug(D_ACLK_SYNC, "%s: default.", __func__);
+ netdata_log_debug(D_ACLK_SYNC, "%s: default.", __func__);
break;
}
if (cmd.completion)
@@ -462,7 +462,7 @@ static void aclk_synchronization(void *arg __maybe_unused)
worker_unregister();
service_exits();
- info("ACLK SYNC: Shutting down ACLK synchronization event loop");
+ netdata_log_info("ACLK SYNC: Shutting down ACLK synchronization event loop");
}
static void aclk_synchronization_init(void)
@@ -543,7 +543,7 @@ void sql_aclk_sync_init(void)
return;
}
- info("Creating archived hosts");
+ netdata_log_info("Creating archived hosts");
int number_of_children = 0;
rc = sqlite3_exec_monitored(db_meta, SQL_FETCH_ALL_HOSTS, create_host_callback, &number_of_children, &err_msg);
@@ -552,7 +552,7 @@ void sql_aclk_sync_init(void)
sqlite3_free(err_msg);
}
- info("Created %d archived hosts", number_of_children);
+ netdata_log_info("Created %d archived hosts", number_of_children);
// Trigger host context load for hosts that have been created
metadata_queue_load_host_context(NULL);
@@ -568,7 +568,7 @@ void sql_aclk_sync_init(void)
}
aclk_synchronization_init();
- info("ACLK sync initialization completed");
+ netdata_log_info("ACLK sync initialization completed");
#endif
}
diff --git a/database/sqlite/sqlite_aclk.h b/database/sqlite/sqlite_aclk.h
index d555a0cef..705102d74 100644
--- a/database/sqlite/sqlite_aclk.h
+++ b/database/sqlite/sqlite_aclk.h
@@ -27,12 +27,20 @@ static inline void uuid_unparse_lower_fix(uuid_t *uuid, char *out)
out[23] = '_';
}
+static inline int uuid_parse_fix(char *in, uuid_t uuid)
+{
+ in[8] = '-';
+ in[13] = '-';
+ in[18] = '-';
+ in[23] = '-';
+ return uuid_parse(in, uuid);
+}
+
static inline int claimed()
{
return localhost->aclk_state.claimed_id != NULL;
}
-
#define TABLE_ACLK_ALERT "CREATE TABLE IF NOT EXISTS aclk_alert_%s (sequence_id INTEGER PRIMARY KEY, " \
"alert_unique_id, date_created, date_submitted, date_cloud_ack, filtered_alert_unique_id NOT NULL, " \
"unique(alert_unique_id));"
@@ -79,6 +87,8 @@ struct aclk_sync_host_config {
char uuid_str[UUID_STR_LEN];
char node_id[UUID_STR_LEN];
char *alerts_snapshot_uuid; // will contain the snapshot_uuid value if snapshot was requested
+ uint64_t alerts_log_first_sequence_id;
+ uint64_t alerts_log_last_sequence_id;
};
extern sqlite3 *db_meta;
diff --git a/database/sqlite/sqlite_aclk_alert.c b/database/sqlite/sqlite_aclk_alert.c
index 52d343acb..d57ae043f 100644
--- a/database/sqlite/sqlite_aclk_alert.c
+++ b/database/sqlite/sqlite_aclk_alert.c
@@ -7,37 +7,7 @@
#include "../../aclk/aclk_alarm_api.h"
#endif
-#define SQL_GET_ALERT_REMOVE_TIME "SELECT when_key FROM health_log_%s WHERE alarm_id = %u " \
- "AND unique_id > %u AND unique_id < %u " \
- "AND new_status = -2;"
-
-time_t removed_when(uint32_t alarm_id, uint32_t before_unique_id, uint32_t after_unique_id, char *uuid_str) {
- sqlite3_stmt *res = NULL;
- time_t when = 0;
- char sql[ACLK_SYNC_QUERY_SIZE];
-
- snprintfz(sql,ACLK_SYNC_QUERY_SIZE-1, SQL_GET_ALERT_REMOVE_TIME, uuid_str, alarm_id, after_unique_id, before_unique_id);
-
- int rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
- if (rc != SQLITE_OK) {
- error_report("Failed to prepare statement when trying to find removed gap.");
- return 0;
- }
-
- rc = sqlite3_step_monitored(res);
- if (likely(rc == SQLITE_ROW)) {
- when = (time_t) sqlite3_column_int64(res, 0);
- }
-
- rc = sqlite3_finalize(res);
- if (unlikely(rc != SQLITE_OK))
- error_report("Failed to finalize statement when trying to find removed gap, rc = %d", rc);
-
- return when;
-}
-
#define SQL_UPDATE_FILTERED_ALERT "UPDATE aclk_alert_%s SET filtered_alert_unique_id = %u where filtered_alert_unique_id = %u"
-
void update_filtered(ALARM_ENTRY *ae, uint32_t unique_id, char *uuid_str) {
char sql[ACLK_SYNC_QUERY_SIZE];
snprintfz(sql, ACLK_SYNC_QUERY_SIZE-1, SQL_UPDATE_FILTERED_ALERT, uuid_str, ae->unique_id, unique_id);
@@ -45,17 +15,16 @@ void update_filtered(ALARM_ENTRY *ae, uint32_t unique_id, char *uuid_str) {
ae->flags |= HEALTH_ENTRY_FLAG_ACLK_QUEUED;
}
-#define SQL_SELECT_ALERT_BY_UNIQUE_ID "SELECT hl.unique_id FROM health_log_%s hl, alert_hash ah WHERE hl.unique_id = %u " \
- "AND hl.config_hash_id = ah.hash_id " \
+#define SQL_SELECT_VARIABLE_ALERT_BY_UNIQUE_ID "SELECT hld.unique_id FROM health_log hl, alert_hash ah, health_log_detail hld WHERE hld.unique_id = %u " \
+ "AND hl.config_hash_id = ah.hash_id AND hld.health_log_id = hl.health_log_id AND host_id = @host_id " \
"AND ah.warn IS NULL AND ah.crit IS NULL;"
-
-static inline bool is_event_from_alert_variable_config(uint32_t unique_id, char *uuid_str) {
+static inline bool is_event_from_alert_variable_config(uint32_t unique_id, uuid_t *host_id) {
sqlite3_stmt *res = NULL;
int rc = 0;
bool ret = false;
char sql[ACLK_SYNC_QUERY_SIZE];
- snprintfz(sql,ACLK_SYNC_QUERY_SIZE-1, SQL_SELECT_ALERT_BY_UNIQUE_ID, uuid_str, unique_id);
+ snprintfz(sql,ACLK_SYNC_QUERY_SIZE-1, SQL_SELECT_VARIABLE_ALERT_BY_UNIQUE_ID, unique_id);
rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
if (rc != SQLITE_OK) {
@@ -63,6 +32,13 @@ static inline bool is_event_from_alert_variable_config(uint32_t unique_id, char
return false;
}
+ rc = sqlite3_bind_blob(res, 1, host_id, sizeof(*host_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for checking alert variable.");
+ sqlite3_finalize(res);
+ return false;
+ }
+
rc = sqlite3_step_monitored(res);
if (likely(rc == SQLITE_ROW)) {
ret = true;
@@ -76,13 +52,12 @@ static inline bool is_event_from_alert_variable_config(uint32_t unique_id, char
}
#define MAX_REMOVED_PERIOD 604800 //a week
-//decide if some events should be sent or not
-
-#define SQL_SELECT_ALERT_BY_ID "SELECT hl.new_status, hl.config_hash_id, hl.unique_id FROM health_log_%s hl, aclk_alert_%s aa " \
- "WHERE hl.unique_id = aa.filtered_alert_unique_id " \
- "AND hl.alarm_id = %u " \
- "ORDER BY alarm_event_id DESC LIMIT 1;"
+//decide if some events should be sent or not
+#define SQL_SELECT_ALERT_BY_ID "SELECT hld.new_status, hl.config_hash_id, hld.unique_id FROM health_log hl, aclk_alert_%s aa, health_log_detail hld " \
+ "WHERE hld.unique_id = aa.filtered_alert_unique_id " \
+ "AND hld.alarm_id = %u AND hl.host_id = @host_id AND hl.health_log_id = hld.health_log_id " \
+ "ORDER BY hld.alarm_event_id DESC LIMIT 1;"
int should_send_to_cloud(RRDHOST *host, ALARM_ENTRY *ae)
{
sqlite3_stmt *res = NULL;
@@ -94,7 +69,7 @@ int should_send_to_cloud(RRDHOST *host, ALARM_ENTRY *ae)
return 0;
}
- if (unlikely(uuid_is_null(ae->config_hash_id)))
+ if (unlikely(uuid_is_null(ae->config_hash_id)))
return 0;
char sql[ACLK_SYNC_QUERY_SIZE];
@@ -104,7 +79,7 @@ int should_send_to_cloud(RRDHOST *host, ALARM_ENTRY *ae)
//get the previous sent event of this alarm_id
//base the search on the last filtered event
- snprintfz(sql,ACLK_SYNC_QUERY_SIZE-1, SQL_SELECT_ALERT_BY_ID, uuid_str, uuid_str, ae->alarm_id);
+ snprintfz(sql,ACLK_SYNC_QUERY_SIZE-1, SQL_SELECT_ALERT_BY_ID, uuid_str, ae->alarm_id);
int rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
if (rc != SQLITE_OK) {
@@ -113,13 +88,19 @@ int should_send_to_cloud(RRDHOST *host, ALARM_ENTRY *ae)
return send;
}
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for checking alert variable.");
+ sqlite3_finalize(res);
+ return false;
+ }
+
rc = sqlite3_step_monitored(res);
if (likely(rc == SQLITE_ROW)) {
status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
if (sqlite3_column_type(res, 1) != SQLITE_NULL)
uuid_copy(config_hash_id, *((uuid_t *) sqlite3_column_blob(res, 1)));
unique_id = (uint32_t) sqlite3_column_int64(res, 2);
-
} else {
send = 1;
goto done;
@@ -136,26 +117,9 @@ int should_send_to_cloud(RRDHOST *host, ALARM_ENTRY *ae)
}
//same status, same config
- if (ae->new_status == RRDCALC_STATUS_CLEAR || ae->new_status == RRDCALC_STATUS_UNDEFINED) {
- send = 0;
- update_filtered(ae, unique_id, uuid_str);
- goto done;
- }
+ send = 0;
+ update_filtered(ae, unique_id, uuid_str);
- //detect a long off period of the agent, TODO make global
- if (ae->new_status == RRDCALC_STATUS_WARNING || ae->new_status == RRDCALC_STATUS_CRITICAL) {
- time_t when = removed_when(ae->alarm_id, ae->unique_id, unique_id, uuid_str);
-
- if (when && (when + (time_t)MAX_REMOVED_PERIOD) < ae->when) {
- send = 1;
- goto done;
- } else {
- send = 0;
- update_filtered(ae, unique_id, uuid_str);
- goto done;
- }
- }
-
done:
rc = sqlite3_finalize(res);
if (unlikely(rc != SQLITE_OK))
@@ -164,12 +128,8 @@ done:
return send;
}
-// will replace call to aclk_update_alarm in health/health_log.c
-// and handle both cases
-
#define SQL_QUEUE_ALERT_TO_CLOUD "INSERT INTO aclk_alert_%s (alert_unique_id, date_created, filtered_alert_unique_id) " \
"VALUES (@alert_unique_id, unixepoch(), @alert_unique_id) ON CONFLICT (alert_unique_id) do nothing;"
-
int sql_queue_alarm_to_aclk(RRDHOST *host, ALARM_ENTRY *ae, int skip_filter)
{
if(!service_running(SERVICE_ACLK))
@@ -193,7 +153,7 @@ int sql_queue_alarm_to_aclk(RRDHOST *host, ALARM_ENTRY *ae, int skip_filter)
char uuid_str[UUID_STR_LEN];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
- if (is_event_from_alert_variable_config(ae->unique_id, uuid_str))
+ if (is_event_from_alert_variable_config(ae->unique_id, &host->host_uuid))
return 0;
sqlite3_stmt *res_alert = NULL;
@@ -286,7 +246,7 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
int rc;
if (unlikely(!wc->alert_updates)) {
- log_access("ACLK STA [%s (%s)]: Ignoring alert push event, updates have been turned off for this node.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
+ netdata_log_access("ACLK STA [%s (%s)]: Ignoring alert push event, updates have been turned off for this node.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
return;
}
@@ -305,21 +265,18 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
sqlite3_stmt *res = NULL;
- buffer_sprintf(sql, "select aa.sequence_id, hl.unique_id, hl.alarm_id, hl.config_hash_id, hl.updated_by_id, hl.when_key, " \
- " hl.duration, hl.non_clear_duration, hl.flags, hl.exec_run_timestamp, hl.delay_up_to_timestamp, hl.name, " \
- " hl.chart, hl.family, hl.exec, hl.recipient, hl.source, hl.units, hl.info, hl.exec_code, hl.new_status, " \
- " hl.old_status, hl.delay, hl.new_value, hl.old_value, hl.last_repeat, hl.chart_context, hl.transition_id, hl.alarm_event_id " \
- " from health_log_%s hl, aclk_alert_%s aa " \
- " where hl.unique_id = aa.alert_unique_id and aa.date_submitted is null " \
- " order by aa.sequence_id asc limit %d;", wc->uuid_str, wc->uuid_str, limit);
+ buffer_sprintf(sql, "select aa.sequence_id, hld.unique_id, hld.alarm_id, hl.config_hash_id, hld.updated_by_id, hld.when_key, " \
+ " hld.duration, hld.non_clear_duration, hld.flags, hld.exec_run_timestamp, hld.delay_up_to_timestamp, hl.name, " \
+ " hl.chart, hl.family, hl.exec, hl.recipient, ha.source, hl.units, hld.info, hld.exec_code, hld.new_status, " \
+ " hld.old_status, hld.delay, hld.new_value, hld.old_value, hld.last_repeat, hl.chart_context, hld.transition_id, hld.alarm_event_id " \
+ " from health_log hl, aclk_alert_%s aa, alert_hash ha, health_log_detail hld " \
+ " where hld.unique_id = aa.alert_unique_id and hl.config_hash_id = ha.hash_id and aa.date_submitted is null " \
+ " and hl.host_id = @host_id and hl.health_log_id = hld.health_log_id " \
+ " order by aa.sequence_id asc limit %d;", wc->uuid_str, limit);
rc = sqlite3_prepare_v2(db_meta, buffer_tostring(sql), -1, &res, 0);
if (rc != SQLITE_OK) {
- // Try to create tables
- if (wc->host)
- sql_create_health_log_table(wc->host);
-
BUFFER *sql_fix = buffer_create(1024, &netdata_buffers_statistics.buffers_sqlite);
buffer_sprintf(sql_fix, TABLE_ACLK_ALERT, wc->uuid_str);
rc = db_execute(db_meta, buffer_tostring(sql_fix));
@@ -344,10 +301,17 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
}
}
- uint64_t first_sequence_id = 0;
- uint64_t last_sequence_id = 0;
- static __thread uint64_t log_first_sequence_id = 0;
- static __thread uint64_t log_last_sequence_id = 0;
+ rc = sqlite3_bind_blob(res, 1, &wc->host->host_uuid, sizeof(wc->host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for pushing alert event.");
+ sqlite3_finalize(res);
+ buffer_free(sql);
+ freez(claim_id);
+ return;
+ }
+
+ uint64_t first_sequence_id = 0;
+ uint64_t last_sequence_id = 0;
while (sqlite3_step_monitored(res) == SQLITE_ROW) {
struct alarm_log_entry alarm_log;
@@ -371,7 +335,8 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
alarm_log.timezone = strdupz(rrdhost_abbrev_timezone(wc->host));
alarm_log.exec_path = sqlite3_column_bytes(res, 14) > 0 ? strdupz((char *)sqlite3_column_text(res, 14)) :
strdupz((char *)string2str(wc->host->health.health_default_exec));
- alarm_log.conf_source = strdupz((char *)sqlite3_column_text(res, 16));
+
+ alarm_log.conf_source = sqlite3_column_bytes(res, 16) > 0 ? strdupz((char *)sqlite3_column_text(res, 16)) : strdupz("");
char *edit_command = sqlite3_column_bytes(res, 16) > 0 ?
health_edit_command_from_source((char *)sqlite3_column_text(res, 16)) :
@@ -420,11 +385,11 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
if (first_sequence_id == 0)
first_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
- if (log_first_sequence_id == 0)
- log_first_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
+ if (wc->alerts_log_first_sequence_id == 0)
+ wc->alerts_log_first_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
last_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
- log_last_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
+ wc->alerts_log_last_sequence_id = (uint64_t) sqlite3_column_int64(res, 0);
destroy_alarm_log_entry(&alarm_log);
freez(edit_command);
@@ -443,15 +408,15 @@ void aclk_push_alert_event(struct aclk_sync_host_config *wc)
rrdhost_flag_set(wc->host, RRDHOST_FLAG_ACLK_STREAM_ALERTS);
} else {
- if (log_first_sequence_id)
- log_access(
+ if (wc->alerts_log_first_sequence_id)
+ netdata_log_access(
"ACLK RES [%s (%s)]: ALERTS SENT from %" PRIu64 " to %" PRIu64 "",
wc->node_id,
wc->host ? rrdhost_hostname(wc->host) : "N/A",
- log_first_sequence_id,
- log_last_sequence_id);
- log_first_sequence_id = 0;
- log_last_sequence_id = 0;
+ wc->alerts_log_first_sequence_id,
+ wc->alerts_log_last_sequence_id);
+ wc->alerts_log_first_sequence_id = 0;
+ wc->alerts_log_last_sequence_id = 0;
}
rc = sqlite3_finalize(res);
@@ -486,19 +451,51 @@ void sql_queue_existing_alerts_to_aclk(RRDHOST *host)
char uuid_str[UUID_STR_LEN];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
BUFFER *sql = buffer_create(1024, &netdata_buffers_statistics.buffers_sqlite);
+ sqlite3_stmt *res = NULL;
+ int rc;
- buffer_sprintf(sql,"delete from aclk_alert_%s; " \
- "insert into aclk_alert_%s (alert_unique_id, date_created, filtered_alert_unique_id) " \
- "select unique_id alert_unique_id, unixepoch(), unique_id alert_unique_id from health_log_%s " \
- "where new_status <> 0 and new_status <> -2 and config_hash_id is not null and updated_by_id = 0 " \
- "order by unique_id asc on conflict (alert_unique_id) do nothing;", uuid_str, uuid_str, uuid_str);
+ rw_spinlock_write_lock(&host->health_log.spinlock);
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+ buffer_sprintf(sql, "delete from aclk_alert_%s; ", uuid_str);
+ if (unlikely(db_execute(db_meta, buffer_tostring(sql)))) {
+ rw_spinlock_write_unlock(&host->health_log.spinlock);
+ buffer_free(sql);
+ return;
+ }
- if (unlikely(db_execute(db_meta, buffer_tostring(sql))))
- error_report("Failed to queue existing ACLK alert events for host %s", rrdhost_hostname(host));
+ buffer_flush(sql);
+ buffer_sprintf(sql, "insert into aclk_alert_%s (alert_unique_id, date_created, filtered_alert_unique_id) " \
+ "select hld.unique_id alert_unique_id, unixepoch(), hld.unique_id alert_unique_id from health_log_detail hld, health_log hl " \
+ "where hld.new_status <> 0 and hld.new_status <> -2 and hl.health_log_id = hld.health_log_id and hl.config_hash_id is not null " \
+ "and hld.updated_by_id = 0 and hl.host_id = @host_id order by hld.unique_id asc on conflict (alert_unique_id) do nothing;", uuid_str);
+
+ rc = sqlite3_prepare_v2(db_meta, buffer_tostring(sql), -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to queue existing alerts.");
+ rw_spinlock_write_unlock(&host->health_log.spinlock);
+ buffer_free(sql);
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for when trying to queue existing alerts.");
+ sqlite3_finalize(res);
+ rw_spinlock_write_unlock(&host->health_log.spinlock);
+ buffer_free(sql);
+ return;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to queue existing alerts, rc = %d", rc);
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize statement to queue existing alerts, rc = %d", rc);
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_write_unlock(&host->health_log.spinlock);
buffer_free(sql);
rrdhost_flag_set(host, RRDHOST_FLAG_ACLK_STREAM_ALERTS);
@@ -514,7 +511,7 @@ void aclk_send_alarm_configuration(char *config_hash)
if (unlikely(!wc))
return;
- log_access("ACLK REQ [%s (%s)]: Request to send alert config %s.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
+ netdata_log_access("ACLK REQ [%s (%s)]: Request to send alert config %s.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
aclk_push_alert_config(wc->node_id, config_hash);
}
@@ -522,8 +519,7 @@ void aclk_send_alarm_configuration(char *config_hash)
#define SQL_SELECT_ALERT_CONFIG "SELECT alarm, template, on_key, class, type, component, os, hosts, plugin," \
"module, charts, families, lookup, every, units, green, red, calc, warn, crit, to_key, exec, delay, repeat, info," \
"options, host_labels, p_db_lookup_dimensions, p_db_lookup_method, p_db_lookup_options, p_db_lookup_after," \
- "p_db_lookup_before, p_update_every FROM alert_hash WHERE hash_id = @hash_id;"
-
+ "p_db_lookup_before, p_update_every, chart_labels FROM alert_hash WHERE hash_id = @hash_id;"
int aclk_push_alert_config_event(char *node_id __maybe_unused, char *config_hash __maybe_unused)
{
int rc = 0;
@@ -624,18 +620,20 @@ int aclk_push_alert_config_event(char *node_id __maybe_unused, char *config_hash
alarm_config.p_update_every = sqlite3_column_int(res, 32);
+ alarm_config.chart_labels = sqlite3_column_bytes(res, 33) > 0 ? strdupz((char *)sqlite3_column_text(res, 33)) : NULL;
+
p_alarm_config.cfg_hash = strdupz((char *) config_hash);
p_alarm_config.cfg = alarm_config;
}
if (likely(p_alarm_config.cfg_hash)) {
- log_access("ACLK RES [%s (%s)]: Sent alert config %s.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
+ netdata_log_access("ACLK RES [%s (%s)]: Sent alert config %s.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
aclk_send_provide_alarm_cfg(&p_alarm_config);
freez(p_alarm_config.cfg_hash);
destroy_aclk_alarm_configuration(&alarm_config);
}
else
- log_access("ACLK STA [%s (%s)]: Alert config for %s not found.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
+ netdata_log_access("ACLK STA [%s (%s)]: Alert config for %s not found.", wc->node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A", config_hash);
bind_fail:
rc = sqlite3_finalize(res);
@@ -670,28 +668,26 @@ void aclk_start_alert_streaming(char *node_id, bool resets)
return;
if (unlikely(!host->health.health_enabled)) {
- log_access("ACLK STA [%s (N/A)]: Ignoring request to stream alert state changes, health is disabled.", node_id);
+ netdata_log_access("ACLK STA [%s (N/A)]: Ignoring request to stream alert state changes, health is disabled.", node_id);
return;
}
if (resets) {
- log_access("ACLK REQ [%s (%s)]: STREAM ALERTS ENABLED (RESET REQUESTED)", node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
+ netdata_log_access("ACLK REQ [%s (%s)]: STREAM ALERTS ENABLED (RESET REQUESTED)", node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
sql_queue_existing_alerts_to_aclk(host);
} else
- log_access("ACLK REQ [%s (%s)]: STREAM ALERTS ENABLED", node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
+ netdata_log_access("ACLK REQ [%s (%s)]: STREAM ALERTS ENABLED", node_id, wc->host ? rrdhost_hostname(wc->host) : "N/A");
wc->alert_updates = 1;
wc->alert_queue_removed = SEND_REMOVED_AFTER_HEALTH_LOOPS;
}
#define SQL_QUEUE_REMOVE_ALERTS "INSERT INTO aclk_alert_%s (alert_unique_id, date_created, filtered_alert_unique_id) " \
- "SELECT unique_id alert_unique_id, UNIXEPOCH(), unique_id alert_unique_id FROM health_log_%s " \
- "WHERE new_status = -2 AND updated_by_id = 0 AND unique_id NOT IN " \
- "(SELECT alert_unique_id FROM aclk_alert_%s) " \
- "AND config_hash_id NOT IN (select hash_id from alert_hash where warn is null and crit is null) " \
- "ORDER BY unique_id ASC " \
- "ON CONFLICT (alert_unique_id) DO NOTHING;"
-
+ "SELECT hld.unique_id alert_unique_id, UNIXEPOCH(), hld.unique_id alert_unique_id FROM health_log hl, health_log_detail hld " \
+ "WHERE hl.host_id = @host_id AND hl.health_log_id = hld.health_log_id AND hld.new_status = -2 AND hld.updated_by_id = 0 " \
+ "AND hld.unique_id NOT IN (SELECT alert_unique_id FROM aclk_alert_%s) " \
+ "AND hl.config_hash_id NOT IN (select hash_id from alert_hash where warn is null and crit is null) " \
+ "ORDER BY hld.unique_id ASC ON CONFLICT (alert_unique_id) DO NOTHING;"
void sql_process_queue_removed_alerts_to_aclk(char *node_id)
{
struct aclk_sync_host_config *wc;
@@ -702,15 +698,35 @@ void sql_process_queue_removed_alerts_to_aclk(char *node_id)
return;
char sql[ACLK_SYNC_QUERY_SIZE * 2];
+ sqlite3_stmt *res = NULL;
- snprintfz(sql,ACLK_SYNC_QUERY_SIZE * 2 - 1, SQL_QUEUE_REMOVE_ALERTS, wc->uuid_str, wc->uuid_str, wc->uuid_str);
+ snprintfz(sql, ACLK_SYNC_QUERY_SIZE * 2 - 1, SQL_QUEUE_REMOVE_ALERTS, wc->uuid_str, wc->uuid_str);
- if (unlikely(db_execute(db_meta, sql))) {
- log_access("ACLK STA [%s (%s)]: QUEUED REMOVED ALERTS FAILED", wc->node_id, rrdhost_hostname(wc->host));
- error_report("Failed to queue ACLK alert removed entries for host %s", rrdhost_hostname(wc->host));
+ int rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to queue removed alerts.");
+ return;
}
- else
- log_access("ACLK STA [%s (%s)]: QUEUED REMOVED ALERTS", wc->node_id, rrdhost_hostname(wc->host));
+
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for when trying to queue remvoed alerts.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ sqlite3_finalize(res);
+ error_report("Failed to queue removed alerts, rc = %d", rc);
+ return;
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize statement to queue removed alerts, rc = %d", rc);
+
+ netdata_log_access("ACLK STA [%s (%s)]: QUEUED REMOVED ALERTS", wc->node_id, rrdhost_hostname(wc->host));
rrdhost_flag_set(wc->host, RRDHOST_FLAG_ACLK_STREAM_ALERTS);
wc->alert_queue_removed = 0;
@@ -738,18 +754,18 @@ void aclk_process_send_alarm_snapshot(char *node_id, char *claim_id __maybe_unus
RRDHOST *host = find_host_by_node_id(node_id);
if (unlikely(!host)) {
- log_access("ACLK STA [%s (N/A)]: ACLK node id does not exist", node_id);
+ netdata_log_access("ACLK STA [%s (N/A)]: ACLK node id does not exist", node_id);
return;
}
struct aclk_sync_host_config *wc = (struct aclk_sync_host_config *)host->aclk_sync_host_config;
if (unlikely(!wc)) {
- log_access("ACLK STA [%s (N/A)]: ACLK node id does not exist", node_id);
+ netdata_log_access("ACLK STA [%s (N/A)]: ACLK node id does not exist", node_id);
return;
}
- log_access(
+ netdata_log_access(
"IN [%s (%s)]: Request to send alerts snapshot, snapshot_uuid %s",
node_id,
wc->host ? rrdhost_hostname(wc->host) : "N/A",
@@ -842,7 +858,7 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
RRDHOST *host = find_host_by_node_id(node_id);
if (unlikely(!host)) {
- log_access("AC [%s (N/A)]: Node id not found", node_id);
+ netdata_log_access("AC [%s (N/A)]: Node id not found", node_id);
freez(node_id);
return;
}
@@ -852,7 +868,7 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
// we perhaps we don't need this for snapshots
if (unlikely(!wc->alert_updates)) {
- log_access(
+ netdata_log_access(
"ACLK STA [%s (%s)]: Ignoring alert snapshot event, updates have been turned off for this node.",
wc->node_id,
wc->host ? rrdhost_hostname(wc->host) : "N/A");
@@ -866,13 +882,13 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
if (unlikely(!claim_id))
return;
- log_access("ACLK REQ [%s (%s)]: Sending alerts snapshot, snapshot_uuid %s", wc->node_id, rrdhost_hostname(wc->host), wc->alerts_snapshot_uuid);
+ netdata_log_access("ACLK REQ [%s (%s)]: Sending alerts snapshot, snapshot_uuid %s", wc->node_id, rrdhost_hostname(wc->host), wc->alerts_snapshot_uuid);
uint32_t cnt = 0;
char uuid_str[UUID_STR_LEN];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_read_lock(&host->health_log.spinlock);
ALARM_ENTRY *ae = host->health_log.alarms;
@@ -886,7 +902,7 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
if (have_recent_alarm(host, ae->alarm_id, ae->unique_id))
continue;
- if (is_event_from_alert_variable_config(ae->unique_id, uuid_str))
+ if (is_event_from_alert_variable_config(ae->unique_id, &host->host_uuid))
continue;
cnt++;
@@ -918,7 +934,7 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
if (have_recent_alarm(host, ae->alarm_id, ae->unique_id))
continue;
- if (is_event_from_alert_variable_config(ae->unique_id, uuid_str))
+ if (is_event_from_alert_variable_config(ae->unique_id, &host->host_uuid))
continue;
cnt++;
@@ -957,7 +973,7 @@ void aclk_push_alert_snapshot_event(char *node_id __maybe_unused)
aclk_send_alarm_snapshot(snapshot_proto);
}
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_read_unlock(&host->health_log.spinlock);
wc->alerts_snapshot_uuid = NULL;
freez(claim_id);
@@ -984,7 +1000,6 @@ void sql_aclk_alert_clean_dead_entries(RRDHOST *host)
#define SQL_GET_MIN_MAX_ALERT_SEQ "SELECT MIN(sequence_id), MAX(sequence_id), " \
"(SELECT MAX(sequence_id) FROM aclk_alert_%s WHERE date_submitted IS NOT NULL) " \
"FROM aclk_alert_%s WHERE date_submitted IS NULL;"
-
int get_proto_alert_status(RRDHOST *host, struct proto_alert_status *proto_alert_status)
{
int rc;
@@ -1032,11 +1047,11 @@ void aclk_send_alarm_checkpoint(char *node_id, char *claim_id __maybe_unused)
wc = (struct aclk_sync_host_config *)host->aclk_sync_host_config;
if (unlikely(!wc)) {
- log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT REQUEST RECEIVED FOR INVALID NODE", node_id);
+ netdata_log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT REQUEST RECEIVED FOR INVALID NODE", node_id);
return;
}
- log_access("ACLK REQ [%s (%s)]: ALERTS CHECKPOINT REQUEST RECEIVED", node_id, rrdhost_hostname(host));
+ netdata_log_access("ACLK REQ [%s (%s)]: ALERTS CHECKPOINT REQUEST RECEIVED", node_id, rrdhost_hostname(host));
wc->alert_checkpoint_req = SEND_CHECKPOINT_AFTER_HEALTH_LOOPS;
}
@@ -1065,14 +1080,14 @@ void aclk_push_alarm_checkpoint(RRDHOST *host __maybe_unused)
#ifdef ENABLE_ACLK
struct aclk_sync_host_config *wc = host->aclk_sync_host_config;
if (unlikely(!wc)) {
- log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT REQUEST RECEIVED FOR INVALID NODE", rrdhost_hostname(host));
+ netdata_log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT REQUEST RECEIVED FOR INVALID NODE", rrdhost_hostname(host));
return;
}
if (rrdhost_flag_check(host, RRDHOST_FLAG_ACLK_STREAM_ALERTS)) {
//postpone checkpoint send
wc->alert_checkpoint_req+=3;
- log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT POSTPONED", rrdhost_hostname(host));
+ netdata_log_access("ACLK REQ [%s (N/A)]: ALERTS CHECKPOINT POSTPONED", rrdhost_hostname(host));
return;
}
@@ -1135,9 +1150,9 @@ void aclk_push_alarm_checkpoint(RRDHOST *host __maybe_unused)
aclk_send_provide_alarm_checkpoint(&alarm_checkpoint);
freez(claim_id);
- log_access("ACLK RES [%s (%s)]: ALERTS CHECKPOINT SENT", wc->node_id, rrdhost_hostname(host));
+ netdata_log_access("ACLK RES [%s (%s)]: ALERTS CHECKPOINT SENT", wc->node_id, rrdhost_hostname(host));
} else {
- log_access("ACLK RES [%s (%s)]: FAILED TO CREATE ALERTS CHECKPOINT HASH", wc->node_id, rrdhost_hostname(host));
+ netdata_log_access("ACLK RES [%s (%s)]: FAILED TO CREATE ALERTS CHECKPOINT HASH", wc->node_id, rrdhost_hostname(host));
}
wc->alert_checkpoint_req = 0;
buffer_free(alarms_to_hash);
diff --git a/database/sqlite/sqlite_aclk_node.c b/database/sqlite/sqlite_aclk_node.c
index 3817296da..82927854a 100644
--- a/database/sqlite/sqlite_aclk_node.c
+++ b/database/sqlite/sqlite_aclk_node.c
@@ -50,7 +50,7 @@ static void build_node_collectors(char *node_id __maybe_unused)
dictionary_destroy(dict);
freez(upd_node_collectors.claim_id);
- log_access("ACLK RES [%s (%s)]: NODE COLLECTORS SENT", node_id, rrdhost_hostname(host));
+ netdata_log_access("ACLK RES [%s (%s)]: NODE COLLECTORS SENT", node_id, rrdhost_hostname(host));
freez(node_id);
}
@@ -124,7 +124,7 @@ static void build_node_info(char *node_id __maybe_unused)
node_info.data.host_labels_ptr = host->rrdlabels;
aclk_update_node_info(&node_info);
- log_access("ACLK RES [%s (%s)]: NODE INFO SENT for guid [%s] (%s)", wc->node_id, rrdhost_hostname(wc->host), host->machine_guid, wc->host == localhost ? "parent" : "child");
+ netdata_log_access("ACLK RES [%s (%s)]: NODE INFO SENT for guid [%s] (%s)", wc->node_id, rrdhost_hostname(wc->host), host->machine_guid, wc->host == localhost ? "parent" : "child");
rrd_unlock();
freez(node_info.claim_id);
@@ -172,7 +172,7 @@ void aclk_check_node_info_and_collectors(void)
dfe_done(host);
if(pending)
- info("ACLK: %zu nodes are pending for contexts to load, skipped sending node info for them", pending);
+ netdata_log_info("ACLK: %zu nodes are pending for contexts to load, skipped sending node info for them", pending);
}
#endif
diff --git a/database/sqlite/sqlite_context.c b/database/sqlite/sqlite_context.c
index b72726dc2..f29fe51e3 100644
--- a/database/sqlite/sqlite_context.c
+++ b/database/sqlite/sqlite_context.c
@@ -43,7 +43,7 @@ int sql_init_context_database(int memory)
return 1;
}
- info("SQLite database %s initialization", sqlite_database);
+ netdata_log_info("SQLite database %s initialization", sqlite_database);
char buf[1024 + 1] = "";
const char *list[2] = { buf, NULL };
@@ -112,7 +112,7 @@ void sql_close_context_database(void)
if (unlikely(!db_context_meta))
return;
- info("Closing context SQLite database");
+ netdata_log_info("Closing context SQLite database");
rc = sqlite3_close_v2(db_context_meta);
if (unlikely(rc != SQLITE_OK))
@@ -431,7 +431,7 @@ int ctx_delete_context(uuid_t *host_uuid, VERSIONED_CONTEXT_DATA *context_data)
else {
char host_uuid_str[UUID_STR_LEN];
uuid_unparse_lower(*host_uuid, host_uuid_str);
- info("%s: Deleted context %s under host %s", __FUNCTION__, context_data->id, host_uuid_str);
+ netdata_log_info("%s: Deleted context %s under host %s", __FUNCTION__, context_data->id, host_uuid_str);
}
#endif
@@ -463,7 +463,7 @@ int sql_context_cache_stats(int op)
static void dict_ctx_get_context_list_cb(VERSIONED_CONTEXT_DATA *context_data, void *data)
{
(void)data;
- info(" Context id = %s "
+ netdata_log_info(" Context id = %s "
"version = %"PRIu64" "
"title = %s "
"chart_type = %s "
@@ -512,48 +512,48 @@ int ctx_unittest(void)
context_data.version = now_realtime_usec();
if (likely(!ctx_store_context(&host_uuid, &context_data)))
- info("Entry %s inserted", context_data.id);
+ netdata_log_info("Entry %s inserted", context_data.id);
else
- info("Entry %s not inserted", context_data.id);
+ netdata_log_info("Entry %s not inserted", context_data.id);
if (likely(!ctx_store_context(&host_uuid, &context_data)))
- info("Entry %s inserted", context_data.id);
+ netdata_log_info("Entry %s inserted", context_data.id);
else
- info("Entry %s not inserted", context_data.id);
+ netdata_log_info("Entry %s not inserted", context_data.id);
// This will change end time
context_data.first_time_s = 1657781000;
context_data.last_time_s = 1657782001;
if (likely(!ctx_update_context(&host_uuid, &context_data)))
- info("Entry %s updated", context_data.id);
+ netdata_log_info("Entry %s updated", context_data.id);
else
- info("Entry %s not updated", context_data.id);
- info("List context start after insert");
+ netdata_log_info("Entry %s not updated", context_data.id);
+ netdata_log_info("List context start after insert");
ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
- info("List context end after insert");
+ netdata_log_info("List context end after insert");
// This will change start time
context_data.first_time_s = 1657782000;
context_data.last_time_s = 1657782001;
if (likely(!ctx_update_context(&host_uuid, &context_data)))
- info("Entry %s updated", context_data.id);
+ netdata_log_info("Entry %s updated", context_data.id);
else
- info("Entry %s not updated", context_data.id);
+ netdata_log_info("Entry %s not updated", context_data.id);
// This will list one entry
- info("List context start after insert");
+ netdata_log_info("List context start after insert");
ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
- info("List context end after insert");
+ netdata_log_info("List context end after insert");
- info("List context start after insert");
+ netdata_log_info("List context start after insert");
ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
- info("List context end after insert");
+ netdata_log_info("List context end after insert");
// This will delete the entry
if (likely(!ctx_delete_context(&host_uuid, &context_data)))
- info("Entry %s deleted", context_data.id);
+ netdata_log_info("Entry %s deleted", context_data.id);
else
- info("Entry %s not deleted", context_data.id);
+ netdata_log_info("Entry %s not deleted", context_data.id);
freez((void *)context_data.id);
freez((void *)context_data.title);
@@ -562,9 +562,9 @@ int ctx_unittest(void)
freez((void *)context_data.units);
// The list should be empty
- info("List context start after delete");
+ netdata_log_info("List context start after delete");
ctx_get_context_list(&host_uuid, dict_ctx_get_context_list_cb, NULL);
- info("List context end after delete");
+ netdata_log_info("List context end after delete");
sql_close_context_database();
diff --git a/database/sqlite/sqlite_db_migration.c b/database/sqlite/sqlite_db_migration.c
index 9c7235fdb..1a6233fce 100644
--- a/database/sqlite/sqlite_db_migration.c
+++ b/database/sqlite/sqlite_db_migration.c
@@ -11,7 +11,6 @@ static int return_int_cb(void *data, int argc, char **argv, char **column)
return 0;
}
-
int table_exists_in_database(const char *table)
{
char *err_msg = NULL;
@@ -23,7 +22,7 @@ int table_exists_in_database(const char *table)
int rc = sqlite3_exec_monitored(db_meta, sql, return_int_cb, (void *) &exists, &err_msg);
if (rc != SQLITE_OK) {
- info("Error checking table existence; %s", err_msg);
+ netdata_log_info("Error checking table existence; %s", err_msg);
sqlite3_free(err_msg);
}
@@ -41,7 +40,7 @@ static int column_exists_in_table(const char *table, const char *column)
int rc = sqlite3_exec_monitored(db_meta, sql, return_int_cb, (void *) &exists, &err_msg);
if (rc != SQLITE_OK) {
- info("Error checking column existence; %s", err_msg);
+ netdata_log_info("Error checking column existence; %s", err_msg);
sqlite3_free(err_msg);
}
@@ -79,11 +78,15 @@ const char *database_migrate_v5_v6[] = {
NULL
};
+const char *database_migrate_v9_v10[] = {
+ "ALTER TABLE alert_hash ADD chart_labels TEXT;",
+ NULL
+};
static int do_migration_v1_v2(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running \"%s\" database migration", name);
+ netdata_log_info("Running \"%s\" database migration", name);
if (table_exists_in_database("host") && !column_exists_in_table("host", "hops"))
return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v1_v2[0]);
@@ -93,7 +96,7 @@ static int do_migration_v1_v2(sqlite3 *database, const char *name)
static int do_migration_v2_v3(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running \"%s\" database migration", name);
+ netdata_log_info("Running \"%s\" database migration", name);
if (table_exists_in_database("host") && !column_exists_in_table("host", "memory_mode"))
return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v2_v3[0]);
@@ -103,7 +106,7 @@ static int do_migration_v2_v3(sqlite3 *database, const char *name)
static int do_migration_v3_v4(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running database migration %s", name);
+ netdata_log_info("Running database migration %s", name);
char sql[256];
@@ -135,7 +138,7 @@ static int do_migration_v3_v4(sqlite3 *database, const char *name)
static int do_migration_v4_v5(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running \"%s\" database migration", name);
+ netdata_log_info("Running \"%s\" database migration", name);
return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v4_v5[0]);
}
@@ -143,7 +146,7 @@ static int do_migration_v4_v5(sqlite3 *database, const char *name)
static int do_migration_v5_v6(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running \"%s\" database migration", name);
+ netdata_log_info("Running \"%s\" database migration", name);
return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v5_v6[0]);
}
@@ -151,7 +154,7 @@ static int do_migration_v5_v6(sqlite3 *database, const char *name)
static int do_migration_v6_v7(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running \"%s\" database migration", name);
+ netdata_log_info("Running \"%s\" database migration", name);
char sql[256];
@@ -185,7 +188,7 @@ static int do_migration_v6_v7(sqlite3 *database, const char *name)
static int do_migration_v7_v8(sqlite3 *database, const char *name)
{
UNUSED(name);
- info("Running database migration %s", name);
+ netdata_log_info("Running database migration %s", name);
char sql[256];
@@ -214,12 +217,95 @@ static int do_migration_v7_v8(sqlite3 *database, const char *name)
return 0;
}
+static int do_migration_v8_v9(sqlite3 *database, const char *name)
+{
+ netdata_log_info("Running database migration %s", name);
+
+ char sql[2048];
+ int rc;
+ sqlite3_stmt *res = NULL;
+
+ //create the health_log table and it's index
+ snprintfz(sql, 2047, "CREATE TABLE IF NOT EXISTS health_log (health_log_id INTEGER PRIMARY KEY, host_id blob, alarm_id int, " \
+ "config_hash_id blob, name text, chart text, family text, recipient text, units text, exec text, " \
+ "chart_context text, last_transition_id blob, UNIQUE (host_id, alarm_id)) ;");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ //TODO indexes
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS health_log_ind_1 ON health_log (host_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ snprintfz(sql, 2047, "CREATE TABLE IF NOT EXISTS health_log_detail (health_log_id int, unique_id int, alarm_id int, alarm_event_id int, " \
+ "updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, " \
+ "flags int, exec_run_timestamp int, delay_up_to_timestamp int, " \
+ "info text, exec_code int, new_status real, old_status real, delay int, " \
+ "new_value double, old_value double, last_repeat int, transition_id blob, global_id int, host_id blob);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS health_log_d_ind_1 ON health_log_detail (unique_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS health_log_d_ind_2 ON health_log_detail (global_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS health_log_d_ind_3 ON health_log_detail (transition_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS health_log_d_ind_4 ON health_log_detail (health_log_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ snprintfz(sql, 2047, "ALTER TABLE alert_hash ADD source text;");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ snprintfz(sql, 2047, "CREATE INDEX IF NOT EXISTS alert_hash_index ON alert_hash (hash_id);");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ snprintfz(sql, 2047, "SELECT name FROM sqlite_schema WHERE type ='table' AND name LIKE 'health_log_%%' AND name <> 'health_log_detail';");
+ rc = sqlite3_prepare_v2(database, sql, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement to alter health_log tables");
+ return 1;
+ }
+
+ DICTIONARY *dict_tables = dictionary_create(DICT_OPTION_NONE);
+
+ while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+ char *table = strdupz((char *) sqlite3_column_text(res, 0));
+ if (health_migrate_old_health_log_table(table)) {
+ dictionary_set(dict_tables, table, NULL, 0);
+ }
+ freez(table);
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize statement when copying health_log tables, rc = %d", rc);
+
+ char *table = NULL;
+ dfe_start_read(dict_tables, table) {
+ sql_drop_table(table_dfe.name);
+ }
+ dfe_done(table);
+ dictionary_destroy(dict_tables);
+
+ snprintfz(sql, 2047, "ALTER TABLE health_log_detail DROP COLUMN host_id;");
+ sqlite3_exec_monitored(database, sql, 0, 0, NULL);
+
+ return 0;
+}
+
+static int do_migration_v9_v10(sqlite3 *database, const char *name)
+{
+ UNUSED(name);
+ netdata_log_info("Running \"%s\" database migration", name);
+
+ if (table_exists_in_database("alert_hash") && !column_exists_in_table("alert_hash", "chart_labels"))
+ return init_database_batch(database, DB_CHECK_NONE, 0, &database_migrate_v9_v10[0]);
+ return 0;
+}
static int do_migration_noop(sqlite3 *database, const char *name)
{
UNUSED(database);
UNUSED(name);
- info("Running database migration %s", name);
+ netdata_log_info("Running database migration %s", name);
return 0;
}
@@ -236,16 +322,16 @@ static int migrate_database(sqlite3 *database, int target_version, char *db_name
int rc = sqlite3_exec_monitored(database, "PRAGMA user_version;", return_int_cb, (void *) &user_version, &err_msg);
if (rc != SQLITE_OK) {
- info("Error checking the %s database version; %s", db_name, err_msg);
+ netdata_log_info("Error checking the %s database version; %s", db_name, err_msg);
sqlite3_free(err_msg);
}
if (likely(user_version == target_version)) {
- info("%s database version is %d (no migration needed)", db_name, target_version);
+ netdata_log_info("%s database version is %d (no migration needed)", db_name, target_version);
return target_version;
}
- info("Database version is %d, current version is %d. Running migration for %s ...", user_version, target_version, db_name);
+ netdata_log_info("Database version is %d, current version is %d. Running migration for %s ...", user_version, target_version, db_name);
for (int i = user_version; i < target_version && migration_list[i].func; i++) {
rc = (migration_list[i].func)(database, migration_list[i].name);
if (unlikely(rc)) {
@@ -266,6 +352,8 @@ DATABASE_FUNC_MIGRATION_LIST migration_action[] = {
{.name = "v5 to v6", .func = do_migration_v5_v6},
{.name = "v6 to v7", .func = do_migration_v6_v7},
{.name = "v7 to v8", .func = do_migration_v7_v8},
+ {.name = "v8 to v9", .func = do_migration_v8_v9},
+ {.name = "v9 to v10", .func = do_migration_v9_v10},
// the terminator of this array
{.name = NULL, .func = NULL}
};
diff --git a/database/sqlite/sqlite_functions.c b/database/sqlite/sqlite_functions.c
index 555db1011..4200c1590 100644
--- a/database/sqlite/sqlite_functions.c
+++ b/database/sqlite/sqlite_functions.c
@@ -3,7 +3,7 @@
#include "sqlite_functions.h"
#include "sqlite_db_migration.h"
-#define DB_METADATA_VERSION 8
+#define DB_METADATA_VERSION 10
const char *database_config[] = {
"CREATE TABLE IF NOT EXISTS host(host_id BLOB PRIMARY KEY, hostname TEXT NOT NULL, "
@@ -32,7 +32,9 @@ const char *database_config[] = {
"every text, units text, calc text, families text, plugin text, module text, charts text, green text, "
"red text, warn text, crit text, exec text, to_key text, info text, delay text, options text, "
"repeat text, host_labels text, p_db_lookup_dimensions text, p_db_lookup_method text, p_db_lookup_options int, "
- "p_db_lookup_after int, p_db_lookup_before int, p_update_every int);",
+ "p_db_lookup_after int, p_db_lookup_before int, p_update_every int, source text, chart_labels text);",
+
+ "CREATE INDEX IF NOT EXISTS alert_hash_index ON alert_hash (hash_id);",
"CREATE TABLE IF NOT EXISTS host_info(host_id blob, system_key text NOT NULL, system_value text NOT NULL, "
"date_created INT, PRIMARY KEY(host_id, system_key));",
@@ -43,6 +45,23 @@ const char *database_config[] = {
"CREATE TRIGGER IF NOT EXISTS ins_host AFTER INSERT ON host BEGIN INSERT INTO node_instance (host_id, date_created)"
" SELECT new.host_id, unixepoch() WHERE new.host_id NOT IN (SELECT host_id FROM node_instance); END;",
+ "CREATE TABLE IF NOT EXISTS health_log (health_log_id INTEGER PRIMARY KEY, host_id blob, alarm_id int, "
+ "config_hash_id blob, name text, chart text, family text, recipient text, units text, exec text, "
+ "chart_context text, last_transition_id blob, UNIQUE (host_id, alarm_id)) ;",
+
+ "CREATE INDEX IF NOT EXISTS health_log_ind_1 ON health_log (host_id);",
+
+ "CREATE TABLE IF NOT EXISTS health_log_detail (health_log_id int, unique_id int, alarm_id int, alarm_event_id int, "
+ "updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, "
+ "flags int, exec_run_timestamp int, delay_up_to_timestamp int, "
+ "info text, exec_code int, new_status real, old_status real, delay int, "
+ "new_value double, old_value double, last_repeat int, transition_id blob, global_id int);",
+
+ "CREATE INDEX IF NOT EXISTS health_log_d_ind_1 ON health_log_detail (unique_id);",
+ "CREATE INDEX IF NOT EXISTS health_log_d_ind_2 ON health_log_detail (global_id);",
+ "CREATE INDEX IF NOT EXISTS health_log_d_ind_3 ON health_log_detail (transition_id);",
+ "CREATE INDEX IF NOT EXISTS health_log_d_ind_4 ON health_log_detail (health_log_id);",
+
NULL
};
@@ -128,9 +147,9 @@ static void add_stmt_to_list(sqlite3_stmt *res)
if (unlikely(!res)) {
if (idx)
- info("Finilizing %d statements", idx);
+ netdata_log_info("Finilizing %d statements", idx);
else
- info("No statements pending to finalize");
+ netdata_log_info("No statements pending to finalize");
while (idx > 0) {
int rc;
rc = sqlite3_finalize(statements[--idx]);
@@ -148,7 +167,7 @@ static void release_statement(void *statement)
{
int rc;
#ifdef NETDATA_DEV_MODE
- info("Thread %d: Cleaning prepared statement on %p", gettid(), statement);
+ netdata_log_info("Thread %d: Cleaning prepared statement on %p", gettid(), statement);
#endif
if (unlikely(rc = sqlite3_finalize((sqlite3_stmt *) statement) != SQLITE_OK))
error_report("Failed to finalize statement, rc = %d", rc);
@@ -175,7 +194,7 @@ int prepare_statement(sqlite3 *database, const char *query, sqlite3_stmt **state
if (likely(key)) {
ret = pthread_setspecific(*key, *statement);
#ifdef NETDATA_DEV_MODE
- info("Thread %d: Using key %u on statement %p", gettid(), keys_used, *statement);
+ netdata_log_info("Thread %d: Using key %u on statement %p", gettid(), keys_used, *statement);
#endif
}
if (ret)
@@ -189,7 +208,7 @@ static int check_table_integrity_cb(void *data, int argc, char **argv, char **co
int *status = data;
UNUSED(argc);
UNUSED(column);
- info("---> %s", argv[0]);
+ netdata_log_info("---> %s", argv[0]);
*status = (strcmp(argv[0], "ok") != 0);
return 0;
}
@@ -202,11 +221,11 @@ static int check_table_integrity(char *table)
char wstr[255];
if (table) {
- info("Checking table %s", table);
+ netdata_log_info("Checking table %s", table);
snprintfz(wstr, 254, "PRAGMA integrity_check(%s);", table);
}
else {
- info("Checking entire database");
+ netdata_log_info("Checking entire database");
strcpy(wstr,"PRAGMA integrity_check;");
}
@@ -240,9 +259,9 @@ static void rebuild_chart()
{
int rc;
char *err_msg = NULL;
- info("Rebuilding chart table");
+ netdata_log_info("Rebuilding chart table");
for (int i = 0; rebuild_chart_commands[i]; i++) {
- info("Executing %s", rebuild_chart_commands[i]);
+ netdata_log_info("Executing %s", rebuild_chart_commands[i]);
rc = sqlite3_exec_monitored(db_meta, rebuild_chart_commands[i], 0, 0, &err_msg);
if (rc != SQLITE_OK) {
error_report("SQLite error during database setup, rc = %d (%s)", rc, err_msg);
@@ -272,9 +291,9 @@ void rebuild_dimension()
int rc;
char *err_msg = NULL;
- info("Rebuilding dimension table");
+ netdata_log_info("Rebuilding dimension table");
for (int i = 0; rebuild_dimension_commands[i]; i++) {
- info("Executing %s", rebuild_dimension_commands[i]);
+ netdata_log_info("Executing %s", rebuild_dimension_commands[i]);
rc = sqlite3_exec_monitored(db_meta, rebuild_dimension_commands[i], 0, 0, &err_msg);
if (rc != SQLITE_OK) {
error_report("SQLite error during database setup, rc = %d (%s)", rc, err_msg);
@@ -286,11 +305,11 @@ void rebuild_dimension()
static int attempt_database_fix()
{
- info("Closing database and attempting to fix it");
+ netdata_log_info("Closing database and attempting to fix it");
int rc = sqlite3_close(db_meta);
if (rc != SQLITE_OK)
error_report("Failed to close database, rc = %d", rc);
- info("Attempting to fix database");
+ netdata_log_info("Attempting to fix database");
db_meta = NULL;
return sql_init_database(DB_CHECK_FIX_DB | DB_CHECK_CONT, 0);
}
@@ -300,7 +319,7 @@ int init_database_batch(sqlite3 *database, int rebuild, int init_type, const cha
int rc;
char *err_msg = NULL;
for (int i = 0; batch[i]; i++) {
- debug(D_METADATALOG, "Executing %s", batch[i]);
+ netdata_log_debug(D_METADATALOG, "Executing %s", batch[i]);
rc = sqlite3_exec_monitored(database, batch[i], 0, 0, &err_msg);
if (rc != SQLITE_OK) {
error_report("SQLite error during database %s, rc = %d (%s)", init_type ? "cleanup" : "setup", rc, err_msg);
@@ -336,6 +355,30 @@ static void sqlite_uuid_parse(sqlite3_context *context, int argc, sqlite3_value
sqlite3_result_blob(context, &uuid, sizeof(uuid_t), SQLITE_TRANSIENT);
}
+void sqlite_now_usec(sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+ if (argc != 1 ){
+ sqlite3_result_null(context);
+ return ;
+ }
+
+ if (sqlite3_value_int(argv[0]) != 0) {
+ struct timespec req = {.tv_sec = 0, .tv_nsec = 1};
+ nanosleep(&req, NULL);
+ }
+
+ sqlite3_result_int64(context, (sqlite_int64) now_realtime_usec());
+}
+
+void sqlite_uuid_random(sqlite3_context *context, int argc, sqlite3_value **argv)
+{
+ (void)argc;
+ (void)argv;
+
+ uuid_t uuid;
+ uuid_generate_random(uuid);
+ sqlite3_result_blob(context, &uuid, sizeof(uuid_t), SQLITE_TRANSIENT);
+}
/*
* Initialize the SQLite database
@@ -363,7 +406,7 @@ int sql_init_database(db_check_action_type_t rebuild, int memory)
if (rebuild & (DB_CHECK_INTEGRITY | DB_CHECK_FIX_DB)) {
int errors_detected = 0;
if (!(rebuild & DB_CHECK_CONT))
- info("Running database check on %s", sqlite_database);
+ netdata_log_info("Running database check on %s", sqlite_database);
if (check_table_integrity("chart")) {
errors_detected++;
@@ -389,7 +432,7 @@ int sql_init_database(db_check_action_type_t rebuild, int memory)
if (rebuild & DB_CHECK_RECLAIM_SPACE) {
if (!(rebuild & DB_CHECK_CONT))
- info("Reclaiming space of %s", sqlite_database);
+ netdata_log_info("Reclaiming space of %s", sqlite_database);
rc = sqlite3_exec_monitored(db_meta, "VACUUM;", 0, 0, &err_msg);
if (rc != SQLITE_OK) {
error_report("Failed to execute VACUUM rc = %d (%s)", rc, err_msg);
@@ -400,11 +443,23 @@ int sql_init_database(db_check_action_type_t rebuild, int memory)
if (rebuild && !(rebuild & DB_CHECK_CONT))
return 1;
- info("SQLite database %s initialization", sqlite_database);
+ netdata_log_info("SQLite database %s initialization", sqlite_database);
char buf[1024 + 1] = "";
const char *list[2] = { buf, NULL };
+ rc = sqlite3_create_function(db_meta, "u2h", 1, SQLITE_ANY | SQLITE_DETERMINISTIC, 0, sqlite_uuid_parse, 0, 0);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to register internal u2h function");
+
+ rc = sqlite3_create_function(db_meta, "now_usec", 1, SQLITE_ANY, 0, sqlite_now_usec, 0, 0);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to register internal now_usec function");
+
+ rc = sqlite3_create_function(db_meta, "uuid_random", 0, SQLITE_ANY, 0, sqlite_uuid_random, 0, 0);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to register internal uuid_random function");
+
int target_version = DB_METADATA_VERSION;
if (likely(!memory))
@@ -450,13 +505,10 @@ int sql_init_database(db_check_action_type_t rebuild, int memory)
if (init_database_batch(db_meta, rebuild, 0, &database_cleanup[0]))
return 1;
- info("SQLite database initialization completed");
+ netdata_log_info("SQLite database initialization completed");
initialize_thread_key_pool();
- rc = sqlite3_create_function(db_meta, "u2h", 1, SQLITE_ANY | SQLITE_DETERMINISTIC, 0, sqlite_uuid_parse, 0, 0);
- if (unlikely(rc != SQLITE_OK))
- error_report("Failed to register internal u2h function");
return 0;
}
@@ -470,7 +522,7 @@ void sql_close_database(void)
if (unlikely(!db_meta))
return;
- info("Closing SQLite database");
+ netdata_log_info("Closing SQLite database");
add_stmt_to_list(NULL);
@@ -771,7 +823,7 @@ struct node_instance_list *get_node_list(void)
uuid_unparse_lower(*host_id, host_guid);
RRDHOST *host = rrdhost_find_by_guid(host_guid);
if (rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD)) {
- info("ACLK: 'host:%s' skipping get node list because context is initializing", rrdhost_hostname(host));
+ netdata_log_info("ACLK: 'host:%s' skipping get node list because context is initializing", rrdhost_hostname(host));
continue;
}
uuid_copy(node_list[row].host_id, *host_id);
@@ -927,3 +979,19 @@ int sql_metadata_cache_stats(int op)
netdata_thread_enable_cancelability();
return count;
}
+
+#define SQL_DROP_TABLE "DROP table %s;"
+
+void sql_drop_table(const char *table)
+{
+ if (!table)
+ return;
+
+ char wstr[255];
+ snprintfz(wstr, 254, SQL_DROP_TABLE, table);
+
+ int rc = sqlite3_exec_monitored(db_meta, wstr, 0, 0, NULL);
+ if (rc != SQLITE_OK) {
+ error_report("DES SQLite error during drop table operation for %s, rc = %d", table, rc);
+ }
+}
diff --git a/database/sqlite/sqlite_functions.h b/database/sqlite/sqlite_functions.h
index ee63a397c..407ed1eff 100644
--- a/database/sqlite/sqlite_functions.h
+++ b/database/sqlite/sqlite_functions.h
@@ -77,4 +77,6 @@ void invalidate_node_instances(uuid_t *host_id, uuid_t *claim_id);
// Provide statistics
int sql_metadata_cache_stats(int op);
+void sql_drop_table(const char *table);
+void sqlite_now_usec(sqlite3_context *context, int argc, sqlite3_value **argv);
#endif //NETDATA_SQLITE_FUNCTIONS_H
diff --git a/database/sqlite/sqlite_health.c b/database/sqlite/sqlite_health.c
index 5c4cdbbd3..3ecd783dc 100644
--- a/database/sqlite/sqlite_health.c
+++ b/database/sqlite/sqlite_health.c
@@ -8,45 +8,12 @@
#define sqlite3_bind_string_or_null(res,key,param) ((key) ? sqlite3_bind_text(res, param, string2str(key), -1, SQLITE_STATIC) : sqlite3_bind_null(res, param))
/* Health related SQL queries
- Creates a health log table in sqlite, one per host guid
-*/
-#define SQL_CREATE_HEALTH_LOG_TABLE(guid) "CREATE TABLE IF NOT EXISTS health_log_%s(hostname text, unique_id int, alarm_id int, alarm_event_id int, config_hash_id blob, updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, flags int, exec_run_timestamp int, delay_up_to_timestamp int, name text, chart text, family text, exec text, recipient text, source text, units text, info text, exec_code int, new_status real, old_status real, delay int, new_value double, old_value double, last_repeat int, class text, component text, type text, chart_context text, transition_id blob);", guid
-int sql_create_health_log_table(RRDHOST *host) {
- int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
-
- if (unlikely(!db_meta)) {
- if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
- error_report("HEALTH [%s]: Database has not been initialized", rrdhost_hostname(host));
- return 1;
- }
-
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CREATE_HEALTH_LOG_TABLE(uuid_str));
-
- rc = db_execute(db_meta, command);
- if (unlikely(rc))
- error_report("HEALTH [%s]: SQLite error during creation of health log table", rrdhost_hostname(host));
- else {
- snprintfz(command, MAX_HEALTH_SQL_SIZE, "CREATE INDEX IF NOT EXISTS health_log_index_%s ON health_log_%s (unique_id); ", uuid_str, uuid_str);
- rc = db_execute(db_meta, command);
- if (unlikely(unlikely(rc)))
- error_report("HEALTH [%s]: SQLite error during creation of health log table index", rrdhost_hostname(host));
- }
-
- return rc;
-}
-
-/* Health related SQL queries
Updates an entry in the table
*/
-#define SQL_UPDATE_HEALTH_LOG(guid) "UPDATE health_log_%s set updated_by_id = ?, flags = ?, exec_run_timestamp = ?, exec_code = ? where unique_id = ?;", guid
+#define SQL_UPDATE_HEALTH_LOG "UPDATE health_log_detail set updated_by_id = ?, flags = ?, exec_run_timestamp = ?, exec_code = ? where unique_id = ? AND alarm_id = ? and transition_id = ?;"
void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
sqlite3_stmt *res = NULL;
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
if (unlikely(!db_meta)) {
if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
@@ -54,19 +21,10 @@ void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
return;
}
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_UPDATE_HEALTH_LOG(uuid_str));
-
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG, -1, &res, 0);
if (unlikely(rc != SQLITE_OK)) {
- sql_create_health_log_table(host);
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
- if (unlikely(rc != SQLITE_OK)) {
- error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
- return;
- }
+ error_report("HEALTH [%s]: Failed to prepare statement for SQL_UPDATE_HEALTH_LOG", rrdhost_hostname(host));
+ return;
}
rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) ae->updated_by_id);
@@ -99,6 +57,18 @@ void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
goto failed;
}
+ rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->alarm_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind unique_id parameter for SQL_UPDATE_HEALTH_LOG");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_blob(res, 7, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for SQL_UPDATE_HEALTH_LOG.");
+ goto failed;
+ }
+
rc = execute_insert(res);
if (unlikely(rc != SQLITE_DONE)) {
error_report("HEALTH [%s]: Failed to update health log, rc = %d", rrdhost_hostname(host), rc);
@@ -112,16 +82,19 @@ failed:
/* Health related SQL queries
Inserts an entry in the table
*/
-#define SQL_INSERT_HEALTH_LOG(guid) "INSERT INTO health_log_%s(hostname, unique_id, alarm_id, alarm_event_id, " \
- "config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, " \
- "exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, " \
- "units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, " \
- "class, component, type, chart_context, transition_id) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);", guid
-
+#define SQL_INSERT_HEALTH_LOG "INSERT INTO health_log (host_id, alarm_id, " \
+ "config_hash_id, name, chart, family, exec, recipient, units, chart_context, last_transition_id) " \
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?) " \
+ "ON CONFLICT (host_id, alarm_id) DO UPDATE SET last_transition_id = excluded.last_transition_id RETURNING health_log_id; "
+
+#define SQL_INSERT_HEALTH_LOG_DETAIL "INSERT INTO health_log_detail (health_log_id, unique_id, alarm_id, alarm_event_id, " \
+ "updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, " \
+ "info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id) " \
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,@global_id); "
void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
sqlite3_stmt *res = NULL;
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
+ uint64_t health_log_id = 0;
if (unlikely(!db_meta)) {
if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
@@ -129,222 +102,231 @@ void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
return;
}
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INSERT_HEALTH_LOG(uuid_str));
-
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG, -1, &res, 0);
if (unlikely(rc != SQLITE_OK)) {
- sql_create_health_log_table(host);
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
- if (unlikely(rc != SQLITE_OK)) {
- error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
- return;
- }
+ error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG", rrdhost_hostname(host));
+ return;
}
- rc = sqlite3_bind_text(res, 1, rrdhost_hostname(host), -1, SQLITE_STATIC);
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind hostname parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind host_id for SQL_INSERT_HEALTH_LOG.");
goto failed;
}
- rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->unique_id);
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->alarm_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind alarm_id parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->alarm_id);
+ rc = sqlite3_bind_blob(res, 3, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind alarm_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) ae->alarm_event_id);
+ rc = sqlite3_bind_string_or_null(res, ae->name, 4);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind alarm_event_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind name parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_blob(res, 5, &ae->config_hash_id, sizeof(ae->config_hash_id), SQLITE_STATIC);
+ rc = sqlite3_bind_string_or_null(res, ae->chart, 5);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind chart parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->updated_by_id);
+ rc = sqlite3_bind_string_or_null(res, ae->family, 6);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind updated_by_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind family parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 7, (sqlite3_int64) ae->updates_id);
+ rc = sqlite3_bind_string_or_null(res, ae->exec, 7);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind updates_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind exec parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 8, (sqlite3_int64) ae->when);
+ rc = sqlite3_bind_string_or_null(res, ae->recipient, 8);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind when parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind recipient parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 9, (sqlite3_int64) ae->duration);
+ rc = sqlite3_bind_string_or_null(res, ae->units, 9);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind duration parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind host_id parameter to store node instance information");
goto failed;
}
- rc = sqlite3_bind_int64(res, 10, (sqlite3_int64) ae->non_clear_duration);
+ rc = sqlite3_bind_string_or_null(res, ae->chart_context, 10);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind non_clear_duration parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 11, (sqlite3_int64) ae->flags);
+ rc = sqlite3_bind_blob(res, 11, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind flags parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG");
goto failed;
}
- rc = sqlite3_bind_int64(res, 12, (sqlite3_int64) ae->exec_run_timestamp);
+ rc = sqlite3_step_monitored(res);
+ if (likely(rc == SQLITE_ROW))
+ health_log_id = (size_t) sqlite3_column_int64(res, 0);
+ else {
+ error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", rrdhost_hostname(host), rc);
+ goto failed;
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("HEALTH [%s]: Failed to finalize the prepared statement for inserting to health log.", rrdhost_hostname(host));
+
+ rc = sqlite3_prepare_v2(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("HEALTH [%s]: Failed to prepare statement for SQL_INSERT_HEALTH_LOG_DETAIL", rrdhost_hostname(host));
+ return;
+ }
+
+ rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind exec_run_timestamp parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int64(res, 13, (sqlite3_int64) ae->delay_up_to_timestamp);
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) ae->unique_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind delay_up_to_timestamp parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->name, 14);
+ rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) ae->alarm_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind name parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind unique_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->chart, 15);
+ rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) ae->alarm_event_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind chart parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind alarm_event_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->family, 16);
+ rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) ae->updated_by_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind family parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind updated_by_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->exec, 17);
+ rc = sqlite3_bind_int64(res, 6, (sqlite3_int64) ae->updates_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind exec parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind updates_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->recipient, 18);
+ rc = sqlite3_bind_int64(res, 7, (sqlite3_int64) ae->when);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind recipient parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind when parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->source, 19);
+ rc = sqlite3_bind_int64(res, 8, (sqlite3_int64) ae->duration);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind source parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->units, 20);
+ rc = sqlite3_bind_int64(res, 9, (sqlite3_int64) ae->non_clear_duration);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind host_id parameter to store node instance information");
+ error_report("Failed to bind non_clear_duration parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->info, 21);
+ rc = sqlite3_bind_int64(res, 10, (sqlite3_int64) ae->flags);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind info parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind flags parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int(res, 22, ae->exec_code);
+ rc = sqlite3_bind_int64(res, 11, (sqlite3_int64) ae->exec_run_timestamp);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind exec_code parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind exec_run_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int(res, 23, ae->new_status);
+ rc = sqlite3_bind_int64(res, 12, (sqlite3_int64) ae->delay_up_to_timestamp);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind new_status parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind delay_up_to_timestamp parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int(res, 24, ae->old_status);
+ rc = sqlite3_bind_string_or_null(res, ae->info, 13);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind old_status parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind info parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int(res, 25, ae->delay);
+ rc = sqlite3_bind_int(res, 14, ae->exec_code);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind delay parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind exec_code parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_double(res, 26, ae->new_value);
+ rc = sqlite3_bind_int(res, 15, ae->new_status);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind new_value parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind new_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_double(res, 27, ae->old_value);
+ rc = sqlite3_bind_int(res, 16, ae->old_status);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind old_value parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind old_status parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_int64(res, 28, (sqlite3_int64) ae->last_repeat);
+ rc = sqlite3_bind_int(res, 17, ae->delay);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind last_repeat parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind delay parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->classification, 29);
+ rc = sqlite3_bind_double(res, 18, ae->new_value);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind classification parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind new_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->component, 30);
+ rc = sqlite3_bind_double(res, 19, ae->old_value);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind component parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind old_value parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->type, 31);
+ rc = sqlite3_bind_int64(res, 20, (sqlite3_int64) ae->last_repeat);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind type parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind last_repeat parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_string_or_null(res, ae->chart_context, 32);
+ rc = sqlite3_bind_blob(res, 21, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
- rc = sqlite3_bind_blob(res, 33, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC);
+ rc = sqlite3_bind_int64(res, 22, (sqlite3_int64) ae->global_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind transition_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind global_id parameter for SQL_INSERT_HEALTH_LOG_DETAIL");
goto failed;
}
rc = execute_insert(res);
if (unlikely(rc != SQLITE_DONE)) {
- error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", rrdhost_hostname(host), rc);
+ error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG_DETAIL, rc = %d", rrdhost_hostname(host), rc);
goto failed;
}
@@ -363,7 +345,7 @@ void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae)
else {
sql_health_alarm_log_insert(host, ae);
#ifdef ENABLE_ACLK
- if (netdata_cloud_setting) {
+ if (netdata_cloud_enabled) {
sql_queue_alarm_to_aclk(host, ae, 0);
}
#endif
@@ -373,11 +355,10 @@ void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae)
/* Health related SQL queries
Get a count of rows from health log table
*/
-#define SQL_COUNT_HEALTH_LOG(guid) "SELECT count(1) FROM health_log_%s;", guid
+#define SQL_COUNT_HEALTH_LOG_DETAIL "SELECT count(1) FROM health_log_detail hld, health_log hl where hl.host_id = @host_id and hl.health_log_id = hld.health_log_id;"
void sql_health_alarm_log_count(RRDHOST *host) {
sqlite3_stmt *res = NULL;
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
if (unlikely(!db_meta)) {
if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
@@ -385,17 +366,19 @@ void sql_health_alarm_log_count(RRDHOST *host) {
return;
}
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COUNT_HEALTH_LOG(uuid_str));
-
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_COUNT_HEALTH_LOG_DETAIL, -1, &res, 0);
if (unlikely(rc != SQLITE_OK)) {
error_report("Failed to prepare statement to count health log entries from db");
return;
}
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for SQL_COUNT_HEALTH_LOG.");
+ sqlite3_finalize(res);
+ return;
+ }
+
rc = sqlite3_step_monitored(res);
if (likely(rc == SQLITE_ROW))
host->health.health_log_entries_written = (size_t) sqlite3_column_int64(res, 0);
@@ -404,14 +387,14 @@ void sql_health_alarm_log_count(RRDHOST *host) {
if (unlikely(rc != SQLITE_OK))
error_report("Failed to finalize the prepared statement to count health log entries from db");
- info("HEALTH [%s]: Table health_log_%s, contains %lu entries.", rrdhost_hostname(host), uuid_str, (unsigned long int) host->health.health_log_entries_written);
+ netdata_log_info("HEALTH [%s]: Table health_log_detail contains %lu entries.", rrdhost_hostname(host), (unsigned long int) host->health.health_log_entries_written);
}
/* Health related SQL queries
- Cleans up the health_log table on a non-claimed host
+ Cleans up the health_log_detail table on a non-claimed host
*/
-#define SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED(guid,limit) "DELETE FROM health_log_%s ORDER BY unique_id ASC LIMIT %lu;", guid, limit
-void sql_health_alarm_log_cleanup_not_claimed(RRDHOST *host, size_t rotate_every) {
+#define SQL_CLEANUP_HEALTH_LOG_DETAIL_NOT_CLAIMED "DELETE FROM health_log_detail WHERE health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = ?1) AND when_key + ?2 < unixepoch() AND updated_by_id <> 0 AND transition_id NOT IN (SELECT last_transition_id FROM health_log hl WHERE hl.host_id = ?3);"
+void sql_health_alarm_log_cleanup_not_claimed(RRDHOST *host) {
sqlite3_stmt *res = NULL;
int rc;
char command[MAX_HEALTH_SQL_SIZE + 1];
@@ -425,23 +408,42 @@ void sql_health_alarm_log_cleanup_not_claimed(RRDHOST *host, size_t rotate_every
char uuid_str[UUID_STR_LEN];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED(uuid_str, (unsigned long int) (host->health.health_log_entries_written - rotate_every)));
+ rc = sqlite3_prepare_v2(db_meta, SQL_CLEANUP_HEALTH_LOG_DETAIL_NOT_CLAIMED, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to cleanup health log detail table (un-claimed)");
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
+ sqlite3_finalize(res);
+ return;
+ }
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64)host->health_log.health_log_history);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind health log history for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 3, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to prepare statement to cleanup health log table");
+ error_report("Failed to bind host_id for SQL_CLEANUP_HEALTH_LOG_NOT_CLAIMED.");
+ sqlite3_finalize(res);
return;
}
rc = sqlite3_step_monitored(res);
if (unlikely(rc != SQLITE_DONE))
- error_report("Failed to cleanup health log table, rc = %d", rc);
+ error_report("Failed to cleanup health log detail table, rc = %d", rc);
rc = sqlite3_finalize(res);
if (unlikely(rc != SQLITE_OK))
- error_report("Failed to finalize the prepared statement to cleanup health log table");
+ error_report("Failed to finalize the prepared statement to cleanup health log detail table (un-claimed)");
- host->health.health_log_entries_written = rotate_every;
+ sql_health_alarm_log_count(host);
snprintfz(command, MAX_HEALTH_SQL_SIZE, "aclk_alert_%s", uuid_str);
if (unlikely(table_exists_in_database(command))) {
@@ -450,10 +452,10 @@ void sql_health_alarm_log_cleanup_not_claimed(RRDHOST *host, size_t rotate_every
}
/* Health related SQL queries
- Cleans up the health_log table on a claimed host
+ Cleans up the health_log_detail table on a claimed host
*/
-#define SQL_CLEANUP_HEALTH_LOG_CLAIMED(guid, guid2, guid3, limit) "DELETE from health_log_%s WHERE unique_id NOT IN (SELECT filtered_alert_unique_id FROM aclk_alert_%s) AND unique_id IN (SELECT unique_id FROM health_log_%s ORDER BY unique_id asc LIMIT %lu);", guid, guid2, guid3, limit
-void sql_health_alarm_log_cleanup_claimed(RRDHOST *host, size_t rotate_every) {
+#define SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(guid) "DELETE from health_log_detail WHERE unique_id NOT IN (SELECT filtered_alert_unique_id FROM aclk_alert_%s) AND unique_id IN (SELECT hld.unique_id FROM health_log hl, health_log_detail hld WHERE hl.host_id = ?1 AND hl.health_log_id = hld.health_log_id) AND health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = ?2) AND when_key + ?3 < unixepoch() AND updated_by_id <> 0 AND transition_id NOT IN (SELECT last_transition_id FROM health_log hl WHERE hl.host_id = ?4);", guid
+void sql_health_alarm_log_cleanup_claimed(RRDHOST *host) {
sqlite3_stmt *res = NULL;
int rc;
char command[MAX_HEALTH_SQL_SIZE + 1];
@@ -469,70 +471,83 @@ void sql_health_alarm_log_cleanup_claimed(RRDHOST *host, size_t rotate_every) {
snprintfz(command, MAX_HEALTH_SQL_SIZE, "aclk_alert_%s", uuid_str);
if (!table_exists_in_database(command)) {
- sql_health_alarm_log_cleanup_not_claimed(host, rotate_every);
+ sql_health_alarm_log_cleanup_not_claimed(host);
return;
}
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG_CLAIMED(uuid_str, uuid_str, uuid_str, (unsigned long int) (host->health.health_log_entries_written - rotate_every)));
+ snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(uuid_str));
rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to prepare statement to cleanup health log table");
+ error_report("Failed to prepare statement to cleanup health log detail table (claimed)");
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind first host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 2, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind second host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ rc = sqlite3_bind_int64(res, 3, (sqlite3_int64)host->health_log.health_log_history);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind health log history for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 4, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind second host_id for SQL_CLEANUP_HEALTH_LOG_CLAIMED.");
+ sqlite3_finalize(res);
return;
}
rc = sqlite3_step_monitored(res);
if (unlikely(rc != SQLITE_DONE))
- error_report("Failed to cleanup health log table, rc = %d", rc);
+ error_report("Failed to cleanup health log detail table, rc = %d", rc);
rc = sqlite3_finalize(res);
if (unlikely(rc != SQLITE_OK))
- error_report("Failed to finalize the prepared statement to cleanup health log table");
+ error_report("Failed to finalize the prepared statement to cleanup health log detail table (claimed)");
sql_health_alarm_log_count(host);
sql_aclk_alert_clean_dead_entries(host);
+
}
/* Health related SQL queries
Cleans up the health_log table.
*/
void sql_health_alarm_log_cleanup(RRDHOST *host) {
- static size_t rotate_every = 0;
-
- if(unlikely(rotate_every == 0)) {
- rotate_every = (size_t)config_get_number(CONFIG_SECTION_HEALTH, "rotate log every lines", 2000);
- if(rotate_every < 100) rotate_every = 100;
- }
-
- if(likely(host->health.health_log_entries_written < rotate_every)) {
- return;
- }
-
if (!claimed()) {
- sql_health_alarm_log_cleanup_not_claimed(host, rotate_every);
+ sql_health_alarm_log_cleanup_not_claimed(host);
} else
- sql_health_alarm_log_cleanup_claimed(host, rotate_every);
+ sql_health_alarm_log_cleanup_claimed(host);
}
-#define SQL_INJECT_REMOVED(guid, guid2) "insert into health_log_%s (hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, " \
-"delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context, transition_id) " \
-"select hostname, ?1, ?2, ?3, config_hash_id, 0, ?4, unixepoch(), 0, 0, flags, exec_run_timestamp, " \
-"unixepoch(), name, chart, family, exec, recipient, source, units, info, exec_code, -2, new_status, delay, NULL, new_value, 0, class, component, type, chart_context, ?5 " \
-"from health_log_%s where unique_id = ?6", guid, guid2
-#define SQL_INJECT_REMOVED_UPDATE(guid) "update health_log_%s set flags = flags | ?1, updated_by_id = ?2 where unique_id = ?3; ", guid
-void sql_inject_removed_status(char *uuid_str, uint32_t alarm_id, uint32_t alarm_event_id, uint32_t unique_id, uint32_t max_unique_id)
+#define SQL_INJECT_REMOVED "insert into health_log_detail (health_log_id, unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id) select health_log_id, ?1, ?2, ?3, 0, ?4, unixepoch(), 0, 0, flags, exec_run_timestamp, unixepoch(), info, exec_code, -2, new_status, delay, NULL, new_value, 0, ?5, now_usec(0) from health_log_detail where unique_id = ?6 and transition_id = ?7;"
+#define SQL_INJECT_REMOVED_UPDATE_DETAIL "update health_log_detail set flags = flags | ?1, updated_by_id = ?2 where unique_id = ?3 and transition_id = ?4;"
+#define SQL_INJECT_REMOVED_UPDATE_LOG "update health_log set last_transition_id = ?1 where alarm_id = ?2 and last_transition_id = ?3 and host_id = ?4;"
+void sql_inject_removed_status(RRDHOST *host, uint32_t alarm_id, uint32_t alarm_event_id, uint32_t unique_id, uint32_t max_unique_id, uuid_t *prev_transition_id)
{
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
if (!alarm_id || !alarm_event_id || !unique_id || !max_unique_id)
return;
sqlite3_stmt *res = NULL;
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INJECT_REMOVED(uuid_str, uuid_str));
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED, -1, &res, 0);
if (rc != SQLITE_OK) {
error_report("Failed to prepare statement when trying to inject removed event");
return;
@@ -566,7 +581,7 @@ void sql_inject_removed_status(char *uuid_str, uint32_t alarm_id, uint32_t alarm
uuid_generate_random(transition_id);
rc = sqlite3_bind_blob(res, 5, &transition_id, sizeof(transition_id), SQLITE_STATIC);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind config_hash_id parameter for SQL_INSERT_HEALTH_LOG");
+ error_report("Failed to bind config_hash_id parameter for SQL_INJECT_REMOVED");
goto failed;
}
@@ -576,6 +591,12 @@ void sql_inject_removed_status(char *uuid_str, uint32_t alarm_id, uint32_t alarm
goto failed;
}
+ rc = sqlite3_bind_blob(res, 7, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED.");
+ goto failed;
+ }
+
rc = execute_insert(res);
if (unlikely(rc != SQLITE_DONE)) {
error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED, rc = %d", rc);
@@ -585,35 +606,77 @@ void sql_inject_removed_status(char *uuid_str, uint32_t alarm_id, uint32_t alarm
if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
- //update the old entry
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_INJECT_REMOVED_UPDATE(uuid_str));
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ //update the old entry in health_log_detail
+ rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_DETAIL, -1, &res, 0);
if (rc != SQLITE_OK) {
- error_report("Failed to prepare statement when trying to update during inject removed event");
+ error_report("Failed to prepare statement when trying to update health_log_detail during inject removed event");
return;
}
rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) HEALTH_ENTRY_FLAG_UPDATED);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind flags parameter for SQL_INJECT_REMOVED (update)");
+ error_report("Failed to bind flags parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
goto failed;
}
rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) max_unique_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED (update)");
+ error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
goto failed;
}
rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) unique_id);
if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED (update)");
+ error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_blob(res, 4, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
goto failed;
}
rc = execute_insert(res);
if (unlikely(rc != SQLITE_DONE)) {
- error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE, rc = %d", rc);
+ error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
+ goto failed;
+ }
+
+ //update the health_log_table
+ rc = sqlite3_prepare_v2(db_meta, SQL_INJECT_REMOVED_UPDATE_LOG, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to update health_log during inject removed event");
+ return;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &transition_id, sizeof(transition_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_blob(res, 3, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_LOG");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_blob(res, 4, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_INJECT_REMOVED_UPDATE_DETAIL");
+ goto failed;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
goto failed;
}
@@ -622,22 +685,27 @@ failed:
error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
}
-#define SQL_SELECT_MAX_UNIQUE_ID(guid) "SELECT MAX(unique_id) from health_log_%s", guid
-uint32_t sql_get_max_unique_id (char *uuid_str)
+#define SQL_SELECT_MAX_UNIQUE_ID "SELECT MAX(hld.unique_id) from health_log_detail hld, health_log hl where hl.host_id = @host_id; and hl.health_log_id = hld.health_log_id"
+uint32_t sql_get_max_unique_id (RRDHOST *host)
{
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
uint32_t max_unique_id = 0;
sqlite3_stmt *res = NULL;
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_MAX_UNIQUE_ID(uuid_str));
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_MAX_UNIQUE_ID, -1, &res, 0);
if (rc != SQLITE_OK) {
error_report("Failed to prepare statement when trying to get max unique id");
return 0;
}
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_SELECT_MAX_UNIQUE_ID.");
+ sqlite3_finalize(res);
+ return 0;
+ }
+
while (sqlite3_step_monitored(res) == SQLITE_ROW) {
max_unique_id = (uint32_t) sqlite3_column_int64(res, 0);
}
@@ -649,36 +717,42 @@ uint32_t sql_get_max_unique_id (char *uuid_str)
return max_unique_id;
}
-#define SQL_SELECT_LAST_STATUSES(guid) "SELECT new_status, unique_id, alarm_id, alarm_event_id from health_log_%s group by alarm_id having max(alarm_event_id)", guid
-void sql_check_removed_alerts_state(char *uuid_str)
+#define SQL_SELECT_LAST_STATUSES "SELECT hld.new_status, hld.unique_id, hld.alarm_id, hld.alarm_event_id, hld.transition_id from health_log hl, health_log_detail hld where hl.host_id = @host_id and hl.last_transition_id = hld.transition_id;"
+void sql_check_removed_alerts_state(RRDHOST *host)
{
int rc;
- char command[MAX_HEALTH_SQL_SIZE + 1];
uint32_t max_unique_id = 0;
-
sqlite3_stmt *res = NULL;
+ uuid_t transition_id;
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_LAST_STATUSES(uuid_str));
- rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ rc = sqlite3_prepare_v2(db_meta, SQL_SELECT_LAST_STATUSES, -1, &res, 0);
if (rc != SQLITE_OK) {
error_report("Failed to prepare statement when trying to check removed statuses");
return;
}
- while (sqlite3_step_monitored(res) == SQLITE_ROW) {
- uint32_t alarm_id, alarm_event_id, unique_id;
- RRDCALC_STATUS status;
-
- status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
- unique_id = (uint32_t) sqlite3_column_int64(res, 1);
- alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
- alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
- if (unlikely(status != RRDCALC_STATUS_REMOVED)) {
- if (unlikely(!max_unique_id))
- max_unique_id = sql_get_max_unique_id (uuid_str);
- sql_inject_removed_status (uuid_str, alarm_id, alarm_event_id, unique_id, ++max_unique_id);
- }
- }
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_SELECT_LAST_STATUSES.");
+ sqlite3_finalize(res);
+ return;
+ }
+
+ while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+ uint32_t alarm_id, alarm_event_id, unique_id;
+ RRDCALC_STATUS status;
+
+ status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
+ unique_id = (uint32_t) sqlite3_column_int64(res, 1);
+ alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
+ alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
+ uuid_copy(transition_id, *((uuid_t *) sqlite3_column_blob(res, 4)));
+ if (unlikely(status != RRDCALC_STATUS_REMOVED)) {
+ if (unlikely(!max_unique_id))
+ max_unique_id = sql_get_max_unique_id (host);
+ sql_inject_removed_status (host, alarm_id, alarm_event_id, unique_id, ++max_unique_id, &transition_id);
+ }
+ }
rc = sqlite3_finalize(res);
if (unlikely(rc != SQLITE_OK))
@@ -688,12 +762,17 @@ void sql_check_removed_alerts_state(char *uuid_str)
/* Health related SQL queries
Load from the health log table
*/
-#define SQL_LOAD_HEALTH_LOG(guid) "SELECT hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context, transition_id FROM health_log_%s group by alarm_id having max(alarm_event_id);", guid
+#define SQL_LOAD_HEALTH_LOG "SELECT hld.unique_id, hld.alarm_id, hld.alarm_event_id, hl.config_hash_id, hld.updated_by_id, " \
+ "hld.updates_id, hld.when_key, hld.duration, hld.non_clear_duration, hld.flags, hld.exec_run_timestamp, " \
+ "hld.delay_up_to_timestamp, hl.name, hl.chart, hl.family, hl.exec, hl.recipient, ah.source, hl.units, " \
+ "hld.info, hld.exec_code, hld.new_status, hld.old_status, hld.delay, hld.new_value, hld.old_value, " \
+ "hld.last_repeat, ah.class, ah.component, ah.type, hl.chart_context, hld.transition_id, hld.global_id " \
+ "FROM health_log hl, alert_hash ah, health_log_detail hld " \
+ "WHERE hl.config_hash_id = ah.hash_id and hl.host_id = @host_id and hl.last_transition_id = hld.transition_id;"
void sql_health_alarm_log_load(RRDHOST *host) {
sqlite3_stmt *res = NULL;
int ret;
ssize_t errored = 0, loaded = 0;
- char command[MAX_HEALTH_SQL_SIZE + 1];
host->health.health_log_entries_written = 0;
@@ -703,19 +782,21 @@ void sql_health_alarm_log_load(RRDHOST *host) {
return;
}
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- sql_check_removed_alerts_state(uuid_str);
+ sql_check_removed_alerts_state(host);
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_LOAD_HEALTH_LOG(uuid_str));
-
- ret = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ ret = sqlite3_prepare_v2(db_meta, SQL_LOAD_HEALTH_LOG, -1, &res, 0);
if (unlikely(ret != SQLITE_OK)) {
error_report("HEALTH [%s]: Failed to prepare sql statement to load health log.", rrdhost_hostname(host));
return;
}
+ ret = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(ret != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_LOAD_HEALTH_LOG.");
+ sqlite3_finalize(res);
+ return;
+ }
+
DICTIONARY *all_rrdcalcs = dictionary_create(
DICT_OPTION_NAME_LINK_DONT_CLONE | DICT_OPTION_VALUE_LINK_DONT_CLONE | DICT_OPTION_DONT_OVERWRITE_VALUE);
RRDCALC *rc;
@@ -724,20 +805,20 @@ void sql_health_alarm_log_load(RRDHOST *host) {
}
foreach_rrdcalc_in_rrdhost_done(rc);
- netdata_rwlock_rdlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_read_lock(&host->health_log.spinlock);
while (sqlite3_step_monitored(res) == SQLITE_ROW) {
ALARM_ENTRY *ae = NULL;
// check that we have valid ids
- uint32_t unique_id = (uint32_t) sqlite3_column_int64(res, 1);
+ uint32_t unique_id = (uint32_t) sqlite3_column_int64(res, 0);
if(!unique_id) {
error_report("HEALTH [%s]: Got invalid unique id. Ignoring it.", rrdhost_hostname(host));
errored++;
continue;
}
- uint32_t alarm_id = (uint32_t) sqlite3_column_int64(res, 2);
+ uint32_t alarm_id = (uint32_t) sqlite3_column_int64(res, 1);
if(!alarm_id) {
error_report("HEALTH [%s]: Got invalid alarm id. Ignoring it.", rrdhost_hostname(host));
errored++;
@@ -745,28 +826,28 @@ void sql_health_alarm_log_load(RRDHOST *host) {
}
//need name, chart and family
- if (sqlite3_column_type(res, 13) == SQLITE_NULL) {
+ if (sqlite3_column_type(res, 12) == SQLITE_NULL) {
error_report("HEALTH [%s]: Got null name field. Ignoring it.", rrdhost_hostname(host));
errored++;
continue;
}
- if (sqlite3_column_type(res, 14) == SQLITE_NULL) {
+ if (sqlite3_column_type(res, 13) == SQLITE_NULL) {
error_report("HEALTH [%s]: Got null chart field. Ignoring it.", rrdhost_hostname(host));
errored++;
continue;
}
- if (sqlite3_column_type(res, 15) == SQLITE_NULL) {
+ if (sqlite3_column_type(res, 14) == SQLITE_NULL) {
error_report("HEALTH [%s]: Got null family field. Ignoring it.", rrdhost_hostname(host));
errored++;
continue;
}
// Check if we got last_repeat field
- time_t last_repeat = (time_t)sqlite3_column_int64(res, 27);
+ time_t last_repeat = (time_t)sqlite3_column_int64(res, 26);
- rc = dictionary_get(all_rrdcalcs, (char *) sqlite3_column_text(res, 14));
+ rc = dictionary_get(all_rrdcalcs, (char *) sqlite3_column_text(res, 13));
if(unlikely(rc)) {
if (rrdcalc_isrepeating(rc)) {
rc->last_repeat = last_repeat;
@@ -782,84 +863,87 @@ void sql_health_alarm_log_load(RRDHOST *host) {
ae->unique_id = unique_id;
ae->alarm_id = alarm_id;
- if (sqlite3_column_type(res, 4) != SQLITE_NULL)
- uuid_copy(ae->config_hash_id, *((uuid_t *) sqlite3_column_blob(res, 4)));
+ if (sqlite3_column_type(res, 3) != SQLITE_NULL)
+ uuid_copy(ae->config_hash_id, *((uuid_t *) sqlite3_column_blob(res, 3)));
- ae->alarm_event_id = (uint32_t) sqlite3_column_int64(res, 3);
- ae->updated_by_id = (uint32_t) sqlite3_column_int64(res, 5);
- ae->updates_id = (uint32_t) sqlite3_column_int64(res, 6);
+ ae->alarm_event_id = (uint32_t) sqlite3_column_int64(res, 2);
+ ae->updated_by_id = (uint32_t) sqlite3_column_int64(res, 4);
+ ae->updates_id = (uint32_t) sqlite3_column_int64(res, 5);
- ae->when = (time_t) sqlite3_column_int64(res, 7);
- ae->duration = (time_t) sqlite3_column_int64(res, 8);
- ae->non_clear_duration = (time_t) sqlite3_column_int64(res, 9);
+ ae->when = (time_t) sqlite3_column_int64(res, 6);
+ ae->duration = (time_t) sqlite3_column_int64(res, 7);
+ ae->non_clear_duration = (time_t) sqlite3_column_int64(res, 8);
- ae->flags = (uint32_t) sqlite3_column_int64(res, 10);
+ ae->flags = (uint32_t) sqlite3_column_int64(res, 9);
ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
- ae->exec_run_timestamp = (time_t) sqlite3_column_int64(res, 11);
- ae->delay_up_to_timestamp = (time_t) sqlite3_column_int64(res, 12);
+ ae->exec_run_timestamp = (time_t) sqlite3_column_int64(res, 10);
+ ae->delay_up_to_timestamp = (time_t) sqlite3_column_int64(res, 11);
- ae->name = string_strdupz((char *) sqlite3_column_text(res, 13));
- ae->chart = string_strdupz((char *) sqlite3_column_text(res, 14));
- ae->family = string_strdupz((char *) sqlite3_column_text(res, 15));
+ ae->name = string_strdupz((char *) sqlite3_column_text(res, 12));
+ ae->chart = string_strdupz((char *) sqlite3_column_text(res, 13));
+ ae->family = string_strdupz((char *) sqlite3_column_text(res, 14));
- if (sqlite3_column_type(res, 16) != SQLITE_NULL)
- ae->exec = string_strdupz((char *) sqlite3_column_text(res, 16));
+ if (sqlite3_column_type(res, 15) != SQLITE_NULL)
+ ae->exec = string_strdupz((char *) sqlite3_column_text(res, 15));
else
ae->exec = NULL;
- if (sqlite3_column_type(res, 17) != SQLITE_NULL)
- ae->recipient = string_strdupz((char *) sqlite3_column_text(res, 17));
+ if (sqlite3_column_type(res, 16) != SQLITE_NULL)
+ ae->recipient = string_strdupz((char *) sqlite3_column_text(res, 16));
else
ae->recipient = NULL;
- if (sqlite3_column_type(res, 18) != SQLITE_NULL)
- ae->source = string_strdupz((char *) sqlite3_column_text(res, 18));
+ if (sqlite3_column_type(res, 17) != SQLITE_NULL)
+ ae->source = string_strdupz((char *) sqlite3_column_text(res, 17));
else
ae->source = NULL;
- if (sqlite3_column_type(res, 19) != SQLITE_NULL)
- ae->units = string_strdupz((char *) sqlite3_column_text(res, 19));
+ if (sqlite3_column_type(res, 18) != SQLITE_NULL)
+ ae->units = string_strdupz((char *) sqlite3_column_text(res, 18));
else
ae->units = NULL;
- if (sqlite3_column_type(res, 20) != SQLITE_NULL)
- ae->info = string_strdupz((char *) sqlite3_column_text(res, 20));
+ if (sqlite3_column_type(res, 19) != SQLITE_NULL)
+ ae->info = string_strdupz((char *) sqlite3_column_text(res, 19));
else
ae->info = NULL;
- ae->exec_code = (int) sqlite3_column_int(res, 21);
- ae->new_status = (RRDCALC_STATUS) sqlite3_column_int(res, 22);
- ae->old_status = (RRDCALC_STATUS)sqlite3_column_int(res, 23);
- ae->delay = (int) sqlite3_column_int(res, 24);
+ ae->exec_code = (int) sqlite3_column_int(res, 20);
+ ae->new_status = (RRDCALC_STATUS) sqlite3_column_int(res, 21);
+ ae->old_status = (RRDCALC_STATUS)sqlite3_column_int(res, 22);
+ ae->delay = (int) sqlite3_column_int(res, 23);
- ae->new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 25);
- ae->old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 26);
+ ae->new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 24);
+ ae->old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 25);
ae->last_repeat = last_repeat;
- if (sqlite3_column_type(res, 28) != SQLITE_NULL)
- ae->classification = string_strdupz((char *) sqlite3_column_text(res, 28));
+ if (sqlite3_column_type(res, 27) != SQLITE_NULL)
+ ae->classification = string_strdupz((char *) sqlite3_column_text(res, 27));
else
ae->classification = NULL;
- if (sqlite3_column_type(res, 29) != SQLITE_NULL)
- ae->component = string_strdupz((char *) sqlite3_column_text(res, 29));
+ if (sqlite3_column_type(res, 28) != SQLITE_NULL)
+ ae->component = string_strdupz((char *) sqlite3_column_text(res, 28));
else
ae->component = NULL;
- if (sqlite3_column_type(res, 30) != SQLITE_NULL)
- ae->type = string_strdupz((char *) sqlite3_column_text(res, 30));
+ if (sqlite3_column_type(res, 29) != SQLITE_NULL)
+ ae->type = string_strdupz((char *) sqlite3_column_text(res, 29));
else
ae->type = NULL;
- if (sqlite3_column_type(res, 31) != SQLITE_NULL)
- ae->chart_context = string_strdupz((char *) sqlite3_column_text(res, 31));
+ if (sqlite3_column_type(res, 30) != SQLITE_NULL)
+ ae->chart_context = string_strdupz((char *) sqlite3_column_text(res, 30));
else
ae->chart_context = NULL;
- if (sqlite3_column_type(res, 32) != SQLITE_NULL)
- uuid_copy(ae->transition_id, *((uuid_t *) sqlite3_column_blob(res, 32)));
+ if (sqlite3_column_type(res, 31) != SQLITE_NULL)
+ uuid_copy(ae->transition_id, *((uuid_t *)sqlite3_column_blob(res, 31)));
+
+ if (sqlite3_column_type(res, 32) != SQLITE_NULL)
+ ae->global_id = sqlite3_column_int64(res, 32);
char value_string[100 + 1];
string_freez(ae->old_value_string);
@@ -879,7 +963,7 @@ void sql_health_alarm_log_load(RRDHOST *host) {
loaded++;
}
- netdata_rwlock_unlock(&host->health_log.alarm_log_rwlock);
+ rw_spinlock_read_unlock(&host->health_log.spinlock);
dictionary_destroy(all_rrdcalcs);
all_rrdcalcs = NULL;
@@ -891,7 +975,7 @@ void sql_health_alarm_log_load(RRDHOST *host) {
if (unlikely(!host->health_log.next_alarm_id || host->health_log.next_alarm_id <= host->health_max_alarm_id))
host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
- log_health("[%s]: Table health_log_%s, loaded %zd alarm entries, errors in %zd entries.", rrdhost_hostname(host), uuid_str, loaded, errored);
+ netdata_log_health("[%s]: Table health_log, loaded %zd alarm entries, errors in %zd entries.", rrdhost_hostname(host), loaded, errored);
ret = sqlite3_finalize(res);
if (unlikely(ret != SQLITE_OK))
@@ -907,8 +991,8 @@ void sql_health_alarm_log_load(RRDHOST *host) {
"on_key, class, component, type, os, hosts, lookup, every, units, calc, families, plugin, module, " \
"charts, green, red, warn, crit, exec, to_key, info, delay, options, repeat, host_labels, " \
"p_db_lookup_dimensions, p_db_lookup_method, p_db_lookup_options, p_db_lookup_after, " \
- "p_db_lookup_before, p_update_every) values (?1,unixepoch(),?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12," \
- "?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34);"
+ "p_db_lookup_before, p_update_every, source, chart_labels) values (?1,unixepoch(),?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12," \
+ "?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34,?35,?36);"
int sql_store_alert_config_hash(uuid_t *hash_id, struct alert_config *cfg)
{
@@ -1088,6 +1172,14 @@ int sql_store_alert_config_hash(uuid_t *hash_id, struct alert_config *cfg)
if (unlikely(rc != SQLITE_OK))
goto bind_fail;
+ rc = sqlite3_bind_string_or_null(res, cfg->source, ++param);
+ if (unlikely(rc != SQLITE_OK))
+ goto bind_fail;
+
+ rc = sqlite3_bind_string_or_null(res, cfg->chart_labels, ++param);
+ if (unlikely(rc != SQLITE_OK))
+ goto bind_fail;
+
rc = execute_insert(res);
if (unlikely(rc != SQLITE_DONE))
error_report("Failed to store alert config, rc = %d", rc);
@@ -1175,18 +1267,14 @@ int alert_hash_and_store_config(
return 1;
}
-#define SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT "SELECT new_status FROM health_log_%s WHERE alarm_id = %u AND unique_id != %u AND flags & %d ORDER BY unique_id DESC LIMIT 1"
+#define SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT "SELECT hld.new_status FROM health_log hl, health_log_detail hld WHERE hl.alarm_id = %u AND hld.unique_id != %u AND hld.flags & %u AND hl.host_id = @host_id and hl.health_log_id = hld.health_log_id ORDER BY hld.unique_id DESC LIMIT 1;"
int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_STATUS *last_executed_status)
{
int rc = 0, ret = -1;
char command[MAX_HEALTH_SQL_SIZE + 1];
-
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
sqlite3_stmt *res = NULL;
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, uuid_str, ae->alarm_id, ae->unique_id, HEALTH_ENTRY_FLAG_EXEC_RUN);
+ snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, ae->alarm_id, ae->unique_id, (uint32_t) HEALTH_ENTRY_FLAG_EXEC_RUN);
rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
if (rc != SQLITE_OK) {
@@ -1194,6 +1282,13 @@ int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_S
return ret;
}
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT.");
+ sqlite3_finalize(res);
+ return ret;
+ }
+
ret = 0;
while (sqlite3_step_monitored(res) == SQLITE_ROW) {
*last_executed_status = (RRDCALC_STATUS) sqlite3_column_int(res, 0);
@@ -1207,7 +1302,7 @@ int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_S
return ret;
}
-#define SQL_SELECT_HEALTH_LOG(guid) "SELECT hostname, unique_id, alarm_id, alarm_event_id, config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, class, component, type, chart_context, transition_id FROM health_log_%s WHERE 1=1 ", guid
+#define SQL_SELECT_HEALTH_LOG "SELECT hld.unique_id, hld.alarm_id, hld.alarm_event_id, hl.config_hash_id, hld.updated_by_id, hld.updates_id, hld.when_key, hld.duration, hld.non_clear_duration, hld.flags, hld.exec_run_timestamp, hld.delay_up_to_timestamp, hl.name, hl.chart, hl.family, hl.exec, hl.recipient, ah.source, hl.units, hld.info, hld.exec_code, hld.new_status, hld.old_status, hld.delay, hld.new_value, hld.old_value, hld.last_repeat, ah.class, ah.component, ah.type, hl.chart_context, hld.transition_id FROM health_log hl, alert_hash ah, health_log_detail hld WHERE hl.config_hash_id = ah.hash_id and hl.health_log_id = hld.health_log_id and hl.host_id = @host_id "
void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart) {
buffer_strcat(wb, "[");
@@ -1219,26 +1314,23 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *
int rc;
BUFFER *command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
- char uuid_str[UUID_STR_LEN];
- uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
-
- buffer_sprintf(command, SQL_SELECT_HEALTH_LOG(uuid_str));
+ buffer_sprintf(command, SQL_SELECT_HEALTH_LOG);
if (chart) {
char chart_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(chart_sql, MAX_HEALTH_SQL_SIZE, "AND chart = '%s' ", chart);
+ snprintfz(chart_sql, MAX_HEALTH_SQL_SIZE, "AND hl.chart = '%s' ", chart);
buffer_strcat(command, chart_sql);
}
if (after) {
char after_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(after_sql, MAX_HEALTH_SQL_SIZE, "AND unique_id > %u ", after);
+ snprintfz(after_sql, MAX_HEALTH_SQL_SIZE, "AND hld.unique_id > %u ", after);
buffer_strcat(command, after_sql);
}
{
char limit_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(limit_sql, MAX_HEALTH_SQL_SIZE, "ORDER BY unique_id DESC LIMIT %u ", max);
+ snprintfz(limit_sql, MAX_HEALTH_SQL_SIZE, "ORDER BY hld.unique_id DESC LIMIT %u ", max);
buffer_strcat(command, limit_sql);
}
@@ -1249,19 +1341,27 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *
return;
}
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id for SQL_SELECT_HEALTH_LOG.");
+ sqlite3_finalize(res);
+ buffer_free(command);
+ return;
+ }
+
while (sqlite3_step(res) == SQLITE_ROW) {
char old_value_string[100 + 1];
char new_value_string[100 + 1];
char config_hash_id[UUID_STR_LEN];
- uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 4)), config_hash_id);
+ uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 3)), config_hash_id);
char transition_id[UUID_STR_LEN] = {0};
- if (sqlite3_column_type(res, 32) != SQLITE_NULL)
- uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 32)), transition_id);
+ if (sqlite3_column_type(res, 31) != SQLITE_NULL)
+ uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 31)), transition_id);
- char *edit_command = health_edit_command_from_source((char *)sqlite3_column_text(res, 18));
+ char *edit_command = sqlite3_column_bytes(res, 17) > 0 ? health_edit_command_from_source((char *)sqlite3_column_text(res, 17)) : strdupz("UNKNOWN=0=UNKNOWN");
if (count)
buffer_sprintf(wb, ",");
@@ -1309,63 +1409,63 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *
"\t\t\"old_value_string\": \"%s\",\n"
"\t\t\"last_repeat\": \"%lu\",\n"
"\t\t\"silenced\": \"%s\",\n",
- sqlite3_column_text(res, 0),
+ rrdhost_hostname(host),
host->utc_offset,
rrdhost_abbrev_timezone(host),
+ (unsigned int) sqlite3_column_int64(res, 0),
(unsigned int) sqlite3_column_int64(res, 1),
(unsigned int) sqlite3_column_int64(res, 2),
- (unsigned int) sqlite3_column_int64(res, 3),
config_hash_id,
transition_id,
+ sqlite3_column_text(res, 12),
sqlite3_column_text(res, 13),
+ sqlite3_column_text(res, 30),
sqlite3_column_text(res, 14),
- sqlite3_column_text(res, 31),
- sqlite3_column_text(res, 15),
+ sqlite3_column_text(res, 27) ? (const char *) sqlite3_column_text(res, 27) : (char *) "Unknown",
sqlite3_column_text(res, 28) ? (const char *) sqlite3_column_text(res, 28) : (char *) "Unknown",
sqlite3_column_text(res, 29) ? (const char *) sqlite3_column_text(res, 29) : (char *) "Unknown",
- sqlite3_column_text(res, 30) ? (const char *) sqlite3_column_text(res, 30) : (char *) "Unknown",
- (sqlite3_column_int64(res, 10) & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false",
- (sqlite3_column_int64(res, 10) & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false",
- (long unsigned int)sqlite3_column_int64(res, 11),
- (sqlite3_column_int64(res, 10) & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false",
- sqlite3_column_text(res, 16) ? (const char *) sqlite3_column_text(res, 16) : string2str(host->health.health_default_exec),
- sqlite3_column_text(res, 17) ? (const char *) sqlite3_column_text(res, 17) : string2str(host->health.health_default_recipient),
- sqlite3_column_int(res, 21),
- sqlite3_column_text(res, 18),
+ (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_PROCESSED)?"true":"false",
+ (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_UPDATED)?"true":"false",
+ (long unsigned int)sqlite3_column_int64(res, 10),
+ (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_EXEC_FAILED)?"true":"false",
+ sqlite3_column_text(res, 15) ? (const char *) sqlite3_column_text(res, 15) : string2str(host->health.health_default_exec),
+ sqlite3_column_text(res, 16) ? (const char *) sqlite3_column_text(res, 16) : string2str(host->health.health_default_recipient),
+ sqlite3_column_int(res, 20),
+ sqlite3_column_text(res, 17) ? (const char *) sqlite3_column_text(res, 17) : (char *) "Unknown",
edit_command,
- sqlite3_column_text(res, 19),
+ sqlite3_column_text(res, 18),
+ (long unsigned int)sqlite3_column_int64(res, 6),
(long unsigned int)sqlite3_column_int64(res, 7),
(long unsigned int)sqlite3_column_int64(res, 8),
- (long unsigned int)sqlite3_column_int64(res, 9),
+ rrdcalc_status2string(sqlite3_column_int(res, 21)),
rrdcalc_status2string(sqlite3_column_int(res, 22)),
- rrdcalc_status2string(sqlite3_column_int(res, 23)),
- sqlite3_column_int(res, 24),
- (long unsigned int)sqlite3_column_int64(res, 12),
+ sqlite3_column_int(res, 23),
+ (long unsigned int)sqlite3_column_int64(res, 11),
+ (unsigned int)sqlite3_column_int64(res, 4),
(unsigned int)sqlite3_column_int64(res, 5),
- (unsigned int)sqlite3_column_int64(res, 6),
- sqlite3_column_type(res, 25) == SQLITE_NULL ? "-" : format_value_and_unit(new_value_string, 100, sqlite3_column_double(res, 25), (char *) sqlite3_column_text(res, 19), -1),
- sqlite3_column_type(res, 26) == SQLITE_NULL ? "-" : format_value_and_unit(old_value_string, 100, sqlite3_column_double(res, 26), (char *) sqlite3_column_text(res, 19), -1),
- (long unsigned int)sqlite3_column_int64(res, 27),
- (sqlite3_column_int64(res, 10) & HEALTH_ENTRY_FLAG_SILENCED)?"true":"false");
+ sqlite3_column_type(res, 24) == SQLITE_NULL ? "-" : format_value_and_unit(new_value_string, 100, sqlite3_column_double(res, 24), (char *) sqlite3_column_text(res, 18), -1),
+ sqlite3_column_type(res, 25) == SQLITE_NULL ? "-" : format_value_and_unit(old_value_string, 100, sqlite3_column_double(res, 25), (char *) sqlite3_column_text(res, 18), -1),
+ (long unsigned int)sqlite3_column_int64(res, 26),
+ (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_SILENCED)?"true":"false");
- health_string2json(wb, "\t\t", "info", (char *) sqlite3_column_text(res, 20), ",\n");
+ health_string2json(wb, "\t\t", "info", (char *) sqlite3_column_text(res, 19), ",\n");
- if(unlikely(sqlite3_column_int64(res, 10) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
+ if(unlikely(sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
}
buffer_strcat(wb, "\t\t\"value\":");
- if (sqlite3_column_type(res, 25) == SQLITE_NULL)
+ if (sqlite3_column_type(res, 24) == SQLITE_NULL)
buffer_strcat(wb, "null");
else
- buffer_print_netdata_double(wb, sqlite3_column_double(res, 25));
+ buffer_print_netdata_double(wb, sqlite3_column_double(res, 24));
buffer_strcat(wb, ",\n");
buffer_strcat(wb, "\t\t\"old_value\":");
- if (sqlite3_column_type(res, 26) == SQLITE_NULL)
+ if (sqlite3_column_type(res, 25) == SQLITE_NULL)
buffer_strcat(wb, "null");
else
- buffer_print_netdata_double(wb, sqlite3_column_double(res, 26));
+ buffer_print_netdata_double(wb, sqlite3_column_double(res, 25));
buffer_strcat(wb, "\n");
buffer_strcat(wb, "\t}");
@@ -1381,3 +1481,609 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *
buffer_free(command);
}
+
+#define SQL_COPY_HEALTH_LOG(table) "INSERT OR IGNORE INTO health_log (host_id, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context) SELECT ?1, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context from %s;", table
+#define SQL_COPY_HEALTH_LOG_DETAIL(table) "INSERT INTO health_log_detail (unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, global_id, host_id) SELECT unique_id, alarm_id, alarm_event_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, exec_run_timestamp, delay_up_to_timestamp, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, transition_id, now_usec(1), ?1 from %s;", table
+#define SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID "update health_log_detail set transition_id = uuid_random() where transition_id is null;"
+#define SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID "update health_log_detail set health_log_id = (select health_log_id from health_log where host_id = ?1 and alarm_id = health_log_detail.alarm_id) where health_log_id is null and host_id = ?2;"
+#define SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID "update health_log set last_transition_id = (select transition_id from health_log_detail where health_log_id = health_log.health_log_id and alarm_id = health_log.alarm_id group by (alarm_id) having max(alarm_event_id)) where host_id = ?1;"
+int health_migrate_old_health_log_table(char *table) {
+ if (!table)
+ return 0;
+
+ //table should contain guid. We need to
+ //keep it in the new table along with it's data
+ //health_log_XXXXXXXX_XXXX_XXXX_XXXX_XXXXXXXXXXXX
+ if (strnlen(table, 46) != 46) {
+ return 0;
+ }
+
+ char *uuid_from_table = strdupz(table + 11);
+ uuid_t uuid;
+ if (uuid_parse_fix(uuid_from_table, uuid)) {
+ freez(uuid_from_table);
+ return 0;
+ }
+
+ int rc;
+ char command[MAX_HEALTH_SQL_SIZE + 1];
+ sqlite3_stmt *res = NULL;
+ snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG(table));
+ rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to copy health log, rc = %d", rc);
+ freez(uuid_from_table);
+ return 0;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to copy health log table, rc = %d", rc);
+ freez(uuid_from_table);
+ return 0;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to execute SQL_COPY_HEALTH_LOG, rc = %d", rc);
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to copy health log table, rc = %d", rc);
+ freez(uuid_from_table);
+ }
+
+ //detail
+ snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG_DETAIL(table));
+ rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to copy health log detail, rc = %d", rc);
+ return 0;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to copy health log detail, rc = %d", rc);
+ return 0;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to execute SQL_COPY_HEALTH_LOG_DETAIL, rc = %d", rc);
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to copy health log detail table, rc = %d", rc);
+ return 0;
+ }
+
+ //update transition ids
+ rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to update health log detail with transition ids, rc = %d", rc);
+ return 0;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_DETAIL_TRANSITION_ID, rc = %d", rc);
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log detail table with transition ids, rc = %d", rc);
+ return 0;
+ }
+
+ //update health_log_id
+ rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to update health log detail with health log ids, rc = %d", rc);
+ return 0;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log detail with health log ids, rc = %d", rc);
+ return 0;
+ }
+
+ rc = sqlite3_bind_blob(res, 2, &uuid, sizeof(uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log detail with health log ids, rc = %d", rc);
+ return 0;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_DETAIL_HEALTH_LOG_ID, rc = %d", rc);
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log detail table with health log ids, rc = %d", rc);
+ }
+
+ //update last transition id
+ rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to update health log with last transition id, rc = %d", rc);
+ return 0;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &uuid, sizeof(uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log with last transition id, rc = %d", rc);
+ return 0;
+ }
+
+ rc = execute_insert(res);
+ if (unlikely(rc != SQLITE_DONE)) {
+ error_report("Failed to execute SQL_UPDATE_HEALTH_LOG_LAST_TRANSITION_ID, rc = %d", rc);
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to update health log table with last transition id, rc = %d", rc);
+ }
+
+ return 1;
+}
+
+#define SQL_GET_ALARM_ID "select alarm_id, health_log_id from health_log where host_id = @host_id and chart = @chart and name = @name and config_hash_id = @config_hash_id"
+#define SQL_GET_EVENT_ID "select max(alarm_event_id) + 1 from health_log_detail where health_log_id = @health_log_id and alarm_id = @alarm_id"
+uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id)
+{
+ int rc = 0;
+ sqlite3_stmt *res = NULL;
+ uint32_t alarm_id = 0;
+ uint64_t health_log_id = 0;
+
+ rc = sqlite3_prepare_v2(db_meta, SQL_GET_ALARM_ID, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to get an alarm id");
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_blob(res, 1, &host->host_uuid, sizeof(host->host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_GET_ALARM_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_string_or_null(res, chart, 2);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind char parameter for SQL_GET_ALARM_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_string_or_null(res, name, 3);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind name parameter for SQL_GET_ALARM_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_blob(res, 4, config_hash_id, sizeof(*config_hash_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind config_hash_id parameter for SQL_GET_ALARM_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+ alarm_id = (uint32_t) sqlite3_column_int64(res, 0);
+ health_log_id = (uint64_t) sqlite3_column_int64(res, 1);
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize the statement while getting an alarm id.");
+
+ if (alarm_id) {
+ rc = sqlite3_prepare_v2(db_meta, SQL_GET_EVENT_ID, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to get an event id");
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) health_log_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind host_id parameter for SQL_GET_EVENT_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind char parameter for SQL_GET_EVENT_ID.");
+ sqlite3_finalize(res);
+ return alarm_id;
+ }
+
+ while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+ *next_event_id = (uint32_t) sqlite3_column_int64(res, 0);
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize the statement while getting an alarm id.");
+ }
+
+ return alarm_id;
+}
+
+#define SQL_GET_ALARM_ID_FROM_TRANSITION_ID "SELECT hld.alarm_id, hl.host_id, hl.chart_context FROM " \
+ "health_log_detail hld, health_log hl WHERE hld.transition_id = @transition_id " \
+ "and hld.health_log_id = hl.health_log_id"
+
+bool sql_find_alert_transition(const char *transition, void (*cb)(const char *machine_guid, const char *context, time_t alert_id, void *data), void *data)
+{
+ static __thread sqlite3_stmt *res = NULL;
+
+ char machine_guid[UUID_STR_LEN];
+
+ int rc;
+ uuid_t transition_uuid;
+ if (uuid_parse(transition, transition_uuid))
+ return false;
+
+ if (unlikely(!res)) {
+ rc = prepare_statement(db_meta, SQL_GET_ALARM_ID_FROM_TRANSITION_ID, &res);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement when trying to get transition id");
+ return false;
+ }
+ }
+
+ bool ok = false;
+
+ rc = sqlite3_bind_blob(res, 1, &transition_uuid, sizeof(transition_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind transition");
+ goto fail;
+ }
+
+ while (sqlite3_step_monitored(res) == SQLITE_ROW) {
+ ok = true;
+ uuid_unparse_lower(*(uuid_t *) sqlite3_column_blob(res, 1), machine_guid);
+ cb(machine_guid, (const char *) sqlite3_column_text(res, 2), sqlite3_column_int(res, 0), data);
+ }
+
+fail:
+ rc = sqlite3_reset(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset the statement when trying to find transition");
+
+ return ok;
+}
+
+#define SQL_BUILD_ALERT_TRANSITION "CREATE TEMP TABLE IF NOT EXISTS v_%p (host_id blob)"
+
+#define SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE "INSERT INTO v_%p (host_id) VALUES (@host_id)"
+
+#define SQL_SEARCH_ALERT_TRANSITION_SELECT "SELECT " \
+ "h.host_id, h.alarm_id, h.config_hash_id, h.name, h.chart, h.family, h.recipient, h.units, h.exec, " \
+ "h.chart_context, d.when_key, d.duration, d.non_clear_duration, d.flags, d.delay_up_to_timestamp, " \
+ "d.info, d.exec_code, d.new_status, d.old_status, d.delay, d.new_value, d.old_value, d.last_repeat, " \
+ "d.transition_id, d.global_id, ah.class, ah.type, ah.component, d.exec_run_timestamp"
+
+#define SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE \
+ "h.config_hash_id = ah.hash_id AND h.health_log_id = d.health_log_id"
+
+#define SQL_SEARCH_ALERT_TRANSITION SQL_SEARCH_ALERT_TRANSITION_SELECT " FROM health_log h, health_log_detail d, v_%p t, alert_hash ah " \
+ " WHERE h.host_id = t.host_id AND " SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE " AND ( d.new_status > 2 OR d.old_status > 2 ) AND d.global_id BETWEEN @after AND @before "
+
+#define SQL_SEARCH_ALERT_TRANSITION_DIRECT SQL_SEARCH_ALERT_TRANSITION_SELECT " FROM health_log h, health_log_detail d, alert_hash ah " \
+ " WHERE " SQL_SEARCH_ALERT_TRANSITION_COMMON_WHERE " AND transition_id = @transition "
+
+void sql_alert_transitions(
+ DICTIONARY *nodes,
+ time_t after,
+ time_t before,
+ const char *context,
+ const char *alert_name,
+ const char *transition,
+ void (*cb)(struct sql_alert_transition_data *, void *),
+ void *data,
+ bool debug __maybe_unused)
+{
+ uuid_t transition_uuid;
+ char sql[512];
+ int rc;
+ sqlite3_stmt *res = NULL;
+ BUFFER *command = NULL;
+
+ if (unlikely(!nodes))
+ return;
+
+ if (transition) {
+ if (uuid_parse(transition, transition_uuid)) {
+ error_report("Invalid transition given %s", transition);
+ return;
+ }
+
+ rc = sqlite3_prepare_v2(db_meta, SQL_SEARCH_ALERT_TRANSITION_DIRECT, -1, &res, 0);
+
+ rc = sqlite3_bind_blob(res, 1, &transition_uuid, sizeof(transition_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind transition_id parameter");
+ goto fail;
+ }
+ goto run_query;
+ }
+
+ snprintfz(sql, 511, SQL_BUILD_ALERT_TRANSITION, nodes);
+ rc = db_execute(db_meta, sql);
+ if (rc)
+ return;
+
+ snprintfz(sql, 511, SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE, nodes);
+
+ // Prepare statement to add things
+ rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to INSERT into v_%p", nodes);
+ goto fail_only_drop;
+ }
+
+ void *t;
+ dfe_start_read(nodes, t) {
+ uuid_t host_uuid;
+ uuid_parse( t_dfe.name, host_uuid);
+
+ rc = sqlite3_bind_blob(res, 1, &host_uuid, sizeof(host_uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to bind host_id parameter.");
+
+ rc = sqlite3_step_monitored(res);
+ if (rc != SQLITE_DONE)
+ error_report("Error while populating temp table");
+
+ rc = sqlite3_reset(res);
+ if (rc != SQLITE_OK)
+ error_report("Error while resetting parameters");
+ }
+ dfe_done(t);
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK)) {
+ // log error but continue
+ error_report("Failed to finalize statement for sql_alert_transitions temp table population");
+ }
+
+ command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
+
+ buffer_sprintf(command, SQL_SEARCH_ALERT_TRANSITION, nodes);
+
+ if (context)
+ buffer_sprintf(command, " AND h.chart_context = @context");
+
+ if (alert_name)
+ buffer_sprintf(command, " AND h.name = @alert_name");
+
+ buffer_strcat(command, " ORDER BY d.global_id DESC");
+
+ rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement sql_alert_transitions");
+ goto fail_only_drop;
+ }
+
+ int param = 1;
+ rc = sqlite3_bind_int64(res, param++, (sqlite3_int64)(after * USEC_PER_SEC));
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind after parameter");
+ goto fail;
+ }
+
+ rc = sqlite3_bind_int64(res, param++, (sqlite3_int64)(before * USEC_PER_SEC));
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind before parameter");
+ goto fail;
+ }
+
+ if (context) {
+ rc = sqlite3_bind_text(res, param++, context, -1, SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind context parameter");
+ goto fail;
+ }
+ }
+
+ if (alert_name) {
+ rc = sqlite3_bind_text(res, param++, alert_name, -1, SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind alert_name parameter");
+ goto fail;
+ }
+ }
+
+run_query:;
+
+ struct sql_alert_transition_data atd = {0 };
+
+ while (sqlite3_step(res) == SQLITE_ROW) {
+ atd.host_id = (uuid_t *) sqlite3_column_blob(res, 0);
+ atd.alarm_id = sqlite3_column_int64(res, 1);
+ atd.config_hash_id = (uuid_t *)sqlite3_column_blob(res, 2);
+ atd.alert_name = (const char *) sqlite3_column_text(res, 3);
+ atd.chart = (const char *) sqlite3_column_text(res, 4);
+ atd.chart_name = (const char *) sqlite3_column_text(res, 4); // FIXME don't copy the id, find the name
+ atd.family = (const char *) sqlite3_column_text(res, 5);
+ atd.recipient = (const char *) sqlite3_column_text(res, 6);
+ atd.units = (const char *) sqlite3_column_text(res, 7);
+ atd.exec = (const char *) sqlite3_column_text(res, 8);
+ atd.chart_context = (const char *) sqlite3_column_text(res, 9);
+ atd.when_key = sqlite3_column_int64(res, 10);
+ atd.duration = sqlite3_column_int64(res, 11);
+ atd.non_clear_duration = sqlite3_column_int64(res, 12);
+ atd.flags = sqlite3_column_int64(res, 13);
+ atd.delay_up_to_timestamp = sqlite3_column_int64(res, 14);
+ atd.info = (const char *) sqlite3_column_text(res, 15);
+ atd.exec_code = sqlite3_column_int(res, 16);
+ atd.new_status = sqlite3_column_int(res, 17);
+ atd.old_status = sqlite3_column_int(res, 18);
+ atd.delay = (int) sqlite3_column_int(res, 19);
+ atd.new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 20);
+ atd.old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 21);
+ atd.last_repeat = sqlite3_column_int64(res, 22);
+ atd.transition_id = (uuid_t *) sqlite3_column_blob(res, 23);
+ atd.global_id = sqlite3_column_int64(res, 24);
+ atd.classification = (const char *) sqlite3_column_text(res, 25);
+ atd.type = (const char *) sqlite3_column_text(res, 26);
+ atd.component = (const char *) sqlite3_column_text(res, 27);
+ atd.exec_run_timestamp = sqlite3_column_int64(res, 28);
+
+ cb(&atd, data);
+ }
+
+fail:
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize statement for sql_alert_transitions");
+
+fail_only_drop:
+ if (likely(!transition)) {
+ (void)snprintfz(sql, 511, "DROP TABLE IF EXISTS v_%p", nodes);
+ (void)db_execute(db_meta, sql);
+ buffer_free(command);
+ }
+}
+
+#define SQL_BUILD_CONFIG_TARGET_LIST "CREATE TEMP TABLE IF NOT EXISTS c_%p (hash_id blob)"
+
+#define SQL_POPULATE_TEMP_CONFIG_TARGET_TABLE "INSERT INTO c_%p (hash_id) VALUES (@hash_id)"
+
+#define SQL_SEARCH_CONFIG_LIST "SELECT ah.hash_id, alarm, template, on_key, class, component, type, os, hosts, lookup, every, " \
+ " units, calc, families, plugin, module, charts, green, red, warn, crit, " \
+ " exec, to_key, info, delay, options, repeat, host_labels, p_db_lookup_dimensions, p_db_lookup_method, " \
+ " p_db_lookup_options, p_db_lookup_after, p_db_lookup_before, p_update_every, source, chart_labels " \
+ " FROM alert_hash ah, c_%p t where ah.hash_id = t.hash_id"
+
+int sql_get_alert_configuration(
+ DICTIONARY *configs,
+ void (*cb)(struct sql_alert_config_data *, void *),
+ void *data,
+ bool debug __maybe_unused)
+{
+ int added = -1;
+ char sql[512];
+ int rc;
+ sqlite3_stmt *res = NULL;
+ BUFFER *command = NULL;
+
+ if (unlikely(!configs))
+ return added;
+
+ snprintfz(sql, 511, SQL_BUILD_CONFIG_TARGET_LIST, configs);
+ rc = db_execute(db_meta, sql);
+ if (rc)
+ return added;
+
+ snprintfz(sql, 511, SQL_POPULATE_TEMP_CONFIG_TARGET_TABLE, configs);
+
+ // Prepare statement to add things
+ rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to INSERT into c_%p", configs);
+ goto fail_only_drop;
+ }
+
+ void *t;
+ dfe_start_read(configs, t) {
+ uuid_t hash_id;
+ uuid_parse( t_dfe.name, hash_id);
+
+ rc = sqlite3_bind_blob(res, 1, &hash_id, sizeof(hash_id), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to bind host_id parameter.");
+
+ rc = sqlite3_step_monitored(res);
+ if (rc != SQLITE_DONE)
+ error_report("Error while populating temp table");
+
+ rc = sqlite3_reset(res);
+ if (rc != SQLITE_OK)
+ error_report("Error while resetting parameters");
+ }
+ dfe_done(t);
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK)) {
+ // log error but continue
+ error_report("Failed to finalize statement for sql_get_alert_configuration temp table population");
+ }
+
+ command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
+
+ buffer_sprintf(command, SQL_SEARCH_CONFIG_LIST, configs);
+
+ rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement sql_get_alert_configuration");
+ goto fail_only_drop;
+ }
+
+ struct sql_alert_config_data acd = {0 };
+
+ added = 0;
+ int param;
+ while (sqlite3_step(res) == SQLITE_ROW) {
+ param = 0;
+ acd.config_hash_id = (uuid_t *) sqlite3_column_blob(res, param++);
+ acd.name = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.on_template = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.on_key = (const char *) sqlite3_column_text(res, param++);
+ acd.classification = (const char *) sqlite3_column_text(res, param++);
+ acd.component = (const char *) sqlite3_column_text(res, param++);
+ acd.type = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.os = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.hosts = (const char *) sqlite3_column_text(res, param++);
+ acd.value.db.lookup = (const char *) sqlite3_column_text(res, param++);
+ acd.value.every = (const char *) sqlite3_column_text(res, param++);
+ acd.value.units = (const char *) sqlite3_column_text(res, param++);
+ acd.value.calc = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.families = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.plugin = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.module = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.charts = (const char *) sqlite3_column_text(res, param++);
+ acd.status.green = (const char *) sqlite3_column_text(res, param++);
+ acd.status.red = (const char *) sqlite3_column_text(res, param++);
+ acd.status.warn = (const char *) sqlite3_column_text(res, param++);
+ acd.status.crit = (const char *) sqlite3_column_text(res, param++);
+ acd.notification.exec = (const char *) sqlite3_column_text(res, param++);
+ acd.notification.to_key = (const char *) sqlite3_column_text(res, param++);
+ acd.info = (const char *) sqlite3_column_text(res, param++);
+ acd.notification.delay = (const char *) sqlite3_column_text(res, param++);
+ acd.notification.options = (const char *) sqlite3_column_text(res, param++);
+ acd.notification.repeat = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.host_labels = (const char *) sqlite3_column_text(res, param++);
+ acd.value.db.dimensions = (const char *) sqlite3_column_text(res, param++);
+ acd.value.db.method = (const char *) sqlite3_column_text(res, param++);
+ acd.value.db.options = (uint32_t) sqlite3_column_int(res, param++);
+ acd.value.db.after = (int32_t) sqlite3_column_int(res, param++);
+ acd.value.db.before = (int32_t) sqlite3_column_int(res, param++);
+ acd.value.update_every = (int32_t) sqlite3_column_int(res, param++);
+ acd.source = (const char *) sqlite3_column_text(res, param++);
+ acd.selectors.chart_labels = (const char *) sqlite3_column_text(res, param++);
+
+ cb(&acd, data);
+ added++;
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize statement for sql_get_alert_configuration");
+
+fail_only_drop:
+ (void)snprintfz(sql, 511, "DROP TABLE IF EXISTS c_%p", configs);
+ (void)db_execute(db_meta, sql);
+ buffer_free(command);
+ return added;
+}
+
diff --git a/database/sqlite/sqlite_health.h b/database/sqlite/sqlite_health.h
index 96d090b54..55e523d2f 100644
--- a/database/sqlite/sqlite_health.h
+++ b/database/sqlite/sqlite_health.h
@@ -5,9 +5,10 @@
#include "../../daemon/common.h"
#include "sqlite3.h"
+struct sql_alert_transition_data;
+struct sql_alert_config_data;
extern sqlite3 *db_meta;
void sql_health_alarm_log_load(RRDHOST *host);
-int sql_create_health_log_table(RRDHOST *host);
void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae);
void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae);
void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae);
@@ -16,4 +17,24 @@ int alert_hash_and_store_config(uuid_t hash_id, struct alert_config *cfg, int st
void sql_aclk_alert_clean_dead_entries(RRDHOST *host);
int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_STATUS *last_executed_status);
void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart);
+int health_migrate_old_health_log_table(char *table);
+uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t *next_event_id, uuid_t *config_hash_id);
+void sql_alert_transitions(
+ DICTIONARY *nodes,
+ time_t after,
+ time_t before,
+ const char *context,
+ const char *alert_name,
+ const char *transition,
+ void (*cb)(struct sql_alert_transition_data *, void *),
+ void *data,
+ bool debug);
+
+int sql_get_alert_configuration(
+ DICTIONARY *configs,
+ void (*cb)(struct sql_alert_config_data *, void *),
+ void *data,
+ bool debug __maybe_unused);
+
+bool sql_find_alert_transition(const char *transition, void (*cb)(const char *machine_guid, const char *context, time_t alert_id, void *data), void *data);
#endif //NETDATA_SQLITE_HEALTH_H
diff --git a/database/sqlite/sqlite_metadata.c b/database/sqlite/sqlite_metadata.c
index 607d789a5..697772bf5 100644
--- a/database/sqlite/sqlite_metadata.c
+++ b/database/sqlite/sqlite_metadata.c
@@ -37,8 +37,8 @@
#define SELECT_DIMENSION_LIST "SELECT dim_id, rowid FROM dimension WHERE rowid > @row_id"
-#define STORE_HOST_INFO "INSERT OR REPLACE INTO host_info (host_id, system_key, system_value, date_created) VALUES "
-#define STORE_HOST_INFO_VALUES "(u2h('%s'), '%s','%s', unixepoch())"
+#define SQL_STORE_HOST_SYSTEM_INFO_VALUES "INSERT OR REPLACE INTO host_info (host_id, system_key, system_value, date_created) VALUES " \
+ "(@uuid, @name, @value, unixepoch())"
#define MIGRATE_LOCALHOST_TO_NEW_MACHINE_GUID \
"UPDATE chart SET host_id = @host_id WHERE host_id in (SELECT host_id FROM host where host_id <> @host_id and hops = 0);"
@@ -378,59 +378,90 @@ bind_fail:
return 1;
}
-static void add_host_sysinfo_key_value(const char *name, const char *value, void *data)
+static int add_host_sysinfo_key_value(const char *name, const char *value, uuid_t *uuid)
{
- struct query_build *lb = data;
+ static __thread sqlite3_stmt *res = NULL;
+ int rc, param = 0;
- if (unlikely(!value))
- return;
+ if (unlikely(!db_meta)) {
+ if (default_rrd_memory_mode != RRD_MEMORY_MODE_DBENGINE)
+ return 0;
+ error_report("Database has not been initialized");
+ return 0;
+ }
- if (unlikely(!lb->count))
- buffer_sprintf(
- lb->sql, STORE_HOST_INFO);
- else
- buffer_strcat(lb->sql, ", ");
- buffer_sprintf(lb->sql, STORE_HOST_INFO_VALUES, lb->uuid_str, name, value);
- lb->count++;
+ if (unlikely((!res))) {
+ rc = prepare_statement(db_meta, SQL_STORE_HOST_SYSTEM_INFO_VALUES, &res);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement to store host info values, rc = %d", rc);
+ return 0;
+ }
+ }
+
+ rc = sqlite3_bind_blob(res, ++param, uuid, sizeof(*uuid), SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK))
+ goto bind_fail;
+
+ rc = bind_text_null(res, ++param, name, 0);
+ if (unlikely(rc != SQLITE_OK))
+ goto bind_fail;
+
+ rc = bind_text_null(res, ++param, value ? value : "unknown", 0);
+ if (unlikely(rc != SQLITE_OK))
+ goto bind_fail;
+
+ int store_rc = sqlite3_step_monitored(res);
+ if (unlikely(store_rc != SQLITE_DONE))
+ error_report("Failed to store host info value %s, rc = %d", name, rc);
+
+ rc = sqlite3_reset(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to store host info value %s, rc = %d", name, rc);
+
+ return store_rc == SQLITE_DONE;
+bind_fail:
+ error_report("Failed to bind %d parameter to store host info values %s, rc = %d", param, name, rc);
+ rc = sqlite3_reset(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement to store host info values %s, rc = %d", name, rc);
+ return 0;
}
-static bool build_host_system_info_statements(RRDHOST *host, BUFFER *work_buffer)
+static bool store_host_systeminfo(RRDHOST *host)
{
struct rrdhost_system_info *system_info = host->system_info;
if (unlikely(!system_info))
return false;
- buffer_flush(work_buffer);
- struct query_build key_data = {.sql = work_buffer, .count = 0};
- uuid_unparse_lower(host->host_uuid, key_data.uuid_str);
-
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_NAME", system_info->container_os_name, &key_data);
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_ID", system_info->container_os_id, &key_data);
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_ID_LIKE", system_info->container_os_id_like, &key_data);
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_VERSION", system_info->container_os_version, &key_data);
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_VERSION_ID", system_info->container_os_version_id, &key_data);
- add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_DETECTION", system_info->host_os_detection, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_NAME", system_info->host_os_name, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_ID", system_info->host_os_id, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_ID_LIKE", system_info->host_os_id_like, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_VERSION", system_info->host_os_version, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_VERSION_ID", system_info->host_os_version_id, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_OS_DETECTION", system_info->host_os_detection, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_KERNEL_NAME", system_info->kernel_name, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT", system_info->host_cores, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_CPU_FREQ", system_info->host_cpu_freq, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_TOTAL_RAM", system_info->host_ram_total, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_TOTAL_DISK_SIZE", system_info->host_disk_space, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_KERNEL_VERSION", system_info->kernel_version, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_ARCHITECTURE", system_info->architecture, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_VIRTUALIZATION", system_info->virtualization, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_VIRT_DETECTION", system_info->virt_detection, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_CONTAINER", system_info->container, &key_data);
- add_host_sysinfo_key_value("NETDATA_SYSTEM_CONTAINER_DETECTION", system_info->container_detection, &key_data);
- add_host_sysinfo_key_value("NETDATA_HOST_IS_K8S_NODE", system_info->is_k8s_node, &key_data);
-
- return true;
+ int ret = 0;
+
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_NAME", system_info->container_os_name, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_ID", system_info->container_os_id, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_ID_LIKE", system_info->container_os_id_like, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_VERSION", system_info->container_os_version, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_VERSION_ID", system_info->container_os_version_id, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_CONTAINER_OS_DETECTION", system_info->host_os_detection, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_NAME", system_info->host_os_name, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_ID", system_info->host_os_id, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_ID_LIKE", system_info->host_os_id_like, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_VERSION", system_info->host_os_version, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_VERSION_ID", system_info->host_os_version_id, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_OS_DETECTION", system_info->host_os_detection, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_KERNEL_NAME", system_info->kernel_name, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_CPU_LOGICAL_CPU_COUNT", system_info->host_cores, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_CPU_FREQ", system_info->host_cpu_freq, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_TOTAL_RAM", system_info->host_ram_total, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_TOTAL_DISK_SIZE", system_info->host_disk_space, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_KERNEL_VERSION", system_info->kernel_version, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_ARCHITECTURE", system_info->architecture, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_VIRTUALIZATION", system_info->virtualization, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_VIRT_DETECTION", system_info->virt_detection, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_CONTAINER", system_info->container, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_SYSTEM_CONTAINER_DETECTION", system_info->container_detection, &host->host_uuid);
+ ret += add_host_sysinfo_key_value("NETDATA_HOST_IS_K8S_NODE", system_info->is_k8s_node, &host->host_uuid);
+
+ return !(24 == ret);
}
@@ -522,7 +553,7 @@ static int store_chart_metadata(RRDSET *st)
if (unlikely(rc != SQLITE_OK))
goto bind_fail;
- rc = sqlite3_bind_int(res, ++param, (int) st->entries);
+ rc = sqlite3_bind_int(res, ++param, (int) st->db.entries);
if (unlikely(rc != SQLITE_OK))
goto bind_fail;
@@ -665,7 +696,7 @@ static void check_dimension_metadata(struct metadata_wc *wc)
uint32_t total_deleted= 0;
uint64_t last_row_id = wc->row_id;
- info("METADATA: Checking dimensions starting after row %"PRIu64, wc->row_id);
+ netdata_log_info("METADATA: Checking dimensions starting after row %"PRIu64, wc->row_id);
while (sqlite3_step_monitored(res) == SQLITE_ROW && total_deleted < MAX_METADATA_CLEANUP) {
if (unlikely(metadata_flag_check(wc, METADATA_FLAG_SHUTDOWN)))
@@ -685,7 +716,7 @@ static void check_dimension_metadata(struct metadata_wc *wc)
wc->check_metadata_after = now + METADATA_MAINTENANCE_RETRY;
} else
wc->row_id = 0;
- info("METADATA: Checked %u, deleted %u -- will resume after row %"PRIu64" in %lld seconds", total_checked, total_deleted, wc->row_id,
+ netdata_log_info("METADATA: Checked %u, deleted %u -- will resume after row %"PRIu64" in %lld seconds", total_checked, total_deleted, wc->row_id,
(long long)(wc->check_metadata_after - now));
skip_run:
@@ -919,7 +950,7 @@ static void cleanup_finished_threads(struct host_context_load_thread *hclt, size
|| (wait && __atomic_load_n(&(hclt[index].busy), __ATOMIC_ACQUIRE))) {
int rc = uv_thread_join(&(hclt[index].thread));
if (rc)
- error("Failed to join thread, rc = %d",rc);
+ netdata_log_error("Failed to join thread, rc = %d",rc);
__atomic_store_n(&(hclt[index].busy), false, __ATOMIC_RELEASE);
__atomic_store_n(&(hclt[index].finished), false, __ATOMIC_RELEASE);
}
@@ -1067,23 +1098,15 @@ static bool metadata_scan_host(RRDHOST *host, uint32_t max_count, bool use_trans
return more_to_do;
}
-static void store_host_and_system_info(RRDHOST *host, BUFFER *work_buffer, size_t *query_counter)
+static void store_host_and_system_info(RRDHOST *host, size_t *query_counter)
{
- bool free_work_buffer = (NULL == work_buffer);
-
- if (unlikely(free_work_buffer))
- work_buffer = buffer_create(1024, &netdata_buffers_statistics.buffers_sqlite);
-
- if (build_host_system_info_statements(host, work_buffer)) {
- int rc = db_execute(db_meta, buffer_tostring(work_buffer));
- if (unlikely(rc)) {
- error_report("METADATA: 'host:%s': Failed to store host updated information in the database", rrdhost_hostname(host));
- rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_UPDATE);
- }
- else {
- if (likely(query_counter))
- (*query_counter)++;
- }
+ if (unlikely(store_host_systeminfo(host))) {
+ error_report("METADATA: 'host:%s': Failed to store host updated system information in the database", rrdhost_hostname(host));
+ rrdhost_flag_set(host, RRDHOST_FLAG_METADATA_INFO | RRDHOST_FLAG_METADATA_UPDATE);
+ }
+ else {
+ if (likely(query_counter))
+ (*query_counter)++;
}
if (unlikely(store_host_metadata(host))) {
@@ -1094,9 +1117,6 @@ static void store_host_and_system_info(RRDHOST *host, BUFFER *work_buffer, size_
if (likely(query_counter))
(*query_counter)++;
}
-
- if (unlikely(free_work_buffer))
- buffer_free(work_buffer);
}
// Worker thread to scan hosts for pending metadata to store
@@ -1170,7 +1190,7 @@ static void start_metadata_hosts(uv_work_t *req __maybe_unused)
}
if (unlikely(rrdhost_flag_check(host, RRDHOST_FLAG_METADATA_INFO))) {
rrdhost_flag_clear(host, RRDHOST_FLAG_METADATA_INFO);
- store_host_and_system_info(host, work_buffer, &query_counter);
+ store_host_and_system_info(host, &query_counter);
}
// For clarity
@@ -1224,27 +1244,27 @@ static void metadata_event_loop(void *arg)
loop = wc->loop = mallocz(sizeof(uv_loop_t));
ret = uv_loop_init(loop);
if (ret) {
- error("uv_loop_init(): %s", uv_strerror(ret));
+ netdata_log_error("uv_loop_init(): %s", uv_strerror(ret));
goto error_after_loop_init;
}
loop->data = wc;
ret = uv_async_init(wc->loop, &wc->async, async_cb);
if (ret) {
- error("uv_async_init(): %s", uv_strerror(ret));
+ netdata_log_error("uv_async_init(): %s", uv_strerror(ret));
goto error_after_async_init;
}
wc->async.data = wc;
ret = uv_timer_init(loop, &wc->timer_req);
if (ret) {
- error("uv_timer_init(): %s", uv_strerror(ret));
+ netdata_log_error("uv_timer_init(): %s", uv_strerror(ret));
goto error_after_timer_init;
}
wc->timer_req.data = wc;
fatal_assert(0 == uv_timer_start(&wc->timer_req, timer_cb, TIMER_INITIAL_PERIOD_MS, TIMER_REPEAT_PERIOD_MS));
- info("Starting metadata sync thread with %d entries command queue", METADATA_CMD_Q_MAX_SIZE);
+ netdata_log_info("Starting metadata sync thread with %d entries command queue", METADATA_CMD_Q_MAX_SIZE);
struct metadata_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
@@ -1309,7 +1329,7 @@ static void metadata_event_loop(void *arg)
break;
case METADATA_ADD_HOST_INFO:
host = (RRDHOST *) cmd.param[0];
- store_host_and_system_info(host, NULL, NULL);
+ store_host_and_system_info(host, NULL);
break;
case METADATA_SCAN_HOSTS:
if (unlikely(metadata_flag_check(wc, METADATA_FLAG_SCANNING_HOSTS)))
@@ -1394,7 +1414,7 @@ static void metadata_event_loop(void *arg)
freez(loop);
worker_unregister();
- info("METADATA: Shutting down event loop");
+ netdata_log_info("METADATA: Shutting down event loop");
completion_mark_complete(&wc->init_complete);
return;
@@ -1415,15 +1435,15 @@ void metadata_sync_shutdown(void)
struct metadata_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
- info("METADATA: Sending a shutdown command");
+ netdata_log_info("METADATA: Sending a shutdown command");
cmd.opcode = METADATA_SYNC_SHUTDOWN;
metadata_enq_cmd(&metasync_worker, &cmd);
/* wait for metadata thread to shut down */
- info("METADATA: Waiting for shutdown ACK");
+ netdata_log_info("METADATA: Waiting for shutdown ACK");
completion_wait_for(&metasync_worker.init_complete);
completion_destroy(&metasync_worker.init_complete);
- info("METADATA: Shutdown complete");
+ netdata_log_info("METADATA: Shutdown complete");
}
void metadata_sync_shutdown_prepare(void)
@@ -1437,11 +1457,11 @@ void metadata_sync_shutdown_prepare(void)
struct completion compl;
completion_init(&compl);
- info("METADATA: Sending a scan host command");
+ netdata_log_info("METADATA: Sending a scan host command");
uint32_t max_wait_iterations = 2000;
while (unlikely(metadata_flag_check(&metasync_worker, METADATA_FLAG_SCANNING_HOSTS)) && max_wait_iterations--) {
if (max_wait_iterations == 1999)
- info("METADATA: Current worker is running; waiting to finish");
+ netdata_log_info("METADATA: Current worker is running; waiting to finish");
sleep_usec(1000);
}
@@ -1449,10 +1469,10 @@ void metadata_sync_shutdown_prepare(void)
cmd.completion = &compl;
metadata_enq_cmd(&metasync_worker, &cmd);
- info("METADATA: Waiting for host scan completion");
+ netdata_log_info("METADATA: Waiting for host scan completion");
completion_wait_for(&compl);
completion_destroy(&compl);
- info("METADATA: Host scan complete; can continue with shutdown");
+ netdata_log_info("METADATA: Host scan complete; can continue with shutdown");
}
// -------------------------------------------------------------
@@ -1471,7 +1491,7 @@ void metadata_sync_init(void)
completion_wait_for(&wc->init_complete);
completion_destroy(&wc->init_complete);
- info("SQLite metadata sync initialization complete");
+ netdata_log_info("SQLite metadata sync initialization complete");
}
@@ -1485,7 +1505,6 @@ static inline void queue_metadata_cmd(enum metadata_opcode opcode, const void *p
cmd.param[1] = param1;
cmd.completion = NULL;
metadata_enq_cmd(&metasync_worker, &cmd);
-
}
// Public