10 #include <sys/socket.h>
14 * This weird macro cascade forces the glibc to define `NAN'. I don't know
15 * another way to solve this, so more intelligent solutions are welcome. -octo
18 # define DISABLE__USE_ISOC99 1
19 # define __USE_ISOC99 1
22 #ifdef DISABLE__USE_ISOC99
23 # undef DISABLE__USE_ISOC99
29 #define RET_CRITICAL 2
42 typedef struct range_s range_t;
45 extern int optind, opterr, optopt;
47 static char *socket_file_g = NULL;
48 static char *value_string_g = NULL;
49 static char *hostname_g = NULL;
51 static range_t range_critical_g;
52 static range_t range_warning_g;
53 static int consolitation_g = CON_NONE;
55 static char **match_ds_g = NULL;
56 static int match_ds_num_g = 0;
58 static int ignore_ds (const char *name)
62 if (match_ds_g == NULL)
65 for (i = 0; i < match_ds_num_g; i++)
66 if (strcasecmp (match_ds_g[i], name) == 0)
72 static void parse_range (char *string, range_t *range)
83 max_ptr = strchr (string, ':');
96 assert (max_ptr != NULL);
101 /* :10 == ~:10 == -inf:10 */
102 else if ((*min_ptr == '\0') || (*min_ptr == '~'))
105 range->min = atof (min_ptr);
107 if ((*max_ptr == '\0') || (*max_ptr == '~'))
110 range->max = atof (max_ptr);
111 } /* void parse_range */
113 int match_range (range_t *range, double value)
117 if (!isnan (range->min) && (range->min > value))
119 if (!isnan (range->max) && (range->max < value))
122 return (((ret - range->invert) == 0) ? 0 : 1);
125 static int get_values (int *ret_values_num, double **ret_values,
126 char ***ret_values_names)
128 struct sockaddr_un sa;
140 fd = socket (PF_UNIX, SOCK_STREAM, 0);
143 fprintf (stderr, "socket failed: %s\n",
148 memset (&sa, '\0', sizeof (sa));
149 sa.sun_family = AF_UNIX;
150 strncpy (sa.sun_path, socket_file_g,
151 sizeof (sa.sun_path) - 1);
153 status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
156 fprintf (stderr, "connect failed: %s\n",
161 fh = fdopen (fd, "r+");
164 fprintf (stderr, "fdopen failed: %s\n",
170 fprintf (fh, "GETVAL %s/%s\n", hostname_g, value_string_g);
173 if (fgets (buffer, sizeof (buffer), fh) == NULL)
175 fprintf (stderr, "fgets failed: %s\n",
182 values_num = atoi (buffer);
186 values = (double *) malloc (values_num * sizeof (double));
189 fprintf (stderr, "malloc failed: %s\n",
194 values_names = (char **) malloc (values_num * sizeof (char *));
195 if (values_names == NULL)
197 fprintf (stderr, "malloc failed: %s\n",
204 char *ptr = strchr (buffer, ' ') + 1;
209 while ((key = strtok (ptr, " \t")) != NULL)
212 value = strchr (key, '=');
215 *value = '\0'; value++;
217 if (ignore_ds (key) != 0)
220 values_names[i] = strdup (key);
221 values[i] = atof (value);
230 *ret_values_num = values_num;
231 *ret_values = values;
232 *ret_values_names = values_names;
235 } /* int get_values */
237 static void usage (const char *name)
239 fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
241 "Valid options are:\n"
242 " -s <socket> Path to collectd's UNIX-socket.\n"
243 " -n <v_spec> Value specification to get from collectd.\n"
244 " Format: `plugin-instance/type-instance'\n"
245 " -d <ds> Select the DS to examine. May be repeated to examine multiple\n"
246 " DSes. By default all DSes are used.\n"
247 " -g <consol> Method to use to consolidate several DSes.\n"
248 " Valid arguments are `none', `average' and `sum'\n"
249 " -H <host> Hostname to query the values for.\n"
250 " -c <range> Critical range\n"
251 " -w <range> Warning range\n"
253 "Consolidation functions:\n"
254 " none: Apply the warning- and critical-ranges to each data-source\n"
256 " average: Calculate the average of all matching DSes and apply the\n"
257 " warning- and critical-ranges to the calculated average.\n"
258 " sum: Apply the ranges to the sum of all DSes.\n"
263 int do_check_con_none (int values_num, double *values, char **values_names)
267 int num_critical = 0;
271 for (i = 0; i < values_num; i++)
273 if (isnan (values[i]))
275 else if (match_range (&range_critical_g, values[i]) != 0)
277 else if (match_range (&range_warning_g, values[i]) != 0)
283 if ((num_critical != 0) || (values_num == 0))
285 printf ("CRITICAL: %i critical, %i warning, %i okay\n",
286 num_critical, num_warning, num_okay);
287 return (RET_CRITICAL);
289 else if (num_warning != 0)
291 printf ("WARNING: %i warning, %i okay\n",
292 num_warning, num_okay);
293 return (RET_WARNING);
297 printf ("OKAY: %i okay\n", num_okay);
301 return (RET_UNKNOWN);
302 } /* int do_check_con_none */
304 int do_check_con_average (int values_num, double *values, char **values_names)
312 for (i = 0; i < values_num; i++)
314 if (!isnan (values[i]))
323 printf ("WARNING: No defined values found\n");
324 return (RET_WARNING);
327 if (match_range (&range_critical_g, total / total_num) != 0)
329 printf ("CRITICAL: Average = %lf\n",
330 (double) (total / total_num));
331 return (RET_CRITICAL);
333 else if (match_range (&range_warning_g, total / total_num) != 0)
335 printf ("WARNING: Average = %lf\n",
336 (double) (total / total_num));
337 return (RET_WARNING);
341 printf ("OKAY: Average = %lf\n",
342 (double) (total / total_num));
346 return (RET_UNKNOWN);
347 } /* int do_check_con_average */
349 int do_check_con_sum (int values_num, double *values, char **values_names)
357 for (i = 0; i < values_num; i++)
359 if (!isnan (values[i]))
368 printf ("WARNING: No defined values found\n");
369 return (RET_WARNING);
372 if (match_range (&range_critical_g, total) != 0)
374 printf ("CRITICAL: Sum = %lf\n", total);
375 return (RET_CRITICAL);
377 else if (match_range (&range_warning_g, total) != 0)
379 printf ("WARNING: Sum = %lf\n", total);
380 return (RET_WARNING);
384 printf ("OKAY: Sum = %lf\n", total);
388 return (RET_UNKNOWN);
389 } /* int do_check_con_sum */
397 if (get_values (&values_num, &values, &values_names) != 0)
399 fputs ("ERROR: Cannot get values from daemon\n", stdout);
400 return (RET_CRITICAL);
403 if (consolitation_g == CON_NONE)
404 return (do_check_con_none (values_num, values, values_names));
405 else if (consolitation_g == CON_AVERAGE)
406 return (do_check_con_average (values_num, values, values_names));
407 else if (consolitation_g == CON_SUM)
408 return (do_check_con_sum (values_num, values, values_names));
413 return (RET_UNKNOWN);
416 int main (int argc, char **argv)
418 range_critical_g.min = NAN;
419 range_critical_g.max = NAN;
420 range_critical_g.invert = 0;
422 range_warning_g.min = NAN;
423 range_warning_g.max = NAN;
424 range_warning_g.invert = 0;
430 c = getopt (argc, argv, "w:c:s:n:H:g:d:h");
437 parse_range (optarg, &range_critical_g);
440 parse_range (optarg, &range_warning_g);
443 socket_file_g = optarg;
446 value_string_g = optarg;
452 if (strcasecmp (optarg, "none") == 0)
453 consolitation_g = CON_NONE;
454 else if (strcasecmp (optarg, "average") == 0)
455 consolitation_g = CON_AVERAGE;
456 else if (strcasecmp (optarg, "sum") == 0)
457 consolitation_g = CON_SUM;
464 tmp = (char **) realloc (match_ds_g,
469 fprintf (stderr, "realloc failed: %s\n",
471 return (RET_UNKNOWN);
474 match_ds_g[match_ds_num_g] = strdup (optarg);
475 if (match_ds_g[match_ds_num_g] == NULL)
477 fprintf (stderr, "strdup failed: %s\n",
479 return (RET_UNKNOWN);
489 if ((socket_file_g == NULL) || (value_string_g == NULL)
490 || (hostname_g == NULL))
493 return (do_check ());