summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Harl <sh@teamix.net>2011-04-15 14:37:21 +0200
committerSebastian Harl <sh@teamix.net>2012-06-06 14:10:55 +0200
commit4ad6e441b68cca4b2f283af3f783794279fbb11c (patch)
treee87fb48e3ad12e8ddbbb984068352a0897c0c0d0
parentd7a1f2a7a08aeaaf5efd0d454b2355554a413f2b (diff)
downloadmonitoring-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.c127
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";
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{