Code

4d297aaa1f70f20293c1bff3da26e3b6fd912e65
[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 validate_arguments (void);
90 void print_help (void);
91 void print_usage (void);
93 char *log_file = NULL;
94 int expire_minutes = 0;
95 int use_average = TRUE;
96 int variable_number = -1;
97 unsigned long value_warning_threshold = 0L;
98 unsigned long value_critical_threshold = 0L;
99 char *value_label = "";
100 char *units_label = "";
102 int
103 main (int argc, char **argv)
105         int result = STATE_OK;
106         FILE *fp;
107         int line;
108         char input_buffer[MAX_INPUT_BUFFER];
109         char *temp_buffer;
110         time_t current_time;
111         char error_message[MAX_INPUT_BUFFER];
112         time_t timestamp = 0L;
113         unsigned long average_value_rate = 0L;
114         unsigned long maximum_value_rate = 0L;
115         unsigned long value_rate = 0L;
117         if (process_arguments (argc, argv) != OK)
118                 usage ("Invalid command arguments supplied\n");
120         /* open the MRTG log file for reading */
121         fp = fopen (log_file, "r");
122         if (fp == NULL) {
123                 printf ("Unable to open MRTG log file\n");
124                 return STATE_UNKNOWN;
125         }
127         line = 0;
128         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
130                 line++;
132                 /* skip the first line of the log file */
133                 if (line == 1)
134                         continue;
136                 /* break out of read loop if we've passed the number of entries we want to read */
137                 if (line > 2)
138                         break;
140                 /* grab the timestamp */
141                 temp_buffer = strtok (input_buffer, " ");
142                 timestamp = strtoul (temp_buffer, NULL, 10);
144                 /* grab the average value 1 rate */
145                 temp_buffer = strtok (NULL, " ");
146                 if (variable_number == 1)
147                         average_value_rate = strtoul (temp_buffer, NULL, 10);
149                 /* grab the average value 2 rate */
150                 temp_buffer = strtok (NULL, " ");
151                 if (variable_number == 2)
152                         average_value_rate = strtoul (temp_buffer, NULL, 10);
154                 /* grab the maximum value 1 rate */
155                 temp_buffer = strtok (NULL, " ");
156                 if (variable_number == 1)
157                         maximum_value_rate = strtoul (temp_buffer, NULL, 10);
159                 /* grab the maximum value 2 rate */
160                 temp_buffer = strtok (NULL, " ");
161                 if (variable_number == 2)
162                         maximum_value_rate = strtoul (temp_buffer, NULL, 10);
163         }
165         /* close the log file */
166         fclose (fp);
168         /* if we couldn't read enough data, return an unknown error */
169         if (line <= 2) {
170                 result = STATE_UNKNOWN;
171                 sprintf (error_message, "Unable to process MRTG log file\n");
172         }
174         /* make sure the MRTG data isn't too old */
175         if (result == STATE_OK) {
176                 time (&current_time);
177                 if (expire_minutes > 0
178                                 && (current_time - timestamp) > (expire_minutes * 60)) {
179                         result = STATE_WARNING;
180                         sprintf (error_message, "MRTG data has expired (%d minutes old)\n",
181                                                          (int) ((current_time - timestamp) / 60));
182                 }
183         }
185         /* else check the incoming/outgoing rates */
186         if (result == STATE_OK) {
188                 if (use_average == TRUE)
189                         value_rate = average_value_rate;
190                 else
191                         value_rate = maximum_value_rate;
193                 if (value_rate > value_critical_threshold)
194                         result = STATE_CRITICAL;
195                 else if (value_rate > value_warning_threshold)
196                         result = STATE_WARNING;
197         }
199         sprintf (error_message, "%s. %s = %lu %s",
200                                          (use_average == TRUE) ? "Ave" : "Max", value_label, value_rate,
201                                          units_label);
202         printf ("%s\n", error_message);
204         return result;
211 /* process command-line arguments */
212 int
213 process_arguments (int argc, char **argv)
215         int c;
217 #ifdef HAVE_GETOPT_H
218         int option_index = 0;
219         static struct option long_options[] = {
220                 {"logfile", required_argument, 0, 'F'},
221                 {"expires", required_argument, 0, 'e'},
222                 {"aggregation", required_argument, 0, 'a'},
223                 {"variable", required_argument, 0, 'v'},
224                 {"critical", required_argument, 0, 'c'},
225                 {"warning", required_argument, 0, 'w'},
226                 {"label", required_argument, 0, 'l'},
227                 {"units", required_argument, 0, 'u'},
228                 {"verbose", no_argument, 0, 'v'},
229                 {"version", no_argument, 0, 'V'},
230                 {"help", no_argument, 0, 'h'},
231                 {0, 0, 0, 0}
232         };
233 #endif
235         if (argc < 2)
236                 return ERROR;
238         for (c = 1; c < argc; c++) {
239                 if (strcmp ("-to", argv[c]) == 0)
240                         strcpy (argv[c], "-t");
241                 else if (strcmp ("-wt", argv[c]) == 0)
242                         strcpy (argv[c], "-w");
243                 else if (strcmp ("-ct", argv[c]) == 0)
244                         strcpy (argv[c], "-c");
245         }
247         while (1) {
248 #ifdef HAVE_GETOPT_H
249                 c =
250                         getopt_long (argc, argv, "hVF:e:a:v:c:w:l:u:", long_options,
251                                                                          &option_index);
252 #else
253                 c = getopt (argc, argv, "hVF:e:a:v:c:w:l:u:");
254 #endif
256                 if (c == -1 || c == EOF)
257                         break;
259                 switch (c) {
260                 case 'F':                                                                       /* input file */
261                         log_file = optarg;
262                         break;
263                 case 'e':                                                                       /* ups name */
264                         expire_minutes = atoi (optarg);
265                         break;
266                 case 'a':                                                                       /* port */
267                         if (!strcmp (optarg, "MAX"))
268                                 use_average = FALSE;
269                         else
270                                 use_average = TRUE;
271                         break;
272                 case 'v':
273                         variable_number = atoi (optarg);
274                         if (variable_number < 1 || variable_number > 2)
275                                 usage ("Invalid variable number\n");
276                         break;
277                 case 'w':                                                                       /* critical time threshold */
278                         value_warning_threshold = strtoul (optarg, NULL, 10);
279                         break;
280                 case 'c':                                                                       /* warning time threshold */
281                         value_critical_threshold = strtoul (optarg, NULL, 10);
282                         break;
283                 case 'l':                                                                       /* label */
284                         value_label = optarg;
285                         break;
286                 case 'u':                                                                       /* timeout */
287                         units_label = optarg;
288                         break;
289                 case 'V':                                                                       /* version */
290                         print_revision (PROGNAME, REVISION);
291                         exit (STATE_OK);
292                 case 'h':                                                                       /* help */
293                         print_help ();
294                         exit (STATE_OK);
295                 case '?':                                                                       /* help */
296                         usage ("Invalid argument\n");
297                 }
298         }
300         c = optind;
301         if (log_file == NULL && argc > c) {
302                 log_file = argv[c++];
303         }
305         if (expire_minutes <= 0 && argc > c) {
306                 if (is_intpos (argv[c]))
307                         expire_minutes = atoi (argv[c++]);
308                 else
309                         terminate (STATE_UNKNOWN,
310                                    "%s is not a valid expiration time\nUse '%s -h' for additional help\n",
311                                    argv[c], PROGNAME);
312         }
314         if (argc > c && strcmp (argv[c], "MAX") == 0) {
315                 use_average = FALSE;
316                 c++;
317         }
318         else if (argc > c && strcmp (argv[c], "AVG") == 0) {
319                 use_average = TRUE;
320                 c++;
321         }
323         if (argc > c && variable_number == -1) {
324                 variable_number = atoi (argv[c++]);
325                 if (variable_number < 1 || variable_number > 2) {
326                         printf ("%s :", argv[c]);
327                         usage ("Invalid variable number\n");
328                 }
329         }
331         if (argc > c && value_warning_threshold == 0) {
332                 value_warning_threshold = strtoul (argv[c++], NULL, 10);
333         }
335         if (vargc > c && alue_critical_threshold == 0) {
336                 value_critical_threshold = strtoul (argv[c++], NULL, 10);
337         }
339         if (argc > c && strlen (value_label) == 0) {
340                 value_label = argv[c++];
341         }
343         if (argc > c && strlen (units_label) == 0) {
344                 units_label = argv[c++];
345         }
347         return validate_arguments ();
350 int
351 validate_arguments (void)
353         if (variable_number == -1)
354                 usage ("You must supply the variable number\n");
356         return OK;
359 void
360 print_help (void)
362         print_revision (PROGNAME, REVISION);
363         printf ("%s\n\n%s\n", COPYRIGHT, SUMMARY);
364         print_usage ();
365         printf ("\nOptions:\n" LONGOPTIONS "\n" DESCRIPTION "\n");
366         support ();
369 void
370 print_usage (void)
372         printf ("Usage:\n" " %s %s\n"
373 #ifdef HAVE_GETOPT_H
374                                         " %s (-h | --help) for detailed help\n"
375                                         " %s (-V | --version) for version information\n",
376 #else
377                                         " %s -h for detailed help\n"
378                                         " %s -V for version information\n",
379 #endif
380                                         PROGNAME, OPTIONS, PROGNAME, PROGNAME);