Remove usage of defined %hash in test for perl 5.21.x and later
[Nagios-Plugin.git] / lib / Nagios / Monitoring / Plugin.pm
blobfbf6f77fff252d5a4424c9a71b1925b66fd5d8e0
2 package Nagios::Monitoring::Plugin;
4 use Nagios::Monitoring::Plugin::Functions qw(:codes %ERRORS %STATUS_TEXT @STATUS_CODES);
5 use Params::Validate qw(:all);
7 use strict;
8 use warnings;
10 use Carp;
11 use base qw(Class::Accessor::Fast);
13 Nagios::Monitoring::Plugin->mk_accessors(qw(
14 shortname
15 perfdata
16 messages
17 opts
18 threshold
19 ));
21 use Exporter;
22 our @ISA = qw(Exporter);
23 our @EXPORT = (@STATUS_CODES);
24 our @EXPORT_OK = qw(%ERRORS %STATUS_TEXT);
26 # CPAN stupidly won't index this module without a literal $VERSION here,
27 # so we're forced to duplicate it explicitly
28 # Make sure you update $Nagios::Monitoring::Plugin::Functions::VERSION too
29 our $VERSION = "0.51";
31 sub new {
32 my $class = shift;
33 # my %args = @_;
35 my %args = validate( @_,
37 shortname => 0,
38 usage => 0,
39 version => 0,
40 url => 0,
41 plugin => 0,
42 blurb => 0,
43 extra => 0,
44 license => 0,
45 timeout => 0
49 my $shortname = Nagios::Monitoring::Plugin::Functions::get_shortname(\%args);
50 delete $args{shortname} if (exists $args{shortname});
51 my $self = {
52 shortname => $shortname,
53 perfdata => [], # to be added later
54 messages => {
55 warning => [],
56 critical => [],
57 ok => []
59 opts => undef, # see below
60 threshold => undef, # defined later
62 bless $self, $class;
63 if (exists $args{usage}) {
64 require Nagios::Monitoring::Plugin::Getopt;
65 $self->opts( new Nagios::Monitoring::Plugin::Getopt(%args) );
67 return $self;
70 sub add_perfdata {
71 my ($self, %args) = @_;
72 require Nagios::Monitoring::Plugin::Performance;
73 my $perf = Nagios::Monitoring::Plugin::Performance->new(%args);
74 push @{$self->perfdata}, $perf;
76 sub all_perfoutput {
77 my $self = shift;
78 return join(" ", map {$_->perfoutput} (@{$self->perfdata}));
81 sub set_thresholds {
82 my $self = shift;
83 require Nagios::Monitoring::Plugin::Threshold;
84 return $self->threshold( Nagios::Monitoring::Plugin::Threshold->set_thresholds(@_));
87 # NP::Functions wrappers
88 sub nagios_exit {
89 my $self = shift;
90 Nagios::Monitoring::Plugin::Functions::nagios_exit(@_, { plugin => $self });
92 sub nagios_die {
93 my $self = shift;
94 Nagios::Monitoring::Plugin::Functions::nagios_die(@_, { plugin => $self });
96 sub die {
97 my $self = shift;
98 Nagios::Monitoring::Plugin::Functions::nagios_die(@_, { plugin => $self });
100 sub max_state {
101 Nagios::Monitoring::Plugin::Functions::max_state(@_);
103 sub max_state_alt {
104 Nagios::Monitoring::Plugin::Functions::max_state_alt(@_);
107 # top level interface to Nagios::Monitoring::Plugin::Threshold
108 sub check_threshold {
109 my $self = shift;
111 my %args;
113 if ( $#_ == 0 && (! ref $_[0] || ref $_[0] eq "ARRAY" )) { # one positional param
114 %args = (check => shift);
116 else {
117 %args = validate ( @_, { # named params
118 check => 1,
119 warning => 0,
120 critical => 0,
121 } );
124 # in order of preference, get warning and critical from
125 # 1. explicit arguments to check_threshold
126 # 2. previously explicitly set threshold object
127 # 3. implicit options from Getopts object
128 if ( exists $args{warning} || exists $args{critical} ) {
129 $self->set_thresholds(
130 warning => $args{warning},
131 critical => $args{critical},
134 elsif ( defined $self->threshold ) {
135 # noop
137 elsif ( defined $self->opts ) {
138 $self->set_thresholds(
139 warning => $self->opts->warning,
140 critical => $self->opts->critical,
143 else {
144 return UNKNOWN;
147 return $self->threshold->get_status($args{check});
150 # top level interface to my Nagios::Monitoring::Plugin::Getopt object
151 sub add_arg {
152 my $self = shift;
153 $self->opts->arg(@_) if $self->_check_for_opts;
155 sub getopts {
156 my $self = shift;
157 $self->opts->getopts(@_) if $self->_check_for_opts;
160 sub _check_for_opts {
161 my $self = shift;
162 croak
163 "You have to supply a 'usage' param to Nagios::Monitoring::Plugin::new() if you want to use Getopts from your Nagios::Monitoring::Plugin object."
164 unless ref $self->opts() eq 'Nagios::Monitoring::Plugin::Getopt';
165 return $self;
170 # -------------------------------------------------------------------------
171 # NP::Functions::check_messages helpers and wrappers
173 sub add_message {
174 my $self = shift;
175 my ($code, @messages) = @_;
177 croak "Invalid error code '$code'"
178 unless defined($ERRORS{uc $code}) || defined($STATUS_TEXT{$code});
180 # Store messages using strings rather than numeric codes
181 $code = $STATUS_TEXT{$code} if $STATUS_TEXT{$code};
182 $code = lc $code;
183 croak "Error code '$code' not supported by add_message"
184 if $code eq 'unknown' || $code eq 'dependent';
186 $self->messages($code, []) unless $self->messages->{$code};
187 push @{$self->messages->{$code}}, @messages;
190 sub check_messages {
191 my $self = shift;
192 my %args = @_;
194 # Add object messages to any passed in as args
195 for my $code (qw(critical warning ok)) {
196 my $messages = $self->messages->{$code} || [];
197 if ($args{$code}) {
198 unless (ref $args{$code} eq 'ARRAY') {
199 if ($code eq 'ok') {
200 $args{$code} = [ $args{$code} ];
201 } else {
202 croak "Invalid argument '$code'"
205 push @{$args{$code}}, @$messages;
207 else {
208 $args{$code} = $messages;
212 Nagios::Monitoring::Plugin::Functions::check_messages(%args);
215 # -------------------------------------------------------------------------
219 #vim:et:sw=4
221 __END__
223 =head1 NAME
225 Nagios::Monitoring::Plugin - A family of perl modules to streamline writing Nagios
226 plugins
228 =head1 SYNOPSIS
230 # Constants OK, WARNING, CRITICAL, and UNKNOWN are exported by default
231 # See also Nagios::Monitoring::Plugin::Functions for a functional interface
232 use Nagios::Monitoring::Plugin;
234 # Constructor
235 $np = Nagios::Monitoring::Plugin->new; # OR
236 $np = Nagios::Monitoring::Plugin->new( shortname => "PAGESIZE" ); # OR
239 # use Nagios::Monitoring::Plugin::Getopt to process the @ARGV command line options:
240 # --verbose, --help, --usage, --timeout and --host are defined automatically.
241 $np = Nagios::Monitoring::Plugin->new(
242 usage => "Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>] "
243 . "[ -c|--critical=<threshold> ] [ -w|--warning=<threshold> ]",
246 # add valid command line options and build them into your usage/help documentation.
247 $np->add_arg(
248 spec => 'warning|w=s',
249 help => '-w, --warning=INTEGER:INTEGER . See '
250 . 'https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT '
251 . 'for the threshold format. ',
254 # Parse @ARGV and process standard arguments (e.g. usage, help, version)
255 $np->getopts;
258 # Exit/return value methods - nagios_exit( CODE, MESSAGE ),
259 # nagios_die( MESSAGE, [CODE])
260 $page = retrieve_page($page1)
261 or $np->nagios_exit( UNKNOWN, "Could not retrieve page" );
262 # Return code: 3;
263 # output: PAGESIZE UNKNOWN - Could not retrieve page
264 test_page($page)
265 or $np->nagios_exit( CRITICAL, "Bad page found" );
267 # nagios_die() is just like nagios_exit(), but return code defaults
268 # to UNKNOWN
269 $page = retrieve_page($page2)
270 or $np->nagios_die( "Could not retrieve page" );
271 # Return code: 3;
272 # output: PAGESIZE UNKNOWN - Could not retrieve page
274 # Threshold methods
275 $code = $np->check_threshold(
276 check => $value,
277 warning => $warning_threshold,
278 critical => $critical_threshold,
280 $np->nagios_exit( $code, "Threshold check failed" ) if $code != OK;
283 # Message methods (EXPERIMENTAL AND SUBJECT TO CHANGE) -
284 # add_message( CODE, $message ); check_messages()
285 for (@collection) {
286 if (m/Error/) {
287 $np->add_message( CRITICAL, $_ );
288 } else {
289 $np->add_message( OK, $_ );
292 ($code, $message) = $np->check_messages();
293 nagios_exit( $code, $message );
294 # If any items in collection matched m/Error/, returns CRITICAL and
295 # the joined set of Error messages; otherwise returns OK and the
296 # joined set of ok messages
299 # Perfdata methods
300 $np->add_perfdata(
301 label => "size",
302 value => $value,
303 uom => "kB",
304 threshold => $threshold,
306 $np->add_perfdata( label => "time", ... );
307 $np->nagios_exit( OK, "page size at http://... was ${value}kB" );
308 # Return code: 0;
309 # output: PAGESIZE OK - page size at http://... was 36kB \
310 # | size=36kB;10:25;25: time=...
313 =head1 DESCRIPTION
315 Nagios::Monitoring::Plugin and its associated Nagios::Monitoring::Plugin::* modules are a
316 family of perl modules to streamline writing Nagios plugins. The main
317 end user modules are Nagios::Monitoring::Plugin, providing an object-oriented
318 interface to the entire Nagios::Monitoring::Plugin::* collection, and
319 Nagios::Monitoring::Plugin::Functions, providing a simpler functional interface to
320 a useful subset of the available functionality.
322 The purpose of the collection is to make it as simple as possible for
323 developers to create plugins that conform the Nagios Plugin guidelines
324 (https://nagios-plugins.org/doc/guidelines.html).
327 =head2 EXPORTS
329 Nagios status code constants are exported by default:
332 WARNING
333 CRITICAL
334 UNKNOWN
335 DEPENDENT
337 The following variables are also exported on request:
339 =over 4
341 =item %ERRORS
343 A hash mapping error strings ("CRITICAL", "UNKNOWN", etc.) to the
344 corresponding status code.
346 =item %STATUS_TEXT
348 A hash mapping status code constants (OK, WARNING, CRITICAL, etc.) to the
349 corresponding error string ("OK", "WARNING, "CRITICAL", etc.) i.e. the
350 reverse of %ERRORS.
352 =back
355 =head2 CONSTRUCTOR
357 Nagios::Monitoring::Plugin->new;
359 Nagios::Monitoring::Plugin->new( shortname => 'PAGESIZE' );
361 Nagios::Monitoring::Plugin->new(
362 usage => "Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>]
363 [ -c|--critical=<critical threshold> ] [ -w|--warning=<warning threshold> ] ",
364 version => $VERSION,
365 blurb => $blurb,
366 extra => $extra,
367 url => $url,
368 license => $license,
369 plugin => basename $0,
370 timeout => 15,
373 Instantiates a new Nagios::Monitoring::Plugin object. Accepts the following named
374 arguments:
376 =over 4
378 =item shortname
380 The 'shortname' for this plugin, used as the first token in the plugin
381 output by the various exit methods. Default: uc basename $0.
383 =item usage ("Usage: %s --foo --bar")
385 Passing a value for the usage() argument makes Nagios::Monitoring::Plugin
386 instantiate its own C<Nagios::Monitoring::Plugin::Getopt> object so you can start
387 doing command line argument processing. See
388 L<Nagios::Monitoring::Plugin::Getopt/CONSTRUCTOR> for more about "usage" and the
389 following options:
391 =item version
393 =item url
395 =item blurb
397 =item license
399 =item extra
401 =item plugin
403 =item timeout
405 =back
407 =head2 OPTION HANDLING METHODS
409 C<Nagios::Monitoring::Plugin> provides these methods for accessing the functionality in C<Nagios::Monitoring::Plugin::Getopt>.
411 =over 4
413 =item add_arg
415 Examples:
417 # Define --hello argument (named parameters)
418 $plugin->add_arg(
419 spec => 'hello=s',
420 help => "--hello\n Hello string",
421 required => 1,
424 # Define --hello argument (positional parameters)
425 # Parameter order is 'spec', 'help', 'default', 'required?'
426 $plugin->add_arg('hello=s', "--hello\n Hello string", undef, 1);
428 See L<Nagios::Monitoring::Plugin::Getopt/ARGUMENTS> for more details.
430 =item getopts()
432 Parses and processes the command line options you've defined,
433 automatically doing the right thing with help/usage/version arguments.
435 See L<Nagios::Monitoring::Plugin::Getopt/GETOPTS> for more details.
437 =item opts()
439 Assuming you've instantiated it by passing 'usage' to new(), opts()
440 returns the Nagios::Monitoring::Plugin object's C<Nagios::Monitoring::Plugin::Getopt> object,
441 with which you can do lots of great things.
443 E.g.
445 if ( $plugin->opts->verbose ) {
446 print "yah yah YAH YAH YAH!!!";
449 # start counting down to timeout
450 alarm $plugin->opts->timeout;
451 your_long_check_step_that_might_time_out();
453 # access any of your custom command line options,
454 # assuming you've done these steps above:
455 # $plugin->add_arg('my_argument=s', '--my_argument [STRING]');
456 # $plugin->getopts;
457 print $plugin->opts->my_argument;
459 Again, see L<Nagios::Monitoring::Plugin::Getopt>.
461 =back
463 =head2 EXIT METHODS
465 =over 4
467 =item nagios_exit( <CODE>, $message )
469 Exit with return code CODE, and a standard nagios message of the
470 form "SHORTNAME CODE - $message".
472 =item nagios_die( $message, [<CODE>] )
474 Same as nagios_exit(), except that CODE is optional, defaulting
475 to UNKNOWN. NOTE: exceptions are not raised by default to calling code.
476 Set C<$_use_die> flag if this functionality is required (see test code).
478 =item die( $message, [<CODE>] )
480 Alias for nagios_die(). Deprecated.
482 =item max_state, max_state_alt
484 These are wrapper function for Nagios::Monitoring::Plugin::Functions::max_state and
485 Nagios::Monitoring::Plugin::Functions::max_state_alt.
487 =back
489 =head2 THRESHOLD METHODS
491 These provide a top level interface to the
492 C<Nagios::Monitoring::Plugin::Threshold> module; for more details, see
493 L<Nagios::Monitoring::Plugin::Threshold> and L<Nagios::Monitoring::Plugin::Range>.
495 =over 4
497 =item check_threshold( $value )
499 =item check_threshold( check => $value, warning => $warn, critical => $crit )
501 Evaluates $value against the thresholds and returns OK, CRITICAL, or
502 WARNING constant. The thresholds may be:
504 1. explicitly set by passing 'warning' and/or 'critical' parameters to
505 C<check_threshold()>, or,
507 2. explicitly set by calling C<set_thresholds()> before C<check_threshold()>, or,
509 3. implicitly set by command-line parameters -w, -c, --critical or
510 --warning, if you have run C<< $plugin->getopts() >>.
512 You can specify $value as an array of values and each will be checked against
513 the thresholds.
515 The return value is ready to pass to C <nagios_exit>, e . g .,
517 $p->nagios_exit(
518 return_code => $p->check_threshold($result),
519 message => " sample result was $result"
523 =item set_thresholds(warning => "10:25", critical => "~:25")
525 Sets the acceptable ranges and creates the plugin's
526 Nagios::Monitoring::Plugins::Threshold object. See
527 https://nagios-plugins.org/doc/guidelines.html#THRESHOLDFORMAT
528 for details and examples of the threshold format.
530 =item threshold()
532 Returns the object's C<Nagios::Monitoring::Plugin::Threshold> object, if it has
533 been defined by calling set_thresholds(). You can pass a new
534 Threshold object to it to replace the old one too, but you shouldn't
535 need to do that from a plugin script.
537 =back
539 =head2 MESSAGE METHODS
541 EXPERIMENTAL AND SUBJECT TO CHANGE
543 add_messages and check_messages are higher-level convenience methods to add
544 and then check a set of messages, returning an appropriate return code
545 and/or result message. They are equivalent to maintaining a set of @critical,
546 @warning, and and @ok message arrays (add_message), and then doing a final
547 if test (check_messages) like this:
549 if (@critical) {
550 nagios_exit( CRITICAL, join(' ', @critical) );
552 elsif (@warning) {
553 nagios_exit( WARNING, join(' ', @warning) );
555 else {
556 nagios_exit( OK, join(' ', @ok) );
559 =over 4
561 =item add_message( <CODE>, $message )
563 Add a message with CODE status to the object. May be called multiple times.
564 The messages added are checked by check_messages, following.
566 Only CRITICAL, WARNING, and OK are accepted as valid codes.
569 =item check_messages()
571 Check the current set of messages and return an appropriate nagios return
572 code and/or a result message. In scalar context, returns only a return
573 code; in list context returns both a return code and an output message,
574 suitable for passing directly to nagios_exit() e.g.
576 $code = $np->check_messages;
577 ($code, $message) = $np->check_messages;
579 check_messages returns CRITICAL if any critical messages are found, WARNING
580 if any warning messages are found, and OK otherwise. The message returned
581 in list context defaults to the joined set of error messages; this may be
582 customised using the arguments below.
584 check_messages accepts the following named arguments (none are required):
586 =over 4
588 =item join => SCALAR
590 A string used to join the relevant array to generate the message
591 string returned in list context i.e. if the 'critical' array @crit
592 is non-empty, check_messages would return:
594 join( $join, @crit )
596 as the result message. Default: ' ' (space).
598 =item join_all => SCALAR
600 By default, only one set of messages are joined and returned in the
601 result message i.e. if the result is CRITICAL, only the 'critical'
602 messages are included in the result; if WARNING, only the 'warning'
603 messages are included; if OK, the 'ok' messages are included (if
604 supplied) i.e. the default is to return an 'errors-only' type
605 message.
607 If join_all is supplied, however, it will be used as a string to
608 join the resultant critical, warning, and ok messages together i.e.
609 all messages are joined and returned.
611 =item critical => ARRAYREF
613 Additional critical messages to supplement any passed in via add_message().
615 =item warning => ARRAYREF
617 Additional warning messages to supplement any passed in via add_message().
619 =item ok => ARRAYREF | SCALAR
621 Additional ok messages to supplement any passed in via add_message().
623 =back
625 =back
628 =head2 PERFORMANCE DATA METHODS
630 =over 4
632 =item add_perfdata( label => "size", value => $value, uom => "kB", threshold => $threshold )
634 Add a set of performance data to the object. May be called multiple times.
635 The performance data is included in the standard plugin output messages by
636 the various exit methods.
638 See the Nagios::Monitoring::Plugin::Performance documentation for more information on
639 performance data and the various field definitions, as well as the relevant
640 section of the Nagios Plugin guidelines
641 (https://nagios-plugins.org/doc/guidelines.html#AEN202).
643 =back
646 =head1 EXAMPLES
648 "Enough talk! Show me some examples!"
650 See the file 'check_stuff.pl' in the 't' directory included with the
651 Nagios::Monitoring::Plugin distribution for a complete working example of a plugin
652 script.
655 =head1 VERSIONING
657 The Nagios::Monitoring::Plugin::* modules are currently experimental and so the
658 interfaces may change up until Nagios::Monitoring::Plugin hits version 1.0, although
659 every attempt will be made to keep them as backwards compatible as
660 possible.
663 =head1 SEE ALSO
665 See L<Nagios::Monitoring::Plugin::Functions> for a simple functional interface to a subset
666 of the available Nagios::Monitoring::Plugin functionality.
668 See also L<Nagios::Monitoring::Plugin::Getopt>, L<Nagios::Monitoring::Plugin::Range>,
669 L<Nagios::Monitoring::Plugin::Performance>, L<Nagios::Monitoring::Plugin::Range>, and
670 L<Nagios::Monitoring::Plugin::Threshold>.
672 The Nagios Plugin project page is at https://nagios-plugins.org.
675 =head1 BUGS
677 Please report bugs in these modules to the Nagios Plugin development team:
678 nagiosplug-devel@lists.sourceforge.net.
681 =head1 AUTHOR
683 Maintained by the Nagios Plugin development team -
684 https://nagios-plugins.org.
686 Originally by Ton Voon, E<lt>ton.voon@altinity.comE<gt>.
688 =head1 COPYRIGHT AND LICENSE
690 Copyright (C) 2006-2015 by Nagios Plugin Development Team
692 This library is free software; you can redistribute it and/or modify it
693 under the same terms as Perl itself, either Perl version 5.8.4 or, at your
694 option, any later version of Perl 5 you may have available.
696 =cut