Fetch summarily recursively from failed subchecks

This commit is contained in:
Lorenz Kästle 2026-04-22 13:47:00 +02:00
parent eb0f272cf7
commit 9c60c29700

View file

@ -20,8 +20,53 @@ static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck che
unsigned int indentation);
static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
// mp_compare_state compares two state arguments
// if *first* is WORSE than *second*, the result is < 0
// if *first* is equal to *second*, the result is 0
// if *first* is BETTER (less bad) the result is > 0
static int mp_compare_state(mp_state_enum first, mp_state_enum second);
// == Implementation ==
// get_subcheck_failed_output retrieves the output of the
// worst and first leave node in a subcheck tree
// or NULL if no such message exists
// the return string is a copy of the original
static char *get_subcheck_failed_output(const mp_subcheck tree) {
if (tree.subchecks == NULL) {
// this is a leave node
if (mp_compute_subcheck_state(tree) == STATE_OK) {
// ALL OK, nothing to return
return NULL;
}
char *result = strdup(tree.output);
return result;
}
// not a leave node, go through tree
mp_subcheck_list *subcheck = tree.subchecks;
mp_subcheck *worst_first_node = NULL;
mp_state_enum worst_state = STATE_OK;
while (subcheck != NULL) {
mp_state_enum current = mp_compute_subcheck_state(subcheck->subcheck);
if (mp_compare_state(current, worst_state) < 0) {
worst_first_node = &subcheck->subcheck;
}
subcheck = subcheck->next;
}
if (worst_first_node == NULL) {
// we did not find a failed subcheck, return the output
// of the current node
char *result = strdup(tree.output);
return result;
}
return get_subcheck_failed_output(*worst_first_node);
}
/*
* Generate output string for a mp_subcheck object
*/
@ -172,36 +217,36 @@ void mp_set_summary(mp_check check[static 1], char *summary) { check->summary =
char *get_subcheck_summary(mp_check check) {
mp_subcheck_list *subchecks = check.subchecks;
unsigned int ok = 0;
unsigned int warning = 0;
unsigned int critical = 0;
unsigned int unknown = 0;
unsigned int ok_count = 0;
unsigned int warning_count = 0;
unsigned int critical_count = 0;
unsigned int unknown_count = 0;
char *result = NULL;
while (subchecks != NULL) {
switch (mp_compute_subcheck_state(subchecks->subcheck)) {
case STATE_OK:
ok++;
ok_count++;
break;
case STATE_WARNING:
if (critical == 0 && unknown == 0 && warning == 0) {
if (critical_count == 0 && unknown_count == 0 && warning_count == 0) {
// set summary to first warning subcheck output
asprintf(&result, "%s", subchecks->subcheck.output);
asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck));
}
warning++;
warning_count++;
break;
case STATE_CRITICAL:
if (critical == 0) {
if (critical_count == 0) {
// set summary to first critical subcheck output
asprintf(&result, "%s", subchecks->subcheck.output);
asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck));
}
critical++;
critical_count++;
break;
case STATE_UNKNOWN:
if (critical == 0 && unknown == 0) {
if (critical_count == 0 && unknown_count == 0) {
// set summary to first unknown subcheck output
asprintf(&result, "%s", subchecks->subcheck.output);
asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck));
}
unknown++;
unknown_count++;
break;
default:
die(STATE_UNKNOWN, "Unknown state in get_subcheck_summary");
@ -210,20 +255,20 @@ char *get_subcheck_summary(mp_check check) {
}
if (result == NULL) {
if (ok > 0) {
asprintf(&result, "ok=%d", ok);
if (ok_count > 0) {
asprintf(&result, "ok=%d", ok_count);
}
if (warning > 0) {
asprintf(&result, "%swarning=%d", (result == NULL ? "" : ", "), warning);
if (warning_count > 0) {
asprintf(&result, "%swarning=%d", (result == NULL ? "" : ", "), warning_count);
}
if (critical > 0) {
asprintf(&result, "%scritical=%d", (result == NULL ? "" : ", "), critical);
if (critical_count > 0) {
asprintf(&result, "%scritical=%d", (result == NULL ? "" : ", "), critical_count);
}
if (unknown > 0) {
asprintf(&result, "%sunknown=%d", (result == NULL ? "" : ", "), unknown);
if (unknown_count > 0) {
asprintf(&result, "%sunknown=%d", (result == NULL ? "" : ", "), unknown_count);
}
}
@ -688,3 +733,46 @@ mp_state_enum mp_eval_unknown(mp_check overall) {
(void)overall;
return STATE_UNKNOWN;
}
static int mp_compare_state(mp_state_enum first, mp_state_enum second) {
switch (first) {
case STATE_OK:
switch (second) {
case STATE_OK:
return 0;
case STATE_WARNING:
case STATE_UNKNOWN:
case STATE_CRITICAL:
return 1;
}
case STATE_WARNING:
switch (second) {
case STATE_OK:
return -1;
case STATE_WARNING:
return 0;
case STATE_UNKNOWN:
case STATE_CRITICAL:
return 1;
}
case STATE_UNKNOWN:
switch (second) {
case STATE_OK:
case STATE_WARNING:
return -1;
case STATE_UNKNOWN:
return 0;
case STATE_CRITICAL:
return 1;
}
case STATE_CRITICAL:
switch (second) {
case STATE_OK:
case STATE_WARNING:
case STATE_UNKNOWN:
return -1;
case STATE_CRITICAL:
return 0;
}
}
}