[collectd] [patch] collectd-nagios human readable input and output

daniel hilst danielhilst at gmail.com
Tue Aug 14 22:42:30 CEST 2012


collectd-nagios outputs values in absolute form, as in
# ./collectd-nagios -s ../var/run/collectd-unixsock -H $myhost -n 
df-root/df_complex-used
OKAY: 0 critical, 0 warning, 1 okay | value=30707630000.000000;;;;

I've create a patch to improve its outputs, to it prints only the 
current status and the value on human readable, like this:
# ./collectd-nagios -s ../var/run/collectd-unixsock -H $myhost -n 
df-root/df_complex-used -R
OK: 28.60 GB,

Take attetion on -R option, is new.. You can force collectd-nagios to 
print on some ratio, in megabytes for example:
# ./collectd-nagios -s ../var/run/collectd-unixsock -H $myhost -n 
df-root/df_complex-used -rm
OK: 29287.20 MB,

And you can pass suffixes to -w and -c options.. so:
# ./collectd-nagios -s ../var/run/collectd-unixsock -H $myhost -n 
df-root/df_complex-used -R -c @0:30g
CRITICAL: 28.60 GB,
# ./collectd-nagios -s ../var/run/collectd-unixsock -H $myhost -n 
df-root/df_complex-used -R -c @0:2500m
OK: 28.60 GB,

The suffixes supported are k, m and g, and they are case insensitivy

Yet... there is a bug.. -c and -w options expect a range.. so n:m.. if 
you do not pass a range to, it segfaults.. I'm working on this.. just 
need some free time to do it..

As workaround I use -c n:n instead of -c n

I hope you like, cheers!

Hilst,
-------------- next part --------------
>From f1dd868beebb4ef89e6bab619c6ea8647d57a13d Mon Sep 17 00:00:00 2001
From: Daniel Hilst <danielhilst at gmail.com>
Date: Mon, 6 Feb 2012 11:18:28 -0200
Subject: [PATCH] collectd-nagios: added support to k/m/g prefix on -w and -c
 options. Added two new options -R and -r <rate>

---
 src/collectd-nagios.c |  192 ++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 167 insertions(+), 25 deletions(-)

diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
index 88a5302..795e9f8 100644
--- a/src/collectd-nagios.c
+++ b/src/collectd-nagios.c
@@ -27,6 +27,7 @@
 # define __attribute__(x) /**/
 #endif
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -78,6 +79,7 @@
 #define CON_SUM      2
 #define CON_PERCENTAGE  3
 
+
 struct range_s
 {
 	double min;
@@ -86,6 +88,33 @@ struct range_s
 };
 typedef struct range_s range_t;
 
+struct rate_v {
+	char *name;
+	double value;
+};
+
+static struct rate_v rates[] = {
+	{ "", 1 },
+	{ " KB", 0x400 },
+	{ " MB", 0x100000 },
+	{ " GB", 0x40000000 },
+/* collectd-nagios.c:101: warning: integer constant is too large for 'long' type */
+/* 	{ " TB", 0x10000000000 },  */
+	{ NULL, 0 },
+};
+
+enum { 
+	BT_INDX,
+	KB_INDX,
+	MB_INDX,
+	GB_INDX,
+	TB_INDX,
+};
+
+static struct rate_v *rate_ptr = &rates[BT_INDX];
+/* static int rate = 1; */
+/* static char *ratestr = ""; */
+
 extern char *optarg;
 extern int optind, opterr, optopt;
 
@@ -101,6 +130,7 @@ static _Bool nan_is_error_g = 0;
 static char **match_ds_g = NULL;
 static int    match_ds_num_g = 0;
 
+
 /* `strdup' is an XSI extension. I don't want to pull in all of XSI just for
  * that, so here's an own implementation.. It's easy enough. The GCC attributes
  * are supposed to get good performance..  -octo */
@@ -117,6 +147,16 @@ static char *cn_strdup (const char *str) /* {{{ */
   return (ret);
 } /* }}} char *cn_strdup */
 
+struct rate_v *convert_rate(double n)
+{
+	struct rate_v *ptr;
+	
+	for (ptr = rates; n > 1024 && ptr->name; ptr++, n /= 1024)
+		; /* empty */
+
+	return ptr;
+}
+
 static int filter_ds (size_t *values_num,
 		double **values, char ***values_names)
 {
@@ -191,6 +231,10 @@ static void parse_range (char *string, range_t *range)
 {
 	char *min_ptr;
 	char *max_ptr;
+	int min_ptr_len;
+	int max_ptr_len;
+	long min_rate = 1;
+	long max_rate = 1;
 
 	if (*string == '@')
 	{
@@ -210,9 +254,51 @@ static void parse_range (char *string, range_t *range)
 		*max_ptr = '\0';
 		max_ptr++;
 	}
-
+	
 	assert (max_ptr != NULL);
 
+	min_ptr_len = strlen(min_ptr) - 1;
+	max_ptr_len = strlen(max_ptr) - 1;
+
+	if (isalpha(min_ptr[min_ptr_len])) {
+		switch (tolower(min_ptr[min_ptr_len])) {
+		/* case 't': */
+		/* 	min_rate = rates[TB_INDX].value; */
+		/* 	break; */
+		case 'g':
+			min_rate = rates[GB_INDX].value;
+			break;
+		case 'm':
+			min_rate = rates[MB_INDX].value;
+			break;
+		case 'k':
+			min_rate = rates[KB_INDX].value;
+			break;
+		}
+
+		min_ptr[min_ptr_len] = '\0';
+	}
+
+	if (isalpha(max_ptr[max_ptr_len])) {
+		switch (tolower(max_ptr[max_ptr_len])) {
+		/* case 't': */
+		/* 	max_rate = rates[TB_INDX].value; */
+		/* 	break; */
+		case 'g':
+			max_rate = rates[GB_INDX].value;
+			break;
+		case 'm':
+			max_rate = rates[MB_INDX].value;
+			break;
+		case 'k':
+			max_rate = rates[KB_INDX].value;
+			break;
+		}
+
+		max_ptr[max_ptr_len] = '\0';
+	}
+
+
 	/* `10' == `0:10' */
 	if (min_ptr == NULL)
 		range->min = 0.0;
@@ -220,12 +306,12 @@ static void parse_range (char *string, range_t *range)
 	else if ((*min_ptr == '\0') || (*min_ptr == '~'))
 		range->min = NAN;
 	else
-		range->min = atof (min_ptr);
+		range->min = atof (min_ptr) * min_rate;
 
 	if ((*max_ptr == '\0') || (*max_ptr == '~'))
 		range->max = NAN;
 	else
-		range->max = atof (max_ptr);
+		range->max = atof (max_ptr) * max_rate;
 } /* void parse_range */
 
 static int match_range (range_t *range, double value)
@@ -253,9 +339,11 @@ static void usage (const char *name)
 			"  -g <consol>    Method to use to consolidate several DSes.\n"
 			"                 See below for a list of valid arguments.\n"
 			"  -H <host>      Hostname to query the values for.\n"
-			"  -c <range>     Critical range\n"
-			"  -w <range>     Warning range\n"
+			"  -c <range>     Critical range. Accept k/m/g suffixes\n"
+			"  -w <range>     Warning range. Accept k/m/g suffixes\n"
 			"  -m             Treat \"Not a Number\" (NaN) as critical (default: warning)\n"
+		        "  -r <rate>      Print output in rate, m for megabytes, g for gigabytes, k for kilobytes\n"
+		        "  -R             Print output in human readable format (k/m/g)\n"
 			"\n"
 			"Consolidation functions:\n"
 			"  none:          Apply the warning- and critical-ranges to each data-source\n"
@@ -364,7 +452,7 @@ static int do_check_con_none (size_t values_num,
 	}
 	else if ((num_critical == 0) && (num_warning == 0))
 	{
-		status_str = "OKAY";
+		status_str = "OK";
 		status_code = RET_OKAY;
 	}
 	else if (num_critical == 0)
@@ -378,13 +466,17 @@ static int do_check_con_none (size_t values_num,
 		status_code = RET_CRITICAL;
 	}
 
-	printf ("%s: %i critical, %i warning, %i okay", status_str,
-			num_critical, num_warning, num_okay);
+	printf ("%s: ", status_str);
 	if (values_num > 0)
 	{
-		printf (" |");
-		for (i = 0; i < values_num; i++)
-			printf (" %s=%f;;;;", values_names[i], values[i]);
+		for (i = 0; i < values_num; i++) {
+			if (!rate_ptr) { /* -R option */
+				struct rate_v *ptr = convert_rate(values[i]);
+				printf ("%.2f%s, ", values[i] / ptr->value, ptr->name);
+			} else { /* -r option  */
+				printf ("%.2f%s, ", values[i] / rate_ptr->value, rate_ptr->name);
+			}
+		}
 	}
 	printf ("\n");
 
@@ -439,13 +531,25 @@ static int do_check_con_average (size_t values_num,
 	}
 	else
 	{
-		status_str = "OKAY";
+		status_str = "OK";
 		status_code = RET_OKAY;
 	}
 
-	printf ("%s: %g average |", status_str, average);
-	for (i = 0; i < values_num; i++)
-		printf (" %s=%f;;;;", values_names[i], values[i]);
+	if (!rate_ptr) {
+		struct rate_v *ptr = convert_rate(average);
+		printf ("%s: %.2g %s average ", status_str, average / ptr->value, ptr->name);
+  	} else {
+		printf ("%s: %.2g %s average ", status_str, average / rate_ptr->value, rate_ptr->name);
+	}
+
+	for (i = 0; i < values_num; i++) {
+		if (!rate_ptr) {
+			struct rate_v *ptr = convert_rate(values[i]);
+			printf ("%.2f%s, ", values[i] / ptr->value, ptr->name);
+		} else {
+			printf ("%.2f%s, ", values[i] / rate_ptr->value, rate_ptr->name);
+		}
+	}
 	printf ("\n");
 
 	return (status_code);
@@ -496,13 +600,25 @@ static int do_check_con_sum (size_t values_num,
 	}
 	else
 	{
-		status_str = "OKAY";
+		status_str = "OK";
 		status_code = RET_OKAY;
 	}
 
-	printf ("%s: %g sum |", status_str, total);
-	for (i = 0; i < values_num; i++)
-		printf (" %s=%f;;;;", values_names[i], values[i]);
+	if (!rate_ptr) {
+		struct rate_v *ptr = convert_rate(total);
+		printf ("%s: %.2g %s sum ", status_str, total / ptr->value, ptr->name);
+	} else {
+		printf ("%s: %.2g %s sum ", status_str, total / rate_ptr->value, rate_ptr->name);
+	}
+
+ 	for (i = 0; i < values_num; i++) {
+		if (!rate_ptr) {
+			struct rate_v *ptr = convert_rate(values[i]);
+			printf ("%.2f%s, ", values[i] / ptr->value, ptr->name);
+		} else {
+			printf ("%.2f%s, ", values[i] / rate_ptr->value, rate_ptr->name);
+		}
+	}
 	printf ("\n");
 
 	return (status_code);
@@ -559,13 +675,20 @@ static int do_check_con_percentage (size_t values_num,
 	}
 	else
 	{
-		status_str  = "OKAY";
+		status_str  = "OK";
 		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]);
+	printf ("%s: %.2lf  percent ", status_str, percentage);
+	for (i = 0; i < values_num; i++) {
+		if (!rate_ptr) {
+			struct rate_v *ptr = convert_rate(values[i]);
+			printf ("%.2lf%s, ", values[i] / ptr->value, ptr->name);
+		} else {
+			printf ("%.2lf%s, ", values[i] / rate_ptr->value, rate_ptr->name);
+		}
+	}
+	printf("\n");
 	return (status_code);
 } /* int do_check_con_percentage */
 
@@ -647,7 +770,7 @@ int main (int argc, char **argv)
 	{
 		int c;
 
-		c = getopt (argc, argv, "w:c:s:n:H:g:d:hm");
+		c = getopt (argc, argv, "w:c:s:n:H:g:d:hmr:R");
 		if (c < 0)
 			break;
 
@@ -710,7 +833,26 @@ int main (int argc, char **argv)
 			case 'm':
 				nan_is_error_g = 1;
 				break;
-			default:
+                        case 'r':
+                                switch (tolower(*optarg)) {
+				/* case 't': */
+				/* 	rate_ptr = &rates[TB_INDX]; */
+				/* 	break; */
+                                case 'g':
+					rate_ptr = &rates[GB_INDX];
+                                        break;
+                                case 'm':
+					rate_ptr = &rates[MB_INDX];
+                                        break;
+                                case 'k':
+					rate_ptr = &rates[KB_INDX];
+                                        break;
+                                }
+                                break;
+		        case 'R':
+				rate_ptr = NULL;
+				break;
+		        default:
 				usage (argv[0]);
 		} /* switch (c) */
 	}
-- 
1.7.8.4




More information about the collectd mailing list