diff options
Diffstat (limited to 'lib/Monitoring/Plugin/Performance.pm')
| -rw-r--r-- | lib/Monitoring/Plugin/Performance.pm | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/lib/Monitoring/Plugin/Performance.pm b/lib/Monitoring/Plugin/Performance.pm new file mode 100644 index 0000000..90fc9f4 --- /dev/null +++ b/lib/Monitoring/Plugin/Performance.pm | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | package Monitoring::Plugin::Performance; | ||
| 2 | |||
| 3 | use 5.006; | ||
| 4 | |||
| 5 | use strict; | ||
| 6 | use warnings; | ||
| 7 | |||
| 8 | use Carp; | ||
| 9 | use base qw(Class::Accessor::Fast); | ||
| 10 | __PACKAGE__->mk_ro_accessors( | ||
| 11 | qw(label value uom warning critical min max) | ||
| 12 | ); | ||
| 13 | |||
| 14 | use Monitoring::Plugin::Functions; | ||
| 15 | use Monitoring::Plugin::Threshold; | ||
| 16 | use Monitoring::Plugin::Range; | ||
| 17 | our ($VERSION) = $Monitoring::Plugin::Functions::VERSION; | ||
| 18 | |||
| 19 | sub import { | ||
| 20 | my ($class, %attr) = @_; | ||
| 21 | $_ = $attr{use_die} || 0; | ||
| 22 | Monitoring::Plugin::Functions::_use_die($_); | ||
| 23 | } | ||
| 24 | |||
| 25 | # This is NOT the same as N::P::Functions::value_re. We leave that to be the strict | ||
| 26 | # version. This one allows commas to be part of the numeric value. | ||
| 27 | my $value = qr/[-+]?[\d\.,]+/; | ||
| 28 | my $value_re = qr/$value(?:e$value)?/; | ||
| 29 | my $value_with_negative_infinity = qr/$value_re|~/; | ||
| 30 | sub _parse { | ||
| 31 | my $class = shift; | ||
| 32 | my $string = shift; | ||
| 33 | $string =~ /^'?([^'=]+)'?=($value_re)([\w%]*);?($value_with_negative_infinity\:?$value_re?)?;?($value_with_negative_infinity\:?$value_re?)?;?($value_re)?;?($value_re)?/o; | ||
| 34 | return undef unless ((defined $1 && $1 ne "") && (defined $2 && $2 ne "")); | ||
| 35 | my @info = ($1, $2, $3, $4, $5, $6, $7); | ||
| 36 | # We convert any commas to periods, in the value fields | ||
| 37 | map { defined $info[$_] && $info[$_] =~ s/,/./go } (1, 3, 4, 5, 6); | ||
| 38 | |||
| 39 | # Check that $info[1] is an actual value | ||
| 40 | # We do this by returning undef if a warning appears | ||
| 41 | my $performance_value; | ||
| 42 | { | ||
| 43 | my $not_value; | ||
| 44 | local $SIG{__WARN__} = sub { $not_value++ }; | ||
| 45 | $performance_value = $info[1]+0; | ||
| 46 | return undef if $not_value; | ||
| 47 | } | ||
| 48 | my $p = $class->new( | ||
| 49 | label => $info[0], value => $performance_value, uom => $info[2], warning => $info[3], critical => $info[4], | ||
| 50 | min => $info[5], max => $info[6] | ||
| 51 | ); | ||
| 52 | return $p; | ||
| 53 | } | ||
| 54 | |||
| 55 | # Map undef to '' | ||
| 56 | sub _nvl { | ||
| 57 | my ($self, $value) = @_; | ||
| 58 | defined $value ? $value : '' | ||
| 59 | } | ||
| 60 | |||
| 61 | sub perfoutput { | ||
| 62 | my $self = shift; | ||
| 63 | # Add quotes if label contains a space character | ||
| 64 | my $label = $self->label; | ||
| 65 | if ($label =~ / /) { | ||
| 66 | $label = "'$label'"; | ||
| 67 | } | ||
| 68 | my $out = sprintf "%s=%s%s;%s;%s;%s;%s", | ||
| 69 | $label, | ||
| 70 | $self->value, | ||
| 71 | $self->_nvl($self->uom), | ||
| 72 | $self->_nvl($self->warning), | ||
| 73 | $self->_nvl($self->critical), | ||
| 74 | $self->_nvl($self->min), | ||
| 75 | $self->_nvl($self->max); | ||
| 76 | # Previous implementation omitted trailing ;; - do we need this? | ||
| 77 | $out =~ s/;;$//; | ||
| 78 | return $out; | ||
| 79 | } | ||
| 80 | |||
| 81 | sub parse_perfstring { | ||
| 82 | my ($class, $perfstring) = @_; | ||
| 83 | my @perfs = (); | ||
| 84 | my $obj; | ||
| 85 | while ($perfstring) { | ||
| 86 | $perfstring =~ s/^\s*//; | ||
| 87 | # If there is more than 1 equals sign, split it out and parse individually | ||
| 88 | if (@{[$perfstring =~ /=/g]} > 1) { | ||
| 89 | $perfstring =~ s/^(.*?=.*?)\s//; | ||
| 90 | if (defined $1) { | ||
| 91 | $obj = $class->_parse($1); | ||
| 92 | } else { | ||
| 93 | # This could occur if perfdata was soemthing=value= | ||
| 94 | # Since this is invalid, we reset the string and continue | ||
| 95 | $perfstring = ""; | ||
| 96 | $obj = $class->_parse($perfstring); | ||
| 97 | } | ||
| 98 | } else { | ||
| 99 | $obj = $class->_parse($perfstring); | ||
| 100 | $perfstring = ""; | ||
| 101 | } | ||
| 102 | push @perfs, $obj if $obj; | ||
| 103 | } | ||
| 104 | return @perfs; | ||
| 105 | } | ||
| 106 | |||
| 107 | sub rrdlabel { | ||
| 108 | my $self = shift; | ||
| 109 | my $name = $self->clean_label; | ||
| 110 | # Shorten | ||
| 111 | return substr( $name, 0, 19 ); | ||
| 112 | } | ||
| 113 | |||
| 114 | sub clean_label { | ||
| 115 | my $self = shift; | ||
| 116 | my $name = $self->label; | ||
| 117 | if ($name eq "/") { | ||
| 118 | $name = "root"; | ||
| 119 | } elsif ( $name =~ s/^\/// ) { | ||
| 120 | $name =~ s/\//_/g; | ||
| 121 | } | ||
| 122 | # Convert all other characters | ||
| 123 | $name =~ s/\W/_/g; | ||
| 124 | return $name; | ||
| 125 | } | ||
| 126 | |||
| 127 | # Backward compatibility: create a threshold object on the fly as requested | ||
| 128 | sub threshold | ||
| 129 | { | ||
| 130 | my $self = shift; | ||
| 131 | return Monitoring::Plugin::Threshold->set_thresholds( | ||
| 132 | warning => $self->warning, critical => $self->critical | ||
| 133 | ); | ||
| 134 | } | ||
| 135 | |||
| 136 | # Constructor - unpack thresholds, map args to hashref | ||
| 137 | sub new | ||
| 138 | { | ||
| 139 | my $class = shift; | ||
| 140 | my %arg = @_; | ||
| 141 | |||
| 142 | # Convert thresholds | ||
| 143 | if (my $threshold = delete $arg{threshold}) { | ||
| 144 | $arg{warning} ||= $threshold->warning . ""; | ||
| 145 | $arg{critical} ||= $threshold->critical . ""; | ||
| 146 | } | ||
| 147 | |||
| 148 | $class->SUPER::new(\%arg); | ||
| 149 | } | ||
| 150 | |||
| 151 | 1; | ||
| 152 | |||
| 153 | __END__ | ||
| 154 | |||
| 155 | =head1 NAME | ||
| 156 | |||
| 157 | Monitoring::Plugin::Performance - class for handling Monitoring::Plugin | ||
| 158 | performance data. | ||
| 159 | |||
| 160 | =head1 SYNOPSIS | ||
| 161 | |||
| 162 | use Monitoring::Plugin::Performance use_die => 1; | ||
| 163 | |||
| 164 | # Constructor (also accepts a 'threshold' obj instead of warning/critical) | ||
| 165 | $p = Monitoring::Plugin::Performance->new( | ||
| 166 | label => 'size', | ||
| 167 | value => $value, | ||
| 168 | uom => "kB", | ||
| 169 | warning => $warning, | ||
| 170 | critical => $critical, | ||
| 171 | min => $min, | ||
| 172 | max => $max, | ||
| 173 | ); | ||
| 174 | |||
| 175 | # Parser | ||
| 176 | @perf = Monitoring::Plugin::Performance->parse_perfstring( | ||
| 177 | "/=382MB;15264;15269;; /var=218MB;9443;9448" | ||
| 178 | ) | ||
| 179 | or warn("Failed to parse perfstring"); | ||
| 180 | |||
| 181 | # Accessors | ||
| 182 | for $p (@perf) { | ||
| 183 | printf "label: %s\n", $p->label; | ||
| 184 | printf "value: %s\n", $p->value; | ||
| 185 | printf "uom: %s\n", $p->uom; | ||
| 186 | printf "warning: %s\n", $p->warning; | ||
| 187 | printf "critical: %s\n", $p->critical; | ||
| 188 | printf "min: %s\n", $p->min; | ||
| 189 | printf "max: %s\n", $p->max; | ||
| 190 | # Special accessor returning a threshold obj containing warning/critical | ||
| 191 | $threshold = $p->threshold; | ||
| 192 | } | ||
| 193 | |||
| 194 | # Perfdata output format i.e. label=value[uom];[warn];[crit];[min];[max] | ||
| 195 | print $p->perfoutput; | ||
| 196 | |||
| 197 | |||
| 198 | =head1 DESCRIPTION | ||
| 199 | |||
| 200 | Monitoring::Plugin class for handling performance data. This is a public | ||
| 201 | interface because it could be used by performance graphing routines, | ||
| 202 | such as nagiostat (http://nagiostat.sourceforge.net), perfparse | ||
| 203 | (http://perfparse.sourceforge.net), nagiosgraph | ||
| 204 | (http://nagiosgraph.sourceforge.net) or NagiosGrapher | ||
| 205 | (http://www.nagiosexchange.org/NagiosGrapher.84.0.html). | ||
| 206 | |||
| 207 | Monitoring::Plugin::Performance offers both a parsing interface (via | ||
| 208 | parse_perfstring), for turning nagios performance output strings into | ||
| 209 | their components, and a composition interface (via new), for turning | ||
| 210 | components into perfdata strings. | ||
| 211 | |||
| 212 | =head1 USE'ING THE MODULE | ||
| 213 | |||
| 214 | If you are using this module for the purposes of parsing perf data, you | ||
| 215 | will probably want to set use_die => 1 at use time. This forces | ||
| 216 | &Monitoring::Plugin::Functions::plugin_exit to call die() - rather than exit() - | ||
| 217 | when an error occurs. This is then trappable by an eval. If you don't set use_die, | ||
| 218 | then an error in these modules will cause your script to exit | ||
| 219 | |||
| 220 | =head1 CLASS METHODS | ||
| 221 | |||
| 222 | =over 4 | ||
| 223 | |||
| 224 | =item Monitoring::Plugin::Performance->new(%attributes) | ||
| 225 | |||
| 226 | Instantiates a new Monitoring::Plugin::Performance object with the given | ||
| 227 | attributes. | ||
| 228 | |||
| 229 | =item Monitoring::Plugin::Performance->parse_perfstring($string) | ||
| 230 | |||
| 231 | Returns an array of Monitoring::Plugin::Performance objects based on the string | ||
| 232 | entered. If there is an error parsing the string - which may consists of several | ||
| 233 | sets of data - will return an array with all the successfully parsed sets. | ||
| 234 | |||
| 235 | If values are input with commas instead of periods, due to different locale settings, | ||
| 236 | then it will still be parsed, but the commas will be converted to periods. | ||
| 237 | |||
| 238 | =back | ||
| 239 | |||
| 240 | =head1 OBJECT METHODS (ACCESSORS) | ||
| 241 | |||
| 242 | =over 4 | ||
| 243 | |||
| 244 | =item label, value, uom, warning, critical, min, max | ||
| 245 | |||
| 246 | These all return scalars. min and max are not well supported yet. | ||
| 247 | |||
| 248 | =item threshold | ||
| 249 | |||
| 250 | Returns a Monitoring::Plugin::Threshold object holding the warning and critical | ||
| 251 | ranges for this performance data (if any). | ||
| 252 | |||
| 253 | =item rrdlabel | ||
| 254 | |||
| 255 | Returns a string based on 'label' that is suitable for use as dataset name of | ||
| 256 | an RRD i.e. munges label to be 1-19 characters long with only characters | ||
| 257 | [a-zA-Z0-9_]. | ||
| 258 | |||
| 259 | This calls $self->clean_label and then truncates to 19 characters. | ||
| 260 | |||
| 261 | There is no guarantee that multiple N:P:Performance objects will have unique | ||
| 262 | rrdlabels. | ||
| 263 | |||
| 264 | =item clean_label | ||
| 265 | |||
| 266 | Returns a "clean" label for use as a dataset name in RRD, ie, it converts | ||
| 267 | characters that are not [a-zA-Z0-9_] to _. | ||
| 268 | |||
| 269 | It also converts "/" to "root" and "/{name}" to "{name}". | ||
| 270 | |||
| 271 | =item perfoutput | ||
| 272 | |||
| 273 | Outputs the data in Monitoring::Plugin perfdata format i.e. | ||
| 274 | label=value[uom];[warn];[crit];[min];[max]. | ||
| 275 | |||
| 276 | =back | ||
| 277 | |||
| 278 | =head1 SEE ALSO | ||
| 279 | |||
| 280 | Monitoring::Plugin, Monitoring::Plugin::Threshold, https://www.monitoring-plugins.org/doc/guidelines.html | ||
| 281 | |||
| 282 | =head1 AUTHOR | ||
| 283 | |||
| 284 | This code is maintained by the Monitoring Plugin Development Team: see | ||
| 285 | https://monitoring-plugins.org | ||
| 286 | |||
| 287 | =head1 COPYRIGHT AND LICENSE | ||
| 288 | |||
| 289 | Copyright (C) 2006-2014 Monitoring Plugin Development Team | ||
| 290 | |||
| 291 | This library is free software; you can redistribute it and/or modify | ||
| 292 | it under the same terms as Perl itself. | ||
| 293 | |||
| 294 | =cut | ||
