File Coverage

blib/lib/Monitoring/Plugin/Functions.pm
Criterion Covered Total %
statement 125 135 92.5
branch 81 90 90.0
condition 42 63 66.6
subroutine 20 22 90.9
pod 6 8 75.0
total 274 318 86.1


line stmt bran cond sub pod time code
1             package Monitoring::Plugin::Functions;
2              
3             # Functional interface to basic Monitoring::Plugin constants, exports,
4             # and functions
5              
6 17     17   254274 use 5.006;
  17         84  
7 17     17   69 use strict;
  17         24  
  17         305  
8 17     17   63 use warnings;
  17         35  
  17         388  
9              
10 17     17   132 use File::Basename;
  17         25  
  17         1291  
11 17     17   5489 use Params::Validate qw(:types validate);
  17         89493  
  17         2384  
12 17     17   5899 use Math::Calc::Units;
  17         319452  
  17         1826  
13              
14             # Remember to update Monitoring::Plugins as well
15             our $VERSION = "0.40";
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 17     17   110 use constant OK => 0;
  17         44  
  17         700  
30 17     17   89 use constant WARNING => 1;
  17         32  
  17         670  
31 17     17   79 use constant CRITICAL => 2;
  17         31  
  17         625  
32 17     17   75 use constant UNKNOWN => 3;
  17         27  
  17         618  
33 17     17   87 use constant DEPENDENT => 4;
  17         28  
  17         20848  
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 9 50   9   699 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 10 50   10   301 sub _use_die { @_ ? $_use_die = shift : $_use_die };
55              
56             sub get_shortname {
57 72     72 1 1532 my $arg = shift;
58              
59 72         97 my $shortname = undef;
60              
61 72 100       163 return $arg->{shortname} if (defined($arg->{shortname}));
62 68 100       128 $shortname = $arg->{plugin} if (defined( $arg->{plugin}));
63              
64 68   33     2183 $shortname = uc basename($shortname || $ENV{PLUGIN_NAME} || $ENV{NAGIOS_PLUGIN} || $0);
65 68         169 $shortname =~ s/^CHECK_(?:BY_)?//; # Remove any leading CHECK_[BY_]
66 68         258 $shortname =~ s/\..*$//; # Remove any trailing suffix
67 68         235 return $shortname;
68             }
69              
70             sub max_state {
71 7 100   7 1 1008 return CRITICAL if grep { $_ == CRITICAL } @_;
  16         31  
72 6 100       9 return WARNING if grep { $_ == WARNING } @_;
  14         26  
73 3 100       6 return OK if grep { $_ == OK } @_;
  4         10  
74 1 50       3 return UNKNOWN if grep { $_ == UNKNOWN } @_;
  0         0  
75 1 50       2 return DEPENDENT if grep { $_ == DEPENDENT } @_;
  0         0  
76 1         2 return UNKNOWN;
77             }
78              
79             sub max_state_alt {
80 7 100   7 1 1210 return CRITICAL if grep { $_ == CRITICAL } @_;
  16         36  
81 6 100       11 return WARNING if grep { $_ == WARNING } @_;
  14         29  
82 3 100       5 return UNKNOWN if grep { $_ == UNKNOWN } @_;
  4         10  
83 2 50       4 return DEPENDENT if grep { $_ == DEPENDENT } @_;
  2         5  
84 2 100       4 return OK if grep { $_ == OK } @_;
  2         6  
85 1         3 return UNKNOWN;
86             }
87              
88             # plugin_exit( $code, $message )
89             sub plugin_exit {
90 95     95 1 8157 my ($code, $message, $arg) = @_;
91              
92             # Handle named parameters
93 95 100 66     459 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     33 if (int(@_ / 2) != @_ / 2 && ref $_[$#_]) {
96 6         8 $arg = pop @_;
97             } else {
98 0         0 undef $arg;
99             }
100 6         15 my %arg = @_;
101 6         10 $code = $arg{return_code};
102 6         10 $message = $arg{message};
103             }
104 95   100     302 $arg ||= {};
105              
106             # Handle string codes
107 95 100 100     349 $code = $ERRORS{$code} if defined $code && exists $ERRORS{$code};
108              
109             # Set defaults
110 95 100 100     354 $code = UNKNOWN unless defined $code && exists $STATUS_TEXT{$code};
111 95 100       197 $message = '' unless defined $message;
112 95 50 33     230 if (ref $message && ref $message eq 'ARRAY') {
113 0         0 $message = join(' ', map { chomp; $_ } @$message);
  0         0  
  0         0  
114             }
115             else {
116 95         168 chomp $message;
117             }
118              
119             # Setup output
120 95         222 my $output = "$STATUS_TEXT{$code}";
121 95 100 66     319 if (defined $message && $message ne '') {
122 87 100       307 $output .= " - " unless $message =~ /^\s*\n/mxs;
123 87         167 $output .= $message;
124             }
125 95 100       1347 my $shortname = ($arg->{plugin} ? $arg->{plugin}->shortname : undef);
126 95   66     420 $shortname ||= get_shortname(); # Should happen only if funnctions are called directly
127 95 50       245 $output = "$shortname $output" if $shortname;
128 95 100       181 if ($arg->{plugin}) {
129 48         51 my $plugin = $arg->{plugin};
130 48 100 66     662 $output .= " | ". $plugin->all_perfoutput
131             if $plugin->perfdata && $plugin->all_perfoutput;
132             }
133 95         318 $output .= "\n";
134              
135             # Don't actually exit if _fake_exit set
136 95 100       156 if ($_fake_exit) {
137 92         1568 require Monitoring::Plugin::ExitResult;
138 92         255 return Monitoring::Plugin::ExitResult->new($code, $output);
139             }
140              
141 3         9 _plugin_exit($code, $output);
142             }
143              
144             sub _plugin_exit {
145 17     17   38 my ($code, $output) = @_;
146             # Print output and exit; die if flag set and called via a die in stack backtrace
147 17 100       32 if ($_use_die) {
148 16         39 for (my $i = 0;; $i++) {
149 34         204 @_ = caller($i);
150 34 50       79 last unless @_;
151 34 100       92 if ($_[3] =~ m/die/) {
152 16         30 $! = $code;
153 16         162 die($output);
154             }
155             }
156             }
157 1         18 print $output;
158 1         122 exit $code;
159             }
160              
161             # plugin_die( $message, [ $code ]) OR plugin_die( $code, $message )
162             # Default $code: UNKNOWN
163             sub plugin_die {
164 55     55 1 4418 my ($arg1, $arg2, $rest) = @_;
165              
166             # Named parameters
167 55 100 66     538 if (defined $arg1 && ($arg1 eq 'return_code' || $arg1 eq 'message')) {
    100 100        
    100 66        
      66        
      66        
      66        
168 6         12 return plugin_exit(@_);
169             }
170              
171             # ($code, $message)
172             elsif (defined $arg1 && (exists $ERRORS{$arg1} || exists $STATUS_TEXT{$arg1})) {
173 20         51 return plugin_exit(@_);
174             }
175              
176             # ($message, $code)
177             elsif (defined $arg2 && (exists $ERRORS{$arg2} || exists $STATUS_TEXT{$arg2})) {
178 21         51 return plugin_exit($arg2, $arg1, $rest);
179             }
180              
181             # Else just assume $arg1 is the message and hope for the best
182             else {
183 8         25 return plugin_exit( UNKNOWN, $arg1, $arg2 );
184             }
185             }
186              
187             # For backwards compatibility
188 0     0 0 0 sub die { plugin_die(@_); }
189              
190              
191             # ------------------------------------------------------------------------
192             # Utility functions
193              
194             # Simple wrapper around Math::Calc::Units::convert
195             sub convert
196             {
197 0     0 0 0 my ($value, $from, $to) = @_;
198 0         0 my ($newval) = Math::Calc::Units::convert("$value $from", $to, 'exact');
199 0         0 return $newval;
200             }
201              
202             # ------------------------------------------------------------------------
203             # check_messages - return a status and/or message based on a set of
204             # message arrays.
205             # Returns a nagios status code in scalar context.
206             # Returns a code and a message in list context.
207             # The message is join($join, @array) for the relevant array for the code,
208             # or join($join_all, $message) for all arrays if $join_all is set.
209             sub check_messages {
210 53     53 1 14117 my %arg = validate( @_, {
211             critical => { type => ARRAYREF },
212             warning => { type => ARRAYREF },
213             ok => { type => ARRAYREF | SCALAR, optional => 1 },
214             'join' => { default => ' ' },
215             join_all => 0,
216             });
217 50 100       259 $arg{join} = ' ' unless defined $arg{join};
218              
219             # Decide $code
220 50         66 my $code = OK;
221 50 100 50     53 $code ||= CRITICAL if @{$arg{critical}};
  50         131  
222 50 100 100     56 $code ||= WARNING if @{$arg{warning}};
  50         122  
223 50 100       86 return $code unless wantarray;
224              
225             # Compose message
226 44         57 my $message = '';
227 44 100       65 if ($arg{join_all}) {
228             $message = join( $arg{join_all},
229 36 100       76 map { @$_ ? join( $arg{'join'}, @$_) : () }
230             $arg{critical},
231             $arg{warning},
232 12 100       36 $arg{ok} ? (ref $arg{ok} ? $arg{ok} : [ $arg{ok} ]) : []
    100          
233             );
234             }
235              
236             else {
237 32 100 33     67 $message ||= join( $arg{'join'}, @{$arg{critical}} )
  13         37  
238             if $code == CRITICAL;
239 32 100 33     58 $message ||= join( $arg{'join'}, @{$arg{warning}} )
  10         27  
240             if $code == WARNING;
241 8         23 $message ||= ref $arg{ok} ? join( $arg{'join'}, @{$arg{ok}} ) : $arg{ok}
242 32 100 100     80 if $arg{ok};
    100          
243             }
244              
245 44         171 return ($code, $message);
246             }
247              
248             # ------------------------------------------------------------------------
249              
250             1;
251              
252             # vim:sw=4:sm:et
253              
254             __END__