From dd814a7c1a8de056a79f7238578b09236edd5506 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 10 Aug 2023 11:18:49 +0200 Subject: Adding upstream version 1.42.0. Signed-off-by: Daniel Baumann --- database/sqlite/sqlite_health.c | 275 +++++++++++++++++++++++++++++++++++----- 1 file changed, 242 insertions(+), 33 deletions(-) (limited to 'database/sqlite/sqlite_health.c') diff --git a/database/sqlite/sqlite_health.c b/database/sqlite/sqlite_health.c index 3ecd783dc..9c103f098 100644 --- a/database/sqlite/sqlite_health.c +++ b/database/sqlite/sqlite_health.c @@ -83,9 +83,10 @@ failed: Inserts an entry in the table */ #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; " + "config_hash_id, name, chart, family, 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, " \ @@ -174,6 +175,12 @@ void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) { goto failed; } + rc = sqlite3_bind_string_or_null(res, ae->chart_name, 12); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind chart_name parameter for SQL_INSERT_HEALTH_LOG"); + goto failed; + } + rc = sqlite3_step_monitored(res); if (likely(rc == SQLITE_ROW)) health_log_id = (size_t) sqlite3_column_int64(res, 0); @@ -685,7 +692,10 @@ failed: error_report("HEALTH [N/A]: Failed to finalize the prepared statement for injecting removed event."); } -#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" +#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; @@ -766,7 +776,7 @@ void sql_check_removed_alerts_state(RRDHOST *host) "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 " \ + "hld.last_repeat, ah.class, ah.component, ah.type, hl.chart_context, hld.transition_id, hld.global_id, hl.chart_name " \ "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) { @@ -945,6 +955,11 @@ void sql_health_alarm_log_load(RRDHOST *host) { if (sqlite3_column_type(res, 32) != SQLITE_NULL) ae->global_id = sqlite3_column_int64(res, 32); + if (sqlite3_column_type(res, 33) != SQLITE_NULL) + ae->chart_name = string_strdupz((char *) sqlite3_column_text(res, 33)); + else + ae->chart_name = NULL; + char value_string[100 + 1]; string_freez(ae->old_value_string); string_freez(ae->new_value_string); @@ -1203,7 +1218,7 @@ bind_fail: if cloud is disabled or openssl is not available (which will prevent cloud connectivity) skip hash calculations */ -#if !defined DISABLE_CLOUD && defined ENABLE_HTTPS +#if defined ENABLE_HTTPS #define DIGEST_ALERT_CONFIG_VAL(v) ((v) ? EVP_DigestUpdate(evpctx, (string2str(v)), string_strlen((v))) : EVP_DigestUpdate(evpctx, "", 1)) #endif int alert_hash_and_store_config( @@ -1211,7 +1226,7 @@ int alert_hash_and_store_config( struct alert_config *cfg, int store_hash) { -#if !defined DISABLE_CLOUD && defined ENABLE_HTTPS +#if defined ENABLE_HTTPS EVP_MD_CTX *evpctx; unsigned char hash_value[EVP_MAX_MD_SIZE]; unsigned int hash_len; @@ -1717,6 +1732,135 @@ uint32_t sql_get_alarm_id(RRDHOST *host, STRING *chart, STRING *name, uint32_t * return alarm_id; } +#define SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH "update health_log set config_hash_id = @config_hash_id where host_id = @host_id and alarm_id = @alarm_id and health_log_id = @health_log_id" +void sql_update_alarm_with_config_hash(RRDHOST *host, uint32_t alarm_id, uint64_t health_log_id, uuid_t *config_hash_id) +{ + int rc = 0; + sqlite3_stmt *res = NULL; + + rc = sqlite3_prepare_v2(db_meta, SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH, -1, &res, 0); + if (rc != SQLITE_OK) { + error_report("Failed to prepare statement when trying to update an alarm id with a config hash."); + return; + } + + rc = sqlite3_bind_blob(res, 1, 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_UPDATE_ALARM_ID_WITH_CONFIG_HASH."); + 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 host_id parameter for SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH."); + sqlite3_finalize(res); + return; + } + + rc = sqlite3_bind_int64(res, 3, (sqlite3_int64) alarm_id); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind alarm_id parameter for SQL_GET_ALARM_ID."); + sqlite3_finalize(res); + return; + } + + rc = sqlite3_bind_int64(res, 4, (sqlite3_int64) health_log_id); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to bind alarm_id parameter for SQL_GET_ALARM_ID."); + sqlite3_finalize(res); + return; + } + + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) { + error_report("Failed to execute SQL_UPDATE_ALARM_ID_WITH_CONFIG_HASH, 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 config hash ids, rc = %d", rc); + return; + } +} + +#define SQL_GET_ALARM_ID_CHECK_ZERO_HASH "select alarm_id, health_log_id from health_log where host_id = @host_id and chart = @chart and name = @name and (config_hash_id is null or config_hash_id = zeroblob(16))" +uint32_t sql_get_alarm_id_check_zero_hash(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_CHECK_ZERO_HASH, -1, &res, 0); + if (rc != SQLITE_OK) { + error_report("Failed to prepare statement when trying to get an alarm id with zero hash"); + 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_CHECK_ZERO_HASH."); + 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_CHECK_ZERO_HASH."); + 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_CHECK_ZERO_HASH."); + 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) { + sql_update_alarm_with_config_hash(host, alarm_id, health_log_id, config_hash_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" @@ -1767,7 +1911,7 @@ fail: #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.host_id, h.alarm_id, h.config_hash_id, h.name, h.chart, h.chart_name, 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" @@ -1913,31 +2057,31 @@ run_query:; 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); + atd.chart_name = (const char *) sqlite3_column_text(res, 5); + atd.family = (const char *) sqlite3_column_text(res, 6); + atd.recipient = (const char *) sqlite3_column_text(res, 7); + atd.units = (const char *) sqlite3_column_text(res, 8); + atd.exec = (const char *) sqlite3_column_text(res, 9); + atd.chart_context = (const char *) sqlite3_column_text(res, 10); + atd.when_key = sqlite3_column_int64(res, 11); + atd.duration = sqlite3_column_int64(res, 12); + atd.non_clear_duration = sqlite3_column_int64(res, 13); + atd.flags = sqlite3_column_int64(res, 14); + atd.delay_up_to_timestamp = sqlite3_column_int64(res, 15); + atd.info = (const char *) sqlite3_column_text(res, 16); + atd.exec_code = sqlite3_column_int(res, 17); + atd.new_status = sqlite3_column_int(res, 18); + atd.old_status = sqlite3_column_int(res, 19); + atd.delay = (int) sqlite3_column_int(res, 20); + atd.new_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 21); + atd.old_value = (NETDATA_DOUBLE) sqlite3_column_double(res, 22); + atd.last_repeat = sqlite3_column_int64(res, 23); + atd.transition_id = (uuid_t *) sqlite3_column_blob(res, 24); + atd.global_id = sqlite3_column_int64(res, 25); + atd.classification = (const char *) sqlite3_column_text(res, 26); + atd.type = (const char *) sqlite3_column_text(res, 27); + atd.component = (const char *) sqlite3_column_text(res, 28); + atd.exec_run_timestamp = sqlite3_column_int64(res, 29); cb(&atd, data); } @@ -2087,3 +2231,68 @@ fail_only_drop: return added; } +#define SQL_FETCH_CHART_NAME "SELECT chart_name FROM health_log where host_id = @host_id LIMIT 1;" +bool is_chart_name_populated(uuid_t *host_uuid) +{ + sqlite3_stmt *res = NULL; + int rc; + + bool status = true; + + rc = sqlite3_prepare_v2(db_meta, SQL_FETCH_CHART_NAME, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to check health_log chart_name"); + return true; + } + + 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 for health_log chart_name check"); + goto fail; + } + + rc = sqlite3_step_monitored(res); + if (likely(rc == SQLITE_ROW)) + status = sqlite3_column_type(res, 0) != SQLITE_NULL; +fail: + + rc = sqlite3_finalize(res); + if (unlikely(rc != SQLITE_OK)) + error_report("Failed to finalize the prepared statement for health_log chart_name check"); + + return status; +} + +#define SQL_POPULATE_CHART_NAME " UPDATE health_log SET chart_name = upd.chart_name FROM " \ + "(SELECT c.type || '.' || IFNULL(c.name, c.id) AS chart_name, hl.host_id, hl.health_log_id FROM " \ + "chart c, health_log hl WHERE (c.type || '.' || c.id) = hl.chart AND c.host_id = hl.host_id " \ + "AND hl.host_id = @host_id) AS upd WHERE health_log.host_id = upd.host_id " \ + "AND health_log.health_log_id = upd.health_log_id" + +void chart_name_populate(uuid_t *host_uuid) +{ + sqlite3_stmt *res = NULL; + int rc; + + rc = sqlite3_prepare_v2(db_meta, SQL_POPULATE_CHART_NAME, -1, &res, 0); + if (unlikely(rc != SQLITE_OK)) { + error_report("Failed to prepare statement to update health_log chart_name"); + return; + } + + 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 for health_log chart_name update"); + goto fail; + } + + rc = execute_insert(res); + if (unlikely(rc != SQLITE_DONE)) + error_report("Failed to update chart name in health_log, rc = %d", rc); + +fail: + + rc = sqlite3_finalize(res); + if (unlikely(rc != SQLITE_OK)) + error_report("Failed to finalize the prepared statement for health_log chart_name update"); +} -- cgit v1.2.3