From f84f614f219b395810e4ca35d5eb5f5a8d2f1d5b Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:34:20 +0200 Subject: Bugfix in output --- lib/output.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib/output.c') diff --git a/lib/output.c b/lib/output.c index 61fbf832..01e50770 100644 --- a/lib/output.c +++ b/lib/output.c @@ -13,6 +13,7 @@ // == Global variables static mp_output_format output_format = MP_FORMAT_DEFAULT; +static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; // == Prototypes == static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); @@ -202,7 +203,12 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { } mp_subcheck_list *scl = check.subchecks; - mp_state_enum result = check.default_state; + + if (scl == NULL) { + return check.default_state; + } + + mp_state_enum result = STATE_OK; while (scl != NULL) { result = max_state_alt(result, mp_compute_subcheck_state(scl->subcheck)); -- cgit v1.2.3-74-g34f1 From f413ac38e30e606beda4ef7f6bf1db40b49682d3 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sun, 30 Mar 2025 22:34:42 +0200 Subject: Add selectable level of detail for output --- lib/output.c | 8 +++++++- lib/output.h | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'lib/output.c') diff --git a/lib/output.c b/lib/output.c index 01e50770..c408a2f5 100644 --- a/lib/output.c +++ b/lib/output.c @@ -253,7 +253,9 @@ char *mp_fmt_output(mp_check check) { mp_subcheck_list *subchecks = check.subchecks; while (subchecks != NULL) { - asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); + if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { + asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); + } subchecks = subchecks->next; } @@ -545,3 +547,7 @@ parsed_output_format mp_parse_output_format(char *format_string) { void mp_set_format(mp_output_format format) { output_format = format; } mp_output_format mp_get_format(void) { return output_format; } + +void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } + +mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } diff --git a/lib/output.h b/lib/output.h index 2bdfa074..3bd91f90 100644 --- a/lib/output.h +++ b/lib/output.h @@ -38,8 +38,18 @@ typedef enum output_format { /* * Format related functions */ - void mp_set_format(mp_output_format format); - mp_output_format mp_get_format(void); +void mp_set_format(mp_output_format format); +mp_output_format mp_get_format(void); + +// Output detail level + +typedef enum output_detail_level { + MP_DETAIL_ALL, + MP_DETAIL_NON_OK_ONLY, +} mp_output_detail_level; + +void mp_set_level_of_detail(mp_output_detail_level level); +mp_output_detail_level mp_get_level_of_detail(void); /* * The main state object of a plugin. Exists only ONCE per plugin. @@ -48,7 +58,7 @@ typedef enum output_format { * in the first layer of subchecks */ typedef struct { - char *summary; // Overall summary, if not set a summary will be automatically generated + char *summary; // Overall summary, if not set a summary will be automatically generated mp_subcheck_list *subchecks; } mp_check; -- cgit v1.2.3-74-g34f1 From b71cb430cb79e89b5d8bf56990919b6c753cd271 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 19 Jun 2025 01:15:11 +0200 Subject: Implement flexible state override functions --- lib/output.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++------------- lib/output.h | 31 ++++++++++++++++++----- 2 files changed, 90 insertions(+), 24 deletions(-) (limited to 'lib/output.c') 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; static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; // == Prototypes == -static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); +static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, + unsigned int indentation); static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); // == Implementation == @@ -58,7 +59,9 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) { * It sets useful defaults */ mp_check mp_check_init(void) { - mp_check check = {0}; + mp_check check = { + .evaluation_function = &mp_eval_check_default, + }; return check; } @@ -121,7 +124,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata */ int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { if (subcheck.output == NULL) { - die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL"); + die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, + "Sub check output is NULL"); } mp_subcheck_list *tmp = NULL; @@ -194,18 +198,30 @@ char *get_subcheck_summary(mp_check check) { return result; } +mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) { + if (subcheck.evaluation_function == NULL) { + return mp_eval_subcheck_default(subcheck); + } + return subcheck.evaluation_function(subcheck); +} + /* - * Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states + * Generate the result state of a mp_subcheck object based on its own state and its subchecks + * states */ -mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { - if (check.state_set_explicitly) { - return check.state; +mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) { + if (subcheck.evaluation_function != NULL) { + return subcheck.evaluation_function(subcheck); } - mp_subcheck_list *scl = check.subchecks; + if (subcheck.state_set_explicitly) { + return subcheck.state; + } + + mp_subcheck_list *scl = subcheck.subchecks; if (scl == NULL) { - return check.default_state; + return subcheck.default_state; } mp_state_enum result = STATE_OK; @@ -218,10 +234,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { return result; } +mp_state_enum mp_compute_check_state(const mp_check check) { + // just a safety check + if (check.evaluation_function == NULL) { + return mp_eval_check_default(check); + } + return check.evaluation_function(check); +} + /* * Generate the result state of a mp_check object based on it's own state and it's subchecks states */ -mp_state_enum mp_compute_check_state(const mp_check check) { +mp_state_enum mp_eval_check_default(const mp_check check) { assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here mp_subcheck_list *scl = check.subchecks; @@ -253,8 +277,10 @@ char *mp_fmt_output(mp_check check) { mp_subcheck_list *subchecks = check.subchecks; while (subchecks != NULL) { - if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { - asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); + if (level_of_detail == MP_DETAIL_ALL || + mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { + asprintf(&result, "%s\n%s", result, + fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); } subchecks = subchecks->next; } @@ -266,7 +292,8 @@ char *mp_fmt_output(mp_check check) { if (pd_string == NULL) { asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); } else { - asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck)); + asprintf(&pd_string, "%s %s", pd_string, + fmt_subcheck_perfdata(subchecks->subcheck)); } subchecks = subchecks->next; @@ -335,19 +362,21 @@ static char *generate_indentation_string(unsigned int indentation) { /* * Helper function to generate the output string of mp_subcheck */ -static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) { +static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, + unsigned int indentation) { char *result = NULL; mp_subcheck_list *subchecks = NULL; switch (output_format) { case MP_FORMAT_MULTI_LINE: - asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), state_text(mp_compute_subcheck_state(check)), - check.output); + asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), + state_text(mp_compute_subcheck_state(check)), check.output); subchecks = check.subchecks; while (subchecks != NULL) { - asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); + asprintf(&result, "%s\n%s", result, + fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); subchecks = subchecks->next; } return result; @@ -551,3 +580,23 @@ mp_output_format mp_get_format(void) { return output_format; } void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } + +mp_state_enum mp_eval_ok(mp_check overall) { + (void)overall; + return STATE_OK; +} + +mp_state_enum mp_eval_warning(mp_check overall) { + (void)overall; + return STATE_WARNING; +} + +mp_state_enum mp_eval_critical(mp_check overall) { + (void)overall; + return STATE_CRITICAL; +} + +mp_state_enum mp_eval_unknown(mp_check overall) { + (void)overall; + return STATE_UNKNOWN; +} 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 @@ /* * A partial check result */ -typedef struct { +typedef struct mp_subcheck mp_subcheck; +struct mp_subcheck { mp_state_enum state; // OK, Warning, Critical ... set explicitly mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly - bool state_set_explicitly; // was the state set explicitly (or should it be derived from subchecks) + bool state_set_explicitly; // was the state set explicitly (or should it be derived from + // subchecks) - char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP connection to..") - pd_list *perfdata; // Performance data for this check + char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP + // connection to..") + pd_list *perfdata; // Performance data for this check struct subcheck_list *subchecks; // subchecks deeper in the hierarchy -} mp_subcheck; + + // the evaluation_functions computes the state of subcheck + mp_state_enum (*evaluation_function)(mp_subcheck); +}; /* * 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); * The final result is always derived from the children and the "worst" state * in the first layer of subchecks */ -typedef struct { +typedef struct mp_check mp_check; +struct mp_check { char *summary; // Overall summary, if not set a summary will be automatically generated mp_subcheck_list *subchecks; -} mp_check; + + // the evaluation_functions computes the state of check + mp_state_enum (*evaluation_function)(mp_check); +}; mp_check mp_check_init(void); mp_subcheck mp_subcheck_init(void); @@ -78,6 +88,13 @@ void mp_add_summary(mp_check check[static 1], char *summary); mp_state_enum mp_compute_check_state(mp_check); mp_state_enum mp_compute_subcheck_state(mp_subcheck); +mp_state_enum mp_eval_ok(mp_check overall); +mp_state_enum mp_eval_warning(mp_check overall); +mp_state_enum mp_eval_critical(mp_check overall); +mp_state_enum mp_eval_unknown(mp_check overall); +mp_state_enum mp_eval_check_default(mp_check check); +mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck); + typedef struct { bool parsing_success; mp_output_format output_format; -- cgit v1.2.3-74-g34f1