Improve alert transition processing (#19487)
Use prepared statements when processing alerts from the health thread
Stelios Fragkakis committed
Jan 26, 2025 at 18:53 UTC
bb775105ffee2f8a62e7f685e5860963f27c6fd5
3 files changed
+170
-40
src/database/sqlite/sqlite_aclk_alert.c
+93
-19
@@ -5,6 +5,8 @@
5
6
#include "../../aclk/aclk_alarm_api.h"
7
8
+extern __thread bool is_health_thread;
9
+
10
#define SQLITE3_COLUMN_STRDUPZ_OR_NULL(res, param) \
11
({ \
12
int _param = (param); \
@@ -18,10 +20,19 @@
20
21
static inline bool is_event_from_alert_variable_config(int64_t unique_id, nd_uuid_t *host_id)
22
{
23
+ static __thread sqlite3_stmt *compiled_res = NULL;
24
sqlite3_stmt *res = NULL;
25
23
- if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_VARIABLE_ALERT_BY_UNIQUE_ID, &res))
24
- return false;
26
+ if (is_health_thread) {
27
+ if (!compiled_res) {
28
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_SELECT_VARIABLE_ALERT_BY_UNIQUE_ID, &compiled_res))
29
+ return false;
30
+ }
31
+ res = compiled_res;
32
+ } else {
33
+ if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_VARIABLE_ALERT_BY_UNIQUE_ID, &res))
34
+ return false;
35
+ }
36
37
bool ret = false;
38
@@ -34,7 +45,10 @@ static inline bool is_event_from_alert_variable_config(int64_t unique_id, nd_uui
45
46
done:
47
REPORT_BIND_FAIL(res, param);
37
- SQLITE_FINALIZE(res);
48
+ if (is_health_thread)
49
+ SQLITE_RESET(res);
50
+ else
51
+ SQLITE_FINALIZE(res);
52
return ret;
53
}
54
@@ -43,10 +57,19 @@ done:
57
58
static void update_alert_version_transition(int64_t health_log_id, int64_t unique_id)
59
{
60
+ static __thread sqlite3_stmt *compiled_res = NULL;
61
sqlite3_stmt *res = NULL;
62
48
- if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_ALERT_VERSION_TRANSITION, &res))
49
- return;
63
+ if (is_health_thread) {
64
+ if (!compiled_res) {
65
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_UPDATE_ALERT_VERSION_TRANSITION, &compiled_res))
66
+ return;
67
+ }
68
+ res = compiled_res;
69
+ } else {
70
+ if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_ALERT_VERSION_TRANSITION, &res))
71
+ return;
72
+ }
73
74
int param = 0;
75
SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, unique_id));
@@ -59,7 +82,10 @@ static void update_alert_version_transition(int64_t health_log_id, int64_t uniqu
82
83
done:
84
REPORT_BIND_FAIL(res, param);
62
- SQLITE_FINALIZE(res);
85
+ if (is_health_thread)
86
+ SQLITE_RESET(res);
87
+ else
88
+ SQLITE_FINALIZE(res);
89
}
90
91
//decide if some events should be sent or not
@@ -68,10 +94,19 @@ done:
94
95
static bool cloud_status_matches(int64_t health_log_id, RRDCALC_STATUS status)
96
{
97
+ static __thread sqlite3_stmt *compiled_res = NULL;
98
sqlite3_stmt *res = NULL;
99
73
- if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_LAST_ALERT_STATUS, &res))
74
- return true;
100
+ if (is_health_thread) {
101
+ if (!compiled_res) {
102
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_SELECT_LAST_ALERT_STATUS, &compiled_res))
103
+ return true;
104
+ }
105
+ res = compiled_res;
106
+ } else {
107
+ if (!PREPARE_STATEMENT(db_meta, SQL_SELECT_LAST_ALERT_STATUS, &res))
108
+ return true;
109
+ }
110
111
bool send = false;
112
@@ -87,7 +122,10 @@ static bool cloud_status_matches(int64_t health_log_id, RRDCALC_STATUS status)
122
123
done:
124
REPORT_BIND_FAIL(res, param);
90
- SQLITE_FINALIZE(res);
125
+ if (is_health_thread)
126
+ SQLITE_RESET(res);
127
+ else
128
+ SQLITE_FINALIZE(res);
129
return send;
130
}
131
@@ -106,6 +144,7 @@ done:
144
//
145
static int insert_alert_to_submit_queue(RRDHOST *host, int64_t health_log_id, uint32_t unique_id, RRDCALC_STATUS status)
146
{
147
+ static __thread sqlite3_stmt *compiled_res = NULL;
148
sqlite3_stmt *res = NULL;
149
150
if (cloud_status_matches(health_log_id, status)) {
@@ -116,8 +155,16 @@ static int insert_alert_to_submit_queue(RRDHOST *host, int64_t health_log_id, ui
155
if (is_event_from_alert_variable_config(unique_id, &host->host_id.uuid))
156
return 2;
157
119
- if (!PREPARE_STATEMENT(db_meta, SQL_QUEUE_ALERT_TO_CLOUD, &res))
120
- return -1;
158
+ if (is_health_thread) {
159
+ if (!compiled_res) {
160
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_QUEUE_ALERT_TO_CLOUD, &compiled_res))
161
+ return -1;
162
+ }
163
+ res = compiled_res;
164
+ } else {
165
+ if (!PREPARE_STATEMENT(db_meta, SQL_QUEUE_ALERT_TO_CLOUD, &res))
166
+ return -1;
167
+ }
168
169
int param = 0;
170
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
@@ -125,13 +172,16 @@ static int insert_alert_to_submit_queue(RRDHOST *host, int64_t health_log_id, ui
172
SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (int64_t) unique_id));
173
174
param = 0;
128
- int rc = execute_insert(res);
175
+ int rc = sqlite3_step_monitored(res);
176
if (unlikely(rc != SQLITE_DONE))
177
error_report("Failed to insert alert in the submit queue %"PRIu32", rc = %d", unique_id, rc);
178
179
done:
180
REPORT_BIND_FAIL(res, param);
134
- SQLITE_FINALIZE(res);
181
+ if (is_health_thread)
182
+ SQLITE_RESET(res);
183
+ else
184
+ SQLITE_FINALIZE(res);
185
return 0;
186
}
187
@@ -486,10 +536,19 @@ done:
536
537
static void delete_alert_from_pending_queue(RRDHOST *host, int64_t row)
538
{
539
+ static __thread sqlite3_stmt *compiled_res = NULL;
540
sqlite3_stmt *res = NULL;
541
491
- if (!PREPARE_STATEMENT(db_meta, SQL_DELETE_PROCESSED_ROWS, &res))
492
- return;
542
+ if (is_health_thread) {
543
+ if (!compiled_res) {
544
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_DELETE_PROCESSED_ROWS, &compiled_res))
545
+ return;
546
+ }
547
+ res = compiled_res;
548
+ } else {
549
+ if (!PREPARE_STATEMENT(db_meta, SQL_DELETE_PROCESSED_ROWS, &res))
550
+ return;
551
+ }
552
553
int param = 0;
554
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
@@ -502,7 +561,10 @@ static void delete_alert_from_pending_queue(RRDHOST *host, int64_t row)
561
562
done:
563
REPORT_BIND_FAIL(res, param);
505
- SQLITE_FINALIZE(res);
564
+ if (is_health_thread)
565
+ SQLITE_RESET(res);
566
+ else
567
+ SQLITE_FINALIZE(res);
568
}
569
570
#define SQL_REBUILD_HOST_ALERT_VERSION_TABLE \
@@ -554,10 +616,19 @@ done:
616
617
bool process_alert_pending_queue(RRDHOST *host)
618
{
619
+ static __thread sqlite3_stmt *compiled_res = NULL;
620
sqlite3_stmt *res = NULL;
621
559
- if (!PREPARE_STATEMENT(db_meta, SQL_PROCESS_ALERT_PENDING_QUEUE, &res))
560
- return false;
622
+ if (is_health_thread) {
623
+ if (!compiled_res) {
624
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_PROCESS_ALERT_PENDING_QUEUE, &compiled_res))
625
+ return false;
626
+ }
627
+ res = compiled_res;
628
+ } else {
629
+ if (!PREPARE_STATEMENT(db_meta, SQL_PROCESS_ALERT_PENDING_QUEUE, &res))
630
+ return false;
631
+ }
632
633
int param = 0;
634
int added =0, count = 0;
@@ -586,7 +657,10 @@ bool process_alert_pending_queue(RRDHOST *host)
657
nd_log(NDLS_ACCESS, NDLP_NOTICE, "ACLK STA [%s (N/A)]: Processed %d entries, queued %d", rrdhost_hostname(host), count, added);
658
done:
659
REPORT_BIND_FAIL(res, param);
589
- SQLITE_FINALIZE(res);
660
+ if (is_health_thread)
661
+ SQLITE_RESET(res);
662
+ else
663
+ SQLITE_FINALIZE(res);
664
return added > 0;
665
}
666
src/database/sqlite/sqlite_health.c
+75
-21
@@ -6,6 +6,8 @@
6
#include "health/health_internals.h"
7
#include "health/health-alert-entry.h"
8
9
+extern __thread bool is_health_thread;
10
+
11
#define MAX_HEALTH_SQL_SIZE 2048
12
#define SQLITE3_BIND_STRING_OR_NULL(res, param, key) \
13
((key) ? sqlite3_bind_text((res), (param), string2str(key), -1, SQLITE_STATIC) : sqlite3_bind_null((res), (param)))
@@ -27,12 +29,21 @@
29
30
static void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae)
31
{
30
-
32
+ static __thread sqlite3_stmt *compiled_res = NULL;
33
sqlite3_stmt *res = NULL;
32
- int rc;
34
34
- if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_HEALTH_LOG, &res))
35
- return;
35
+ if (is_health_thread) {
36
+ if (!compiled_res) {
37
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_UPDATE_HEALTH_LOG, &compiled_res))
38
+ return;
39
+ }
40
+ res = compiled_res;
41
+ } else {
42
+ if (!PREPARE_STATEMENT(db_meta, SQL_UPDATE_HEALTH_LOG, &res))
43
+ return;
44
+ }
45
+
46
+ int rc;
47
48
int param = 0;
49
SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64) ae->updated_by_id));
@@ -44,14 +55,17 @@ static void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae)
55
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &ae->transition_id, sizeof(ae->transition_id), SQLITE_STATIC));
56
57
param = 0;
47
- rc = execute_insert(res);
58
+ rc = sqlite3_step_monitored(res);
59
if (unlikely(rc != SQLITE_DONE)) {
60
error_report("HEALTH [%s]: Failed to update health log, rc = %d", rrdhost_hostname(host), rc);
61
}
62
63
done:
64
REPORT_BIND_FAIL(res, param);
54
- SQLITE_FINALIZE(res);
65
+ if (is_health_thread)
66
+ SQLITE_RESET(res);
67
+ else
68
+ SQLITE_FINALIZE(res);
69
}
70
71
/* Health related SQL queries
@@ -149,7 +163,20 @@ static void insert_alert_queue(
163
RRDCALC_STATUS old_status,
164
RRDCALC_STATUS new_status)
165
{
166
+ static __thread sqlite3_stmt *compiled_res = NULL;
167
sqlite3_stmt *res = NULL;
168
+
169
+ if (is_health_thread) {
170
+ if (!compiled_res) {
171
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_INSERT_ALERT_PENDING_QUEUE, &compiled_res))
172
+ return;
173
+ }
174
+ res = compiled_res;
175
+ } else {
176
+ if (!PREPARE_STATEMENT(db_meta, SQL_INSERT_ALERT_PENDING_QUEUE, &res))
177
+ return;
178
+ }
179
+
180
int rc;
181
182
if (!host->aclk_config)
@@ -169,14 +196,17 @@ static void insert_alert_queue(
196
SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, submit_delay));
197
198
param = 0;
172
- rc = execute_insert(res);
199
+ rc = sqlite3_step_monitored(res);
200
if (rc != SQLITE_DONE)
201
error_report(
202
"HEALTH [%s]: Failed to execute insert_alert_queue, rc = %d", rrdhost_hostname(host), rc);
203
204
done:
205
REPORT_BIND_FAIL(res, param);
179
- SQLITE_FINALIZE(res);
206
+ if (is_health_thread)
207
+ SQLITE_RESET(res);
208
+ else
209
+ SQLITE_FINALIZE(res);
210
}
211
212
#define SQL_INSERT_HEALTH_LOG_DETAIL \
@@ -189,11 +219,21 @@ done:
219
220
static void sql_health_alarm_log_insert_detail(RRDHOST *host, uint64_t health_log_id, ALARM_ENTRY *ae)
221
{
222
+ static __thread sqlite3_stmt *compiled_res = NULL;
223
sqlite3_stmt *res = NULL;
193
- int rc;
224
195
- if (!PREPARE_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, &res))
196
- return;
225
+ if (is_health_thread) {
226
+ if (!compiled_res) {
227
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, &compiled_res))
228
+ return;
229
+ }
230
+ res = compiled_res;
231
+ } else {
232
+ if (!PREPARE_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG_DETAIL, &res))
233
+ return;
234
+ }
235
+
236
+ int rc;
237
238
int param = 0;
239
SQLITE_BIND_FAIL(done, sqlite3_bind_int64(res, ++param, (sqlite3_int64)health_log_id));
@@ -221,7 +261,7 @@ static void sql_health_alarm_log_insert_detail(RRDHOST *host, uint64_t health_lo
261
SQLITE_BIND_FAIL(done, SQLITE3_BIND_STRING_OR_NULL(res, ++param, ae->summary));
262
263
param = 0;
224
- rc = execute_insert(res);
264
+ rc = sqlite3_step_monitored(res);
265
if (rc == SQLITE_DONE)
266
ae->flags |= HEALTH_ENTRY_FLAG_SAVED;
267
else
@@ -230,7 +270,10 @@ static void sql_health_alarm_log_insert_detail(RRDHOST *host, uint64_t health_lo
270
271
done:
272
REPORT_BIND_FAIL(res, param);
233
- SQLITE_FINALIZE(res);
273
+ if (is_health_thread)
274
+ SQLITE_RESET(res);
275
+ else
276
+ SQLITE_FINALIZE(res);
277
}
278
279
#define SQL_INSERT_HEALTH_LOG \
@@ -243,12 +286,21 @@ done:
286
287
static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae)
288
{
289
+ static __thread sqlite3_stmt *compiled_res = NULL;
290
sqlite3_stmt *res = NULL;
291
int rc;
292
uint64_t health_log_id;
293
250
- if (!PREPARE_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG, &res))
251
- return;
294
+ if (is_health_thread) {
295
+ if (!compiled_res) {
296
+ if (!PREPARE_COMPILED_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG, &compiled_res))
297
+ return;
298
+ }
299
+ res = compiled_res;
300
+ } else {
301
+ if (!PREPARE_STATEMENT(db_meta, SQL_INSERT_HEALTH_LOG, &res))
302
+ return;
303
+ }
304
305
int param = 0;
306
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
@@ -275,7 +327,10 @@ static void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae)
327
328
done:
329
REPORT_BIND_FAIL(res, param);
278
- SQLITE_FINALIZE(res);
330
+ if (is_health_thread)
331
+ SQLITE_RESET(res);
332
+ else
333
+ SQLITE_FINALIZE(res);
334
}
335
336
void sql_health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae)
@@ -340,7 +395,7 @@ bool sql_update_transition_in_health_log(RRDHOST *host, uint32_t alarm_id, nd_uu
395
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, &host->host_id.uuid, sizeof(host->host_id.uuid), SQLITE_STATIC));
396
397
param = 0;
343
- rc = execute_insert(res);
398
+ rc = sqlite3_step_monitored(res);
399
if (unlikely(rc != SQLITE_DONE))
400
error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
401
@@ -370,7 +425,7 @@ bool sql_set_updated_by_in_health_log_detail(uint32_t unique_id, uint32_t max_un
425
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, prev_transition_id, sizeof(*prev_transition_id), SQLITE_STATIC));
426
427
param = 0;
373
- rc = execute_insert(res);
428
+ rc = sqlite3_step_monitored(res);
429
if (unlikely(rc != SQLITE_DONE))
430
error_report("HEALTH [N/A]: Failed to execute SQL_INJECT_REMOVED_UPDATE_DETAIL, rc = %d", rc);
431
@@ -418,7 +473,6 @@ static void sql_inject_removed_status(
473
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, last_transition, sizeof(*last_transition), SQLITE_STATIC));
474
475
param = 0;
421
- //int rc = execute_insert(res);
476
while (sqlite3_step_monitored(res) == SQLITE_ROW) {
477
//update the old entry in health_log_detail
478
sql_set_updated_by_in_health_log_detail(unique_id, max_unique_id, last_transition);
@@ -521,7 +575,7 @@ static void sql_remove_alerts_from_deleted_charts(RRDHOST *host, nd_uuid_t *host
575
SQLITE_BIND_FAIL(done, sqlite3_bind_blob(res, ++param, actual_uuid, sizeof(*actual_uuid), SQLITE_STATIC));
576
577
param = 0;
524
- ret = execute_insert(res);
578
+ ret = sqlite3_step_monitored(res);
579
if (ret != SQLITE_DONE)
580
error_report("Failed to execute command to delete missing charts from health_log");
581
@@ -868,7 +922,7 @@ void sql_alert_store_config(RRD_ALERT_PROTOTYPE *ap)
922
SQLITE_BIND_FAIL(done, sqlite3_bind_int(res, ++param, ap->config.data_source));
923
924
param = 0;
871
- int rc = execute_insert(res);
925
+ int rc = sqlite3_step_monitored(res);
926
if (unlikely(rc != SQLITE_DONE))
927
error_report("Failed to store alert config, rc = %d", rc);
928
src/health/health_event_loop.c
+2
@@ -643,8 +643,10 @@ static void health_event_loop_for_host(RRDHOST *host, bool apply_hibernation_del
643
}
644
}
645
646
+__thread bool is_health_thread = false;
647
static void health_event_loop(void) {
648
649
+ is_health_thread = true;
650
while(service_running(SERVICE_HEALTH)) {
651
if(!stream_control_health_should_be_running()) {
652
worker_is_idle();