summaryrefslogtreecommitdiffstats
path: root/lib/Monitoring/Plugin.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Monitoring/Plugin.pm')
-rw-r--r--lib/Monitoring/Plugin.pm712
1 files changed, 712 insertions, 0 deletions
diff --git a/lib/Monitoring/Plugin.pm b/lib/Monitoring/Plugin.pm
new file mode 100644
index 0000000..f9eb49e
--- /dev/null
+++ b/lib/Monitoring/Plugin.pm
@@ -0,0 +1,712 @@
1
2package Monitoring::Plugin;
3
4use Monitoring::Plugin::Functions qw(:codes %ERRORS %STATUS_TEXT @STATUS_CODES);
5use Params::Validate qw(:all);
6
7use strict;
8use warnings;
9
10use Carp;
11use base qw(Class::Accessor::Fast);
12
13Monitoring::Plugin->mk_accessors(qw(
14 shortname
15 perfdata
16 messages
17 opts
18 threshold
19 ));
20
21use Exporter;
22our @ISA = qw(Exporter);
23our @EXPORT = (@STATUS_CODES);
24our @EXPORT_OK = qw(%ERRORS %STATUS_TEXT);
25
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 $Monitoring::Plugin::Functions::VERSION too
29our $VERSION = "0.37";
30
31sub new {
32 my $class = shift;
33# my %args = @_;
34
35 my %args = validate( @_,
36 {
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
46 },
47 );
48
49 my $shortname = 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 => []
58 },
59 opts => undef, # see below
60 threshold => undef, # defined later
61 };
62 bless $self, $class;
63 if (exists $args{usage}) {
64 require Monitoring::Plugin::Getopt;
65 $self->opts( new Monitoring::Plugin::Getopt(%args) );
66 }
67 return $self;
68}
69
70sub add_perfdata {
71 my ($self, %args) = @_;
72 require Monitoring::Plugin::Performance;
73 my $perf = Monitoring::Plugin::Performance->new(%args);
74 push @{$self->perfdata}, $perf;
75}
76sub all_perfoutput {
77 my $self = shift;
78 return join(" ", map {$_->perfoutput} (@{$self->perfdata}));
79}
80
81sub set_thresholds {
82 my $self = shift;
83 require Monitoring::Plugin::Threshold;
84 return $self->threshold( Monitoring::Plugin::Threshold->set_thresholds(@_));
85}
86
87# MP::Functions wrappers
88sub plugin_exit {
89 my $self = shift;
90 Monitoring::Plugin::Functions::plugin_exit(@_, { plugin => $self });
91}
92sub plugin_die {
93 my $self = shift;
94 Monitoring::Plugin::Functions::plugin_die(@_, { plugin => $self });
95}
96sub nagios_exit {
97 my $self = shift;
98 Monitoring::Plugin::Functions::plugin_exit(@_, { plugin => $self });
99}
100sub nagios_die {
101 my $self = shift;
102 Monitoring::Plugin::Functions::plugin_die(@_, { plugin => $self });
103}
104sub die {
105 my $self = shift;
106 Monitoring::Plugin::Functions::plugin_die(@_, { plugin => $self });
107}
108sub max_state {
109 Monitoring::Plugin::Functions::max_state(@_);
110}
111sub max_state_alt {
112 Monitoring::Plugin::Functions::max_state_alt(@_);
113}
114
115# top level interface to Monitoring::Plugin::Threshold
116sub check_threshold {
117 my $self = shift;
118
119 my %args;
120
121 if ( $#_ == 0 && (! ref $_[0] || ref $_[0] eq "ARRAY" )) { # one positional param
122 %args = (check => shift);
123 }
124 else {
125 %args = validate ( @_, { # named params
126 check => 1,
127 warning => 0,
128 critical => 0,
129 } );
130 }
131
132 # in order of preference, get warning and critical from
133 # 1. explicit arguments to check_threshold
134 # 2. previously explicitly set threshold object
135 # 3. implicit options from Getopts object
136 if ( exists $args{warning} || exists $args{critical} ) {
137 $self->set_thresholds(
138 warning => $args{warning},
139 critical => $args{critical},
140 );
141 }
142 elsif ( defined $self->threshold ) {
143 # noop
144 }
145 elsif ( defined $self->opts ) {
146 $self->set_thresholds(
147 warning => $self->opts->warning,
148 critical => $self->opts->critical,
149 );
150 }
151 else {
152 return UNKNOWN;
153 }
154
155 return $self->threshold->get_status($args{check});
156}
157
158# top level interface to my Monitoring::Plugin::Getopt object
159sub add_arg {
160 my $self = shift;
161 $self->opts->arg(@_) if $self->_check_for_opts;
162}
163sub getopts {
164 my $self = shift;
165 $self->opts->getopts(@_) if $self->_check_for_opts;
166}
167
168sub _check_for_opts {
169 my $self = shift;
170 croak
171 "You have to supply a 'usage' param to Monitoring::Plugin::new() if you want to use Getopts from your Monitoring::Plugin object."
172 unless ref $self->opts() eq 'Monitoring::Plugin::Getopt';
173 return $self;
174}
175
176
177
178# -------------------------------------------------------------------------
179# MP::Functions::check_messages helpers and wrappers
180
181sub add_message {
182 my $self = shift;
183 my ($code, @messages) = @_;
184
185 croak "Invalid error code '$code'"
186 unless defined($ERRORS{uc $code}) || defined($STATUS_TEXT{$code});
187
188 # Store messages using strings rather than numeric codes
189 $code = $STATUS_TEXT{$code} if $STATUS_TEXT{$code};
190 $code = lc $code;
191 croak "Error code '$code' not supported by add_message"
192 if $code eq 'unknown' || $code eq 'dependent';
193
194 $self->messages($code, []) unless $self->messages->{$code};
195 push @{$self->messages->{$code}}, @messages;
196}
197
198sub check_messages {
199 my $self = shift;
200 my %args = @_;
201
202 # Add object messages to any passed in as args
203 for my $code (qw(critical warning ok)) {
204 my $messages = $self->messages->{$code} || [];
205 if ($args{$code}) {
206 unless (ref $args{$code} eq 'ARRAY') {
207 if ($code eq 'ok') {
208 $args{$code} = [ $args{$code} ];
209 } else {
210 croak "Invalid argument '$code'"
211 }
212 }
213 push @{$args{$code}}, @$messages;
214 }
215 else {
216 $args{$code} = $messages;
217 }
218 }
219
220 Monitoring::Plugin::Functions::check_messages(%args);
221}
222
223# -------------------------------------------------------------------------
224
2251;
226
227#vim:et:sw=4
228
229__END__
230
231=head1 NAME
232
233Monitoring::Plugin - A family of perl modules to streamline writing Naemon, Nagios,
234Icinga or Shinken (and compatible) plugins.
235
236=head1 SYNOPSIS
237
238 # Constants OK, WARNING, CRITICAL, and UNKNOWN are exported by default
239 # See also Monitoring::Plugin::Functions for a functional interface
240 use Monitoring::Plugin;
241
242 # Constructor
243 $np = Monitoring::Plugin->new; # OR
244 $np = Monitoring::Plugin->new( shortname => "PAGESIZE" ); # OR
245
246
247 # use Monitoring::Plugin::Getopt to process the @ARGV command line options:
248 # --verbose, --help, --usage, --timeout and --host are defined automatically.
249 $np = Monitoring::Plugin->new(
250 usage => "Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>] "
251 . "[ -c|--critical=<threshold> ] [ -w|--warning=<threshold> ]",
252 );
253
254 # add valid command line options and build them into your usage/help documentation.
255 $np->add_arg(
256 spec => 'warning|w=s',
257 help => '-w, --warning=INTEGER:INTEGER . See '
258 . 'https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT '
259 . 'for the threshold format. ',
260 );
261
262 # Parse @ARGV and process standard arguments (e.g. usage, help, version)
263 $np->getopts;
264
265
266 # Exit/return value methods - plugin_exit( CODE, MESSAGE ),
267 # plugin_die( MESSAGE, [CODE])
268 $page = retrieve_page($page1)
269 or $np->plugin_exit( UNKNOWN, "Could not retrieve page" );
270 # Return code: 3;
271 # output: PAGESIZE UNKNOWN - Could not retrieve page
272 test_page($page)
273 or $np->plugin_exit( CRITICAL, "Bad page found" );
274
275 # plugin_die() is just like plugin_exit(), but return code defaults
276 # to UNKNOWN
277 $page = retrieve_page($page2)
278 or $np->plugin_die( "Could not retrieve page" );
279 # Return code: 3;
280 # output: PAGESIZE UNKNOWN - Could not retrieve page
281
282 # Threshold methods
283 $code = $np->check_threshold(
284 check => $value,
285 warning => $warning_threshold,
286 critical => $critical_threshold,
287 );
288 $np->plugin_exit( $code, "Threshold check failed" ) if $code != OK;
289
290
291 # Message methods (EXPERIMENTAL AND SUBJECT TO CHANGE) -
292 # add_message( CODE, $message ); check_messages()
293 for (@collection) {
294 if (m/Error/) {
295 $np->add_message( CRITICAL, $_ );
296 } else {
297 $np->add_message( OK, $_ );
298 }
299 }
300 ($code, $message) = $np->check_messages();
301 plugin_exit( $code, $message );
302 # If any items in collection matched m/Error/, returns CRITICAL and
303 # the joined set of Error messages; otherwise returns OK and the
304 # joined set of ok messages
305
306
307 # Perfdata methods
308 $np->add_perfdata(
309 label => "size",
310 value => $value,
311 uom => "kB",
312 threshold => $threshold,
313 );
314 $np->add_perfdata( label => "time", ... );
315 $np->plugin_exit( OK, "page size at http://... was ${value}kB" );
316 # Return code: 0;
317 # output: PAGESIZE OK - page size at http://... was 36kB \
318 # | size=36kB;10:25;25: time=...
319
320
321=head1 DESCRIPTION
322
323Monitoring::Plugin and its associated Monitoring::Plugin::* modules are a
324family of perl modules to streamline writing Monitoring plugins. The main
325end user modules are Monitoring::Plugin, providing an object-oriented
326interface to the entire Monitoring::Plugin::* collection, and
327Monitoring::Plugin::Functions, providing a simpler functional interface to
328a useful subset of the available functionality.
329
330The purpose of the collection is to make it as simple as possible for
331developers to create plugins that conform the Monitoring Plugin guidelines
332(https://www.monitoring-plugins.org/doc/guidelines.html).
333
334
335=head2 EXPORTS
336
337Nagios status code constants are exported by default:
338
339 OK
340 WARNING
341 CRITICAL
342 UNKNOWN
343 DEPENDENT
344
345The following variables are also exported on request:
346
347=over 4
348
349=item %ERRORS
350
351A hash mapping error strings ("CRITICAL", "UNKNOWN", etc.) to the
352corresponding status code.
353
354=item %STATUS_TEXT
355
356A hash mapping status code constants (OK, WARNING, CRITICAL, etc.) to the
357corresponding error string ("OK", "WARNING, "CRITICAL", etc.) i.e. the
358reverse of %ERRORS.
359
360=back
361
362
363=head2 CONSTRUCTOR
364
365 Monitoring::Plugin->new;
366
367 Monitoring::Plugin->new( shortname => 'PAGESIZE' );
368
369 Monitoring::Plugin->new(
370 usage => "Usage: %s [ -v|--verbose ] [-H <host>] [-t <timeout>]
371 [ -c|--critical=<critical threshold> ] [ -w|--warning=<warning threshold> ] ",
372 version => $VERSION,
373 blurb => $blurb,
374 extra => $extra,
375 url => $url,
376 license => $license,
377 plugin => basename $0,
378 timeout => 15,
379 );
380
381Instantiates a new Monitoring::Plugin object. Accepts the following named
382arguments:
383
384=over 4
385
386=item shortname
387
388The 'shortname' for this plugin, used as the first token in the plugin
389output by the various exit methods. Default: uc basename $0.
390
391=item usage ("Usage: %s --foo --bar")
392
393Passing a value for the usage() argument makes Monitoring::Plugin
394instantiate its own C<Monitoring::Plugin::Getopt> object so you can start
395doing command line argument processing. See
396L<Monitoring::Plugin::Getopt/CONSTRUCTOR> for more about "usage" and the
397following options:
398
399=item version
400
401=item url
402
403=item blurb
404
405=item license
406
407=item extra
408
409=item plugin
410
411=item timeout
412
413=back
414
415=head2 OPTION HANDLING METHODS
416
417C<Monitoring::Plugin> provides these methods for accessing the functionality in C<Monitoring::Plugin::Getopt>.
418
419=over 4
420
421=item add_arg
422
423Examples:
424
425 # Define --hello argument (named parameters)
426 $plugin->add_arg(
427 spec => 'hello=s',
428 help => "--hello\n Hello string",
429 required => 1,
430 );
431
432 # Define --hello argument (positional parameters)
433 # Parameter order is 'spec', 'help', 'default', 'required?'
434 $plugin->add_arg('hello=s', "--hello\n Hello string", undef, 1);
435
436See L<Monitoring::Plugin::Getopt/ARGUMENTS> for more details.
437
438=item getopts()
439
440Parses and processes the command line options you've defined,
441automatically doing the right thing with help/usage/version arguments.
442
443See L<Monitoring::Plugin::Getopt/GETOPTS> for more details.
444
445=item opts()
446
447Assuming you've instantiated it by passing 'usage' to new(), opts()
448returns the Monitoring::Plugin object's C<Monitoring::Plugin::Getopt> object,
449with which you can do lots of great things.
450
451E.g.
452
453 if ( $plugin->opts->verbose ) {
454 print "yah yah YAH YAH YAH!!!";
455 }
456
457 # start counting down to timeout
458 alarm $plugin->opts->timeout;
459 your_long_check_step_that_might_time_out();
460
461 # access any of your custom command line options,
462 # assuming you've done these steps above:
463 # $plugin->add_arg('my_argument=s', '--my_argument [STRING]');
464 # $plugin->getopts;
465 print $plugin->opts->my_argument;
466
467Again, see L<Monitoring::Plugin::Getopt>.
468
469=back
470
471=head2 EXIT METHODS
472
473=over 4
474
475=item plugin_exit( <CODE>, $message )
476
477Exit with return code CODE, and a standard nagios message of the
478form "SHORTNAME CODE - $message".
479
480=item plugin_die( $message, [<CODE>] )
481
482Same as plugin_exit(), except that CODE is optional, defaulting
483to UNKNOWN. NOTE: exceptions are not raised by default to calling code.
484Set C<$_use_die> flag if this functionality is required (see test code).
485
486=item nagios_exit( <CODE>, $message )
487
488Alias for plugin_die(). Deprecated.
489
490=item nagios_die( $message, [<CODE>] )
491
492Alias for plugin_die(). Deprecated.
493
494=item die( $message, [<CODE>] )
495
496Alias for plugin_die(). Deprecated.
497
498=item max_state, max_state_alt
499
500These are wrapper function for Monitoring::Plugin::Functions::max_state and
501Monitoring::Plugin::Functions::max_state_alt.
502
503=back
504
505=head2 THRESHOLD METHODS
506
507These provide a top level interface to the
508C<Monitoring::Plugin::Threshold> module; for more details, see
509L<Monitoring::Plugin::Threshold> and L<Monitoring::Plugin::Range>.
510
511=over 4
512
513=item check_threshold( $value )
514
515=item check_threshold( check => $value, warning => $warn, critical => $crit )
516
517Evaluates $value against the thresholds and returns OK, CRITICAL, or
518WARNING constant. The thresholds may be:
519
5201. explicitly set by passing 'warning' and/or 'critical' parameters to
521 C<check_threshold()>, or,
522
5232. explicitly set by calling C<set_thresholds()> before C<check_threshold()>, or,
524
5253. implicitly set by command-line parameters -w, -c, --critical or
526 --warning, if you have run C<< $plugin->getopts() >>.
527
528You can specify $value as an array of values and each will be checked against
529the thresholds.
530
531The return value is ready to pass to C <plugin_exit>, e . g .,
532
533 $p->plugin_exit(
534 return_code => $p->check_threshold($result),
535 message => " sample result was $result"
536 );
537
538
539=item set_thresholds(warning => "10:25", critical => "~:25")
540
541Sets the acceptable ranges and creates the plugin's
542Monitoring::Plugins::Threshold object. See
543https://www.monitoring-plugins.org/doc/guidelines.html#THRESHOLDFORMAT
544for details and examples of the threshold format.
545
546=item threshold()
547
548Returns the object's C<Monitoring::Plugin::Threshold> object, if it has
549been defined by calling set_thresholds(). You can pass a new
550Threshold object to it to replace the old one too, but you shouldn't
551need to do that from a plugin script.
552
553=back
554
555=head2 MESSAGE METHODS
556
557EXPERIMENTAL AND SUBJECT TO CHANGE
558
559add_messages and check_messages are higher-level convenience methods to add
560and then check a set of messages, returning an appropriate return code
561and/or result message. They are equivalent to maintaining a set of @critical,
562@warning, and and @ok message arrays (add_message), and then doing a final
563if test (check_messages) like this:
564
565 if (@critical) {
566 plugin_exit( CRITICAL, join(' ', @critical) );
567 }
568 elsif (@warning) {
569 plugin_exit( WARNING, join(' ', @warning) );
570 }
571 else {
572 plugin_exit( OK, join(' ', @ok) );
573 }
574
575=over 4
576
577=item add_message( <CODE>, $message )
578
579Add a message with CODE status to the object. May be called multiple times.
580The messages added are checked by check_messages, following.
581
582Only CRITICAL, WARNING, and OK are accepted as valid codes.
583
584
585=item check_messages()
586
587Check the current set of messages and return an appropriate nagios return
588code and/or a result message. In scalar context, returns only a return
589code; in list context returns both a return code and an output message,
590suitable for passing directly to plugin_exit() e.g.
591
592 $code = $np->check_messages;
593 ($code, $message) = $np->check_messages;
594
595check_messages returns CRITICAL if any critical messages are found, WARNING
596if any warning messages are found, and OK otherwise. The message returned
597in list context defaults to the joined set of error messages; this may be
598customised using the arguments below.
599
600check_messages accepts the following named arguments (none are required):
601
602=over 4
603
604=item join => SCALAR
605
606A string used to join the relevant array to generate the message
607string returned in list context i.e. if the 'critical' array @crit
608is non-empty, check_messages would return:
609
610 join( $join, @crit )
611
612as the result message. Default: ' ' (space).
613
614=item join_all => SCALAR
615
616By default, only one set of messages are joined and returned in the
617result message i.e. if the result is CRITICAL, only the 'critical'
618messages are included in the result; if WARNING, only the 'warning'
619messages are included; if OK, the 'ok' messages are included (if
620supplied) i.e. the default is to return an 'errors-only' type
621message.
622
623If join_all is supplied, however, it will be used as a string to
624join the resultant critical, warning, and ok messages together i.e.
625all messages are joined and returned.
626
627=item critical => ARRAYREF
628
629Additional critical messages to supplement any passed in via add_message().
630
631=item warning => ARRAYREF
632
633Additional warning messages to supplement any passed in via add_message().
634
635=item ok => ARRAYREF | SCALAR
636
637Additional ok messages to supplement any passed in via add_message().
638
639=back
640
641=back
642
643
644=head2 PERFORMANCE DATA METHODS
645
646=over 4
647
648=item add_perfdata( label => "size", value => $value, uom => "kB", threshold => $threshold )
649
650Add a set of performance data to the object. May be called multiple times.
651The performance data is included in the standard plugin output messages by
652the various exit methods.
653
654See the Monitoring::Plugin::Performance documentation for more information on
655performance data and the various field definitions, as well as the relevant
656section of the Monitoring Plugin guidelines
657(https://www.monitoring-plugins.org/doc/guidelines.html#AEN202).
658
659=back
660
661
662=head1 EXAMPLES
663
664"Enough talk! Show me some examples!"
665
666See the file 'check_stuff.pl' in the 't' directory included with the
667Monitoring::Plugin distribution for a complete working example of a plugin
668script.
669
670
671=head1 VERSIONING
672
673The Monitoring::Plugin::* modules are currently experimental and so the
674interfaces may change up until Monitoring::Plugin hits version 1.0, although
675every attempt will be made to keep them as backwards compatible as
676possible.
677
678
679=head1 SEE ALSO
680
681See L<Monitoring::Plugin::Functions> for a simple functional interface to a subset
682of the available Monitoring::Plugin functionality.
683
684See also L<Monitoring::Plugin::Getopt>, L<Monitoring::Plugin::Range>,
685L<Monitoring::Plugin::Performance>, L<Monitoring::Plugin::Range>, and
686L<Monitoring::Plugin::Threshold>.
687
688The Monitoring Plugin project page is at http://monitoring-plugins.org.
689
690
691=head1 BUGS
692
693Please report bugs in these modules to the Monitoring Plugin development team:
694devel@monitoring-plugins.org.
695
696
697=head1 AUTHOR
698
699Maintained by the Monitoring Plugin development team -
700https://www.monitoring-plugins.org.
701
702Originally by Ton Voon, E<lt>ton.voon@altinity.comE<gt>.
703
704=head1 COPYRIGHT AND LICENSE
705
706Copyright (C) 2006-2014 by Monitoring Plugin Team
707
708This library is free software; you can redistribute it and/or modify it
709under the same terms as Perl itself, either Perl version 5.8.4 or, at your
710option, any later version of Perl 5 you may have available.
711
712=cut