From e4a32bfb39ddbe90b95ec4c4dee6ab559d0cec42 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 16 Sep 2025 14:34:17 +0200 Subject: Refactoring check_dbi --- plugins/check_dbi.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 468ded31..2e110ce3 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -76,21 +76,6 @@ static mp_state_enum do_query(dbi_conn /*conn*/, const char ** /*res_val_str*/, mp_dbi_type /*type*/, char * /*np_dbi_query*/); int main(int argc, char **argv) { - int status = STATE_UNKNOWN; - - dbi_driver driver; - dbi_conn conn; - - unsigned int server_version; - - struct timeval start_timeval; - struct timeval end_timeval; - double conn_time = 0.0; - double query_time = 0.0; - - const char *query_val_str = NULL; - double query_val = 0.0; - setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -116,8 +101,7 @@ int main(int argc, char **argv) { printf("Initializing DBI\n"); } - dbi_inst *instance_p = {0}; - + dbi_inst *instance_p = NULL; if (dbi_initialize_r(NULL, instance_p) < 0) { printf( "UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); @@ -133,7 +117,7 @@ int main(int argc, char **argv) { printf("Opening DBI driver '%s'\n", config.dbi_driver); } - driver = dbi_driver_open_r(config.dbi_driver, instance_p); + dbi_driver driver = dbi_driver_open_r(config.dbi_driver, instance_p); if (!driver) { printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", config.dbi_driver); @@ -147,9 +131,10 @@ int main(int argc, char **argv) { } /* make a connection to the database */ + struct timeval start_timeval; gettimeofday(&start_timeval, NULL); - conn = dbi_conn_open(driver); + dbi_conn conn = dbi_conn_open(driver); if (!conn) { printf("UNKNOWN - failed top open connection object.\n"); dbi_conn_close(conn); @@ -210,14 +195,16 @@ int main(int argc, char **argv) { return STATE_UNKNOWN; } + struct timeval end_timeval; gettimeofday(&end_timeval, NULL); - conn_time = timediff(start_timeval, end_timeval); + double conn_time = timediff(start_timeval, end_timeval); - server_version = dbi_conn_get_engine_version(conn); + unsigned int server_version = dbi_conn_get_engine_version(conn); if (verbose) { printf("Connected to server version %u\n", server_version); } + int status = STATE_UNKNOWN; if (config.metric == METRIC_SERVER_VERSION) { status = get_status(server_version, config.dbi_thresholds); } @@ -243,6 +230,10 @@ int main(int argc, char **argv) { } } + + const char *query_val_str = NULL; + double query_val = 0.0; + double query_time = 0.0; if (config.dbi_query) { /* execute query */ status = do_query(conn, &query_val_str, &query_val, &query_time, config.metric, config.type, -- cgit v1.2.3-74-g34f1 From fafaee5813830c5ad963f4855566be9a4a6dfc22 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Sat, 18 Oct 2025 12:25:44 +0200 Subject: Fix some bugs after refactoring --- plugins/check_dbi.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 2e110ce3..786fc1b6 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -29,6 +29,7 @@ * *****************************************************************************/ +#include "states.h" const char *progname = "check_dbi"; const char *copyright = "2011-2024"; const char *email = "devel@monitoring-plugins.org"; @@ -101,13 +102,15 @@ int main(int argc, char **argv) { printf("Initializing DBI\n"); } - dbi_inst *instance_p = NULL; - if (dbi_initialize_r(NULL, instance_p) < 0) { + dbi_inst instance_p = NULL; + if (dbi_initialize_r(NULL, &instance_p) < 0) { printf( "UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); return STATE_UNKNOWN; } + dbi_set_verbosity_r(0, instance_p); + if (instance_p == NULL) { printf("UNKNOWN - failed to initialize DBI.\n"); return STATE_UNKNOWN; @@ -230,7 +233,6 @@ int main(int argc, char **argv) { } } - const char *query_val_str = NULL; double query_val = 0.0; double query_time = 0.0; @@ -251,10 +253,15 @@ int main(int argc, char **argv) { status = STATE_OK; } } else if (config.expect_re_str) { - int err; - + int comp_err; regex_t expect_re = {}; - err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0); + comp_err = regcomp(&expect_re, config.expect_re_str, config.expect_re_cflags); + if (comp_err != 0) { + // TODO error, failed to compile regex + return STATE_UNKNOWN; + } + + int err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0); if (!err) { status = STATE_OK; } else if (err == REG_NOMATCH) { -- cgit v1.2.3-74-g34f1 From ec5fd11c1d1f6117e1bccf4955fa99ba5706c6b4 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:05:55 +0100 Subject: check_dbi: new output functionality --- plugins/check_dbi.c | 430 ++++++++++++++++++++++++++++++++++---------------- plugins/t/check_dbi.t | 10 +- 2 files changed, 295 insertions(+), 145 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 786fc1b6..84e3cb5b 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -29,12 +29,14 @@ * *****************************************************************************/ -#include "states.h" const char *progname = "check_dbi"; const char *copyright = "2011-2024"; const char *email = "devel@monitoring-plugins.org"; #include "../lib/monitoringplug.h" +#include "perfdata.h" +#include "output.h" +#include "states.h" #include "check_dbi.d/config.h" #include "common.h" #include "utils.h" @@ -72,9 +74,15 @@ static double timediff(struct timeval /*start*/, struct timeval /*end*/); static void np_dbi_print_error(dbi_conn /*conn*/, char * /*fmt*/, ...); -static mp_state_enum do_query(dbi_conn /*conn*/, const char ** /*res_val_str*/, - double * /*res_val*/, double * /*res_time*/, mp_dbi_metric /*metric*/, - mp_dbi_type /*type*/, char * /*np_dbi_query*/); +typedef struct { + char *result_string; + double result_number; + double query_duration; + int error_code; + const char *error_string; + mp_state_enum query_processing_status; +} do_query_result; +static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type type, char *query); int main(int argc, char **argv) { setlocale(LC_ALL, ""); @@ -104,16 +112,17 @@ int main(int argc, char **argv) { dbi_inst instance_p = NULL; if (dbi_initialize_r(NULL, &instance_p) < 0) { - printf( - "UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); - return STATE_UNKNOWN; + printf("failed to initialize DBI; possibly you don't have any drivers installed.\n"); + exit(STATE_UNKNOWN); } + // Try to prevent libdbi from printing stuff on stderr + // Who thought that would be a good idea anyway? dbi_set_verbosity_r(0, instance_p); if (instance_p == NULL) { - printf("UNKNOWN - failed to initialize DBI.\n"); - return STATE_UNKNOWN; + printf("failed to initialize DBI.\n"); + exit(STATE_UNKNOWN); } if (verbose) { @@ -122,15 +131,14 @@ int main(int argc, char **argv) { dbi_driver driver = dbi_driver_open_r(config.dbi_driver, instance_p); if (!driver) { - printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", - config.dbi_driver); + printf("failed to open DBI driver '%s'; possibly it's not installed.\n", config.dbi_driver); printf("Known drivers:\n"); for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { printf(" - %s\n", dbi_driver_get_name(driver)); } - return STATE_UNKNOWN; + exit(STATE_UNKNOWN); } /* make a connection to the database */ @@ -141,7 +149,7 @@ int main(int argc, char **argv) { if (!conn) { printf("UNKNOWN - failed top open connection object.\n"); dbi_conn_close(conn); - return STATE_UNKNOWN; + exit(STATE_UNKNOWN); } for (size_t i = 0; i < config.dbi_options_num; ++i) { @@ -155,10 +163,10 @@ int main(int argc, char **argv) { if (!dbi_conn_set_option(conn, config.dbi_options[i].key, config.dbi_options[i].value)) { continue; } - /* else: status != 0 */ - np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", - config.dbi_options[i].key, config.dbi_options[i].value); + // Failing to set option + np_dbi_print_error(conn, "failed to set option '%s' to '%s'", config.dbi_options[i].key, + config.dbi_options[i].value); printf("Known driver options:\n"); for (opt = dbi_conn_get_option_list(conn, NULL); opt; @@ -166,7 +174,7 @@ int main(int argc, char **argv) { printf(" - %s\n", opt); } dbi_conn_close(conn); - return STATE_UNKNOWN; + exit(STATE_UNKNOWN); } if (config.host) { @@ -194,31 +202,60 @@ int main(int argc, char **argv) { } if (dbi_conn_connect(conn) < 0) { - np_dbi_print_error(conn, "UNKNOWN - failed to connect to database"); - return STATE_UNKNOWN; + np_dbi_print_error(conn, "failed to connect to database"); + exit(STATE_UNKNOWN); } struct timeval end_timeval; gettimeofday(&end_timeval, NULL); double conn_time = timediff(start_timeval, end_timeval); + if (verbose) { + printf("Time elapsed: %f\n", conn_time); + } + + mp_check overall = mp_check_init(); + + mp_subcheck sc_connection_time = mp_subcheck_init(); + sc_connection_time = mp_set_subcheck_default_state(sc_connection_time, STATE_OK); + xasprintf(&sc_connection_time.output, "Connection time: %f", conn_time); + + mp_perfdata pd_conn_duration = perfdata_init(); + pd_conn_duration.label = "conntime"; + pd_conn_duration = mp_set_pd_value(pd_conn_duration, conn_time); + + if (config.metric == METRIC_CONN_TIME) { + // TODO set pd thresholds + mp_state_enum status = get_status(conn_time, config.dbi_thresholds); + sc_connection_time = mp_set_subcheck_state(sc_connection_time, status); + if (status != STATE_OK) { + xasprintf(&sc_connection_time.output, "%s violates thresholds", + sc_connection_time.output); + } + } + + mp_add_perfdata_to_subcheck(&sc_connection_time, pd_conn_duration); + mp_add_subcheck_to_check(&overall, sc_connection_time); unsigned int server_version = dbi_conn_get_engine_version(conn); if (verbose) { printf("Connected to server version %u\n", server_version); } - int status = STATE_UNKNOWN; + mp_subcheck sc_server_version = mp_subcheck_init(); + sc_server_version = mp_set_subcheck_default_state(sc_server_version, STATE_OK); + xasprintf(&sc_server_version.output, "Connected to server version %u", server_version); + if (config.metric == METRIC_SERVER_VERSION) { - status = get_status(server_version, config.dbi_thresholds); - } + mp_state_enum status = get_status(server_version, config.dbi_thresholds); - if (verbose) { - printf("Time elapsed: %f\n", conn_time); - } + sc_server_version = mp_set_subcheck_state(sc_server_version, status); - if (config.metric == METRIC_CONN_TIME) { - status = get_status(conn_time, config.dbi_thresholds); - } + if (status != STATE_OK) { + xasprintf(&sc_server_version.output, "%s violates thresholds", + sc_server_version.output); + } + }; + mp_add_subcheck_to_check(&overall, sc_server_version); /* select a database */ if (config.dbi_database) { @@ -226,58 +263,152 @@ int main(int argc, char **argv) { printf("Selecting database '%s'\n", config.dbi_database); } + mp_subcheck sc_select_db = mp_subcheck_init(); + sc_select_db = mp_set_subcheck_default_state(sc_select_db, STATE_OK); + if (dbi_conn_select_db(conn, config.dbi_database)) { np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", config.dbi_database); - return STATE_UNKNOWN; + exit(STATE_UNKNOWN); + } else { + mp_add_subcheck_to_check(&overall, sc_select_db); } } - const char *query_val_str = NULL; - double query_val = 0.0; - double query_time = 0.0; + // Do a query (if configured) if (config.dbi_query) { + mp_subcheck sc_query = mp_subcheck_init(); + sc_query = mp_set_subcheck_default_state(sc_query, STATE_UNKNOWN); + /* execute query */ - status = do_query(conn, &query_val_str, &query_val, &query_time, config.metric, config.type, - config.dbi_query); - if (status != STATE_OK) { - /* do_query prints an error message in this case */ - return status; - } + do_query_result query_res = do_query(conn, config.metric, config.type, config.dbi_query); + + if (query_res.error_code != 0) { + xasprintf(&sc_query.output, "Query failed: %s", query_res.error_string); + sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); + } else if (query_res.query_processing_status != STATE_OK) { + if (query_res.error_string) { + xasprintf(&sc_query.output, "Failed to process query: %s", query_res.error_string); + } else { + xasprintf(&sc_query.output, "Failed to process query"); + } + sc_query = mp_set_subcheck_state(sc_query, query_res.query_processing_status); + } else { + // query succeeded in general + xasprintf(&sc_query.output, "Query '%s' succeeded", config.dbi_query); + + // that's a OK by default now + sc_query = mp_set_subcheck_default_state(sc_query, STATE_OK); + + // query duration first + mp_perfdata pd_query_duration = perfdata_init(); + pd_query_duration = mp_set_pd_value(pd_query_duration, query_res.query_duration); + pd_query_duration.label = "querytime"; + if (config.metric == METRIC_QUERY_TIME) { + // TODO set thresholds + } + + mp_add_perfdata_to_subcheck(&sc_query, pd_query_duration); - if (config.metric == METRIC_QUERY_RESULT) { - if (config.expect) { - if ((!query_val_str) || strcmp(query_val_str, config.expect)) { - status = STATE_CRITICAL; + if (config.metric == METRIC_QUERY_RESULT) { + if (config.expect) { + if ((!query_res.result_string) || + strcmp(query_res.result_string, config.expect)) { + xasprintf(&sc_query.output, "Found string '%s' in query result", + config.expect); + sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); + } else { + xasprintf(&sc_query.output, "Did not find string '%s' in query result", + config.expect); + sc_query = mp_set_subcheck_state(sc_query, STATE_OK); + } + } else if (config.expect_re_str) { + int comp_err; + regex_t expect_re = {}; + comp_err = regcomp(&expect_re, config.expect_re_str, config.expect_re_cflags); + if (comp_err != 0) { + // TODO error, failed to compile regex + // TODO move this to config sanitatisation + printf("Failed to compile regex from string '%s'", config.expect_re_str); + exit(STATE_UNKNOWN); + } + + int err = + regexec(&expect_re, query_res.result_string, 0, NULL, /* flags = */ 0); + if (!err) { + sc_query = mp_set_subcheck_state(sc_query, STATE_OK); + xasprintf(&sc_query.output, "Found regular expression '%s' in query result", + config.expect_re_str); + } else if (err == REG_NOMATCH) { + sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); + xasprintf(&sc_query.output, + "Did not find regular expression '%s' in query result", + config.expect_re_str); + } else { + char errmsg[1024]; + regerror(err, &expect_re, errmsg, sizeof(errmsg)); + xasprintf(&sc_query.output, + "ERROR - failed to execute regular expression: %s\n", errmsg); + sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); + } } else { - status = STATE_OK; - } - } else if (config.expect_re_str) { - int comp_err; - regex_t expect_re = {}; - comp_err = regcomp(&expect_re, config.expect_re_str, config.expect_re_cflags); - if (comp_err != 0) { - // TODO error, failed to compile regex - return STATE_UNKNOWN; + // no string matching + if (isnan(query_res.result_number)) { + // The query result is not a number, but no string checking was configured + // so we expected a number + // this is a CRITICAL + xasprintf(&sc_query.output, "Query '%s' result is not numeric", + config.dbi_query, query_res.result_string); + sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); + + } else { + mp_state_enum query_numerical_result = + get_status(query_res.result_number, config.dbi_thresholds); + sc_query = mp_set_subcheck_state(sc_query, query_numerical_result); + + mp_perfdata pd_query_val = perfdata_init(); + pd_query_val = mp_set_pd_value(pd_query_val, query_res.result_number); + pd_query_val.label = "query"; + mp_add_perfdata_to_subcheck(&sc_query, pd_query_val); + + // TODO set pd thresholds + // if (config.dbi_thresholds->warning) { + // pd_query_val.warn= config.dbi_thresholds->warning + // } else { + // } + + if (query_numerical_result == STATE_OK) { + xasprintf(&sc_query.output, + "Query result '%f' is within given thresholds", + query_res.result_number); + } else { + xasprintf(&sc_query.output, + "Query result '%f' violates the given thresholds", + query_res.result_number); + } + } } - - int err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0); - if (!err) { - status = STATE_OK; - } else if (err == REG_NOMATCH) { - status = STATE_CRITICAL; + } else if (config.metric == METRIC_QUERY_TIME) { + mp_state_enum query_time_status = + get_status(query_res.query_duration, config.dbi_thresholds); + mp_set_subcheck_state(sc_query, query_time_status); + + if (query_time_status == STATE_OK) { + xasprintf(&sc_query.output, "Query duration '%f' is withing given thresholds", + query_res.query_duration); } else { - char errmsg[1024]; - regerror(err, &expect_re, errmsg, sizeof(errmsg)); - printf("ERROR - failed to execute regular expression: %s\n", errmsg); - status = STATE_CRITICAL; + xasprintf(&sc_query.output, "Query duration '%f' violates the given thresholds", + query_res.query_duration); } } else { - status = get_status(query_val, config.dbi_thresholds); + /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error + * which should have been reported and handled (abort) before + * ... unless we expected a string to be returned */ + assert((!isnan(query_res.result_number)) || (config.type == TYPE_STRING)); } - } else if (config.metric == METRIC_QUERY_TIME) { - status = get_status(query_time, config.dbi_thresholds); } + + mp_add_subcheck_to_check(&overall, sc_query); } if (verbose) { @@ -285,63 +416,7 @@ int main(int argc, char **argv) { } dbi_conn_close(conn); - /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error - * which should have been reported and handled (abort) before - * ... unless we expected a string to be returned */ - assert((config.metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || - (config.type == TYPE_STRING)); - - assert((config.type != TYPE_STRING) || (config.expect || config.expect_re_str)); - - printf("%s - connection time: %fs", state_text(status), conn_time); - if (config.dbi_query) { - if (config.type == TYPE_STRING) { - assert(config.expect || config.expect_re_str); - printf(", '%s' returned '%s' in %fs", config.dbi_query, - query_val_str ? query_val_str : "", query_time); - if (status != STATE_OK) { - if (config.expect) { - printf(" (expected '%s')", config.expect); - } else if (config.expect_re_str) { - printf(" (expected regex /%s/%s)", config.expect_re_str, - ((config.expect_re_cflags & REG_ICASE) ? "i" : "")); - } - } - } else if (isnan(query_val)) { - printf(", '%s' query execution time: %fs", config.dbi_query, query_time); - } else { - printf(", '%s' returned %f in %fs", config.dbi_query, query_val, query_time); - } - } - - printf( - " | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, - ((config.metric == METRIC_CONN_TIME) && config.warning_range) ? config.warning_range : "", - ((config.metric == METRIC_CONN_TIME) && config.critical_range) ? config.critical_range : "", - server_version, - ((config.metric == METRIC_SERVER_VERSION) && config.warning_range) ? config.warning_range - : "", - ((config.metric == METRIC_SERVER_VERSION) && config.critical_range) ? config.critical_range - : ""); - if (config.dbi_query) { - if (!isnan(query_val)) { /* this is also true when -e is used */ - printf(" query=%f;%s;%s;;", query_val, - ((config.metric == METRIC_QUERY_RESULT) && config.warning_range) - ? config.warning_range - : "", - ((config.metric == METRIC_QUERY_RESULT) && config.critical_range) - ? config.critical_range - : ""); - } - printf(" querytime=%fs;%s;%s;0;", query_time, - ((config.metric == METRIC_QUERY_TIME) && config.warning_range) ? config.warning_range - : "", - ((config.metric == METRIC_QUERY_TIME) && config.critical_range) - ? config.critical_range - : ""); - } - printf("\n"); - return status; + mp_exit(overall); } /* process command-line arguments */ @@ -349,7 +424,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { int option = 0; static struct option longopts[] = {STD_LONG_OPTS, - {"expect", required_argument, 0, 'e'}, {"regex", required_argument, 0, 'r'}, {"regexi", required_argument, 0, 'R'}, @@ -533,6 +607,10 @@ check_dbi_config_wrapper validate_arguments(check_dbi_config_wrapper config_wrap usage("Options -r/-R require metric QUERY_RESULT"); } + if (config_wrapper.config.type == TYPE_STRING) { + assert(config_wrapper.config.expect || config_wrapper.config.expect_re_str); + } + config_wrapper.errorcode = OK; return config_wrapper; } @@ -783,38 +861,110 @@ mp_state_enum get_query_result(dbi_conn conn, dbi_result res, const char **res_v return STATE_OK; } -mp_state_enum do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time, - mp_dbi_metric metric, mp_dbi_type type, char *np_dbi_query) { - dbi_result res; - - struct timeval timeval_start; - struct timeval timeval_end; - mp_state_enum status = STATE_OK; - - assert(np_dbi_query); +static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type type, + char *query) { + assert(query); if (verbose) { - printf("Executing query '%s'\n", np_dbi_query); + printf("Executing query '%s'\n", query); } + do_query_result result = { + .query_duration = 0, + .result_string = NULL, + .result_number = 0, + .error_code = 0, + .query_processing_status = STATE_UNKNOWN, + }; + + struct timeval timeval_start; gettimeofday(&timeval_start, NULL); - res = dbi_conn_query(conn, np_dbi_query); + dbi_result res = dbi_conn_query(conn, query); if (!res) { - np_dbi_print_error(conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); - return STATE_CRITICAL; + dbi_conn_error(conn, &result.error_string); + result.error_code = 1; + return result; } - status = get_query_result(conn, res, res_val_str, res_val, metric, type); - + struct timeval timeval_end; gettimeofday(&timeval_end, NULL); - *res_time = timediff(timeval_start, timeval_end); + result.query_duration = timediff(timeval_start, timeval_end); if (verbose) { - printf("Time elapsed: %f\n", *res_time); + printf("Query duration: %f\n", result.query_duration); + } + + // Default state is OK, all error will be set explicitely + mp_state_enum query_processing_state = STATE_OK; + { + + if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) { + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + dbi_conn_error(conn, &result.error_string); + query_processing_state = STATE_CRITICAL; + } + } else if (dbi_result_get_numrows(res) < 1) { + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + result.error_string = "no rows returned"; + // printf("WARNING - no rows returned\n"); + query_processing_state = STATE_WARNING; + } + } else if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) { + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + dbi_conn_error(conn, &result.error_string); + // np_dbi_print_error(conn, "CRITICAL - failed to fetch fields"); + query_processing_state = STATE_CRITICAL; + } + } else if (dbi_result_get_numfields(res) < 1) { + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + result.error_string = "no fields returned"; + // printf("WARNING - no fields returned\n"); + query_processing_state = STATE_WARNING; + } + } else if (dbi_result_first_row(res) != 1) { + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + dbi_conn_error(conn, &result.error_string); + // np_dbi_print_error(conn, "CRITICAL - failed to fetch first row"); + query_processing_state = STATE_CRITICAL; + } + } else { + unsigned short field_type = dbi_result_get_field_type_idx(res, 1); + if (field_type != DBI_TYPE_ERROR) { + if (type == TYPE_STRING) { + result.result_string = + strdup(get_field_str(conn, res, field_type, metric, type)); + } else { + result.result_number = get_field(conn, res, &field_type, metric, type); + } + } else { + // Error when retrieving the field, that is OK if the Query result is not of + // interest + if (metric != METRIC_QUERY_RESULT) { + query_processing_state = STATE_OK; + } else { + dbi_conn_error(conn, &result.error_string); + // np_dbi_print_error(conn, "CRITICAL - failed to fetch data"); + query_processing_state = STATE_CRITICAL; + } + } + } } + dbi_result_free(res); + + result.query_processing_status = query_processing_state; - return status; + return result; } double timediff(struct timeval start, struct timeval end) { diff --git a/plugins/t/check_dbi.t b/plugins/t/check_dbi.t index c24b5a8c..75444de4 100644 --- a/plugins/t/check_dbi.t +++ b/plugins/t/check_dbi.t @@ -21,12 +21,12 @@ plan tests => $tests; my $missing_driver_output = "failed to open DBI driver 'sqlite3'"; my $bad_driver_output = "/failed to open DBI driver 'nodriver'/"; -my $conn_time_output = "/OK - connection time: [0-9\.]+s \|/"; +my $conn_time_output = "/connection time: [0-9\.]+s \|/"; my $missing_query_output = "/Must specify a query to execute/"; -my $no_rows_output = "/WARNING - no rows returned/"; -my $not_numeric_output = "/CRITICAL - result value is not a numeric:/"; -my $query_time_output = "/OK - connection time: [0-9\.]+s, 'SELECT 1' returned 1.000000 in [0-9\.]+s \|/"; -my $syntax_error_output = "/CRITICAL - failed to execute query 'GET ALL FROM test': 1: near \"GET\": syntax error/"; +my $no_rows_output = "/no rows returned/"; +my $not_numeric_output = "/result value is not a numeric:/"; +my $query_time_output = "/connection time: [0-9\.]+s, 'SELECT 1' returned 1.000000 in [0-9\.]+s \|/"; +my $syntax_error_output = "/1: near \"GET\": syntax error/"; my $result; -- cgit v1.2.3-74-g34f1 From b504a6284ea35efcea4debe93f3dbd35bf9427f3 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 29 Oct 2025 13:08:23 +0100 Subject: Fix spelling errors --- plugins/check_dbi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 84e3cb5b..035e30cd 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -394,7 +394,7 @@ int main(int argc, char **argv) { mp_set_subcheck_state(sc_query, query_time_status); if (query_time_status == STATE_OK) { - xasprintf(&sc_query.output, "Query duration '%f' is withing given thresholds", + xasprintf(&sc_query.output, "Query duration '%f' is within given thresholds", query_res.query_duration); } else { xasprintf(&sc_query.output, "Query duration '%f' violates the given thresholds", @@ -895,7 +895,7 @@ static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type printf("Query duration: %f\n", result.query_duration); } - // Default state is OK, all error will be set explicitely + // Default state is OK, all error will be set explicitly mp_state_enum query_processing_state = STATE_OK; { -- cgit v1.2.3-74-g34f1 From 071de8a73a283ac7e262194c2c08fabfef4473b1 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 29 Oct 2025 23:27:12 +0100 Subject: check_dbi: more refactoring for sanities sake --- plugins/check_dbi.c | 168 ++++++++++++++++------------------------------------ 1 file changed, 51 insertions(+), 117 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 035e30cd..ddd0b328 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -358,7 +358,7 @@ int main(int argc, char **argv) { // so we expected a number // this is a CRITICAL xasprintf(&sc_query.output, "Query '%s' result is not numeric", - config.dbi_query, query_res.result_string); + config.dbi_query); sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); } else { @@ -490,7 +490,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { } break; } - case 'm': if (!strcasecmp(optarg, "CONN_TIME")) { result.config.metric = METRIC_CONN_TIME; @@ -510,7 +509,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { } else { timeout_interval = atoi(optarg); } - break; case 'H': /* host */ if (!is_host(optarg)) { @@ -522,7 +520,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { case 'v': verbose++; break; - case 'd': result.config.dbi_driver = optarg; break; @@ -718,21 +715,12 @@ void print_usage(void) { printf(" [-e ] [-r|-R ]\n"); } -const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type, - mp_dbi_metric metric, mp_dbi_type type) { - const char *str; - - if (field_type != DBI_TYPE_STRING) { - printf("CRITICAL - result value is not a string\n"); - return NULL; - } - - str = dbi_result_get_string_idx(res, 1); +const char *get_field_str(dbi_result res, mp_dbi_metric metric, mp_dbi_type type) { + const char *str = dbi_result_get_string_idx(res, 1); if ((!str) || (strcmp(str, "ERROR") == 0)) { if (metric != METRIC_QUERY_RESULT) { return NULL; } - np_dbi_print_error(conn, "CRITICAL - failed to fetch string value"); return NULL; } @@ -742,36 +730,50 @@ const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_ty return str; } -double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type, mp_dbi_metric metric, - mp_dbi_type type) { - double val = NAN; +typedef struct { + double value; + int error_code; + int dbi_error_code; // not sure if useful +} get_field_wrapper; +get_field_wrapper get_field(dbi_result res, mp_dbi_metric metric, mp_dbi_type type) { + + unsigned short field_type = dbi_result_get_field_type_idx(res, 1); + get_field_wrapper result = { + .value = NAN, + .error_code = OK, + }; - if (*field_type == DBI_TYPE_INTEGER) { - val = (double)dbi_result_get_longlong_idx(res, 1); - } else if (*field_type == DBI_TYPE_DECIMAL) { - val = dbi_result_get_double_idx(res, 1); - } else if (*field_type == DBI_TYPE_STRING) { + if (field_type == DBI_TYPE_INTEGER) { + result.value = (double)dbi_result_get_longlong_idx(res, 1); + } else if (field_type == DBI_TYPE_DECIMAL) { + result.value = dbi_result_get_double_idx(res, 1); + } else if (field_type == DBI_TYPE_STRING) { const char *val_str; char *endptr = NULL; - val_str = get_field_str(conn, res, *field_type, metric, type); + val_str = get_field_str(res, metric, type); if (!val_str) { - if (metric != METRIC_QUERY_RESULT) { - return NAN; - } - *field_type = DBI_TYPE_ERROR; - return NAN; + result.error_code = ERROR; + field_type = DBI_TYPE_ERROR; + return result; } - val = strtod(val_str, &endptr); + result.value = strtod(val_str, &endptr); if (endptr == val_str) { if (metric != METRIC_QUERY_RESULT) { - return NAN; + result.error_code = ERROR; + return result; } - printf("CRITICAL - result value is not a numeric: %s\n", val_str); - *field_type = DBI_TYPE_ERROR; - return NAN; + + if (verbose) { + printf("CRITICAL - result value is not a numeric: %s\n", val_str); + } + + field_type = DBI_TYPE_ERROR; + result.error_code = ERROR; + return result; } + if ((endptr != NULL) && (*endptr != '\0')) { if (verbose) { printf("Garbage after value: %s\n", endptr); @@ -779,86 +781,18 @@ double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type, mp_d } } else { if (metric != METRIC_QUERY_RESULT) { - return NAN; + result.error_code = ERROR; + return result; } - printf("CRITICAL - cannot parse value of type %s (%i)\n", - (*field_type == DBI_TYPE_BINARY) ? "BINARY" - : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME" - : "", - *field_type); - *field_type = DBI_TYPE_ERROR; - return NAN; - } - return val; -} - -mp_state_enum get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, - double *res_val, mp_dbi_metric metric, mp_dbi_type type) { - unsigned short field_type; - double val = NAN; - - if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - np_dbi_print_error(conn, "CRITICAL - failed to fetch rows"); - return STATE_CRITICAL; + // printf("CRITICAL - cannot parse value of type %s (%i)\n", + // (*field_type == DBI_TYPE_BINARY) ? "BINARY" + // : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME" + // : "", + // *field_type); + field_type = DBI_TYPE_ERROR; + result.error_code = ERROR; } - - if (dbi_result_get_numrows(res) < 1) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - printf("WARNING - no rows returned\n"); - return STATE_WARNING; - } - - if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - np_dbi_print_error(conn, "CRITICAL - failed to fetch fields"); - return STATE_CRITICAL; - } - - if (dbi_result_get_numfields(res) < 1) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - printf("WARNING - no fields returned\n"); - return STATE_WARNING; - } - - if (dbi_result_first_row(res) != 1) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - np_dbi_print_error(conn, "CRITICAL - failed to fetch first row"); - return STATE_CRITICAL; - } - - field_type = dbi_result_get_field_type_idx(res, 1); - if (field_type != DBI_TYPE_ERROR) { - if (type == TYPE_STRING) { - /* the value will be freed in dbi_result_free */ - *res_val_str = strdup(get_field_str(conn, res, field_type, metric, type)); - } else { - val = get_field(conn, res, &field_type, metric, type); - } - } - - *res_val = val; - - if (field_type == DBI_TYPE_ERROR) { - if (metric != METRIC_QUERY_RESULT) { - return STATE_OK; - } - np_dbi_print_error(conn, "CRITICAL - failed to fetch data"); - return STATE_CRITICAL; - } - - dbi_result_free(res); - return STATE_OK; + return result; } static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type type, @@ -942,10 +876,10 @@ static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type unsigned short field_type = dbi_result_get_field_type_idx(res, 1); if (field_type != DBI_TYPE_ERROR) { if (type == TYPE_STRING) { - result.result_string = - strdup(get_field_str(conn, res, field_type, metric, type)); + result.result_string = strdup(get_field_str(res, metric, type)); } else { - result.result_number = get_field(conn, res, &field_type, metric, type); + get_field_wrapper gfw = get_field(res, metric, type); + result.result_number = gfw.value; } } else { // Error when retrieving the field, that is OK if the Query result is not of @@ -967,7 +901,7 @@ static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type return result; } -double timediff(struct timeval start, struct timeval end) { +static double timediff(struct timeval start, struct timeval end) { double diff; while (start.tv_usec > end.tv_usec) { @@ -978,7 +912,7 @@ double timediff(struct timeval start, struct timeval end) { return diff; } -void np_dbi_print_error(dbi_conn conn, char *fmt, ...) { +static void np_dbi_print_error(dbi_conn conn, char *fmt, ...) { const char *errmsg = NULL; va_list ap; -- cgit v1.2.3-74-g34f1 From 408783f53d0baaf7341c7c584ca64a9073d66ee2 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Wed, 29 Oct 2025 23:27:31 +0100 Subject: check_dbi: add output format parameter --- plugins/check_dbi.c | 20 ++++++++++++++++++++ plugins/check_dbi.d/config.h | 4 ++++ 2 files changed, 24 insertions(+) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index ddd0b328..286635cc 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -100,6 +100,10 @@ int main(int argc, char **argv) { const check_dbi_config config = tmp.config; + if (config.output_format_is_set) { + mp_set_format(config.output_format); + } + /* Set signal handling and alarm */ if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { usage4(_("Cannot catch SIGALRM")); @@ -421,6 +425,9 @@ int main(int argc, char **argv) { /* process command-line arguments */ check_dbi_config_wrapper process_arguments(int argc, char **argv) { + enum { + output_format_index = CHAR_MAX + 1, + }; int option = 0; static struct option longopts[] = {STD_LONG_OPTS, @@ -432,6 +439,7 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { {"option", required_argument, 0, 'o'}, {"query", required_argument, 0, 'q'}, {"database", required_argument, 0, 'D'}, + {"output-format", required_argument, 0, output_format_index}, {0, 0, 0, 0}}; check_dbi_config_wrapper result = { @@ -556,6 +564,18 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { case 'D': result.config.dbi_database = optarg; break; + case output_format_index: { + parsed_output_format parser = mp_parse_output_format(optarg); + if (!parser.parsing_success) { + // TODO List all available formats here, maybe add anothoer usage function + printf("Invalid output format: %s\n", optarg); + exit(STATE_UNKNOWN); + } + + result.config.output_format_is_set = true; + result.config.output_format = parser.output_format; + break; + } } } diff --git a/plugins/check_dbi.d/config.h b/plugins/check_dbi.d/config.h index f6f0d7b3..09aa67da 100644 --- a/plugins/check_dbi.d/config.h +++ b/plugins/check_dbi.d/config.h @@ -38,6 +38,8 @@ typedef struct { char *critical_range; thresholds *dbi_thresholds; + bool output_format_is_set; + mp_output_format output_format; } check_dbi_config; check_dbi_config check_dbi_config_init() { @@ -58,6 +60,8 @@ check_dbi_config check_dbi_config_init() { .warning_range = NULL, .critical_range = NULL, .dbi_thresholds = NULL, + + .output_format_is_set = false, }; return tmp; } -- cgit v1.2.3-74-g34f1 From 0c70af5fef8bd7cbbad107224fd283f69ae0416a Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Thu, 30 Oct 2025 23:58:38 +0100 Subject: check_dbi: more refactoring for coherence and simplification --- plugins/check_dbi.c | 121 ++++++++++++++++++++++--------------------- plugins/check_dbi.d/config.h | 27 +++++----- 2 files changed, 75 insertions(+), 73 deletions(-) (limited to 'plugins/check_dbi.c') diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 286635cc..9bc68eb3 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c @@ -34,6 +34,7 @@ const char *copyright = "2011-2024"; const char *email = "devel@monitoring-plugins.org"; #include "../lib/monitoringplug.h" +#include "thresholds.h" #include "perfdata.h" #include "output.h" #include "states.h" @@ -66,7 +67,6 @@ typedef struct { } check_dbi_config_wrapper; static check_dbi_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); -static check_dbi_config_wrapper validate_arguments(check_dbi_config_wrapper /*config_wrapper*/); void print_usage(void); static void print_help(void); @@ -82,7 +82,8 @@ typedef struct { const char *error_string; mp_state_enum query_processing_status; } do_query_result; -static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type type, char *query); +static do_query_result do_query(dbi_conn conn, check_dbi_metric metric, check_dbi_type type, + char *query); int main(int argc, char **argv) { setlocale(LC_ALL, ""); @@ -228,8 +229,8 @@ int main(int argc, char **argv) { pd_conn_duration = mp_set_pd_value(pd_conn_duration, conn_time); if (config.metric == METRIC_CONN_TIME) { - // TODO set pd thresholds - mp_state_enum status = get_status(conn_time, config.dbi_thresholds); + pd_conn_duration = mp_pd_set_thresholds(pd_conn_duration, config.thresholds); + mp_state_enum status = mp_get_pd_status(pd_conn_duration); sc_connection_time = mp_set_subcheck_state(sc_connection_time, status); if (status != STATE_OK) { xasprintf(&sc_connection_time.output, "%s violates thresholds", @@ -250,7 +251,11 @@ int main(int argc, char **argv) { xasprintf(&sc_server_version.output, "Connected to server version %u", server_version); if (config.metric == METRIC_SERVER_VERSION) { - mp_state_enum status = get_status(server_version, config.dbi_thresholds); + mp_perfdata pd_server_version = perfdata_init(); + pd_server_version = mp_set_pd_value(pd_server_version, server_version); + pd_server_version = mp_pd_set_thresholds(pd_server_version, config.thresholds); + mp_state_enum status = mp_get_pd_status(pd_server_version); + mp_add_perfdata_to_subcheck(&sc_server_version, pd_server_version); sc_server_version = mp_set_subcheck_state(sc_server_version, status); @@ -262,17 +267,16 @@ int main(int argc, char **argv) { mp_add_subcheck_to_check(&overall, sc_server_version); /* select a database */ - if (config.dbi_database) { + if (config.database) { if (verbose > 1) { - printf("Selecting database '%s'\n", config.dbi_database); + printf("Selecting database '%s'\n", config.database); } mp_subcheck sc_select_db = mp_subcheck_init(); sc_select_db = mp_set_subcheck_default_state(sc_select_db, STATE_OK); - if (dbi_conn_select_db(conn, config.dbi_database)) { - np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", - config.dbi_database); + if (dbi_conn_select_db(conn, config.database)) { + np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", config.database); exit(STATE_UNKNOWN); } else { mp_add_subcheck_to_check(&overall, sc_select_db); @@ -280,12 +284,12 @@ int main(int argc, char **argv) { } // Do a query (if configured) - if (config.dbi_query) { + if (config.query) { mp_subcheck sc_query = mp_subcheck_init(); sc_query = mp_set_subcheck_default_state(sc_query, STATE_UNKNOWN); /* execute query */ - do_query_result query_res = do_query(conn, config.metric, config.type, config.dbi_query); + do_query_result query_res = do_query(conn, config.metric, config.type, config.query); if (query_res.error_code != 0) { xasprintf(&sc_query.output, "Query failed: %s", query_res.error_string); @@ -299,7 +303,7 @@ int main(int argc, char **argv) { sc_query = mp_set_subcheck_state(sc_query, query_res.query_processing_status); } else { // query succeeded in general - xasprintf(&sc_query.output, "Query '%s' succeeded", config.dbi_query); + xasprintf(&sc_query.output, "Query '%s' succeeded", config.query); // that's a OK by default now sc_query = mp_set_subcheck_default_state(sc_query, STATE_OK); @@ -309,7 +313,7 @@ int main(int argc, char **argv) { pd_query_duration = mp_set_pd_value(pd_query_duration, query_res.query_duration); pd_query_duration.label = "querytime"; if (config.metric == METRIC_QUERY_TIME) { - // TODO set thresholds + pd_query_duration = mp_pd_set_thresholds(pd_query_duration, config.thresholds); } mp_add_perfdata_to_subcheck(&sc_query, pd_query_duration); @@ -362,19 +366,20 @@ int main(int argc, char **argv) { // so we expected a number // this is a CRITICAL xasprintf(&sc_query.output, "Query '%s' result is not numeric", - config.dbi_query); + config.query); sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL); } else { - mp_state_enum query_numerical_result = - get_status(query_res.result_number, config.dbi_thresholds); - sc_query = mp_set_subcheck_state(sc_query, query_numerical_result); mp_perfdata pd_query_val = perfdata_init(); pd_query_val = mp_set_pd_value(pd_query_val, query_res.result_number); pd_query_val.label = "query"; + pd_query_val = mp_pd_set_thresholds(pd_query_val, config.thresholds); + mp_add_perfdata_to_subcheck(&sc_query, pd_query_val); + mp_state_enum query_numerical_result = mp_get_pd_status(pd_query_val); + sc_query = mp_set_subcheck_state(sc_query, query_numerical_result); // TODO set pd thresholds // if (config.dbi_thresholds->warning) { // pd_query_val.warn= config.dbi_thresholds->warning @@ -393,8 +398,7 @@ int main(int argc, char **argv) { } } } else if (config.metric == METRIC_QUERY_TIME) { - mp_state_enum query_time_status = - get_status(query_res.query_duration, config.dbi_thresholds); + mp_state_enum query_time_status = mp_get_pd_status(pd_query_duration); mp_set_subcheck_state(sc_query, query_time_status); if (query_time_status == STATE_OK) { @@ -464,14 +468,22 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { print_revision(progname, NP_VERSION); exit(STATE_UNKNOWN); - case 'c': /* critical range */ - result.config.critical_range = optarg; + case 'c': /* critical range */ { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse critical threshold"); + } + result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range); result.config.type = TYPE_NUMERIC; - break; - case 'w': /* warning range */ - result.config.warning_range = optarg; + } break; + case 'w': /* warning range */ { + mp_range_parsed tmp = mp_parse_range_string(optarg); + if (tmp.error != MP_PARSING_SUCCES) { + die(STATE_UNKNOWN, "failed to parse warning threshold"); + } + result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range); result.config.type = TYPE_NUMERIC; - break; + } break; case 'e': result.config.expect = optarg; result.config.type = TYPE_STRING; @@ -559,10 +571,10 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { new->value = value; } break; case 'q': - result.config.dbi_query = optarg; + result.config.query = optarg; break; case 'D': - result.config.dbi_database = optarg; + result.config.database = optarg; break; case output_format_index: { parsed_output_format parser = mp_parse_output_format(optarg); @@ -579,57 +591,48 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) { } } - set_thresholds(&result.config.dbi_thresholds, result.config.warning_range, - result.config.critical_range); - - return validate_arguments(result); -} - -check_dbi_config_wrapper validate_arguments(check_dbi_config_wrapper config_wrapper) { - if (!config_wrapper.config.dbi_driver) { + if (!result.config.dbi_driver) { usage("Must specify a DBI driver"); } - if (((config_wrapper.config.metric == METRIC_QUERY_RESULT) || - (config_wrapper.config.metric == METRIC_QUERY_TIME)) && - (!config_wrapper.config.dbi_query)) { + if (((result.config.metric == METRIC_QUERY_RESULT) || + (result.config.metric == METRIC_QUERY_TIME)) && + (!result.config.query)) { usage("Must specify a query to execute (metric == QUERY_RESULT)"); } - if ((config_wrapper.config.metric != METRIC_CONN_TIME) && - (config_wrapper.config.metric != METRIC_SERVER_VERSION) && - (config_wrapper.config.metric != METRIC_QUERY_RESULT) && - (config_wrapper.config.metric != METRIC_QUERY_TIME)) { + if ((result.config.metric != METRIC_CONN_TIME) && + (result.config.metric != METRIC_SERVER_VERSION) && + (result.config.metric != METRIC_QUERY_RESULT) && + (result.config.metric != METRIC_QUERY_TIME)) { usage("Invalid metric specified"); } - if (config_wrapper.config.expect && - (config_wrapper.config.warning_range || config_wrapper.config.critical_range || - config_wrapper.config.expect_re_str)) { + if (result.config.expect && + (result.config.thresholds.warning_is_set || result.config.thresholds.critical_is_set || + result.config.expect_re_str)) { usage("Do not mix -e and -w/-c/-r/-R"); } - if (config_wrapper.config.expect_re_str && - (config_wrapper.config.warning_range || config_wrapper.config.critical_range || - config_wrapper.config.expect)) { + if (result.config.expect_re_str && + (result.config.thresholds.warning_is_set || result.config.thresholds.critical_is_set || + result.config.expect)) { usage("Do not mix -r/-R and -w/-c/-e"); } - if (config_wrapper.config.expect && (config_wrapper.config.metric != METRIC_QUERY_RESULT)) { + if (result.config.expect && (result.config.metric != METRIC_QUERY_RESULT)) { usage("Option -e requires metric QUERY_RESULT"); } - if (config_wrapper.config.expect_re_str && - (config_wrapper.config.metric != METRIC_QUERY_RESULT)) { + if (result.config.expect_re_str && (result.config.metric != METRIC_QUERY_RESULT)) { usage("Options -r/-R require metric QUERY_RESULT"); } - if (config_wrapper.config.type == TYPE_STRING) { - assert(config_wrapper.config.expect || config_wrapper.config.expect_re_str); + if (result.config.type == TYPE_STRING) { + assert(result.config.expect || result.config.expect_re_str); } - config_wrapper.errorcode = OK; - return config_wrapper; + return result; } void print_help(void) { @@ -735,7 +738,7 @@ void print_usage(void) { printf(" [-e ] [-r|-R ]\n"); } -const char *get_field_str(dbi_result res, mp_dbi_metric metric, mp_dbi_type type) { +const char *get_field_str(dbi_result res, check_dbi_metric metric, check_dbi_type type) { const char *str = dbi_result_get_string_idx(res, 1); if ((!str) || (strcmp(str, "ERROR") == 0)) { if (metric != METRIC_QUERY_RESULT) { @@ -755,7 +758,7 @@ typedef struct { int error_code; int dbi_error_code; // not sure if useful } get_field_wrapper; -get_field_wrapper get_field(dbi_result res, mp_dbi_metric metric, mp_dbi_type type) { +get_field_wrapper get_field(dbi_result res, check_dbi_metric metric, check_dbi_type type) { unsigned short field_type = dbi_result_get_field_type_idx(res, 1); get_field_wrapper result = { @@ -815,7 +818,7 @@ get_field_wrapper get_field(dbi_result res, mp_dbi_metric metric, mp_dbi_type ty return result; } -static do_query_result do_query(dbi_conn conn, mp_dbi_metric metric, mp_dbi_type type, +static do_query_result do_query(dbi_conn conn, check_dbi_metric metric, check_dbi_type type, char *query) { assert(query); diff --git a/plugins/check_dbi.d/config.h b/plugins/check_dbi.d/config.h index 09aa67da..25d74a12 100644 --- a/plugins/check_dbi.d/config.h +++ b/plugins/check_dbi.d/config.h @@ -3,18 +3,19 @@ #include "../../config.h" #include #include "../../lib/monitoringplug.h" +#include "thresholds.h" typedef enum { METRIC_CONN_TIME, METRIC_SERVER_VERSION, METRIC_QUERY_RESULT, METRIC_QUERY_TIME, -} mp_dbi_metric; +} check_dbi_metric; typedef enum { TYPE_NUMERIC, TYPE_STRING, -} mp_dbi_type; +} check_dbi_type; typedef struct { char *key; @@ -24,19 +25,19 @@ typedef struct { typedef struct { char *dbi_driver; char *host; + driver_option_t *dbi_options; size_t dbi_options_num; - char *dbi_database; - char *dbi_query; + + char *database; + char *query; char *expect; char *expect_re_str; int expect_re_cflags; - mp_dbi_metric metric; - mp_dbi_type type; - char *warning_range; - char *critical_range; - thresholds *dbi_thresholds; + check_dbi_metric metric; + check_dbi_type type; + mp_thresholds thresholds; bool output_format_is_set; mp_output_format output_format; @@ -48,8 +49,8 @@ check_dbi_config check_dbi_config_init() { .host = NULL, .dbi_options = NULL, .dbi_options_num = 0, - .dbi_database = NULL, - .dbi_query = NULL, + .database = NULL, + .query = NULL, .expect = NULL, .expect_re_str = NULL, @@ -57,9 +58,7 @@ check_dbi_config check_dbi_config_init() { .metric = METRIC_QUERY_RESULT, .type = TYPE_NUMERIC, - .warning_range = NULL, - .critical_range = NULL, - .dbi_thresholds = NULL, + .thresholds = mp_thresholds_init(), .output_format_is_set = false, }; -- cgit v1.2.3-74-g34f1