File Coverage

blib/lib/Nagios/Monitoring/Plugin/Functions.pm
Criterion Covered Total %
statement 123 133 92.4
branch 79 88 89.7
condition 39 63 61.9
subroutine 20 22 90.9
pod 6 8 75.0
total 267 314 85.0


line stmt bran cond sub pod time code
1             # Functional interface to basic Nagios::Monitoring::Plugin constants, exports,
2             # and functions
3              
4             package Nagios::Monitoring::Plugin::Functions;
5              
6 17     17   140504 use 5.006;
  17         56  
7              
8 17     17   86 use strict;
  17         31  
  17         370  
9 17     17   80 use warnings;
  17         56  
  17         678  
10 17     17   87 use File::Basename;
  17         26  
  17         1966  
11 17     17   11061 use Params::Validate qw(:types validate);
  17         162034  
  17         19875  
12 17     17   24930 use Math::Calc::Units;
  17         567724  
  17         3839  
13              
14             # Remember to update Nagios::Monitoring::Plugins as well
15             our $VERSION = "0.50";
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(nagios_exit nagios_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(nagios_exit nagios_die check_messages max_state max_state_alt convert) ],
27             );
28              
29 17     17   332 use constant OK => 0;
  17         34  
  17         1108  
30 17     17   92 use constant WARNING => 1;
  17         37  
  17         1492  
31 17     17   116 use constant CRITICAL => 2;
  17         34  
  17         1284  
32 17     17   376 use constant UNKNOWN => 3;
  17         33  
  17         1138  
33 17     17   78 use constant DEPENDENT => 4;
  17         26  
  17         37392  
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 7 50   7   81 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 8 50   8   97 sub _use_die { @_ ? $_use_die = shift : $_use_die };
55              
56             sub get_shortname {
57 26     26 1 42 my $arg = shift;
58              
59 26         40 my $shortname = undef;
60              
61 26 100       92 return $arg->{shortname} if (defined($arg->{shortname}));
62 22 100       56 $shortname = $arg->{plugin} if (defined( $arg->{plugin}));
63              
64 22   33     885 $shortname = uc basename($shortname || $ENV{NAGIOS_PLUGIN} || $0);
65 22         46 $shortname =~ s/^CHECK_(?:BY_)?//; # Remove any leading CHECK_[BY_]
66 22         76 $shortname =~ s/\..*$//; # Remove any trailing suffix
67 22         65 return $shortname;
68             }
69              
70             sub max_state {
71 7 100   7 1 1320 return CRITICAL if grep { $_ == CRITICAL } @_;
  16         265  
72 6 100       14 return WARNING if grep { $_ == WARNING } @_;
  14         40  
73 3 100       7 return OK if grep { $_ == OK } @_;
  4         225  
74 1 50       5 return UNKNOWN if grep { $_ == UNKNOWN } @_;
  0         0  
75 1 50       20 return DEPENDENT if grep { $_ == DEPENDENT } @_;
  0         0  
76 1         6 return UNKNOWN;
77             }
78              
79             sub max_state_alt {
80 7 100   7 1 1260 return CRITICAL if grep { $_ == CRITICAL } @_;
  16         39  
81 6 100       12 return WARNING if grep { $_ == WARNING } @_;
  14         33  
82 3 100       5 return UNKNOWN if grep { $_ == UNKNOWN } @_;
  4         14  
83 2 50       4 return DEPENDENT if grep { $_ == DEPENDENT } @_;
  2         6  
84 2 100       4 return OK if grep { $_ == OK } @_;
  2         40  
85 1         6 return UNKNOWN;
86             }
87              
88             # nagios_exit( $code, $message )
89             sub nagios_exit {
90 50     50 1 77 my ($code, $message, $arg) = @_;
91              
92             # Handle named parameters
93 50 100 66     257 if (defined $code && ($code eq 'return_code' || $code eq 'message')) {
      66        
94             # Remove last argument if odd no and last is ref
95 6 50 33     90 if (int(@_ / 2) != @_ / 2 && ref $_[$#_]) {
96 6         11 $arg = pop @_;
97             } else {
98 0         0 undef $arg;
99             }
100 6         20 my %arg = @_;
101 6         14 $code = $arg{return_code};
102 6         14 $message = $arg{message};
103             }
104 50   100     103 $arg ||= {};
105              
106             # Handle string codes
107 50 100 66     194 $code = $ERRORS{$code} if defined $code && exists $ERRORS{$code};
108              
109             # Set defaults
110 50 100 66     156 $code = UNKNOWN unless defined $code && exists $STATUS_TEXT{$code};
111 50 100       85 $message = '' unless defined $message;
112 50 50 33     117 if (ref $message && ref $message eq 'ARRAY') {
113 0         0 $message = join(' ', map { chomp; $_ } @$message);
  0         0  
  0         0  
114             }
115             else {
116 50         81 chomp $message;
117             }
118              
119             # Setup output
120 50         87 my $output = "$STATUS_TEXT{$code}";
121 50 100 66     267 $output .= " - $message" if defined $message && $message ne '';
122 50 100       180 my $shortname = ($arg->{plugin} ? $arg->{plugin}->shortname : undef);
123 50   66     247 $shortname ||= get_shortname(); # Should happen only if funnctions are called directly
124 50 50       127 $output = "$shortname $output" if $shortname;
125 50 100       124 if ($arg->{plugin}) {
126 48         56 my $plugin = $arg->{plugin};
127 48 100 66     112 $output .= " | ". $plugin->all_perfoutput
128             if $plugin->perfdata && $plugin->all_perfoutput;
129             }
130 50         316 $output .= "\n";
131              
132             # Don't actually exit if _fake_exit set
133 50 100       99 if ($_fake_exit) {
134 48         2039 require Nagios::Monitoring::Plugin::ExitResult;
135 48         251 return Nagios::Monitoring::Plugin::ExitResult->new($code, $output);
136             }
137              
138 2         6 _nagios_exit($code, $output);
139             }
140              
141             sub _nagios_exit {
142 16     16   28 my ($code, $output) = @_;
143             # Print output and exit; die if flag set and called via a die in stack backtrace
144 16 100       52 if ($_use_die) {
145 15         35 for (my $i = 0;; $i++) {
146 31         242 @_ = caller($i);
147 31 50       105 last unless @_;
148 31 100       113 if ($_[3] =~ m/die/) {
149 15         46 $! = $code;
150 15         254 die($output);
151             }
152             }
153             }
154 1         129 print $output;
155 1         38 exit $code;
156             }
157              
158             # nagios_die( $message, [ $code ]) OR nagios_die( $code, $message )
159             # Default $code: UNKNOWN
160             sub nagios_die {
161 31     31 1 1123 my ($arg1, $arg2, $rest) = @_;
162              
163             # Named parameters
164 31 100 66     324 if (defined $arg1 && ($arg1 eq 'return_code' || $arg1 eq 'message')) {
    100 66        
    100 66        
      66        
      66        
      66        
165 6         32 return nagios_exit(@_);
166             }
167              
168             # ($code, $message)
169             elsif (defined $arg1 && (exists $ERRORS{$arg1} || exists $STATUS_TEXT{$arg1})) {
170 10         20 return nagios_exit(@_);
171             }
172              
173             # ($message, $code)
174             elsif (defined $arg2 && (exists $ERRORS{$arg2} || exists $STATUS_TEXT{$arg2})) {
175 11         24 return nagios_exit($arg2, $arg1, $rest);
176             }
177              
178             # Else just assume $arg1 is the message and hope for the best
179             else {
180 4         10 return nagios_exit( UNKNOWN, $arg1, $arg2 );
181             }
182             }
183              
184             # For backwards compatibility
185 0     0 0 0 sub die { nagios_die(@_); }
186              
187              
188             # ------------------------------------------------------------------------
189             # Utility functions
190              
191             # Simple wrapper around Math::Calc::Units::convert
192             sub convert
193             {
194 0     0 0 0 my ($value, $from, $to) = @_;
195 0         0 my ($newval) = Math::Calc::Units::convert("$value $from", $to, 'exact');
196 0         0 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 53     53 1 17702 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 50 100       384 $arg{join} = ' ' unless defined $arg{join};
215              
216             # Decide $code
217 50         59 my $code = OK;
218 50 100 50     51 $code ||= CRITICAL if @{$arg{critical}};
  50         185  
219 50 100 100     54 $code ||= WARNING if @{$arg{warning}};
  50         176  
220 50 100       120 return $code unless wantarray;
221              
222             # Compose message
223 44         52 my $message = '';
224 44 100       86 if ($arg{join_all}) {
225             $message = join( $arg{join_all},
226 36 100       108 map { @$_ ? join( $arg{'join'}, @$_) : () }
227             $arg{critical},
228             $arg{warning},
229 12 100       52 $arg{ok} ? (ref $arg{ok} ? $arg{ok} : [ $arg{ok} ]) : []
    100          
230             );
231             }
232              
233             else {
234 32 100 33     84 $message ||= join( $arg{'join'}, @{$arg{critical}} )
  13         70  
235             if $code == CRITICAL;
236 32 100 33     80 $message ||= join( $arg{'join'}, @{$arg{warning}} )
  10         35  
237             if $code == WARNING;
238 8         31 $message ||= ref $arg{ok} ? join( $arg{'join'}, @{$arg{ok}} ) : $arg{ok}
239 32 100 100     116 if $arg{ok};
    100          
240             }
241              
242 44         228 return ($code, $message);
243             }
244              
245             # ------------------------------------------------------------------------
246              
247             1;
248              
249             # vim:sw=4:sm:et
250              
251             __END__