summaryrefslogtreecommitdiffstats
path: root/database/sqlite/sqlite_health.c
diff options
context:
space:
mode:
Diffstat (limited to 'database/sqlite/sqlite_health.c')
-rw-r--r--database/sqlite/sqlite_health.c479
1 files changed, 209 insertions, 270 deletions
diff --git a/database/sqlite/sqlite_health.c b/database/sqlite/sqlite_health.c
index 6fc6a2e64..7d79ff70b 100644
--- a/database/sqlite/sqlite_health.c
+++ b/database/sqlite/sqlite_health.c
@@ -95,18 +95,22 @@ failed:
/* Health related SQL queries
Inserts an entry in the table
*/
+
#define SQL_INSERT_HEALTH_LOG \
"INSERT INTO health_log (host_id, alarm_id, " \
- "config_hash_id, name, chart, exec, recipient, units, chart_context, last_transition_id, chart_name) " \
- "VALUES (?,?,?,?,?,?,?,?,?,?,?) " \
- "ON CONFLICT (host_id, alarm_id) DO UPDATE SET last_transition_id = excluded.last_transition_id, " \
- "chart_name = excluded.chart_name 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, " \
+ "config_hash_id, name, chart, exec, recipient, units, chart_context, last_transition_id, chart_name) " \
+ "VALUES (@host_id,@alarm_id, @config_hash_id,@name,@chart,@exec,@recipient,@units,@chart_context," \
+ "@last_transition_id,@chart_name) ON CONFLICT (host_id, alarm_id) DO UPDATE " \
+ "SET last_transition_id = excluded.last_transition_id, chart_name = excluded.chart_name 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, summary) " \
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,@global_id,?); "
+ "VALUES (@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,@summary)"
+
static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
sqlite3_stmt *res = NULL;
int rc;
@@ -353,7 +357,6 @@ static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
}
ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
- host->health.health_log_entries_written++;
failed:
if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
@@ -374,48 +377,6 @@ 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_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"
-
-static int sql_health_alarm_log_count(RRDHOST *host) {
- sqlite3_stmt *res = NULL;
- int rc;
-
- if (unlikely(!db_meta)) {
- if (default_rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE)
- error_report("Database has not been initialized");
- return -1;
- }
-
- int entries_in_db = -1;
-
- 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");
- goto done;
- }
-
- 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.");
- goto done;
- }
-
- rc = sqlite3_step_monitored(res);
- if (likely(rc == SQLITE_ROW))
- entries_in_db = (int) sqlite3_column_int64(res, 0);
-
-done:
- rc = sqlite3_finalize(res);
- if (unlikely(rc != SQLITE_OK))
- error_report("Failed to finalize the prepared statement to count health log entries from db");
-
- return entries_in_db;
-}
-
/*
*
* Health related SQL queries
@@ -423,19 +384,22 @@ done:
*
*/
-#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 = @host_id) AND when_key < unixepoch() - @history " \
- "AND updated_by_id <> 0 AND transition_id NOT IN " \
- "(SELECT last_transition_id FROM health_log hl WHERE hl.host_id = @host_id);"
-
-#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 = @host_id AND hl.health_log_id = hld.health_log_id) " \
- "AND health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = @host_id) " \
- "AND when_key < unixepoch() - @history " \
- "AND updated_by_id <> 0 AND transition_id NOT IN " \
- "(SELECT last_transition_id FROM health_log hl WHERE hl.host_id = @host_id);", guid
+#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 = @host_id) AND when_key < UNIXEPOCH() - @history " \
+ "AND updated_by_id <> 0 AND transition_id NOT IN " \
+ "(SELECT last_transition_id FROM health_log hl WHERE hl.host_id = @host_id)"
+
+#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 = @host_id AND hl.health_log_id = hld.health_log_id) " \
+ "AND health_log_id IN (SELECT health_log_id FROM health_log WHERE host_id = @host_id) " \
+ "AND when_key < unixepoch() - @history " \
+ "AND updated_by_id <> 0 AND transition_id NOT IN " \
+ "(SELECT last_transition_id FROM health_log hl WHERE hl.host_id = @host_id)", \
+ guid
void sql_health_alarm_log_cleanup(RRDHOST *host, bool claimed) {
sqlite3_stmt *res = NULL;
@@ -450,14 +414,14 @@ void sql_health_alarm_log_cleanup(RRDHOST *host, bool claimed) {
char uuid_str[UUID_STR_LEN];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
- snprintfz(command, MAX_HEALTH_SQL_SIZE, "aclk_alert_%s", uuid_str);
+ snprintfz(command, sizeof(command) - 1, "aclk_alert_%s", uuid_str);
bool aclk_table_exists = table_exists_in_database(db_meta, command);
char *sql = SQL_CLEANUP_HEALTH_LOG_DETAIL_NOT_CLAIMED;
if (claimed && aclk_table_exists) {
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(uuid_str));
+ snprintfz(command, sizeof(command) - 1, SQL_CLEANUP_HEALTH_LOG_DETAIL_CLAIMED(uuid_str));
sql = command;
}
@@ -483,10 +447,6 @@ void sql_health_alarm_log_cleanup(RRDHOST *host, bool claimed) {
if (unlikely(rc != SQLITE_DONE))
error_report("Failed to cleanup health log detail table, rc = %d", rc);
- int rows = sql_health_alarm_log_count(host);
- if (rows >= 0)
- host->health.health_log_entries_written = rows;
-
if (aclk_table_exists)
sql_aclk_alert_clean_dead_entries(host);
@@ -497,17 +457,25 @@ done:
}
#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, " \
+ "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, summary) " \
- "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), summary 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)
+ "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), summary 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;
@@ -737,13 +705,14 @@ void sql_check_removed_alerts_state(RRDHOST *host)
/* Health related SQL queries
Load from the health log table
*/
-#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.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, hl.chart_name, hld.summary " \
- "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;"
+#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.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, " \
+ "hl.chart_name, hld.summary 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)
{
@@ -751,8 +720,6 @@ void sql_health_alarm_log_load(RRDHOST *host)
int ret;
ssize_t errored = 0, loaded = 0;
- host->health.health_log_entries_written = 0;
-
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));
@@ -914,27 +881,28 @@ 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;
- netdata_log_health("[%s]: Table health_log, loaded %zd alarm entries, errors in %zd entries.", rrdhost_hostname(host), loaded, errored);
+ nd_log(NDLS_DAEMON, errored ? NDLP_WARNING : NDLP_DEBUG,
+ "[%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))
error_report("Failed to finalize the health log read statement");
-
- int rows = sql_health_alarm_log_count(host);
-
- if (rows >= 0)
- host->health.health_log_entries_written = rows;
}
/*
* Store an alert config hash in the database
*/
-#define SQL_STORE_ALERT_CONFIG_HASH "insert or replace into alert_hash (hash_id, date_updated, alarm, template, " \
- "on_key, class, component, type, os, hosts, lookup, every, units, calc, 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, summary) 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);"
+#define SQL_STORE_ALERT_CONFIG_HASH \
+ "insert or replace into alert_hash (hash_id, date_updated, alarm, template, " \
+ "on_key, class, component, type, os, hosts, lookup, every, units, calc, 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, summary) values (@hash_id,UNIXEPOCH(),@alarm,@template," \
+ "@on_key,@class,@component,@type,@os,@hosts,@lookup,@every,@units,@calc,@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,@summary)"
int sql_store_alert_config_hash(uuid_t *hash_id, struct alert_config *cfg)
{
@@ -1212,7 +1180,7 @@ int alert_hash_and_store_config(
#define SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT \
"SELECT hld.new_status FROM health_log hl, health_log_detail hld " \
"WHERE hl.host_id = @host_id AND hl.alarm_id = @alarm_id AND hld.unique_id != @unique_id AND hld.flags & @flags " \
- "AND hl.health_log_id = hld.health_log_id ORDER BY hld.unique_id DESC LIMIT 1;"
+ "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)
{
@@ -1270,191 +1238,162 @@ done:
"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.summary " \
"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 "
+ "hl.health_log_id = hld.health_log_id and hl.host_id = @host_id AND hld.unique_id > @after "
-void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, uint32_t after, char *chart) {
+void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const char *chart)
+{
+ unsigned int max = host->health_log.max;
- buffer_strcat(wb, "[");
+ static __thread sqlite3_stmt *stmt_no_chart = NULL;
+ static __thread sqlite3_stmt *stmt_with_chart = NULL;
- unsigned int max = host->health_log.max;
- unsigned int count = 0;
+ sqlite3_stmt **active_stmt;
+ sqlite3_stmt *stmt_query;
- sqlite3_stmt *res = NULL;
- int rc;
+ int rc;
- BUFFER *command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
- buffer_sprintf(command, SQL_SELECT_HEALTH_LOG);
+ active_stmt = chart ? &stmt_with_chart : &stmt_no_chart;
- if (chart) {
- char chart_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(chart_sql, MAX_HEALTH_SQL_SIZE, "AND hl.chart = '%s' ", chart);
- buffer_strcat(command, chart_sql);
- }
+ if (!*active_stmt) {
- if (after) {
- char after_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(after_sql, MAX_HEALTH_SQL_SIZE, "AND hld.unique_id > %u ", after);
- buffer_strcat(command, after_sql);
- }
+ BUFFER *command = buffer_create(MAX_HEALTH_SQL_SIZE, NULL);
+ buffer_sprintf(command, SQL_SELECT_HEALTH_LOG);
- {
- char limit_sql[MAX_HEALTH_SQL_SIZE + 1];
- snprintfz(limit_sql, MAX_HEALTH_SQL_SIZE, "ORDER BY hld.unique_id DESC LIMIT %u ", max);
- buffer_strcat(command, limit_sql);
- }
+ if (chart)
+ buffer_strcat(command, " AND hl.chart = @chart ");
- rc = sqlite3_prepare_v2(db_meta, buffer_tostring(command), -1, &res, 0);
- if (unlikely(rc != SQLITE_OK)) {
- error_report("Failed to prepare statement SQL_SELECT_HEALTH_LOG");
- buffer_free(command);
- return;
- }
+ buffer_strcat(command, " ORDER BY hld.unique_id DESC LIMIT @limit");
- 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;
- }
+ rc = prepare_statement(db_meta, buffer_tostring(command), active_stmt);
+ buffer_free(command);
- while (sqlite3_step(res) == SQLITE_ROW) {
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to prepare statement SQL_SELECT_HEALTH_LOG");
+ return;
+ }
+ }
- char old_value_string[100 + 1];
- char new_value_string[100 + 1];
+ stmt_query = *active_stmt;
- char config_hash_id[UUID_STR_LEN];
- uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 3)), config_hash_id);
+ int param = 0;
+ rc = sqlite3_bind_blob(stmt_query, ++param, &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.");
+ goto finish;
+ }
- char transition_id[UUID_STR_LEN] = {0};
- if (sqlite3_column_type(res, 30) != SQLITE_NULL)
- uuid_unparse_lower(*((uuid_t *) sqlite3_column_blob(res, 30)), transition_id);
-
- char *edit_command = sqlite3_column_bytes(res, 16) > 0 ? health_edit_command_from_source((char *)sqlite3_column_text(res, 16)) : strdupz("UNKNOWN=0=UNKNOWN");
-
- if (count)
- buffer_sprintf(wb, ",");
-
- count++;
-
- buffer_sprintf(
- wb,
- "\n\t{\n"
- "\t\t\"hostname\": \"%s\",\n"
- "\t\t\"utc_offset\": %d,\n"
- "\t\t\"timezone\": \"%s\",\n"
- "\t\t\"unique_id\": %u,\n"
- "\t\t\"alarm_id\": %u,\n"
- "\t\t\"alarm_event_id\": %u,\n"
- "\t\t\"config_hash_id\": \"%s\",\n"
- "\t\t\"transition_id\": \"%s\",\n"
- "\t\t\"name\": \"%s\",\n"
- "\t\t\"chart\": \"%s\",\n"
- "\t\t\"context\": \"%s\",\n"
- "\t\t\"class\": \"%s\",\n"
- "\t\t\"component\": \"%s\",\n"
- "\t\t\"type\": \"%s\",\n"
- "\t\t\"processed\": %s,\n"
- "\t\t\"updated\": %s,\n"
- "\t\t\"exec_run\": %lu,\n"
- "\t\t\"exec_failed\": %s,\n"
- "\t\t\"exec\": \"%s\",\n"
- "\t\t\"recipient\": \"%s\",\n"
- "\t\t\"exec_code\": %d,\n"
- "\t\t\"source\": \"%s\",\n"
- "\t\t\"command\": \"%s\",\n"
- "\t\t\"units\": \"%s\",\n"
- "\t\t\"when\": %lu,\n"
- "\t\t\"duration\": %lu,\n"
- "\t\t\"non_clear_duration\": %lu,\n"
- "\t\t\"status\": \"%s\",\n"
- "\t\t\"old_status\": \"%s\",\n"
- "\t\t\"delay\": %d,\n"
- "\t\t\"delay_up_to_timestamp\": %lu,\n"
- "\t\t\"updated_by_id\": %u,\n"
- "\t\t\"updates_id\": %u,\n"
- "\t\t\"value_string\": \"%s\",\n"
- "\t\t\"old_value_string\": \"%s\",\n"
- "\t\t\"last_repeat\": %lu,\n"
- "\t\t\"silenced\": \"%s\",\n",
- 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),
- config_hash_id,
- transition_id,
- sqlite3_column_text(res, 12),
- sqlite3_column_text(res, 13),
- sqlite3_column_text(res, 29),
- sqlite3_column_text(res, 26) ? (const char *) sqlite3_column_text(res, 26) : (char *) "Unknown",
- 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_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, 14) ? (const char *) sqlite3_column_text(res, 14) : string2str(host->health.health_default_exec),
- sqlite3_column_text(res, 15) ? (const char *) sqlite3_column_text(res, 15) : string2str(host->health.health_default_recipient),
- sqlite3_column_int(res, 19),
- sqlite3_column_text(res, 16) ? (const char *) sqlite3_column_text(res, 16) : (char *) "Unknown",
- edit_command,
- sqlite3_column_text(res, 17),
- (long unsigned int)sqlite3_column_int64(res, 6),
- (long unsigned int)sqlite3_column_int64(res, 7),
- (long unsigned int)sqlite3_column_int64(res, 8),
- rrdcalc_status2string(sqlite3_column_int(res, 20)),
- rrdcalc_status2string(sqlite3_column_int(res, 21)),
- sqlite3_column_int(res, 22),
- (long unsigned int)sqlite3_column_int64(res, 11),
- (unsigned int)sqlite3_column_int64(res, 4),
- (unsigned int)sqlite3_column_int64(res, 5),
- sqlite3_column_type(res, 23) == SQLITE_NULL ? "-" : format_value_and_unit(new_value_string, 100, sqlite3_column_double(res, 23), (char *) sqlite3_column_text(res, 17), -1),
- sqlite3_column_type(res, 24) == SQLITE_NULL ? "-" : format_value_and_unit(old_value_string, 100, sqlite3_column_double(res, 24), (char *) sqlite3_column_text(res, 17), -1),
- (long unsigned int)sqlite3_column_int64(res, 25),
- (sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_SILENCED)?"true":"false");
-
- health_string2json(wb, "\t\t", "summary", (char *) sqlite3_column_text(res, 31), ",\n");
- health_string2json(wb, "\t\t", "info", (char *) sqlite3_column_text(res, 18), ",\n");
-
- if(unlikely(sqlite3_column_int64(res, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
- buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
- }
+ rc = sqlite3_bind_int64(stmt_query, ++param, after);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind after for SQL_SELECT_HEALTH_LOG.");
+ goto finish;
+ }
- buffer_strcat(wb, "\t\t\"value\":");
- if (sqlite3_column_type(res, 23) == SQLITE_NULL)
- buffer_strcat(wb, "null");
- else
- buffer_print_netdata_double(wb, sqlite3_column_double(res, 23));
- buffer_strcat(wb, ",\n");
+ if (chart) {
+ rc = sqlite3_bind_text(stmt_query, ++param, chart, -1, SQLITE_STATIC);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind after for SQL_SELECT_HEALTH_LOG.");
+ goto finish;
+ }
+ }
- buffer_strcat(wb, "\t\t\"old_value\":");
- if (sqlite3_column_type(res, 24) == SQLITE_NULL)
- buffer_strcat(wb, "null");
+ rc = sqlite3_bind_int64(stmt_query, ++param, max);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind max lines for SQL_SELECT_HEALTH_LOG.");
+ goto finish;
+ }
+
+ buffer_json_initialize(wb, "\"", "\"", 0, false, BUFFER_JSON_OPTIONS_DEFAULT);
+ buffer_json_member_add_array(wb, NULL);
+
+ while (sqlite3_step(stmt_query) == 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(stmt_query, 3)), config_hash_id);
+
+ char transition_id[UUID_STR_LEN] = {0};
+ if (sqlite3_column_type(stmt_query, 30) != SQLITE_NULL)
+ uuid_unparse_lower(*((uuid_t *)sqlite3_column_blob(stmt_query, 30)), transition_id);
+
+ char *edit_command = sqlite3_column_bytes(stmt_query, 16) > 0 ?
+ health_edit_command_from_source((char *)sqlite3_column_text(stmt_query, 16)) :
+ strdupz("UNKNOWN=0=UNKNOWN");
+
+ buffer_json_add_array_item_object(wb); // this node
+
+ buffer_json_member_add_string_or_empty(wb, "hostname", rrdhost_hostname(host));
+ buffer_json_member_add_int64(wb, "utc_offset", (int64_t)host->utc_offset);
+ buffer_json_member_add_string_or_empty(wb, "timezone", rrdhost_abbrev_timezone(host));
+ buffer_json_member_add_int64(wb, "unique_id", (int64_t) sqlite3_column_int64(stmt_query, 0));
+ buffer_json_member_add_int64(wb, "alarm_id", (int64_t) sqlite3_column_int64(stmt_query, 1));
+ buffer_json_member_add_int64(wb, "alarm_event_id", (int64_t) sqlite3_column_int64(stmt_query, 2));
+ buffer_json_member_add_string_or_empty(wb, "config_hash_id", config_hash_id);
+ buffer_json_member_add_string_or_empty(wb, "transition_id", transition_id);
+ buffer_json_member_add_string_or_empty(wb, "name", (const char *) sqlite3_column_text(stmt_query, 12));
+ buffer_json_member_add_string_or_empty(wb, "chart", (const char *) sqlite3_column_text(stmt_query, 13));
+ buffer_json_member_add_string_or_empty(wb, "context", (const char *) sqlite3_column_text(stmt_query, 29));
+ buffer_json_member_add_string_or_empty(wb, "class", sqlite3_column_text(stmt_query, 26) ? (const char *) sqlite3_column_text(stmt_query, 26) : (char *) "Unknown");
+ buffer_json_member_add_string_or_empty(wb, "component", sqlite3_column_text(stmt_query, 27) ? (const char *) sqlite3_column_text(stmt_query, 27) : (char *) "Unknown");
+ buffer_json_member_add_string_or_empty(wb, "type", sqlite3_column_text(stmt_query, 28) ? (const char *) sqlite3_column_text(stmt_query, 28) : (char *) "Unknown");
+ buffer_json_member_add_boolean(wb, "processed", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_PROCESSED));
+ buffer_json_member_add_boolean(wb, "updated", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_UPDATED));
+ buffer_json_member_add_int64(wb, "exec_run", (int64_t)sqlite3_column_int64(stmt_query, 10));
+ buffer_json_member_add_boolean(wb, "exec_failed", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_EXEC_FAILED));
+ buffer_json_member_add_string_or_empty(wb, "exec", sqlite3_column_text(stmt_query, 14) ? (const char *) sqlite3_column_text(stmt_query, 14) : string2str(host->health.health_default_exec));
+ buffer_json_member_add_string_or_empty(wb, "recipient", sqlite3_column_text(stmt_query, 15) ? (const char *) sqlite3_column_text(stmt_query, 15) : string2str(host->health.health_default_recipient));
+ buffer_json_member_add_int64(wb, "exec_code", sqlite3_column_int(stmt_query, 19));
+ buffer_json_member_add_string_or_empty(wb, "source", sqlite3_column_text(stmt_query, 16) ? (const char *) sqlite3_column_text(stmt_query, 16) : (char *) "Unknown");
+ buffer_json_member_add_string_or_empty(wb, "command", edit_command);
+ buffer_json_member_add_string_or_empty(wb, "units", (const char *) sqlite3_column_text(stmt_query, 17));
+ buffer_json_member_add_int64(wb, "when", (int64_t)sqlite3_column_int64(stmt_query, 6));
+ buffer_json_member_add_int64(wb, "duration", (int64_t)sqlite3_column_int64(stmt_query, 7));
+ buffer_json_member_add_int64(wb, "non_clear_duration", (int64_t)sqlite3_column_int64(stmt_query, 8));
+ buffer_json_member_add_string_or_empty(wb, "status", rrdcalc_status2string(sqlite3_column_int(stmt_query, 20)));
+ buffer_json_member_add_string_or_empty(wb, "old_status", rrdcalc_status2string(sqlite3_column_int(stmt_query, 21)));
+ buffer_json_member_add_int64(wb, "delay", sqlite3_column_int(stmt_query, 22));
+ buffer_json_member_add_int64(wb, "delay_up_to_timestamp",(int64_t)sqlite3_column_int64(stmt_query, 11));
+ buffer_json_member_add_int64(wb, "updated_by_id", (unsigned int)sqlite3_column_int64(stmt_query, 4));
+ buffer_json_member_add_int64(wb, "updates_id", (unsigned int)sqlite3_column_int64(stmt_query, 5));
+ buffer_json_member_add_string_or_empty(wb, "value_string", sqlite3_column_type(stmt_query, 23) == SQLITE_NULL ? "-" :
+ format_value_and_unit(new_value_string, 100, sqlite3_column_double(stmt_query, 23), (char *) sqlite3_column_text(stmt_query, 17), -1));
+ buffer_json_member_add_string_or_empty(wb, "old_value_string", sqlite3_column_type(stmt_query, 24) == SQLITE_NULL ? "-" :
+ format_value_and_unit(old_value_string, 100, sqlite3_column_double(stmt_query, 24), (char *) sqlite3_column_text(stmt_query, 17), -1));
+ buffer_json_member_add_int64(wb, "last_repeat", (int64_t)sqlite3_column_int64(stmt_query, 25));
+ buffer_json_member_add_boolean(wb, "silenced", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_SILENCED));
+ buffer_json_member_add_string_or_empty(wb, "summary", (const char *) sqlite3_column_text(stmt_query, 31));
+ buffer_json_member_add_string_or_empty(wb, "info", (const char *) sqlite3_column_text(stmt_query, 18));
+ buffer_json_member_add_boolean(wb, "no_clear_notification",(sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION));
+
+ if (sqlite3_column_type(stmt_query, 23) == SQLITE_NULL)
+ buffer_json_member_add_string(wb, "value", NULL);
else
- buffer_print_netdata_double(wb, sqlite3_column_double(res, 24));
- buffer_strcat(wb, "\n");
+ buffer_json_member_add_double(wb, "value", sqlite3_column_double(stmt_query, 23));
- buffer_strcat(wb, "\t}");
+ if (sqlite3_column_type(stmt_query, 24) == SQLITE_NULL)
+ buffer_json_member_add_string(wb, "old_value", NULL);
+ else
+ buffer_json_member_add_double(wb, "old_value", sqlite3_column_double(stmt_query, 23));
freez(edit_command);
+
+ buffer_json_object_close(wb);
}
- buffer_strcat(wb, "\n]");
+ buffer_json_array_close(wb);
+ buffer_json_finalize(wb);
- rc = sqlite3_finalize(res);
- if (unlikely(rc != SQLITE_OK))
- error_report("Failed to finalize statement for SQL_SELECT_HEALTH_LOG");
-
- buffer_free(command);
+finish:
+ rc = sqlite3_reset(stmt_query);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to reset statement for SQL_SELECT_HEALTH_LOG");
}
-#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;"
+#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;
@@ -1476,7 +1415,7 @@ int health_migrate_old_health_log_table(char *table) {
int rc;
char command[MAX_HEALTH_SQL_SIZE + 1];
sqlite3_stmt *res = NULL;
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG(table));
+ snprintfz(command, sizeof(command) - 1, 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);
@@ -1503,7 +1442,7 @@ int health_migrate_old_health_log_table(char *table) {
}
//detail
- snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_COPY_HEALTH_LOG_DETAIL(table));
+ snprintfz(command, sizeof(command) - 1, 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);
@@ -1913,12 +1852,12 @@ void sql_alert_transitions(
goto run_query;
}
- snprintfz(sql, 511, SQL_BUILD_ALERT_TRANSITION, nodes);
+ snprintfz(sql, sizeof(sql) - 1, SQL_BUILD_ALERT_TRANSITION, nodes);
rc = db_execute(db_meta, sql);
if (rc)
return;
- snprintfz(sql, 511, SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE, nodes);
+ snprintfz(sql, sizeof(sql) - 1, SQL_POPULATE_TEMP_ALERT_TRANSITION_TABLE, nodes);
// Prepare statement to add things
rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
@@ -2046,7 +1985,7 @@ done:
done_only_drop:
if (likely(!transition)) {
- (void)snprintfz(sql, 511, "DROP TABLE IF EXISTS v_%p", nodes);
+ (void)snprintfz(sql, sizeof(sql) - 1, "DROP TABLE IF EXISTS v_%p", nodes);
(void)db_execute(db_meta, sql);
buffer_free(command);
}
@@ -2078,12 +2017,12 @@ int sql_get_alert_configuration(
if (unlikely(!configs))
return added;
- snprintfz(sql, 511, SQL_BUILD_CONFIG_TARGET_LIST, configs);
+ snprintfz(sql, sizeof(sql) - 1, 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);
+ snprintfz(sql, sizeof(sql) - 1, SQL_POPULATE_TEMP_CONFIG_TARGET_TABLE, configs);
// Prepare statement to add things
rc = sqlite3_prepare_v2(db_meta, sql, -1, &res, 0);
@@ -2180,7 +2119,7 @@ int sql_get_alert_configuration(
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)snprintfz(sql, sizeof(sql) - 1, "DROP TABLE IF EXISTS c_%p", configs);
(void)db_execute(db_meta, sql);
buffer_free(command);
return added;