summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/check_dbi.c127
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";
47typedef enum { 53typedef 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
52typedef struct { 59typedef 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
444double 477double
445get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) 478get_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
494int 530double
495do_query (dbi_conn conn, double *res_val, double *res_time) 531get_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
584int
585do_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
560double 613double
561timediff (struct timeval start, struct timeval end) 614timediff (struct timeval start, struct timeval end)
562{ 615{