Code

b86686d728116c4375f89612bac787fa0f7e3af2
[nagiosplug.git] / plugins / check_mrtg.c
1 /******************************************************************************
2  *
3  * Program: MRTG (Multi-Router Traffic Grapher) generic plugin for Nagios
4  * License: GPL
5  *
6  * License Information:
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * $Id$
23  *
24  *****************************************************************************/
26 #define PROGNAME "check_mrtg"
27 #define REVISION "$Revision$"
28 #define COPYRIGHT "Copyright (c) 1999-2001 Ethan Galstad"
30 #define SUMMARY "\
31 This plugin will check either the average or maximum value of one of the\n\
32 two variables recorded in an MRTG log file.\n"
34 /* old command line: 
35          <log_file> <expire_minutes> <AVG|MAX> <variable> <vwl> <vcl> <label> [units] */
36 #define OPTIONS "\
37 -F log_file -a <AVG | MAX> -v variable -w warning -c critical\n\
38             [-l label] [-u units] [-e expire_minutes] [-t timeout] [-v]"
40 #define LONGOPTIONS "\
41  -F, --logfile=FILE\n\
42    The MRTG log file containing the data you want to monitor\n\
43  -e, --expires=MINUTES\n\
44    Minutes before MRTG data is considered to be too old\n\
45  -a, --aggregation=AVG|MAX\n\
46    Should we check average or maximum values?\n\
47  -v, --variable=INTEGER\n\
48    Which variable set should we inspect? 1 or 2?\n\
49  -w, --warning=INTEGER\n\
50    Threshold value for data to result in WARNING status\n\
51  -c, --critical=INTEGER\n\
52    Threshold value for data to result in CRITICAL status\n\
53  -l, --label=STRING\n\
54    Type label for data (Examples: Conns, \"Processor Load\", In, Out)\n\
55  -u, --units=STRING\n\
56    Option units label for data (Example: Packets/Sec, Errors/Sec, \n\
57    \"Bytes Per Second\", \"%% Utilization\")\n\
58  -h, --help\n\
59    Print detailed help screen\n\
60  -V, --version\n\
61    Print version information\n"
63 #define DESCRIPTION "\
64 If the value exceeds the <vwl> threshold, a WARNING status is returned.  If\n\
65 the value exceeds the <vcl> threshold, a CRITICAL status is returned.  If\n\
66 the data in the log file is older than <expire_minutes> old, a WARNING\n\
67 status is returned and a warning message is printed.\n\
68 \n\
69 This plugin is useful for monitoring MRTG data that does not correspond to\n\
70 bandwidth usage.  (Use the check_mrtgtraf plugin for monitoring bandwidth).\n\
71 It can be used to monitor any kind of data that MRTG is monitoring - errors,\n\
72 packets/sec, etc.  I use MRTG in conjuction with the Novell NLM that allows\n\
73 me to track processor utilization, user connections, drive space, etc and\n\
74 this plugin works well for monitoring that kind of data as well.\n\
75 \n\
76 Notes:\n\
77 - This plugin only monitors one of the two variables stored in the MRTG log\n\
78   file.  If you want to monitor both values you will have to define two\n\
79   commands with different values for the <variable> argument.  Of course,\n\
80   you can always hack the code to make this plugin work for you...\n\
81 - MRTG stands for the Multi Router Traffic Grapher.  It can be downloaded from\n\
82   http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html\n"
84 #include "config.h"
85 #include "common.h"
86 #include "utils.h"
88 int process_arguments (int, char **);
89 int call_getopt (int, char **);
90 int validate_arguments (void);
91 void print_help (void);
92 void print_usage (void);
94 char *log_file = NULL;
95 int expire_minutes = 0;
96 int use_average = TRUE;
97 int variable_number = -1;
98 unsigned long value_warning_threshold = 0L;
99 unsigned long value_critical_threshold = 0L;
100 char *value_label = NULL;
101 char *units_label = NULL;
103 int
104 main (int argc, char **argv)
106         int result = STATE_OK;
107         FILE *fp;
108         int line;
109         char input_buffer[MAX_INPUT_BUFFER];
110         char *temp_buffer;
111         time_t current_time;
112         char error_message[MAX_INPUT_BUFFER];
113         time_t timestamp = 0L;
114         unsigned long average_value_rate = 0L;
115         unsigned long maximum_value_rate = 0L;
116         unsigned long value_rate = 0L;
118         if (process_arguments (argc, argv) != OK)
119                 usage ("Invalid command arguments supplied\n");
121         /* open the MRTG log file for reading */
122         fp = fopen (log_file, "r");
123         if (fp == NULL) {
124                 printf ("Unable to open MRTG log file\n");
125                 return STATE_UNKNOWN;
126         }
128         line = 0;
129         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
131                 line++;
133                 /* skip the first line of the log file */
134                 if (line == 1)
135                         continue;
137                 /* break out of read loop if we've passed the number of entries we want to read */
138                 if (line > 2)
139                         break;
141                 /* grab the timestamp */
142                 temp_buffer = strtok (input_buffer, " ");
143                 timestamp = strtoul (temp_buffer, NULL, 10);
145                 /* grab the average value 1 rate */
146                 temp_buffer = strtok (NULL, " ");
147                 if (variable_number == 1)
148                         average_value_rate = strtoul (temp_buffer, NULL, 10);
150                 /* grab the average value 2 rate */
151                 temp_buffer = strtok (NULL, " ");
152                 if (variable_number == 2)
153                         average_value_rate = strtoul (temp_buffer, NULL, 10);
155                 /* grab the maximum value 1 rate */
156                 temp_buffer = strtok (NULL, " ");
157                 if (variable_number == 1)
158                         maximum_value_rate = strtoul (temp_buffer, NULL, 10);
160                 /* grab the maximum value 2 rate */
161                 temp_buffer = strtok (NULL, " ");
162                 if (variable_number == 2)
163                         maximum_value_rate = strtoul (temp_buffer, NULL, 10);
164         }
166         /* close the log file */
167         fclose (fp);
169         /* if we couldn't read enough data, return an unknown error */
170         if (line <= 2) {
171                 result = STATE_UNKNOWN;
172                 sprintf (error_message, "Unable to process MRTG log file\n");
173         }
175         /* make sure the MRTG data isn't too old */
176         if (result == STATE_OK) {
177                 time (&current_time);
178                 if (expire_minutes > 0
179                                 && (current_time - timestamp) > (expire_minutes * 60)) {
180                         result = STATE_WARNING;
181                         sprintf (error_message, "MRTG data has expired (%d minutes old)\n",
182                                                          (int) ((current_time - timestamp) / 60));
183                 }
184         }
186         /* else check the incoming/outgoing rates */
187         if (result == STATE_OK) {
189                 if (use_average == TRUE)
190                         value_rate = average_value_rate;
191                 else
192                         value_rate = maximum_value_rate;
194                 if (value_rate > value_critical_threshold)
195                         result = STATE_CRITICAL;
196                 else if (value_rate > value_warning_threshold)
197                         result = STATE_WARNING;
198         }
200         sprintf (error_message, "%s. %s = %lu %s",
201                                          (use_average == TRUE) ? "Ave" : "Max", value_label, value_rate,
202                                          units_label);
203         printf ("%s\n", error_message);
205         return result;
212 /* process command-line arguments */
213 int
214 process_arguments (int argc, char **argv)
216         int c;
218         if (argc < 2)
219                 return ERROR;
221         for (c = 1; c < argc; c++) {
222                 if (strcmp ("-to", argv[c]) == 0)
223                         strcpy (argv[c], "-t");
224                 else if (strcmp ("-wt", argv[c]) == 0)
225                         strcpy (argv[c], "-w");
226                 else if (strcmp ("-ct", argv[c]) == 0)
227                         strcpy (argv[c], "-c");
228         }
232         c = 0;
233         while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
235                 if (is_option (argv[c]))
236                         continue;
238                 if (log_file == NULL) {
239                         log_file = argv[c];
240                 }
241                 else if (expire_minutes <= 0) {
242                         if (is_intpos (argv[c]))
243                                 expire_minutes = atoi (argv[c]);
244                         else
245                                 terminate (STATE_UNKNOWN,
246                                                                          "%s is not a valid expiration time\nUse '%s -h' for additional help\n",
247                                                                          argv[c], PROGNAME);
248                 }
249                 else if (strcmp (argv[c], "MAX") == 0) {
250                         use_average = FALSE;
251                 }
252                 else if (strcmp (argv[c], "AVG") == 0) {
253                         use_average = TRUE;
254                 }
255                 else if (variable_number == -1) {
256                         variable_number = atoi (argv[c]);
257                         if (variable_number < 1 || variable_number > 2) {
258                                 printf ("%s :", argv[c]);
259                                 usage ("Invalid variable number\n");
260                         }
261                 }
262                 else if (value_warning_threshold == 0) {
263                         value_warning_threshold = strtoul (argv[c], NULL, 10);
264                 }
265                 else if (value_critical_threshold == 0) {
266                         value_critical_threshold = strtoul (argv[c], NULL, 10);
267                 }
268                 else if (value_label == NULL) {
269                         value_label = argv[c];
270                 }
271                 else if (units_label == NULL) {
272                         units_label = argv[c];
273                 }
274         }
276         if (value_label == NULL)
277                 value_label = strscpy (NULL, "");
279         if (units_label == NULL)
280                 units_label = strscpy (NULL, "");
282         return validate_arguments ();
290 int
291 call_getopt (int argc, char **argv)
293         int c, i = 0;
295 #ifdef HAVE_GETOPT_H
296         int option_index = 0;
297         static struct option long_options[] = {
298                 {"logfile", required_argument, 0, 'F'},
299                 {"expires", required_argument, 0, 'e'},
300                 {"aggregation", required_argument, 0, 'a'},
301                 {"variable", required_argument, 0, 'v'},
302                 {"critical", required_argument, 0, 'c'},
303                 {"warning", required_argument, 0, 'w'},
304                 {"label", required_argument, 0, 'l'},
305                 {"units", required_argument, 0, 'u'},
306                 {"verbose", no_argument, 0, 'v'},
307                 {"version", no_argument, 0, 'V'},
308                 {"help", no_argument, 0, 'h'},
309                 {0, 0, 0, 0}
310         };
311 #endif
313         while (1) {
314 #ifdef HAVE_GETOPT_H
315                 c =
316                         getopt_long (argc, argv, "+hVF:e:a:v:c:w:l:u:", long_options,
317                                                                          &option_index);
318 #else
319                 c = getopt (argc, argv, "+?hVF:e:a:v:c:w:l:u:");
320 #endif
322                 i++;
324                 if (c == -1 || c == EOF || c == 1)
325                         break;
327                 switch (c) {
328                 case 'F':
329                 case 'e':
330                 case 'a':
331                 case 'v':
332                 case 'c':
333                 case 'w':
334                 case 'l':
335                 case 'u':
336                         i++;
337                 }
339                 switch (c) {
340                 case 'F':                                                                       /* input file */
341                         log_file = optarg;
342                         break;
343                 case 'e':                                                                       /* ups name */
344                         expire_minutes = atoi (optarg);
345                         break;
346                 case 'a':                                                                       /* port */
347                         if (!strcmp (optarg, "MAX"))
348                                 use_average = FALSE;
349                         else
350                                 use_average = TRUE;
351                         break;
352                 case 'v':
353                         variable_number = atoi (optarg);
354                         if (variable_number < 1 || variable_number > 2)
355                                 usage ("Invalid variable number\n");
356                         break;
357                 case 'w':                                                                       /* critical time threshold */
358                         value_warning_threshold = strtoul (optarg, NULL, 10);
359                         break;
360                 case 'c':                                                                       /* warning time threshold */
361                         value_critical_threshold = strtoul (optarg, NULL, 10);
362                         break;
363                 case 'l':                                                                       /* label */
364                         value_label = optarg;
365                         break;
366                 case 'u':                                                                       /* timeout */
367                         units_label = optarg;
368                         break;
369                 case 'V':                                                                       /* version */
370                         print_revision (PROGNAME, "$Revision$");
371                         exit (STATE_OK);
372                 case 'h':                                                                       /* help */
373                         print_help ();
374                         exit (STATE_OK);
375                 case '?':                                                                       /* help */
376                         usage ("Invalid argument\n");
377                 }
378         }
379         return i;
382 int
383 validate_arguments (void)
385         if (variable_number == -1)
386                 usage ("You must supply the variable number\n");
388         return OK;
391 void
392 print_help (void)
394         print_revision (PROGNAME, REVISION);
395         printf ("%s\n\n%s\n", COPYRIGHT, SUMMARY);
396         print_usage ();
397         printf ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n");
398         support ();
401 void
402 print_usage (void)
404         printf ("Usage:\n" " %s %s\n"
405 #ifdef HAVE_GETOPT_H
406                                         " %s (-h | --help) for detailed help\n"
407                                         " %s (-V | --version) for version information\n",
408 #else
409                                         " %s -h for detailed help\n"
410                                         " %s -V for version information\n",
411 #endif
412                                         PROGNAME, OPTIONS, PROGNAME, PROGNAME);