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.c164
1 files changed, 164 insertions, 0 deletions
diff --git a/database/sqlite/sqlite_health.c b/database/sqlite/sqlite_health.c
index 8ba95628f..53742a1a6 100644
--- a/database/sqlite/sqlite_health.c
+++ b/database/sqlite/sqlite_health.c
@@ -433,6 +433,168 @@ void sql_health_alarm_log_count(RRDHOST *host) {
info("HEALTH [%s]: Table health_log_%s, contains %lu entries.", host->hostname, uuid_str, host->health_log_entries_written);
}
+#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) " \
+"select hostname, ?1, ?2, ?3, config_hash_id, 0, ?4, strftime('%%s'), 0, 0, flags, exec_run_timestamp, " \
+"strftime('%%s'), name, chart, family, exec, recipient, source, units, info, exec_code, -2, new_status, delay, NULL, new_value, 0, class, component, type " \
+"from health_log_%s where unique_id = ?5", 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)
+{
+ int rc = 0;
+ 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);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to inject removed event");
+ return;
+ }
+
+ rc = sqlite3_bind_int64(res, 1, (sqlite3_int64) max_unique_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind max_unique_id parameter for SQL_INJECT_REMOVED");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_int64(res, 2, (sqlite3_int64) alarm_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind alarm_id parameter for SQL_INJECT_REMOVED");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_event_id + 1);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind alarm_event_id parameter for SQL_INJECT_REMOVED");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) unique_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind unique_id parameter for SQL_INJECT_REMOVED");
+ goto failed;
+ }
+
+ rc = sqlite3_bind_int64(res, 5, (sqlite3_int64) unique_id);
+ if (unlikely(rc != SQLITE_OK)) {
+ error_report("Failed to bind unique_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);
+ goto failed;
+ }
+
+ 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);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to update 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)");
+ 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)");
+ 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)");
+ 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);
+ goto failed;
+ }
+
+failed:
+ if (unlikely(sqlite3_finalize(res) != SQLITE_OK))
+ error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event.");
+ return;
+
+}
+
+#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)
+{
+ int rc = 0;
+ 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);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to get max unique id");
+ return 0;
+ }
+
+ while (sqlite3_step(res) == SQLITE_ROW) {
+ max_unique_id = (uint32_t) sqlite3_column_int64(res, 0);
+ }
+
+ rc = sqlite3_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize the statement");
+
+ 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)
+{
+ int rc = 0;
+ char command[MAX_HEALTH_SQL_SIZE + 1];
+ RRDCALC_STATUS status;
+ uint32_t alarm_id = 0, alarm_event_id = 0, unique_id = 0, max_unique_id = 0;
+
+ sqlite3_stmt *res = NULL;
+
+ snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_SELECT_LAST_STATUSES(uuid_str));
+ rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);
+ if (rc != SQLITE_OK) {
+ error_report("Failed to prepare statement when trying to check removed statuses");
+ return;
+ }
+
+ while (sqlite3_step(res) == SQLITE_ROW) {
+ 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_finalize(res);
+ if (unlikely(rc != SQLITE_OK))
+ error_report("Failed to finalize the statement");
+}
+
/* Health related SQL queries
Load from the health log table
*/
@@ -454,6 +616,8 @@ void sql_health_alarm_log_load(RRDHOST *host) {
char uuid_str[GUID_LEN + 1];
uuid_unparse_lower_fix(&host->host_uuid, uuid_str);
+ sql_check_removed_alerts_state(uuid_str);
+
snprintfz(command, MAX_HEALTH_SQL_SIZE, SQL_LOAD_HEALTH_LOG(uuid_str, host->health_log.max));
rc = sqlite3_prepare_v2(db_meta, command, -1, &res, 0);