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

Contents of /trunk/plugins/check_haproxy.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 135 - (show annotations) (download)
Fri Mar 12 17:26:57 2010 UTC (10 years, 8 months ago) by racvision
File MIME type: text/plain
File size: 8344 byte(s)
add -U and -P switches to supply username/password credentials
1 #!/usr/bin/perl -w
2 #
3 # Copyright (c) 2010 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: $
21
22 use strict; # should never be differently :-)
23 use warnings;
24
25
26 use Locale::gettext;
27 use File::Basename; # get basename()
28
29 use POSIX qw(setlocale);
30 use Time::HiRes qw(time); # get microtime
31 use POSIX qw(mktime);
32
33 use Nagios::Plugin ;
34
35 use LWP::UserAgent; # http client
36 use HTTP::Request; # used by LWP::UserAgent
37 use HTTP::Status; # to get http err msg
38
39
40 use Data::Dumper;
41
42
43 my $PROGNAME = basename($0);
44 '$Revision: 1.0 $' =~ /^.*(\d+\.\d+) \$$/; # Use The Revision from RCS/CVS/SVN
45 my $VERSION = $1;
46
47 my $DEBUG = 0;
48 my $TIMEOUT = 9;
49
50 # i18n :
51 setlocale(LC_MESSAGES, '');
52 textdomain('nagios-plugins-perl');
53
54
55 my $np = Nagios::Plugin->new(
56 version => $VERSION,
57 blurb => _gt('Plugin to check HAProxy stats url'),
58 usage => "Usage: %s [ -v|--verbose ] -u <url> [-t <timeout>] [-U <username>] [-P <password>] [ -c|--critical=<threshold> ] [ -w|--warning=<threshold> ]",
59 timeout => $TIMEOUT+1
60 );
61 $np->add_arg (
62 spec => 'debug|d',
63 help => _gt('Debug level'),
64 default => 0,
65 );
66 $np->add_arg (
67 spec => 'username|U=s',
68 help => _gt('Username for HTTP Auth'),
69 required => 0,
70 );
71 $np->add_arg (
72 spec => 'password|P=s',
73 help => _gt('Password for HTTP Auth'),
74 required => 0,
75 );
76 $np->add_arg (
77 spec => 'w=f',
78 help => _gt('Warning request time threshold (in seconds)'),
79 default => 2,
80 label => 'FLOAT'
81 );
82 $np->add_arg (
83 spec => 'c=f',
84 help => _gt('Critical request time threshold (in seconds)'),
85 default => 10,
86 label => 'FLOAT'
87 );
88 $np->add_arg (
89 spec => 'url|u=s',
90 help => _gt('URL of the HAProxy csv statistics page.'),
91 required => 1,
92 );
93
94
95 $np->getopts;
96
97 $DEBUG = $np->opts->get('debug');
98 my $verbose = $np->opts->get('verbose');
99 my $username = $np->opts->get('username');
100 my $password = $np->opts->get('password');
101
102 # Thresholds :
103 # time
104 my $warn_t = $np->opts->get('w');
105 my $crit_t = $np->opts->get('c');
106
107 my $url = $np->opts->get('url');
108
109
110 # Create a LWP user agent object:
111 my $ua = new LWP::UserAgent(
112 'env_proxy' => 0,
113 'timeout' => $TIMEOUT,
114 );
115 $ua->agent(basename($0));
116
117 # Workaround for LWP bug :
118 $ua->parse_head(0);
119
120 if ( defined($ENV{'http_proxy'}) ) {
121 # Normal http proxy :
122 $ua->proxy(['http'], $ENV{'http_proxy'});
123 # Https must use Crypt::SSLeay https proxy (to use CONNECT method instead of GET)
124 $ENV{'HTTPS_PROXY'} = $ENV{'http_proxy'};
125 }
126
127 # Build and submit an http request :
128 my $request = HTTP::Request->new('GET', $url);
129 # Authenticate if username and password are supplied
130 if ( defined($username) && defined($password) ) {
131 $request->authorization_basic($username, $password);
132 }
133 my $timer = time();
134 my $http_response = $ua->request( $request );
135 $timer = time()-$timer;
136
137
138
139 my $status = $np->check_threshold(
140 'check' => $timer,
141 'warning' => $warn_t,
142 'critical' => $crit_t,
143 );
144
145 $np->add_perfdata(
146 'label' => 't',
147 'value' => sprintf('%.6f',$timer),
148 'min' => 0,
149 'uom' => 's',
150 'threshold' => $np->threshold()
151 );
152
153 if ( $status > OK ) {
154 $np->add_message($status, sprintf(_gt("Response time degraded: %.6fs !"),$timer) );
155 }
156
157
158 my $message = 'msg';
159
160
161 if ( $http_response->is_error() ) {
162 my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")";
163 $np->add_message(CRITICAL, _gt("HTTP error: ").$err );
164
165 } elsif ( ! $http_response->is_success() ) {
166 my $err = $http_response->code." ".status_message($http_response->code)." (".$http_response->message.")";
167 $np->add_message(CRITICAL, _gt("Internal error: ").$err );
168 }
169
170
171 ($status, $message) = $np->check_messages();
172
173 if ( $http_response->is_success() ) {
174
175 # Get xml content ...
176 my $stats = $http_response->content;
177 if ($DEBUG) {
178 print "------------------===http output===------------------\n$stats\n-----------------------------------------------------\n";
179 print "t=".$timer."s\n";
180 };
181
182 my @fields = ();
183 my @rows = split(/\n/,$stats);
184 if ( $rows[0] =~ /#\ \w+/ ) {
185 $rows[0] =~ s/#\ //;
186 @fields = split(/\,/,$rows[0]);
187 } else {
188 $np->nagios_exit(UNKNOWN, _gt("Can't find csv header !") );
189 }
190
191 my %stats = ();
192 for ( my $y = 1; $y < $#rows; $y++ ) {
193 my @values = split(/\,/,$rows[$y]);
194 if ( !defined($stats{$values[0]}) ) {
195 $stats{$values[0]} = {};
196 }
197 if ( !defined($stats{$values[0]}{$values[1]}) ) {
198 $stats{$values[0]}{$values[1]} = {};
199 }
200 for ( my $x = 2,; $x <= $#values; $x++ ) {
201 # $stats{pxname}{svname}{valuename}
202 $stats{$values[0]}{$values[1]}{$fields[$x]} = $values[$x];
203 }
204 }
205 # print Dumper(\%stats);
206 my %stats2 = ();
207 my $okMsg = '';
208 foreach my $pxname ( keys(%stats) ) {
209 $stats2{$pxname} = {
210 'act' => 0,
211 'acttot' => 0,
212 'bck' => 0,
213 'bcktot' => 0,
214 'scur' => 0,
215 'slim' => 0,
216 };
217 foreach my $svname ( keys(%{$stats{$pxname}}) ) {
218 if ( $stats{$pxname}{$svname}{'type'} eq '2' ) {
219 my $svstatus = $stats{$pxname}{$svname}{'status'} eq 'UP';
220 my $active = $stats{$pxname}{$svname}{'act'} eq '1';
221 my $activeDescr = $active ? _gt("Active service") :_gt("Backup service") ;
222 if ( $stats{$pxname}{$svname}{'status'} eq 'UP' ) {
223 logD( sprintf(_gt("%s '%s' is up on '%s' proxy."),$activeDescr,$svname,$pxname) );
224 } elsif ( $stats{$pxname}{$svname}{'status'} eq 'DOWN' ) {
225 $np->add_message(CRITICAL, sprintf(_gt("%s '%s' is DOWN on '%s' proxy !"),$activeDescr,$svname,$pxname) );
226 }
227 if ( $stats{$pxname}{$svname}{'act'} eq '1' ) {
228 $stats2{$pxname}{'acttot'}++;
229 $stats2{$pxname}{'act'} += $svstatus;
230
231 } elsif ($stats{$pxname}{$svname}{'bck'} eq '1') {
232 $stats2{$pxname}{'bcktot'}++;
233 $stats2{$pxname}{'bck'} += $svstatus;
234 }
235 $stats2{$pxname}{'scur'} += $stats{$pxname}{$svname}{'scur'};
236 logD( "Current sessions : ".$stats{$pxname}{$svname}{'scur'} );
237
238 } elsif ( $stats{$pxname}{$svname}{'type'} eq '0' ) {
239 $stats2{$pxname}{'slim'} = $stats{$pxname}{$svname}{'slim'};
240 }
241 }
242 if ( $stats2{$pxname}{'acttot'} > 0 ) {
243 $okMsg .= ' '.$pxname.' (Active: '.$stats2{$pxname}{'act'}.'/'.$stats2{$pxname}{'acttot'};
244 if ( $stats2{$pxname}{'bcktot'} > 0 ) {
245 $okMsg .= ' , Backup: '.$stats2{$pxname}{'bck'}.'/'.$stats2{$pxname}{'bcktot'};
246 }
247 $okMsg .= ')';
248 $np->add_perfdata(
249 'label' => 'sess_'.$pxname,
250 'value' => $stats2{$pxname}{'scur'},
251 'min' => 0,
252 'uom' => 'sessions',
253 'max' => $stats2{$pxname}{'slim'},
254 );
255 }
256 }
257
258 # print Dumper(\%stats2);
259 ($status, $message) = $np->check_messages('join' => ' ');
260
261 if ( $status == OK ) {
262 $message = $okMsg;
263
264 }
265
266 }
267 # if ( $verbose ) {
268 # ($status, $message) = $np->check_messages('join' => '<br/>','join_all' => '<br/>');
269 # } else {
270 # ($status, $message) = $np->check_messages('join' => '<br/>');
271 # }
272
273
274 $np->nagios_exit($status, $message );
275
276
277 sub logD {
278 print STDERR 'DEBUG: '.$_[0]."\n" if ($DEBUG);
279 }
280 sub logW {
281 print STDERR 'WARNING: '.$_[0]."\n" if ($DEBUG);
282 }
283 # Gettext wrapper
284 sub _gt {
285 return gettext($_[0]);
286 }
287
288
289 __END__
290
291 =head1 NAME
292
293 This Nagios plugins check the statistics url provided by HAProxy (http://haproxy.1wt.eu/).
294
295
296 =head1 NAGIOS CONGIGURATIONS
297
298 In F<checkcommands.cfg> you have to add :
299
300 define command {
301 command_name check_haproxy
302 command_line $USER1$/check_haproxy.pl -u $ARG1$
303 }
304
305
306 In F<services.cfg> you just have to add something like :
307
308 define service {
309 host_name haproxy.exemple.org
310 normal_check_interval 10
311 retry_check_interval 5
312 contact_groups linux-admins
313 service_description HAProxy
314 check_command check_haproxy!http://haproxy.exemple.org/haproxy?stats;csv
315 }
316
317 =head1 AUTHOR
318
319 St├ęphane Urbanovski <stephane.urbanovski@ac-nancy-metz.fr>
320
321 =cut

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.8