diff options
| author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-06-19 01:15:11 +0200 |
|---|---|---|
| committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2025-06-19 01:15:11 +0200 |
| commit | b71cb430cb79e89b5d8bf56990919b6c753cd271 (patch) | |
| tree | 2616418491bf088566225c65f25ea63c97510521 | |
| parent | ca954e4f765ea336e4aef633b38c31a7c6a99d75 (diff) | |
| download | monitoring-plugins-b71cb430cb79e89b5d8bf56990919b6c753cd271.tar.gz | |
Implement flexible state override functions
| -rw-r--r-- | lib/output.c | 83 | ||||
| -rw-r--r-- | lib/output.h | 31 |
2 files changed, 90 insertions, 24 deletions
diff --git a/lib/output.c b/lib/output.c index c408a2f5..b398c2ad 100644 --- a/lib/output.c +++ b/lib/output.c | |||
| @@ -16,7 +16,8 @@ static mp_output_format output_format = MP_FORMAT_DEFAULT; | |||
| 16 | static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; | 16 | static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; |
| 17 | 17 | ||
| 18 | // == Prototypes == | 18 | // == Prototypes == |
| 19 | static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); | 19 | static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, |
| 20 | unsigned int indentation); | ||
| 20 | static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); | 21 | static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); |
| 21 | 22 | ||
| 22 | // == Implementation == | 23 | // == Implementation == |
| @@ -58,7 +59,9 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) { | |||
| 58 | * It sets useful defaults | 59 | * It sets useful defaults |
| 59 | */ | 60 | */ |
| 60 | mp_check mp_check_init(void) { | 61 | mp_check mp_check_init(void) { |
| 61 | mp_check check = {0}; | 62 | mp_check check = { |
| 63 | .evaluation_function = &mp_eval_check_default, | ||
| 64 | }; | ||
| 62 | return check; | 65 | return check; |
| 63 | } | 66 | } |
| 64 | 67 | ||
| @@ -121,7 +124,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata | |||
| 121 | */ | 124 | */ |
| 122 | int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { | 125 | int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { |
| 123 | if (subcheck.output == NULL) { | 126 | if (subcheck.output == NULL) { |
| 124 | die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL"); | 127 | die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, |
| 128 | "Sub check output is NULL"); | ||
| 125 | } | 129 | } |
| 126 | 130 | ||
| 127 | mp_subcheck_list *tmp = NULL; | 131 | mp_subcheck_list *tmp = NULL; |
| @@ -194,18 +198,30 @@ char *get_subcheck_summary(mp_check check) { | |||
| 194 | return result; | 198 | return result; |
| 195 | } | 199 | } |
| 196 | 200 | ||
| 201 | mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) { | ||
| 202 | if (subcheck.evaluation_function == NULL) { | ||
| 203 | return mp_eval_subcheck_default(subcheck); | ||
| 204 | } | ||
| 205 | return subcheck.evaluation_function(subcheck); | ||
| 206 | } | ||
| 207 | |||
| 197 | /* | 208 | /* |
| 198 | * Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states | 209 | * Generate the result state of a mp_subcheck object based on its own state and its subchecks |
| 210 | * states | ||
| 199 | */ | 211 | */ |
| 200 | mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { | 212 | mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) { |
| 201 | if (check.state_set_explicitly) { | 213 | if (subcheck.evaluation_function != NULL) { |
| 202 | return check.state; | 214 | return subcheck.evaluation_function(subcheck); |
| 203 | } | 215 | } |
| 204 | 216 | ||
| 205 | mp_subcheck_list *scl = check.subchecks; | 217 | if (subcheck.state_set_explicitly) { |
| 218 | return subcheck.state; | ||
| 219 | } | ||
| 220 | |||
| 221 | mp_subcheck_list *scl = subcheck.subchecks; | ||
| 206 | 222 | ||
| 207 | if (scl == NULL) { | 223 | if (scl == NULL) { |
| 208 | return check.default_state; | 224 | return subcheck.default_state; |
| 209 | } | 225 | } |
| 210 | 226 | ||
| 211 | mp_state_enum result = STATE_OK; | 227 | mp_state_enum result = STATE_OK; |
| @@ -218,10 +234,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { | |||
| 218 | return result; | 234 | return result; |
| 219 | } | 235 | } |
| 220 | 236 | ||
| 237 | mp_state_enum mp_compute_check_state(const mp_check check) { | ||
| 238 | // just a safety check | ||
| 239 | if (check.evaluation_function == NULL) { | ||
| 240 | return mp_eval_check_default(check); | ||
| 241 | } | ||
| 242 | return check.evaluation_function(check); | ||
| 243 | } | ||
| 244 | |||
| 221 | /* | 245 | /* |
| 222 | * Generate the result state of a mp_check object based on it's own state and it's subchecks states | 246 | * Generate the result state of a mp_check object based on it's own state and it's subchecks states |
| 223 | */ | 247 | */ |
| 224 | mp_state_enum mp_compute_check_state(const mp_check check) { | 248 | mp_state_enum mp_eval_check_default(const mp_check check) { |
| 225 | assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here | 249 | assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here |
| 226 | 250 | ||
| 227 | mp_subcheck_list *scl = check.subchecks; | 251 | mp_subcheck_list *scl = check.subchecks; |
| @@ -253,8 +277,10 @@ char *mp_fmt_output(mp_check check) { | |||
| 253 | mp_subcheck_list *subchecks = check.subchecks; | 277 | mp_subcheck_list *subchecks = check.subchecks; |
| 254 | 278 | ||
| 255 | while (subchecks != NULL) { | 279 | while (subchecks != NULL) { |
| 256 | if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { | 280 | if (level_of_detail == MP_DETAIL_ALL || |
| 257 | asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); | 281 | mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { |
| 282 | asprintf(&result, "%s\n%s", result, | ||
| 283 | fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); | ||
| 258 | } | 284 | } |
| 259 | subchecks = subchecks->next; | 285 | subchecks = subchecks->next; |
| 260 | } | 286 | } |
| @@ -266,7 +292,8 @@ char *mp_fmt_output(mp_check check) { | |||
| 266 | if (pd_string == NULL) { | 292 | if (pd_string == NULL) { |
| 267 | asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); | 293 | asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); |
| 268 | } else { | 294 | } else { |
| 269 | asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck)); | 295 | asprintf(&pd_string, "%s %s", pd_string, |
| 296 | fmt_subcheck_perfdata(subchecks->subcheck)); | ||
| 270 | } | 297 | } |
| 271 | 298 | ||
| 272 | subchecks = subchecks->next; | 299 | subchecks = subchecks->next; |
| @@ -335,19 +362,21 @@ static char *generate_indentation_string(unsigned int indentation) { | |||
| 335 | /* | 362 | /* |
| 336 | * Helper function to generate the output string of mp_subcheck | 363 | * Helper function to generate the output string of mp_subcheck |
| 337 | */ | 364 | */ |
| 338 | static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) { | 365 | static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, |
| 366 | unsigned int indentation) { | ||
| 339 | char *result = NULL; | 367 | char *result = NULL; |
| 340 | mp_subcheck_list *subchecks = NULL; | 368 | mp_subcheck_list *subchecks = NULL; |
| 341 | 369 | ||
| 342 | switch (output_format) { | 370 | switch (output_format) { |
| 343 | case MP_FORMAT_MULTI_LINE: | 371 | case MP_FORMAT_MULTI_LINE: |
| 344 | asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), state_text(mp_compute_subcheck_state(check)), | 372 | asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), |
| 345 | check.output); | 373 | state_text(mp_compute_subcheck_state(check)), check.output); |
| 346 | 374 | ||
| 347 | subchecks = check.subchecks; | 375 | subchecks = check.subchecks; |
| 348 | 376 | ||
| 349 | while (subchecks != NULL) { | 377 | while (subchecks != NULL) { |
| 350 | asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); | 378 | asprintf(&result, "%s\n%s", result, |
| 379 | fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); | ||
| 351 | subchecks = subchecks->next; | 380 | subchecks = subchecks->next; |
| 352 | } | 381 | } |
| 353 | return result; | 382 | return result; |
| @@ -551,3 +580,23 @@ mp_output_format mp_get_format(void) { return output_format; } | |||
| 551 | void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } | 580 | void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } |
| 552 | 581 | ||
| 553 | mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } | 582 | mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } |
| 583 | |||
| 584 | mp_state_enum mp_eval_ok(mp_check overall) { | ||
| 585 | (void)overall; | ||
| 586 | return STATE_OK; | ||
| 587 | } | ||
| 588 | |||
| 589 | mp_state_enum mp_eval_warning(mp_check overall) { | ||
| 590 | (void)overall; | ||
| 591 | return STATE_WARNING; | ||
| 592 | } | ||
| 593 | |||
| 594 | mp_state_enum mp_eval_critical(mp_check overall) { | ||
| 595 | (void)overall; | ||
| 596 | return STATE_CRITICAL; | ||
| 597 | } | ||
| 598 | |||
| 599 | mp_state_enum mp_eval_unknown(mp_check overall) { | ||
| 600 | (void)overall; | ||
| 601 | return STATE_UNKNOWN; | ||
| 602 | } | ||
diff --git a/lib/output.h b/lib/output.h index 3bd91f90..c63c8e3f 100644 --- a/lib/output.h +++ b/lib/output.h | |||
| @@ -7,15 +7,21 @@ | |||
| 7 | /* | 7 | /* |
| 8 | * A partial check result | 8 | * A partial check result |
| 9 | */ | 9 | */ |
| 10 | typedef struct { | 10 | typedef struct mp_subcheck mp_subcheck; |
| 11 | struct mp_subcheck { | ||
| 11 | mp_state_enum state; // OK, Warning, Critical ... set explicitly | 12 | mp_state_enum state; // OK, Warning, Critical ... set explicitly |
| 12 | mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly | 13 | mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly |
| 13 | bool state_set_explicitly; // was the state set explicitly (or should it be derived from subchecks) | 14 | bool state_set_explicitly; // was the state set explicitly (or should it be derived from |
| 15 | // subchecks) | ||
| 14 | 16 | ||
| 15 | char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP connection to..") | 17 | char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP |
| 16 | pd_list *perfdata; // Performance data for this check | 18 | // connection to..") |
| 19 | pd_list *perfdata; // Performance data for this check | ||
| 17 | struct subcheck_list *subchecks; // subchecks deeper in the hierarchy | 20 | struct subcheck_list *subchecks; // subchecks deeper in the hierarchy |
| 18 | } mp_subcheck; | 21 | |
| 22 | // the evaluation_functions computes the state of subcheck | ||
| 23 | mp_state_enum (*evaluation_function)(mp_subcheck); | ||
| 24 | }; | ||
| 19 | 25 | ||
| 20 | /* | 26 | /* |
| 21 | * A list of subchecks, used in subchecks and the main check | 27 | * A list of subchecks, used in subchecks and the main check |
| @@ -57,10 +63,14 @@ mp_output_detail_level mp_get_level_of_detail(void); | |||
| 57 | * The final result is always derived from the children and the "worst" state | 63 | * The final result is always derived from the children and the "worst" state |
| 58 | * in the first layer of subchecks | 64 | * in the first layer of subchecks |
| 59 | */ | 65 | */ |
| 60 | typedef struct { | 66 | typedef struct mp_check mp_check; |
| 67 | struct mp_check { | ||
| 61 | char *summary; // Overall summary, if not set a summary will be automatically generated | 68 | char *summary; // Overall summary, if not set a summary will be automatically generated |
| 62 | mp_subcheck_list *subchecks; | 69 | mp_subcheck_list *subchecks; |
| 63 | } mp_check; | 70 | |
| 71 | // the evaluation_functions computes the state of check | ||
| 72 | mp_state_enum (*evaluation_function)(mp_check); | ||
| 73 | }; | ||
| 64 | 74 | ||
| 65 | mp_check mp_check_init(void); | 75 | mp_check mp_check_init(void); |
| 66 | mp_subcheck mp_subcheck_init(void); | 76 | mp_subcheck mp_subcheck_init(void); |
| @@ -78,6 +88,13 @@ void mp_add_summary(mp_check check[static 1], char *summary); | |||
| 78 | mp_state_enum mp_compute_check_state(mp_check); | 88 | mp_state_enum mp_compute_check_state(mp_check); |
| 79 | mp_state_enum mp_compute_subcheck_state(mp_subcheck); | 89 | mp_state_enum mp_compute_subcheck_state(mp_subcheck); |
| 80 | 90 | ||
| 91 | mp_state_enum mp_eval_ok(mp_check overall); | ||
| 92 | mp_state_enum mp_eval_warning(mp_check overall); | ||
| 93 | mp_state_enum mp_eval_critical(mp_check overall); | ||
| 94 | mp_state_enum mp_eval_unknown(mp_check overall); | ||
| 95 | mp_state_enum mp_eval_check_default(mp_check check); | ||
| 96 | mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck); | ||
| 97 | |||
| 81 | typedef struct { | 98 | typedef struct { |
| 82 | bool parsing_success; | 99 | bool parsing_success; |
| 83 | mp_output_format output_format; | 100 | mp_output_format output_format; |
