@cryptotaxi247 / netdata-1 / commits / 2298e8b82

Further improve alert processing (#19489)

More pre compiled statements (compile once and use in a loop before finalize) Create a new index on alert_queue

Stelios Fragkakis committed Jan 27, 2025 at 10:21 UTC 2298e8b8259973f7616bb054666045b24d5c233c
3 files changed +57 -30
src/database/sqlite/sqlite_aclk_alert.c
+40 -27
@@ -262,7 +262,7 @@ static inline char *sqlite3_text_strdupz_empty(sqlite3_stmt *res, int iCol) {
262
263 #define SQL_UPDATE_ALERT_VERSION \
264 "INSERT INTO alert_version (health_log_id, unique_id, status, version, date_submitted)" \
265 - " VALUES (@health_log_id, @unique_id, @status, @version, UNIXEPOCH())" \
265 + " VALUES (@health_log_id, @unique_id, @status, @version, UNIXEPOCH())" \
266 " ON CONFLICT(health_log_id) DO UPDATE SET status = excluded.status, version = excluded.version, " \
267 " unique_id=excluded.unique_id, date_submitted=excluded.date_submitted"
268
@@ -270,27 +270,32 @@ static inline char *sqlite3_text_strdupz_empty(sqlite3_stmt *res, int iCol) {
270 // Store a new alert transition along with the version after sending to the cloud
271 // - Update an existing alert with the updated version, status, transition and date submitted
272 //
273 -static void sql_update_alert_version(int64_t health_log_id, int64_t unique_id, RRDCALC_STATUS status, uint64_t version)
273 +static void sql_update_alert_version(
274 + int64_t health_log_id,
275 + int64_t unique_id,
276 + RRDCALC_STATUS status,
277 + uint64_t version,
278 + sqlite3_stmt **res)
279 {
275 - sqlite3_stmt *res = NULL;
276 -
277 - if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_ALERT_VERSION, &res))
278 - return;
280 + if (!*res) {
281 + if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_ALERT_VERSION, res))
282 + return;
283 + }
284
285 int param = 0;
281 - SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, health_log_id));
282 - SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, unique_id));
283 - SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, status));
284 - SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, version));
286 + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(*res, ++param, health_log_id));
287 + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(*res, ++param, unique_id));
288 + SQLITE_BIND_FAIL(done, sqlite3_bind_int(*res, ++param, status));
289 + SQLITE_BIND_FAIL(done, sqlite3_bind_int64(*res, ++param, version));
290
291 param = 0;
287 - int rc = sqlite3_step_monitored(res);
292 + int rc = sqlite3_step_monitored(*res);
293 if (rc != SQLITE_DONE)
294 error_report("Failed to execute sql_update_alert_version");
295
296 done:
292 - REPORT_BIND_FAIL(res, param);
293 - SQLITE_FINALIZE(res);
297 + REPORT_BIND_FAIL(*res, param);
298 + SQLITE_RESET(*res);
299 }
300
301 #define SQL_SELECT_ALERT_TO_DUMMY \
@@ -318,6 +323,7 @@ static void commit_alert_events(RRDHOST *host)
323 int64_t first_sequence_id = 0;
324 int64_t last_sequence_id = 0;
325
326 + sqlite3_stmt *res_version = NULL;
327 param = 0;
328 while (sqlite3_step_monitored(res) == SQLITE_ROW) {
329
@@ -330,7 +336,9 @@ static void commit_alert_events(RRDHOST *host)
336 RRDCALC_STATUS status = (RRDCALC_STATUS)sqlite3_column_int(res, 3);
337 int64_t health_log_id = sqlite3_column_int64(res, 4);
338
333 - sql_update_alert_version(health_log_id, unique_id, status, version);
339 + // Prepare the statement on the first time (res_version) then reuse it
340 + // finalize when we are done
341 + sql_update_alert_version(health_log_id, unique_id, status, version, &res_version);
342 }
343
344 if (first_sequence_id)
@@ -469,21 +477,20 @@ void health_alarm_log_populate(
477 " AND hl.host_id = @host_id AND aq.host_id = hl.host_id AND hl.health_log_id = hld.health_log_id" \
478 " ORDER BY aq.sequence_id ASC LIMIT "ACLK_MAX_ALERT_UPDATES
479
472 -static void aclk_push_alert_event(RRDHOST *host __maybe_unused)
473 -
480 +static void aclk_push_alert_event(RRDHOST *host, sqlite3_stmt **res, sqlite3_stmt **res_version)
481 {
482 CLAIM_ID claim_id = claim_id_get();
483
484 if (!claim_id_is_set(claim_id) || UUIDiszero(host->node_id))
485 return;
486
480 - sqlite3_stmt *res = NULL;
481 -
482 - if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_ALERT_TO_PUSH, &res))
483 - return;
487 + if (!*res) {
488 + if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_ALERT_TO_PUSH, res))
489 + return;
490 + }
491
492 int param = 0;
486 - SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
493 + SQLITE_BIND_FAIL(done, sqlite3_bind_blob(*res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
494
495 char node_id_str[UUID_STR_LEN];
496 uuid_unparse_lower(host->node_id.uuid, node_id_str);
@@ -498,8 +505,8 @@ static void aclk_push_alert_event(RRDHOST *host __maybe_unused)
505 param = 0;
506 RRDCALC_STATUS status;
507 struct aclk_sync_cfg_t *wc = host->aclk_config;
501 - while (sqlite3_step_monitored(res) == SQLITE_ROW) {
502 - health_alarm_log_populate(&alarm_log, res, host, &status);
508 + while (sqlite3_step_monitored(*res) == SQLITE_ROW) {
509 + health_alarm_log_populate(&alarm_log, *res, host, &status);
510 aclk_send_alarm_log_entry(&alarm_log);
511 wc->alert_count++;
512
@@ -507,7 +514,9 @@ static void aclk_push_alert_event(RRDHOST *host __maybe_unused)
514 if (first_id == 0)
515 first_id = last_id;
516
510 - sql_update_alert_version(alarm_log.health_log_id, alarm_log.unique_id, status, alarm_log.version);
517 + // The statement to set the version will be compiled once and reset when done
518 + // out caller will finalize the statement to release resources
519 + sql_update_alert_version(alarm_log.health_log_id, alarm_log.unique_id, status, alarm_log.version, res_version);
520
521 destroy_alarm_log_entry(&alarm_log);
522 }
@@ -528,8 +537,8 @@ static void aclk_push_alert_event(RRDHOST *host __maybe_unused)
537 }
538
539 done:
531 - REPORT_BIND_FAIL(res, param);
532 - SQLITE_FINALIZE(res);
540 + REPORT_BIND_FAIL(*res, param);
541 + SQLITE_RESET(*res);
542 }
543
544 #define SQL_DELETE_PROCESSED_ROWS "DELETE FROM alert_queue WHERE host_id = @host_id AND rowid = @row"
@@ -668,6 +677,8 @@ void aclk_push_alert_events_for_all_hosts(void)
677 {
678 RRDHOST *host;
679
680 + sqlite3_stmt *res = NULL; // used to scan pending alerts to send
681 + sqlite3_stmt *res_version = NULL; // used to update the alert version
682 dfe_start_reentrant(rrdhost_root_index, host) {
683 if (!rrdhost_flag_check(host, RRDHOST_FLAG_ACLK_STREAM_ALERTS) ||
684 rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD))
@@ -694,9 +705,11 @@ void aclk_push_alert_events_for_all_hosts(void)
705 wc->send_snapshot = 0;
706 }
707 else
697 - aclk_push_alert_event(host);
708 + aclk_push_alert_event(host, &res, &res_version);
709 }
710 dfe_done(host);
711 + SQLITE_FINALIZE(res);
712 + SQLITE_FINALIZE(res_version);
713 }
714
715 void aclk_send_alert_configuration(char *config_hash)
src/database/sqlite/sqlite_health.c
+15 -3
@@ -939,10 +939,19 @@ done:
939 int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_STATUS *last_executed_status)
940 {
941 int ret = -1;
942 + static __thread sqlite3_stmt *compiled_res = NULL;
943 sqlite3_stmt *res = NULL;
944
944 - if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, &res))
945 - return ret;
945 + if (is_health_thread) {
946 + if (!compiled_res) {
947 + if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, &compiled_res))
948 + return ret;
949 + }
950 + res = compiled_res;
951 + } else {
952 + if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_HEALTH_LAST_EXECUTED_EVENT, &res))
953 + return ret;
954 + }
955
956 int param = 0;
957 SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
@@ -959,7 +968,10 @@ int sql_health_get_last_executed_event(RRDHOST *host, ALARM_ENTRY *ae, RRDCALC_S
968
969 done:
970 REPORT_BIND_FAIL(res, param);
962 - SQLITE_FINALIZE(res);
971 + if (is_health_thread)
972 + SQLITE_RESET(res);
973 + else
974 + SQLITE_FINALIZE(res);
975 return ret;
976 }
977
src/database/sqlite/sqlite_metadata.c
+2
@@ -89,6 +89,8 @@ const char *database_config[] = {
89 " (host_id BLOB, health_log_id INT, unique_id INT, alarm_id INT, status INT, date_scheduled INT, "
90 " UNIQUE(host_id, health_log_id, alarm_id))",
91
92 + "CREATE INDEX IF NOT EXISTS ind_alert_queue1 ON alert_queue(host_id, date_scheduled)",
93 +
94 "CREATE TABLE IF NOT EXISTS alert_version (health_log_id INTEGER PRIMARY KEY, unique_id INT, status INT, "
95 "version INT, date_submitted INT)",
96