summaryrefslogtreecommitdiffstats
path: root/lib/Monitoring/Plugin/Functions.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Monitoring/Plugin/Functions.pm')
-rw-r--r--lib/Monitoring/Plugin/Functions.pm445
1 files changed, 445 insertions, 0 deletions
diff --git a/lib/Monitoring/Plugin/Functions.pm b/lib/Monitoring/Plugin/Functions.pm
new file mode 100644
index 0000000..d2856e8
--- /dev/null
+++ b/lib/Monitoring/Plugin/Functions.pm
@@ -0,0 +1,445 @@
1# Functional interface to basic Monitoring::Plugin constants, exports,
2# and functions
3
4package Monitoring::Plugin::Functions;
5
6use 5.006;
7
8use strict;
9use warnings;
10use File::Basename;
11use Params::Validate qw(:types validate);
12use Math::Calc::Units;
13
14# Remember to update Monitoring::Plugins as well
15our $VERSION = "0.37";
16
17our @STATUS_CODES = qw(OK WARNING CRITICAL UNKNOWN DEPENDENT);
18
19require Exporter;
20our @ISA = qw(Exporter);
21our @EXPORT = (@STATUS_CODES, qw(plugin_exit plugin_die check_messages));
22our @EXPORT_OK = qw(%ERRORS %STATUS_TEXT @STATUS_CODES get_shortname max_state max_state_alt convert $value_re);
23our %EXPORT_TAGS = (
24 all => [ @EXPORT, @EXPORT_OK ],
25 codes => [ @STATUS_CODES ],
26 functions => [ qw(plugin_exit plugin_die check_messages max_state max_state_alt convert) ],
27);
28
29use constant OK => 0;
30use constant WARNING => 1;
31use constant CRITICAL => 2;
32use constant UNKNOWN => 3;
33use constant DEPENDENT => 4;
34
35our %ERRORS = (
36 'OK' => OK,
37 'WARNING' => WARNING,
38 'CRITICAL' => CRITICAL,
39 'UNKNOWN' => UNKNOWN,
40 'DEPENDENT' => DEPENDENT,
41);
42
43our %STATUS_TEXT = reverse %ERRORS;
44
45my $value = qr/[-+]?[\d\.]+/;
46our $value_re = qr/$value(?:e$value)?/;
47
48# _fake_exit flag and accessor/mutator, for testing
49my $_fake_exit = 0;
50sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit };
51
52# _use_die flag and accessor/mutator, so exceptions can be raised correctly
53my $_use_die = 0;
54sub _use_die { @_ ? $_use_die = shift : $_use_die };
55
56sub get_shortname {
57 my $arg = shift;
58
59 my $shortname = undef;
60
61 return $arg->{shortname} if (defined($arg->{shortname}));
62 $shortname = $arg->{plugin} if (defined( $arg->{plugin}));
63
64 $shortname = uc basename($shortname || $ENV{PLUGIN_NAME} || $ENV{NAGIOS_PLUGIN} || $0);
65 $shortname =~ s/^CHECK_(?:BY_)?//; # Remove any leading CHECK_[BY_]
66 $shortname =~ s/\..*$//; # Remove any trailing suffix
67 return $shortname;
68}
69
70sub max_state {
71 return CRITICAL if grep { $_ == CRITICAL } @_;
72 return WARNING if grep { $_ == WARNING } @_;
73 return OK if grep { $_ == OK } @_;
74 return UNKNOWN if grep { $_ == UNKNOWN } @_;
75 return DEPENDENT if grep { $_ == DEPENDENT } @_;
76 return UNKNOWN;
77}
78
79sub max_state_alt {
80 return CRITICAL if grep { $_ == CRITICAL } @_;
81 return WARNING if grep { $_ == WARNING } @_;
82 return UNKNOWN if grep { $_ == UNKNOWN } @_;
83 return DEPENDENT if grep { $_ == DEPENDENT } @_;
84 return OK if grep { $_ == OK } @_;
85 return UNKNOWN;
86}
87
88# plugin_exit( $code, $message )
89sub plugin_exit {
90 my ($code, $message, $arg) = @_;
91
92 # Handle named parameters
93 if (defined $code && ($code eq 'return_code' || $code eq 'message')) {
94 # Remove last argument if odd no and last is ref
95 if (int(@_ / 2) != @_ / 2 && ref $_[$#_]) {
96 $arg = pop @_;
97 } else {
98 undef $arg;
99 }
100 my %arg = @_;
101 $code = $arg{return_code};
102 $message = $arg{message};
103 }
104 $arg ||= {};
105
106 # Handle string codes
107 $code = $ERRORS{$code} if defined $code && exists $ERRORS{$code};
108
109 # Set defaults
110 $code = UNKNOWN unless defined $code && exists $STATUS_TEXT{$code};
111 $message = '' unless defined $message;
112 if (ref $message && ref $message eq 'ARRAY') {
113 $message = join(' ', map { chomp; $_ } @$message);
114 }
115 else {
116 chomp $message;
117 }
118
119 # Setup output
120 my $output = "$STATUS_TEXT{$code}";
121 $output .= " - $message" if defined $message && $message ne '';
122 my $shortname = ($arg->{plugin} ? $arg->{plugin}->shortname : undef);
123 $shortname ||= get_shortname(); # Should happen only if funnctions are called directly
124 $output = "$shortname $output" if $shortname;
125 if ($arg->{plugin}) {
126 my $plugin = $arg->{plugin};
127 $output .= " | ". $plugin->all_perfoutput
128 if $plugin->perfdata && $plugin->all_perfoutput;
129 }
130 $output .= "\n";
131
132 # Don't actually exit if _fake_exit set
133 if ($_fake_exit) {
134 require Monitoring::Plugin::ExitResult;
135 return Monitoring::Plugin::ExitResult->new($code, $output);
136 }
137
138 _plugin_exit($code, $output);
139}
140
141sub _plugin_exit {
142 my ($code, $output) = @_;
143 # Print output and exit; die if flag set and called via a die in stack backtrace
144 if ($_use_die) {
145 for (my $i = 0;; $i++) {
146 @_ = caller($i);
147 last unless @_;
148 if ($_[3] =~ m/die/) {
149 $! = $code;
150 die($output);
151 }
152 }
153 }
154 print $output;
155 exit $code;
156}
157
158# plugin_die( $message, [ $code ]) OR plugin_die( $code, $message )
159# Default $code: UNKNOWN
160sub plugin_die {
161 my ($arg1, $arg2, $rest) = @_;
162
163 # Named parameters
164 if (defined $arg1 && ($arg1 eq 'return_code' || $arg1 eq 'message')) {
165 return plugin_exit(@_);
166 }
167
168 # ($code, $message)
169 elsif (defined $arg1 && (exists $ERRORS{$arg1} || exists $STATUS_TEXT{$arg1})) {
170 return plugin_exit(@_);
171 }
172
173 # ($message, $code)
174 elsif (defined $arg2 && (exists $ERRORS{$arg2} || exists $STATUS_TEXT{$arg2})) {
175 return plugin_exit($arg2, $arg1, $rest);
176 }
177
178 # Else just assume $arg1 is the message and hope for the best
179 else {
180 return plugin_exit( UNKNOWN, $arg1, $arg2 );
181 }
182}
183
184# For backwards compatibility
185sub die { plugin_die(@_); }
186
187
188# ------------------------------------------------------------------------
189# Utility functions
190
191# Simple wrapper around Math::Calc::Units::convert
192sub convert
193{
194 my ($value, $from, $to) = @_;
195 my ($newval) = Math::Calc::Units::convert("$value $from", $to, 'exact');
196 return $newval;
197}
198
199# ------------------------------------------------------------------------
200# check_messages - return a status and/or message based on a set of
201# message arrays.
202# Returns a nagios status code in scalar context.
203# Returns a code and a message in list context.
204# The message is join($join, @array) for the relevant array for the code,
205# or join($join_all, $message) for all arrays if $join_all is set.
206sub check_messages {
207 my %arg = validate( @_, {
208 critical => { type => ARRAYREF },
209 warning => { type => ARRAYREF },
210 ok => { type => ARRAYREF | SCALAR, optional => 1 },
211 'join' => { default => ' ' },
212 join_all => 0,
213 });
214 $arg{join} = ' ' unless defined $arg{join};
215
216 # Decide $code
217 my $code = OK;
218 $code ||= CRITICAL if @{$arg{critical}};
219 $code ||= WARNING if @{$arg{warning}};
220 return $code unless wantarray;
221
222 # Compose message
223 my $message = '';
224 if ($arg{join_all}) {
225 $message = join( $arg{join_all},
226 map { @$_ ? join( $arg{'join'}, @$_) : () }
227 $arg{critical},
228 $arg{warning},
229 $arg{ok} ? (ref $arg{ok} ? $arg{ok} : [ $arg{ok} ]) : []
230 );
231 }
232
233 else {
234 $message ||= join( $arg{'join'}, @{$arg{critical}} )
235 if $code == CRITICAL;
236 $message ||= join( $arg{'join'}, @{$arg{warning}} )
237 if $code == WARNING;
238 $message ||= ref $arg{ok} ? join( $arg{'join'}, @{$arg{ok}} ) : $arg{ok}
239 if $arg{ok};
240 }
241
242 return ($code, $message);
243}
244
245# ------------------------------------------------------------------------
246
2471;
248
249# vim:sw=4:sm:et
250
251__END__
252
253=head1 NAME
254
255Monitoring::Plugin::Functions - functions to simplify the creation of
256Nagios plugins
257
258=head1 SYNOPSIS
259
260 # Constants OK, WARNING, CRITICAL, and UNKNOWN exported by default
261 use Monitoring::Plugin::Functions;
262
263 # plugin_exit( CODE, $message ) - exit with error code CODE,
264 # and message "PLUGIN CODE - $message"
265 plugin_exit( CRITICAL, $critical_error ) if $critical_error;
266 plugin_exit( WARNING, $warning_error ) if $warning_error;
267 plugin_exit( OK, $result );
268
269 # plugin_die( $message, [$CODE] ) - just like plugin_exit(),
270 # but CODE is optional, defaulting to UNKNOWN
271 do_something()
272 or plugin_die("do_something() failed horribly");
273 do_something_critical()
274 or plugin_die("do_something_critical() failed", CRITICAL);
275
276 # check_messages - check a set of message arrays, returning a
277 # CODE and/or a result message
278 $code = check_messages(critical => \@crit, warning => \@warn);
279 ($code, $message) = check_messages(
280 critical => \@crit, warning => \@warn,
281 ok => \@ok );
282
283 # get_shortname - return the default short name for this plugin
284 # (as used by plugin_exit/die; not exported by default)
285 $shortname = get_shortname();
286
287
288=head1 DESCRIPTION
289
290This module is part of the Monitoring::Plugin family, a set of modules
291for simplifying the creation of Nagios plugins. This module exports
292convenience functions for the class methods provided by
293Monitoring::Plugin. It is intended for those who prefer a simpler
294functional interface, and who do not need the additional
295functionality of Monitoring::Plugin.
296
297=head2 EXPORTS
298
299Nagios status code constants are exported by default:
300
301 OK
302 WARNING
303 CRITICAL
304 UNKNOWN
305 DEPENDENT
306
307as are the following functions:
308
309 plugin_exit
310 plugin_die
311 check_messages
312
313The following variables and functions are exported only on request:
314
315 %ERRORS
316 %STATUS_TEXT
317 get_shortname
318 max_state
319 max_state_alt
320
321
322=head2 FUNCTIONS
323
324The following functions are supported:
325
326=over 4
327
328=item plugin_exit( <CODE>, $message )
329
330Exit with return code CODE, and a standard nagios message of the
331form "PLUGIN CODE - $message".
332
333=item plugin_die( $message, [CODE] )
334
335Same as plugin_exit(), except that CODE is optional, defaulting
336to UNKNOWN. NOTE: exceptions are not raised by default to calling code.
337Set C<$_use_die> flag if this functionality is required (see test code).
338
339=item check_messages( critical => \@crit, warning => \@warn )
340
341Convenience function to check a set of message arrays and return
342an appropriate nagios return code and/or a result message. Returns
343only a return code in scalar context; returns a return code and an
344error message in list context i.e.
345
346 # Scalar context
347 $code = check_messages(critical => \@crit, warning => \@warn);
348 # List context
349 ($code, $msg) = check_messages(critical => \@crit, warning => \@warn);
350
351check_messages() accepts the following named arguments:
352
353=over 4
354
355=item critical => ARRAYREF
356
357An arrayref of critical error messages - check_messages() returns
358CRITICAL if this arrayref is non-empty. Mandatory.
359
360=item warning => ARRAYREF
361
362An arrayref of warning error messages - check_messages() returns
363WARNING if this arrayref is non-empty ('critical' is checked
364first). Mandatory.
365
366=item ok => ARRAYREF | SCALAR
367
368An arrayref of informational messages (or a single scalar message),
369used in list context if both the 'critical' and 'warning' arrayrefs
370are empty. Optional.
371
372=item join => SCALAR
373
374A string used to join the relevant array to generate the message
375string returned in list context i.e. if the 'critical' array @crit
376is non-empty, check_messages would return:
377
378 join( $join, @crit )
379
380as the result message. Optional; default: ' ' (space).
381
382=item join_all => SCALAR
383
384By default, only one set of messages are joined and returned in the
385result message i.e. if the result is CRITICAL, only the 'critical'
386messages are included in the result; if WARNING, only the 'warning'
387messages are included; if OK, the 'ok' messages are included (if
388supplied) i.e. the default is to return an 'errors-only' type
389message.
390
391If join_all is supplied, however, it will be used as a string to
392join the resultant critical, warning, and ok messages together i.e.
393all messages are joined and returned.
394
395=back
396
397=item get_shortname
398
399Return the default shortname used for this plugin i.e. the first
400token reported by plugin_exit/plugin_die. The default is basically
401
402 uc basename( $ENV{PLUGIN_NAME} || $ENV{NAGIOS_PLUGIN} || $0 )
403
404with any leading 'CHECK_' and trailing file suffixes removed.
405
406get_shortname is not exported by default, so must be explicitly
407imported.
408
409=item max_state(@a)
410
411Returns the worst state in the array. Order is: CRITICAL, WARNING, OK, UNKNOWN,
412DEPENDENT
413
414The typical usage of max_state is to initialise the state as UNKNOWN and use
415it on the result of various test. If no test were performed successfully the
416state will still be UNKNOWN.
417
418=item max_state_alt(@a)
419
420Returns the worst state in the array. Order is: CRITICAL, WARNING, UNKNOWN,
421DEPENDENT, OK
422
423This is a true definition of a max state (OK last) and should be used if the
424internal tests performed can return UNKNOWN.
425
426=back
427
428=head1 SEE ALSO
429
430Monitoring::Plugin; the nagios plugin developer guidelines at
431https://www.monitoring-plugins.org/doc/guidelines.html.
432
433=head1 AUTHOR
434
435This code is maintained by the Monitoring Plugin Development Team: see
436https://monitoring-plugins.org
437
438=head1 COPYRIGHT AND LICENSE
439
440Copyright (C) 2006-2014 Monitoring Plugin Development Team
441
442This library is free software; you can redistribute it and/or modify
443it under the same terms as Perl itself.
444
445=cut