diff options
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/check_dbi.c | 127 |
1 files changed, 90 insertions, 37 deletions
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index f0099440..4a0a4d69 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c | |||
| @@ -38,7 +38,13 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
| 38 | 38 | ||
| 39 | #include "netutils.h" | 39 | #include "netutils.h" |
| 40 | 40 | ||
| 41 | /* required for NAN */ | ||
| 42 | #ifndef _ISOC99_SOURCE | ||
| 43 | #define _ISOC99_SOURCE | ||
| 44 | #endif | ||
| 45 | |||
| 41 | #include <assert.h> | 46 | #include <assert.h> |
| 47 | #include <math.h> | ||
| 42 | 48 | ||
| 43 | #include <dbi/dbi.h> | 49 | #include <dbi/dbi.h> |
| 44 | 50 | ||
| @@ -47,6 +53,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
| 47 | typedef enum { | 53 | typedef enum { |
| 48 | METRIC_CONN_TIME, | 54 | METRIC_CONN_TIME, |
| 49 | METRIC_QUERY_RESULT, | 55 | METRIC_QUERY_RESULT, |
| 56 | METRIC_QUERY_TIME, | ||
| 50 | } np_dbi_metric_t; | 57 | } np_dbi_metric_t; |
| 51 | 58 | ||
| 52 | typedef struct { | 59 | typedef struct { |
| @@ -224,24 +231,38 @@ main (int argc, char **argv) | |||
| 224 | 231 | ||
| 225 | if (metric == METRIC_QUERY_RESULT) | 232 | if (metric == METRIC_QUERY_RESULT) |
| 226 | status = get_status (query_val, dbi_thresholds); | 233 | status = get_status (query_val, dbi_thresholds); |
| 234 | else if (metric == METRIC_QUERY_TIME) | ||
| 235 | status = get_status (query_time, dbi_thresholds); | ||
| 227 | } | 236 | } |
| 228 | 237 | ||
| 229 | if (verbose) | 238 | if (verbose) |
| 230 | printf("Closing connection\n"); | 239 | printf("Closing connection\n"); |
| 231 | dbi_conn_close (conn); | 240 | dbi_conn_close (conn); |
| 232 | 241 | ||
| 242 | /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error | ||
| 243 | * which should have been reported and handled (abort) before */ | ||
| 244 | assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val))); | ||
| 245 | |||
| 233 | printf ("%s - connection time: %fs", state_text (status), conn_time); | 246 | printf ("%s - connection time: %fs", state_text (status), conn_time); |
| 234 | if (np_dbi_query) | 247 | if (np_dbi_query) { |
| 235 | printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); | 248 | if (isnan (query_val)) |
| 249 | printf (", '%s' query execution time: %fs", np_dbi_query, query_time); | ||
| 250 | else | ||
| 251 | printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); | ||
| 252 | } | ||
| 236 | 253 | ||
| 237 | printf (" | conntime=%fs;%s;%s;0;", conn_time, | 254 | printf (" | conntime=%fs;%s;%s;0;", conn_time, |
| 238 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", | 255 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", |
| 239 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : ""); | 256 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : ""); |
| 240 | if (np_dbi_query) | 257 | if (np_dbi_query) { |
| 241 | printf (" query=%f;%s;%s;; querytime=%fs;;;0;", query_val, | 258 | if (! isnan (query_val)) |
| 242 | ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", | 259 | printf (" query=%f;%s;%s;;", query_val, |
| 243 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : "", | 260 | ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", |
| 244 | query_time); | 261 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); |
| 262 | printf (" querytime=%fs;%s;%s;0;", query_time, | ||
| 263 | ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "", | ||
| 264 | ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : ""); | ||
| 265 | } | ||
| 245 | printf ("\n"); | 266 | printf ("\n"); |
| 246 | return status; | 267 | return status; |
| 247 | } | 268 | } |
| @@ -292,6 +313,8 @@ process_arguments (int argc, char **argv) | |||
| 292 | metric = METRIC_CONN_TIME; | 313 | metric = METRIC_CONN_TIME; |
| 293 | else if (! strcasecmp (optarg, "QUERY_RESULT")) | 314 | else if (! strcasecmp (optarg, "QUERY_RESULT")) |
| 294 | metric = METRIC_QUERY_RESULT; | 315 | metric = METRIC_QUERY_RESULT; |
| 316 | else if (! strcasecmp (optarg, "QUERY_TIME")) | ||
| 317 | metric = METRIC_QUERY_TIME; | ||
| 295 | else | 318 | else |
| 296 | usage2 (_("Invalid metric"), optarg); | 319 | usage2 (_("Invalid metric"), optarg); |
| 297 | break; | 320 | break; |
| @@ -364,11 +387,13 @@ validate_arguments () | |||
| 364 | if (! np_dbi_driver) | 387 | if (! np_dbi_driver) |
| 365 | usage ("Must specify a DBI driver"); | 388 | usage ("Must specify a DBI driver"); |
| 366 | 389 | ||
| 367 | if ((metric == METRIC_QUERY_RESULT) && (! np_dbi_query)) | 390 | if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) |
| 391 | && (! np_dbi_query)) | ||
| 368 | usage ("Must specify a query to execute (metric == QUERY_RESULT)"); | 392 | usage ("Must specify a query to execute (metric == QUERY_RESULT)"); |
| 369 | 393 | ||
| 370 | if ((metric != METRIC_CONN_TIME) | 394 | if ((metric != METRIC_CONN_TIME) |
| 371 | && (metric != METRIC_QUERY_RESULT)) | 395 | && (metric != METRIC_QUERY_RESULT) |
| 396 | && (metric != METRIC_QUERY_TIME)) | ||
| 372 | usage ("Invalid metric specified"); | 397 | usage ("Invalid metric specified"); |
| 373 | 398 | ||
| 374 | return OK; | 399 | return OK; |
| @@ -410,6 +435,8 @@ print_help (void) | |||
| 410 | printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); | 435 | printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); |
| 411 | printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); | 436 | printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); |
| 412 | printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); | 437 | printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); |
| 438 | printf (" QUERY_TIME - %s\n", _("time used to execute the query")); | ||
| 439 | printf (" %s\n", _("(ignore the query result)")); | ||
| 413 | printf ("\n"); | 440 | printf ("\n"); |
| 414 | 441 | ||
| 415 | printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 442 | printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
| @@ -441,10 +468,16 @@ print_usage (void) | |||
| 441 | printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); | 468 | printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); |
| 442 | } | 469 | } |
| 443 | 470 | ||
| 471 | #define CHECK_IGNORE_ERROR(s) \ | ||
| 472 | do { \ | ||
| 473 | if (metric != METRIC_QUERY_RESULT) \ | ||
| 474 | return (s); \ | ||
| 475 | } while (0) | ||
| 476 | |||
| 444 | double | 477 | double |
| 445 | get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | 478 | get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) |
| 446 | { | 479 | { |
| 447 | double val = 0.0; | 480 | double val = NAN; |
| 448 | 481 | ||
| 449 | if (*field_type == DBI_TYPE_INTEGER) { | 482 | if (*field_type == DBI_TYPE_INTEGER) { |
| 450 | val = (double)dbi_result_get_longlong_idx (res, 1); | 483 | val = (double)dbi_result_get_longlong_idx (res, 1); |
| @@ -458,9 +491,10 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
| 458 | 491 | ||
| 459 | val_str = dbi_result_get_string_idx (res, 1); | 492 | val_str = dbi_result_get_string_idx (res, 1); |
| 460 | if ((! val_str) || (strcmp (val_str, "ERROR") == 0)) { | 493 | if ((! val_str) || (strcmp (val_str, "ERROR") == 0)) { |
| 494 | CHECK_IGNORE_ERROR (NAN); | ||
| 461 | np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); | 495 | np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); |
| 462 | *field_type = DBI_TYPE_ERROR; | 496 | *field_type = DBI_TYPE_ERROR; |
| 463 | return 0.0; | 497 | return NAN; |
| 464 | } | 498 | } |
| 465 | 499 | ||
| 466 | if (verbose > 2) | 500 | if (verbose > 2) |
| @@ -468,9 +502,10 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
| 468 | 502 | ||
| 469 | val = strtod (val_str, &endptr); | 503 | val = strtod (val_str, &endptr); |
| 470 | if (endptr == val_str) { | 504 | if (endptr == val_str) { |
| 505 | CHECK_IGNORE_ERROR (NAN); | ||
| 471 | printf ("CRITICAL - result value is not a numeric: %s\n", val_str); | 506 | printf ("CRITICAL - result value is not a numeric: %s\n", val_str); |
| 472 | *field_type = DBI_TYPE_ERROR; | 507 | *field_type = DBI_TYPE_ERROR; |
| 473 | return 0.0; | 508 | return NAN; |
| 474 | } | 509 | } |
| 475 | else if ((endptr != NULL) && (*endptr != '\0')) { | 510 | else if ((endptr != NULL) && (*endptr != '\0')) { |
| 476 | if (verbose) | 511 | if (verbose) |
| @@ -478,6 +513,7 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
| 478 | } | 513 | } |
| 479 | } | 514 | } |
| 480 | else { | 515 | else { |
| 516 | CHECK_IGNORE_ERROR (NAN); | ||
| 481 | printf ("CRITICAL - cannot parse value of type %s (%i)\n", | 517 | printf ("CRITICAL - cannot parse value of type %s (%i)\n", |
| 482 | (*field_type == DBI_TYPE_BINARY) | 518 | (*field_type == DBI_TYPE_BINARY) |
| 483 | ? "BINARY" | 519 | ? "BINARY" |
| @@ -486,55 +522,43 @@ get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | |||
| 486 | : "<unknown>", | 522 | : "<unknown>", |
| 487 | *field_type); | 523 | *field_type); |
| 488 | *field_type = DBI_TYPE_ERROR; | 524 | *field_type = DBI_TYPE_ERROR; |
| 489 | return 0.0; | 525 | return NAN; |
| 490 | } | 526 | } |
| 491 | return val; | 527 | return val; |
| 492 | } | 528 | } |
| 493 | 529 | ||
| 494 | int | 530 | double |
| 495 | do_query (dbi_conn conn, double *res_val, double *res_time) | 531 | get_query_result (dbi_conn conn, dbi_result res, double *res_val) |
| 496 | { | 532 | { |
| 497 | dbi_result res; | ||
| 498 | |||
| 499 | unsigned short field_type; | 533 | unsigned short field_type; |
| 500 | double val = 0.0; | 534 | double val = NAN; |
| 501 | |||
| 502 | struct timeval timeval_start, timeval_end; | ||
| 503 | |||
| 504 | assert (np_dbi_query); | ||
| 505 | |||
| 506 | if (verbose) | ||
| 507 | printf ("Executing query '%s'\n", np_dbi_query); | ||
| 508 | |||
| 509 | gettimeofday (&timeval_start, NULL); | ||
| 510 | |||
| 511 | res = dbi_conn_query (conn, np_dbi_query); | ||
| 512 | if (! res) { | ||
| 513 | np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); | ||
| 514 | return STATE_CRITICAL; | ||
| 515 | } | ||
| 516 | 535 | ||
| 517 | if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { | 536 | if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { |
| 537 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 518 | np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); | 538 | np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); |
| 519 | return STATE_CRITICAL; | 539 | return STATE_CRITICAL; |
| 520 | } | 540 | } |
| 521 | 541 | ||
| 522 | if (dbi_result_get_numrows (res) < 1) { | 542 | if (dbi_result_get_numrows (res) < 1) { |
| 543 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 523 | printf ("WARNING - no rows returned\n"); | 544 | printf ("WARNING - no rows returned\n"); |
| 524 | return STATE_WARNING; | 545 | return STATE_WARNING; |
| 525 | } | 546 | } |
| 526 | 547 | ||
| 527 | if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { | 548 | if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { |
| 549 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 528 | np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); | 550 | np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); |
| 529 | return STATE_CRITICAL; | 551 | return STATE_CRITICAL; |
| 530 | } | 552 | } |
| 531 | 553 | ||
| 532 | if (dbi_result_get_numfields (res) < 1) { | 554 | if (dbi_result_get_numfields (res) < 1) { |
| 555 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 533 | printf ("WARNING - no fields returned\n"); | 556 | printf ("WARNING - no fields returned\n"); |
| 534 | return STATE_WARNING; | 557 | return STATE_WARNING; |
| 535 | } | 558 | } |
| 536 | 559 | ||
| 537 | if (dbi_result_first_row (res) != 1) { | 560 | if (dbi_result_first_row (res) != 1) { |
| 561 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 538 | np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); | 562 | np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); |
| 539 | return STATE_CRITICAL; | 563 | return STATE_CRITICAL; |
| 540 | } | 564 | } |
| @@ -543,20 +567,49 @@ do_query (dbi_conn conn, double *res_val, double *res_time) | |||
| 543 | if (field_type != DBI_TYPE_ERROR) | 567 | if (field_type != DBI_TYPE_ERROR) |
| 544 | val = get_field (conn, res, &field_type); | 568 | val = get_field (conn, res, &field_type); |
| 545 | 569 | ||
| 546 | gettimeofday (&timeval_end, NULL); | 570 | *res_val = val; |
| 547 | *res_time = timediff (timeval_start, timeval_end); | ||
| 548 | 571 | ||
| 549 | if (field_type == DBI_TYPE_ERROR) { | 572 | if (field_type == DBI_TYPE_ERROR) { |
| 573 | CHECK_IGNORE_ERROR (STATE_OK); | ||
| 550 | np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); | 574 | np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); |
| 551 | return STATE_CRITICAL; | 575 | return STATE_CRITICAL; |
| 552 | } | 576 | } |
| 553 | 577 | ||
| 554 | *res_val = val; | ||
| 555 | |||
| 556 | dbi_result_free (res); | 578 | dbi_result_free (res); |
| 557 | return STATE_OK; | 579 | return STATE_OK; |
| 558 | } | 580 | } |
| 559 | 581 | ||
| 582 | #undef CHECK_IGNORE_ERROR | ||
| 583 | |||
| 584 | int | ||
| 585 | do_query (dbi_conn conn, double *res_val, double *res_time) | ||
| 586 | { | ||
| 587 | dbi_result res; | ||
| 588 | |||
| 589 | struct timeval timeval_start, timeval_end; | ||
| 590 | int status = STATE_OK; | ||
| 591 | |||
| 592 | assert (np_dbi_query); | ||
| 593 | |||
| 594 | if (verbose) | ||
| 595 | printf ("Executing query '%s'\n", np_dbi_query); | ||
| 596 | |||
| 597 | gettimeofday (&timeval_start, NULL); | ||
| 598 | |||
| 599 | res = dbi_conn_query (conn, np_dbi_query); | ||
| 600 | if (! res) { | ||
| 601 | np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); | ||
| 602 | return STATE_CRITICAL; | ||
| 603 | } | ||
| 604 | |||
| 605 | status = get_query_result (conn, res, res_val); | ||
| 606 | |||
| 607 | gettimeofday (&timeval_end, NULL); | ||
| 608 | *res_time = timediff (timeval_start, timeval_end); | ||
| 609 | |||
| 610 | return status; | ||
| 611 | } | ||
| 612 | |||
| 560 | double | 613 | double |
| 561 | timediff (struct timeval start, struct timeval end) | 614 | timediff (struct timeval start, struct timeval end) |
| 562 | { | 615 | { |
