10 #include <sys/socket.h>
14 * This is copied directly from collectd.h. Make changes there!
16 #if NAN_STATIC_DEFAULT
18 /* #endif NAN_STATIC_DEFAULT*/
21 # define DISABLE_ISOC99 1
22 # define __USE_ISOC99 1
23 # endif /* !defined(__USE_ISOC99) */
26 # undef DISABLE_ISOC99
28 # endif /* DISABLE_ISOC99 */
29 /* #endif NAN_STATIC_ISOC */
35 # define NAN (0.0 / 0.0)
37 # define isnan(f) ((f) != (f))
38 # endif /* !defined(isnan) */
39 #endif /* NAN_ZERO_ZERO */
43 #define RET_CRITICAL 2
56 typedef struct range_s range_t;
59 extern int optind, opterr, optopt;
61 static char *socket_file_g = NULL;
62 static char *value_string_g = NULL;
63 static char *hostname_g = NULL;
65 static range_t range_critical_g;
66 static range_t range_warning_g;
67 static int consolitation_g = CON_NONE;
69 static char **match_ds_g = NULL;
70 static int match_ds_num_g = 0;
72 static int ignore_ds (const char *name)
76 if (match_ds_g == NULL)
79 for (i = 0; i < match_ds_num_g; i++)
80 if (strcasecmp (match_ds_g[i], name) == 0)
86 static void parse_range (char *string, range_t *range)
97 max_ptr = strchr (string, ':');
110 assert (max_ptr != NULL);
115 /* :10 == ~:10 == -inf:10 */
116 else if ((*min_ptr == '\0') || (*min_ptr == '~'))
119 range->min = atof (min_ptr);
121 if ((*max_ptr == '\0') || (*max_ptr == '~'))
124 range->max = atof (max_ptr);
125 } /* void parse_range */
127 int match_range (range_t *range, double value)
131 if (!isnan (range->min) && (range->min > value))
133 if (!isnan (range->max) && (range->max < value))
136 return (((ret - range->invert) == 0) ? 0 : 1);
139 static int get_values (int *ret_values_num, double **ret_values,
140 char ***ret_values_names)
142 struct sockaddr_un sa;
145 FILE *fh_in, *fh_out;
154 fd = socket (PF_UNIX, SOCK_STREAM, 0);
157 fprintf (stderr, "socket failed: %s\n",
162 memset (&sa, '\0', sizeof (sa));
163 sa.sun_family = AF_UNIX;
164 strncpy (sa.sun_path, socket_file_g,
165 sizeof (sa.sun_path) - 1);
167 status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
170 fprintf (stderr, "connect failed: %s\n",
175 fh_in = fdopen (fd, "r");
178 fprintf (stderr, "fdopen failed: %s\n",
184 fh_out = fdopen (fd, "w");
187 fprintf (stderr, "fdopen failed: %s\n",
193 fprintf (fh_out, "GETVAL %s/%s\n", hostname_g, value_string_g);
196 if (fgets (buffer, sizeof (buffer), fh_in) == NULL)
198 fprintf (stderr, "fgets failed: %s\n",
204 fclose (fh_in); fh_in = NULL; fd = -1;
205 fclose (fh_out); fh_out = NULL;
207 values_num = atoi (buffer);
211 values = (double *) malloc (values_num * sizeof (double));
214 fprintf (stderr, "malloc failed: %s\n",
219 values_names = (char **) malloc (values_num * sizeof (char *));
220 if (values_names == NULL)
222 fprintf (stderr, "malloc failed: %s\n",
229 char *ptr = strchr (buffer, ' ') + 1;
234 while ((key = strtok (ptr, " \t")) != NULL)
237 value = strchr (key, '=');
240 *value = '\0'; value++;
242 if (ignore_ds (key) != 0)
245 values_names[i] = strdup (key);
246 values[i] = atof (value);
255 *ret_values_num = values_num;
256 *ret_values = values;
257 *ret_values_names = values_names;
260 } /* int get_values */
262 static void usage (const char *name)
264 fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
266 "Valid options are:\n"
267 " -s <socket> Path to collectd's UNIX-socket.\n"
268 " -n <v_spec> Value specification to get from collectd.\n"
269 " Format: `plugin-instance/type-instance'\n"
270 " -d <ds> Select the DS to examine. May be repeated to examine multiple\n"
271 " DSes. By default all DSes are used.\n"
272 " -g <consol> Method to use to consolidate several DSes.\n"
273 " Valid arguments are `none', `average' and `sum'\n"
274 " -H <host> Hostname to query the values for.\n"
275 " -c <range> Critical range\n"
276 " -w <range> Warning range\n"
278 "Consolidation functions:\n"
279 " none: Apply the warning- and critical-ranges to each data-source\n"
281 " average: Calculate the average of all matching DSes and apply the\n"
282 " warning- and critical-ranges to the calculated average.\n"
283 " sum: Apply the ranges to the sum of all DSes.\n"
288 int do_check_con_none (int values_num, double *values, char **values_names)
292 int num_critical = 0;
296 for (i = 0; i < values_num; i++)
298 if (isnan (values[i]))
300 else if (match_range (&range_critical_g, values[i]) != 0)
302 else if (match_range (&range_warning_g, values[i]) != 0)
308 printf ("%i critical, %i warning, %i okay",
309 num_critical, num_warning, num_okay);
313 for (i = 0; i < values_num; i++)
314 printf (" %s=%lf;;;;", values_names[i], values[i]);
318 if ((num_critical != 0) || (values_num == 0))
319 return (RET_CRITICAL);
320 else if (num_warning != 0)
321 return (RET_WARNING);
324 } /* int do_check_con_none */
326 int do_check_con_average (int values_num, double *values, char **values_names)
335 for (i = 0; i < values_num; i++)
337 if (!isnan (values[i]))
347 average = total / total_num;
348 printf ("%lf average |", average);
349 for (i = 0; i < values_num; i++)
350 printf (" %s=%lf;;;;", values_names[i], values[i]);
353 return (RET_WARNING);
356 || match_range (&range_critical_g, average))
357 return (RET_CRITICAL);
358 else if (match_range (&range_warning_g, average) != 0)
359 return (RET_WARNING);
362 } /* int do_check_con_average */
364 int do_check_con_sum (int values_num, double *values, char **values_names)
372 for (i = 0; i < values_num; i++)
374 if (!isnan (values[i]))
383 printf ("WARNING: No defined values found\n");
384 return (RET_WARNING);
387 if (match_range (&range_critical_g, total) != 0)
389 printf ("CRITICAL: Sum = %lf\n", total);
390 return (RET_CRITICAL);
392 else if (match_range (&range_warning_g, total) != 0)
394 printf ("WARNING: Sum = %lf\n", total);
395 return (RET_WARNING);
399 printf ("OKAY: Sum = %lf\n", total);
403 return (RET_UNKNOWN);
404 } /* int do_check_con_sum */
412 if (get_values (&values_num, &values, &values_names) != 0)
414 fputs ("ERROR: Cannot get values from daemon\n", stdout);
415 return (RET_CRITICAL);
418 if (consolitation_g == CON_NONE)
419 return (do_check_con_none (values_num, values, values_names));
420 else if (consolitation_g == CON_AVERAGE)
421 return (do_check_con_average (values_num, values, values_names));
422 else if (consolitation_g == CON_SUM)
423 return (do_check_con_sum (values_num, values, values_names));
426 free (values_names); /* FIXME? */
428 return (RET_UNKNOWN);
431 int main (int argc, char **argv)
433 range_critical_g.min = NAN;
434 range_critical_g.max = NAN;
435 range_critical_g.invert = 0;
437 range_warning_g.min = NAN;
438 range_warning_g.max = NAN;
439 range_warning_g.invert = 0;
445 c = getopt (argc, argv, "w:c:s:n:H:g:d:h");
452 parse_range (optarg, &range_critical_g);
455 parse_range (optarg, &range_warning_g);
458 socket_file_g = optarg;
461 value_string_g = optarg;
467 if (strcasecmp (optarg, "none") == 0)
468 consolitation_g = CON_NONE;
469 else if (strcasecmp (optarg, "average") == 0)
470 consolitation_g = CON_AVERAGE;
471 else if (strcasecmp (optarg, "sum") == 0)
472 consolitation_g = CON_SUM;
479 tmp = (char **) realloc (match_ds_g,
484 fprintf (stderr, "realloc failed: %s\n",
486 return (RET_UNKNOWN);
489 match_ds_g[match_ds_num_g] = strdup (optarg);
490 if (match_ds_g[match_ds_num_g] == NULL)
492 fprintf (stderr, "strdup failed: %s\n",
494 return (RET_UNKNOWN);
504 if ((socket_file_g == NULL) || (value_string_g == NULL)
505 || (hostname_g == NULL))
508 return (do_check ());