X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fcollectd-nagios.c;h=af8744de6da58353d0c47d69381fc6acec664b7b;hb=59c7ee1cafaf53814838794908dd84f8101334c7;hp=c915791836ddd27000961f4028b968d2d6ea958e;hpb=98fef31471541485002b5b87afa8991a280190d6;p=collectd.git diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c index c9157918..af8744de 100644 --- a/src/collectd-nagios.c +++ b/src/collectd-nagios.c @@ -1,6 +1,6 @@ /** * collectd-nagios - src/collectd-nagios.c - * Copyright (C) 2008 Florian octo Forster + * Copyright (C) 2008-2010 Florian octo Forster * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,29 +19,8 @@ * Florian octo Forster **/ -/* Set to C99 and POSIX code */ -#ifndef _ISOC99_SOURCE -# define _ISOC99_SOURCE -#endif -#ifndef _POSIX_SOURCE -# define _POSIX_SOURCE -#endif -#ifndef _POSIX_C_SOURCE -# define _POSIX_C_SOURCE 200112L -#endif -#ifndef _REENTRANT -# define _REENTRANT -#endif - -/* Disable non-standard extensions */ -#ifdef _BSD_SOURCE -# undef _BSD_SOURCE -#endif -#ifdef _SVID_SOURCE -# undef _SVID_SOURCE -#endif -#ifdef _GNU_SOURCE -# undef _GNU_SOURCE +#if HAVE_CONFIG_H +# include "config.h" #endif #if !defined(__GNUC__) || !__GNUC__ @@ -56,15 +35,6 @@ #include #include -#include -#include - -#include "config.h" -#include "libcollectdclient/client.h" - -/* - * This is copied directly from collectd.h. Make changes there! - */ #if NAN_STATIC_DEFAULT # include /* #endif NAN_STATIC_DEFAULT*/ @@ -88,8 +58,16 @@ # ifndef isnan # define isnan(f) ((f) != (f)) # endif /* !defined(isnan) */ +# ifndef isfinite +# define isfinite(f) (((f) - (f)) == 0.0) +# endif +# ifndef isinf +# define isinf(f) (!isfinite(f) && !isnan(f)) +# endif #endif /* NAN_ZERO_ZERO */ +#include "libcollectdclient/client.h" + #define RET_OKAY 0 #define RET_WARNING 1 #define RET_CRITICAL 2 @@ -98,6 +76,7 @@ #define CON_NONE 0 #define CON_AVERAGE 1 #define CON_SUM 2 +#define CON_PERCENTAGE 3 struct range_s { @@ -117,6 +96,7 @@ static char *hostname_g = NULL; static range_t range_critical_g; static range_t range_warning_g; static int consolitation_g = CON_NONE; +static _Bool nan_is_error_g = 0; static char **match_ds_g = NULL; static int match_ds_num_g = 0; @@ -137,19 +117,75 @@ static char *cn_strdup (const char *str) /* {{{ */ return (ret); } /* }}} char *cn_strdup */ -static int ignore_ds (const char *name) +static int filter_ds (size_t *values_num, + double **values, char ***values_names) { - int i; + gauge_t *new_values; + char **new_names; + + size_t i; if (match_ds_g == NULL) - return (0); + return (RET_OKAY); + + new_values = (gauge_t *)calloc (match_ds_num_g, sizeof (*new_values)); + if (new_values == NULL) + { + fprintf (stderr, "malloc failed: %s\n", strerror (errno)); + return (RET_UNKNOWN); + } - for (i = 0; i < match_ds_num_g; i++) - if (strcasecmp (match_ds_g[i], name) == 0) - return (0); + new_names = (char **)calloc (match_ds_num_g, sizeof (*new_names)); + if (new_names == NULL) + { + fprintf (stderr, "malloc failed: %s\n", strerror (errno)); + free (new_values); + return (RET_UNKNOWN); + } - return (1); -} /* int ignore_ds */ + for (i = 0; i < (size_t) match_ds_num_g; i++) + { + size_t j; + + /* match_ds_g keeps pointers into argv but the names will be freed */ + new_names[i] = cn_strdup (match_ds_g[i]); + if (new_names[i] == NULL) + { + fprintf (stderr, "cn_strdup failed: %s\n", strerror (errno)); + free (new_values); + for (j = 0; j < i; j++) + free (new_names[j]); + free (new_names); + return (RET_UNKNOWN); + } + + for (j = 0; j < *values_num; j++) + if (strcasecmp (new_names[i], (*values_names)[j]) == 0) + break; + + if (j == *values_num) + { + printf ("ERROR: DS `%s' is not available.\n", new_names[i]); + free (new_values); + for (j = 0; j <= i; j++) + free (new_names[j]); + free (new_names); + return (RET_CRITICAL); + } + + new_values[i] = (*values)[j]; + } + + free (*values); + for (i = 0; i < *values_num; i++) + free ((*values_names)[i]); + free (*values_names); + + *values = new_values; + *values_names = new_names; + *values_num = match_ds_num_g; + return (RET_OKAY); +} /* int filter_ds */ static void parse_range (char *string, range_t *range) { @@ -215,10 +251,11 @@ static void usage (const char *name) " -d Select the DS to examine. May be repeated to examine multiple\n" " DSes. By default all DSes are used.\n" " -g Method to use to consolidate several DSes.\n" - " Valid arguments are `none', `average' and `sum'\n" + " See below for a list of valid arguments.\n" " -H Hostname to query the values for.\n" " -c Critical range\n" " -w Warning range\n" + " -m Treat \"Not a Number\" (NaN) as critical (default: warning)\n" "\n" "Consolidation functions:\n" " none: Apply the warning- and critical-ranges to each data-source\n" @@ -226,11 +263,13 @@ static void usage (const char *name) " average: Calculate the average of all matching DSes and apply the\n" " warning- and critical-ranges to the calculated average.\n" " sum: Apply the ranges to the sum of all DSes.\n" + " percentage: Apply the ranges to the ratio (in percent) of the first value\n" + " and the sum of all values." "\n", name); exit (1); } /* void usage */ -static int do_check_con_none (int values_num, +static int do_check_con_none (size_t values_num, double *values, char **values_names) { int num_critical = 0; @@ -238,15 +277,17 @@ static int do_check_con_none (int values_num, int num_okay = 0; const char *status_str = "UNKNOWN"; int status_code = RET_UNKNOWN; - int i; + size_t i; for (i = 0; i < values_num; i++) { - if (ignore_ds (values_names[i])) - continue; - if (isnan (values[i])) - num_warning++; + { + if (nan_is_error_g) + num_critical++; + else + num_warning++; + } else if (match_range (&range_critical_g, values[i]) != 0) num_critical++; else if (match_range (&range_warning_g, values[i]) != 0) @@ -282,17 +323,17 @@ static int do_check_con_none (int values_num, { printf (" |"); for (i = 0; i < values_num; i++) - printf (" %s=%g;;;;", values_names[i], values[i]); + printf (" %s=%f;;;;", values_names[i], values[i]); } printf ("\n"); return (status_code); } /* int do_check_con_none */ -static int do_check_con_average (int values_num, +static int do_check_con_average (size_t values_num, double *values, char **values_names) { - int i; + size_t i; double total; int total_num; double average; @@ -303,14 +344,18 @@ static int do_check_con_average (int values_num, total_num = 0; for (i = 0; i < values_num; i++) { - if (ignore_ds (values_names[i])) - continue; - - if (!isnan (values[i])) + if (isnan (values[i])) { - total += values[i]; - total_num++; + if (!nan_is_error_g) + continue; + + printf ("CRITICAL: Data source \"%s\" is NaN\n", + values_names[i]); + return (RET_CRITICAL); } + + total += values[i]; + total_num++; } if (total_num == 0) @@ -339,15 +384,16 @@ static int do_check_con_average (int values_num, printf ("%s: %g average |", status_str, average); for (i = 0; i < values_num; i++) - printf (" %s=%g;;;;", values_names[i], values[i]); + printf (" %s=%f;;;;", values_names[i], values[i]); printf ("\n"); return (status_code); } /* int do_check_con_average */ -static int do_check_con_sum (int values_num, double *values, char **values_names) +static int do_check_con_sum (size_t values_num, + double *values, char **values_names) { - int i; + size_t i; double total; int total_num; const char *status_str = "UNKNOWN"; @@ -357,14 +403,18 @@ static int do_check_con_sum (int values_num, double *values, char **values_names total_num = 0; for (i = 0; i < values_num; i++) { - if (ignore_ds (values_names[i])) - continue; - - if (!isnan (values[i])) + if (isnan (values[i])) { - total += values[i]; - total_num++; + if (!nan_is_error_g) + continue; + + printf ("CRITICAL: Data source \"%s\" is NaN\n", + values_names[i]); + return (RET_CRITICAL); } + + total += values[i]; + total_num++; } if (total_num == 0) @@ -391,12 +441,73 @@ static int do_check_con_sum (int values_num, double *values, char **values_names printf ("%s: %g sum |", status_str, total); for (i = 0; i < values_num; i++) - printf (" %s=%g;;;;", values_names[i], values[i]); + printf (" %s=%f;;;;", values_names[i], values[i]); printf ("\n"); return (status_code); } /* int do_check_con_sum */ +static int do_check_con_percentage (size_t values_num, + double *values, char **values_names) +{ + size_t i; + double sum = 0.0; + double percentage; + + const char *status_str = "UNKNOWN"; + int status_code = RET_UNKNOWN; + + if ((values_num < 1) || (isnan (values[0]))) + { + printf ("WARNING: The first value is not defined\n"); + return (RET_WARNING); + } + + for (i = 0; i < values_num; i++) + { + if (isnan (values[i])) + { + if (!nan_is_error_g) + continue; + + printf ("CRITICAL: Data source \"%s\" is NaN\n", + values_names[i]); + return (RET_CRITICAL); + } + + sum += values[i]; + } + + if (sum == 0.0) + { + printf ("WARNING: Values sum up to zero\n"); + return (RET_WARNING); + } + + percentage = 100.0 * values[0] / sum; + + if (match_range (&range_critical_g, percentage) != 0) + { + status_str = "CRITICAL"; + status_code = RET_CRITICAL; + } + else if (match_range (&range_warning_g, percentage) != 0) + { + status_str = "WARNING"; + status_code = RET_WARNING; + } + else + { + status_str = "OKAY"; + status_code = RET_OKAY; + } + + printf ("%s: %lf percent |", status_str, percentage); + for (i = 0; i < values_num; i++) + printf (" %s=%lf;;;;", values_names[i], values[i]); + return (status_code); +} /* int do_check_con_percentage */ + static int do_check (void) { lcc_connection_t *connection; @@ -447,6 +558,10 @@ static int do_check (void) LCC_DESTROY (connection); + status = filter_ds (&values_num, &values, &values_names); + if (status != RET_OKAY) + return (status); + status = RET_UNKNOWN; if (consolitation_g == CON_NONE) status = do_check_con_none (values_num, values, values_names); @@ -454,6 +569,8 @@ static int do_check (void) status = do_check_con_average (values_num, values, values_names); else if (consolitation_g == CON_SUM) status = do_check_con_sum (values_num, values, values_names); + else if (consolitation_g == CON_PERCENTAGE) + status = do_check_con_percentage (values_num, values, values_names); free (values); if (values_names != NULL) @@ -478,7 +595,7 @@ int main (int argc, char **argv) { int c; - c = getopt (argc, argv, "w:c:s:n:H:g:d:h"); + c = getopt (argc, argv, "w:c:s:n:H:g:d:hm"); if (c < 0) break; @@ -506,8 +623,14 @@ int main (int argc, char **argv) consolitation_g = CON_AVERAGE; else if (strcasecmp (optarg, "sum") == 0) consolitation_g = CON_SUM; + else if (strcasecmp (optarg, "percentage") == 0) + consolitation_g = CON_PERCENTAGE; else + { + fprintf (stderr, "Unknown consolidation function `%s'.\n", + optarg); usage (argv[0]); + } break; case 'd': { @@ -532,6 +655,9 @@ int main (int argc, char **argv) match_ds_num_g++; break; } + case 'm': + nan_is_error_g = 1; + break; default: usage (argv[0]); } /* switch (c) */ @@ -539,7 +665,10 @@ int main (int argc, char **argv) if ((socket_file_g == NULL) || (value_string_g == NULL) || (hostname_g == NULL)) + { + fprintf (stderr, "Missing required arguments.\n"); usage (argv[0]); + } return (do_check ()); } /* int main */