diff options
Diffstat (limited to 'lib/Monitoring/Plugin/Functions.pm')
| -rw-r--r-- | lib/Monitoring/Plugin/Functions.pm | 445 |
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 | |||
| 4 | package Monitoring::Plugin::Functions; | ||
| 5 | |||
| 6 | use 5.006; | ||
| 7 | |||
| 8 | use strict; | ||
| 9 | use warnings; | ||
| 10 | use File::Basename; | ||
| 11 | use Params::Validate qw(:types validate); | ||
| 12 | use Math::Calc::Units; | ||
| 13 | |||
| 14 | # Remember to update Monitoring::Plugins as well | ||
| 15 | our $VERSION = "0.37"; | ||
| 16 | |||
| 17 | our @STATUS_CODES = qw(OK WARNING CRITICAL UNKNOWN DEPENDENT); | ||
| 18 | |||
| 19 | require Exporter; | ||
| 20 | our @ISA = qw(Exporter); | ||
| 21 | our @EXPORT = (@STATUS_CODES, qw(plugin_exit plugin_die check_messages)); | ||
| 22 | our @EXPORT_OK = qw(%ERRORS %STATUS_TEXT @STATUS_CODES get_shortname max_state max_state_alt convert $value_re); | ||
| 23 | our %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 | |||
| 29 | use constant OK => 0; | ||
| 30 | use constant WARNING => 1; | ||
| 31 | use constant CRITICAL => 2; | ||
| 32 | use constant UNKNOWN => 3; | ||
| 33 | use constant DEPENDENT => 4; | ||
| 34 | |||
| 35 | our %ERRORS = ( | ||
| 36 | 'OK' => OK, | ||
| 37 | 'WARNING' => WARNING, | ||
| 38 | 'CRITICAL' => CRITICAL, | ||
| 39 | 'UNKNOWN' => UNKNOWN, | ||
| 40 | 'DEPENDENT' => DEPENDENT, | ||
| 41 | ); | ||
| 42 | |||
| 43 | our %STATUS_TEXT = reverse %ERRORS; | ||
| 44 | |||
| 45 | my $value = qr/[-+]?[\d\.]+/; | ||
| 46 | our $value_re = qr/$value(?:e$value)?/; | ||
| 47 | |||
| 48 | # _fake_exit flag and accessor/mutator, for testing | ||
| 49 | my $_fake_exit = 0; | ||
| 50 | sub _fake_exit { @_ ? $_fake_exit = shift : $_fake_exit }; | ||
| 51 | |||
| 52 | # _use_die flag and accessor/mutator, so exceptions can be raised correctly | ||
| 53 | my $_use_die = 0; | ||
| 54 | sub _use_die { @_ ? $_use_die = shift : $_use_die }; | ||
| 55 | |||
| 56 | sub 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 | |||
| 70 | sub 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 | |||
| 79 | sub 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 ) | ||
| 89 | sub 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 | |||
| 141 | sub _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 | ||
| 160 | sub 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 | ||
| 185 | sub die { plugin_die(@_); } | ||
| 186 | |||
| 187 | |||
| 188 | # ------------------------------------------------------------------------ | ||
| 189 | # Utility functions | ||
| 190 | |||
| 191 | # Simple wrapper around Math::Calc::Units::convert | ||
| 192 | sub 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. | ||
| 206 | sub 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 | |||
| 247 | 1; | ||
| 248 | |||
| 249 | # vim:sw=4:sm:et | ||
| 250 | |||
| 251 | __END__ | ||
| 252 | |||
| 253 | =head1 NAME | ||
| 254 | |||
| 255 | Monitoring::Plugin::Functions - functions to simplify the creation of | ||
| 256 | Nagios 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 | |||
| 290 | This module is part of the Monitoring::Plugin family, a set of modules | ||
| 291 | for simplifying the creation of Nagios plugins. This module exports | ||
| 292 | convenience functions for the class methods provided by | ||
| 293 | Monitoring::Plugin. It is intended for those who prefer a simpler | ||
| 294 | functional interface, and who do not need the additional | ||
| 295 | functionality of Monitoring::Plugin. | ||
| 296 | |||
| 297 | =head2 EXPORTS | ||
| 298 | |||
| 299 | Nagios status code constants are exported by default: | ||
| 300 | |||
| 301 | OK | ||
| 302 | WARNING | ||
| 303 | CRITICAL | ||
| 304 | UNKNOWN | ||
| 305 | DEPENDENT | ||
| 306 | |||
| 307 | as are the following functions: | ||
| 308 | |||
| 309 | plugin_exit | ||
| 310 | plugin_die | ||
| 311 | check_messages | ||
| 312 | |||
| 313 | The 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 | |||
| 324 | The following functions are supported: | ||
| 325 | |||
| 326 | =over 4 | ||
| 327 | |||
| 328 | =item plugin_exit( <CODE>, $message ) | ||
| 329 | |||
| 330 | Exit with return code CODE, and a standard nagios message of the | ||
| 331 | form "PLUGIN CODE - $message". | ||
| 332 | |||
| 333 | =item plugin_die( $message, [CODE] ) | ||
| 334 | |||
| 335 | Same as plugin_exit(), except that CODE is optional, defaulting | ||
| 336 | to UNKNOWN. NOTE: exceptions are not raised by default to calling code. | ||
| 337 | Set C<$_use_die> flag if this functionality is required (see test code). | ||
| 338 | |||
| 339 | =item check_messages( critical => \@crit, warning => \@warn ) | ||
| 340 | |||
| 341 | Convenience function to check a set of message arrays and return | ||
| 342 | an appropriate nagios return code and/or a result message. Returns | ||
| 343 | only a return code in scalar context; returns a return code and an | ||
| 344 | error 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 | |||
| 351 | check_messages() accepts the following named arguments: | ||
| 352 | |||
| 353 | =over 4 | ||
| 354 | |||
| 355 | =item critical => ARRAYREF | ||
| 356 | |||
| 357 | An arrayref of critical error messages - check_messages() returns | ||
| 358 | CRITICAL if this arrayref is non-empty. Mandatory. | ||
| 359 | |||
| 360 | =item warning => ARRAYREF | ||
| 361 | |||
| 362 | An arrayref of warning error messages - check_messages() returns | ||
| 363 | WARNING if this arrayref is non-empty ('critical' is checked | ||
| 364 | first). Mandatory. | ||
| 365 | |||
| 366 | =item ok => ARRAYREF | SCALAR | ||
| 367 | |||
| 368 | An arrayref of informational messages (or a single scalar message), | ||
| 369 | used in list context if both the 'critical' and 'warning' arrayrefs | ||
| 370 | are empty. Optional. | ||
| 371 | |||
| 372 | =item join => SCALAR | ||
| 373 | |||
| 374 | A string used to join the relevant array to generate the message | ||
| 375 | string returned in list context i.e. if the 'critical' array @crit | ||
| 376 | is non-empty, check_messages would return: | ||
| 377 | |||
| 378 | join( $join, @crit ) | ||
| 379 | |||
| 380 | as the result message. Optional; default: ' ' (space). | ||
| 381 | |||
| 382 | =item join_all => SCALAR | ||
| 383 | |||
| 384 | By default, only one set of messages are joined and returned in the | ||
| 385 | result message i.e. if the result is CRITICAL, only the 'critical' | ||
| 386 | messages are included in the result; if WARNING, only the 'warning' | ||
| 387 | messages are included; if OK, the 'ok' messages are included (if | ||
| 388 | supplied) i.e. the default is to return an 'errors-only' type | ||
| 389 | message. | ||
| 390 | |||
| 391 | If join_all is supplied, however, it will be used as a string to | ||
| 392 | join the resultant critical, warning, and ok messages together i.e. | ||
| 393 | all messages are joined and returned. | ||
| 394 | |||
| 395 | =back | ||
| 396 | |||
| 397 | =item get_shortname | ||
| 398 | |||
| 399 | Return the default shortname used for this plugin i.e. the first | ||
| 400 | token reported by plugin_exit/plugin_die. The default is basically | ||
| 401 | |||
| 402 | uc basename( $ENV{PLUGIN_NAME} || $ENV{NAGIOS_PLUGIN} || $0 ) | ||
| 403 | |||
| 404 | with any leading 'CHECK_' and trailing file suffixes removed. | ||
| 405 | |||
| 406 | get_shortname is not exported by default, so must be explicitly | ||
| 407 | imported. | ||
| 408 | |||
| 409 | =item max_state(@a) | ||
| 410 | |||
| 411 | Returns the worst state in the array. Order is: CRITICAL, WARNING, OK, UNKNOWN, | ||
| 412 | DEPENDENT | ||
| 413 | |||
| 414 | The typical usage of max_state is to initialise the state as UNKNOWN and use | ||
| 415 | it on the result of various test. If no test were performed successfully the | ||
| 416 | state will still be UNKNOWN. | ||
| 417 | |||
| 418 | =item max_state_alt(@a) | ||
| 419 | |||
| 420 | Returns the worst state in the array. Order is: CRITICAL, WARNING, UNKNOWN, | ||
| 421 | DEPENDENT, OK | ||
| 422 | |||
| 423 | This is a true definition of a max state (OK last) and should be used if the | ||
| 424 | internal tests performed can return UNKNOWN. | ||
| 425 | |||
| 426 | =back | ||
| 427 | |||
| 428 | =head1 SEE ALSO | ||
| 429 | |||
| 430 | Monitoring::Plugin; the nagios plugin developer guidelines at | ||
| 431 | https://www.monitoring-plugins.org/doc/guidelines.html. | ||
| 432 | |||
| 433 | =head1 AUTHOR | ||
| 434 | |||
| 435 | This code is maintained by the Monitoring Plugin Development Team: see | ||
| 436 | https://monitoring-plugins.org | ||
| 437 | |||
| 438 | =head1 COPYRIGHT AND LICENSE | ||
| 439 | |||
| 440 | Copyright (C) 2006-2014 Monitoring Plugin Development Team | ||
| 441 | |||
| 442 | This library is free software; you can redistribute it and/or modify | ||
| 443 | it under the same terms as Perl itself. | ||
| 444 | |||
| 445 | =cut | ||
