Fixed duplicate alarm ids in health-log.db (#9428)
Fixed duplicate alarm ids in health-log.db
Stelios Fragkakis committed
Jun 29, 2020 at 22:12 UTC
adc37259c2b158232e8faf0c9806df1546558044
3 files changed
+53
-31
database/rrdcalc.c
+3
@@ -252,6 +252,9 @@ inline uint32_t rrdcalc_get_unique_id(RRDHOST *host, const char *chart, const ch
252
}
253
}
254
255
+ if (unlikely(!host->health_log.next_alarm_id))
256
+ host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
257
+
258
return host->health_log.next_alarm_id++;
259
}
260
database/rrdhost.c
+30
-30
@@ -199,8 +199,8 @@ RRDHOST *rrdhost_create(const char *hostname,
199
host->health_log.next_log_id = 1;
200
host->health_log.next_alarm_id = 1;
201
host->health_log.max = 1000;
202
- host->health_log.next_log_id =
203
- host->health_log.next_alarm_id = (uint32_t)now_realtime_sec();
202
+ host->health_log.next_log_id = (uint32_t)now_realtime_sec();
203
+ host->health_log.next_alarm_id = 0;
204
205
long n = config_get_number(CONFIG_SECTION_HEALTH, "in memory max health log entries", host->health_log.max);
206
if(n < 10) {
@@ -243,6 +243,34 @@ RRDHOST *rrdhost_create(const char *hostname,
243
}
244
245
}
246
+
247
+ if(host->health_enabled) {
248
+ snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
249
+ int r = mkdir(filename, 0775);
250
+ if(r != 0 && errno != EEXIST)
251
+ error("Host '%s': cannot create directory '%s'", host->hostname, filename);
252
+ }
253
+
254
+ snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
255
+ host->health_log_filename = strdupz(filename);
256
+
257
+ snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_primary_plugins_dir);
258
+ host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
259
+ host->health_default_recipient = strdupz("root");
260
+
261
+
262
+ // ------------------------------------------------------------------------
263
+ // load health configuration
264
+
265
+ if(host->health_enabled) {
266
+ rrdhost_wrlock(host);
267
+ health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL);
268
+ rrdhost_unlock(host);
269
+
270
+ health_alarm_log_load(host);
271
+ health_alarm_log_open(host);
272
+ }
273
+
274
if (host->rrd_memory_mode == RRD_MEMORY_MODE_DBENGINE) {
275
#ifdef ENABLE_DBENGINE
276
if (unlikely(-1 == uuid_parse(host->machine_guid, host->host_uuid))) {
@@ -273,34 +301,6 @@ RRDHOST *rrdhost_create(const char *hostname,
301
#endif
302
}
303
276
- if(host->health_enabled) {
277
- snprintfz(filename, FILENAME_MAX, "%s/health", host->varlib_dir);
278
- int r = mkdir(filename, 0775);
279
- if(r != 0 && errno != EEXIST)
280
- error("Host '%s': cannot create directory '%s'", host->hostname, filename);
281
- }
282
-
283
- snprintfz(filename, FILENAME_MAX, "%s/health/health-log.db", host->varlib_dir);
284
- host->health_log_filename = strdupz(filename);
285
-
286
- snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_primary_plugins_dir);
287
- host->health_default_exec = strdupz(config_get(CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
288
- host->health_default_recipient = strdupz("root");
289
-
290
-
291
- // ------------------------------------------------------------------------
292
- // load health configuration
293
-
294
- if(host->health_enabled) {
295
- rrdhost_wrlock(host);
296
- health_readdir(host, health_user_config_dir(), health_stock_config_dir(), NULL);
297
- rrdhost_unlock(host);
298
-
299
- health_alarm_log_load(host);
300
- health_alarm_log_open(host);
301
- }
302
-
303
-
304
// ------------------------------------------------------------------------
305
// link it and add it to the index
306
health/health_log.c
+20
-1
@@ -158,6 +158,22 @@ inline void health_alarm_log_save(RRDHOST *host, ALARM_ENTRY *ae) {
158
#endif
159
}
160
161
+uint32_t is_valid_alarm_id(RRDHOST *host, const char *chart, const char *name, uint32_t alarm_id)
162
+{
163
+ uint32_t hash_chart = simple_hash(chart);
164
+ uint32_t hash_name = simple_hash(name);
165
+
166
+ ALARM_ENTRY *ae;
167
+ for(ae = host->health_log.alarms; ae ;ae = ae->next) {
168
+ if (unlikely(
169
+ ae->alarm_id == alarm_id && (!(ae->hash_name == hash_name && ae->hash_chart == hash_chart &&
170
+ !strcmp(name, ae->name) && !strcmp(chart, ae->chart))))) {
171
+ return 0;
172
+ }
173
+ }
174
+ return 1;
175
+}
176
+
177
inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filename) {
178
errno = 0;
179
@@ -286,6 +302,8 @@ inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filena
302
// error("HEALTH [%s]: line %zu of file '%s' provides an alarm for host '%s' but this is named '%s'.", host->hostname, line, filename, pointers[1], host->hostname);
303
304
ae->unique_id = unique_id;
305
+ if (!is_valid_alarm_id(host, pointers[14], pointers[13], alarm_id))
306
+ alarm_id = rrdcalc_get_unique_id(host, pointers[14], pointers[13], NULL);
307
ae->alarm_id = alarm_id;
308
ae->alarm_event_id = (uint32_t)strtoul(pointers[4], NULL, 16);
309
ae->updated_by_id = (uint32_t)strtoul(pointers[5], NULL, 16);
@@ -376,7 +394,8 @@ inline ssize_t health_alarm_log_read(RRDHOST *host, FILE *fp, const char *filena
394
if(!host->health_max_alarm_id) host->health_max_alarm_id = (uint32_t)now_realtime_sec();
395
396
host->health_log.next_log_id = host->health_max_unique_id + 1;
379
- host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
397
+ if (unlikely(!host->health_log.next_alarm_id || host->health_log.next_alarm_id <= host->health_max_alarm_id))
398
+ host->health_log.next_alarm_id = host->health_max_alarm_id + 1;
399
400
debug(D_HEALTH, "HEALTH [%s]: loaded file '%s' with %zd new alarm entries, updated %zd alarms, errors %zd entries, duplicate %zd", host->hostname, filename, loaded, updated, errored, duplicate);
401
return loaded;