diff options
author | Costa Tsaousis <costa@netdata.cloud> | 2024-06-14 17:17:08 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-14 17:17:08 +0300 |
commit | 03b138974eee7a17ece5164842581d233f774a7b (patch) | |
tree | 51b4fab8fe68576b1e08dce1306660ef30ae6fbd /src | |
parent | 2d0cf8ed9a4fbad8dff06630056966bb861c30b4 (diff) |
allow alerts to be created without too many requirements (#17894)
Diffstat (limited to 'src')
-rw-r--r-- | src/health/health_config.c | 4 | ||||
-rw-r--r-- | src/health/health_dyncfg.c | 45 | ||||
-rw-r--r-- | src/health/health_internals.h | 2 | ||||
-rw-r--r-- | src/health/health_prototypes.c | 10 | ||||
-rw-r--r-- | src/health/schema.d/health%3Aalert%3Aprototype.json | 2 |
5 files changed, 37 insertions, 26 deletions
diff --git a/src/health/health_config.c b/src/health/health_config.c index 05ced8bddc..c17f7e21dc 100644 --- a/src/health/health_config.c +++ b/src/health/health_config.c @@ -651,7 +651,7 @@ int health_readfile(const char *filename, void *data __maybe_unused, bool stock_ lookup_data_source_from_rrdr_options(ap); dims_grouping_from_rrdr_options(ap); replace_green_red(ap, green, red); - health_prototype_add(ap); + health_prototype_add(ap, NULL); freez(ap); } @@ -833,7 +833,7 @@ int health_readfile(const char *filename, void *data __maybe_unused, bool stock_ lookup_data_source_from_rrdr_options(ap); dims_grouping_from_rrdr_options(ap); replace_green_red(ap, green, red); - health_prototype_add(ap); + health_prototype_add(ap, NULL); freez(ap); } diff --git a/src/health/health_dyncfg.c b/src/health/health_dyncfg.c index 092fda51c4..4bbda1a92f 100644 --- a/src/health/health_dyncfg.c +++ b/src/health/health_dyncfg.c @@ -96,8 +96,8 @@ static bool parse_config_value_database_lookup(json_object *jobj, const char *pa static bool parse_config_value(json_object *jobj, const char *path, struct rrd_alert_config *config, BUFFER *error, bool strict) { JSONC_PARSE_SUBOBJECT(jobj, path, "database_lookup", config, parse_config_value_database_lookup, error, strict); - JSONC_PARSE_TXT2EXPRESSION_OR_ERROR_AND_RETURN(jobj, path, "calculation", config->calculation, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "units", config->units, error, strict); + JSONC_PARSE_TXT2EXPRESSION_OR_ERROR_AND_RETURN(jobj, path, "calculation", config->calculation, error, false); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "units", config->units, error, false); JSONC_PARSE_INT_OR_ERROR_AND_RETURN(jobj, path, "update_every", config->update_every, error, strict); return true; } @@ -137,15 +137,15 @@ static bool parse_config(json_object *jobj, const char *path, RRD_ALERT_PROTOTYP // JSONC_PARSE_TXT2ENUM_OR_ERROR_AND_RETURN(jobj, path, "source_type", dyncfg_source_type2id, ap->config.source_type, error, strict); // JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "source", ap->config.source, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "summary", ap->config.summary, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "info", ap->config.info, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "type", ap->config.type, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "component", ap->config.component, error, strict); - JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "classification", ap->config.classification, error, strict); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "summary", ap->config.summary, error, false); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "info", ap->config.info, error, false); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "type", ap->config.type, error, false); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "component", ap->config.component, error, false); + JSONC_PARSE_TXT2STRING_OR_ERROR_AND_RETURN(jobj, path, "classification", ap->config.classification, error, false); JSONC_PARSE_SUBOBJECT(jobj, path, "value", &ap->config, parse_config_value, error, strict); - JSONC_PARSE_SUBOBJECT(jobj, path, "conditions", &ap->config, parse_config_conditions, error, strict); - JSONC_PARSE_SUBOBJECT(jobj, path, "action", &ap->config, parse_config_action, error, strict); + JSONC_PARSE_SUBOBJECT(jobj, path, "conditions", &ap->config, parse_config_conditions, error, false); + JSONC_PARSE_SUBOBJECT(jobj, path, "action", &ap->config, parse_config_action, error, false); JSONC_PARSE_SUBOBJECT(jobj, path, "match", &ap->match, parse_match, error, strict); return true; @@ -227,6 +227,11 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload, if(!base->config.name && name) base->config.name = string_strdupz(name); + if(name && *name && string_strcmp(base->config.name, name) != 0) { + string_freez(base->config.name); + base->config.name = string_strdupz(name); + } + int i = 1; for(RRD_ALERT_PROTOTYPE *ap = base; ap; ap = ap->_internal.next, i++) { if(ap->config.name != base->config.name) { @@ -235,7 +240,7 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload, } if(!RRDCALC_HAS_DB_LOOKUP(ap) && !ap->config.calculation && strict) { - buffer_sprintf(error, "the rule No %d has neither database lookup nor calculation", i); + buffer_sprintf(error, "Item %d has neither database lookup nor calculation", i - 1); goto cleanup; } @@ -246,13 +251,6 @@ static RRD_ALERT_PROTOTYPE *health_prototype_payload_parse(const char *payload, base->_internal.enabled = true; } - if(string_strcmp(base->config.name, name) != 0) { - buffer_sprintf(error, - "name parsed ('%s') does not match the name of the alert prototype ('%s')", - string2str(base->config.name), name); - goto cleanup; - } - return base; cleanup: @@ -552,12 +550,15 @@ static int dyncfg_health_prototype_template_action(BUFFER *result, DYNCFG_CMDS c if(!nap) code = dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, buffer_tostring(error)); else { + char *msg = ""; + nap->config.source_type = DYNCFG_SOURCE_TYPE_DYNCFG; - bool added = health_prototype_add(nap); // this swaps ap <-> nap + bool added = health_prototype_add(nap, &msg); // this swaps ap <-> nap if(!added) { health_prototype_free(nap); - return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "required attributes are missing"); + if(!msg || !*msg) msg = "required attributes are missing"; + return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, msg); } else freez(nap); @@ -677,12 +678,14 @@ static int dyncfg_health_prototype_job_action(BUFFER *result, DYNCFG_CMDS cmd, B if(!nap) code = dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, buffer_tostring(error)); else { + char *msg = ""; nap->config.source_type = DYNCFG_SOURCE_TYPE_DYNCFG; - bool added = health_prototype_add(nap); // this swaps ap <-> nap + bool added = health_prototype_add(nap, &msg); // this swaps ap <-> nap if(!added) { health_prototype_free(nap); - return dyncfg_default_response( result, HTTP_RESP_BAD_REQUEST, "required attributes are missing"); + if(!msg || !*msg) msg = "required attributes are missing"; + return dyncfg_default_response( result, HTTP_RESP_BAD_REQUEST, msg); } else freez(nap); diff --git a/src/health/health_internals.h b/src/health/health_internals.h index 251400241f..638a961959 100644 --- a/src/health/health_internals.h +++ b/src/health/health_internals.h @@ -60,7 +60,7 @@ typedef struct rrd_alert_prototype { struct rrd_alert_prototype *prev, *next; } _internal; } RRD_ALERT_PROTOTYPE; -bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap); +bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap, char **msg); void health_prototype_cleanup(RRD_ALERT_PROTOTYPE *ap); void health_prototype_free(RRD_ALERT_PROTOTYPE *ap); diff --git a/src/health/health_prototypes.c b/src/health/health_prototypes.c index 075e9cbe97..c430961156 100644 --- a/src/health/health_prototypes.c +++ b/src/health/health_prototypes.c @@ -395,12 +395,14 @@ void health_prototype_hash_id(RRD_ALERT_PROTOTYPE *ap) { sql_alert_store_config(ap); } -bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) { +bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap, char **msg) { if(!ap->match.is_template) { if(!ap->match.on.chart) { netdata_log_error( "HEALTH: alert '%s' does not define a instance (parameter 'on'). Source: %s", string2str(ap->config.name), string2str(ap->config.source)); + if(msg) + *msg = "missing match 'on' parameter for instance"; return false; } } @@ -409,6 +411,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) { netdata_log_error( "HEALTH: alert '%s' does not define a context (parameter 'on'). Source: %s", string2str(ap->config.name), string2str(ap->config.source)); + if(msg) + *msg = "missing match 'on' parameter for context"; return false; } } @@ -417,6 +421,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) { netdata_log_error( "HEALTH: alert '%s' has no frequency (parameter 'every'). Source: %s", string2str(ap->config.name), string2str(ap->config.source)); + if(msg) + *msg = "missing update frequency"; return false; } @@ -424,6 +430,8 @@ bool health_prototype_add(RRD_ALERT_PROTOTYPE *ap) { netdata_log_error( "HEALTH: alert '%s' is useless (no db lookup, no calculation, no warning and no critical expressions). Source: %s", string2str(ap->config.name), string2str(ap->config.source)); + if(msg) + *msg = "no db lookup, calculation and warning/critical conditions"; return false; } diff --git a/src/health/schema.d/health%3Aalert%3Aprototype.json b/src/health/schema.d/health%3Aalert%3Aprototype.json index 309d052de9..6c5e8c756a 100644 --- a/src/health/schema.d/health%3Aalert%3Aprototype.json +++ b/src/health/schema.d/health%3Aalert%3Aprototype.json @@ -122,7 +122,7 @@ }, "after": { "type": "integer", - "default": -600, + "default": 0, "title": "From", "description": "Relative to 'To'" }, |