@cryptotaxi247 / netdata-1 / commits / 2fd260747

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);