diff options
| author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2026-05-30 12:30:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-30 12:30:39 +0200 |
| commit | 44e1913da4d227aaabb7b5ccfae65d879082a5e4 (patch) | |
| tree | a0054efa808083974a2fc1b728104a3b86eadbe8 | |
| parent | e1cde41866912ff4369145842c6e47a93b17d5e2 (diff) | |
| download | monitoring-plugins-44e1913da4d227aaabb7b5ccfae65d879082a5e4.tar.gz | |
* lib: properly name function to set summary
* lib: set first non-ok subcheck as the summary for the overall check
* Fetch summarily recursively from failed subchecks
---------
Co-authored-by: Lorenz Kästle <lorenz.kaestle@netways.de>
| -rw-r--r-- | lib/output.c | 140 | ||||
| -rw-r--r-- | lib/output.h | 2 |
2 files changed, 130 insertions, 12 deletions
diff --git a/lib/output.c b/lib/output.c index 3c04d63d..9bcd02d9 100644 --- a/lib/output.c +++ b/lib/output.c | |||
| @@ -20,8 +20,53 @@ static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck che | |||
| 20 | unsigned int indentation); | 20 | unsigned int indentation); |
| 21 | static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); | 21 | static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); |
| 22 | 22 | ||
| 23 | // mp_compare_state compares two state arguments | ||
| 24 | // if *first* is WORSE than *second*, the result is < 0 | ||
| 25 | // if *first* is equal to *second*, the result is 0 | ||
| 26 | // if *first* is BETTER (less bad) the result is > 0 | ||
| 27 | static int mp_compare_state(mp_state_enum first, mp_state_enum second); | ||
| 28 | |||
| 23 | // == Implementation == | 29 | // == Implementation == |
| 24 | 30 | ||
| 31 | // get_subcheck_failed_output retrieves the output of the | ||
| 32 | // worst and first leave node in a subcheck tree | ||
| 33 | // or NULL if no such message exists | ||
| 34 | // the return string is a copy of the original | ||
| 35 | static char *get_subcheck_failed_output(const mp_subcheck tree) { | ||
| 36 | if (tree.subchecks == NULL) { | ||
| 37 | // this is a leave node | ||
| 38 | if (mp_compute_subcheck_state(tree) == STATE_OK) { | ||
| 39 | // ALL OK, nothing to return | ||
| 40 | return NULL; | ||
| 41 | } | ||
| 42 | |||
| 43 | char *result = strdup(tree.output); | ||
| 44 | return result; | ||
| 45 | } | ||
| 46 | |||
| 47 | // not a leave node, go through tree | ||
| 48 | mp_subcheck_list *subcheck = tree.subchecks; | ||
| 49 | mp_subcheck *worst_first_node = NULL; | ||
| 50 | mp_state_enum worst_state = STATE_OK; | ||
| 51 | while (subcheck != NULL) { | ||
| 52 | mp_state_enum current = mp_compute_subcheck_state(subcheck->subcheck); | ||
| 53 | if (mp_compare_state(current, worst_state) < 0) { | ||
| 54 | worst_first_node = &subcheck->subcheck; | ||
| 55 | } | ||
| 56 | |||
| 57 | subcheck = subcheck->next; | ||
| 58 | } | ||
| 59 | |||
| 60 | if (worst_first_node == NULL) { | ||
| 61 | // we did not find a failed subcheck, return the output | ||
| 62 | // of the current node | ||
| 63 | char *result = strdup(tree.output); | ||
| 64 | return result; | ||
| 65 | } | ||
| 66 | |||
| 67 | return get_subcheck_failed_output(*worst_first_node); | ||
| 68 | } | ||
| 69 | |||
| 25 | /* | 70 | /* |
| 26 | * Generate output string for a mp_subcheck object | 71 | * Generate output string for a mp_subcheck object |
| 27 | */ | 72 | */ |
| @@ -164,7 +209,7 @@ int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subchec | |||
| 164 | * Add a manual summary to a mp_check object, effectively replacing | 209 | * Add a manual summary to a mp_check object, effectively replacing |
| 165 | * the autogenerated one | 210 | * the autogenerated one |
| 166 | */ | 211 | */ |
| 167 | void mp_add_summary(mp_check check[static 1], char *summary) { check->summary = summary; } | 212 | void mp_set_summary(mp_check check[static 1], char *summary) { check->summary = strdup(summary); } |
| 168 | 213 | ||
| 169 | /* | 214 | /* |
| 170 | * Generate the summary string of a mp_check object based on its subchecks | 215 | * Generate the summary string of a mp_check object based on its subchecks |
| @@ -172,31 +217,61 @@ void mp_add_summary(mp_check check[static 1], char *summary) { check->summary = | |||
| 172 | char *get_subcheck_summary(mp_check check) { | 217 | char *get_subcheck_summary(mp_check check) { |
| 173 | mp_subcheck_list *subchecks = check.subchecks; | 218 | mp_subcheck_list *subchecks = check.subchecks; |
| 174 | 219 | ||
| 175 | unsigned int ok = 0; | 220 | unsigned int ok_count = 0; |
| 176 | unsigned int warning = 0; | 221 | unsigned int warning_count = 0; |
| 177 | unsigned int critical = 0; | 222 | unsigned int critical_count = 0; |
| 178 | unsigned int unknown = 0; | 223 | unsigned int unknown_count = 0; |
| 224 | char *result = NULL; | ||
| 179 | while (subchecks != NULL) { | 225 | while (subchecks != NULL) { |
| 180 | switch (mp_compute_subcheck_state(subchecks->subcheck)) { | 226 | switch (mp_compute_subcheck_state(subchecks->subcheck)) { |
| 181 | case STATE_OK: | 227 | case STATE_OK: |
| 182 | ok++; | 228 | ok_count++; |
| 183 | break; | 229 | break; |
| 184 | case STATE_WARNING: | 230 | case STATE_WARNING: |
| 185 | warning++; | 231 | if (critical_count == 0 && unknown_count == 0 && warning_count == 0) { |
| 232 | // set summary to first warning subcheck output | ||
| 233 | asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck)); | ||
| 234 | } | ||
| 235 | warning_count++; | ||
| 186 | break; | 236 | break; |
| 187 | case STATE_CRITICAL: | 237 | case STATE_CRITICAL: |
| 188 | critical++; | 238 | if (critical_count == 0) { |
| 239 | // set summary to first critical subcheck output | ||
| 240 | asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck)); | ||
| 241 | } | ||
| 242 | critical_count++; | ||
| 189 | break; | 243 | break; |
| 190 | case STATE_UNKNOWN: | 244 | case STATE_UNKNOWN: |
| 191 | unknown++; | 245 | if (critical_count == 0 && unknown_count == 0) { |
| 246 | // set summary to first unknown subcheck output | ||
| 247 | asprintf(&result, "%s", get_subcheck_failed_output(subchecks->subcheck)); | ||
| 248 | } | ||
| 249 | unknown_count++; | ||
| 192 | break; | 250 | break; |
| 193 | default: | 251 | default: |
| 194 | die(STATE_UNKNOWN, "Unknown state in get_subcheck_summary"); | 252 | die(STATE_UNKNOWN, "Unknown state in get_subcheck_summary"); |
| 195 | } | 253 | } |
| 196 | subchecks = subchecks->next; | 254 | subchecks = subchecks->next; |
| 197 | } | 255 | } |
| 198 | char *result = NULL; | 256 | |
| 199 | asprintf(&result, "ok=%d, warning=%d, critical=%d, unknown=%d", ok, warning, critical, unknown); | 257 | if (result == NULL) { |
| 258 | if (ok_count > 0) { | ||
| 259 | asprintf(&result, "ok=%d", ok_count); | ||
| 260 | } | ||
| 261 | |||
| 262 | if (warning_count > 0) { | ||
| 263 | asprintf(&result, "%swarning=%d", (result == NULL ? "" : ", "), warning_count); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (critical_count > 0) { | ||
| 267 | asprintf(&result, "%scritical=%d", (result == NULL ? "" : ", "), critical_count); | ||
| 268 | } | ||
| 269 | |||
| 270 | if (unknown_count > 0) { | ||
| 271 | asprintf(&result, "%sunknown=%d", (result == NULL ? "" : ", "), unknown_count); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 200 | return result; | 275 | return result; |
| 201 | } | 276 | } |
| 202 | 277 | ||
| @@ -658,3 +733,46 @@ mp_state_enum mp_eval_unknown(mp_check overall) { | |||
| 658 | (void)overall; | 733 | (void)overall; |
| 659 | return STATE_UNKNOWN; | 734 | return STATE_UNKNOWN; |
| 660 | } | 735 | } |
| 736 | |||
| 737 | static int mp_compare_state(mp_state_enum first, mp_state_enum second) { | ||
| 738 | switch (first) { | ||
| 739 | case STATE_OK: | ||
| 740 | switch (second) { | ||
| 741 | case STATE_OK: | ||
| 742 | return 0; | ||
| 743 | case STATE_WARNING: | ||
| 744 | case STATE_UNKNOWN: | ||
| 745 | case STATE_CRITICAL: | ||
| 746 | return 1; | ||
| 747 | } | ||
| 748 | case STATE_WARNING: | ||
| 749 | switch (second) { | ||
| 750 | case STATE_OK: | ||
| 751 | return -1; | ||
| 752 | case STATE_WARNING: | ||
| 753 | return 0; | ||
| 754 | case STATE_UNKNOWN: | ||
| 755 | case STATE_CRITICAL: | ||
| 756 | return 1; | ||
| 757 | } | ||
| 758 | case STATE_UNKNOWN: | ||
| 759 | switch (second) { | ||
| 760 | case STATE_OK: | ||
| 761 | case STATE_WARNING: | ||
| 762 | return -1; | ||
| 763 | case STATE_UNKNOWN: | ||
| 764 | return 0; | ||
| 765 | case STATE_CRITICAL: | ||
| 766 | return 1; | ||
| 767 | } | ||
| 768 | case STATE_CRITICAL: | ||
| 769 | switch (second) { | ||
| 770 | case STATE_OK: | ||
| 771 | case STATE_WARNING: | ||
| 772 | case STATE_UNKNOWN: | ||
| 773 | return -1; | ||
| 774 | case STATE_CRITICAL: | ||
| 775 | return 0; | ||
| 776 | } | ||
| 777 | } | ||
| 778 | } | ||
diff --git a/lib/output.h b/lib/output.h index f5011268..6ca63cfe 100644 --- a/lib/output.h +++ b/lib/output.h | |||
| @@ -87,7 +87,7 @@ int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck); | |||
| 87 | 87 | ||
| 88 | void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], mp_perfdata); | 88 | void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], mp_perfdata); |
| 89 | 89 | ||
| 90 | void mp_add_summary(mp_check check[static 1], char *summary); | 90 | void mp_set_summary(mp_check check[static 1], char *summary); |
| 91 | 91 | ||
| 92 | mp_state_enum mp_compute_check_state(mp_check); | 92 | mp_state_enum mp_compute_check_state(mp_check); |
| 93 | mp_state_enum mp_compute_subcheck_state(mp_subcheck); | 93 | mp_state_enum mp_compute_subcheck_state(mp_subcheck); |
