mirror of
https://github.com/monitoring-plugins/monitoring-plugins.git
synced 2026-06-11 09:40:05 -04:00
Merge pull request #2168 from RincewindsHat/refactor/check_dbi
check_dbi: new output functionality
This commit is contained in:
commit
ca3acbe274
3 changed files with 433 additions and 325 deletions
|
|
@ -34,6 +34,10 @@ 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"
|
||||
#include "check_dbi.d/config.h"
|
||||
#include "common.h"
|
||||
#include "utils.h"
|
||||
|
|
@ -63,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);
|
||||
|
||||
|
|
@ -71,26 +74,18 @@ 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, check_dbi_metric metric, check_dbi_type type,
|
||||
char *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);
|
||||
|
|
@ -106,6 +101,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"));
|
||||
|
|
@ -116,44 +115,46 @@ int main(int argc, char **argv) {
|
|||
printf("Initializing DBI\n");
|
||||
}
|
||||
|
||||
dbi_inst *instance_p = {0};
|
||||
|
||||
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_inst instance_p = NULL;
|
||||
if (dbi_initialize_r(NULL, &instance_p) < 0) {
|
||||
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) {
|
||||
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);
|
||||
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 */
|
||||
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);
|
||||
return STATE_UNKNOWN;
|
||||
exit(STATE_UNKNOWN);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < config.dbi_options_num; ++i) {
|
||||
|
|
@ -167,10 +168,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;
|
||||
|
|
@ -178,7 +179,7 @@ int main(int argc, char **argv) {
|
|||
printf(" - %s\n", opt);
|
||||
}
|
||||
dbi_conn_close(conn);
|
||||
return STATE_UNKNOWN;
|
||||
exit(STATE_UNKNOWN);
|
||||
}
|
||||
|
||||
if (config.host) {
|
||||
|
|
@ -206,80 +207,216 @@ 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);
|
||||
conn_time = timediff(start_timeval, end_timeval);
|
||||
|
||||
server_version = dbi_conn_get_engine_version(conn);
|
||||
if (verbose) {
|
||||
printf("Connected to server version %u\n", server_version);
|
||||
}
|
||||
|
||||
if (config.metric == METRIC_SERVER_VERSION) {
|
||||
status = get_status(server_version, config.dbi_thresholds);
|
||||
}
|
||||
|
||||
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) {
|
||||
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",
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
if (config.database) {
|
||||
if (verbose > 1) {
|
||||
printf("Selecting database '%s'\n", config.dbi_database);
|
||||
printf("Selecting database '%s'\n", config.database);
|
||||
}
|
||||
|
||||
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;
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.dbi_query) {
|
||||
// Do a query (if configured)
|
||||
if (config.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.query);
|
||||
|
||||
if (config.metric == METRIC_QUERY_RESULT) {
|
||||
if (config.expect) {
|
||||
if ((!query_val_str) || strcmp(query_val_str, config.expect)) {
|
||||
status = STATE_CRITICAL;
|
||||
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.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) {
|
||||
pd_query_duration = mp_pd_set_thresholds(pd_query_duration, config.thresholds);
|
||||
}
|
||||
|
||||
mp_add_perfdata_to_subcheck(&sc_query, pd_query_duration);
|
||||
|
||||
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;
|
||||
// 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.query);
|
||||
sc_query = mp_set_subcheck_state(sc_query, STATE_CRITICAL);
|
||||
|
||||
} else {
|
||||
|
||||
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
|
||||
// } 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (config.expect_re_str) {
|
||||
int err;
|
||||
} else if (config.metric == METRIC_QUERY_TIME) {
|
||||
mp_state_enum query_time_status = mp_get_pd_status(pd_query_duration);
|
||||
mp_set_subcheck_state(sc_query, query_time_status);
|
||||
|
||||
regex_t expect_re = {};
|
||||
err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0);
|
||||
if (!err) {
|
||||
status = STATE_OK;
|
||||
} else if (err == REG_NOMATCH) {
|
||||
status = STATE_CRITICAL;
|
||||
if (query_time_status == STATE_OK) {
|
||||
xasprintf(&sc_query.output, "Query duration '%f' is within 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) {
|
||||
|
|
@ -287,71 +424,17 @@ 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 : "<nothing>", 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 */
|
||||
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,
|
||||
|
||||
{"expect", required_argument, 0, 'e'},
|
||||
{"regex", required_argument, 0, 'r'},
|
||||
{"regexi", required_argument, 0, 'R'},
|
||||
|
|
@ -360,6 +443,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 = {
|
||||
|
|
@ -384,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;
|
||||
|
|
@ -418,7 +510,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;
|
||||
|
|
@ -438,7 +529,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) {
|
|||
} else {
|
||||
timeout_interval = atoi(optarg);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'H': /* host */
|
||||
if (!is_host(optarg)) {
|
||||
|
|
@ -450,7 +540,6 @@ check_dbi_config_wrapper process_arguments(int argc, char **argv) {
|
|||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
result.config.dbi_driver = optarg;
|
||||
break;
|
||||
|
|
@ -482,61 +571,68 @@ 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
config_wrapper.errorcode = OK;
|
||||
return config_wrapper;
|
||||
if (result.config.type == TYPE_STRING) {
|
||||
assert(result.config.expect || result.config.expect_re_str);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void print_help(void) {
|
||||
|
|
@ -642,21 +738,12 @@ void print_usage(void) {
|
|||
printf(" [-e <string>] [-r|-R <regex>]\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, 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) {
|
||||
return NULL;
|
||||
}
|
||||
np_dbi_print_error(conn, "CRITICAL - failed to fetch string value");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -666,36 +753,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, check_dbi_metric metric, check_dbi_type type) {
|
||||
|
||||
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) {
|
||||
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) {
|
||||
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);
|
||||
|
|
@ -703,123 +804,127 @@ 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"
|
||||
: "<unknown>",
|
||||
*field_type);
|
||||
*field_type = DBI_TYPE_ERROR;
|
||||
return NAN;
|
||||
// printf("CRITICAL - cannot parse value of type %s (%i)\n",
|
||||
// (*field_type == DBI_TYPE_BINARY) ? "BINARY"
|
||||
// : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME"
|
||||
// : "<unknown>",
|
||||
// *field_type);
|
||||
field_type = DBI_TYPE_ERROR;
|
||||
result.error_code = ERROR;
|
||||
}
|
||||
return val;
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
static do_query_result do_query(dbi_conn conn, check_dbi_metric metric, check_dbi_type type,
|
||||
char *query) {
|
||||
assert(query);
|
||||
|
||||
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;
|
||||
if (verbose) {
|
||||
printf("Executing query '%s'\n", query);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
struct timeval timeval_end;
|
||||
mp_state_enum status = STATE_OK;
|
||||
|
||||
assert(np_dbi_query);
|
||||
|
||||
if (verbose) {
|
||||
printf("Executing query '%s'\n", np_dbi_query);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return status;
|
||||
// Default state is OK, all error will be set explicitly
|
||||
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(res, metric, type));
|
||||
} else {
|
||||
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
|
||||
// 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 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) {
|
||||
|
|
@ -830,7 +935,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,18 +3,19 @@
|
|||
#include "../../config.h"
|
||||
#include <stddef.h>
|
||||
#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,20 +25,22 @@ 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;
|
||||
} check_dbi_config;
|
||||
|
||||
check_dbi_config check_dbi_config_init() {
|
||||
|
|
@ -46,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,
|
||||
|
|
@ -55,9 +58,9 @@ 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,
|
||||
};
|
||||
return tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue