diff options
author | Sebastian Harl <sh@teamix.net> | 2011-04-15 12:37:21 (GMT) |
---|---|---|
committer | Sebastian Harl <sh@teamix.net> | 2012-06-06 12:10:55 (GMT) |
commit | 4ad6e441b68cca4b2f283af3f783794279fbb11c (patch) | |
tree | e87fb48e3ad12e8ddbbb984068352a0897c0c0d0 | |
parent | d7a1f2a7a08aeaaf5efd0d454b2355554a413f2b (diff) | |
download | monitoring-plugins-4ad6e441b68cca4b2f283af3f783794279fbb11c.tar.gz |
check_dbi: Added QUERY_TIME metric.
This metric checks the execution time of the specified query. In case the
query does not return any (parsable) data, this is not treated as an error
when using this metric.
-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 f009944..4a0a4d6 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 | { |