/[nagios-plugins-perl]/trunk/plugins/check_application_en.pl
ViewVC logotype

Contents of /trunk/plugins/check_application_en.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 121 - (show annotations) (download)
Thu Nov 12 13:29:04 2009 UTC (11 years ago) by racvision
File MIME type: text/plain
File size: 11303 byte(s)
convert source structure from autotools to rpm-build.sh
1 #!/usr/bin/perl -w
2 #
3 # Copyright (c) 2002-2008 St├ęphane Urbanovski <stephane.urbanovski@ac-nancy-metz.fr>
4 #
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty
12 # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # you should have received a copy of the GNU General Public License
16 # along with this program (or with Nagios); if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA
19 #
20 # $Id: check_application_en.pl,v 1.20 2008-10-28 15:43:46 uid5000 Exp $
21
22 use strict; # should never be differently :-)
23 use warnings;
24
25 use File::Basename; # get basename()
26 use lib dirname($0); # to get local libs
27 use libplugins qw(%EXIT_CODES %ERR_LEVELS &showUsage &showVersion);
28
29 use LWP::UserAgent; # http client
30 use HTTP::Request; # used by LWP::UserAgent
31 use HTTP::Status; # to get http err msg
32
33 use POSIX qw(mktime);
34 use Unicode::String qw(latin1 utf8); # Convert between iso-8859-1 and utf-8
35 use Time::HiRes; # get microtime
36
37 use XML::XQL; # xml parser
38 use XML::XQL::DOM;
39
40 #use Data::Dumper; # debug tool
41
42
43 # Return codes used in xml test page
44 my %RETURN_CODE_VALUES = (
45 'UNKNOWN' => 1,
46 'OK' => 0,
47 'WARN' => 2,
48 'CRIT' => 3,
49 'MAINT' => 4
50 );
51
52 my $DEBUG=0;
53
54 # Default values :
55 my %DEFVALUES = (
56 'TIMEOUT' => {
57 'v' => 30,
58 'desc' => _("HTTP connection timeout"),
59 },
60 'VERSION' => {
61 'v' => "3.2",
62 'desc' => _("Plugin Version"),
63 },
64 'TIME_WARNING' => {
65 'v' => 5,
66 'desc' => _("Response time warning level"),
67 },
68 'TIME_CRITICAL' => {
69 'v' => 15,
70 'desc' => _("Response time critical level"),
71 },
72 );
73
74
75 # Get arguments :
76 use vars qw( $opt_V $opt_h $opt_m $url $opt_v $opt_w $opt_c $opt_perf $opt_encoding);
77
78 Getopt::Long::GetOptions (
79 "V|version" => \$opt_V,
80 "h|?" => \$opt_h, "help|man" => \$opt_m,
81 "d" => \$DEBUG, "debug=i" => \$DEBUG,
82 "v|verbose" => \$opt_v,
83
84 "w=i" => \$opt_w, "warning=i" => \$opt_w,
85 "c=i" => \$opt_c, "critical=i" => \$opt_c,
86 "perf" => \$opt_perf,
87 "u=s" => \$url, "url=s" => \$url,
88 "encoding:s" => \$opt_encoding,
89 );
90
91 my $state = 'UNKNOWN';
92 my $answer = '';
93 my $details = '';
94
95 if ( defined ($opt_h) || defined ($opt_m) ) {
96 &showUsage($opt_m,\%DEFVALUES);
97 }
98 if ( defined ($opt_V) ) {
99 &showVersion($DEFVALUES{'VERSION'}{'v'});
100 }
101
102 if ( (!defined ($url)) || ($url eq "")) {
103 print _("Missing <url> parameter !")."\n";
104 &showUsage($opt_m);
105 exit $EXIT_CODES{$state};
106 }
107
108 if ( !defined ($opt_encoding) ) {
109 $opt_encoding='';
110 }
111
112 # Set default values :
113 $opt_w = $opt_w || $DEFVALUES{'TIME_WARNING'}{'v'};
114 $opt_c = $opt_c || $DEFVALUES{'TIME_CRITICAL'}{'v'};
115
116 # Create a LWP user agent object:
117 my $ua = new LWP::UserAgent(
118 'env_proxy' => 0,
119 'timeout' => $DEFVALUES{'TIMEOUT'}{'v'}
120 );
121 $ua->agent(basename($0));
122
123 # Workaround for LWP bug :
124 $ua->parse_head(0);
125
126 if ( defined($ENV{'http_proxy'}) ) {
127 # Normal http proxy :
128 $ua->proxy(['http'], $ENV{'http_proxy'});
129 # Https must use Crypt::SSLeay https proxy (to use CONNECT method instead of GET)
130 $ENV{'HTTPS_PROXY'} = $ENV{'http_proxy'};
131 }
132
133 # Build and submit an http request :
134 my $request = HTTP::Request->new('GET', $url);
135 my $timer = Time::HiRes::time();
136 my $http_response = $ua->request( $request );
137 $timer = Time::HiRes::time()-$timer;
138
139 my $perf = sprintf('t=%.3fs;%i;%i;0;%i',$timer,$opt_w,$opt_c,$DEFVALUES{'TIMEOUT'}{'v'});
140
141 if ( $http_response->is_success() ) {
142
143 # Get xml content ...
144 my $xml = $http_response->content;
145 if ($DEBUG) {
146 print "------------------===http output===------------------\n$xml\n-----------------------------------------------------\n";
147 print "t=".$timer."s\n";
148 };
149
150 # Remove DOCTYPE and new lines:
151 $xml =~ s/\<\!DOCTYPE .*\>// ;
152 my $fxml = '';
153 foreach ( split("[\r\n]+",$xml) ) {
154 s/^\s+//;
155 $fxml .= $_;
156 }
157 $xml = $fxml ;
158
159 if ($DEBUG) {
160 print "------------------===sanitized===------------------\n$xml\n-----------------------------------------------------\n";
161 };
162
163 # Get XML tools:
164 my $parser;
165
166 # Manage encoding :
167 if ( $opt_encoding eq 'iso-8859-1' || $opt_encoding eq 'iso-8859-15') {
168 # transcode iso-8859-1 to utf8 :
169 my $tmp = latin1($xml);
170 $xml = $tmp->utf8;
171 $parser = new XML::DOM::Parser (
172 'ProtocolEncoding' => 'utf-8',
173 );
174
175 } else {
176 $parser = new XML::DOM::Parser ();
177 }
178
179 #Force xml output to utf-8
180 utf8::upgrade($xml);
181
182 my $xql;
183 if ( $xml !~ /^<\?xml/) {
184 $state = 'UNKNOWN';
185 $answer = _("Not an xml file !");
186
187 } elsif ( eval { $xql = $parser->parse($xml); } ) {
188
189 # print Dumper($parser);print "\n\n";
190
191 my $max_state_level = -1;
192
193 my $app_name = &getFirstValue($xql,'/apptest/application/name') || '('._("no name").')';
194 my $app_version = &getFirstValue($xql,'/apptest/application/version') || '('._("no version").')';
195
196 if ($DEBUG) { print 'DEBUG:'." name[".$app_name."] - version[$app_version]\n"; };
197
198 my @ns = $xql->xql('/apptest/application/test');
199 my $nbtest = $#ns+1;
200 if ( $nbtest ) {
201 for ( my $i = 0 ; $i < $nbtest ; $i++ ) {
202 my $id = &getFirstValue($ns[$i],"/apptest/application/test[$i]/\@id") || $i;
203 my $description = &getFirstValue($ns[$i],"/apptest/application/test[$i]/description") || '('._("no description").')';
204 my $state = &getFirstValue($ns[$i],"/apptest/application/test[$i]/state/\@val") || 'UNKNOWN';
205 my $msg = &getFirstValue($ns[$i],"/apptest/application/test[$i]/state") || '('._("no msg").')';
206 my $value = &getFirstValue($ns[$i],"/apptest/application/test[$i]/value");
207 my $unit = &getFirstValue($ns[$i],"/apptest/application/test[$i]/value/\@unit")|| '';
208
209 if ( defined($value) && $value =~ /^[\d\.]+$/ ) {
210 $perf .= ' V'.$id.'='.$value.$unit.';;;;';
211 } else {
212 $value = '';
213 }
214
215 if ( !exists($RETURN_CODE_VALUES{$state}) ) {
216 print "ERROR: Unknown state [$state] !\n";
217 $state = 'UNKNOWN';
218 }
219 if ($DEBUG) {
220 print 'DEBUG:'.$i."/$nbtest ) id =[$id] - description[".$description."] - state[$state] - msg[$msg]\n";
221 print 'DEBUG: value['.$value."] - unit[$unit]\n";
222 };
223
224 if ( ("$state" ne 'OK') || $opt_v ) {
225 $details .= '<br /> '.sprintf(_("%s - %s : %s"),$state,$description,$msg);
226 }
227
228 # the final result is the worst one :
229 if ( $RETURN_CODE_VALUES{$state} > $max_state_level ) {
230 $max_state_level = $RETURN_CODE_VALUES{$state};
231 }
232 }
233 } else {
234 $answer = '<br />'._("XML Error : no test declaration found !");
235 };
236
237 if ( $max_state_level == $RETURN_CODE_VALUES{'OK'} ) {
238 $state = 'OK';
239
240 } elsif ( $max_state_level == $RETURN_CODE_VALUES{'WARN'} ) {
241 $state = 'WARNING';
242
243 } elsif ( $max_state_level == $RETURN_CODE_VALUES{'CRIT'} ) {
244 $state = 'CRITICAL';
245
246 } elsif ( $max_state_level == $RETURN_CODE_VALUES{'MAINT'} ) {
247 $state = 'MAINT';
248
249 };
250
251 if ( $state eq 'OK' ) {
252 $answer = sprintf(_("%s (v%s) : All tests (%i) are OK"),$app_name,$app_version,$nbtest);
253 if ($opt_v) {
254 $answer .= ' : '.$details;
255 } else {
256 $answer .= '.';
257 }
258
259 } elsif ( $state eq 'MAINT' ) {
260 $answer = sprintf(_("Application %s suspended :"),$app_name).$details;
261 $state = 'WARNING';
262
263 } else {
264 $answer = sprintf(_("%s (v%s) : Problem detected (%s) :"),$app_name,$app_version,$state).$details;
265
266 }
267
268 @ns = $xql->xql('/apptest/application/period');
269 my $nbperiod = $#ns+1;
270 if ( $nbperiod ) {
271
272 for ( my $i = 0 ; $i < $nbperiod ; $i++ ) {
273 my $period_start = &getFirstValue($ns[$i],"/apptest/application/period[$i]/start") || 0;
274 my $period_end = &getFirstValue($ns[$i],"/apptest/application/period[$i]/end") || 0;
275 my $time_start = 0;
276 my $time_end = 0;
277 if ($DEBUG) { print 'DEBUG: period : '."start=$period_start end=$period_end\n"; };
278 if ($period_start =~ /^(\d{4})\-(\d{2})\-(\d{2})\s(\d{2}):(\d{2}):(\d{2})/) { #2005-09-15 08:00:00
279 $time_start = mktime($6, $5, $4, $3, $2-1, $1-1900)||0;
280 }
281 if ($period_end =~ /^(\d{4})\-(\d{2})\-(\d{2})\s(\d{2}):(\d{2}):(\d{2})/) { #2005-09-15 08:00:00
282 $time_end = mktime($6, $5, $4, $3, $2-1, $1-1900)||0;
283 }
284 my $time_now = time();
285 my $out_of_period = 0;
286 if ($DEBUG) { print "DEBUG: period : actual=$time_now start=$time_start end=$time_end\n"; };
287 if ( $time_start && ($time_now < $time_start) ) {
288 $answer .= sprintf(_("(before campaign starting at %s)"),$period_start);
289 $out_of_period = 1;
290 } elsif ( $time_end && ($time_now > $time_end) ) {
291 $answer .= sprintf(_("(after campaign ending at %s)"),$period_end);
292 $out_of_period = 1;
293 }
294 if ( $out_of_period && (($state eq 'CRITICAL')||($state eq 'WARNING')) ) {
295 $state = 'UNKNOWN';
296 }
297 }
298 }
299
300 if ( $timer > $opt_w ) {
301
302 if ( $answer ) {
303 $answer.="<br />";
304 }
305 if ( $state eq 'OK' ) {
306 $state = 'WARNING';
307 }
308
309 if ( $timer > $opt_c ) {
310 $state = 'CRITICAL';
311 $answer.= sprintf(_("Response time critical : %.3fs !"),$timer);
312 } else {
313 $answer.= sprintf(_("Response time warning : %.3fs !"),$timer);
314 }
315 }
316
317 } else {
318 $state = 'CRITICAL';
319 $details = $@;
320 $details =~ s/\n/<br \/>/g;
321 $answer = _("An XML parsing error occurred:"). $details;
322 }
323
324 } elsif ( $http_response->is_error() ) {
325 $state = 'CRITICAL';
326 my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")";
327 $answer = _("HTTP error: ").$err;
328
329 } else {
330 $state = 'CRITICAL';
331 my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")";
332 $answer = _("Internal error: ").$err;
333 }
334
335 if ($opt_perf) {
336 $answer .= "|$perf";
337 }
338
339 print $answer."\n";
340 exit $EXIT_CODES{$state};
341
342 # Get the first value returned by a xql query
343 sub getFirstValue () {
344 my ($xql, $query) = @_;
345 my @result = $xql->xql ($query);
346 if ( ! exists($result[0]) ) {
347 return undef;
348 };
349 return $result[0]->xql_toString();
350 }
351
352
353 __END__
354
355 =head1 NAME
356
357 This Nagios plugins check a specified Racvision url (xml document) returned by an application and parse its content.
358
359 =head1 SYNOPSIS
360
361 B<check_application_en.pl> S<-u I<url>>
362
363 =head1 OPTIONS
364
365 =item B<-u> B<--url> I<url>
366
367 URL of the application test page.
368
369 =item B<--encoding> I<caracter encoding>
370
371 Force caracters encoding ('utf-8','iso-8859-1', etc ...) when parsing XML DATA
372
373 =item B<-p> B<--perf>
374
375 Get performance datas.
376
377 =item B<-h>
378
379 A short help. Also give default values.
380
381 =item B<--help> | B<--man>
382
383 The full man page.
384
385 =head1 NAGIOS CONGIGURATIONS
386
387 In F<checkcommands.cfg> you have to add :
388
389 define command {
390 command_name check_application_en
391 command_line $USER1$/check_application_en.pl -u $ARG1$
392 }
393
394
395 In F<services.cfg> you just have to add something like :
396
397 define service {
398 host_name www.exemple.org
399 normal_check_interval 10
400 retry_check_interval 5
401 contact_groups linux-admins
402 service_description My great web application
403 check_command check_application_en!http://www.exemple.org/myApplication/racvision
404 }
405
406 =head1 AUTHOR
407
408 St├ęphane Urbanovski <stephane.urbanovski@ac-nancy-metz.fr>
409
410 =cut

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.8