@cryptotaxi247 / netdata-1 / commits / 03b138974

allow alerts to be created without too many requirements (#17894)

Costa Tsaousis committed Jun 14, 2024 at 17:17 UTC 03b138974eee7a17ece5164842581d233f774a7b
5 files changed +37 -26
src/health/health_config.c
+2 -2
@@ -651,7 +651,7 @@ int health_readfile(const char *filename, void *data __maybe_unused, bool stock_
651 lookup_data_source_from_rrdr_options(ap);
652 dims_grouping_from_rrdr_options(ap);
653 replace_green_red(ap, green, red);
654 - health_prototype_add(ap);
654 + health_prototype_add(ap, NULL);
655 freez(ap);
656 }
657
@@ -833,7 +833,7 @@ int health_readfile(const char *filename, void *data __maybe_unused, bool stock_
833 lookup_data_source_from_rrdr_options(ap);
834 dims_grouping_from_rrdr_options(ap);
835 replace_green_red(ap, green, red);
836 - health_prototype_add(ap);
836 + health_prototype_add(ap, NULL);
837 freez(ap);
838 }
839
src/health/health_dyncfg.c
+24 -21
@@ -96,8 +96,8 @@ static bool parse_config_value_database_lookup(json_object *jobj, const char *pa
96
97 static bool parse_config_value(json_object *jobj, const char *path, struct rrd_alert_config *config, BUFFER *error, bool strict) {
98 JSONC_PARSE_SUBOBJECT(jobj, path, "database_lookup", config, parse_config_value_database_lookup, error, strict);
99 - JSONC_PARSE_TXT2EXPRESSION_OR_ERROR_AND_RETURN(jobj, path, "calculation", config->calculation, error, strict);
100 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "units", config->units, error, strict);
99 + JSONC_PARSE_TXT2EXPRESSION_OR_ERROR_AND_RETURN(jobj, path, "calculation", config->calculation, error, false);
100 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "units", config->units, error, false);
101 JSONC_PARSE_INT_OR_ERROR_AND_RETURN(jobj, path, "update_every", config->update_every, error, strict);
102 return true;
103 }
@@ -137,15 +137,15 @@ static bool parse_config(json_object *jobj, const char *path, RRD_ALERT_PROTOTYP
137 // JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "source_type", dyncfg_source_type2id, ap->config.source_type, error, strict);
138 // JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "source", ap->config.source, error, strict);
139
140 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "summary", ap->config.summary, error, strict);
141 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "info", ap->config.info, error, strict);
142 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "type", ap->config.type, error, strict);
143 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "component", ap->config.component, error, strict);
144 - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "classification", ap->config.classification, error, strict);
140 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "summary", ap->config.summary, error, false);
141 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "info", ap->config.info, error, false);
142 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "type", ap->config.type, error, false);
143 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "component", ap->config.component, error, false);
144 + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "classification", ap->config.classification, error, false);
145
146 JSONC_PARSE_SUBOBJECT(jobj, path, "value", &ap->config, parse_config_value, error, strict);
147 - JSONC_PARSE_SUBOBJECT(jobj, path, "conditions", &ap->config, parse_config_conditions, error, strict);
148 - JSONC_PARSE_SUBOBJECT(jobj, path, "action", &ap->config, parse_config_action, error, strict);
147 + JSONC_PARSE_SUBOBJECT(jobj, path, "conditions", &ap->config, parse_config_conditions, error, false);
148 + JSONC_PARSE_SUBOBJECT(jobj, path, "action", &ap->config, parse_config_action, error, false);
149 JSONC_PARSE_SUBOBJECT(jobj, path, "match", &ap->match, parse_match, error, strict);
150
151 return true;
@@ -227,6 +227,11 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload,
227 if(!base->config.name && name)
228 base->config.name = string_strdupz(name);
229
230 + if(name && *name && string_strcmp(base->config.name, name) != 0) {
231 + string_freez(base->config.name);
232 + base->config.name = string_strdupz(name);
233 + }
234 +
235 int i = 1;
236 for(RRD_ALERT_PROTOTYPE *ap = base; ap; ap = ap->_internal.next, i++) {
237 if(ap->config.name != base->config.name) {
@@ -235,7 +240,7 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload,
240 }
241
242 if(!RRDCALC_HAS_DB_LOOKUP(ap) && !ap->config.calculation && strict) {
238 - buffer_sprintf(error, "the rule No %d has neither database lookup nor calculation", i);
243 + buffer_sprintf(error, "Item %d has neither database lookup nor calculation", i - 1);
244 goto cleanup;
245 }
246
@@ -246,13 +251,6 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload,
251 base->_internal.enabled = true;
252 }
253
249 - if(string_strcmp(base->config.name, name) != 0) {
250 - buffer_sprintf(error,
251 - "name parsed ('%s') does not match the name of the alert prototype ('%s')",
252 - string2str(base->config.name), name);
253 - goto cleanup;
254 - }
255 -
254 return base;
255
256 cleanup:
@@ -552,12 +550,15 @@ static int dyncfg_health_prototype_template_action(BUFFER *result, DYNCFG_CMDS c
550 if(!nap)
551 code = dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, buffer_tostring(error));
552 else {
553 + char *msg = "";
554 +
555 nap->config.source_type = DYNCFG_SOURCE_TYPE_DYNCFG;
556 - bool added = health_prototype_add(nap); // this swaps ap <-> nap
556 + bool added = health_prototype_add(nap, &msg); // this swaps ap <-> nap
557
558 if(!added) {
559 health_prototype_free(nap);
560 - return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "required attributes are missing");
560 + if(!msg || !*msg) msg = "required attributes are missing";
561 + return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, msg);
562 }
563 else
564 freez(nap);
@@ -677,12 +678,14 @@ static int dyncfg_health_prototype_job_action(BUFFER *result, DYNCFG_CMDS cmd, B
678 if(!nap)
679 code = dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, buffer_tostring(error));
680 else {
681 + char *msg = "";
682 nap->config.source_type = DYNCFG_SOURCE_TYPE_DYNCFG;
681 - bool added = health_prototype_add(nap); // this swaps ap <-> nap
683 + bool added = health_prototype_add(nap, &msg); // this swaps ap <-> nap
684
685 if(!added) {
686 health_prototype_free(nap);
685 - return dyncfg_default_response( result, HTTP_RESP_BAD_REQUEST, "required attributes are missing");
687 + if(!msg || !*msg) msg = "required attributes are missing";
688 + return dyncfg_default_response( result, HTTP_RESP_BAD_REQUEST, msg);
689 }
690 else
691 freez(nap);
src/health/health_internals.h
+1 -1
@@ -60,7 +60,7 @@ typedef struct rrd_alert_prototype {
60 struct rrd_alert_prototype *prev, *next;
61 } _internal;
62 } RRD_ALERT_PROTOTYPE;
63 -bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap);
63 +bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap, char **msg);
64 void health_prototype_cleanup(RRD_ALERT_PROTOTYPE *ap);
65 void health_prototype_free(RRD_ALERT_PROTOTYPE *ap);
66
src/health/health_prototypes.c
+9 -1
@@ -395,12 +395,14 @@ void health_prototype_hash_id(RRD_ALERT_PROTOTYPE *ap) {
395 sql_alert_store_config(ap);
396 }
397
398 -bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) {
398 +bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap, char **msg) {
399 if(!ap->match.is_template) {
400 if(!ap->match.on.chart) {
401 netdata_log_error(
402 "HEALTH: alert '%s' does not define a instance (parameter 'on'). Source: %s",
403 string2str(ap->config.name), string2str(ap->config.source));
404 + if(msg)
405 + *msg = "missing match 'on' parameter for instance";
406 return false;
407 }
408 }
@@ -409,6 +411,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) {
411 netdata_log_error(
412 "HEALTH: alert '%s' does not define a context (parameter 'on'). Source: %s",
413 string2str(ap->config.name), string2str(ap->config.source));
414 + if(msg)
415 + *msg = "missing match 'on' parameter for context";
416 return false;
417 }
418 }
@@ -417,6 +421,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) {
421 netdata_log_error(
422 "HEALTH: alert '%s' has no frequency (parameter 'every'). Source: %s",
423 string2str(ap->config.name), string2str(ap->config.source));
424 + if(msg)
425 + *msg = "missing update frequency";
426 return false;
427 }
428
@@ -424,6 +430,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) {
430 netdata_log_error(
431 "HEALTH: alert '%s' is useless (no db lookup, no calculation, no warning and no critical expressions). Source: %s",
432 string2str(ap->config.name), string2str(ap->config.source));
433 + if(msg)
434 + *msg = "no db lookup, calculation and warning/critical conditions";
435 return false;
436 }
437
src/health/schema.d/health%3Aalert%3Aprototype.json
+1 -1
@@ -122,7 +122,7 @@
122 },
123 "after": {
124 "type": "integer",
125 - "default": -600,
125 + "default": 0,
126 "title": "From",
127 "description": "Relative to 'To'"
128 },