8 #include <sys/socket.h>
12 * This weird macro cascade forces the glibc to define `NAN'. I don't know
13 * another way to solve this, so more intelligent solutions are welcome. -octo
16 # define DISABLE__USE_ISOC99 1
17 # define __USE_ISOC99 1
20 #ifdef DISABLE__USE_ISOC99
21 # undef DISABLE__USE_ISOC99
27 #define RET_CRITICAL 2
40 typedef struct range_s range_t;
43 extern int optind, opterr, optopt;
45 static char *socket_file_g = NULL;
46 static char *value_string_g = NULL;
47 static range_t range_critical_g;
48 static range_t range_warning_g;
49 static int consolitation_g = CON_NONE;
51 static char **match_ds_g = NULL;
52 static int match_ds_num_g = 0;
54 static int ignore_ds (const char *name)
58 if (match_ds_g == NULL)
61 for (i = 0; i < match_ds_num_g; i++)
62 if (strcasecmp (match_ds_g[i], name) == 0)
68 static void parse_range (char *string, range_t *range)
79 max_ptr = strchr (string, ':');
92 assert (max_ptr != NULL);
97 /* :10 == ~:10 == -inf:10 */
98 else if ((*min_ptr == '\0') || (*min_ptr == '~'))
101 range->min = atof (min_ptr);
103 if ((*max_ptr == '\0') || (*max_ptr == '~'))
106 range->max = atof (max_ptr);
107 } /* void parse_range */
109 int match_range (range_t *range, double value)
113 if ((range->min != NAN) && (range->min > value))
115 if ((range->max != NAN) && (range->max < value))
118 return (((ret - range->invert) == 0) ? 0 : 1);
121 static int get_values (int *ret_values_num, double **ret_values,
122 char ***ret_values_names)
124 struct sockaddr_un sa;
136 fd = socket (PF_UNIX, SOCK_STREAM, 0);
139 fprintf (stderr, "socket failed: %s\n",
144 memset (&sa, '\0', sizeof (sa));
145 sa.sun_family = AF_UNIX;
146 strncpy (sa.sun_path, socket_file_g,
147 sizeof (sa.sun_path) - 1);
149 status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
152 fprintf (stderr, "connect failed: %s\n",
157 fh = fdopen (fd, "r+");
160 fprintf (stderr, "fdopen failed: %s\n",
166 fprintf (fh, "GETVAL %s\n", value_string_g);
169 if (fgets (buffer, sizeof (buffer), fh) == NULL)
171 fprintf (stderr, "fgets failed: %s\n",
178 values_num = atoi (buffer);
182 values = (double *) malloc (values_num * sizeof (double));
185 fprintf (stderr, "malloc failed: %s\n",
190 values_names = (char **) malloc (values_num * sizeof (char *));
191 if (values_names == NULL)
193 fprintf (stderr, "malloc failed: %s\n",
200 char *ptr = strchr (buffer, ' ') + 1;
205 while ((key = strtok (ptr, " \t")) != NULL)
208 value = strchr (key, '=');
211 *value = '\0'; value++;
213 if (ignore_ds (key) != 0)
216 values_names[i] = strdup (key);
217 values[i] = atof (value);
226 *ret_values_num = values_num;
227 *ret_values = values;
228 *ret_values_names = values_names;
231 } /* int get_values */
233 static void usage (const char *name)
235 fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> [options]\n"
237 "Valid options are:\n"
238 " -s <socket> Path to collectd's UNIX-socket.\n"
239 " -n <v_spec> Value specification to get from collectd.\n"
240 " Format: `plugin-instance/type-instance'\n"
241 " -d <ds> Select the DS to examine. May be repeated to examine multiple\n"
242 " DSes. By default all DSes are used.\n"
243 " -g <consol> Method to use to consolidate several DSes.\n"
244 " Valid arguments are `none', `average' and `sum'\n"
245 " -c <range> Critical range\n"
246 " -w <range> Warning range\n"
248 "Consolidation functions:\n"
249 " none: Apply the warning- and critical-ranges to each data-source\n"
251 " average: Calculate the average of all matching DSes and apply the\n"
252 " warning- and critical-ranges to the calculated average.\n"
253 " sum: Apply the ranges to the sum of all DSes.\n"
258 int do_check_con_none (int values_num, double *values, char **values_names)
262 int num_critical = 0;
266 for (i = 0; i < values_num; i++)
268 if (values[i] == NAN)
270 else if (match_range (&range_critical_g, values[i]) != 0)
272 else if (match_range (&range_warning_g, values[i]) != 0)
278 if ((num_critical != 0) || (values_num == 0))
280 printf ("CRITICAL: %i critical, %i warning, %i okay\n",
281 num_critical, num_warning, num_okay);
282 return (RET_CRITICAL);
284 else if (num_warning != 0)
286 printf ("WARNING: %i warning, %i okay\n",
287 num_warning, num_okay);
288 return (RET_WARNING);
292 printf ("OKAY: %i okay\n", num_okay);
296 return (RET_UNKNOWN);
297 } /* int do_check_con_none */
299 int do_check_con_average (int values_num, double *values, char **values_names)
307 for (i = 0; i < values_num; i++)
309 if (values[i] != NAN)
318 printf ("WARNING: No defined values found\n");
319 return (RET_WARNING);
322 if (match_range (&range_critical_g, total / total_num) != 0)
324 printf ("CRITICAL: Average = %lf\n",
325 (double) (total / total_num));
326 return (RET_CRITICAL);
328 else if (match_range (&range_warning_g, total / total_num) != 0)
330 printf ("WARNING: Average = %lf\n",
331 (double) (total / total_num));
332 return (RET_WARNING);
336 printf ("OKAY: Average = %lf\n",
337 (double) (total / total_num));
341 return (RET_UNKNOWN);
342 } /* int do_check_con_average */
344 int do_check_con_sum (int values_num, double *values, char **values_names)
352 for (i = 0; i < values_num; i++)
354 if (values[i] != NAN)
363 printf ("WARNING: No defined values found\n");
364 return (RET_WARNING);
367 if (match_range (&range_critical_g, total) != 0)
369 printf ("CRITICAL: Sum = %lf\n", total);
370 return (RET_CRITICAL);
372 else if (match_range (&range_warning_g, total) != 0)
374 printf ("WARNING: Sum = %lf\n", total);
375 return (RET_WARNING);
379 printf ("OKAY: Sum = %lf\n", total);
383 return (RET_UNKNOWN);
384 } /* int do_check_con_sum */
392 if (get_values (&values_num, &values, &values_names) != 0)
394 fputs ("ERROR: Cannot get values from daemon\n", stdout);
395 return (RET_CRITICAL);
398 if (consolitation_g == CON_NONE)
399 return (do_check_con_none (values_num, values, values_names));
400 else if (consolitation_g == CON_AVERAGE)
401 return (do_check_con_average (values_num, values, values_names));
402 else if (consolitation_g == CON_SUM)
403 return (do_check_con_sum (values_num, values, values_names));
408 return (RET_UNKNOWN);
411 int main (int argc, char **argv)
413 range_critical_g.min = NAN;
414 range_critical_g.max = NAN;
415 range_critical_g.invert = 0;
417 range_warning_g.min = NAN;
418 range_warning_g.max = NAN;
419 range_warning_g.invert = 0;
425 c = getopt (argc, argv, "w:c:s:n:g:d:h");
432 parse_range (optarg, &range_critical_g);
435 parse_range (optarg, &range_warning_g);
438 socket_file_g = optarg;
441 value_string_g = optarg;
444 if (strcasecmp (optarg, "none") == 0)
445 consolitation_g = CON_NONE;
446 else if (strcasecmp (optarg, "average") == 0)
447 consolitation_g = CON_AVERAGE;
448 else if (strcasecmp (optarg, "sum") == 0)
449 consolitation_g = CON_SUM;
456 tmp = (char **) realloc (match_ds_g,
461 fprintf (stderr, "realloc failed: %s\n",
463 return (RET_UNKNOWN);
466 match_ds_g[match_ds_num_g] = strdup (optarg);
467 if (match_ds_g[match_ds_num_g] == NULL)
469 fprintf (stderr, "strdup failed: %s\n",
471 return (RET_UNKNOWN);
481 if ((socket_file_g == NULL) || (value_string_g == NULL))
484 return (do_check ());