[Nagiosplug-devel] unsubscribe
Roy Hogervorst
joop3 at gmx.net
Fri Sep 4 16:46:41 CEST 2009
On 4 sep 2009, at 16:41, Jose Luis Martinez wrote:
> Hi,
>
> I wrote a mini-module for doing the same in Perl plugins. Haven't
> CPANned it yet, so take this as a call for community revision.
>
> It's called Nagios::Plugin::Differences, and I'll discuss the design
> so that maybe you can lift some ideas for the C API, or that my module
> gets benefitted from the discussion in place.
>
> - Each plugin is responsable for it's storage. I don't like FD
> passing
> either.
>
> - The serializer is the Perl Storable class. Well-proven, and core
> module. I use the lock_store method to serialize data to the files (so
> appropiate locks get placed). There are not methods in place to change
> storage type, but it can be done via subclassing (overriding persist
> and
> load_last).
>
> - The temporary file is defaulted to '/tmp/_nagios_plugin_%s.tmp',
> where %s is the filename name of the plugin when the object gets
> constructed.
>
> - It's plugins responsibility to choose a different temp file if it's
> anticipated there will be temporary file collisions. For example:
>
> "check_disk_io --dev sda" and "check_disk_io --dev sdb", being
> executed
> on the same machine will pick up one anothers temp file. They would
> have
> to construct the Nagios::Plugin::Differences object requesting a
> tempfile like /tmp/_nagios_plugin_check_disk_io_sda.tmp and
> /tmp/_nagios_plugin_check_disk_io_sdb.tmp.
>
> - The method for persisting data automatically adds the timestamp to
> the reading, you can override it if you want.
>
> - There are helper methods for doing the "dirty" work of calculating
> differences and rates between now and the last reading.
>
> - Plugins with incompatible datastructures in different versions can
> be detected with the plugin just storing 'struct_version' as one of
> the
> values to be persisted and taking appropiate action (up to the
> plugin).
>
> I attach the pm file so you can inspect it (also, if you wan't I can
> attach test files too). I'm open to feedback, corrections and
> discussion. Please don't use or publish a plugin that uses this module
> until it's CPANned, as the API is open to change.
>
> Just my 2 cents,
>
> Jose Luis Martinez
> jlmartinez at capside.com
>
> package Nagios::Plugin::Differences;
>
> use strict;
> no warnings;
>
> use Carp;
> use File::Basename qw//;
> use Storable qw//;
>
> =head1 NAME
>
> Nagios::Plugin::Differences - Module to streamline Nagios plugins
> that need to store temporary data and calculate the differences
> between the readings.
>
> =head1 VERSION
>
> Version 0.01
>
> =cut
>
> our $VERSION = '0.01';
>
> =head1 SYNOPSIS
>
> This module is useful for when there is need to store a set of values
> that need to be reread at the next invocation of the plugin. It
> provides
> a set of functions to calculate the differences between the readings.
>
> use Nagios::Plugin::Differences;
>
> my $npd = Nagios::Plugin::Differences->new();
> $npd->load_last;
> # suppose last reading was
> # { 'bytes' => 200, 'packets' => 3 }
> # at time 1234567890
> $npd->new_reading({
> 'bytes' => 500
> 'packets' => 6
> });
> # new reading is at time 123456900
> $npd->persist;
> my $rate = $npd->rate('difference');
> # rate returns the bytes/s and the packets/s that had to be
> # attained to get from the last reading to the new reading
> # in the time passed between readings
> # { 'bytes' => 30,
> # 'packets' => 0.3 }
>
> =head1 FUNCTIONS
>
> =head2 new(%options)
>
> Constructor for the Nagios::Plugin::Differences object. You
> can pass 'file' => '/tmp/xxx' to override the default file
> ('/tmp/_nagios_plugin_$0.tmp').
>
> =cut
>
> sub new {
> my ($class, %options) = @_;
>
> my $self = { 'file' => sprintf("/tmp/_nagios_plugin_%s.tmp",
> File::Basename::basename($0)),
> %options };
> bless $self, $class;
> }
>
> =head2 new_reading($data, [$ts])
>
> Report a new reading. The reading has to be a hashref. You can
> optionally
> pass the timestamp for the reading. If you don't pass $ts, the
> timestamp
> of the invocation of the method will be used.
>
> =cut
>
> sub new_reading {
> my ($self, $data, $ts) = @_;
> croak "cannot store non-hashref data" if (ref($data) ne 'HASH');
> $ts = time() if (not defined $ts);
>
> $self->{'last'} = $self->{'current'} if (defined $self-
> >{'current'});
> $self->{'current'} = { 'ts' => $ts, 'data' => $data };
> }
>
> =head2 persist([$file])
>
> Write the stored data to the temporary file
>
> =cut
>
> sub persist {
> my ($self, $file) = @_;
> $file ||= $self->{'file'};
> Storable::lock_store($self->{'current'}, $file);
> }
>
> =head2 load_last([$file])
>
> Load the last reading from the temporary file.
>
> =cut
>
> sub load_last {
> my ($self, $file) = @_;
> $file ||= $self->{'file'};
> $self->{'last'} = $self->{'current'} if (defined $self-
> >{'current'});
> $self->{'current'} = Storable::retrieve($file);
> }
>
>
> #head2 difference_from_zero
> #
> #Calculate the difference between current and zero.
> #
> #cut
> #
> #sub difference_from_zero {
> # my ($self) = @_;
> # return ($self->{'current'}->{'data'});
> #}
>
> =head1 CALCULATING DIFFERENCES
>
> =head2 difference
>
> Calculates the difference between current reading and last reading.
>
> =cut
>
> sub difference {
> my ($self) = @_;
>
> die 'no new_reading' if (not defined $self->{'current'});
> die 'no last' if (not defined $self->{'last'});
>
> my $current_data = $self->{'current'}->{'data'};
> my $last_data = $self->{'last'}->{'data'};
> my $delta = {};
>
> foreach my $item (keys %$last_data){
> # if we don't have item, $data_last->{ xxx } will be undef.
> The correct reading would be zero
> $delta->{ $item } = $current_data->{ $item } - ($last_data-
> >{ $item } || 0);
> }
> return ($delta);
> }
>
> =head2 forward_difference($wrap_at)
>
> =cut
>
> sub forward_difference {
> my ($self, $wrap_at) = @_;
>
> die 'no new_reading' if (not defined $self->{'current'});
> die 'no last' if (not defined $self->{'last'});
>
> my $current_data = $self->{'current'}->{'data'};
> my $last_data = $self->{'last'}->{'data'};
> my $delta = {};
>
> foreach my $item (keys %$last_data){
> if ($current_data->{ $item } >= $last_data->{ $item }){
> $delta->{ $item } = $current_data->{ $item } -
> ($last_data->{ $item } || 0);
> } else {
> # If the current reading is smaller than the last time we
> saw it, then we have to
> # take into account the wrap value.
> # time |=======|------------|===========|
> # 0 current last wrap
> $delta->{ $item } = ($wrap_at - $last_data->{ $item }) +
> $current_data->{ $item };
> }
> }
> return ($delta);
> }
>
> =head2 forward_difference_unknown_wrap
>
> If the value of a key from the current reading is less than the last
> reading, the
> difference will be taken from zero. This is handy when you are
> storing counters
> that increment, but can be reset to zero.
>
> =cut
>
> sub forward_difference_unknown_wrap {
> my ($self) = @_;
>
> die 'no new_reading' if (not defined $self->{'current'});
> die 'no last' if (not defined $self->{'last'});
>
> my $current_data = $self->{'current'}->{'data'};
> my $last_data = $self->{'last'}->{'data'};
> my $delta = {};
>
> foreach my $item (keys %$last_data){
> if ($current_data->{ $item } >= $last_data->{ $item }){
> $delta->{ $item } = $current_data->{ $item } -
> ($last_data->{ $item } || 0);
> } else {
> # If the current reading is smaller than the last time we
> saw it, then we have to
> # discard the last reading. The counter has been reset,
> and we cannot know what
> # happened between the last reading and the current one.
> # time |=======|------------|???????....
> # current last
> $delta->{ $item } = $current_data->{ $item };
> }
> }
> return ($delta);
> }
>
> =head2 rate($method, [params_to_method])
>
> Calculate the rate of change (derive) between the current reading
> and the last reading.
> To calculate rate of change, you need to calculate the change. The
> change gets calculated
> with any of the "difference" methods
>
> $npd->rate('difference');
>
> $npd->rate('forward_difference', 1000);
>
> $npd->rate('forward_difference_unknown_wrap');
>
> =cut
>
> sub rate {
> my ($self, $method, @params_to_method) = @_;
>
> my $delta = $self->$method(@params_to_method);
> my $time = $self->{'current'}->{'ts'} - $self->{'last'}->{'ts'};
>
> my $rates = {};
> foreach my $item (keys %$delta){
> $rates->{$item} = $delta->{$item} / $time;
> }
>
> return $rates;
> }
>
> =head2 proportion(
>
> Calculate the proportions of the values of one key respect to the
> total sum of all the values.
>
> proportion({ 'red' => 5, 'green' => 15 });
> # returns: { 'red' => 0.25, 'green' => 0.75 }
>
> =cut
>
> sub proportion {
> my ($self, $hashref) = @_;
>
> my $total = 0;
> map { $total += $_ } values %$hashref;
>
> my $proportion = {};
> foreach my $item (keys %$hashref){
> $proportion->{$item} = $hashref->{$item} / $total;
> }
> return($proportion);
> }
>
> 1;
>
>
> =head1 AUTHOR
>
> JLMARTIN, C<< <jlmartinez at capside.com> >>
>
> =head1 BUGS
>
> Please report any bugs or feature requests to C<bug-nagios-plugin-
> differences at rt.cpan.org>, or through
> the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Nagios-Plugin-Differences
> >. I will be notified, and then you'll automatically be notified of
> progress on your bug as I make changes.
>
> =head1 SUPPORT
>
> You can find documentation for this module with the perldoc command.
>
> perldoc Nagios::Plugin::Differences
>
> You can also look for information at:
>
> =over 4
>
> =item * RT: CPAN's request tracker
>
> L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Nagios-Plugin-Differences>
>
> =item * AnnoCPAN: Annotated CPAN documentation
>
> L<http://annocpan.org/dist/Nagios-Plugin-Differences>
>
> =item * CPAN Ratings
>
> L<http://cpanratings.perl.org/d/Nagios-Plugin-Differences>
>
> =item * Search CPAN
>
> L<http://search.cpan.org/dist/Nagios-Plugin-Differences>
>
> =back
>
> =head1 ACKNOWLEDGEMENTS
>
> =head1 COPYRIGHT & LICENSE
>
> Copyright 2009 Jose Luis Martinez Torres, all rights reserved.
>
> This program is free software; you can redistribute it and/or modify
> it
> under the same terms as Perl itself.
>
>
> =cut
>
> 1; # End of Nagios::Plugin::Differences
>
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008
> 30-Day
> trial. Simplify your report design, integration and deployment - and
> focus on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july_______________________________________________________
> Nagios Plugin Development Mailing List Nagiosplug-devel at lists.sourceforge.net
> Unsubscribe at https://lists.sourceforge.net/lists/listinfo/nagiosplug-devel
> ::: Please include plugins version (-v) and OS when reporting any
> issue.
> ::: Messages without supporting info will risk being sent to /dev/null
More information about the Devel
mailing list