Send chart context with alert events to the cloud (#13409)
* add chart context to alert events * migrate health log tables to add chart_context * send it via proto message * add from v3 to v4 * free table * free chart_context
Emmanuel Vasilakis committed
Aug 4, 2022 at 10:18 UTC
2fd2607475479bcb1e5d929f109ffd5537303bb7
12 files changed
+77
-15
aclk/schema-wrappers/alarm_stream.cc
+3
@@ -118,6 +118,7 @@ void destroy_alarm_log_entry(struct alarm_log_entry *entry)
118
freez(entry->old_value_string);
119
120
freez(entry->rendered_info);
121
+ freez(entry->chart_context);
122
}
123
124
static void fill_alarm_log_entry(struct alarm_log_entry *data, AlarmLogEntry *proto)
@@ -166,6 +167,8 @@ static void fill_alarm_log_entry(struct alarm_log_entry *data, AlarmLogEntry *pr
167
proto->set_updated(data->updated);
168
169
proto->set_rendered_info(data->rendered_info);
170
+
171
+ proto->set_chart_context(data->chart_context);
172
}
173
174
char *generate_alarm_log_entry(size_t *len, struct alarm_log_entry *data)
aclk/schema-wrappers/alarm_stream.h
+2
@@ -97,6 +97,8 @@ struct alarm_log_entry {
97
98
// rendered_info
99
char *rendered_info;
100
+
101
+ char *chart_context;
102
};
103
104
struct send_alarm_snapshot {
database/rrd.h
+1
@@ -694,6 +694,7 @@ struct alarm_entry {
694
695
char *chart;
696
uint32_t hash_chart;
697
+ char *chart_context;
698
699
char *family;
700
database/rrdcalc.c
+2
@@ -92,6 +92,7 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
92
now,
93
rc->name,
94
rc->rrdset->id,
95
+ rc->rrdset->context,
96
rc->rrdset->family,
97
rc->classification,
98
rc->component,
@@ -164,6 +165,7 @@ inline void rrdsetcalc_unlink(RRDCALC *rc) {
165
now,
166
rc->name,
167
rc->rrdset->id,
168
+ rc->rrdset->context,
169
rc->rrdset->family,
170
rc->classification,
171
rc->component,
database/sqlite/sqlite_aclk_alert.c
+5
-1
@@ -261,7 +261,7 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
261
buffer_sprintf(sql, "select aa.sequence_id, hl.unique_id, hl.alarm_id, hl.config_hash_id, hl.updated_by_id, hl.when_key, \
262
hl.duration, hl.non_clear_duration, hl.flags, hl.exec_run_timestamp, hl.delay_up_to_timestamp, hl.name, \
263
hl.chart, hl.family, hl.exec, hl.recipient, hl.source, hl.units, hl.info, hl.exec_code, hl.new_status, \
264
- hl.old_status, hl.delay, hl.new_value, hl.old_value, hl.last_repeat \
264
+ hl.old_status, hl.delay, hl.new_value, hl.old_value, hl.last_repeat, hl.chart_context \
265
from health_log_%s hl, aclk_alert_%s aa \
266
where hl.unique_id = aa.alert_unique_id and aa.date_submitted is null \
267
order by aa.sequence_id asc limit %d;", wc->uuid_str, wc->uuid_str, limit);
@@ -344,6 +344,10 @@ void aclk_push_alert_event(struct aclk_database_worker_config *wc, struct aclk_d
344
strdupz((char *)"") :
345
strdupz((char *)sqlite3_column_text(res, 18));
346
347
+ alarm_log.chart_context = sqlite3_column_type(res, 26) == SQLITE_NULL ?
348
+ strdupz((char *)"") :
349
+ strdupz((char *)sqlite3_column_text(res, 26));
350
+
351
aclk_send_alarm_log_entry(&alarm_log);
352
353
if (first_sequence_id == 0)
database/sqlite/sqlite_db_migration.c
+32
-1
@@ -84,6 +84,37 @@ static int do_migration_v2_v3(sqlite3 *database, const char *name)
84
return 0;
85
}
86
87
+static int do_migration_v3_v4(sqlite3 *database, const char *name)
88
+{
89
+ UNUSED(name);
90
+ info("Running database migration %s", name);
91
+
92
+ char sql[256];
93
+
94
+ int rc;
95
+ sqlite3_stmt *res = NULL;
96
+ snprintfz(sql, 255, "SELECT name FROM sqlite_schema WHERE type ='table' AND name LIKE 'health_log_%%';");
97
+ rc = sqlite3_prepare_v2(database, sql, -1, &res, 0);
98
+ if (rc != SQLITE_OK) {
99
+ error_report("Failed to prepare statement to alter health_log tables");
100
+ return 1;
101
+ }
102
+
103
+ while (sqlite3_step(res) == SQLITE_ROW) {
104
+ char *table = strdupz((char *) sqlite3_column_text(res, 0));
105
+ if (!column_exists_in_table(table, "chart_context")) {
106
+ snprintfz(sql, 255, "ALTER TABLE %s ADD chart_context text", table);
107
+ sqlite3_exec(database, sql, 0, 0, NULL);
108
+ }
109
+ freez(table);
110
+ }
111
+
112
+ rc = sqlite3_finalize(res);
113
+ if (unlikely(rc != SQLITE_OK))
114
+ error_report("Failed to finalize statement when altering health_log tables, rc = %d", rc);
115
+
116
+ return 0;
117
+}
118
119
static int do_migration_noop(sqlite3 *database, const char *name)
120
{
@@ -131,13 +162,13 @@ DATABASE_FUNC_MIGRATION_LIST migration_action[] = {
162
{.name = "v0 to v1", .func = do_migration_noop},
163
{.name = "v1 to v2", .func = do_migration_v1_v2},
164
{.name = "v2 to v3", .func = do_migration_v2_v3},
165
+ {.name = "v3 to v4", .func = do_migration_v3_v4},
166
// the terminator of this array
167
{.name = NULL, .func = NULL}
168
};
169
170
DATABASE_FUNC_MIGRATION_LIST context_migration_action[] = {
171
{.name = "v0 to v1", .func = do_migration_noop},
140
-
172
// the terminator of this array
173
{.name = NULL, .func = NULL}
174
};
database/sqlite/sqlite_functions.c
+1
-1
@@ -3,7 +3,7 @@
3
#include "sqlite_functions.h"
4
#include "sqlite_db_migration.h"
5
6
-#define DB_METADATA_VERSION 3
6
+#define DB_METADATA_VERSION 4
7
8
const char *database_config[] = {
9
"CREATE TABLE IF NOT EXISTS host(host_id BLOB PRIMARY KEY, hostname TEXT NOT NULL, "
database/sqlite/sqlite_health.c
+16
-5
@@ -8,7 +8,7 @@
8
/* Health related SQL queries
9
Creates a health log table in sqlite, one per host guid
10
*/
11
-#define SQL_CREATE_HEALTH_LOG_TABLE(guid) "CREATE TABLE IF NOT EXISTS health_log_%s(hostname text, unique_id int, alarm_id int, alarm_event_id int, config_hash_id blob, updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, flags int, exec_run_timestamp int, delay_up_to_timestamp int, name text, chart text, family text, exec text, recipient text, source text, units text, info text, exec_code int, new_status real, old_status real, delay int, new_value double, old_value double, last_repeat int, class text, component text, type text);", guid
11
+#define SQL_CREATE_HEALTH_LOG_TABLE(guid) "CREATE TABLE IF NOT EXISTS health_log_%s(hostname text, unique_id int, alarm_id int, alarm_event_id int, config_hash_id blob, updated_by_id int, updates_id int, when_key int, duration int, non_clear_duration int, flags int, exec_run_timestamp int, delay_up_to_timestamp int, name text, chart text, family text, exec text, recipient text, source text, units text, info text, exec_code int, new_status real, old_status real, delay int, new_value double, old_value double, last_repeat int, class text, component text, type text, chart_context text);", guid
12
int sql_create_health_log_table(RRDHOST *host) {
13
int rc;
14
char *err_msg = NULL, command[MAX_HEALTH_SQL_SIZE + 1];
@@ -113,7 +113,7 @@ void sql_health_alarm_log_update(RRDHOST *host, ALARM_ENTRY *ae) {
113
"config_hash_id, updated_by_id, updates_id, when_key, duration, non_clear_duration, flags, " \
114
"exec_run_timestamp, delay_up_to_timestamp, name, chart, family, exec, recipient, source, " \
115
"units, info, exec_code, new_status, old_status, delay, new_value, old_value, last_repeat, " \
116
- "class, component, type) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);", guid
116
+ "class, component, type, chart_context) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);", guid
117
118
void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
119
sqlite3_stmt *res = NULL;
@@ -323,6 +323,12 @@ void sql_health_alarm_log_insert(RRDHOST *host, ALARM_ENTRY *ae) {
323
goto failed;
324
}
325
326
+ rc = sqlite3_bind_text(res, 32, ae->chart_context, -1, SQLITE_STATIC);
327
+ if (unlikely(rc != SQLITE_OK)) {
328
+ error_report("Failed to bind chart_context parameter for SQL_INSERT_HEALTH_LOG");
329
+ goto failed;
330
+ }
331
+
332
rc = execute_insert(res);
333
if (unlikely(rc != SQLITE_DONE)) {
334
error_report("HEALTH [%s]: Failed to execute SQL_INSERT_HEALTH_LOG, rc = %d", host->hostname, rc);
@@ -434,9 +440,9 @@ void sql_health_alarm_log_count(RRDHOST *host) {
440
}
441
442
#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, " \
437
-"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) " \
443
+"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, chart_context) " \
444
"select hostname, ?1, ?2, ?3, config_hash_id, 0, ?4, unixepoch(), 0, 0, flags, exec_run_timestamp, " \
439
-"unixepoch(), name, chart, family, exec, recipient, source, units, info, exec_code, -2, new_status, delay, NULL, new_value, 0, class, component, type " \
445
+"unixepoch(), name, chart, family, exec, recipient, source, units, info, exec_code, -2, new_status, delay, NULL, new_value, 0, class, component, type, chart_context " \
446
"from health_log_%s where unique_id = ?5", guid, guid2
447
#define SQL_INJECT_REMOVED_UPDATE(guid) "update health_log_%s set flags = flags | ?1, updated_by_id = ?2 where unique_id = ?3; ", guid
448
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)
@@ -598,7 +604,7 @@ void sql_check_removed_alerts_state(char *uuid_str)
604
/* Health related SQL queries
605
Load from the health log table
606
*/
601
-#define SQL_LOAD_HEALTH_LOG(guid,limit) "SELECT 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 FROM (SELECT 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 FROM health_log_%s order by unique_id desc limit %u) order by unique_id asc;", guid, limit
607
+#define SQL_LOAD_HEALTH_LOG(guid,limit) "SELECT 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, chart_context FROM (SELECT 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, chart_context FROM health_log_%s order by unique_id desc limit %u) order by unique_id asc;", guid, limit
608
void sql_health_alarm_log_load(RRDHOST *host) {
609
sqlite3_stmt *res = NULL;
610
int rc;
@@ -771,6 +777,11 @@ void sql_health_alarm_log_load(RRDHOST *host) {
777
else
778
ae->type = NULL;
779
780
+ if (sqlite3_column_type(res, 31) != SQLITE_NULL)
781
+ ae->chart_context = strdupz((char *) sqlite3_column_text(res, 31));
782
+ else
783
+ ae->chart_context = NULL;
784
+
785
char value_string[100 + 1];
786
freez(ae->old_value_string);
787
freez(ae->new_value_string);
health/health.c
+3
-3
@@ -853,7 +853,7 @@ void *health_main(void *ptr) {
853
worker_is_busy(WORKER_HEALTH_JOB_ALARM_LOG_ENTRY);
854
time_t now = now_realtime_sec();
855
ALARM_ENTRY *ae = health_create_alarm_entry(
856
- host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id,
856
+ host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id, rc->rrdset->context,
857
rc->rrdset->family, rc->classification, rc->component, rc->type, rc->exec, rc->recipient, now - rc->last_status_change,
858
rc->value, NAN, rc->status, RRDCALC_STATUS_REMOVED, rc->source, rc->units, rc->info, 0, 0);
859
if (ae) {
@@ -1113,7 +1113,7 @@ void *health_main(void *ptr) {
1113
1114
1115
ALARM_ENTRY *ae = health_create_alarm_entry(
1116
- host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id,
1116
+ host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id, rc->rrdset->context,
1117
rc->rrdset->family, rc->classification, rc->component, rc->type, rc->exec, rc->recipient, now - rc->last_status_change,
1118
rc->old_value, rc->value, rc->status, status, rc->source, rc->units, rc->info,
1119
rc->delay_last,
@@ -1165,7 +1165,7 @@ void *health_main(void *ptr) {
1165
rc->last_repeat = now;
1166
if (likely(rc->times_repeat < UINT32_MAX)) rc->times_repeat++;
1167
ALARM_ENTRY *ae = health_create_alarm_entry(
1168
- host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id,
1168
+ host, rc->id, rc->next_event_id++, rc->config_hash_id, now, rc->name, rc->rrdset->id, rc->rrdset->context,
1169
rc->rrdset->family, rc->classification, rc->component, rc->type, rc->exec, rc->recipient, now - rc->last_status_change,
1170
rc->old_value, rc->value, rc->old_status, rc->status, rc->source, rc->units, rc->info,
1171
rc->delay_last,
health/health.h
+3
-2
@@ -56,6 +56,7 @@ extern ALARM_ENTRY* health_create_alarm_entry(
56
time_t when,
57
const char *name,
58
const char *chart,
59
+ const char *chart_context,
60
const char *family,
61
const char *classification,
62
const char *component,
@@ -63,8 +64,8 @@ extern ALARM_ENTRY* health_create_alarm_entry(
64
const char *exec,
65
const char *recipient,
66
time_t duration,
66
- NETDATA_DOUBLE old_value,
67
- NETDATA_DOUBLE new_value,
67
+ NETDATA_DOUBLE old_value,
68
+ NETDATA_DOUBLE new_value,
69
RRDCALC_STATUS old_status,
70
RRDCALC_STATUS new_status,
71
const char *source,
health/health_json.c
+2
@@ -29,6 +29,7 @@ void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host)
29
"\t\t\"config_hash_id\": \"%s\",\n"
30
"\t\t\"name\": \"%s\",\n"
31
"\t\t\"chart\": \"%s\",\n"
32
+ "\t\t\"context\": \"%s\",\n"
33
"\t\t\"family\": \"%s\",\n"
34
"\t\t\"class\": \"%s\",\n"
35
"\t\t\"component\": \"%s\",\n"
@@ -65,6 +66,7 @@ void health_alarm_entry2json_nolock(BUFFER *wb, ALARM_ENTRY *ae, RRDHOST *host)
66
, config_hash_id
67
, ae->name
68
, ae->chart
69
+ , ae->chart_context
70
, ae->family
71
, ae->classification?ae->classification:"Unknown"
72
, ae->component?ae->component:"Unknown"
health/health_log.c
+7
-2
@@ -450,6 +450,7 @@ inline ALARM_ENTRY* health_create_alarm_entry(
450
time_t when,
451
const char *name,
452
const char *chart,
453
+ const char *chart_context,
454
const char *family,
455
const char *class,
456
const char *component,
@@ -457,8 +458,8 @@ inline ALARM_ENTRY* health_create_alarm_entry(
458
const char *exec,
459
const char *recipient,
460
time_t duration,
460
- NETDATA_DOUBLE old_value,
461
- NETDATA_DOUBLE new_value,
461
+ NETDATA_DOUBLE old_value,
462
+ NETDATA_DOUBLE new_value,
463
RRDCALC_STATUS old_status,
464
RRDCALC_STATUS new_status,
465
const char *source,
@@ -478,6 +479,9 @@ inline ALARM_ENTRY* health_create_alarm_entry(
479
ae->hash_chart = simple_hash(ae->chart);
480
}
481
482
+ if(chart_context)
483
+ ae->chart_context = strdupz(chart_context);
484
+
485
uuid_copy(ae->config_hash_id, *((uuid_t *) config_hash_id));
486
487
if(family)
@@ -583,6 +587,7 @@ inline void health_alarm_log(
587
inline void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae) {
588
freez(ae->name);
589
freez(ae->chart);
590
+ freez(ae->chart_context);
591
freez(ae->family);
592
freez(ae->classification);
593
freez(ae->component);