diff options
-rw-r--r-- | plugins/check_dbi.c | 95 |
1 files changed, 76 insertions, 19 deletions
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index eefcf02a..94c6b15f 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c | |||
@@ -68,6 +68,8 @@ char *warning_range = NULL; | |||
68 | char *critical_range = NULL; | 68 | char *critical_range = NULL; |
69 | thresholds *dbi_thresholds = NULL; | 69 | thresholds *dbi_thresholds = NULL; |
70 | 70 | ||
71 | char *expect = NULL; | ||
72 | |||
71 | np_dbi_metric_t metric = METRIC_QUERY_RESULT; | 73 | np_dbi_metric_t metric = METRIC_QUERY_RESULT; |
72 | 74 | ||
73 | char *np_dbi_driver = NULL; | 75 | char *np_dbi_driver = NULL; |
@@ -85,7 +87,7 @@ double timediff (struct timeval, struct timeval); | |||
85 | 87 | ||
86 | void np_dbi_print_error (dbi_conn, char *, ...); | 88 | void np_dbi_print_error (dbi_conn, char *, ...); |
87 | 89 | ||
88 | int do_query (dbi_conn, double *, double *); | 90 | int do_query (dbi_conn, const char **, double *, double *); |
89 | 91 | ||
90 | int | 92 | int |
91 | main (int argc, char **argv) | 93 | main (int argc, char **argv) |
@@ -99,6 +101,7 @@ main (int argc, char **argv) | |||
99 | double conn_time = 0.0; | 101 | double conn_time = 0.0; |
100 | double query_time = 0.0; | 102 | double query_time = 0.0; |
101 | 103 | ||
104 | const char *query_val_str = NULL; | ||
102 | double query_val = 0.0; | 105 | double query_val = 0.0; |
103 | 106 | ||
104 | int i; | 107 | int i; |
@@ -224,13 +227,21 @@ main (int argc, char **argv) | |||
224 | 227 | ||
225 | if (np_dbi_query) { | 228 | if (np_dbi_query) { |
226 | /* execute query */ | 229 | /* execute query */ |
227 | status = do_query (conn, &query_val, &query_time); | 230 | status = do_query (conn, &query_val_str, &query_val, &query_time); |
228 | if (status != STATE_OK) | 231 | if (status != STATE_OK) |
229 | /* do_query prints an error message in this case */ | 232 | /* do_query prints an error message in this case */ |
230 | return status; | 233 | return status; |
231 | 234 | ||
232 | if (metric == METRIC_QUERY_RESULT) | 235 | if (metric == METRIC_QUERY_RESULT) { |
233 | status = get_status (query_val, dbi_thresholds); | 236 | if (expect) { |
237 | if ((! query_val_str) || strcmp (query_val_str, expect)) | ||
238 | status = STATE_CRITICAL; | ||
239 | else | ||
240 | status = STATE_OK; | ||
241 | } | ||
242 | else | ||
243 | status = get_status (query_val, dbi_thresholds); | ||
244 | } | ||
234 | else if (metric == METRIC_QUERY_TIME) | 245 | else if (metric == METRIC_QUERY_TIME) |
235 | status = get_status (query_time, dbi_thresholds); | 246 | status = get_status (query_time, dbi_thresholds); |
236 | } | 247 | } |
@@ -241,11 +252,17 @@ main (int argc, char **argv) | |||
241 | 252 | ||
242 | /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error | 253 | /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error |
243 | * which should have been reported and handled (abort) before */ | 254 | * which should have been reported and handled (abort) before */ |
244 | assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val))); | 255 | assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) || expect); |
245 | 256 | ||
246 | printf ("%s - connection time: %fs", state_text (status), conn_time); | 257 | printf ("%s - connection time: %fs", state_text (status), conn_time); |
247 | if (np_dbi_query) { | 258 | if (np_dbi_query) { |
248 | if (isnan (query_val)) | 259 | if (expect) { |
260 | printf (", '%s' returned '%s' in %fs", np_dbi_query, | ||
261 | query_val_str ? query_val_str : "<nothing>", query_time); | ||
262 | if (status != STATE_OK) | ||
263 | printf (" (expected '%s')", expect); | ||
264 | } | ||
265 | else if (isnan (query_val)) | ||
249 | printf (", '%s' query execution time: %fs", np_dbi_query, query_time); | 266 | printf (", '%s' query execution time: %fs", np_dbi_query, query_time); |
250 | else | 267 | else |
251 | printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); | 268 | printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); |
@@ -255,7 +272,7 @@ main (int argc, char **argv) | |||
255 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", | 272 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", |
256 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : ""); | 273 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : ""); |
257 | if (np_dbi_query) { | 274 | if (np_dbi_query) { |
258 | if (! isnan (query_val)) | 275 | if (! isnan (query_val)) /* this is also true when -e is used */ |
259 | printf (" query=%f;%s;%s;;", query_val, | 276 | printf (" query=%f;%s;%s;;", query_val, |
260 | ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", | 277 | ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", |
261 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); | 278 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); |
@@ -277,6 +294,7 @@ process_arguments (int argc, char **argv) | |||
277 | static struct option longopts[] = { | 294 | static struct option longopts[] = { |
278 | STD_LONG_OPTS, | 295 | STD_LONG_OPTS, |
279 | 296 | ||
297 | {"expect", required_argument, 0, 'e'}, | ||
280 | {"metric", required_argument, 0, 'm'}, | 298 | {"metric", required_argument, 0, 'm'}, |
281 | {"driver", required_argument, 0, 'd'}, | 299 | {"driver", required_argument, 0, 'd'}, |
282 | {"option", required_argument, 0, 'o'}, | 300 | {"option", required_argument, 0, 'o'}, |
@@ -286,7 +304,7 @@ process_arguments (int argc, char **argv) | |||
286 | }; | 304 | }; |
287 | 305 | ||
288 | while (1) { | 306 | while (1) { |
289 | c = getopt_long (argc, argv, "Vvht:c:w:m:H:d:o:q:D:", | 307 | c = getopt_long (argc, argv, "Vvht:c:w:e:m:H:d:o:q:D:", |
290 | longopts, &option); | 308 | longopts, &option); |
291 | 309 | ||
292 | if (c == EOF) | 310 | if (c == EOF) |
@@ -308,6 +326,9 @@ process_arguments (int argc, char **argv) | |||
308 | case 'w': /* warning range */ | 326 | case 'w': /* warning range */ |
309 | warning_range = optarg; | 327 | warning_range = optarg; |
310 | break; | 328 | break; |
329 | case 'e': | ||
330 | expect = optarg; | ||
331 | break; | ||
311 | case 'm': | 332 | case 'm': |
312 | if (! strcasecmp (optarg, "CONN_TIME")) | 333 | if (! strcasecmp (optarg, "CONN_TIME")) |
313 | metric = METRIC_CONN_TIME; | 334 | metric = METRIC_CONN_TIME; |
@@ -396,6 +417,12 @@ validate_arguments () | |||
396 | && (metric != METRIC_QUERY_TIME)) | 417 | && (metric != METRIC_QUERY_TIME)) |
397 | usage ("Invalid metric specified"); | 418 | usage ("Invalid metric specified"); |
398 | 419 | ||
420 | if (expect && (warning_range || critical_range)) | ||
421 | usage ("Do not mix -e and -w/-c"); | ||
422 | |||
423 | if (expect && (metric != METRIC_QUERY_RESULT)) | ||
424 | usage ("Option -e requires metric QUERY_RESULT"); | ||
425 | |||
399 | return OK; | 426 | return OK; |
400 | } | 427 | } |
401 | 428 | ||
@@ -431,6 +458,9 @@ print_help (void) | |||
431 | printf ("\n"); | 458 | printf ("\n"); |
432 | 459 | ||
433 | printf (UT_WARN_CRIT_RANGE); | 460 | printf (UT_WARN_CRIT_RANGE); |
461 | printf (" %s\n", "-e, --expect=STRING"); | ||
462 | printf (" %s\n", _("String to expect as query result")); | ||
463 | printf (" %s\n", _("Do not mix with -w or -c!")); | ||
434 | printf (" %s\n", "-m, --metric=METRIC"); | 464 | printf (" %s\n", "-m, --metric=METRIC"); |
435 | printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); | 465 | printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); |
436 | printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); | 466 | printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); |
@@ -481,6 +511,7 @@ print_usage (void) | |||
481 | printf ("%s\n", _("Usage:")); | 511 | printf ("%s\n", _("Usage:")); |
482 | printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); | 512 | printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); |
483 | printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); | 513 | printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); |
514 | printf (" [-e <string>]\n"); | ||
484 | } | 515 | } |
485 | 516 | ||
486 | #define CHECK_IGNORE_ERROR(s) \ | 517 | #define CHECK_IGNORE_ERROR(s) \ |
@@ -489,6 +520,28 @@ print_usage (void) | |||
489 | return (s); \ | 520 | return (s); \ |
490 | } while (0) | 521 | } while (0) |
491 | 522 | ||
523 | const char * | ||
524 | get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type) | ||
525 | { | ||
526 | const char *str; | ||
527 | |||
528 | if (field_type != DBI_TYPE_STRING) { | ||
529 | printf ("CRITICAL - result value is not a string\n"); | ||
530 | return NULL; | ||
531 | } | ||
532 | |||
533 | str = dbi_result_get_string_idx (res, 1); | ||
534 | if ((! str) || (strcmp (str, "ERROR") == 0)) { | ||
535 | CHECK_IGNORE_ERROR (NULL); | ||
536 | np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); | ||
537 | return NULL; | ||
538 | } | ||
539 | |||
540 | if ((verbose && expect) || (verbose > 2)) | ||
541 | printf ("Query returned string '%s'\n", str); | ||
542 | return str; | ||
543 | } | ||
544 | |||
492 | double | 545 | double |
493 | get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | 546 | get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) |
494 | { | 547 | { |
@@ -504,17 +557,13 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
504 | const char *val_str; | 557 | const char *val_str; |
505 | char *endptr = NULL; | 558 | char *endptr = NULL; |
506 | 559 | ||
507 | val_str = dbi_result_get_string_idx (res, 1); | 560 | val_str = get_field_str (conn, res, *field_type); |
508 | if ((! val_str) || (strcmp (val_str, "ERROR") == 0)) { | 561 | if (! val_str) { |
509 | CHECK_IGNORE_ERROR (NAN); | 562 | CHECK_IGNORE_ERROR (NAN); |
510 | np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); | ||
511 | *field_type = DBI_TYPE_ERROR; | 563 | *field_type = DBI_TYPE_ERROR; |
512 | return NAN; | 564 | return NAN; |
513 | } | 565 | } |
514 | 566 | ||
515 | if (verbose > 2) | ||
516 | printf ("Query returned string '%s'\n", val_str); | ||
517 | |||
518 | val = strtod (val_str, &endptr); | 567 | val = strtod (val_str, &endptr); |
519 | if (endptr == val_str) { | 568 | if (endptr == val_str) { |
520 | CHECK_IGNORE_ERROR (NAN); | 569 | CHECK_IGNORE_ERROR (NAN); |
@@ -543,7 +592,7 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
543 | } | 592 | } |
544 | 593 | ||
545 | double | 594 | double |
546 | get_query_result (dbi_conn conn, dbi_result res, double *res_val) | 595 | get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) |
547 | { | 596 | { |
548 | unsigned short field_type; | 597 | unsigned short field_type; |
549 | double val = NAN; | 598 | double val = NAN; |
@@ -579,8 +628,13 @@ get_query_result (dbi_conn conn, dbi_result res, double *res_val) | |||
579 | } | 628 | } |
580 | 629 | ||
581 | field_type = dbi_result_get_field_type_idx (res, 1); | 630 | field_type = dbi_result_get_field_type_idx (res, 1); |
582 | if (field_type != DBI_TYPE_ERROR) | 631 | if (field_type != DBI_TYPE_ERROR) { |
583 | val = get_field (conn, res, &field_type); | 632 | if (expect) |
633 | /* the value will be freed in dbi_result_free */ | ||
634 | *res_val_str = strdup (get_field_str (conn, res, field_type)); | ||
635 | else | ||
636 | val = get_field (conn, res, &field_type); | ||
637 | } | ||
584 | 638 | ||
585 | *res_val = val; | 639 | *res_val = val; |
586 | 640 | ||
@@ -597,7 +651,7 @@ get_query_result (dbi_conn conn, dbi_result res, double *res_val) | |||
597 | #undef CHECK_IGNORE_ERROR | 651 | #undef CHECK_IGNORE_ERROR |
598 | 652 | ||
599 | int | 653 | int |
600 | do_query (dbi_conn conn, double *res_val, double *res_time) | 654 | do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) |
601 | { | 655 | { |
602 | dbi_result res; | 656 | dbi_result res; |
603 | 657 | ||
@@ -617,11 +671,14 @@ do_query (dbi_conn conn, double *res_val, double *res_time) | |||
617 | return STATE_CRITICAL; | 671 | return STATE_CRITICAL; |
618 | } | 672 | } |
619 | 673 | ||
620 | status = get_query_result (conn, res, res_val); | 674 | status = get_query_result (conn, res, res_val_str, res_val); |
621 | 675 | ||
622 | gettimeofday (&timeval_end, NULL); | 676 | gettimeofday (&timeval_end, NULL); |
623 | *res_time = timediff (timeval_start, timeval_end); | 677 | *res_time = timediff (timeval_start, timeval_end); |
624 | 678 | ||
679 | if (verbose) | ||
680 | printf ("Time elapsed: %f\n", *res_time); | ||
681 | |||
625 | return status; | 682 | return status; |
626 | } | 683 | } |
627 | 684 | ||